From af1731209624aa21f08be3dffb316ef5cbd076cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Ruz=CC=8Cevic=CC=81?= Date: Sat, 27 Apr 2024 20:35:33 +0200 Subject: [PATCH] updating helpers from the PR suggestions --- src/Cache/AbstractManifestCache.php | 12 +- src/Cli/Cli.php | 6 +- src/Config/AbstractConfigData.php | 100 +++++++++-- src/Config/ConfigDataInterface.php | 44 ----- src/Config/ConfigPluginCli.php | 113 ++++++++++++ ...figExample.php => ConfigPluginExample.php} | 8 +- .../{ConfigCli.php => ConfigThemeCli.php} | 14 +- src/Config/ConfigThemeExample.php | 66 +++++++ src/Exception/InvalidPath.php | 29 ++- src/Helpers/ApiTrait.php | 170 ++++++++++++++++++ src/Helpers/Components.php | 9 +- src/Helpers/ObjectHelperTrait.php | 75 ++++++++ 12 files changed, 551 insertions(+), 95 deletions(-) delete mode 100644 src/Config/ConfigDataInterface.php create mode 100644 src/Config/ConfigPluginCli.php rename src/Config/{ConfigExample.php => ConfigPluginExample.php} (84%) rename src/Config/{ConfigCli.php => ConfigThemeCli.php} (86%) create mode 100644 src/Config/ConfigThemeExample.php create mode 100644 src/Helpers/ApiTrait.php diff --git a/src/Cache/AbstractManifestCache.php b/src/Cache/AbstractManifestCache.php index 16f7a53f4..ed5b5311e 100644 --- a/src/Cache/AbstractManifestCache.php +++ b/src/Cache/AbstractManifestCache.php @@ -70,12 +70,16 @@ public function getManifestCacheTopItem(string $key, string $cacheType = self::T 'key' => $key, ]; - if (\defined('WP_ENVIRONMENT_TYPE') && \WP_ENVIRONMENT_TYPE === 'development') { - $data = $this->getAllManifests()[$key] ?? []; - } else { + $data = []; + + if (\defined('WP_ENVIRONMENT_TYPE') && \WP_ENVIRONMENT_TYPE !== 'development') { $data = $this->getCache($cacheType)[$key] ?? []; } + if (!$data) { + $data = $this->getAllManifests()[$key] ?? []; + } + if (!$data) { return $output; } @@ -218,7 +222,7 @@ protected function getCacheBuilder(): array 'multiple' => false, ], self::ASSETS_KEY => [ - 'path' => 'themePath', + 'path' => 'themeRoot', 'fileName' => "public{$sep}manifest.json", 'multiple' => false, ], diff --git a/src/Cli/Cli.php b/src/Cli/Cli.php index be37505d9..176fbda9e 100644 --- a/src/Cli/Cli.php +++ b/src/Cli/Cli.php @@ -30,7 +30,8 @@ use EightshiftLibs\Cli\ParentGroups\CliBlocks; use EightshiftLibs\Cli\ParentGroups\CliInit; use EightshiftLibs\Columns\Media\WebPMediaColumnCli; -use EightshiftLibs\Config\ConfigCli; +use EightshiftLibs\Config\ConfigThemeCli; +use EightshiftLibs\Config\ConfigPluginCli; use EightshiftLibs\ConfigProject\ConfigProjectCli; use EightshiftLibs\Setup\PluginManageCli; use EightshiftLibs\View\EscapedViewCli; @@ -102,7 +103,8 @@ class Cli ReusableBlocksHeaderFooterCli::class, AnalyticsGdprCli::class, WebPMediaColumnCli::class, - ConfigCli::class, + ConfigThemeCli::class, + ConfigPluginCli::class, ConfigProjectCli::class, AcfMetaCli::class, PostTypeCli::class, diff --git a/src/Config/AbstractConfigData.php b/src/Config/AbstractConfigData.php index 5a4075224..c7fc585a8 100644 --- a/src/Config/AbstractConfigData.php +++ b/src/Config/AbstractConfigData.php @@ -16,37 +16,103 @@ /** * The project config class. */ -abstract class AbstractConfigData implements ConfigDataInterface +abstract class AbstractConfig { /** - * Return project absolute path. + * Get the plugin version. * - * If used in a theme use get_template_directory() and in case it's used in a plugin use __DIR__. + * @return string + */ + public static function getPluginVersion(): string + { + return static::getPluginDetails()['Version'] ?? esc_html('1.0.0'); + } + + /** + * Get the plugin version. + * + * @return string + */ + public static function getPluginName(): string + { + return static::getPluginDetails()['Name'] ?? esc_html('Plugin'); + } + + /** + * Get the plugin text domain. + * + * @return string + */ + public static function getPluginTextDomain(): string + { + return static::getPluginDetails()['TextDomain'] ?? esc_html('PluginTextDomain'); + } + + /** + * Get the theme version. + * + * @return string + */ + public static function getThemeVersion(): string + { + return \wp_get_theme()->get('Version'); + } + + /** + * Get the theme name. + * + * @return string + */ + public static function getThemeName(): string + { + return \wp_get_theme()->get('Name'); + } + + /** + * Get the theme text domain. + * + * @return string + */ + public static function getThemeTextDomain(): string + { + return \wp_get_theme()->get('TextDomain'); + } + + /** + * Return projects absolute path. * * @param string $path Additional path to add to project path. * - * @throws InvalidPath If an invalid URI was passed. + * @throws InvalidPath If the path is not readable. * - * @return string Valid URI. + * @return string */ public static function getProjectPath(string $path = ''): string { - $locations = [ - Components::getProjectPaths('root', $path), - \trailingslashit(\get_stylesheet_directory()) . $path, - \trailingslashit(\get_template_directory()) . $path, - ]; + $fullPath = Components::getProjectPaths('themeRoot') . ltrim($path, \DIRECTORY_SEPARATOR); - foreach ($locations as $location) { - if (\is_readable($location)) { - return $location; - } + if (!\is_readable($fullPath)) { + throw InvalidPath::missingDirectoryException($fullPath); } - if (!\is_readable($path)) { - throw InvalidPath::fromUri($path); + return $fullPath; + } + + /** + * Get the plugin details. + * + * @return array + */ + private static function getPluginDetails(): array + { + if (!\function_exists('get_plugin_data')) { + require_once(\ABSPATH . 'wp-admin/includes/plugin.php'); } - return $path; + $path = Components::getProjectPaths('pluginRoot'); + + $name = \basename($path); + + return \get_plugin_data("{$path}{$name}.php"); } } diff --git a/src/Config/ConfigDataInterface.php b/src/Config/ConfigDataInterface.php deleted file mode 100644 index ee6c30162..000000000 --- a/src/Config/ConfigDataInterface.php +++ /dev/null @@ -1,44 +0,0 @@ - + */ + public function getDefaultArgs(): array + { + return [ + 'routes_version' => '1', + ]; + } + + /** + * Get WPCLI command doc + * + * @return array>|string> + */ + public function getDoc(): array + { + return [ + 'shortdesc' => 'Create plugin config service class.', + 'synopsis' => [ + [ + 'type' => 'assoc', + 'name' => 'routes_version', + 'description' => 'Define project REST version.', + 'optional' => true, + 'default' => $this->getDefaultArg('routes_version'), + ], + ], + 'longdesc' => $this->prepareLongDesc(" + ## USAGE + + Used to create plugin config class with settings like project name, version, REST-API name/version, etc. + + ## EXAMPLES + + # Create service class: + $ wp {$this->commandParentName} {$this->getCommandParentName()} {$this->getCommandName()} + + ## RESOURCES + + Service class will be created from this example: + https://github.com/infinum/eightshift-libs/blob/develop/src/Config/ConfigPluginExample.php + "), + ]; + } + + /* @phpstan-ignore-next-line */ + public function __invoke(array $args, array $assocArgs) + { + $this->getIntroText($assocArgs); + + // Get Props. + $routesVersion = $this->getArg($assocArgs, 'routes_version'); + + $className = $this->getClassShortName(); + + // Read the template contents, and replace the placeholders with provided variables. + $class = $this->getExampleTemplate(__DIR__, $className) + ->renameClassName($className) + ->renameNamespace($assocArgs) + ->renameUse($assocArgs); + + if (!empty($routesVersion)) { + $class->searchReplaceString($this->getArgTemplate('routes_version'), $routesVersion); + } + + // Output final class to new file/folder and finish. + $class->outputWrite(Components::getProjectPaths('srcDestination', 'Config'), "{$className}.php", $assocArgs); + } +} diff --git a/src/Config/ConfigExample.php b/src/Config/ConfigPluginExample.php similarity index 84% rename from src/Config/ConfigExample.php rename to src/Config/ConfigPluginExample.php index c4bb760de..904d5ad53 100644 --- a/src/Config/ConfigExample.php +++ b/src/Config/ConfigPluginExample.php @@ -13,12 +13,12 @@ namespace EightshiftBoilerplate\Config; -use EightshiftLibs\Config\AbstractConfigData; +use EightshiftLibs\Config\AbstractConfig; /** * The project config class. */ -class ConfigExample extends AbstractConfigData +class ConfigPluginExample extends AbstractConfig { /** * Method that returns project name. @@ -27,7 +27,7 @@ class ConfigExample extends AbstractConfigData */ public static function getProjectName(): string { - return \wp_get_theme('', \dirname(__DIR__, 3))->get('TextDomain'); + return self::getPluginName(); } /** @@ -37,7 +37,7 @@ public static function getProjectName(): string */ public static function getProjectVersion(): string { - return \wp_get_theme('', \dirname(__DIR__, 3))->get('Version'); + return self::getPluginVersion(); } /** diff --git a/src/Config/ConfigCli.php b/src/Config/ConfigThemeCli.php similarity index 86% rename from src/Config/ConfigCli.php rename to src/Config/ConfigThemeCli.php index c3920b57b..d524a6ce8 100644 --- a/src/Config/ConfigCli.php +++ b/src/Config/ConfigThemeCli.php @@ -1,7 +1,7 @@ 'Create project config service class.', + 'shortdesc' => 'Create theme config service class.', 'synopsis' => [ [ 'type' => 'assoc', @@ -72,7 +72,7 @@ public function getDoc(): array 'longdesc' => $this->prepareLongDesc(" ## USAGE - Used to create project config class with settings like project name, version, REST-API name/version, etc. + Used to create theme config class with settings like project name, version, REST-API name/version, etc. ## EXAMPLES @@ -82,7 +82,7 @@ public function getDoc(): array ## RESOURCES Service class will be created from this example: - https://github.com/infinum/eightshift-libs/blob/develop/src/Config/ConfigExample.php + https://github.com/infinum/eightshift-libs/blob/develop/src/Config/ConfigThemeExample.php "), ]; } diff --git a/src/Config/ConfigThemeExample.php b/src/Config/ConfigThemeExample.php new file mode 100644 index 000000000..574fbd421 --- /dev/null +++ b/src/Config/ConfigThemeExample.php @@ -0,0 +1,66 @@ + $additional Additonal data to attach to response. + * + * @return array|int|string> + */ + public static function getApiSuccessPublicOutput(string $msg, array $additional = []): array + { + $output = [ + 'status' => self::STATUS_SUCCESS, + 'code' => self::API_RESPONSE_CODE_SUCCESS, + 'message' => $msg, + ]; + + if ($additional) { + $output['data'] = $additional; + } + + return $output; + } + + /** + * Return API warning response array. + * + * @param string $msg Msg for the user. + * @param array $additional Additonal data to attach to response. + * + * @return array|int|string> + */ + public static function getApiWarningPublicOutput(string $msg, array $additional = []): array + { + $output = [ + 'status' => self::STATUS_WARNING, + 'code' => self::API_RESPONSE_CODE_SUCCESS, + 'message' => $msg, + ]; + + if ($additional) { + $output['data'] = $additional; + } + + return $output; + } + + /** + * Return API error response array. + * + * @param string $msg Msg for the user. + * @param array $additional Additonal data to attach to response. + * + * @return array|int|string> + */ + public static function getApiErrorPublicOutput(string $msg, array $additional = []): array + { + $output = [ + 'status' => self::STATUS_ERROR, + 'code' => self::API_RESPONSE_CODE_ERROR, + 'message' => $msg, + ]; + + if ($additional) { + $output['data'] = $additional; + } + + return $output; + } + + /** + * Get API route URL data. + * + * @param string $namespace The namespace. + * @param string $version The version. + * @param string $path The path. + * + * @return array + */ + public static function getApiRouteUrlData(string $namespace, string $version, string $path): array + { + $prefix = rtrim(\get_rest_url(\get_current_blog_id()), '/'); + + return [ + 'prefix' => $prefix, + 'namespace' => $namespace, + 'version' => $version, + 'url' => "{$prefix}/{$namespace}/{$version}/{$path}", + ]; + } +} diff --git a/src/Helpers/Components.php b/src/Helpers/Components.php index 164d37c5b..777d9a5e5 100644 --- a/src/Helpers/Components.php +++ b/src/Helpers/Components.php @@ -59,6 +59,11 @@ class Components */ use MediaTrait; + /** + * API trait. + */ + use ApiTrait; + /** * Get all project paths for store. * @@ -372,8 +377,8 @@ public static function getProjectPaths(string $type = '', string $suffix = '', s break; case 'cliOutput': - case 'themePath': - case 'pluginPath': + case 'themeRoot': + case 'pluginRoot': if (\getenv('ES_TEST')) { $internalPrefix = \dirname(__FILE__, 3); $path = $cliOutputPath; diff --git a/src/Helpers/ObjectHelperTrait.php b/src/Helpers/ObjectHelperTrait.php index 1fb6d7303..0c4664427 100644 --- a/src/Helpers/ObjectHelperTrait.php +++ b/src/Helpers/ObjectHelperTrait.php @@ -13,6 +13,8 @@ use DOMDocument; use EightshiftLibs\Exception\InvalidManifest; +use RecursiveArrayIterator; +use RecursiveIteratorIterator; /** * Class Object Helper @@ -71,6 +73,29 @@ function ($a) use (&$output) { return $output; } + /** + * Find array value by key in recursive array. + * + * @param array $array Array to find. + * @param string $needle Key name to find. + * + * @return array + */ + public static function recursiveArrayFind(array $array, string $needle): array + { + $iterator = new RecursiveArrayIterator($array); + $recursive = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST); + $aHitList = []; + + foreach ($recursive as $key => $value) { + if ($key === $needle) { + \array_push($aHitList, $value); + } + } + + return $aHitList; + } + /** * Sanitize all values in an array. * @@ -132,6 +157,18 @@ public static function camelToKebabCase(string $convert): string return \str_replace('--', '-', $output); } + /** + * Convert camel to snake case + * + * @param string $input Name to change. + * + * @return string + */ + public static function camelToSnakeCase($input): string + { + return \strtolower((string) \preg_replace('/(?