test(plugins): add test suite for Plugins service

This commit is contained in:
Yassine Doghri 2024-06-04 13:10:56 +00:00
parent 3a900bbab6
commit 91dc8c8325
29 changed files with 416 additions and 59 deletions

View File

@ -52,11 +52,7 @@ abstract class BasePlugin implements PluginInterface
$this->manifest = new Manifest($this->key); $this->manifest = new Manifest($this->key);
$this->manifest->loadFromFile($manifestPath); $this->manifest->loadFromFile($manifestPath);
if ($this->getManifestErrors() !== []) { $this->status = get_plugin_setting($this->key, 'active') ? PluginStatus::ACTIVE : PluginStatus::INACTIVE;
$this->status = PluginStatus::INVALID;
} else {
$this->status = get_plugin_option($this->key, 'active') ? PluginStatus::ACTIVE : PluginStatus::INACTIVE;
}
$this->iconSrc = $this->loadIcon($directory . '/icon.svg'); $this->iconSrc = $this->loadIcon($directory . '/icon.svg');
@ -98,17 +94,48 @@ abstract class BasePlugin implements PluginInterface
final public function getGeneralSetting(string $key): mixed final public function getGeneralSetting(string $key): mixed
{ {
return get_plugin_option($this->key, $key); return get_plugin_setting($this->key, $key);
} }
final public function getPodcastSetting(int $podcastId, string $key): mixed final public function getPodcastSetting(int $podcastId, string $key): mixed
{ {
return get_plugin_option($this->key, $key, ['podcast', $podcastId]); return get_plugin_setting($this->key, $key, ['podcast', $podcastId]);
} }
final public function getEpisodeSetting(int $episodeId, string $key): mixed final public function getEpisodeSetting(int $episodeId, string $key): mixed
{ {
return get_plugin_option($this->key, $key, ['episode', $episodeId]); return get_plugin_setting($this->key, $key, ['episode', $episodeId]);
}
/**
* @return bool true on success, false on failure
*/
final public function activate(): bool
{
if ($this->status === PluginStatus::ACTIVE) {
return false;
}
$this->setStatus(PluginStatus::ACTIVE);
if ($this->status === PluginStatus::INACTIVE) {
return false;
}
set_plugin_setting($this->key, 'active', true);
return true;
}
final public function deactivate(): bool
{
if ($this->status !== PluginStatus::ACTIVE) {
return false;
}
$this->setStatus(PluginStatus::INACTIVE);
set_plugin_setting($this->key, 'active', false);
return true;
} }
final public function getStatus(): PluginStatus final public function getStatus(): PluginStatus
@ -243,14 +270,30 @@ abstract class BasePlugin implements PluginInterface
return $this->manifest->license ?? 'UNLICENSED'; return $this->manifest->license ?? 'UNLICENSED';
} }
/**
* @param PluginStatus::ACTIVE|PluginStatus::INACTIVE $value
*/
final protected function setStatus(PluginStatus $value): self
{
if ($this->getManifestErrors() !== []) {
$this->status = PluginStatus::INVALID;
return $this;
}
$this->status = $value;
return $this;
}
final protected function getOption(string $option): mixed final protected function getOption(string $option): mixed
{ {
return get_plugin_option($this->key, $option); return get_plugin_setting($this->key, $option);
} }
final protected function setOption(string $option, mixed $value = null): void final protected function setOption(string $option, mixed $value = null): void
{ {
set_plugin_option($this->key, $option, $value); set_plugin_setting($this->key, $option, $value);
} }
private function loadIcon(string $path): string private function loadIcon(string $path): string

View File

