diff --git a/.gitattributes b/.gitattributes index 57b0381..fd150f6 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,4 +2,5 @@ /.gitattributes export-ignore /.gitignore export-ignore /LICENSE export-ignore -/README.md export-ignore \ No newline at end of file +/README.md export-ignore +.php-cs.php \ No newline at end of file diff --git a/.gitignore b/.gitignore index c6ba632..124a343 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /vendor/* !/vendor/.gitignore +composer.lock +.php-cs-fixer.cache \ No newline at end of file diff --git a/.php-cs.php b/.php-cs.php new file mode 100644 index 0000000..7392fce --- /dev/null +++ b/.php-cs.php @@ -0,0 +1,158 @@ +setRiskyAllowed(true) + ->setRules([ + 'array_syntax' => true, + 'assign_null_coalescing_to_coalesce_equal' => true, + 'backtick_to_shell_exec' => true, + 'binary_operator_spaces' => true, + 'blank_line_after_namespace' => true, + 'blank_line_after_opening_tag' => true, + 'blank_line_before_statement' => true, + 'blank_line_between_import_groups' => true, + 'braces' => true, + 'cast_spaces' => true, + 'class_attributes_separation' => true, + 'class_definition' => true, + 'class_reference_name_casing' => true, + 'clean_namespace' => true, + 'compact_nullable_typehint' => true, + 'concat_space' => ['spacing'=>'one'], + 'constant_case' => true, + 'declare_equal_normalize' => true, + 'echo_tag_syntax' => true, + 'elseif' => true, + 'empty_loop_body' => true, + 'empty_loop_condition' => true, + 'encoding' => true, + 'full_opening_tag' => true, + 'fully_qualified_strict_types' => false, + 'function_declaration' => false, + 'function_typehint_space' => true, + 'general_phpdoc_tag_rename' => true, + 'heredoc_indentation' => true, + 'include' => true, + 'increment_style' => true, + 'indentation_type' => true, + 'integer_literal_case' => true, + 'lambda_not_used_import' => true, + 'line_ending' => true, + 'linebreak_after_opening_tag' => true, + 'list_syntax' => true, + 'lowercase_cast' => true, + 'lowercase_keywords' => true, + 'lowercase_static_reference' => true, + 'magic_constant_casing' => true, + 'magic_method_casing' => true, + 'method_argument_space' => true, + 'native_function_casing' => true, + 'native_function_type_declaration_casing' => true, + 'new_with_braces' => true, + 'no_alias_language_construct_call' => true, + 'no_alternative_syntax' => true, + 'no_binary_string' => true, + 'no_blank_lines_after_class_opening' => true, + 'no_blank_lines_after_phpdoc' => true, + 'no_break_comment' => true, + 'no_closing_tag' => true, + 'no_empty_comment' => true, + 'no_empty_phpdoc' => true, + 'no_empty_statement' => true, + 'no_extra_blank_lines' => true, + 'no_leading_import_slash' => true, + 'no_leading_namespace_whitespace' => true, + 'no_mixed_echo_print' => true, + 'no_multiline_whitespace_around_double_arrow' => true, + 'no_short_bool_cast' => true, + 'no_singleline_whitespace_before_semicolons' => true, + 'no_space_around_double_colon' => true, + 'no_spaces_after_function_name' => true, + 'no_spaces_around_offset' => true, + 'no_spaces_inside_parenthesis' => true, + 'no_superfluous_phpdoc_tags' => true, + 'no_trailing_comma_in_list_call' => true, + 'no_trailing_comma_in_singleline_array' => true, + 'no_trailing_comma_in_singleline_function_call' => true, + 'no_trailing_whitespace' => true, + 'no_trailing_whitespace_in_comment' => true, + 'no_unneeded_control_parentheses' => true, + 'no_unneeded_curly_braces' => true, + 'no_unneeded_import_alias' => true, + 'no_unset_cast' => true, + 'no_unused_imports' => true, + 'no_useless_nullsafe_operator' => true, + 'no_whitespace_before_comma_in_array' => true, + 'no_whitespace_in_blank_line' => true, + 'normalize_index_brace' => true, + 'object_operator_without_whitespace' => true, + 'ordered_class_elements' => true, + 'ordered_imports' => true, + 'php_unit_fqcn_annotation' => true, + 'php_unit_method_casing' => true, + 'phpdoc_align' => true, + 'phpdoc_annotation_without_dot' => true, + 'phpdoc_indent' => true, + 'phpdoc_inline_tag_normalizer' => true, + 'phpdoc_no_access' => true, + 'phpdoc_no_alias_tag' => true, + 'phpdoc_no_package' => true, + 'phpdoc_no_useless_inheritdoc' => true, + 'phpdoc_return_self_reference' => true, + 'phpdoc_scalar' => true, + 'phpdoc_separation' => true, + 'phpdoc_single_line_var_spacing' => true, + 'phpdoc_summary' => true, + 'phpdoc_tag_type' => true, + 'phpdoc_to_comment' => true, + 'phpdoc_trim' => true, + 'phpdoc_trim_consecutive_blank_line_separation' => true, + 'phpdoc_types' => true, + 'phpdoc_types_order' => true, + 'phpdoc_var_without_name' => true, + 'protected_to_private' => true, + 'return_type_declaration' => true, + 'semicolon_after_instruction' => true, + 'short_scalar_cast' => true, + 'simple_to_complex_string_variable' => true, + 'single_blank_line_at_eof' => true, + 'single_blank_line_before_namespace' => true, + 'single_class_element_per_statement' => true, + 'single_import_per_statement' => true, + 'single_line_after_imports' => true, + 'single_line_comment_spacing' => true, + 'single_line_comment_style' => true, + 'single_line_throw' => true, + 'single_quote' => true, + 'single_space_after_construct' => true, + 'single_trait_insert_per_statement' => true, + 'space_after_semicolon' => true, + 'standardize_increment' => true, + 'standardize_not_equals' => true, + 'switch_case_semicolon_to_colon' => true, + 'switch_case_space' => true, + 'switch_continue_to_break' => true, + 'ternary_operator_spaces' => true, + 'ternary_to_null_coalescing' => true, + 'trailing_comma_in_multiline' => true, + 'trim_array_spaces' => true, + 'types_spaces' => true, + 'unary_operator_spaces' => true, + 'visibility_required' => true, + 'whitespace_after_comma_in_array' => true, + 'yoda_style' => true, + ]) + ->setFinder( + PhpCsFixer\Finder::create() + ->exclude( + [ + 'vendor', + 'single_pages' + ] + ) + ->in( + [ + __DIR__ + ] + ) + ); diff --git a/README.md b/README.md index 721835f..d7e9977 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,19 @@ -[![SensioLabsInsight](https://insight.sensiolabs.com/projects/86a71f44-22ed-46e6-9fc7-d7d3ca79815e/mini.png)](https://insight.sensiolabs.com/projects/86a71f44-22ed-46e6-9fc7-d7d3ca79815e) - -Concrete5 package for v8 - Adds beberlei/DoctrineExtensions to concrete5 +Concrete CMS Package (v8/v9): Doctrine DQL Extentsions ====== +Adds beberlei/DoctrineExtensions to Concrete CMS Installation ------------------ ### Install the package with the projects composer.json file -1. Run the following command from the installation {root} folder to get the latest version - - - composer require kaapiii/concrete5_doctrine_dql_extensions - - -2. Add the following line to the 'require' section of the concrete5 composer.json file - - - "kaapiii/concrete5_doctrine_dql_extensions": "^1.1" +1. Run the following command from the installation **{root}** folder to get the latest version. +```shell +composer require kaapiii/concrete5_doctrine_dql_extensions +``` -3. Install the package -4. Navigate to **System & Settings -> Doctrine DQL Extensions** to see the available DQL functions. You can now use the most common MySQL functions in your DQL queries and in the QueryBuilder. +2. Install the package +3. Navigate to **System & Settings -> Doctrine DQL Extensions** to see the available DQL functions. You can now use the most common MySQL functions in your DQL queries and in the QueryBuilder. ![screenshot](https://user-images.githubusercontent.com/995643/68252188-23a49500-0025-11ea-8a64-fb6329970608.png) diff --git a/composer.json b/composer.json index 9a8a778..355c774 100644 --- a/composer.json +++ b/composer.json @@ -10,10 +10,19 @@ } ], "config": { - "vendor-dir":"./vendor" + "vendor-dir":"./vendor", + "allow-plugins": { + "composer/installers": true + } }, "require": { "composer/installers": "~1.0", - "beberlei/doctrineextensions": "1.1.9" + "beberlei/doctrineextensions": "^1.1.9" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.17" + }, + "scripts": { + "csfixer": "vendor/bin/php-cs-fixer fix --config .php-cs.php" } } diff --git a/controller.php b/controller.php index 79e6ec5..b315c25 100644 --- a/controller.php +++ b/controller.php @@ -2,69 +2,66 @@ namespace Concrete\Package\Concrete5DoctrineDqlExtensions; -use Concrete\Core\Support\Facade\Log; use Concrete\Core\Package\Package; use Concrete\Core\Page\Single as PageSingle; -use Symfony\Component\Yaml\Yaml; +use Concrete\Core\Support\Facade\Log; +use Doctrine\ORM\Configuration; +use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Yaml\Exception\ParseException; +use Symfony\Component\Yaml\Yaml; /** - * Package controller + * Package controller. * * @author Markus Liechti * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -class Controller extends Package +final class controller extends Package { - protected $pkgHandle = 'concrete5_doctrine_dql_extensions'; + public const BEBERLEI = 'beberlei'; + + public const DOCTRINEEXTENSIONS = 'doctrineextensions'; + + public const CONFIG_FILE_NAME = 'mysql.yml'; + protected $appVersionRequired = '8.0.0'; - protected $pkgVersion = '1.1.1'; + + protected $pkgHandle = 'concrete5_doctrine_dql_extensions'; + + protected $pkgVersion = '1.2.0'; public function getPackageDescription() { - return t('Package adds additional MySQL functions for Doctrine2 query language and QueryBuilder'); + return t('Package adds additional MySQL functions for Doctrine Query Language and QueryBuilder'); } public function getPackageName() { - return t('Doctrine2 dql extensions'); + return t('Doctrine DQL Extensions'); } public function install() { $pkg = parent::install(); - PageSingle::add('/dashboard/system/doctrine_dql_extensions',$pkg); + PageSingle::add('/dashboard/system/doctrine_dql_extensions', $pkg); } public function on_start() { - // register the autoloading - if(file_exists($this->getPackagePath() . '/vendor/autoload.php')){ - require $this->getPackagePath() . '/vendor/autoload.php'; + if (file_exists($this->getPackagePath() . '/vendor/autoload.php')) { + require_once $this->getPackagePath() . '/vendor/autoload.php'; } - /** @var \Doctrine\ORM\EntityManager $em */ - $em = $this->app->make('Doctrine\ORM\EntityManager'); - /** @var \Doctrine\ORM\Configuration $config */ + $em = $this->app->make(EntityManagerInterface::class); $config = $em->getConfiguration(); - try{ - $this->registerDoctrineDqlExtensions($config); - }catch(\Doctrine\ORM\ORMException $e){ - Log::addAlert('While adding Doctrine DQL extensions to the EntityManager configuration something went wrong: '. $e); - } + $this->registerDoctrineDqlExtensions($config); } - /** - * Register Doctrine2 dql extensions - * - * @param $config \Doctrine\ORM\Configuration - * @return \Doctrine\ORM\Configuration mixed - * @throws \Doctrine\ORM\ORMException + * Register Doctrine DQL extensions. */ - public function registerDoctrineDqlExtensions($config) + public function registerDoctrineDqlExtensions(Configuration $config) { - $configSQL = $this->parseDoctrineQueryExtensionConfig(); $dqlFunctions = $configSQL['doctrine']['orm']['dql']; @@ -72,66 +69,54 @@ public function registerDoctrineDqlExtensions($config) $datetimeFunctions = $dqlFunctions['datetime_functions']; $numericFunctions = $dqlFunctions['numeric_functions']; $stringFunctions = $dqlFunctions['string_functions']; - if(count($datetimeFunctions)){ - foreach($datetimeFunctions as $name => $class){ + if (count($datetimeFunctions)) { + foreach ($datetimeFunctions as $name => $class) { $config->addCustomDatetimeFunction($name, $class); } } - if(count($numericFunctions)){ - foreach($numericFunctions as $name => $class){ + if (count($numericFunctions)) { + foreach ($numericFunctions as $name => $class) { $config->addCustomNumericFunction($name, $class); } } - if(count($stringFunctions)){ - foreach($stringFunctions as $name => $class){ + if (count($stringFunctions)) { + foreach ($stringFunctions as $name => $class) { $config->addCustomStringFunction($name, $class); } } - return $config; - } - /** - * Parse yaml config of MySQL doctrine dql extensions - * - * @return array - */ - protected function parseDoctrineQueryExtensionConfig(){ - try { - $config = Yaml::parse(file_get_contents($this->getMysqlConfig())); - } catch (ParseException $e) { - Log::addAlert('Unable to parse the MySQL YAML config file: '. $e); - } return $config; } /** * Get path to MySQL yaml config the vendor - * It takes into account how the package was installed + * It takes into account how the package was installed. * * @return string */ - protected function getMysqlConfig(){ + protected function getMysqlConfig() + { // Path to the mysql config, if package was installed manually, and the // package contains a 'vendor' directory - $localVendorPath = $this->getPackagePath(). DIRECTORY_SEPARATOR . DIRNAME_VENDOR - . DIRECTORY_SEPARATOR . 'beberlei' . DIRECTORY_SEPARATOR - . 'doctrineextensions' . DIRECTORY_SEPARATOR . 'config' - . DIRECTORY_SEPARATOR . 'mysql.yml'; + $localVendorPath = $this->getPackagePath() . DIRECTORY_SEPARATOR . DIRNAME_VENDOR + . DIRECTORY_SEPARATOR . self::BEBERLEI . DIRECTORY_SEPARATOR + . self::DOCTRINEEXTENSIONS . DIRECTORY_SEPARATOR . DIRNAME_CONFIG + . DIRECTORY_SEPARATOR . self::CONFIG_FILE_NAME; $globalVendorPath = DIR_BASE_CORE . DIRECTORY_SEPARATOR . DIRNAME_VENDOR - . DIRECTORY_SEPARATOR . 'beberlei' . DIRECTORY_SEPARATOR - . 'doctrineextensions' . DIRECTORY_SEPARATOR . 'config' - . DIRECTORY_SEPARATOR . 'mysql.yml'; + . DIRECTORY_SEPARATOR . self::BEBERLEI . DIRECTORY_SEPARATOR + . self::DOCTRINEEXTENSIONS . DIRECTORY_SEPARATOR . DIRNAME_CONFIG + . DIRECTORY_SEPARATOR . self::CONFIG_FILE_NAME; - # needed if concrete5 was created with "composer create-project -n concrete5/composer ." - $globalVendorPathWithComposer = dirname(DIR_BASE) . DIRECTORY_SEPARATOR . DIRNAME_VENDOR - . DIRECTORY_SEPARATOR . 'beberlei' . DIRECTORY_SEPARATOR - . 'doctrineextensions' . DIRECTORY_SEPARATOR . 'config' - . DIRECTORY_SEPARATOR . 'mysql.yml'; + // needed if concrete5 was created with "composer create-project -n concrete5/composer ." + $globalVendorPathWithComposer = DIR_BASE . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . DIRNAME_VENDOR + . DIRECTORY_SEPARATOR . self::BEBERLEI . DIRECTORY_SEPARATOR + . self::DOCTRINEEXTENSIONS . DIRECTORY_SEPARATOR . DIRNAME_CONFIG + . DIRECTORY_SEPARATOR . self::CONFIG_FILE_NAME; - if(file_exists($localVendorPath)){ + if (file_exists($localVendorPath)) { $path = $localVendorPath; - } else if (file_exists($globalVendorPath)){ + } elseif (file_exists($globalVendorPath)) { $path = $globalVendorPath; } else { $path = $globalVendorPathWithComposer; @@ -139,4 +124,20 @@ protected function getMysqlConfig(){ return $path; } + + /** + * Parse yaml config of MySQL doctrine dql extensions. + * + * @return array + */ + protected function parseDoctrineQueryExtensionConfig() + { + try { + $config = Yaml::parse(file_get_contents($this->getMysqlConfig())); + } catch (ParseException $e) { + Log::addAlert('Unable to parse the MySQL YAML config file: ' . $e); + } + + return $config; + } } diff --git a/controllers/single_page/dashboard/system/doctrine_dql_extensions.php b/controllers/single_page/dashboard/system/doctrine_dql_extensions.php index 9846037..a9a563a 100644 --- a/controllers/single_page/dashboard/system/doctrine_dql_extensions.php +++ b/controllers/single_page/dashboard/system/doctrine_dql_extensions.php @@ -2,81 +2,77 @@ namespace Concrete\Package\Concrete5DoctrineDqlExtensions\Controller\SinglePage\Dashboard\System; -use Concrete\Core\Package\Package; +use Concrete\Core\Page\Controller\DashboardPageController; +use Doctrine\ORM\Configuration; +use Doctrine\ORM\EntityManager; +use Doctrine\ORM\EntityManagerInterface; +use Log; +use ReflectionClass; +use ReflectionException; /** - * Behavioral settings controller + * Behavioral settings controller. * * @author Markus Liechti * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -class DoctrineDqlExtensions extends \Concrete\Core\Page\Controller\DashboardPageController{ - - - const DQL_STING_FUNCTION_KEYS = array( +final class DoctrineDqlExtensions extends DashboardPageController +{ + public const DQL_STING_FUNCTION_KEYS = [ 'customDatetimeFunctions', 'customNumericFunctions', - 'customStringFunctions'); + 'customStringFunctions', + ]; /** - * Constructor - * - * @param \Concrete\Core\Page\Page $c - */ - public function __construct(\Concrete\Core\Page\Page $c) { - parent::__construct($c); - } - - /** - * Show cateogry Tree + * Show category Tree. */ - public function view(){ - - $em = $this->app->make('Doctrine\ORM\EntityManager'); + public function view(): void + { + /** @var EntityManagerInterface $em */ + $em = $this->app->make(EntityManager::class); $config = $em->getConfiguration(); - $customFunctions = $this->filterCustomDQLFunctions($config); - $this->set('customFunctions', $customFunctions); - } - + /** - * With this function a protected or private - * property of a object can be accessed - * + * With this function a protected or private + * property of a object can be accessed. + * * @param object $obj - * @param string $prop + * + * @throws ReflectionException + * * @return type - * @throws \ReflectionException */ - protected function accessProtected($obj, $prop) { - $reflection = new \ReflectionClass($obj); + protected function accessProtected($obj, string $prop): mixed + { + $reflection = new ReflectionClass($obj); $property = $reflection->getProperty($prop); $property->setAccessible(true); + return $property->getValue($obj); } /** - * Filter protected ORM config values so only the custom functions are kept - * - * @param $config \Doctrine\ORM\Configuration - * @return array + * Filter protected ORM config values so only the custom functions are kept. */ - protected function filterCustomDQLFunctions($config){ + protected function filterCustomDQLFunctions(Configuration $config): array + { // Access the private property for \Doctrine\ORM\Config - - try{ + try { $customFunctions = $this->accessProtected($config, '_attributes'); - }catch(\ReflectionException $e){ - \Log::addAlert('The registered DQL functions could not be retrieved. ' . $e); + } catch (ReflectionException $e) { + Log::addAlert('The registered DQL functions could not be retrieved. ' . $e); } $allowedKeys = self::DQL_STING_FUNCTION_KEYS; - $filteredFunctions = array_filter($customFunctions, function($key) use ($allowedKeys){ - return in_array($key, $allowedKeys); - }, ARRAY_FILTER_USE_KEY); - return $filteredFunctions; + return array_filter( + $customFunctions, + static fn ($key) => in_array($key, $allowedKeys), + ARRAY_FILTER_USE_KEY, + ); } }