Skip to content
Snippets Groups Projects
Verified Commit f75263bc authored by Bartek Jaskulski's avatar Bartek Jaskulski
Browse files

build: prepare tools and basic build

parent 16880789
No related branches found
No related tags found
No related merge requests found
Pipeline #8880 failed with stages
in 30 seconds
Showing
with 1206 additions and 164 deletions
# This file is for unifying the coding style for different editors and IDEs
# editorconfig.org
# WordPress Coding Standards
# https://make.wordpress.org/core/handbook/coding-standards/
# Configuration for PhpStorm
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = tab
indent_size = 4
tab_width = 4
ij_continuation_indent_size = 4
[*.scss]
ij_scss_enforce_quotes_on_format = true
ij_scss_hex_color_long_format = true
ij_scss_hex_color_lower_case = true
[{*.cjs,*.js}]
indent_style = space
indent_size = 2
ij_javascript_do_while_brace_force = always
ij_javascript_if_brace_force = always
ij_javascript_import_sort_module_name = true
ij_javascript_reformat_c_style_comments = true
ij_javascript_space_after_unary_not = true
ij_javascript_space_before_unary_not = true
ij_javascript_spaces_within_array_initializer_brackets = true
ij_javascript_spaces_within_brackets = true
ij_javascript_spaces_within_catch_parentheses = true
ij_javascript_spaces_within_for_parentheses = true
ij_javascript_spaces_within_if_parentheses = true
ij_javascript_spaces_within_imports = true
ij_javascript_spaces_within_interpolation_expressions = true
ij_javascript_spaces_within_method_call_parentheses = true
ij_javascript_spaces_within_method_parentheses = true
ij_javascript_spaces_within_object_literal_braces = true
ij_javascript_spaces_within_parentheses = true
ij_javascript_spaces_within_switch_parentheses = true
ij_javascript_spaces_within_while_parentheses = true
ij_javascript_while_brace_force = always
[{*.ctp,*.hphp,*.inc,*.module,*.php,*.php4,*.php5,*.phtml}]
ij_php_align_assignments = true
ij_php_align_class_constants = true
ij_php_align_key_value_pairs = true
ij_php_align_phpdoc_comments = true
ij_php_align_phpdoc_param_names = true
ij_php_class_brace_style = end_of_line
ij_php_comma_after_last_array_element = true
ij_php_else_if_style = combine
ij_php_force_short_declaration_array_style = true
ij_php_getters_setters_naming_style = snake_case
ij_php_if_brace_force = always
ij_php_lower_case_boolean_const = true
ij_php_lower_case_null_const = true
ij_php_method_brace_style = end_of_line
ij_php_phpdoc_blank_line_before_tags = true
ij_php_phpdoc_blank_lines_around_parameters = true
ij_php_phpdoc_keep_blank_lines = false
ij_php_phpdoc_wrap_long_lines = true
ij_php_space_after_type_cast = true
ij_php_space_after_unary_not = true
ij_php_space_before_unary_not = true
ij_php_spaces_around_var_within_brackets = true
ij_php_spaces_within_array_initializer_braces = true
ij_php_spaces_within_catch_parentheses = true
ij_php_spaces_within_for_parentheses = true
ij_php_spaces_within_if_parentheses = true
ij_php_spaces_within_method_call_parentheses = true
ij_php_spaces_within_method_parentheses = true
ij_php_spaces_within_parentheses = true
ij_php_spaces_within_switch_parentheses = true
ij_php_spaces_within_while_parentheses = true
ij_php_ternary_operation_signs_on_next_line = true
ij_php_variable_naming_style = snake_case
[{*.htm,*.html,*.ng,*.sht,*.shtm,*.shtml}]
ij_html_add_new_line_before_tags = div,p,a
ij_html_align_attributes = false
ij_html_do_not_indent_children_of_tags = html,thead,tbody,tfoot
ij_html_new_line_after_last_attribute = when multiline
ij_html_space_inside_empty_tag = true
ij_html_uniform_ident = true
.idea
vendor
.phpcs-cache
image: php:latest
cache:
paths:
- vendor
build:
stage: build
script:
- tools/composer install
test:
stage: test
script:
- tools/composer test
<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<phar name="phpstan" version="^1.6.7" installed="1.6.7" location="./tools/phpstan" copy="true"/>
<phar name="phpunit" version="^9.5.20" installed="9.5.20" location="./tools/phpunit" copy="true"/>
<phar name="phpcs" version="^3.6.2" installed="3.6.2" location="./tools/phpcs" copy="true"/>
<phar name="phpcbf" version="^3.6.2" installed="3.6.2" location="./tools/phpcbf" copy="true"/>
<phar name="grumphp" version="^1.12.0" installed="1.12.0" location="./tools/grumphp" copy="true"/>
</phive>
...@@ -15,5 +15,21 @@ ...@@ -15,5 +15,21 @@
"psr-4": { "psr-4": {
"WPDesk\\Migrations\\": "src" "WPDesk\\Migrations\\": "src"
} }
},
"require-dev": {
"szepeviktor/phpstan-wordpress": "^1.1"
},
"scripts": {
"test:phpstan": "./tools/phpstan --configuration=phpstan.neon.dist --memory-limit=-1 analyze",
"test:phpcs": "./tools/phpcs",
"test": [
"@test:phpcs",
"@test:phpstan"
]
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": false
}
} }
} }
This diff is collapsed.
grumphp:
tasks:
phpcs: ~
phpstan: ~
<?xml version="1.0"?>
<ruleset name="WordPress Coding Standards for WP Desk Plugin">
<!--
#############################################################################
COMMAND LINE ARGUMENTS
https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-ruleset.xml
#############################################################################
-->
<config
name="installed_paths"
value="vendor/wp-coding-standards/wpcs,vendor/wpdesk/wp-code-sniffer"/>
<!-- Scan all files. -->
<file>./src</file>
<!-- Only check PHP files. -->
<arg name="extensions" value="php"/>
<!-- Show progress, show the error codes for each message (source). -->
<arg value="sp"/>
<!-- Check up to 8 files simultaneously. -->
<arg name="parallel" value="8"/>
<!-- Cache outcomes for better performance. Remember to add the file to .gitignore. -->
<arg name="cache" value="./.phpcs-cache"/>
<!-- Always exclude all files in version management related directories. -->
<exclude-pattern>*/.git/*</exclude-pattern>
<exclude-pattern>*/.wordpress-svn/*</exclude-pattern>
<!-- Always exclude all files in dependency related directories. -->
<exclude-pattern>*/node_modules/*</exclude-pattern>
<exclude-pattern>*/vendor(_prefixed)?/*</exclude-pattern>
<!-- Always exclude all tests. Differences between PHPUnit, mocking libraries and WPCS make it hard to enforce some CS. -->
<exclude-pattern>*/tests/*</exclude-pattern>
<exclude-pattern>scoper\.inc\.php$</exclude-pattern>
<rule ref="WordPress">
<!-- Follow PSR-4 for autoloading naming convention -->
<exclude name="WordPress.Files.FileName"/>
<!-- WPCS demands long arrays. WPDeskCS demands short arrays. -->
<exclude name="Generic.Arrays.DisallowShortArraySyntax"/>
<!-- Demanding Yoda conditions is stupid. -->
<exclude name="WordPress.PHP.YodaConditions"/>
<!-- The only required comments are for the classes. -->
<exclude name="Squiz.Commenting.FunctionComment"/>
<exclude name="Generic.Commenting.DocComment.MissingShort"/>
<!-- You can use short if-else form. -->
<exclude name="WordPress.PHP.DisallowShortTernary"/>
<!-- If a conscious choice has been made for a non-strict comparison, that's ok.
I.e. when `strict` has been explicitly set to `false` in an array comparison,
it will be allowed. -->
<exclude name="WordPress.PHP.StrictInArray.FoundNonStrictFalse"/>
<exclude name="WordPress.WP.AlternativeFunctions" />
<!-- Sometimes it's better not to use user's timezone. -->
<exclude name="WordPress.DateTime.RestrictedFunctions.date_date" />
</rule>
<!-- Allow slash in hook name. -->
<rule ref="WordPress.NamingConventions.ValidHookName">
<properties>
<property name="additionalWordDelimiters" value="/"/>
</properties>
</rule>
<!-- Template files should have comment with passed variables. -->
<rule ref="Squiz.Commenting.FileComment">
<include-pattern>*/templates/*</include-pattern>
<exclude name="Squiz.Commenting.FileComment.MissingPackageTag"/>
</rule>
<rule ref="WordPress.Arrays.MultipleStatementAlignment">
<type>error</type>
<properties>
<!-- No need to adjust alignment of large arrays when the item with the largest key is removed. -->
<property name="exact" value="false"/>
<!-- Don't align multi-line items if ALL items in the array are multi-line. -->
<property name="alignMultilineItems" value="!=100"/>
<!-- Array Assignment operator should always be on the same line as the array key. -->
<property name="ignoreNewlines" value="false"/>
</properties>
</rule>
<!-- In contrast to WPCS: demand short arrays. -->
<rule ref="Generic.Arrays.DisallowLongArraySyntax"/>
<!-- Check the complexity of code in advance to prevent too complex structures. -->
<rule ref="Generic.Metrics.CyclomaticComplexity">
<properties>
<property name="complexity" value="15"/>
<property name="absoluteComplexity" value="30"/>
</properties>
</rule>
<rule ref="Generic.Metrics.NestingLevel">
<properties>
<property name="nestingLevel" value="6" />
<property name="absoluteNestingLevel" value="10" />
</properties>
</rule>
<!--
#############################################################################
ADD SOME SPECIFIC EXTRA SNIFFS
These may make it into WPCS at some point. If so, they can be removed here.
#############################################################################
-->
<!-- CS: no blank line between the content of a function and a function close brace.-->
<rule ref="PSR2.Methods.FunctionClosingBrace"/>
<!-- CS: ensure exactly one blank line before each property declaration. -->
<rule ref="Squiz.WhiteSpace.MemberVarSpacing"/>
<!-- CS: don't allow "// end class" comments and the likes. -->
<rule ref="PSR12.Classes.ClosingBrace"/>
<!-- CS: enforce consistent indentation of chained object method calls. -->
<rule ref="PEAR.WhiteSpace.ObjectOperatorIndent">
<properties>
<property name="multilevel" value="true"/>
</properties>
</rule>
<!-- Error prevention: Ensure no git conflicts make it into the code base. -->
<!-- PHPCS 3.4.0: This sniff will be added to WPCS in due time and can then be removed from this ruleset.
Related: https://github.com/WordPress/WordPress-Coding-Standards/issues/1500 -->
<rule ref="Generic.VersionControl.GitMergeConflict"/>
<!-- CS: no space between an increment/decrement operator and the variable it applies to. -->
<!-- PHPCS 3.4.0: This sniff will be added to WPCS in due time and can then be removed from this ruleset.
Related: https://github.com/WordPress/WordPress-Coding-Standards/issues/1511 -->
<rule ref="Generic.WhiteSpace.IncrementDecrementSpacing"/>
<!-- QA: Function declarations should not contain parameters which will never be used. -->
<!-- PHPCS 3.4.0: This sniff will be added to WPCS in due time and can then be removed from this ruleset.
Related: https://github.com/WordPress/WordPress-Coding-Standards/issues/1510 -->
<rule ref="Generic.CodeAnalysis.UnusedFunctionParameter.Found"/>
<rule ref="Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed"/>
<!-- CS: Ensure consistent whitespace around spread operators. -->
<!-- PHPCS 3.5.0: This sniff will be added to WPCS in due time and can then be removed from this ruleset.
Related: https://github.com/WordPress/WordPress-Coding-Standards/issues/1762 -->
<rule ref="Generic.WhiteSpace.SpreadOperatorSpacingAfter"/>
<!-- CS: Disallow a leading backslash at the start of an import use statement. -->
<!-- PHPCS 3.5.0: This sniff may be added to WPCS in due time and can then be removed from this ruleset. -->
<rule ref="PSR12.Files.ImportStatement"/>
<!-- CS: Enforces that a PHP open tag is on a line by itself when used at the start of a PHP-only file. -->
<!-- PHPCS 3.5.0: This sniff may be added to WPCS in due time and can then be removed from this ruleset. -->
<rule ref="PSR12.Files.OpenTag"/>
<!-- ##### Documentation Sniffs vs empty index files ##### -->
<!-- Exclude the 'empty' index files from some documentation checks -->
<rule ref="Squiz.Commenting.InlineComment.NoSpaceBefore">
<exclude-pattern>*/index\.php$</exclude-pattern>
</rule>
<rule ref="Squiz.Commenting.FileComment.WrongStyle">
<exclude-pattern>*/index\.php$</exclude-pattern>
</rule>
</ruleset>
includes:
- vendor/szepeviktor/phpstan-wordpress/extension.neon
parameters:
level: max
paths:
- src/
<?php declare(strict_types=1); <?php
declare(strict_types=1);
namespace WPDesk\Migrations; namespace WPDesk\Migrations;
...@@ -6,16 +7,19 @@ use Psr\Log\LoggerInterface; ...@@ -6,16 +7,19 @@ use Psr\Log\LoggerInterface;
abstract class AbstractMigration { abstract class AbstractMigration {
protected $wpdb; /** @var \wpdb */
protected $logger; protected $wpdb;
public function __construct(\wpdb $wpdb, LoggerInterface $logger){ /** @var LoggerInterface */
$this->wpdb = $wpdb; protected $logger;
$this->logger = $logger;
}
abstract public function up(): bool; public function __construct( \wpdb $wpdb, LoggerInterface $logger ) {
$this->wpdb = $wpdb;
$this->logger = $logger;
}
public function down(): void {} abstract public function up(): bool;
} public function down(): void {}
\ No newline at end of file
}
<?php
declare(strict_types=1);
namespace WPDesk\Migrations;
use WPDesk\Migrations\Version\Comparator;
use WPDesk\Migrations\Version\MigrationFactory;
use WPDesk\Migrations\Version\Version;
abstract class AbstractMigrationsRepository implements MigrationsRepository {
/** @var MigrationFactory */
private $version_factory;
/** @var AvailableMigration[] */
protected $migrations = [];
/** @var string[] */
protected $migrations_source;
/** @var Comparator */
private $comparator;
/**
* @param string[] $migrations_source
*/
public function __construct(
array $migrations_source,
MigrationFactory $version_factory,
Comparator $comparator
) {
$this->version_factory = $version_factory;
$this->comparator = $comparator;
$this->migrations_source = $migrations_source;
}
public function register_migration( string $migration_class_name ): void {
$migration = $this->version_factory->create_version( $migration_class_name );
$version = new Version( $migration_class_name );
$this->migrations[ (string) $version ] = new AvailableMigration( $version, $migration );
}
public function get_migrations(): iterable {
$this->load_migrations();
$migrations = $this->migrations;
usort(
$migrations,
function( AvailableMigration $a, AvailableMigration $b ): int {
return $this->comparator->compare( $a->get_version(), $b->get_version() );
}
);
return $migrations;
}
abstract protected function load_migrations(): void;
}
<?php
declare(strict_types=1);
namespace WPDesk\Migrations;
class ArrayMigrationsRepository extends AbstractMigrationsRepository {
protected function load_migrations(): void {
foreach ( $this->migrations_source as $class ) {
$this->register_migration( $class );
}
}
}
<?php declare(strict_types=1); <?php
declare(strict_types=1);
namespace WPDesk\Migrations; namespace WPDesk\Migrations;
...@@ -6,20 +7,23 @@ use WPDesk\Migrations\Version\Version; ...@@ -6,20 +7,23 @@ use WPDesk\Migrations\Version\Version;
class AvailableMigration { class AvailableMigration {
private $version; /** @var Version */
private $migration; private $version;
public function __construct(Version $version, AbstractMigration $migration) { /** @var AbstractMigration */
$this->version = $version; private $migration;
$this->migration = $migration;
}
public function get_version(): Version { public function __construct( Version $version, AbstractMigration $migration ) {
return $this->version; $this->version = $version;
} $this->migration = $migration;
}
public function get_migration(): AbstractMigration { public function get_version(): Version {
return $this->migration; return $this->version;
} }
} public function get_migration(): AbstractMigration {
\ No newline at end of file return $this->migration;
}
}
<?php declare(strict_types=1); <?php
declare(strict_types=1);
namespace WPDesk\Migrations; namespace WPDesk\Migrations;
use WPDesk\Migrations\Finder\MigrationFinder; use WPDesk\Migrations\Finder\MigrationFinder;
use WPDesk\Migrations\Version\Comparator;
use WPDesk\Migrations\Version\MigrationFactory; use WPDesk\Migrations\Version\MigrationFactory;
use WPDesk\Migrations\Version\Version;
class FilesystemMigrationsRepository implements MigrationsRepository { final class FilesystemMigrationsRepository extends AbstractMigrationsRepository {
private $migrations_loaded = false; /** @var bool */
private $migrations_loaded = false;
private $migration_directories;
/** @var MigrationFinder */
private $migration_finder; private $migration_finder;
private $version_factory; /**
* @param string[] $migration_directories
private $migrations = []; */
public function __construct(
public function __construct( array $migration_directories,
array $migration_directories, MigrationFinder $migration_finder,
MigrationFinder $migration_finder, MigrationFactory $version_factory,
MigrationFactory $version_factory Comparator $comparator
) { ) {
$this->migration_directories = $migration_directories; parent::__construct( $migration_directories, $version_factory, $comparator );
$this->migration_finder = $migration_finder; $this->migration_finder = $migration_finder;
$this->version_factory = $version_factory; }
}
/** @param string[] $migrations */
public function register_migration(string $migration_class_name) { private function register_migrations( array $migrations ): void {
$migration = $this->version_factory->create_version($migration_class_name); foreach ( $migrations as $migration ) {
$version = new Version($migration_class_name); $this->register_migration( $migration );
}
$this->migrations[(string) $version] = new AvailableMigration($version, $migration); }
}
protected function load_migrations(): void {
private function register_migrations(array $migrations){ if ( $this->migrations_loaded ) {
foreach ($migrations as $migration) { return;
$this->register_migration($migration); }
}
} $this->migrations_loaded = true;
public function get_migrations(): iterable { foreach ( $this->migrations_source as $directory ) {
$this->load_migrations(); $migrations = $this->migration_finder->find_migrations( $directory );
$this->register_migrations( $migrations );
return $this->migrations; }
} }
}
private function load_migrations(): void {
if ($this->migrations_loaded) {
return;
}
$this->migrations_loaded = true;
foreach ($this->migration_directories as $directory) {
$migrations = $this->migration_finder->find_migrations($directory);
$this->register_migrations($migrations);
}
}
}
\ No newline at end of file
<?php declare(strict_types=1); <?php
declare(strict_types=1);
namespace WPDesk\Migrations\Finder; namespace WPDesk\Migrations\Finder;
use WPDesk\Migrations\Migration; use WPDesk\Migrations\AbstractMigration;
final class GlobFinder implements MigrationFinder { final class GlobFinder implements MigrationFinder {
/** public function find_migrations( string $directory ): array {
* @param string $directory $dir = realpath( $directory );
* @return class-string<Migration>[]
*/ $files = glob( rtrim( $dir, '/' ) . '/Version*.php' );
public function find_migrations(string $directory): array { if ( $files === false ) {
$dir = realpath($directory); $files = [];
}
$files = glob(rtrim($dir, '/') . '/Version*.php');
if ($files === false) { return $this->load_migrations( $files );
$files = []; }
}
/**
return $this->load_migrations($files); * @param string[] $files
} *
* @return class-string<AbstractMigration>[]
private function load_migrations(array $files): array { * @throws \ReflectionException
$included_files = []; */
foreach ($files as $file) { private function load_migrations( array $files ): array {
require_once $file; $included_files = [];
$real_file = realpath($file); foreach ( $files as $file ) {
$included_files[] = $real_file; require_once $file;
} $real_file = realpath( $file );
if ( ! $real_file ) {
$classes = $this->load_migration_classes($included_files); continue;
$versions = []; }
foreach ($classes as $class) { $included_files[] = $real_file;
$versions[] = $class->getName(); }
}
$classes = $this->load_migration_classes( $included_files );
return $versions; $versions = [];
} foreach ( $classes as $class ) {
$versions[] = $class->getName();
/** }
* @param array $included_files
* @return \ReflectionClass[] return $versions;
* @throws \ReflectionException }
*/
private function load_migration_classes(array $included_files): array { /**
$classes = []; * @param string[] $included_files
foreach (get_declared_classes() as $class) { * @return \ReflectionClass[]
$r = new \ReflectionClass($class); * @throws \ReflectionException
*/
if (in_array($r->getFileName(), $included_files, true)) { private function load_migration_classes( array $included_files ): array {
$classes[] = $r; $classes = [];
} foreach ( get_declared_classes() as $class ) {
} $r = new \ReflectionClass( $class );
return $classes;
} if ( in_array( $r->getFileName(), $included_files, true ) ) {
} $classes[] = $r;
\ No newline at end of file }
}
return $classes;
}
}
<?php declare(strict_types=1); <?php
declare(strict_types=1);
namespace WPDesk\Migrations\Finder; namespace WPDesk\Migrations\Finder;
use WPDesk\Migrations\Migration; use WPDesk\Migrations\AbstractMigration;
interface MigrationFinder { interface MigrationFinder {
/** /**
* @param string $directory * @param string $directory
* @return class-string<Migration>[] * @return class-string<AbstractMigration>[]
*/ */
public function find_migrations(string $directory): array; public function find_migrations( string $directory): array;
} }
\ No newline at end of file
<?php declare(strict_types=1);
namespace WPDesk\Migrations;
interface Migration {
public function up( \wpdb $wpdb ): bool;
}
...@@ -2,8 +2,12 @@ ...@@ -2,8 +2,12 @@
namespace WPDesk\Migrations; namespace WPDesk\Migrations;
interface MigrationsRepository use WPDesk\Migrations\Version\Version;
{
/** @return iterable<AvailableMigration> */ interface MigrationsRepository {
public function get_migrations(): iterable;
} /** @return iterable<AvailableMigration> */
\ No newline at end of file public function get_migrations(): iterable;
public function register_migration( string $migration_class_name ): void;
}
<?php declare(strict_types=1); <?php
declare(strict_types=1);
namespace WPDesk\Migrations; namespace WPDesk\Migrations;
interface Migrator { interface Migrator {
public function migrate(): void; public function migrate(): void;
} }
\ No newline at end of file
<?php declare(strict_types=1); <?php
declare(strict_types=1);
namespace WPDesk\Migrations\Version; namespace WPDesk\Migrations\Version;
class AlphabeticalComparator implements Comparator { class AlphabeticalComparator implements Comparator {
public function compare(Version $a, Version $b): int { public function compare( Version $a, Version $b ): int {
return strcmp((string) $a, (string) $b); return strcmp( (string) $a, (string) $b );
} }
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment