diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..22d0d82f8 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +vendor diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..ce1973f8c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,64 @@ +sudo: false + +dist: trusty + +language: php + +php: + - 7.0 + - 7.1 + - 7.2 + - 7.3 + +notifications: + email: + on_success: never + on_failure: change + +branches: + only: + - master + - development + +cache: + apt: true + directories: + - vendor + - node_modules + - composer + - $HOME/.composer/cache + +matrix: + fast_finish: true + include: + - php: 7.3 + env: WP_VERSION=latest WP_MULTISITE=0 + - php: 7.2 + env: WP_VERSION=latest WP_MULTISITE=0 + - php: 7.2 + env: WP_VERSION=latest WP_MULTISITE=1 + - php: 7.1 + env: WP_VERSION=latest WP_MULTISITE=0 + - php: 7.0 + env: WP_VERSION=latest WP_MULTISITE=1 + + allow_failures: + # Allow failures for unstable builds. + - php: nightly + +before_install: + # Speed up build time by disabling Xdebug. + # https://johnblackbourn.com/reducing-travis-ci-build-times-for-wordpress-projects/ + # https://twitter.com/kelunik/status/954242454676475904 + - phpenv config-rm xdebug.ini || echo 'No xdebug config.' + # Install PHP CodeSniffer. + - composer self-update + - composer clearcache + - composer install + - phpenv rehash + +script: + # Search for PHP syntax errors. + - find -L . -path ./vendor -prune -o -name '*.php' -print0 | xargs -0 -n 1 -P 4 php -l + # Run PHPCS. + - composer check-cs . -- --runtime-set ignore_warnings_on_exit 1 diff --git a/README.md b/README.md new file mode 100644 index 000000000..ae733528e --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Eightshift Libs + +TBD diff --git a/composer.json b/composer.json new file mode 100644 index 000000000..69f8be61a --- /dev/null +++ b/composer.json @@ -0,0 +1,44 @@ +{ + "name": "infinum/eightshift-libs", + "description": "WordPress libs developed by Eightshift team to use in modern WordPress.", + "keywords": [ + "composer", "installer", "plugin" + ], + "homepage": "https://eightshift.com/", + "license": "MIT", + "authors": [ + { + "name": "Eightshift team", + "email": "team@eightshift.com", + "homepage": "https://eightshift.com/", + "role": "Developer / IT Manager" + } + ], + "support": { + "issues": "https://github.com/infinum/eightshift-libs/issues", + "source": "https://github.com/infinum/eightshift-libs" + }, + "require": { + "php": ">=7.0" + }, + "require-dev": { + "infinum/coding-standards-wp": "^0.4.1", + "dealerdirect/phpcodesniffer-composer-installer": "^0.5" + }, + "autoload": { + "psr-4": { + "Eightshift_Libs\\": "src/" + } + }, + "minimum-stability": "dev", + "prefer-stable": true, + "config": { + "sort-packages": true, + "optimize-autoloader": true, + "process-timeout": 2000 + }, + "scripts": { + "check-cs": "@php ./vendor/bin/phpcs", + "fix-cs": "@php ./vendor/bin/phpcbf" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 000000000..50de2d975 --- /dev/null +++ b/composer.lock @@ -0,0 +1,389 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "fda87bcab613aa12bab5ea6cc1cf4ea0", + "packages": [], + "packages-dev": [ + { + "name": "dealerdirect/phpcodesniffer-composer-installer", + "version": "v0.5.0", + "source": { + "type": "git", + "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", + "reference": "e749410375ff6fb7a040a68878c656c2e610b132" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/e749410375ff6fb7a040a68878c656c2e610b132", + "reference": "e749410375ff6fb7a040a68878c656c2e610b132", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0", + "php": "^5.3|^7", + "squizlabs/php_codesniffer": "^2|^3" + }, + "require-dev": { + "composer/composer": "*", + "phpcompatibility/php-compatibility": "^9.0", + "sensiolabs/security-checker": "^4.1.0" + }, + "type": "composer-plugin", + "extra": { + "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + }, + "autoload": { + "psr-4": { + "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Franck Nijhof", + "email": "franck.nijhof@dealerdirect.com", + "homepage": "http://www.frenck.nl", + "role": "Developer / IT Manager" + } + ], + "description": "PHP_CodeSniffer Standards Composer Installer Plugin", + "homepage": "http://www.dealerdirect.com", + "keywords": [ + "PHPCodeSniffer", + "PHP_CodeSniffer", + "code quality", + "codesniffer", + "composer", + "installer", + "phpcs", + "plugin", + "qa", + "quality", + "standard", + "standards", + "style guide", + "stylecheck", + "tests" + ], + "time": "2018-10-26T13:21:45+00:00" + }, + { + "name": "infinum/coding-standards-wp", + "version": "0.4.1", + "source": { + "type": "git", + "url": "https://github.com/infinum/coding-standards-wp.git", + "reference": "87aa3608eb064308291f8f7f3d3d30a8fd1ea296" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/infinum/coding-standards-wp/zipball/87aa3608eb064308291f8f7f3d3d30a8fd1ea296", + "reference": "87aa3608eb064308291f8f7f3d3d30a8fd1ea296", + "shasum": "" + }, + "require": { + "php": ">=5.6", + "phpcompatibility/phpcompatibility-wp": "^2.0", + "squizlabs/php_codesniffer": "^3.3.0", + "wp-coding-standards/wpcs": "^1.0.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3", + "phpcompatibility/php-compatibility": "^9.0", + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0", + "roave/security-advisories": "dev-master" + }, + "suggest": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically." + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Contributors", + "homepage": "https://github.com/infinum/coding-standards-wp/graphs/contributors" + } + ], + "description": "Infinum WordPress Coding Standards", + "homepage": "https://github.com/infinum/coding-standards-wp", + "keywords": [ + "Eightshift", + "Infinum", + "phpcs", + "standards", + "wordpress" + ], + "time": "2018-11-15T12:49:58+00:00" + }, + { + "name": "phpcompatibility/php-compatibility", + "version": "9.1.1", + "source": { + "type": "git", + "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", + "reference": "2b63c5d284ab8857f7b1d5c240ddb507a6b2293c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/2b63c5d284ab8857f7b1d5c240ddb507a6b2293c", + "reference": "2b63c5d284ab8857f7b1d5c240ddb507a6b2293c", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "squizlabs/php_codesniffer": "^2.3 || ^3.0.2" + }, + "conflict": { + "squizlabs/php_codesniffer": "2.6.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0" + }, + "suggest": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Contributors", + "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors" + }, + { + "name": "Wim Godden", + "homepage": "https://github.com/wimg", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + } + ], + "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", + "homepage": "http://techblog.wimgodden.be/tag/codesniffer/", + "keywords": [ + "compatibility", + "phpcs", + "standards" + ], + "time": "2018-12-30T23:16:27+00:00" + }, + { + "name": "phpcompatibility/phpcompatibility-paragonie", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git", + "reference": "9160de79fcd683b5c99e9c4133728d91529753ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/9160de79fcd683b5c99e9c4133728d91529753ea", + "reference": "9160de79fcd683b5c99e9c4133728d91529753ea", + "shasum": "" + }, + "require": { + "phpcompatibility/php-compatibility": "^9.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.4" + }, + "suggest": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.4 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Wim Godden", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "lead" + } + ], + "description": "A set of rulesets for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by the Paragonie polyfill libraries.", + "homepage": "http://phpcompatibility.com/", + "keywords": [ + "compatibility", + "paragonie", + "phpcs", + "polyfill", + "standards" + ], + "time": "2018-12-16T19:10:44+00:00" + }, + { + "name": "phpcompatibility/phpcompatibility-wp", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git", + "reference": "cb303f0067cd5b366a41d4fb0e254fb40ff02efd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/cb303f0067cd5b366a41d4fb0e254fb40ff02efd", + "reference": "cb303f0067cd5b366a41d4fb0e254fb40ff02efd", + "shasum": "" + }, + "require": { + "phpcompatibility/php-compatibility": "^9.0", + "phpcompatibility/phpcompatibility-paragonie": "^1.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3" + }, + "suggest": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Wim Godden", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "lead" + } + ], + "description": "A ruleset for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by WordPress.", + "homepage": "http://phpcompatibility.com/", + "keywords": [ + "compatibility", + "phpcs", + "standards", + "wordpress" + ], + "time": "2018-10-07T18:31:37+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.4.1", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "5b4333b4010625d29580eb4a41f1e53251be6baa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5b4333b4010625d29580eb4a41f1e53251be6baa", + "reference": "5b4333b4010625d29580eb4a41f1e53251be6baa", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "bin": [ + "bin/phpcs", + "bin/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards" + ], + "time": "2019-03-19T03:22:27+00:00" + }, + { + "name": "wp-coding-standards/wpcs", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards.git", + "reference": "f328bcafd97377e8e5e5d7b244d5ddbf301a3a5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/WordPress-Coding-Standards/WordPress-Coding-Standards/zipball/f328bcafd97377e8e5e5d7b244d5ddbf301a3a5c", + "reference": "f328bcafd97377e8e5e5d7b244d5ddbf301a3a5c", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "squizlabs/php_codesniffer": "^2.9.0 || ^3.0.2" + }, + "require-dev": { + "phpcompatibility/php-compatibility": "^9.0" + }, + "suggest": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically." + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Contributors", + "homepage": "https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress coding conventions", + "keywords": [ + "phpcs", + "standards", + "wordpress" + ], + "time": "2018-12-18T09:43:51+00:00" + } + ], + "aliases": [], + "minimum-stability": "dev", + "stability-flags": [], + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": ">=7.0" + }, + "platform-dev": [] +} diff --git a/examples/admin/class-register-post-type.php b/examples/admin/class-register-post-type.php new file mode 100644 index 000000000..3affd0477 --- /dev/null +++ b/examples/admin/class-register-post-type.php @@ -0,0 +1,72 @@ + esc_html_x( 'FAQ', 'post type upper case singular name', 'eightshift-libs' ), + Label_Generator::SINGULAR_NAME_LC => esc_html_x( 'faq', 'post type lower case singular name', 'eightshift-libs' ), + Label_Generator::PLURAL_NAME_UC => esc_html_x( 'FAQs', 'post type upper case plural name', 'eightshift-libs' ), + Label_Generator::PLURAL_NAME_LC => esc_html_x( 'faqs', 'post type lower case plural name', 'eightshift-libs' ), + ]; + + return [ + 'label' => $nouns[ Label_Generator::SINGULAR_NAME_UC ], + 'labels' => ( new Label_Generator() )->get_generated_labels( $nouns ), + 'public' => true, + 'menu_position' => 50, + 'menu_icon' => self::MENU_ICON, + 'supports' => array( 'title', 'revisions', 'editor' ), + 'has_archive' => false, + 'show_in_rest' => true, + 'publicly_queryable' => true, + 'capability_type' => 'page', + 'map_meta_cap' => true, + 'can_export' => true, + ]; + } +} diff --git a/examples/admin/class-register-taxonomy.php b/examples/admin/class-register-taxonomy.php new file mode 100644 index 000000000..1c8c94924 --- /dev/null +++ b/examples/admin/class-register-taxonomy.php @@ -0,0 +1,77 @@ + esc_html_x( 'FAQ category', 'post type upper case singular name', 'eighshift-libs' ), + Label_Generator::SINGULAR_NAME_LC => esc_html_x( 'faq category', 'post type lower case singular name', 'eighshift-libs' ), + Label_Generator::PLURAL_NAME_UC => esc_html_x( 'FAQ categories', 'post type upper case plural name', 'eighshift-libs' ), + Label_Generator::PLURAL_NAME_LC => esc_html_x( 'faq categories', 'post type lower case plural name', 'eighshift-libs' ), + ]; + + return [ + 'label' => $nouns[ Label_Generator::SINGULAR_NAME_UC ], + 'labels' => ( new Label_Generator() )->get_generated_labels( $nouns ), + 'hierarchical' => true, + 'show_ui' => true, + 'show_admin_column' => true, + 'update_count_callback' => '_update_post_term_count', + 'query_var' => true, + ]; + } +} diff --git a/examples/blocks/heading/class-heading.php b/examples/blocks/heading/class-heading.php new file mode 100644 index 000000000..c259d09e8 --- /dev/null +++ b/examples/blocks/heading/class-heading.php @@ -0,0 +1,51 @@ + array( + 'type' => parent::TYPE_STRING, + ), + 'level' => array( + 'type' => parent::TYPE_NUMBER, + 'default' => '2', + ), + 'styleAlign' => array( + 'type' => parent::TYPE_STRING, + 'default' => 'center', + ), + 'styleSize' => array( + 'type' => parent::TYPE_STRING, + 'default' => 'huge', + ), + ); + } +} diff --git a/examples/includes/class-main.php b/examples/includes/class-main.php new file mode 100644 index 000000000..771cf621b --- /dev/null +++ b/examples/includes/class-main.php @@ -0,0 +1,41 @@ + Array of fully qualified class names. + */ + protected function get_service_classes() : array { + return [ + Admin\Admin::class, + ]; + } +} diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 000000000..4441c7318 --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,22 @@ + + + Eightshift Library uses extended WordPress coding standards with some minor corections. TBD + + + + + 0 + + + + 0 + + + + 0 + + + + 0 + + diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 000000000..e69de29bb diff --git a/src/blocks/class-attribute-type-enums.php b/src/blocks/class-attribute-type-enums.php new file mode 100644 index 000000000..7eb51a564 --- /dev/null +++ b/src/blocks/class-attribute-type-enums.php @@ -0,0 +1,60 @@ + [ $this, 'render' ], + 'attributes' => $this->get_attributes(), + ) + ); + } + ); + } + + /** + * Adds default attributes that are dynamically built for all blocks. + * These are: + * - blockName: Block's full name including namespace (example: infinum/heading) + * - rootClass: Block's root (base) BEM CSS class, built in "block/$name" format (example: block-heading) + * - jsClass: Block's js selector class, built in "js-block-$name" format (example: js-block-heading) + * + * @throws \Exception On missing block name. + * + * @return array + * + * @since 1.0.0 + */ + public function get_default_attributes() : array { + + // Make sure the class (block) extending this class (abstract Base_Block) + // has defined its own name. + if ( static::NAME === self::NAME ) { + throw Missing_Block::name_exception(); + } + + return [ + 'blockName' => array( + 'type' => parent::TYPE_STRING, + 'default' => self::BLOCK_NAMESPACE . '/' . static::NAME, + ), + 'rootClass' => array( + 'type' => parent::TYPE_STRING, + 'default' => 'block-' . static::NAME, + ), + 'jsClass' => array( + 'type' => parent::TYPE_STRING, + 'default' => 'js-block-' . static::NAME, + ), + ]; + } + + /** + * Get block attributes assigned inside block class. + * + * @return array + * + * @since 1.0.0 + */ + public function get_block_attributes() : array { + return []; + } + + /** + * Get all block attributes. Default and block attributes. + * + * @return array + * + * @since 1.0.0 + */ + public function get_attributes() : array { + return array_merge( $this->get_default_attributes(), $this->get_block_attributes() ); + } + + /** + * Renders the block using a template in Infinum\Blocks\Templates namespace/folder. + * Template file must have the same name as the class-blockname file, for example: + * + * Block: class-heading.php + * Template: heading.php + * + * @param array $attributes Array of attributes as defined in block's index.js. + * @param string $content Block's content. + * + * @throws \Exception On missing attributes OR missing template. + * @echo string + * + * @since 1.0.0 + */ + public function render( array $attributes, string $content ) : string { + + // Block must have a defined name to find its template. + // Make sure the class (block) extending this class (abstract Base_Block) + // has defined its own name. + if ( static::NAME === self::NAME ) { + throw Missing_Block::name_exception(); + } + + $template_path = 'src/blocks/' . static::NAME . '/view/' . static::NAME . '.php'; + $template = locate_template( $template_path ); + + if ( empty( $template ) ) { + throw Missing_Block::view_exception( static::NAME, $template_path ); + } + + // If everything is ok, return the contents of the template (return, NOT echo). + ob_start(); + include $template; + $output = ob_get_clean(); + unset( $template ); + return $output; + } +} diff --git a/src/blocks/interface-block.php b/src/blocks/interface-block.php new file mode 100644 index 000000000..8fbc6ad91 --- /dev/null +++ b/src/blocks/interface-block.php @@ -0,0 +1,76 @@ +register_assets_manifest_data(); + } + + /** + * Register the individual services of this plugin. + * + * @throws Exception\Invalid_Service If a service is not valid. + * + * @return void + * + * @since 1.0.0 + */ + public function register_services() : void { + + // Bail early so we don't instantiate services twice. + if ( ! empty( $this->services ) ) { + return; + } + + $classes = $this->get_service_classes(); + + $this->services = array_map( + [ $this, 'instantiate_service' ], + $classes + ); + array_walk( + $this->services, + function( Service $service ) { + $service->register(); + } + ); + } + + /** + * Provide menifest json url location. + * + * @return string + * + * @since 1.0.0 + */ + protected function get_manifest_url() : string { + return get_template_directory() . '/skin/public/manifest.json'; + } + + /** + * Register bundled asset manifest + * + * @throws Exception\Missing_Manifest Throws error if manifest is missing. + * + * @return void + * + * @since 1.0.0 + */ + public function register_assets_manifest_data() : void { + + $manifest = $this->get_manifest_url(); + if ( ! file_exists( $manifest ) ) { + $error_message = esc_html__( 'manifest.json is missing. Bundle the theme before using it.', 'developer-portal' ); + throw Exception\Missing_Manifest::message( $error_message ); + } + + define( 'INF_ASSETS_MANIFEST', implode( ' ', file( $manifest ) ) ); + } + + /** + * Instantiate a single service. + * + * @param string $class Service class to instantiate. + * + * @throws Exception\Invalid_Service If the service is not valid. + * + * @return Service + * + * @since 1.0.0 + */ + private function instantiate_service( $class ) { + if ( ! class_exists( $class ) ) { + throw Exception\Invalid_Service::from_service( $class ); + } + + $service = new $class(); + if ( ! $service instanceof Service ) { + throw Exception\Invalid_Service::from_service( $service ); + } + + return $service; + } + + /** + * Get the list of services to register. + * + * A list of classes which contain hooks. + * + * @return array Array of fully qualified class names. + * + * @since 1.0.0 + */ + protected function get_service_classes() : array { + return []; + } +} diff --git a/src/custom-post-type/class-base-post-type.php b/src/custom-post-type/class-base-post-type.php new file mode 100644 index 000000000..e22dbfdf8 --- /dev/null +++ b/src/custom-post-type/class-base-post-type.php @@ -0,0 +1,51 @@ +get_post_type_slug(), $this->get_post_type_arguments() ); + } + ); + } + + /** + * Get the slug to use for the custom post type. + * + * @return string Custom post type slug. + * + * @since 1.0.0 + */ + abstract protected function get_post_type_slug() : string; + + /** + * Get the arguments that configure the custom post type. + * + * @return array Array of arguments. + * + * @since 1.0.0 + */ + abstract protected function get_post_type_arguments() : array; +} diff --git a/src/custom-post-type/class-label-generator.php b/src/custom-post-type/class-label-generator.php new file mode 100644 index 000000000..20ffd69c5 --- /dev/null +++ b/src/custom-post-type/class-label-generator.php @@ -0,0 +1,159 @@ + esc_html_x( '%3$s', 'Post Type General Name', 'developer-portal' ), /* phpcs:disable */ + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'singular_name' => esc_html_x( '%1$s', 'Post Type Singular Name', 'developer-portal' ), /* phpcs:disable */ + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'menu_name' => esc_html__( '%3$s', 'developer-portal' ), /* phpcs:disable */ + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'name_admin_bar' => esc_html__( '%1$s', 'developer-portal' ), /* phpcs:disable */ + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'archives' => esc_html__( '%1$s Archives', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'attributes' => esc_html__( '%1$s Attributes', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'parent_item_colon' => esc_html__( 'Parent %1$s:', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'all_items' => esc_html__( 'All %3$s', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'add_new_item' => esc_html__( 'Add New %1$s', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'add_new' => esc_html__( 'Add New', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'new_item' => esc_html__( 'New %1$s', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'edit_item' => esc_html__( 'Edit %1$s', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'update_item' => esc_html__( 'Update %1$s', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'view_item' => esc_html__( 'View %1$s', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'view_items' => esc_html__( 'View %3$s', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'search_items' => esc_html__( 'Search %1$s', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'not_found' => esc_html__( 'Not found', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'not_found_in_trash' => esc_html__( 'Not found in Trash', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'featured_image' => esc_html__( 'Featured Image', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'set_featured_image' => esc_html__( 'Set featured image', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'remove_featured_image' => esc_html__( 'Remove featured image', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'use_featured_image' => esc_html__( 'Use as featured image', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'insert_into_item' => esc_html__( 'Insert into %2$s', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'uploaded_to_this_item' => esc_html__( 'Uploaded to this %2$s', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'items_list' => esc_html__( '%3$s list', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'items_list_navigation' => esc_html__( '%3$s list navigation', 'developer-portal' ), + /* Translators: %1$s uc singular, %2$s lc singular, %3$s uc plural, %4$s lc plural. */ + 'filter_items_list' => esc_html__( 'Filter %4$s list', 'developer-portal' ), + ]; + + return array_map( + function( $label ) use ( $nouns ) { + return sprintf( + $label, + $nouns[ self::SINGULAR_NAME_UC ], + $nouns[ self::SINGULAR_NAME_LC ], + $nouns[ self::PLURAL_NAME_UC ], + $nouns[ self::PLURAL_NAME_LC ] + ); + }, + $label_templates + ); + } +} diff --git a/src/custom-taxonomy/class-base-taxonomy.php b/src/custom-taxonomy/class-base-taxonomy.php new file mode 100644 index 000000000..0db369850 --- /dev/null +++ b/src/custom-taxonomy/class-base-taxonomy.php @@ -0,0 +1,66 @@ +get_taxonomy_slug(), + [ $this->get_post_type_slug() ], + $this->get_taxonomy_arguments() + ); + } + ); + } + + /** + * Get the slug of the custom taxonomy + * + * @return string Custom taxonomy slug. + * + * @since 1.0.0 + */ + abstract protected function get_taxonomy_slug() : string; + + /** + * Get the post type slug to use the taxonomy to + * + * @return string Custom post type slug. + * + * @since 1.0.0 + */ + abstract protected function get_post_type_slug() : string; + + /** + * Get the arguments that configure the custom taxonomy. + * + * @return array Array of arguments. + * + * @since 1.0.0 + */ + abstract protected function get_taxonomy_arguments() : array; +} diff --git a/src/exception/class-failed-to-load-view.php b/src/exception/class-failed-to-load-view.php new file mode 100644 index 000000000..2a6e3b038 --- /dev/null +++ b/src/exception/class-failed-to-load-view.php @@ -0,0 +1,37 @@ +getMessage() + ); + + return new static( $message, $exception->getCode(), $exception ); + } +} diff --git a/src/exception/class-invalid-callback.php b/src/exception/class-invalid-callback.php new file mode 100644 index 000000000..4a400ace1 --- /dev/null +++ b/src/exception/class-invalid-callback.php @@ -0,0 +1,36 @@ +