@ -209,12 +209,16 @@ class Plugins
public function activate(BasePlugin $plugin): void public function activate(BasePlugin $plugin): void
{ {
set_plugin_option($plugin->getKey(), 'active', true); if ($plugin->activate()) {
++self::$activeCount;
}
} }
public function deactivate(BasePlugin $plugin): void public function deactivate(BasePlugin $plugin): void
{ {
set_plugin_option($plugin->getKey(), 'active', false); if ($plugin->deactivate()) {
--self::$activeCount;
}
} }
/** /**
@ -222,7 +226,7 @@ class Plugins
*/ */
public function setOption(BasePlugin $plugin, string $name, mixed $value, array $additionalContext = null): void public function setOption(BasePlugin $plugin, string $name, mixed $value, array $additionalContext = null): void
{ {
set_plugin_option($plugin->getKey(), $name, $value, $additionalContext); set_plugin_setting($plugin->getKey(), $name, $value, $additionalContext);
} }
public function getInstalledCount(): int public function getInstalledCount(): int
@ -282,12 +286,23 @@ class Plugins
ucwords(str_replace(['-', '_', '.'], ' ', $vendor . ' ' . $package)) . 'Plugin' ucwords(str_replace(['-', '_', '.'], ' ', $vendor . ' ' . $package)) . 'Plugin'
); );
spl_autoload_register(static function ($class) use (&$className, &$pluginDirectory): void { $pluginFile = $pluginDirectory . DIRECTORY_SEPARATOR . 'Plugin.php';
if ($class === $className) { spl_autoload_register(static function ($class) use (&$className, &$pluginFile): void {
include $pluginDirectory . DIRECTORY_SEPARATOR . 'Plugin.php'; if ($class !== $className) {
return;
} }
if (! file_exists($pluginFile)) {
return;
}
include_once $pluginFile;
}, true); }, true);
if (! class_exists($className)) {
continue;
}
$plugin = new $className($vendor, $package, $pluginDirectory); $plugin = new $className($vendor, $package, $pluginDirectory);
if (! $plugin instanceof BasePlugin) { if (! $plugin instanceof BasePlugin) {
continue; continue;

View File

@ -11,11 +11,11 @@ if (! function_exists('plugins')) {
} }
} }
if (! function_exists('get_plugin_option')) { if (! function_exists('get_plugin_setting')) {
/** /**
* @param ?array{'podcast'|'episode',int} $additionalContext * @param ?array{'podcast'|'episode',int} $additionalContext
*/ */
function get_plugin_option(string $pluginKey, string $option, array $additionalContext = null): mixed function get_plugin_setting(string $pluginKey, string $option, array $additionalContext = null): mixed
{ {
$key = sprintf('Plugins.%s', $option); $key = sprintf('Plugins.%s', $option);
$context = sprintf('plugin:%s', $pluginKey); $context = sprintf('plugin:%s', $pluginKey);
@ -28,11 +28,11 @@ if (! function_exists('get_plugin_option')) {
} }
} }
if (! function_exists('set_plugin_option')) { if (! function_exists('set_plugin_setting')) {
/** /**
* @param ?array{'podcast'|'episode',int} $additionalContext * @param ?array{'podcast'|'episode',int} $additionalContext
*/ */
function set_plugin_option( function set_plugin_setting(
string $pluginKey, string $pluginKey,
string $option, string $option,
mixed $value = null, mixed $value = null,

View File

@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace Tests\Modules\Api\Rest\V1; namespace Tests\Modules\Plugins;
use CodeIgniter\Test\CIUnitTestCase; use CodeIgniter\Test\CIUnitTestCase;
use Modules\Plugins\Manifest\Manifest; use Modules\Plugins\Manifest\Manifest;
@ -20,7 +20,7 @@ final class ManifestTest extends CIUnitTestCase
$this->assertNotEquals($manifest->name, 'acme/hello-world'); $this->assertNotEquals($manifest->name, 'acme/hello-world');
$this->assertNotEquals($manifest->version, '1.0.0'); $this->assertNotEquals($manifest->version, '1.0.0');
$manifest->loadFromFile(TESTPATH . 'modules/Plugins/Mocks/manifests/manifest-required.json'); $manifest->loadFromFile(TESTPATH . 'modules/Plugins/mocks/manifests/manifest-required.json');
// no errors // no errors
$this->assertEmpty($manifest->getPluginErrors('acme/hello-world')); $this->assertEmpty($manifest->getPluginErrors('acme/hello-world'));
@ -34,7 +34,7 @@ final class ManifestTest extends CIUnitTestCase
{ {
$manifest = new Manifest('acme/hello-world'); $manifest = new Manifest('acme/hello-world');
$manifest->loadFromFile(TESTPATH . 'modules/Plugins/Mocks/manifests/manifest-empty.json'); $manifest->loadFromFile(TESTPATH . 'modules/Plugins/mocks/manifests/manifest-empty.json');
$errors = $manifest->getPluginErrors('acme/hello-world'); $errors = $manifest->getPluginErrors('acme/hello-world');
@ -49,7 +49,7 @@ final class ManifestTest extends CIUnitTestCase
{ {
$manifest = new Manifest('acme/hello-world'); $manifest = new Manifest('acme/hello-world');
$manifest->loadFromFile(TESTPATH . 'modules/Plugins/Mocks/manifests/manifest-full-valid.json'); $manifest->loadFromFile(TESTPATH . 'modules/Plugins/mocks/manifests/manifest-full-valid.json');
// no errors // no errors
$this->assertEmpty($manifest->getPluginErrors('acme/hello-world')); $this->assertEmpty($manifest->getPluginErrors('acme/hello-world'));
@ -59,7 +59,7 @@ final class ManifestTest extends CIUnitTestCase
{ {
$manifest = new Manifest('acme/hello-world'); $manifest = new Manifest('acme/hello-world');
$manifest->loadFromFile(TESTPATH . 'modules/Plugins/Mocks/manifests/manifest-full-invalid.json'); $manifest->loadFromFile(TESTPATH . 'modules/Plugins/mocks/manifests/manifest-full-invalid.json');
// errors // errors
$this->assertNotEmpty($manifest->getPluginErrors('acme/hello-world')); $this->assertNotEmpty($manifest->getPluginErrors('acme/hello-world'));

View File

@ -1,11 +0,0 @@
<?php
declare(strict_types=1);
namespace Tests\Modules\Plugins\Mocks\Plugins\AcmeHelloUniverse;
use Modules\Plugins\Core\BasePlugin;
class Plugin extends BasePlugin
{
}

View File

@ -1,11 +0,0 @@
<?php
declare(strict_types=1);
namespace Tests\Modules\Plugins\Mocks\Plugins\AcmeHelloWorld;
use Modules\Plugins\Core\BasePlugin;
class Plugin extends BasePlugin
{
}

View File

@ -0,0 +1,175 @@
<?php
declare(strict_types=1);
namespace Tests\Modules\Plugins;
use App\Entities\Episode;
use App\Entities\Podcast;
use App\Libraries\SimpleRSSElement;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
use Modules\Plugins\Config\Plugins as PluginsConfig;
use Modules\Plugins\Core\Plugins;
use Modules\Plugins\Core\PluginStatus;
use Override;
/**
* @internal
*/
final class PluginsTest extends CIUnitTestCase
{
use DatabaseTestTrait;
protected $migrate = true;
protected $migrateOnce = false;
protected $refresh = true;
/**
* @var string|null
*/
protected $namespace;
protected static Plugins $plugins;
#[Override]
public static function setUpBeforeClass(): void
{
$pluginsConfig = new PluginsConfig();
$pluginsConfig->folder = __DIR__ . '/mocks/plugins' . DIRECTORY_SEPARATOR;
self::$plugins = new Plugins($pluginsConfig);
}
public function testRegister(): void
{
$this->assertCount(7, self::$plugins->getAllPlugins());
$this->assertEquals(7, self::$plugins->getInstalledCount());
$this->assertEquals(0, self::$plugins->getActiveCount());
}
public function testActivateDeactivate(): void
{
$this->assertEquals(0, self::$plugins->getActiveCount());
$plugin = self::$plugins->getAllPlugins()[0];
// get first plugin and activate it
self::$plugins->activate($plugin);
$this->assertEquals(1, self::$plugins->getActiveCount());
$this->assertEquals(PluginStatus::ACTIVE, $plugin->getStatus());
$this->seeInDatabase('settings', [
'class' => PluginsConfig::class,
'key' => 'active',
'value' => '1',
'type' => 'boolean',
'context' => 'plugin:' . $plugin->getKey(),
]);
// get first plugin and deactivate it
self::$plugins->deactivate($plugin);
$this->assertEquals(0, self::$plugins->getActiveCount());
$this->assertEquals(PluginStatus::INACTIVE, $plugin->getStatus());
$this->seeInDatabase('settings', [
'class' => PluginsConfig::class,
'key' => 'active',
'value' => '0',
'type' => 'boolean',
'context' => 'plugin:' . $plugin->getKey(),
]);
}
public function testRunHooksActive(): void
{
$acmeAllHooksPlugin = self::$plugins->getPlugin('acme', 'all-hooks');
self::$plugins->activate($acmeAllHooksPlugin);
$this->assertEquals(1, self::$plugins->getActiveCount());
$podcast = new Podcast();
$this->assertEquals('', $podcast->title);
self::$plugins->runHook('rssBeforeChannel', [$podcast]);
$this->assertEquals('Podcast test', $podcast->title);
$channel = new SimpleRSSElement('<channel></channel>');
$this->assertTrue(empty($channel->foo));
self::$plugins->runHook('rssAfterChannel', [$podcast, $channel]);
$this->assertFalse(empty($channel->foo));
$episode = new Episode();
$this->assertEquals('', $episode->title);
self::$plugins->runHook('rssBeforeItem', [$episode]);
$this->assertEquals('Episode test', $episode->title);
$item = new SimpleRSSElement('<item></item>');
$this->assertTrue(empty($item->efoo));
self::$plugins->runHook('rssAfterItem', [$episode, $item]);
$this->assertFalse(empty($item->efoo));
ob_start();
self::$plugins->runHook('siteHead', []);
$result = ob_get_contents();
ob_end_clean(); //Discard output buffer
$this->assertEquals('hello', $result);
}
public function testRunHooksInactive(): void
{
$acmeAllHooksPlugin = self::$plugins->getPlugin('acme', 'all-hooks');
self::$plugins->deactivate($acmeAllHooksPlugin);
$this->assertEquals(0, self::$plugins->getActiveCount());
// nothing should change when running hooks as the plugin is inactive
$podcast = new Podcast();
$this->assertEquals('', $podcast->title);
self::$plugins->runHook('rssBeforeChannel', [$podcast]);
$this->assertEquals('', $podcast->title);
$channel = new SimpleRSSElement('<channel></channel>');
$this->assertTrue(empty($channel->foo));
self::$plugins->runHook('rssAfterChannel', [$podcast, $channel]);
$this->assertTrue(empty($channel->foo));
$episode = new Episode();
$this->assertEquals('', $episode->title);
self::$plugins->runHook('rssBeforeItem', [$episode]);
$this->assertEquals('', $episode->title);
$item = new SimpleRSSElement('<item></item>');
$this->assertTrue(empty($item->efoo));
self::$plugins->runHook('rssAfterItem', [$episode, $item]);
$this->assertTrue(empty($item->efoo));
ob_start();
self::$plugins->runHook('siteHead', []);
$result = ob_get_contents();
ob_end_clean(); //Discard output buffer
$this->assertEquals('', $result);
}
public function testRunUndeclaredHook(): void
{
$acmeUndeclaredHookPlugin = self::$plugins->getPlugin('acme', 'undeclared-hook');
self::$plugins->activate($acmeUndeclaredHookPlugin);
$podcast = new Podcast();
$this->assertEquals('', $podcast->title);
self::$plugins->runHook('rssBeforeChannel', [$podcast]);
$this->assertEquals('Podcast test undeclared', $podcast->title);
// rssAfterChannel has not been declared in plugin manifest, should not be running
$channel = new SimpleRSSElement('<channel></channel>');
$this->assertTrue(empty($channel->foo));
self::$plugins->runHook('rssAfterChannel', [$podcast, $channel]);
$this->assertTrue(empty($channel->foo));
}
}

View File

@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
use App\Entities\Episode;
use App\Entities\Podcast;
use App\Libraries\SimpleRSSElement;
use Modules\Plugins\Core\BasePlugin;
class AcmeAllHooksPlugin extends BasePlugin
{
#[Override]
public function rssBeforeChannel(Podcast $podcast): void
{
$podcast->title = 'Podcast test';
}
#[Override]
public function rssAfterChannel(Podcast $podcast, SimpleRSSElement $channel): void
{
$channel->addChild('foo', 'bar');
}
#[Override]
public function rssBeforeItem(Episode $episode): void
{
$episode->title = 'Episode test';
}
#[Override]
public function rssAfterItem(Episode $episode, SimpleRSSElement $item): void
{
$item->addChild('efoo', 'ebar');
}
#[Override]
public function siteHead(): void
{
echo 'hello';
}
}

View File

@ -0,0 +1,11 @@
{
"name": "acme/all-hooks",
"version": "1.0.0",
"hooks": [
"rssBeforeChannel",
"rssAfterChannel",
"rssBeforeItem",
"rssAfterItem",
"siteHead"
]
}

View File

@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
use Modules\Plugins\Core\BasePlugin;
class AcmeEmptyManifestPlugin extends BasePlugin
{
}

View File

@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
use Modules\Plugins\Core\BasePlugin;
class AcmeHelloUniversePlugin extends BasePlugin
{
}

View File

@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
use Modules\Plugins\Core\BasePlugin;
class AcmeHelloWorldPlugin extends BasePlugin
{
}

View File

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
use App\Entities\Podcast;
use App\Libraries\SimpleRSSElement;
use Modules\Plugins\Core\BasePlugin;
class AcmeUndeclaredHookPlugin extends BasePlugin
{
#[Override]
public function rssBeforeChannel(Podcast $podcast): void
{
$podcast->title = 'Podcast test undeclared';
}
#[Override]
public function rssAfterChannel(Podcast $podcast, SimpleRSSElement $channel): void
{
$channel->addChild('foo', 'bar');
}
}

View File

@ -0,0 +1,5 @@
{
"name": "acme/all-hooks",
"version": "1.0.0",
"hooks": ["rssBeforeChannel"]
}

View File

@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
use Modules\Plugins\Core\BasePlugin;
class AtlantisHelloBroken extends BasePlugin
{
}

View File

@ -0,0 +1,4 @@
{
"name": "atlantis/hello-broken",
"version": "1.0.0"
}

View File

@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
use Modules\Plugins\Core\BasePlugin;
class AtlantisHelloWorldPlugin extends BasePlugin
{
}

View File

@ -0,0 +1,4 @@
{
"name": "atlantis/hello-world",
"version": "1.0.0"
}

View File

@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
use Modules\Plugins\Core\BasePlugin;
class AtlantisNoManifestPlugin extends BasePlugin
{
}

View File

@ -0,0 +1,4 @@
{
"name": "atlantis/no-plugin-file",
"version": "1.0.0"
}

View File

@ -6,14 +6,14 @@
<x-Forms.Checkbox <x-Forms.Checkbox
name="<?= $field->key ?>" name="<?= $field->key ?>"
hint="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>" hint="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>"
isChecked="<?= get_plugin_option($plugin->getKey(), $field->key, $context) ? 'true' : 'false' ?>" isChecked="<?= get_plugin_setting($plugin->getKey(), $field->key, $context) ? 'true' : 'false' ?>"
><?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.label', $plugin->getKey(), $type, $field->key), $field->label)) ?></x-Forms.Checkbox> ><?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.label', $plugin->getKey(), $type, $field->key), $field->label)) ?></x-Forms.Checkbox>
<?php break; <?php break;
case 'toggler': ?> case 'toggler': ?>
<x-Forms.Toggler <x-Forms.Toggler
name="<?= $field->key ?>" name="<?= $field->key ?>"
hint="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>" hint="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>"
isChecked="<?= get_plugin_option($plugin->getKey(), $field->key, $context) ? 'true' : 'false' ?>" isChecked="<?= get_plugin_setting($plugin->getKey(), $field->key, $context) ? 'true' : 'false' ?>"
><?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.label', $plugin->getKey(), $type, $field->key), $field->label)) ?></x-Forms.Toggler> ><?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.label', $plugin->getKey(), $type, $field->key), $field->label)) ?></x-Forms.Toggler>
<?php break; <?php break;
case 'radio-group': ?> case 'radio-group': ?>
@ -24,7 +24,7 @@
helper="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>" helper="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>"
options="<?= esc(json_encode($field->getOptionsArray(sprintf('%s.settings.%s.%s.options', $plugin->getKey(), $type, $field->key)))) ?>" options="<?= esc(json_encode($field->getOptionsArray(sprintf('%s.settings.%s.%s.options', $plugin->getKey(), $type, $field->key)))) ?>"
isRequired="<?= $field->optional ? 'false' : 'true' ?>" isRequired="<?= $field->optional ? 'false' : 'true' ?>"
value="<?= get_plugin_option($plugin->getKey(), $field->key, $context) ?>" value="<?= get_plugin_setting($plugin->getKey(), $field->key, $context) ?>"
/> />
<?php break; <?php break;
case 'select': ?> case 'select': ?>
@ -36,7 +36,7 @@
helper="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>" helper="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>"
options="<?= esc(json_encode($field->getOptionsArray(sprintf('%s.settings.%s.%s.options', $plugin->getKey(), $type, $field->key)))) ?>" options="<?= esc(json_encode($field->getOptionsArray(sprintf('%s.settings.%s.%s.options', $plugin->getKey(), $type, $field->key)))) ?>"
isRequired="<?= $field->optional ? 'false' : 'true' ?>" isRequired="<?= $field->optional ? 'false' : 'true' ?>"
value="<?= get_plugin_option($plugin->getKey(), $field->key, $context) ?>" value="<?= get_plugin_setting($plugin->getKey(), $field->key, $context) ?>"
/> />
<?php break; <?php break;
case 'select-multiple': ?> case 'select-multiple': ?>
@ -48,7 +48,7 @@
helper="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>" helper="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>"
options="<?= esc(json_encode($field->getOptionsArray(sprintf('%s.settings.%s.%s.options', $plugin->getKey(), $type, $field->key)))) ?>" options="<?= esc(json_encode($field->getOptionsArray(sprintf('%s.settings.%s.%s.options', $plugin->getKey(), $type, $field->key)))) ?>"
isRequired="<?= $field->optional ? 'false' : 'true' ?>" isRequired="<?= $field->optional ? 'false' : 'true' ?>"
value="<?= esc(json_encode(get_plugin_option($plugin->getKey(), $field->key, $context))) ?>" value="<?= esc(json_encode(get_plugin_setting($plugin->getKey(), $field->key, $context))) ?>"
/> />
<?php break; <?php break;
case 'email': ?> case 'email': ?>
@ -60,7 +60,7 @@
hint="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>" hint="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>"
helper="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>" helper="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>"
isRequired="<?= $field->optional ? 'false' : 'true' ?>" isRequired="<?= $field->optional ? 'false' : 'true' ?>"
value="<?= get_plugin_option($plugin->getKey(), $field->key, $context) ?>" value="<?= get_plugin_setting($plugin->getKey(), $field->key, $context) ?>"
/> />
<?php break; <?php break;
case 'url': ?> case 'url': ?>
@ -73,7 +73,7 @@
hint="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>" hint="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>"
helper="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>" helper="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>"
isRequired="<?= $field->optional ? 'false' : 'true' ?>" isRequired="<?= $field->optional ? 'false' : 'true' ?>"
value="<?= get_plugin_option($plugin->getKey(), $field->key, $context) ?>" value="<?= get_plugin_setting($plugin->getKey(), $field->key, $context) ?>"
/> />
<?php break; <?php break;
case 'number': ?> case 'number': ?>
@ -85,7 +85,7 @@
hint="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>" hint="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>"
helper="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>" helper="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>"
isRequired="<?= $field->optional ? 'false' : 'true' ?>" isRequired="<?= $field->optional ? 'false' : 'true' ?>"
value="<?= get_plugin_option($plugin->getKey(), $field->key, $context) ?>" value="<?= get_plugin_setting($plugin->getKey(), $field->key, $context) ?>"
/> />
<?php break; <?php break;
case 'textarea': ?> case 'textarea': ?>
@ -96,7 +96,7 @@
hint="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>" hint="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>"
helper="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>" helper="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>"
isRequired="<?= $field->optional ? 'false' : 'true' ?>" isRequired="<?= $field->optional ? 'false' : 'true' ?>"
value="<?= get_plugin_option($plugin->getKey(), $field->key, $context) ?>" value="<?= get_plugin_setting($plugin->getKey(), $field->key, $context) ?>"
/> />
<?php break; <?php break;
case 'markdown': ?> case 'markdown': ?>
@ -107,7 +107,7 @@
hint="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>" hint="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>"
helper="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>" helper="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>"
isRequired="<?= $field->optional ? 'false' : 'true' ?>" isRequired="<?= $field->optional ? 'false' : 'true' ?>"
value="<?= get_plugin_option($plugin->getKey(), $field->key, $context) ?>" value="<?= get_plugin_setting($plugin->getKey(), $field->key, $context) ?>"
/> />
<?php break; <?php break;
case 'datetime': case 'datetime':
@ -119,7 +119,7 @@
hint="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>" hint="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>"
helper="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>" helper="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>"
isRequired="<?= $field->optional ? 'false' : 'true' ?>" isRequired="<?= $field->optional ? 'false' : 'true' ?>"
value="<?= get_plugin_option($plugin->getKey(), $field->key, $context) ?>" value="<?= get_plugin_setting($plugin->getKey(), $field->key, $context) ?>"
/> />
<?php break; <?php break;
default: ?> default: ?>
@ -130,7 +130,7 @@
hint="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>" hint="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>"
helper="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>" helper="<?= esc($field->getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>"
isRequired="<?= $field->optional ? 'false' : 'true' ?>" isRequired="<?= $field->optional ? 'false' : 'true' ?>"
value="<?= get_plugin_option($plugin->getKey(), $field->key, $context) ?>" value="<?= get_plugin_setting($plugin->getKey(), $field->key, $context) ?>"
/> />
<?php endswitch; ?> <?php endswitch; ?>