From cc72373e3dd1103efd68fbbc42b2aff0c5f1ad66 Mon Sep 17 00:00:00 2001 From: Hugo Sales Date: Sun, 15 Mar 2020 21:21:11 +0000 Subject: [PATCH] [DOCTRINE][SCHEMADEF] Create a new metadata driver to allow us to continue using static schemaDef functions This has the benefit of requiring fewer code changes, as well as providing a better isolation between GNU social and symfony, useful in case the framework needs to be changed --- .gitignore | 5 + .php_cs | 270 ++++++++++++++++++ bin/pre-commit | 24 ++ composer.json | 4 +- composer.lock | 253 +++++++++++++++- config/bootstrap.php | 10 +- config/bundles.php | 20 +- config/packages/doctrine.yaml | 20 +- config/packages/framework.yaml | 2 +- config/routes.php | 4 +- config/services.yaml | 8 +- public/index.php | 8 +- src/Controller/NetworkPublic.php | 5 +- .../Compiler/SchemaDefCompilerPass.php | 23 ++ src/Entity/User.php | 60 ++++ src/Kernel.php | 34 ++- src/Util/Common.php | 26 +- src/Util/GNUsocial.php | 47 ++- src/Util/GSEvent.php | 36 +-- src/Util/I18n.php | 74 ++--- src/Util/Log.php | 4 + src/Util/SchemaDefDriver.php | 15 + symfony.lock | 21 ++ tests/bootstrap.php | 10 +- 24 files changed, 835 insertions(+), 148 deletions(-) create mode 100644 .php_cs create mode 100755 bin/pre-commit create mode 100644 src/DependencyInjection/Compiler/SchemaDefCompilerPass.php create mode 100644 src/Entity/User.php create mode 100644 src/Util/SchemaDefDriver.php diff --git a/.gitignore b/.gitignore index eaa3cd32e2..b9ce883dc4 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,8 @@ .phpunit.result.cache /phpunit.xml ###< symfony/phpunit-bridge ### + +###> friendsofphp/php-cs-fixer ### +!.php_cs +/.php_cs.cache +###< friendsofphp/php-cs-fixer ### diff --git a/.php_cs b/.php_cs new file mode 100644 index 0000000000..822d6b4d87 --- /dev/null +++ b/.php_cs @@ -0,0 +1,270 @@ +setRiskyAllowed(true) + ->setRules([ + // Each line of multi-line DocComments must have an asterisk [PSR-5] and must be aligned with the first one. + 'align_multiline_comment' => ['comment_type' => 'phpdocs_like'], + // PHP arrays should be declared using the configured syntax. + 'array_syntax' => ['syntax' => 'short'], + // Binary operators should be surrounded by space as configured. + 'binary_operator_spaces' => ['default' => 'align_single_space_minimal'], + // There MUST be one blank line after the namespace declaration. + 'blank_line_after_namespace' => true, + // Each element of an array must be indented exactly once. + 'array_indentation' => true, + // Ensure there is no code on the same line as the PHP open tag and it is followed by a blank line. + 'blank_line_after_opening_tag' => true, + // The body of each structure MUST be enclosed by braces. Braces should be properly placed. Body of braces should be properly indented. + 'braces' => ['allow_single_line_closure' => true, 'position_after_functions_and_oop_constructs' => 'next'], + // A single space or none should be between cast and variable. + 'cast_spaces' => true, + // Class, trait and interface elements must be separated with one blank line. + 'class_attributes_separation' => true, + // Whitespace around the keywords of a class, trait or interfaces definition should be one space. + 'class_definition' => ['single_item_single_line' => true, 'single_line' => true], + // Using `isset($var) &&` multiple times should be done in one call. + 'combine_consecutive_issets' => true, + // Calling `unset` on multiple items should be done in one call. + 'combine_consecutive_unsets' => true, + // Remove extra spaces in a nullable typehint. + 'compact_nullable_typehint' => true, + // Concatenation should be spaced according configuration. + 'concat_space' => ['spacing' => 'one'], + // The PHP constants `true`, `false`, and `null` MUST be written using the correct casing. + 'constant_case' => true, + // Equal sign in declare statement should be surrounded by spaces or not following configuration. + 'declare_equal_normalize' => ['space' => 'single'], + // Replaces `dirname(__FILE__)` expression with equivalent `__DIR__` constant. + 'dir_constant' => true, + // PHP code MUST use only UTF-8 without BOM (remove BOM). + 'encoding' => true, + // Replace deprecated `ereg` regular expression functions with `preg`. + 'ereg_to_preg' => true, + // Escape implicit backslashes in strings and heredocs to ease the understanding of which are special chars interpreted by PHP and which not. + 'escape_implicit_backslashes' => true, + // Add curly braces to indirect variables to make them clear to understand. Requires PHP >= 7.0. + 'explicit_indirect_variable' => true, + // Converts implicit variables into explicit ones in double-quoted strings or heredoc syntax. + 'explicit_string_variable' => true, + // PHP code must use the long ` true, + // Transforms imported FQCN parameters and return types in function arguments to short version. + 'fully_qualified_strict_types' => true, + // Spaces should be properly placed in a function declaration. + 'function_declaration' => ['closure_function_spacing' => 'one'], + // Ensure single space between function's argument and its typehint. + 'function_typehint_space' => true, + // Pre- or post-increment and decrement operators should be used if possible. + 'increment_style' => true, + // Code MUST use configured indentation type. + 'indentation_type' => true, + // All PHP files must use same line ending. + 'line_ending' => true, + // Use `&&` and `||` logical operators instead of `and` and `or`. + 'logical_operators' => true, + // PHP keywords MUST be in lower case. + 'lowercase_keywords' => true, + // Class static references `self`, `static` and `parent` MUST be in lower case. + 'lowercase_static_reference' => true, + // Magic constants should be referred to using the correct casing. + 'magic_constant_casing' => true, + // Magic method definitions and calls must be using the correct casing. + 'magic_method_casing' => true, + // Replaces `intval`, `floatval`, `doubleval`, `strval` and `boolval` function calls with according type casting operator. + 'modernize_types_casting' => true, + // DocBlocks must start with two asterisks, multiline comments must start with a single asterisk, after the opening slash. Both must end with a single asterisk before the closing slash. + 'multiline_comment_opening_closing' => true, + // Forbid multi-line whitespace before the closing semicolon or move the semicolon to the new line for chained calls. + 'multiline_whitespace_before_semicolons' => true, + // Add leading `\` before constant invocation of internal constant to speed up resolving. Constant name match is case-sensitive, except for `null`, `false` and `true`. + 'native_constant_invocation' => false, + // Function defined by PHP should be called using the correct casing. + 'native_function_casing' => true, + // Add leading `\` before function invocation to speed up resolving. + 'native_function_invocation' => false, + // Native type hints for functions should use the correct case. + 'native_function_type_declaration_casing' => true, + // There should be no empty lines after class opening brace. + 'no_blank_lines_after_class_opening' => true, + // There should not be blank lines between docblock and the documented element. + 'no_blank_lines_after_phpdoc' => true, + // There must be a comment when fall-through is intentional in a non-empty case body. + 'no_break_comment' => true, + // The closing `? >` tag MUST be omitted from files containing only PHP. + 'no_closing_tag' => true, + // There should not be any empty comments. + 'no_empty_comment' => true, + // There should not be empty PHPDoc blocks. + 'no_empty_phpdoc' => true, + // Remove useless semicolon statements. + 'no_empty_statement' => true, + // Removes extra blank lines and/or blank lines following configuration. + 'no_extra_blank_lines' => true, + // Remove leading slashes in `use` clauses. + 'no_leading_import_slash' => true, + // The namespace declaration line shouldn't contain leading whitespace. + 'no_leading_namespace_whitespace' => true, + // Either language construct `print` or `echo` should be used. + 'no_mixed_echo_print' => true, + // Operator `=>` should not be surrounded by multi-line whitespaces. + 'no_multiline_whitespace_around_double_arrow' => true, + // Properties MUST not be explicitly initialized with `null` except when they have a type declaration (PHP 7.4). + 'no_null_property_initialization' => true, + // Short cast `bool` using double exclamation mark should not be used. + 'no_short_bool_cast' => true, + // Replace short-echo ` true, + // Single-line whitespace before closing semicolon are prohibited. + 'no_singleline_whitespace_before_semicolons' => true, + // When making a method or function call, there MUST NOT be a space between the method or function name and the opening parenthesis. + 'no_spaces_after_function_name' => true, + // There MUST NOT be spaces around offset braces. + 'no_spaces_around_offset' => true, + // There MUST NOT be a space after the opening parenthesis. There MUST NOT be a space before the closing parenthesis. + 'no_spaces_inside_parenthesis' => true, + // Replaces superfluous `elseif` with `if`. + 'no_superfluous_elseif' => true, + // Remove trailing commas in list function calls. + 'no_trailing_comma_in_list_call' => true, + // PHP single-line arrays should not have trailing comma. + 'no_trailing_comma_in_singleline_array' => true, + // Remove trailing whitespace at the end of non-blank lines. + 'no_trailing_whitespace' => true, + // There MUST be no trailing spaces inside comment or PHPDoc. + 'no_trailing_whitespace_in_comment' => true, + // Removes unneeded parentheses around control statements. + 'no_unneeded_control_parentheses' => true, + // Removes unneeded curly braces that are superfluous and aren't part of a control structure's body. + 'no_unneeded_curly_braces' => true, + // In function arguments there must not be arguments with default values before non-default ones. + 'no_unreachable_default_argument_value' => true, + // Variables must be set `null` instead of using `(unset)` casting. + 'no_unset_cast' => true, + // Properties should be set to `null` instead of using `unset`. + 'no_unset_on_property' => true, + // Unused `use` statements must be removed. + 'no_unused_imports' => true, + // There should not be useless `else` cases. + 'no_useless_else' => true, + // There should not be an empty `return` statement at the end of a function. + 'no_useless_return' => true, + // In array declaration, there MUST NOT be a whitespace before each comma. + 'no_whitespace_before_comma_in_array' => true, + // Remove trailing whitespace at the end of blank lines. + 'no_whitespace_in_blank_line' => true, + // Remove Zero-width space (ZWSP), Non-breaking space (NBSP) and other invisible unicode symbols. + 'non_printable_character' => true, + // Array index should always be written by using square braces. + 'normalize_index_brace' => true, + // There should not be space before or after object `T_OBJECT_OPERATOR` `->`. + 'object_operator_without_whitespace' => true, + // Ordering `use` statements. + 'ordered_imports' => true, + // Orders the elements of classes/interfaces/traits. + 'ordered_class_elements' => true, + // PHPUnit assertion method calls like `->assertSame(true, $foo)` should be written with dedicated method like `->assertTrue($foo)`. + 'php_unit_construct' => true, + // PHPUnit annotations should be a FQCNs including a root namespace. + 'php_unit_fqcn_annotation' => true, + // Enforce camel (or snake) case for PHPUnit test methods, following configuration. + 'php_unit_method_casing' => true, + // Usage of PHPUnit's mock e.g. `->will($this->returnValue(..))` must be replaced by its shorter equivalent such as `->willReturn(...)`. + 'php_unit_mock_short_will_return' => true, + // Order `@covers` annotation of PHPUnit tests. + 'php_unit_ordered_covers' => true, + // Changes the visibility of the `setUp()` and `tearDown()` functions of PHPUnit to `protected`, to match the PHPUnit TestCase. + 'php_unit_set_up_tear_down_visibility' => true, + // PHPUnit methods like `assertSame` should be used instead of `assertEquals`. + 'php_unit_strict' => true, + // Calls to `PHPUnit\Framework\TestCase` static methods must all be of the same type, either `$this->`, `self::` or `static::`. + 'php_unit_test_case_static_method_calls' => true, + // PHPDoc should contain `@param` for all params. + 'phpdoc_add_missing_param_annotation' => true, + // All items of the given phpdoc tags must be either left-aligned or (by default) aligned vertically. + 'phpdoc_align' => true, + // Docblocks should have the same indentation as the documented subject. + 'phpdoc_indent' => true, + // Fix PHPDoc inline tags, make `@inheritdoc` always inline. + 'phpdoc_inline_tag' => true, + // `@access` annotations should be omitted from PHPDoc. + 'phpdoc_no_access' => true, + // No alias PHPDoc tags should be used. + 'phpdoc_no_alias_tag' => true, + // Annotations in PHPDoc should be ordered so that `@param` annotations come first, then `@throws` annotations, then `@return` annotations. + 'phpdoc_order' => true, + // The type of `@return` annotations of methods returning a reference to itself must the configured one. + 'phpdoc_return_self_reference' => true, + // Scalar types should always be written in the same form. `int` not `integer`, `bool` not `boolean`, `float` not `real` or `double`. + 'phpdoc_scalar' => true, + // Annotations in PHPDoc should be grouped together so that annotations of the same type immediately follow each other, and annotations of a different type are separated by a single blank line. + 'phpdoc_separation' => true, + // Single line `@var` PHPDoc should have proper spacing. + 'phpdoc_single_line_var_spacing' => true, + // Removes extra blank lines after summary and after description in PHPDoc. + 'phpdoc_trim_consecutive_blank_line_separation' => true, + // The correct case must be used for standard PHP types in PHPDoc. + 'phpdoc_types' => true, + // Sorts PHPDoc types. + 'phpdoc_types_order' => true, + // `@var` and `@type` annotations must have type and name in the correct order. + 'phpdoc_var_annotation_correct_order' => true, + // Class names should match the file name. + 'psr4' => true, + // There should be one or no space before colon, and one space after it in return type declarations, according to configuration. + 'return_type_declaration' => true, + // Inside class or interface element `self` should be preferred to the class name itself. + 'self_accessor' => true, + // Instructions must be terminated with a semicolon. + 'semicolon_after_instruction' => true, + // Cast shall be used, not `settype`. + 'set_type_to_cast' => true, + // Cast `(boolean)` and `(integer)` should be written as `(bool)` and `(int)`, `(double)` and `(real)` as `(float)`, `(binary)` as `(string)`. + 'short_scalar_cast' => true, + // Converts explicit variables in double-quoted strings and heredoc syntax from simple to complex format (`${` to `{$`). + 'simple_to_complex_string_variable' => true, + // There should be exactly one blank line before a namespace declaration. + 'single_blank_line_before_namespace' => true, + // There MUST be one use keyword per declaration. + 'single_import_per_statement' => true, + // There MUST NOT be more than one property or constant declared per statement. + 'single_class_element_per_statement' => true, + // Each namespace use MUST go on its own line and there MUST be one blank line after the use statements block. + 'single_line_after_imports' => true, + // Single-line comments and multi-line comments with only one line of actual content should use the `//` syntax. + 'single_line_comment_style' => true, + // Convert double quotes to single quotes for simple strings. + 'single_quote' => true, + // Each trait `use` must be done as single statement. + 'single_trait_insert_per_statement' => true, + // Fix whitespace after a semicolon. + 'space_after_semicolon' => true, + // Increment and decrement operators should be used if possible. + 'standardize_increment' => true, + // Replace all `<>` with `!=`. + 'standardize_not_equals' => true, + // A case should be followed by a colon and not a semicolon. + 'switch_case_semicolon_to_colon' => true, + // Removes extra spaces between colon and case value. + 'switch_case_space' => true, + // Standardize spaces around ternary operator. + 'ternary_operator_spaces' => true, + // PHP multi-line arrays should have a trailing comma. + 'trailing_comma_in_multiline_array' => true, + // Unary operators should be placed adjacent to their operands. + 'unary_operator_spaces' => true, + // Visibility MUST be declared on all properties and methods; `abstract` and `final` MUST be declared before the visibility; `static` MUST be declared after the visibility. + 'visibility_required' => true, + // In array declaration, there MUST be a whitespace after each comma. + 'whitespace_after_comma_in_array' => true, + ]) + ->setFinder(PhpCsFixer\Finder::create() + ->exclude('vendor') + ->exclude('var') + ->in(__DIR__) + ); diff --git a/bin/pre-commit b/bin/pre-commit new file mode 100755 index 0000000000..704de44dad --- /dev/null +++ b/bin/pre-commit @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# get the list of changed files +staged_files=$(git diff --cached --name-only) + +# build command to fix files +cmd="$(git rev-parse --show-toplevel)/vendor/bin/php-cs-fixer" + +echo "Running php-cs-fixer on edited files" + +for staged in ${staged_files}; do + # work only with existing files + if [[ -f ${staged} && ${staged} == *.php ]]; then + # use php-cs-fixer and get flag of correction + "${cmd}" -q fix "${staged}" + + # if php-cs-fixer fix works, it returns 0 + if [[ $? -eq 0 ]]; then + git add "${staged}" # execute git add directly + fi + fi +done + +exit 0 # do commit diff --git a/composer.json b/composer.json index d398f2457c..91a5275f38 100644 --- a/composer.json +++ b/composer.json @@ -33,6 +33,7 @@ "symfony/yaml": "5.0.*" }, "require-dev": { + "friendsofphp/php-cs-fixer": "^2.16", "symfony/debug-pack": "*", "symfony/maker-bundle": "^1.14", "symfony/profiler-pack": "*", @@ -69,7 +70,8 @@ "assets:install %PUBLIC_DIR%": "symfony-cmd" }, "post-install-cmd": [ - "@auto-scripts" + "@auto-scripts", + "cp bin/pre-commit .git/hooks" ], "post-update-cmd": [ "@auto-scripts" diff --git a/composer.lock b/composer.lock index 23dd34da02..8191bbf369 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b541aad7b6660bdcba29f51d2f3e6163", + "content-hash": "29d2cd792b5bb1a62925c27414e0a448", "packages": [ { "name": "doctrine/annotations", @@ -6172,6 +6172,117 @@ } ], "packages-dev": [ + { + "name": "composer/semver", + "version": "1.5.1", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "c6bea70230ef4dd483e6bbcab6005f682ed3a8de" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/c6bea70230ef4dd483e6bbcab6005f682ed3a8de", + "reference": "c6bea70230ef4dd483e6bbcab6005f682ed3a8de", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.5 || ^5.0.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "time": "2020-01-13T12:06:48+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "1ab9842d69e64fb3a01be6b656501032d1b78cb7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/1ab9842d69e64fb3a01be6b656501032d1b78cb7", + "reference": "1ab9842d69e64fb3a01be6b656501032d1b78cb7", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0", + "psr/log": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + } + ], + "time": "2020-03-01T12:26:26+00:00" + }, { "name": "easycorp/easy-log-handler", "version": "v1.0.9", @@ -6222,6 +6333,95 @@ ], "time": "2019-10-24T07:13:31+00:00" }, + { + "name": "friendsofphp/php-cs-fixer", + "version": "v2.16.1", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", + "reference": "c8afb599858876e95e8ebfcd97812d383fa23f02" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/c8afb599858876e95e8ebfcd97812d383fa23f02", + "reference": "c8afb599858876e95e8ebfcd97812d383fa23f02", + "shasum": "" + }, + "require": { + "composer/semver": "^1.4", + "composer/xdebug-handler": "^1.2", + "doctrine/annotations": "^1.2", + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^5.6 || ^7.0", + "php-cs-fixer/diff": "^1.3", + "symfony/console": "^3.4.17 || ^4.1.6 || ^5.0", + "symfony/event-dispatcher": "^3.0 || ^4.0 || ^5.0", + "symfony/filesystem": "^3.0 || ^4.0 || ^5.0", + "symfony/finder": "^3.0 || ^4.0 || ^5.0", + "symfony/options-resolver": "^3.0 || ^4.0 || ^5.0", + "symfony/polyfill-php70": "^1.0", + "symfony/polyfill-php72": "^1.4", + "symfony/process": "^3.0 || ^4.0 || ^5.0", + "symfony/stopwatch": "^3.0 || ^4.0 || ^5.0" + }, + "require-dev": { + "johnkary/phpunit-speedtrap": "^1.1 || ^2.0 || ^3.0", + "justinrainbow/json-schema": "^5.0", + "keradus/cli-executor": "^1.2", + "mikey179/vfsstream": "^1.6", + "php-coveralls/php-coveralls": "^2.1", + "php-cs-fixer/accessible-object": "^1.0", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.1", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.1", + "phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.1", + "phpunitgoodpractices/traits": "^1.8", + "symfony/phpunit-bridge": "^4.3 || ^5.0", + "symfony/yaml": "^3.0 || ^4.0 || ^5.0" + }, + "suggest": { + "ext-mbstring": "For handling non-UTF8 characters in cache signature.", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "For IsIdenticalString constraint.", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "For XmlMatchesXsd constraint.", + "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." + }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", + "autoload": { + "psr-4": { + "PhpCsFixer\\": "src/" + }, + "classmap": [ + "tests/Test/AbstractFixerTestCase.php", + "tests/Test/AbstractIntegrationCaseFactory.php", + "tests/Test/AbstractIntegrationTestCase.php", + "tests/Test/Assert/AssertTokensTrait.php", + "tests/Test/IntegrationCase.php", + "tests/Test/IntegrationCaseFactory.php", + "tests/Test/IntegrationCaseFactoryInterface.php", + "tests/Test/InternalIntegrationCaseFactory.php", + "tests/TestCase.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Dariusz RumiƄski", + "email": "dariusz.ruminski@gmail.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "time": "2019-11-25T22:10:32+00:00" + }, { "name": "nikic/php-parser", "version": "v4.3.0", @@ -6274,6 +6474,57 @@ ], "time": "2019-11-08T13:50:10+00:00" }, + { + "name": "php-cs-fixer/diff", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/diff.git", + "reference": "78bb099e9c16361126c86ce82ec4405ebab8e756" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/78bb099e9c16361126c86ce82ec4405ebab8e756", + "reference": "78bb099e9c16361126c86ce82ec4405ebab8e756", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7.23 || ^6.4.3", + "symfony/process": "^3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "SpacePossum" + } + ], + "description": "sebastian/diff v2 backport support for PHP5.6", + "homepage": "https://github.com/PHP-CS-Fixer", + "keywords": [ + "diff" + ], + "time": "2018-02-15T16:58:55+00:00" + }, { "name": "symfony/browser-kit", "version": "v5.0.5", diff --git a/config/bootstrap.php b/config/bootstrap.php index 3164fd1c60..85691ad51e 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -2,22 +2,22 @@ use Symfony\Component\Dotenv\Dotenv; -require dirname(__DIR__).'/vendor/autoload.php'; +require dirname(__DIR__) . '/vendor/autoload.php'; // Load cached env vars if the .env.local.php file exists // Run "composer dump-env prod" to create it (requires symfony/flex >=1.2) -if (is_array($env = @include dirname(__DIR__).'/.env.local.php') && (!isset($env['APP_ENV']) || ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? $env['APP_ENV']) === $env['APP_ENV'])) { +if (\is_array($env = @include dirname(__DIR__) . '/.env.local.php') && (!isset($env['APP_ENV']) || ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? $env['APP_ENV']) === $env['APP_ENV'])) { foreach ($env as $k => $v) { $_ENV[$k] = $_ENV[$k] ?? (isset($_SERVER[$k]) && 0 !== strpos($k, 'HTTP_') ? $_SERVER[$k] : $v); } -} elseif (!class_exists(Dotenv::class)) { +} elseif (!\class_exists(Dotenv::class)) { throw new RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.'); } else { // load all the .env files - (new Dotenv(false))->loadEnv(dirname(__DIR__).'/.env'); + (new Dotenv(false))->loadEnv(\dirname(__DIR__) . '/.env'); } $_SERVER += $_ENV; -$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev'; +$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev'; $_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV']; $_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0'; diff --git a/config/bundles.php b/config/bundles.php index 320079751f..a00a55707d 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -1,15 +1,15 @@ ['all' => true], - Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], - Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true], - Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], - Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], - Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true], + Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true], + Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], + Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true], + Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], + Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], + Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true], Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true], - Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], - Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], - Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], - Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], + Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], + Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], + Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], + Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], ]; diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml index 5e80e77b16..3a24482e61 100644 --- a/config/packages/doctrine.yaml +++ b/config/packages/doctrine.yaml @@ -1,18 +1,16 @@ doctrine: dbal: + # TODO In case of special URL characters, this needs to be handled differently url: '%env(resolve:DATABASE_URL)%' - - # IMPORTANT: You MUST configure your server version, - # either here or in the DATABASE_URL env var (see .env file) - #server_version: '5.7' orm: auto_generate_proxy_classes: true naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware auto_mapping: true - mappings: - App: - is_bundle: false - type: annotation - dir: '%kernel.project_dir%/src/Entity' - prefix: 'App\Entity' - alias: App + # Defined in the compiler pass to use SchemaDefDriver + # mappings: + # App: + # is_bundle: false + # type: staticphp + # dir: '%kernel.project_dir%/src/Entity' + # prefix: 'App\Entity' + # alias: App diff --git a/config/packages/framework.yaml b/config/packages/framework.yaml index 6089f4bd0d..882841ba21 100644 --- a/config/packages/framework.yaml +++ b/config/packages/framework.yaml @@ -1,6 +1,6 @@ framework: secret: '%env(APP_SECRET)%' - #csrf_protection: true + csrf_protection: true #http_method_override: true # Enables session support. Note that the session will ONLY be started if you read or write from it. diff --git a/config/routes.php b/config/routes.php index 0964a08f81..539dfced56 100644 --- a/config/routes.php +++ b/config/routes.php @@ -1,9 +1,9 @@ add('network.public', '/main/all') ->controller(NetworkPublic::class); diff --git a/config/services.yaml b/config/services.yaml index fed3db4a75..2d483616e2 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -15,7 +15,7 @@ services: # this creates a service per class whose id is the fully-qualified class name App\: resource: '../src/*' - exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php,lib/*}' + exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}' # controllers are imported separately to make sure services can be injected # as action arguments even if you don't extend any base controller class @@ -25,3 +25,9 @@ services: # add more service definitions when explicit configuration is needed # please note that last definitions always *replace* previous ones + + # Wrapper arround Doctrine's StaticPHP metadata driver + app.util.schemadef_driver: + class: App\Util\SchemaDefDriver + arguments: + - '%kernel.project_dir%/src/Entity' diff --git a/public/index.php b/public/index.php index f094a9b193..87ce437308 100755 --- a/public/index.php +++ b/public/index.php @@ -4,7 +4,7 @@ use App\Kernel; use Symfony\Component\ErrorHandler\Debug; use Symfony\Component\HttpFoundation\Request; -require dirname(__DIR__).'/config/bootstrap.php'; +require dirname(__DIR__) . '/config/bootstrap.php'; if ($_SERVER['APP_DEBUG']) { umask(0000); @@ -13,15 +13,15 @@ if ($_SERVER['APP_DEBUG']) { } if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? $_ENV['TRUSTED_PROXIES'] ?? false) { - Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST); + Request::setTrustedProxies(\explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST); } if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? $_ENV['TRUSTED_HOSTS'] ?? false) { Request::setTrustedHosts([$trustedHosts]); } -$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']); -$request = Request::createFromGlobals(); +$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']); +$request = Request::createFromGlobals(); $response = $kernel->handle($request); $response->send(); $kernel->terminate($request, $response); diff --git a/src/Controller/NetworkPublic.php b/src/Controller/NetworkPublic.php index 97ac7bd4a7..0a58b5d48d 100644 --- a/src/Controller/NetworkPublic.php +++ b/src/Controller/NetworkPublic.php @@ -2,11 +2,10 @@ namespace App\Controller; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; - use App\Util\GSEvent; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; + class NetworkPublic extends AbstractController { public function __invoke() diff --git a/src/DependencyInjection/Compiler/SchemaDefCompilerPass.php b/src/DependencyInjection/Compiler/SchemaDefCompilerPass.php new file mode 100644 index 0000000000..1f6cfb4b86 --- /dev/null +++ b/src/DependencyInjection/Compiler/SchemaDefCompilerPass.php @@ -0,0 +1,23 @@ +findDefinition('doctrine.orm.default_metadata_driver') + ->addMethodCall('addDriver', + [new Reference('app.util.schemadef_driver'), 'App\\Entity'] + ); + + $container->setParameter('doctrine.orm.metadata.schemadef.class', App\Util\SchemaDefDriver::class); + } +} diff --git a/src/Entity/User.php b/src/Entity/User.php new file mode 100644 index 0000000000..f74ff1b53e --- /dev/null +++ b/src/Entity/User.php @@ -0,0 +1,60 @@ + 'local users', + 'fields' => [ + 'id' => ['type' => 'int', 'not null' => true, 'description' => 'foreign key to profile table'], + 'nickname' => ['type' => 'varchar', 'length' => 64, 'description' => 'nickname or username, duped in profile'], + 'password' => ['type' => 'varchar', 'length' => 191, 'description' => 'salted password, can be null for OpenID users'], + 'email' => ['type' => 'varchar', 'length' => 191, 'description' => 'email address for password recovery etc.'], + 'incomingemail' => ['type' => 'varchar', 'length' => 191, 'description' => 'email address for post-by-email'], + 'emailnotifysub' => ['type' => 'bool', 'default' => true, 'description' => 'Notify by email of subscriptions'], + 'emailnotifyfav' => ['type' => 'int', 'size' => 'tiny', 'default' => null, 'description' => 'Notify by email of favorites'], + 'emailnotifynudge' => ['type' => 'bool', 'default' => true, 'description' => 'Notify by email of nudges'], + 'emailnotifymsg' => ['type' => 'bool', 'default' => true, 'description' => 'Notify by email of direct messages'], + 'emailnotifyattn' => ['type' => 'bool', 'default' => true, 'description' => 'Notify by email of @-replies'], + 'language' => ['type' => 'varchar', 'length' => 50, 'description' => 'preferred language'], + 'timezone' => ['type' => 'varchar', 'length' => 50, 'description' => 'timezone'], + 'emailpost' => ['type' => 'bool', 'default' => true, 'description' => 'Post by email'], + 'sms' => ['type' => 'varchar', 'length' => 64, 'description' => 'sms phone number'], + 'carrier' => ['type' => 'int', 'description' => 'foreign key to sms_carrier'], + 'smsnotify' => ['type' => 'bool', 'default' => false, 'description' => 'whether to send notices to SMS'], + 'smsreplies' => ['type' => 'bool', 'default' => false, 'description' => 'whether to send notices to SMS on replies'], + 'smsemail' => ['type' => 'varchar', 'length' => 191, 'description' => 'built from sms and carrier'], + 'uri' => ['type' => 'varchar', 'length' => 191, 'description' => 'universally unique identifier, usually a tag URI'], + 'autosubscribe' => ['type' => 'bool', 'default' => false, 'description' => 'automatically subscribe to users who subscribe to us'], + 'subscribe_policy' => ['type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => '0 = anybody can subscribe; 1 = require approval'], + 'urlshorteningservice' => ['type' => 'varchar', 'length' => 50, 'default' => 'internal', 'description' => 'service to use for auto-shortening URLs'], + 'private_stream' => ['type' => 'bool', 'default' => false, 'description' => 'whether to limit all notices to followers only'], + 'created' => ['type' => 'datetime', 'not null' => true, 'default' => '0000-00-00 00:00:00', 'description' => 'date this record was created'], + 'modified' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'], + ], + 'primary key' => ['id'], + 'unique keys' => [ + 'user_nickname_key' => ['nickname'], + 'user_email_key' => ['email'], + 'user_incomingemail_key' => ['incomingemail'], + 'user_sms_key' => ['sms'], + 'user_uri_key' => ['uri'], + ], + 'foreign keys' => [ + 'user_id_fkey' => ['profile', ['id' => 'id']], + 'user_carrier_fkey' => ['sms_carrier', ['carrier' => 'id']], + ], + 'indexes' => [ + 'user_created_idx' => ['created'], + 'user_smsemail_idx' => ['smsemail'], + ], + ]; + } +} diff --git a/src/Kernel.php b/src/Kernel.php index 10e367d701..a38b28f0e6 100644 --- a/src/Kernel.php +++ b/src/Kernel.php @@ -2,14 +2,15 @@ namespace App; +use App\DependencyInjection\Compiler\SchemaDefCompilerPass; +use const PHP_VERSION_ID; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Kernel as BaseKernel; + use Symfony\Component\Routing\RouteCollectionBuilder; -use function dirname; -use const PHP_VERSION_ID; class Kernel extends BaseKernel { @@ -19,7 +20,7 @@ class Kernel extends BaseKernel public function registerBundles(): iterable { - $contents = require $this->getProjectDir().'/config/bundles.php'; + $contents = require $this->getProjectDir() . '/config/bundles.php'; foreach ($contents as $class => $envs) { if ($envs[$this->environment] ?? $envs['all'] ?? false) { yield new $class(); @@ -34,23 +35,30 @@ class Kernel extends BaseKernel protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void { - $container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php')); + $container->addResource(new FileResource($this->getProjectDir() . '/config/bundles.php')); $container->setParameter('container.dumper.inline_class_loader', PHP_VERSION_ID < 70400 || $this->debug); $container->setParameter('container.dumper.inline_factories', true); - $confDir = $this->getProjectDir().'/config'; + $confDir = $this->getProjectDir() . '/config'; - $loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob'); - $loader->load($confDir.'/{packages}/'.$this->environment.'/*'.self::CONFIG_EXTS, 'glob'); - $loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob'); - $loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob'); + $loader->load($confDir . '/{packages}/*' . self::CONFIG_EXTS, 'glob'); + $loader->load($confDir . '/{packages}/' . $this->environment . '/*' . self::CONFIG_EXTS, 'glob'); + $loader->load($confDir . '/{services}' . self::CONFIG_EXTS, 'glob'); + $loader->load($confDir . '/{services}_' . $this->environment . self::CONFIG_EXTS, 'glob'); } protected function configureRoutes(RouteCollectionBuilder $routes): void { - $confDir = $this->getProjectDir().'/config'; + $confDir = $this->getProjectDir() . '/config'; - $routes->import($confDir.'/{routes}/'.$this->environment.'/*'.self::CONFIG_EXTS, '/', 'glob'); - $routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob'); - $routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob'); + $routes->import($confDir . '/{routes}/' . $this->environment . '/*' . self::CONFIG_EXTS, '/', 'glob'); + $routes->import($confDir . '/{routes}/*' . self::CONFIG_EXTS, '/', 'glob'); + $routes->import($confDir . '/{routes}' . self::CONFIG_EXTS, '/', 'glob'); + } + + protected function build(ContainerBuilder $container): void + { + parent::build($container); + + $container->addCompilerPass(new SchemaDefCompilerPass($container)); } } diff --git a/src/Util/Common.php b/src/Util/Common.php index 6e3c082393..2ac531e8a5 100644 --- a/src/Util/Common.php +++ b/src/Util/Common.php @@ -1,4 +1,5 @@ * @author Brion Vibber * @author Brion Vibber @@ -51,38 +53,30 @@ namespace App\Util; -use Psr\Log\LoggerInterface; use Psr\Container\ContainerInterface; -use Symfony\Contracts\Translation\TranslatorInterface; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\EventDispatcher\EventDispatcher; +use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\KernelEvents; - -use App\Util\Log; -use App\Util\GSEvent; -use App\Util\I18n; +use Symfony\Contracts\Translation\TranslatorInterface; class GNUsocial implements EventSubscriberInterface { protected ContainerInterface $container; + protected LoggerInterface $logger; + protected TranslatorInterface $translator; public function __construct(ContainerInterface $container, LoggerInterface $logger, TranslatorInterface $translator) { - $this->container = $container; - $this->logger = $logger; + $this->container = $container; + $this->logger = $logger; $this->translator = $translator; - } - public function onKernelRequest(RequestEvent $event, - string $event_name, - $event_dispatcher): RequestEvent - { - if (!defined('INSTALLDIR')) { + if (!\defined('INSTALLDIR')) { define('INSTALLDIR', dirname(__DIR__)); define('SRCDIR', INSTALLDIR . '/src'); define('PUBLICDIR', INSTALLDIR . '/public'); @@ -98,29 +92,28 @@ class GNUsocial implements EventSubscriberInterface define('GNUSOCIAL_VERSION', GNUSOCIAL_BASE_VERSION . '-' . GNUSOCIAL_LIFECYCLE); define('GNUSOCIAL_CODENAME', 'Big bang'); - /* Work internally in UTC */ + // Work internally in UTC date_default_timezone_set('UTC'); - /* Work internally with UTF-8 */ + // Work internally with UTF-8 mb_internal_encoding('UTF-8'); + } + } + public function onKernelRequest(RequestEvent $event, + string $event_name, + $event_dispatcher): RequestEvent + { + if (!\defined('INSTALLDIR')) { Log::setLogger($this->logger); GSEvent::setDispatcher($event_dispatcher); I18n::setTranslator($this->translator); } - - - GSEvent::addHandler('test', function ($x) { - Log::info(_m("Logging from an event " . var_export($x, true))); - }); - return $event; } public static function getSubscribedEvents() { - return array( - KernelEvents::REQUEST => 'onKernelRequest' - ); + return [KernelEvents::REQUEST => 'onKernelRequest']; } } diff --git a/src/Util/GSEvent.php b/src/Util/GSEvent.php index af944f53b4..6065fa0774 100644 --- a/src/Util/GSEvent.php +++ b/src/Util/GSEvent.php @@ -1,4 +1,5 @@ addListener( $name, @@ -70,10 +71,10 @@ abstract class GSEvent { && call_user_func_array($handler, $event->getArguments()) == self::stop) { $event->stopPropagation(); return $event; - } else { - // Symfony style of events - call_user_func($handler, $event, $event_name, $dispatcher); } + // Symfony style of events + call_user_func($handler, $event, $event_name, $dispatcher); + return null; }, $priority @@ -94,7 +95,7 @@ abstract class GSEvent { * @param array $args Arguments for handlers * * @return bool flag saying whether to continue processing, based - * on results of handlers. + * on results of handlers. */ public static function handle(string $name, array $args = []): bool { @@ -109,17 +110,17 @@ abstract class GSEvent { * Look to see if there's any handler for a given event, or narrow * by providing the name of a specific plugin class. * - * @param string $name Name of the event to look for + * @param string $name Name of the event to look for * @param string $plugin Optional name of the plugin class to look for * * @return bool flag saying whether such a handler exists */ - public static function hasHandler(string $name, ?string $plugin=null): bool + public static function hasHandler(string $name, ?string $plugin = null): bool { $listeners = self::$dispatcher->getListeners($name); if (isset($plugin)) { foreach ($listeners as $handler) { - if (get_class($handler[0]) == $plugin) { + if (\get_class($handler[0]) == $plugin) { return true; } } @@ -133,6 +134,7 @@ abstract class GSEvent { * Get the array of handlers for $name * * @param string $name Name of event + * * @return array * @return array */ diff --git a/src/Util/I18n.php b/src/Util/I18n.php index 5530c7dea1..adf7280c73 100644 --- a/src/Util/I18n.php +++ b/src/Util/I18n.php @@ -1,4 +1,5 @@ * @author Ciaran Gultnieks * @author Evan Prodromou @@ -31,33 +33,38 @@ namespace App\Util; // Locale category constants are usually predefined, but may not be // on some systems such as Win32. -$LC_CATEGORIES = ['LC_CTYPE', - 'LC_NUMERIC', - 'LC_TIME', - 'LC_COLLATE', - 'LC_MONETARY', - 'LC_MESSAGES', - 'LC_ALL']; +$LC_CATEGORIES = [ + 'LC_CTYPE', + 'LC_NUMERIC', + 'LC_TIME', + 'LC_COLLATE', + 'LC_MONETARY', + 'LC_MESSAGES', + 'LC_ALL', +]; foreach ($LC_CATEGORIES as $key => $name) { - if (!defined($name)) { + if (!\defined($name)) { define($name, $key); } } use Symfony\Contracts\Translation\TranslatorInterface; -use App\Util\Common; - -abstract class I18n { - +abstract class I18n +{ public static ?TranslatorInterface $translator = null; - public static function setTranslator($trans): void { self::$translator = $trans; } + + public static function setTranslator($trans): void + { + self::$translator = $trans; + } /** * Looks for which plugin we've been called from to set the gettext domain; * if not in a plugin subdirectory, we'll use the default 'gnusocial'. * * @param array $backtrace debug_backtrace() output + * * @return string * @private */ @@ -76,10 +83,10 @@ abstract class I18n { static $cached; $path = $backtrace[0]['file']; if (!isset($cached[$path])) { - $path = common::normalizePath($path); + $path = common::normalizePath($path); $cached[$path] = common::pluginFromPath($path); } - return $cached[$path] ?? ""; + return $cached[$path] ?? ''; } } @@ -100,19 +107,21 @@ abstract class I18n { * * @param string $msg * @param extra params as described above - * @return string + * * @throws Exception + * + * @return string */ function _m(string $msg /*, ...*/): string { - $domain = I18n::_mdomain(debug_backtrace()); - $args = func_get_args(); - switch (count($args)) { + $domain = I18n::_mdomain(\debug_backtrace()); + $args = func_get_args(); + switch (\count($args)) { case 1: // Empty parameters return I18n::$translator->trans($msg, [], $domain); case 2: - $context = $args[0]; + $context = $args[0]; $msg_single = $args[1]; // ASCII 4 is EOT, used to separate context from string return I18n::$translator->trans($context . '\004' . $msg_single, [], $domain); @@ -120,18 +129,18 @@ function _m(string $msg /*, ...*/): string // '|' separates the singular from the plural version $msg_single = $args[0]; $msg_plural = $args[1]; - $n = $args[2]; + $n = $args[2]; return I18n::$translator->trans($msg_single . '|' . $msg_plural, ['%d' => $n], $domain); case 4: // Combine both - $context = $args[0]; + $context = $args[0]; $msg_single = $args[1]; $msg_plural = $args[2]; - $n = $args[3]; + $n = $args[3]; return I18n::$translator->trans($context . '\004' . $msg_single . '|' . $msg_plural, ['%d' => $n], $domain); default: - throw new Exception("Bad parameter count to _m()"); + throw new Exception('Bad parameter count to _m()'); } } @@ -139,11 +148,12 @@ function _m(string $msg /*, ...*/): string * Content negotiation for language codes * * @param string $http_accept_lang_header HTTP Accept-Language header + * * @return string language code for best language match, false otherwise */ function client_preferred_language(string $http_accept_lang_header): string { - $client_langs = []; + $client_langs = []; $all_languages = Common::config('site', 'languages'); preg_match_all('"(((\S\S)-?(\S\S)?)(;q=([0-9.]+))?)\s*(,\s*|$)"', @@ -152,13 +162,11 @@ function client_preferred_language(string $http_accept_lang_header): string for ($i = 0; $i < count($http_langs); ++$i) { if (!empty($http_langs[2][$i])) { // if no q default to 1.0 - $client_langs[$http_langs[2][$i]] = - ($http_langs[6][$i] ? (float)$http_langs[6][$i] : 1.0 - ($i * 0.01)); + $client_langs[$http_langs[2][$i]] = ($http_langs[6][$i] ? (float) $http_langs[6][$i] : 1.0 - ($i * 0.01)); } if (!empty($http_langs[3][$i]) && empty($client_langs[$http_langs[3][$i]])) { // if a catchall default 0.01 lower - $client_langs[$http_langs[3][$i]] = - ($http_langs[6][$i] ? (float)$http_langs[6][$i] - 0.01 : 0.99); + $client_langs[$http_langs[3][$i]] = ($http_langs[6][$i] ? (float) $http_langs[6][$i] - 0.01 : 0.99); } } // sort in descending q @@ -166,7 +174,7 @@ function client_preferred_language(string $http_accept_lang_header): string foreach ($client_langs as $lang => $q) { if (isset($all_languages[$lang])) { - return ($all_languages[$lang]['lang']); + return $all_languages[$lang]['lang']; } } return false; @@ -177,10 +185,9 @@ function client_preferred_language(string $http_accept_lang_header): string * * @return array map of available languages by code to language name. */ - function get_nice_language_list(): array { - $nice_lang = []; + $nice_lang = []; $all_languages = common_config('site', 'languages'); foreach ($all_languages as $lang) { @@ -194,9 +201,8 @@ function get_nice_language_list(): array * * @param string $lang language code of the language to check * - * @return boolean true if language is rtl + * @return bool true if language is rtl */ - function is_rtl(string $lang_value): bool { foreach (common_config('site', 'languages') as $code => $info) { diff --git a/src/Util/Log.php b/src/Util/Log.php index a578061faf..f24a838d88 100644 --- a/src/Util/Log.php +++ b/src/Util/Log.php @@ -1,4 +1,5 @@ error($msg); } + public static function info(string $msg): void { self::$logger->info($msg); } + public static function debug(string $msg): void { $logger->debug($msg); diff --git a/src/Util/SchemaDefDriver.php b/src/Util/SchemaDefDriver.php new file mode 100644 index 0000000000..af2a84d05e --- /dev/null +++ b/src/Util/SchemaDefDriver.php @@ -0,0 +1,15 @@ +addField($schema[0]); + } +} diff --git a/symfony.lock b/symfony.lock index 12de45c15d..3245d76de7 100644 --- a/symfony.lock +++ b/symfony.lock @@ -1,4 +1,10 @@ { + "composer/semver": { + "version": "1.5.1" + }, + "composer/xdebug-handler": { + "version": "1.4.1" + }, "doctrine/annotations": { "version": "1.0", "recipe": { @@ -90,6 +96,18 @@ "egulias/email-validator": { "version": "2.1.17" }, + "friendsofphp/php-cs-fixer": { + "version": "2.2", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "2.2", + "ref": "cc05ab6abf6894bddb9bbd6a252459010ebe040b" + }, + "files": [ + ".php_cs.dist" + ] + }, "jdorn/sql-formatter": { "version": "v1.2.17" }, @@ -117,6 +135,9 @@ "php": { "version": "7.4" }, + "php-cs-fixer/diff": { + "version": "v1.3.0" + }, "phpdocumentor/reflection-common": { "version": "2.0.0" }, diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 469dccee49..2a0282cfff 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -2,10 +2,10 @@ use Symfony\Component\Dotenv\Dotenv; -require dirname(__DIR__).'/vendor/autoload.php'; +require dirname(__DIR__) . '/vendor/autoload.php'; -if (file_exists(dirname(__DIR__).'/config/bootstrap.php')) { - require dirname(__DIR__).'/config/bootstrap.php'; -} elseif (method_exists(Dotenv::class, 'bootEnv')) { - (new Dotenv())->bootEnv(dirname(__DIR__).'/.env'); +if (\file_exists(\dirname(__DIR__) . '/config/bootstrap.php')) { + require dirname(__DIR__) . '/config/bootstrap.php'; +} elseif (\method_exists(Dotenv::class, 'bootEnv')) { + (new Dotenv())->bootEnv(\dirname(__DIR__) . '/.env'); }