From 712c99ce072b8d7ea5f1132865b20ddc2f1bf0a5 Mon Sep 17 00:00:00 2001 From: CyberVitexus Date: Wed, 20 Nov 2024 23:20:16 +0100 Subject: [PATCH 1/4] Strict types update --- src/Queries/Base.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Queries/Base.php b/src/Queries/Base.php index b05aae1..0e76cd3 100644 --- a/src/Queries/Base.php +++ b/src/Queries/Base.php @@ -174,7 +174,7 @@ protected function resetClause($clause) * @throws Exception */ #[\ReturnTypeWillChange] - public function getIterator() + public function getIterator(): \Traversable { return $this->execute(); } From 6407150134d5b318bd9d58f979501d111dc3f53f Mon Sep 17 00:00:00 2001 From: CyberVitexus Date: Tue, 21 Oct 2025 23:41:54 +0200 Subject: [PATCH 2/4] Ensures array values are JSON-encoded for compatibility Converts array values to JSON strings to ensure compatibility with PDO and other components that require scalar values. This change prevents potential issues when handling array data in query parameters and type conversions. Adds support for encoding arrays in the Utilities class, enhancing data handling consistency across the application. --- src/Queries/Base.php | 9 +++++++++ src/Utilities.php | 3 +++ 2 files changed, 12 insertions(+) diff --git a/src/Queries/Base.php b/src/Queries/Base.php index 0e76cd3..52a986d 100644 --- a/src/Queries/Base.php +++ b/src/Queries/Base.php @@ -390,6 +390,11 @@ protected function buildParameters(): array if (is_array($clauses)) { foreach ($clauses as $key => $value) { + // Convert arrays to JSON strings for PDO compatibility + if (is_array($value)) { + $value = json_encode($value); + } + if (strpos($key, ':') === 0) { // these are named params e.g. (':name' => 'Mark') $parameters += [$key => $value]; } else { @@ -397,6 +402,10 @@ protected function buildParameters(): array } } } elseif ($clauses !== false && $clauses !== null) { + // Convert arrays to JSON strings for PDO compatibility + if (is_array($clauses)) { + $clauses = json_encode($clauses); + } $parameters[] = $clauses; } } diff --git a/src/Utilities.php b/src/Utilities.php index 3c939f7..c040725 100644 --- a/src/Utilities.php +++ b/src/Utilities.php @@ -110,6 +110,9 @@ public static function convertValue($value) case 'boolean': $conversion = ($value) ? 1 : 0; break; + case 'array': + $conversion = json_encode($value); + break; default: $conversion = $value; break; From a3a34098eec4065c066cac75b37f9c4a837d0419 Mon Sep 17 00:00:00 2001 From: CyberVitexus Date: Wed, 22 Oct 2025 00:19:51 +0200 Subject: [PATCH 3/4] Add modernization and CI/CD setup for PHP 8.1+ support Introduce full support for PHP 8.1+ by leveraging strict typing, union types, and modern features. Update composer dependencies and configuration to align with current PHP standards. Add CI/CD configurations, including testing workflows with PHPUnit and dependency updates via Dependabot. Enhance developer experience with PHP-CS-Fixer, customized IDE settings, and detailed documentation guidelines. Provide funding model instructions and update project metadata to reflect the modernized fork. Includes breaking changes such as raising the minimum PHP version to 8.1 and updating method signatures for type safety. --- .build/php-cs-fixer/.php-cs-fixer.cache | 1 + .github/FUNDING.yml | 12 + .github/copilot-instructions.md | 43 + .github/dependabot.yml | 14 + .github/workflows/testing.yml | 21 + .php-cs-fixer.dist.php | 104 + .vscode/settings.json | 23 + CHANGELOG.md | 51 + Makefile | 19 + WARP.md | 99 + composer.json | 79 +- composer.lock | 6130 ++++++++++++++++++++--- readme.md | 120 +- src/Exception.php | 14 +- src/Literal.php | 30 +- src/Queries/Base.php | 414 +- src/Queries/Common.php | 298 +- src/Queries/Delete.php | 90 +- src/Queries/Insert.php | 107 +- src/Queries/Json.php | 50 +- src/Queries/Select.php | 106 +- src/Queries/Update.php | 83 +- src/Query.php | 157 +- src/Regex.php | 130 +- src/Structure.php | 56 +- src/Utilities.php | 88 +- tests/Queries/CommonTest.php | 194 +- tests/Queries/DeleteTest.php | 43 +- tests/Queries/InsertTest.php | 79 +- tests/Queries/SelectTest.php | 108 +- tests/Queries/UpdateTest.php | 92 +- tests/RegexTest.php | 81 +- tests/StructureTest.php | 29 +- tests/UtilitiesTest.php | 42 +- tests/_resources/init.php | 19 +- 35 files changed, 7085 insertions(+), 1941 deletions(-) create mode 100644 .build/php-cs-fixer/.php-cs-fixer.cache create mode 100644 .github/FUNDING.yml create mode 100644 .github/copilot-instructions.md create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/testing.yml create mode 100644 .php-cs-fixer.dist.php create mode 100644 .vscode/settings.json create mode 100644 CHANGELOG.md create mode 100644 Makefile create mode 100644 WARP.md diff --git a/.build/php-cs-fixer/.php-cs-fixer.cache b/.build/php-cs-fixer/.php-cs-fixer.cache new file mode 100644 index 0000000..29b1b89 --- /dev/null +++ b/.build/php-cs-fixer/.php-cs-fixer.cache @@ -0,0 +1 @@ +{"php":"8.4.13","version":"3.88.2:v3.88.2#a8d15584bafb0f0d9d938827840060fd4a3ebc99","indent":" ","lineEnding":"\n","rules":{"ErickSkrauch\/line_break_after_statements":true,"PhpCsFixerCustomFixers\/multiline_comment_opening_closing_alone":true,"PhpCsFixerCustomFixers\/no_duplicated_array_key":{"ignore_expressions":true},"PhpCsFixerCustomFixers\/no_duplicated_imports":true,"PhpCsFixerCustomFixers\/php_unit_requires_constraint":true,"PhpCsFixerCustomFixers\/phpdoc_types_comma_spaces":true,"align_multiline_comment":{"comment_type":"all_multiline"},"array_indentation":true,"array_push":true,"array_syntax":{"syntax":"short"},"assign_null_coalescing_to_coalesce_equal":true,"backtick_to_shell_exec":true,"binary_operator_spaces":{"default":"single_space","operators":[]},"blank_line_after_namespace":true,"blank_line_after_opening_tag":true,"blank_line_before_statement":{"statements":["break","continue","declare","default","do","exit","for","foreach","goto","if","include","include_once","require","require_once","return","switch","throw","try","while"]},"blank_lines_before_namespace":{"max_line_breaks":2,"min_line_breaks":2},"braces_position":{"allow_single_line_anonymous_functions":false,"allow_single_line_empty_anonymous_classes":false,"anonymous_classes_opening_brace":"same_line","anonymous_functions_opening_brace":"same_line","classes_opening_brace":"next_line_unless_newline_at_signature_end","control_structures_opening_brace":"same_line","functions_opening_brace":"next_line_unless_newline_at_signature_end"},"cast_spaces":{"space":"single"},"class_attributes_separation":{"elements":{"const":"only_if_meta","property":"only_if_meta","trait_import":"none","case":"none"}},"class_definition":{"inline_constructor_arguments":true,"multi_line_extends_each_single_line":false,"single_item_single_line":false,"single_line":false,"space_before_parenthesis":false},"class_reference_name_casing":true,"clean_namespace":true,"combine_consecutive_issets":true,"combine_consecutive_unsets":true,"combine_nested_dirname":true,"comment_to_phpdoc":{"ignored_tags":[]},"compact_nullable_type_declaration":true,"concat_space":{"spacing":"none"},"constant_case":{"case":"lower"},"control_structure_braces":true,"control_structure_continuation_position":{"position":"same_line"},"date_time_create_from_format_call":true,"declare_equal_normalize":{"space":"none"},"declare_parentheses":true,"declare_strict_types":true,"dir_constant":true,"doctrine_annotation_array_assignment":{"ignored_tags":["abstract","access","after","afterClass","api","author","backupGlobals","backupStaticAttributes","before","beforeClass","category","code","codeCoverageIgnore","codeCoverageIgnoreEnd","codeCoverageIgnoreStart","copyright","covers","coversDefaultClass","coversNothing","dataProvider","depends","deprec","deprecated","encode","enduml","example","exception","expectedException","expectedExceptionCode","expectedExceptionMessage","expectedExceptionMessageRegExp","filesource","final","fix","FIXME","fixme","global","group","ignore","ingroup","inheritdoc","inheritDoc","internal","large","license","link","magic","medium","method","name","noinspection","override","package","package_version","param","preserveGlobalState","private","property","property-read","property-write","requires","return","runInSeparateProcess","runTestsInSeparateProcesses","see","since","small","source","startuml","static","staticvar","staticVar","subpackage","SuppressWarnings","template","test","testdox","throw","throws","ticket","toc","todo","TODO","tutorial","usedBy","uses","uses","var","version"],"operator":":"},"doctrine_annotation_braces":{"ignored_tags":["abstract","access","after","afterClass","api","author","backupGlobals","backupStaticAttributes","before","beforeClass","category","code","codeCoverageIgnore","codeCoverageIgnoreEnd","codeCoverageIgnoreStart","copyright","covers","coversDefaultClass","coversNothing","dataProvider","depends","deprec","deprecated","encode","enduml","example","exception","expectedException","expectedExceptionCode","expectedExceptionMessage","expectedExceptionMessageRegExp","filesource","final","fix","FIXME","fixme","global","group","ignore","ingroup","inheritdoc","inheritDoc","internal","large","license","link","magic","medium","method","name","noinspection","override","package","package_version","param","preserveGlobalState","private","property","property-read","property-write","requires","return","runInSeparateProcess","runTestsInSeparateProcesses","see","since","small","source","startuml","static","staticvar","staticVar","subpackage","SuppressWarnings","template","test","testdox","throw","throws","ticket","toc","todo","TODO","tutorial","usedBy","uses","uses","var","version"],"syntax":"without_braces"},"doctrine_annotation_indentation":{"ignored_tags":["abstract","access","after","afterClass","api","author","backupGlobals","backupStaticAttributes","before","beforeClass","category","code","codeCoverageIgnore","codeCoverageIgnoreEnd","codeCoverageIgnoreStart","copyright","covers","coversDefaultClass","coversNothing","dataProvider","depends","deprec","deprecated","encode","enduml","example","exception","expectedException","expectedExceptionCode","expectedExceptionMessage","expectedExceptionMessageRegExp","filesource","final","fix","FIXME","fixme","global","group","ignore","ingroup","inheritdoc","inheritDoc","internal","large","license","link","magic","medium","method","name","noinspection","override","package","package_version","param","preserveGlobalState","private","property","property-read","property-write","requires","return","runInSeparateProcess","runTestsInSeparateProcesses","see","since","small","source","startuml","static","staticvar","staticVar","subpackage","SuppressWarnings","template","test","testdox","throw","throws","ticket","toc","todo","TODO","tutorial","usedBy","uses","uses","var","version"],"indent_mixed_lines":false},"doctrine_annotation_spaces":{"after_argument_assignments":false,"after_array_assignments_colon":true,"after_array_assignments_equals":false,"around_commas":true,"around_parentheses":true,"before_argument_assignments":false,"before_array_assignments_colon":false,"before_array_assignments_equals":false,"ignored_tags":["abstract","access","after","afterClass","api","author","backupGlobals","backupStaticAttributes","before","beforeClass","category","code","codeCoverageIgnore","codeCoverageIgnoreEnd","codeCoverageIgnoreStart","copyright","covers","coversDefaultClass","coversNothing","dataProvider","depends","deprec","deprecated","encode","enduml","example","exception","expectedException","expectedExceptionCode","expectedExceptionMessage","expectedExceptionMessageRegExp","filesource","final","fix","FIXME","fixme","global","group","ignore","ingroup","inheritdoc","inheritDoc","internal","large","license","link","magic","medium","method","name","noinspection","override","package","package_version","param","preserveGlobalState","private","property","property-read","property-write","requires","return","runInSeparateProcess","runTestsInSeparateProcesses","see","since","small","source","startuml","static","staticvar","staticVar","subpackage","SuppressWarnings","template","test","testdox","throw","throws","ticket","toc","todo","TODO","tutorial","usedBy","uses","uses","var","version"]},"echo_tag_syntax":{"format":"long","long_function":"echo","shorten_simple_statements_only":true},"elseif":true,"empty_loop_body":{"style":"braces"},"empty_loop_condition":{"style":"while"},"encoding":true,"ereg_to_preg":true,"explicit_indirect_variable":true,"explicit_string_variable":true,"final_internal_class":{"consider_absent_docblock_as_internal_class":false,"exclude":["@Entity","@final","@Mapping\\Entity","@ORM\\Entity","@ORM\\Mapping\\Entity"],"include":["@internal"]},"fopen_flag_order":true,"fopen_flags":{"b_mode":true},"full_opening_tag":true,"function_declaration":{"closure_fn_spacing":"one","closure_function_spacing":"one","trailing_comma_single_line":false},"function_to_constant":{"functions":["get_called_class","get_class","php_sapi_name","phpversion","pi"]},"general_phpdoc_tag_rename":{"case_sensitive":false,"fix_annotation":true,"fix_inline":true,"replacements":{"inheritdoc":"inheritdoc","inheritdocs":"inheritdoc"}},"get_class_to_class_keyword":true,"global_namespace_import":{"import_classes":false,"import_constants":false,"import_functions":false},"header_comment":{"comment_type":"PHPDoc","header":"This file is part of the EaseCore package.\n\n(c) V\u00edt\u011bzslav Dvo\u0159\u00e1k \n\nFor the full copyright and license information, please view the LICENSE\nfile that was distributed with this source code.","location":"after_declare_strict","separate":"both"},"heredoc_to_nowdoc":true,"implode_call":true,"include":true,"increment_style":{"style":"pre"},"indentation_type":true,"integer_literal_case":true,"is_null":true,"lambda_not_used_import":true,"line_ending":true,"linebreak_after_opening_tag":true,"list_syntax":{"syntax":"short"},"logical_operators":true,"long_to_shorthand_operator":true,"lowercase_cast":true,"lowercase_keywords":true,"lowercase_static_reference":true,"magic_constant_casing":true,"magic_method_casing":true,"method_argument_space":{"after_heredoc":false,"attribute_placement":"standalone","keep_multiple_spaces_after_comma":false,"on_multiline":"ensure_fully_multiline"},"method_chaining_indentation":true,"modernize_strpos":{"modernize_stripos":true},"modernize_types_casting":true,"modifier_keywords":{"elements":["const","method","property"]},"multiline_comment_opening_closing":true,"multiline_promoted_properties":{"keep_blank_lines":false,"minimum_number_of_parameters":2},"multiline_string_to_heredoc":true,"multiline_whitespace_before_semicolons":{"strategy":"no_multi_line"},"native_constant_invocation":{"exclude":["false","null","true"],"fix_built_in":true,"include":[],"scope":"all","strict":false},"native_function_casing":true,"native_function_invocation":{"exclude":["sprintf"],"include":["@compiler_optimized"],"scope":"all","strict":false},"native_type_declaration_casing":true,"new_with_parentheses":{"anonymous_class":true,"named_class":true},"no_alias_functions":{"sets":["@all"]},"no_alias_language_construct_call":true,"no_alternative_syntax":{"fix_non_monolithic_code":true},"no_binary_string":true,"no_blank_lines_after_class_opening":true,"no_blank_lines_after_phpdoc":true,"no_break_comment":{"comment_text":"no break"},"no_closing_tag":true,"no_empty_comment":true,"no_empty_phpdoc":true,"no_empty_statement":true,"no_extra_blank_lines":{"tokens":["attribute","break","case","comma","continue","curly_brace_block","default","extra","parenthesis_brace_block","return","square_brace_block","switch","throw","use"]},"no_homoglyph_names":true,"no_leading_import_slash":true,"no_leading_namespace_whitespace":true,"no_mixed_echo_print":{"use":"echo"},"no_multiline_whitespace_around_double_arrow":true,"no_multiple_statements_per_line":true,"no_null_property_initialization":true,"no_short_bool_cast":true,"no_singleline_whitespace_before_semicolons":true,"no_space_around_double_colon":true,"no_spaces_after_function_name":true,"no_spaces_around_offset":{"positions":["inside","outside"]},"no_superfluous_elseif":true,"no_superfluous_phpdoc_tags":{"allow_hidden_params":false,"allow_mixed":true,"allow_unused_params":false,"remove_inheritdoc":false},"no_trailing_comma_in_singleline":{"elements":["arguments","array","array_destructuring","group_import"]},"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"no_trailing_whitespace_in_string":true,"no_unneeded_braces":{"namespaces":true},"no_unneeded_control_parentheses":{"statements":["break","clone","continue","echo_print","negative_instanceof","others","return","switch_case","yield","yield_from"]},"no_unneeded_final_method":{"private_methods":true},"no_unneeded_import_alias":true,"no_unreachable_default_argument_value":true,"no_unset_cast":true,"no_unset_on_property":true,"no_unused_imports":true,"no_useless_concat_operator":{"juggle_simple_strings":true},"no_useless_else":true,"no_useless_nullsafe_operator":true,"no_useless_printf":true,"no_useless_return":true,"no_useless_sprintf":true,"no_whitespace_before_comma_in_array":{"after_heredoc":false},"no_whitespace_in_blank_line":true,"non_printable_character":{"use_escape_sequences_in_strings":false},"normalize_index_brace":true,"nullable_type_declaration":{"syntax":"question_mark"},"nullable_type_declaration_for_default_null_value":true,"object_operator_without_whitespace":true,"octal_notation":true,"operator_linebreak":{"only_booleans":true,"position":"beginning"},"ordered_attributes":{"order":[],"sort_algorithm":"alpha"},"ordered_class_elements":{"case_sensitive":false,"order":["use_trait","case","constant_public","constant_protected","constant_private","property_public","property_protected","property_private","construct","destruct","magic","phpunit","method_public","method_protected","method_private"],"sort_algorithm":"none"},"ordered_imports":{"case_sensitive":false,"imports_order":["class","const","function"],"sort_algorithm":"alpha"},"ordered_interfaces":{"case_sensitive":false,"direction":"ascend","order":"alpha"},"ordered_types":{"case_sensitive":false,"null_adjustment":"always_first","sort_algorithm":"alpha"},"php_unit_construct":{"assertions":["assertEquals","assertNotEquals","assertNotSame","assertSame"]},"php_unit_data_provider_method_order":{"placement":"after"},"php_unit_data_provider_return_type":true,"php_unit_data_provider_static":{"force":false},"php_unit_dedicate_assert":{"target":"newest"},"php_unit_dedicate_assert_internal_type":{"target":"newest"},"php_unit_expectation":{"target":"newest"},"php_unit_fqcn_annotation":true,"php_unit_method_casing":{"case":"camel_case"},"php_unit_mock":{"target":"newest"},"php_unit_mock_short_will_return":true,"php_unit_namespaced":{"target":"newest"},"php_unit_no_expectation_annotation":{"target":"newest","use_class_const":true},"php_unit_set_up_tear_down_visibility":true,"php_unit_test_annotation":{"style":"prefix"},"phpdoc_add_missing_param_annotation":{"only_untyped":true},"phpdoc_align":{"align":"vertical","spacing":1,"tags":["method","param","property","property-read","property-write","return","throws","type","var"]},"phpdoc_annotation_without_dot":true,"phpdoc_indent":true,"phpdoc_inline_tag_normalizer":{"tags":["example","id","inheritdoc","inheritdocs","internal","link","source","toc","tutorial"]},"phpdoc_line_span":{"const":"multi","method":"multi","property":"multi"},"phpdoc_no_access":true,"phpdoc_no_alias_tag":{"replacements":{"link":"see","property-read":"property","property-write":"property","type":"var"}},"phpdoc_no_empty_return":true,"phpdoc_no_package":true,"phpdoc_no_useless_inheritdoc":true,"phpdoc_order":{"order":["deprecated","internal","covers","uses","dataProvider","param","throws","return"]},"phpdoc_order_by_value":{"annotations":["author","covers","coversNothing","dataProvider","depends","group","internal","method","mixin","property","property-read","property-write","requires","throws","uses"]},"phpdoc_param_order":true,"phpdoc_return_self_reference":{"replacements":{"$self":"self","$static":"static","@self":"self","@static":"static","@this":"$this","this":"$this"}},"phpdoc_scalar":{"types":["boolean","callback","double","integer","real","str"]},"phpdoc_separation":{"groups":[["deprecated"],["link","see","since"],["author","copyright","license"],["category","package","subpackage"],["property","property-read","property-write"]],"skip_unlisted_annotations":false},"phpdoc_single_line_var_spacing":true,"phpdoc_summary":true,"phpdoc_tag_casing":{"tags":["inheritDoc"]},"phpdoc_tag_type":{"tags":{"inheritdoc":"inline"}},"phpdoc_to_property_type":{"scalar_types":true,"types_map":[],"union_types":true},"phpdoc_trim":true,"phpdoc_trim_consecutive_blank_line_separation":true,"phpdoc_types":{"groups":["alias","meta","simple"]},"phpdoc_types_order":{"case_sensitive":false,"null_adjustment":"always_first","sort_algorithm":"alpha"},"phpdoc_var_annotation_correct_order":true,"phpdoc_var_without_name":true,"pow_to_exponentiation":true,"protected_to_private":true,"psr_autoloading":{"dir":null},"random_api_migration":{"replacements":{"getrandmax":"mt_getrandmax","rand":"mt_rand","srand":"mt_srand"}},"regular_callable_call":true,"return_assignment":true,"return_type_declaration":{"space_before":"none"},"self_accessor":true,"self_static_accessor":true,"semicolon_after_instruction":true,"set_type_to_cast":true,"short_scalar_cast":true,"simple_to_complex_string_variable":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["const","property"]},"single_import_per_statement":{"group_to_single_imports":true},"single_line_after_imports":true,"single_line_comment_spacing":true,"single_line_comment_style":{"comment_types":["hash"]},"single_quote":{"strings_containing_single_quote_chars":false},"single_space_around_construct":{"constructs_contain_a_single_space":["yield_from"],"constructs_followed_by_a_single_space":["abstract","as","attribute","break","case","catch","class","clone","comment","const","const_import","continue","do","echo","else","elseif","enum","extends","final","finally","for","foreach","function","function_import","global","goto","if","implements","include","include_once","instanceof","insteadof","interface","match","named_argument","namespace","new","open_tag_with_echo","php_doc","php_open","print","private","protected","public","readonly","require","require_once","return","static","switch","throw","trait","try","type_colon","use","use_lambda","use_trait","var","while","yield","yield_from"],"constructs_preceded_by_a_single_space":["as","else","elseif","use_lambda"]},"single_trait_insert_per_statement":true,"space_after_semicolon":{"remove_in_empty_for_expressions":false},"spaces_inside_parentheses":{"space":"none"},"standardize_increment":true,"standardize_not_equals":true,"statement_indentation":{"stick_comment_to_next_continuous_control_statement":false},"static_lambda":true,"static_private_method":true,"strict_comparison":true,"strict_param":true,"string_implicit_backslashes":{"double_quoted":"escape","heredoc":"escape","single_quoted":"ignore"},"string_length_to_empty":true,"string_line_ending":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"switch_continue_to_break":true,"ternary_operator_spaces":true,"ternary_to_elvis_operator":true,"ternary_to_null_coalescing":true,"trailing_comma_in_multiline":{"after_heredoc":false,"elements":["arguments","array_destructuring","arrays","match","parameters"]},"trim_array_spaces":true,"type_declaration_spaces":{"elements":["constant","function","property"]},"types_spaces":{"space":"none","space_multiple_catch":"none"},"unary_operator_spaces":{"only_dec_inc":false},"void_return":true,"whitespace_after_comma_in_array":{"ensure_single_space":true}},"hashes":{"tests\/Queries\/CommonTest.php":"8ad8dec7a945ff3dbfbc8ef8f7c86eaf","tests\/_resources\/init.php":"83768ef674cd61267b4371fff20b2553","\/home\/vitex\/Projects\/VitexSoftware\/php-vitexsoftware-fluentpdo\/.php-cs-fixer.dist.php":"3177cb95719cf6d4c0f4a0e8dae81229","src\/Structure.php":"59ce9704a50bbded92bf8b60d244610e","src\/Regex.php":"adab89e94b1dfc35fbb6f92cf307c056","src\/Utilities.php":"f1e09b971af6b70d17f92993a41615a4","src\/Exception.php":"c6b0a74b886e899d7e09d37f83fe86c8","src\/Query.php":"427d9b9cbcba946c63db851c45f347cf","src\/Literal.php":"0c426a399ef95bc2c3bccedf502e106c","src\/Queries\/Common.php":"6298aa616141fa78b7007246c6810724","src\/Queries\/Delete.php":"1ee5ab0f19fb2da294d8b479faafe49f","src\/Queries\/Update.php":"a5df65da2943c90cc1f21456c75710d4","src\/Queries\/Select.php":"725ab00d77b4f24707493d70d112e76b","src\/Queries\/Base.php":"5af655b6e57be15ce327fec6c1f53614","src\/Queries\/Json.php":"11e8a883f2d36f10fe3a0f3b8566d990","src\/Queries\/Insert.php":"81be972e139ace8300a84fba46616cc7","tests\/RegexTest.php":"81cb4b332c2dae7b9f2a8db3711910c2","tests\/UtilitiesTest.php":"19d25aecce6b2446fd3ed243e1039cb8","tests\/StructureTest.php":"fbb1191659253ddb81de194c50bd3a55","tests\/Queries\/DeleteTest.php":"327658563233eee74b74c079c96b47e0","tests\/Queries\/SelectTest.php":"0ae3c14e0e4518ea93afc1c34334bd2d","tests\/Queries\/UpdateTest.php":"11698bca67bad8911d54da167cf60f03","tests\/Queries\/InsertTest.php":"3aae78edceac150a12f6cef6afb09437"}} \ No newline at end of file diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..a12c4dc --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: VitexSoftware +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..c80b6ce --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,43 @@ + + +All code comments should be written in English. + +All messages, including error messages, should be written in English. + +All code should be written in PHP 8.4 or later. + +All code should follow the PSR-12 coding standard. + +When writing code, always include a docblock for functions and classes, describing their purpose, parameters, and return types. + +When writing tests, use PHPUnit and follow the PSR-12 coding standard. + +When writing documentation, use MarkDown format. + +When writing commit messages, use the imperative mood and keep them concise. + +When writing code comments, use complete sentences and proper grammar. + +When writing code, always use meaningful variable names that describe their purpose. + +When writing code, avoid using magic numbers or strings; instead, define constants for them. + +When writing code, always handle exceptions properly and provide meaningful error messages. + +When writing code, always include type hints for function parameters and return types. + +We are using the i18n library for internationalization, so always use the _() functions for strings that need to be translated. + +When writing code, always ensure that it is secure and does not expose any sensitive information. + +When writing code, always consider performance and optimize where necessary. + +When writing code, always ensure that it is compatible with the latest version of PHP and the libraries we are using. + +When writing code, always ensure that it is well-tested and includes unit tests where applicable. + +When writing code, always ensure that it is maintainable and follows best practices. + +When create new class or update existing class, always create or update its phpunit test files. + +After every single edit to a PHP file, always run `php -l` on the edited file to lint it and ensure code sanity before proceeding further. This is mandatory for all PHP code changes. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..a9f4ba3 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,14 @@ +version: 2 +updates: + - package-ecosystem: "composer" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + versioning-strategy: increase + commit-message: + prefix: "composer" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml new file mode 100644 index 0000000..d195b3c --- /dev/null +++ b/.github/workflows/testing.yml @@ -0,0 +1,21 @@ +name: PHPUnit + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@master + env: + DEBIAN_FRONTEND: "noninteractive" + LC_ALL: "en_US.UTF-8" + LANG: "en_US.UTF-8" + - name: Prepare Environment + run: | + sudo apt-get install -y composer exim4 + composer update + - name: Run tests + run: make phpunit diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 0000000..05c151c --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Ergebnis\PhpCsFixer\Config\Factory; +use Ergebnis\PhpCsFixer\Config\Rules; +use Ergebnis\PhpCsFixer\Config\RuleSet\Php81; + +$header = <<<'HEADER' +This file is part of the EaseCore package. + +(c) Vítězslav Dvořák + +For the full copyright and license information, please view the LICENSE +file that was distributed with this source code. +HEADER; + +$ruleSet = Php81::create()->withHeader($header)->withRules(Rules::fromArray([ + 'blank_line_before_statement' => [ + 'statements' => [ + 'break', + 'continue', + 'declare', + 'default', + 'do', + 'exit', + 'for', + 'foreach', + 'goto', + 'if', + 'include', + 'include_once', + 'require', + 'require_once', + 'return', + 'switch', + 'throw', + 'try', + 'while', + ], + ], + 'concat_space' => [ + 'spacing' => 'none', + ], + 'date_time_immutable' => false, + 'error_suppression' => false, + 'final_class' => false, + 'mb_str_functions' => false, + 'native_function_invocation' => [ + 'exclude' => [ + 'sprintf', + ], + 'include' => [ + '@compiler_optimized', + ], + 'scope' => 'all', + 'strict' => false, + ], + 'php_unit_internal_class' => false, + 'php_unit_test_annotation' => [ + 'style' => 'prefix', + ], + 'php_unit_test_class_requires_covers' => false, + 'return_to_yield_from' => false, + 'phpdoc_array_type' => false, + 'phpdoc_list_type' => false, + 'attribute_empty_parentheses' => false, + 'final_public_method_for_abstract_class' => false, + 'class_attributes_separation' => [ + 'elements' => [ + 'const' => 'only_if_meta', + 'property' => 'only_if_meta', + 'trait_import' => 'none', + 'case' => 'none', + ], + ], + 'yoda_style' => false, + 'php_unit_test_case_static_method_calls' => false, +])); + +$config = Factory::fromRuleSet($ruleSet)->setUnsupportedPhpVersionAllowed(true); + +$config->getFinder() + ->append([ + __DIR__.'/.php-cs-fixer.dist.php', + ]) + ->append([ + __DIR__.'/rector.php', + ]) + ->in('src') + ->in('tests'); + +$config->setCacheFile(__DIR__.'/.build/php-cs-fixer/.php-cs-fixer.cache'); + +return $config; diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..cddbb74 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,23 @@ +{ + "php.version": "8.2", + "workbench.colorCustomizations": { + "activityBar.activeBackground": "#225d9c", + "activityBar.background": "#225d9c", + "activityBar.foreground": "#e7e7e7", + "activityBar.inactiveForeground": "#e7e7e799", + "activityBarBadge.background": "#dd629d", + "activityBarBadge.foreground": "#15202b", + "commandCenter.border": "#e7e7e799", + "sash.hoverBorder": "#225d9c", + "statusBar.background": "#194472", + "statusBar.foreground": "#e7e7e7", + "statusBarItem.hoverBackground": "#225d9c", + "statusBarItem.remoteBackground": "#194472", + "statusBarItem.remoteForeground": "#e7e7e7", + "titleBar.activeBackground": "#194472", + "titleBar.activeForeground": "#e7e7e7", + "titleBar.inactiveBackground": "#19447299", + "titleBar.inactiveForeground": "#e7e7e799" + }, + "peacock.color": "#194472" +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..6fe51ba --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,51 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +## [3.0.0] - 2025-01-21 + +### Added +- **PHP 8.1+ Support**: Complete modernization for PHP 8.1 and higher +- **Strict Type Declarations**: All files now use `declare(strict_types=1)` +- **Modern Type System**: Full use of PHP 8.1+ type declarations including: + - Union types (e.g., `string|null`, `array|string|null`) + - Mixed types for flexible parameters + - Proper return type declarations + - Typed properties throughout the codebase +- **Array Parameter Handling**: Automatic JSON serialization of array parameters +- **Enhanced IDE Support**: Better autocomplete and error detection with proper type hints +- **Updated Dependencies**: Modern development tools and PHPUnit 12.4+ + +### Changed +- **Breaking**: Minimum PHP version increased from 7.3 to 8.1 +- **Package Name**: Changed from `envms/fluentpdo` to `vitexsoftware/fluentpdo` +- **Type Safety**: All method signatures updated with proper type declarations +- **Error Handling**: Improved error messages and debugging capabilities +- **Performance**: Better memory usage through strict typing + +### Fixed +- **Array to String Conversion**: Fixed PHP warnings when arrays are passed as parameters +- **Type Compatibility**: Resolved all PHP 8.1+ compatibility issues +- **Method Signatures**: Updated all method signatures to match modern PHP standards + +### Removed +- **PHP < 8.1 Support**: No longer supports PHP versions below 8.1 + +## About This Fork + +This is a modernized fork of the original [envms/fluentpdo](https://github.com/envms/fluentpdo) project. The original project has been inactive since 2021, with the last commit being 3+ years old. This fork aims to: + +- Provide PHP 8.1+ compatibility with modern features +- Maintain API compatibility with the original project +- Add enhanced type safety and developer experience improvements +- Keep the library up-to-date with current PHP best practices + +## Migration from Original FluentPDO + +If you're migrating from the original `envms/fluentpdo`, the API remains compatible, but you'll need: + +1. PHP 8.1 or higher +2. Update your composer requirement to `vitexsoftware/fluentpdo` +3. Optionally add `declare(strict_types=1)` to your files for better performance + +The core API and functionality remain unchanged, so your existing code should work without modifications. \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..24852a5 --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +# vim: set tabstop=8 softtabstop=8 noexpandtab: +.PHONY: help +help: ## Displays this list of targets with descriptions + @grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[32m%-30s\033[0m %s\n", $$1, $$2}' + +.PHONY: cs +cs: vendor ## Normalizes composer.json with ergebnis/composer-normalize and fixes code style issues with friendsofphp/php-cs-fixer + mkdir -p .build/php-cs-fixer + vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php --diff --verbose + +phpdoc: clean ## Generate PHPDoc + mkdir -p docs + phpdoc --defaultpackagename=MainPackage + mv .phpdoc/build/* docs + +apigen: ## Build Apigen documentation + rm -rfv docs ; mkdir docs + VERSION=`cat debian/composer.json | grep version | awk -F'"' '{print $4}'`; \ + apigen generate --destination=docs --title "FluentPDO ${VERSION}" --charset UTF-8 --access-levels public --access-levels protected --php --tree -- src/ diff --git a/WARP.md b/WARP.md new file mode 100644 index 0000000..2bb1be7 --- /dev/null +++ b/WARP.md @@ -0,0 +1,99 @@ +# WARP.md + +This file provides guidance to WARP (warp.dev) when working with code in this repository. + +## Project Overview + +FluentPDO - PHP 8.1+ Edition is a modernized fork of the original FluentPDO project. It's a PHP SQL query builder library using PDO with a smart join builder that automatically creates table joins. This version (3.x) requires PHP 8.1+ and includes modern type declarations, strict typing, and enhanced features. + +## Common Development Commands + +### Testing +```bash +# Run all tests +phpunit --configuration phpunit.xml + +# Install dependencies first if needed +composer install + +# Set up test database (for local development) +mysql -u $DB_USER < tests/_resources/fluentdb.sql +``` + +### Development Setup +```bash +# Install dependencies +composer install + +# For testing, you need a MySQL database named 'fluentdb' +# Check tests/_resources/init.php for database configuration +``` + +## Code Architecture + +### Core Classes Structure +- `Query` - Main entry point, creates query objects (SELECT, INSERT, UPDATE, DELETE) +- `Structure` - Handles table relationships, primary/foreign key conventions +- `Base` - Abstract base class for all query types, handles execution and parameters +- `Common` - Shared functionality for SELECT/UPDATE/DELETE queries (WHERE, JOIN clauses) + +### Query Types (src/Queries/) +- `Select` - SELECT query builder with smart joins, implements Countable +- `Insert` - INSERT query builder +- `Update` - UPDATE query builder +- `Delete` - DELETE query builder +- `Json` - JSON query support + +### Key Features +- **Smart Join Builder**: Automatically creates JOINs based on column references (e.g., `user.name` auto-joins user table) +- **Fluent Interface**: Method chaining for building queries +- **PDO Integration**: Built on top of PDO for database portability +- **Type Conversion**: Optional type conversion for read/write operations + +### Database Conventions +- Primary keys default to 'id' +- Foreign keys follow pattern '%s_id' (e.g., `user_id` for user table) +- These conventions can be customized via `Structure` class + +### Usage Patterns +```php +// Basic setup +$fluent = new \Envms\FluentPDO\Query($pdo); + +// Smart joins automatically created +$query = $fluent->from('comment') + ->where('article.published_at > ?', $date) // Auto-joins article table + ->orderBy('published_at DESC'); + +// Shorthand methods for single-row operations +$user = $fluent->from('user', 1)->fetch(); // WHERE id = 1 +$fluent->update('article', $data, 1)->execute(); // WHERE id = 1 +``` + +## Testing Environment + +Tests use MySQL with database 'fluentdb'. Test configuration: +- Travis CI: Uses root user with no password +- Local development: Uses 'vagrant'/'vagrant' credentials +- Database schema: `tests/_resources/fluentdb.sql` +- Test initialization: `tests/_resources/init.php` + +## Development Notes + +- **Modern PHP 8.1+**: This fork requires PHP 8.1+ with strict typing throughout +- **Type Safety**: All classes use `declare(strict_types=1)` and proper type declarations +- **Array Handling**: Arrays are automatically converted to JSON strings for database storage +- **Union Types**: Uses modern PHP union types where appropriate (e.g., `mixed`, `string|null`) +- **PSR-4 Autoloading**: Namespace remains `Envms\FluentPDO` for compatibility +- **Iterator Support**: All query builders implement `IteratorAggregate` for direct iteration +- **Debugging**: Debug mode available via `$fluent->debug` property (mixed type) +- **Error Handling**: Exception handling configurable via `exceptionOnError` property +- **Fetch Modes**: Supports both object and array fetch modes with enhanced type safety + +## Fork Information + +This is a modernized fork of [envms/fluentpdo](https://github.com/envms/fluentpdo) (inactive since 2021). Changes include: +- PHP 8.1+ compatibility with modern type system +- Fixed array parameter handling (JSON serialization) +- Enhanced IDE support with proper type hints +- Updated development dependencies and tools diff --git a/composer.json b/composer.json index 8b2c70f..33b3d4f 100644 --- a/composer.json +++ b/composer.json @@ -1,26 +1,63 @@ { - "name": "envms/fluentpdo", - "description": "FluentPDO is a quick and light PHP library for rapid query building. It features a smart join builder, which automatically creates table joins.", - "keywords": ["db", "database", "dbal", "pdo", "fluent", "query", "builder", "mysql", "oracle"], - "homepage": "https://github.com/envms/fluentpdo", - "license": ["Apache-2.0", "GPL-2.0+"], - "authors": [ - { - "name": "envms", - "homepage": "https://env.ms" - } - ], - "autoload": { - "psr-4": { - "Envms\\FluentPDO\\": "src/" - } - }, + "name": "vitexsoftware/fluentpdo", + "description": "FluentPDO - PHP 8.1+ Edition. A modernized fork with strict typing, union types, and enhanced features. Quick and light PHP library for rapid query building with smart join builder.", + "type": "library", + "keywords": [ + "db", + "database", + "dbal", + "pdo", + "fluent", + "query", + "builder", + "mysql", + "oracle", + "mssql", + "php8", + "php81", + "strict-types", + "union-types", + "modern-php" + ], + "homepage": "https://github.com/VitexSoftware/php-vitexsoftware-fluentpdo", + "license": [ + "Apache-2.0", + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "envms", + "homepage": "https://env.ms" + }, + { + "name": "vitex", + "homepage": "https://vitexsoftware.com" + } + ], + "autoload": { + "psr-4": { + "Envms\\FluentPDO\\": "src/" + } + }, "require": { - "php": ">=7.1", + "php": ">=8.1", "ext-pdo": "*" }, - "require-dev": { - "phpunit/phpunit": "^8.0", - "envms/fluent-test": "^1.0" - } + "require-dev": { + "phpunit/phpunit": "^12.4", + "envms/fluent-test": "^1.0", + "roave/security-advisories": "dev-latest", + "phpstan/phpstan": "*", + "friendsofphp/php-cs-fixer": "^3.87", + "ergebnis/composer-normalize": "^2.48", + "ergebnis/php-cs-fixer-config": "^6.54" + }, + "config": { + "allow-plugins": { + "ergebnis/composer-normalize": true + } + }, + "replace": { + "envms/fluentpdo": "^2.2" + } } diff --git a/composer.lock b/composer.lock index 7143cb3..7378959 100644 --- a/composer.lock +++ b/composer.lock @@ -4,44 +4,35 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "43294b3845978b000b9d0d3002f2c3d3", + "content-hash": "80ad202d044bf390369c3e5409a17e28", "packages": [], "packages-dev": [ { - "name": "doctrine/instantiator", - "version": "1.3.1", + "name": "clue/ndjson-react", + "version": "v1.3.0", "source": { "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "f350df0268e904597e3bd9c4685c53e0e333feea" + "url": "https://github.com/clue/reactphp-ndjson.git", + "reference": "392dc165fce93b5bb5c637b67e59619223c931b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f350df0268e904597e3bd9c4685c53e0e333feea", - "reference": "f350df0268e904597e3bd9c4685c53e0e333feea", + "url": "https://api.github.com/repos/clue/reactphp-ndjson/zipball/392dc165fce93b5bb5c637b67e59619223c931b0", + "reference": "392dc165fce93b5bb5c637b67e59619223c931b0", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": ">=5.3", + "react/stream": "^1.2" }, "require-dev": { - "doctrine/coding-standard": "^6.0", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^0.13", - "phpstan/phpstan-phpunit": "^0.11", - "phpstan/phpstan-shim": "^0.11", - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35", + "react/event-loop": "^1.2" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, "autoload": { "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + "Clue\\React\\NDJson\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -50,255 +41,358 @@ ], "authors": [ { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" + "name": "Christian Lück", + "email": "christian@clue.engineering" } ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "description": "Streaming newline-delimited JSON (NDJSON) parser and encoder for ReactPHP.", + "homepage": "https://github.com/clue/reactphp-ndjson", "keywords": [ - "constructor", - "instantiate" + "NDJSON", + "json", + "jsonlines", + "newline", + "reactphp", + "streaming" ], + "support": { + "issues": "https://github.com/clue/reactphp-ndjson/issues", + "source": "https://github.com/clue/reactphp-ndjson/tree/v1.3.0" + }, "funding": [ { - "url": "https://www.doctrine-project.org/sponsorship.html", + "url": "https://clue.engineering/support", "type": "custom" }, { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" + "url": "https://github.com/clue", + "type": "github" } ], - "time": "2020-05-29T17:27:14+00:00" + "time": "2022-12-23T10:58:28+00:00" }, { - "name": "envms/fluent-test", - "version": "v1.0.1", + "name": "composer/pcre", + "version": "3.3.2", "source": { "type": "git", - "url": "https://github.com/envms/fluent-test.git", - "reference": "2db2a96ce65f64b7c6328040b7da5d2240782f23" + "url": "https://github.com/composer/pcre.git", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/envms/fluent-test/zipball/2db2a96ce65f64b7c6328040b7da5d2240782f23", - "reference": "2db2a96ce65f64b7c6328040b7da5d2240782f23", + "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", "shasum": "" }, + "require": { + "php": "^7.4 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<1.11.10" + }, + "require-dev": { + "phpstan/phpstan": "^1.12 || ^2", + "phpstan/phpstan-strict-rules": "^1 || ^2", + "phpunit/phpunit": "^8 || ^9" + }, "type": "library", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-main": "3.x-dev" + } + }, "autoload": { "psr-4": { - "Envms\\FluentTest\\": "src/" + "Composer\\Pcre\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "Apache-2.0", - "GPL-2.0+" + "MIT" ], "authors": [ { - "name": "envms", - "homepage": "http://env.ms" + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" } ], - "description": "A library for testing FluentPDO with mock data and classes", - "homepage": "https://github.com/envms/fluent-test", + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", "keywords": [ - "fluentpdo", - "library", - "test" + "PCRE", + "preg", + "regex", + "regular expression" ], - "time": "2018-08-23T17:42:04+00:00" + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.3.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-11-12T16:29:46+00:00" }, { - "name": "myclabs/deep-copy", - "version": "1.10.1", + "name": "composer/semver", + "version": "3.4.4", "source": { "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "969b211f9a51aa1f6c01d1d2aef56d3bd91598e5" + "url": "https://github.com/composer/semver.git", + "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/969b211f9a51aa1f6c01d1d2aef56d3bd91598e5", - "reference": "969b211f9a51aa1f6c01d1d2aef56d3bd91598e5", + "url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95", + "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" - }, - "replace": { - "myclabs/deep-copy": "self.version" + "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^7.1" + "phpstan/phpstan": "^1.11", + "symfony/phpunit-bridge": "^3 || ^7" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, "autoload": { "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - }, - "files": [ - "src/DeepCopy/deep_copy.php" - ] + "Composer\\Semver\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Create deep copies (clones) of your objects", + "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": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" + "semantic", + "semver", + "validation", + "versioning" ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.4" + }, "funding": [ { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" } ], - "time": "2020-06-29T13:22:24+00:00" + "time": "2025-08-20T19:15:30+00:00" }, { - "name": "phar-io/manifest", - "version": "1.0.3", + "name": "composer/xdebug-handler", + "version": "3.0.5", "source": { "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", - "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-phar": "*", - "phar-io/version": "^2.0", - "php": "^5.6 || ^7.0" + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" }, + "type": "library", "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" }, { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" + "url": "https://github.com/composer", + "type": "github" }, { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" } ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "time": "2018-07-08T19:23:20+00:00" + "time": "2024-05-06T16:37:16+00:00" }, { - "name": "phar-io/version", - "version": "2.0.1", + "name": "envms/fluent-test", + "version": "v1.0.1", "source": { "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" + "url": "https://github.com/envms/fluent-test.git", + "reference": "2db2a96ce65f64b7c6328040b7da5d2240782f23" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", - "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "url": "https://api.github.com/repos/envms/fluent-test/zipball/2db2a96ce65f64b7c6328040b7da5d2240782f23", + "reference": "2db2a96ce65f64b7c6328040b7da5d2240782f23", "shasum": "" }, - "require": { - "php": "^5.6 || ^7.0" - }, "type": "library", "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Envms\\FluentTest\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "Apache-2.0", + "GPL-2.0+" ], "authors": [ { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" + "name": "envms", + "homepage": "http://env.ms" } ], - "description": "Library for handling version information and constraints", - "time": "2018-07-08T19:19:57+00:00" + "description": "A library for testing FluentPDO with mock data and classes", + "homepage": "https://github.com/envms/fluent-test", + "keywords": [ + "fluentpdo", + "library", + "test" + ], + "support": { + "issues": "https://github.com/envms/fluent-test/issues", + "source": "https://github.com/envms/fluent-test/tree/v1.0.1" + }, + "time": "2018-08-23T17:42:04+00:00" }, { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", + "name": "ergebnis/composer-normalize", + "version": "2.48.2", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + "url": "https://github.com/ergebnis/composer-normalize.git", + "reference": "86dc9731b8320f49e9be9ad6d8e4de9b8b0e9b8b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "url": "https://api.github.com/repos/ergebnis/composer-normalize/zipball/86dc9731b8320f49e9be9ad6d8e4de9b8b0e9b8b", + "reference": "86dc9731b8320f49e9be9ad6d8e4de9b8b0e9b8b", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "composer-plugin-api": "^2.0.0", + "ergebnis/json": "^1.4.0", + "ergebnis/json-normalizer": "^4.9.0", + "ergebnis/json-printer": "^3.7.0", + "ext-json": "*", + "justinrainbow/json-schema": "^5.2.12 || ^6.0.0", + "localheinz/diff": "^1.3.0", + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, - "type": "library", + "require-dev": { + "composer/composer": "^2.8.3", + "ergebnis/license": "^2.7.0", + "ergebnis/php-cs-fixer-config": "^6.53.0", + "ergebnis/phpstan-rules": "^2.11.0", + "ergebnis/phpunit-slow-test-detector": "^2.20.0", + "fakerphp/faker": "^1.24.1", + "infection/infection": "~0.26.6", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpstan/phpstan-phpunit": "^2.0.7", + "phpstan/phpstan-strict-rules": "^2.0.6", + "phpunit/phpunit": "^9.6.20", + "rector/rector": "^2.1.4", + "symfony/filesystem": "^5.4.41" + }, + "type": "composer-plugin", "extra": { + "class": "Ergebnis\\Composer\\Normalize\\NormalizePlugin", "branch-alias": { - "dev-2.x": "2.x-dev" + "dev-main": "2.49-dev" + }, + "plugin-optional": true, + "composer-normalize": { + "indent-size": 2, + "indent-style": "space" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": "src/" + "Ergebnis\\Composer\\Normalize\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -307,54 +401,74 @@ ], "authors": [ { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" + "name": "Andreas Möller", + "email": "am@localheinz.com", + "homepage": "https://localheinz.com" } ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", + "description": "Provides a composer plugin for normalizing composer.json.", + "homepage": "https://github.com/ergebnis/composer-normalize", "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" + "composer", + "normalize", + "normalizer", + "plugin" ], - "time": "2020-06-27T09:03:43+00:00" + "support": { + "issues": "https://github.com/ergebnis/composer-normalize/issues", + "security": "https://github.com/ergebnis/composer-normalize/blob/main/.github/SECURITY.md", + "source": "https://github.com/ergebnis/composer-normalize" + }, + "time": "2025-09-06T11:42:34+00:00" }, { - "name": "phpdocumentor/reflection-docblock", - "version": "5.2.1", + "name": "ergebnis/json", + "version": "1.6.0", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "d870572532cd70bc3fab58f2e23ad423c8404c44" + "url": "https://github.com/ergebnis/json.git", + "reference": "7b56d2b5d9e897e75b43e2e753075a0904c921b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d870572532cd70bc3fab58f2e23ad423c8404c44", - "reference": "d870572532cd70bc3fab58f2e23ad423c8404c44", + "url": "https://api.github.com/repos/ergebnis/json/zipball/7b56d2b5d9e897e75b43e2e753075a0904c921b1", + "reference": "7b56d2b5d9e897e75b43e2e753075a0904c921b1", "shasum": "" }, "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" + "ext-json": "*", + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "require-dev": { - "mockery/mockery": "~1.3.2" + "ergebnis/composer-normalize": "^2.44.0", + "ergebnis/data-provider": "^3.3.0", + "ergebnis/license": "^2.5.0", + "ergebnis/php-cs-fixer-config": "^6.37.0", + "ergebnis/phpstan-rules": "^2.11.0", + "ergebnis/phpunit-slow-test-detector": "^2.16.1", + "fakerphp/faker": "^1.24.0", + "infection/infection": "~0.26.6", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.1.22", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpstan/phpstan-phpunit": "^2.0.7", + "phpstan/phpstan-strict-rules": "^2.0.6", + "phpunit/phpunit": "^9.6.24", + "rector/rector": "^2.1.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.x-dev" + "dev-main": "1.7-dev" + }, + "composer-normalize": { + "indent-size": 2, + "indent-style": "space" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": "src" + "Ergebnis\\Json\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -363,47 +477,79 @@ ], "authors": [ { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" + "name": "Andreas Möller", + "email": "am@localheinz.com", + "homepage": "https://localheinz.com" } ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2020-08-15T11:14:08+00:00" + "description": "Provides a Json value object for representing a valid JSON string.", + "homepage": "https://github.com/ergebnis/json", + "keywords": [ + "json" + ], + "support": { + "issues": "https://github.com/ergebnis/json/issues", + "security": "https://github.com/ergebnis/json/blob/main/.github/SECURITY.md", + "source": "https://github.com/ergebnis/json" + }, + "time": "2025-09-06T09:08:45+00:00" }, { - "name": "phpdocumentor/type-resolver", - "version": "1.3.0", + "name": "ergebnis/json-normalizer", + "version": "4.10.1", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "e878a14a65245fbe78f8080eba03b47c3b705651" + "url": "https://github.com/ergebnis/json-normalizer.git", + "reference": "77961faf2c651c3f05977b53c6c68e8434febf62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e878a14a65245fbe78f8080eba03b47c3b705651", - "reference": "e878a14a65245fbe78f8080eba03b47c3b705651", + "url": "https://api.github.com/repos/ergebnis/json-normalizer/zipball/77961faf2c651c3f05977b53c6c68e8434febf62", + "reference": "77961faf2c651c3f05977b53c6c68e8434febf62", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" + "ergebnis/json": "^1.2.0", + "ergebnis/json-pointer": "^3.4.0", + "ergebnis/json-printer": "^3.5.0", + "ergebnis/json-schema-validator": "^4.2.0", + "ext-json": "*", + "justinrainbow/json-schema": "^5.2.12 || ^6.0.0", + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "require-dev": { - "ext-tokenizer": "*" + "composer/semver": "^3.4.3", + "ergebnis/composer-normalize": "^2.44.0", + "ergebnis/data-provider": "^3.3.0", + "ergebnis/license": "^2.5.0", + "ergebnis/php-cs-fixer-config": "^6.37.0", + "ergebnis/phpunit-slow-test-detector": "^2.16.1", + "fakerphp/faker": "^1.24.0", + "infection/infection": "~0.26.6", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.10", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.1", + "phpunit/phpunit": "^9.6.19", + "rector/rector": "^1.2.10" + }, + "suggest": { + "composer/semver": "If you want to use ComposerJsonNormalizer or VersionConstraintNormalizer" }, "type": "library", "extra": { "branch-alias": { - "dev-1.x": "1.x-dev" + "dev-main": "4.11-dev" + }, + "composer-normalize": { + "indent-size": 2, + "indent-style": "space" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": "src" + "Ergebnis\\Json\\Normalizer\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -412,47 +558,70 @@ ], "authors": [ { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" + "name": "Andreas Möller", + "email": "am@localheinz.com", + "homepage": "https://localheinz.com" } ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "time": "2020-06-27T10:12:23+00:00" + "description": "Provides generic and vendor-specific normalizers for normalizing JSON documents.", + "homepage": "https://github.com/ergebnis/json-normalizer", + "keywords": [ + "json", + "normalizer" + ], + "support": { + "issues": "https://github.com/ergebnis/json-normalizer/issues", + "security": "https://github.com/ergebnis/json-normalizer/blob/main/.github/SECURITY.md", + "source": "https://github.com/ergebnis/json-normalizer" + }, + "time": "2025-09-06T09:18:13+00:00" }, { - "name": "phpspec/prophecy", - "version": "1.11.1", + "name": "ergebnis/json-pointer", + "version": "3.7.1", "source": { "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "b20034be5efcdab4fb60ca3a29cba2949aead160" + "url": "https://github.com/ergebnis/json-pointer.git", + "reference": "43bef355184e9542635e35dd2705910a3df4c236" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/b20034be5efcdab4fb60ca3a29cba2949aead160", - "reference": "b20034be5efcdab4fb60ca3a29cba2949aead160", + "url": "https://api.github.com/repos/ergebnis/json-pointer/zipball/43bef355184e9542635e35dd2705910a3df4c236", + "reference": "43bef355184e9542635e35dd2705910a3df4c236", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.2", - "php": "^7.2", - "phpdocumentor/reflection-docblock": "^5.0", - "sebastian/comparator": "^3.0 || ^4.0", - "sebastian/recursion-context": "^3.0 || ^4.0" + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "require-dev": { - "phpspec/phpspec": "^6.0", - "phpunit/phpunit": "^8.0" + "ergebnis/composer-normalize": "^2.43.0", + "ergebnis/data-provider": "^3.2.0", + "ergebnis/license": "^2.4.0", + "ergebnis/php-cs-fixer-config": "^6.32.0", + "ergebnis/phpunit-slow-test-detector": "^2.15.0", + "fakerphp/faker": "^1.23.1", + "infection/infection": "~0.26.6", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.10", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.1", + "phpunit/phpunit": "^9.6.19", + "rector/rector": "^1.2.10" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11.x-dev" + "dev-main": "3.8-dev" + }, + "composer-normalize": { + "indent-size": 2, + "indent-style": "space" } }, "autoload": { "psr-4": { - "Prophecy\\": "src/Prophecy" + "Ergebnis\\Json\\Pointer\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -461,567 +630,676 @@ ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" + "name": "Andreas Möller", + "email": "am@localheinz.com", + "homepage": "https://localheinz.com" } ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", + "description": "Provides an abstraction of a JSON pointer.", + "homepage": "https://github.com/ergebnis/json-pointer", "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" + "RFC6901", + "json", + "pointer" ], - "time": "2020-07-08T12:44:21+00:00" + "support": { + "issues": "https://github.com/ergebnis/json-pointer/issues", + "security": "https://github.com/ergebnis/json-pointer/blob/main/.github/SECURITY.md", + "source": "https://github.com/ergebnis/json-pointer" + }, + "time": "2025-09-06T09:28:19+00:00" }, { - "name": "phpunit/php-code-coverage", - "version": "7.0.10", + "name": "ergebnis/json-printer", + "version": "3.8.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "f1884187926fbb755a9aaf0b3836ad3165b478bf" + "url": "https://github.com/ergebnis/json-printer.git", + "reference": "211d73fc7ec6daf98568ee6ed6e6d133dee8503e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f1884187926fbb755a9aaf0b3836ad3165b478bf", - "reference": "f1884187926fbb755a9aaf0b3836ad3165b478bf", + "url": "https://api.github.com/repos/ergebnis/json-printer/zipball/211d73fc7ec6daf98568ee6ed6e6d133dee8503e", + "reference": "211d73fc7ec6daf98568ee6ed6e6d133dee8503e", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-xmlwriter": "*", - "php": "^7.2", - "phpunit/php-file-iterator": "^2.0.2", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^3.1.1", - "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^4.2.2", - "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1.3" + "ext-json": "*", + "ext-mbstring": "*", + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "require-dev": { - "phpunit/phpunit": "^8.2.2" - }, - "suggest": { - "ext-xdebug": "^2.7.2" + "ergebnis/composer-normalize": "^2.44.0", + "ergebnis/data-provider": "^3.3.0", + "ergebnis/license": "^2.5.0", + "ergebnis/php-cs-fixer-config": "^6.37.0", + "ergebnis/phpunit-slow-test-detector": "^2.16.1", + "fakerphp/faker": "^1.24.0", + "infection/infection": "~0.26.6", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.10", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.1", + "phpstan/phpstan-strict-rules": "^1.6.1", + "phpunit/phpunit": "^9.6.21", + "rector/rector": "^1.2.10" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "7.0-dev" + "dev-main": "3.9-dev" + }, + "composer-normalize": { + "indent-size": 2, + "indent-style": "space" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Ergebnis\\Json\\Printer\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Andreas Möller", + "email": "am@localheinz.com", + "homepage": "https://localheinz.com" } ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "description": "Provides a JSON printer, allowing for flexible indentation.", + "homepage": "https://github.com/ergebnis/json-printer", "keywords": [ - "coverage", - "testing", - "xunit" + "formatter", + "json", + "printer" ], - "time": "2019-11-20T13:55:58+00:00" + "support": { + "issues": "https://github.com/ergebnis/json-printer/issues", + "security": "https://github.com/ergebnis/json-printer/blob/main/.github/SECURITY.md", + "source": "https://github.com/ergebnis/json-printer" + }, + "time": "2025-09-06T09:59:26+00:00" }, { - "name": "phpunit/php-file-iterator", - "version": "2.0.2", + "name": "ergebnis/json-schema-validator", + "version": "4.5.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "050bedf145a257b1ff02746c31894800e5122946" + "url": "https://github.com/ergebnis/json-schema-validator.git", + "reference": "b739527a480a9e3651360ad351ea77e7e9019df2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946", - "reference": "050bedf145a257b1ff02746c31894800e5122946", + "url": "https://api.github.com/repos/ergebnis/json-schema-validator/zipball/b739527a480a9e3651360ad351ea77e7e9019df2", + "reference": "b739527a480a9e3651360ad351ea77e7e9019df2", "shasum": "" }, "require": { - "php": "^7.1" + "ergebnis/json": "^1.2.0", + "ergebnis/json-pointer": "^3.4.0", + "ext-json": "*", + "justinrainbow/json-schema": "^5.2.12 || ^6.0.0", + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "require-dev": { - "phpunit/phpunit": "^7.1" + "ergebnis/composer-normalize": "^2.44.0", + "ergebnis/data-provider": "^3.3.0", + "ergebnis/license": "^2.5.0", + "ergebnis/php-cs-fixer-config": "^6.37.0", + "ergebnis/phpunit-slow-test-detector": "^2.16.1", + "fakerphp/faker": "^1.24.0", + "infection/infection": "~0.26.6", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.10", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.1", + "phpunit/phpunit": "^9.6.20", + "rector/rector": "^1.2.10" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-main": "4.6-dev" + }, + "composer-normalize": { + "indent-size": 2, + "indent-style": "space" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Ergebnis\\Json\\SchemaValidator\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Andreas Möller", + "email": "am@localheinz.com", + "homepage": "https://localheinz.com" } ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "description": "Provides a JSON schema validator, building on top of justinrainbow/json-schema.", + "homepage": "https://github.com/ergebnis/json-schema-validator", "keywords": [ - "filesystem", - "iterator" + "json", + "schema", + "validator" ], - "time": "2018-09-13T20:33:42+00:00" + "support": { + "issues": "https://github.com/ergebnis/json-schema-validator/issues", + "security": "https://github.com/ergebnis/json-schema-validator/blob/main/.github/SECURITY.md", + "source": "https://github.com/ergebnis/json-schema-validator" + }, + "time": "2025-09-06T11:37:35+00:00" }, { - "name": "phpunit/php-text-template", - "version": "1.2.1", + "name": "ergebnis/php-cs-fixer-config", + "version": "6.55.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + "url": "https://github.com/ergebnis/php-cs-fixer-config.git", + "reference": "e43a11451c844ca2cbcb826c7d3e14553f914532" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "url": "https://api.github.com/repos/ergebnis/php-cs-fixer-config/zipball/e43a11451c844ca2cbcb826c7d3e14553f914532", + "reference": "e43a11451c844ca2cbcb826c7d3e14553f914532", "shasum": "" }, "require": { - "php": ">=5.3.3" + "erickskrauch/php-cs-fixer-custom-fixers": "~1.3.0", + "ext-filter": "*", + "friendsofphp/php-cs-fixer": "~3.88.2", + "kubawerlos/php-cs-fixer-custom-fixers": "~3.35.1", + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.48.2", + "ergebnis/data-provider": "^3.6.0", + "ergebnis/license": "^2.7.0", + "ergebnis/phpstan-rules": "^2.12.0", + "ergebnis/phpunit-slow-test-detector": "^2.20.0", + "ergebnis/rector-rules": "^1.6.0", + "fakerphp/faker": "^1.24.1", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.1.29", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpstan/phpstan-phpunit": "^2.0.7", + "phpstan/phpstan-strict-rules": "^2.0.7", + "phpunit/phpunit": "^9.6.22", + "rector/rector": "^2.1.7", + "symfony/filesystem": "^5.0.0 || ^6.0.0", + "symfony/process": "^5.0.0 || ^6.0.0" }, "type": "library", + "extra": { + "composer-normalize": { + "indent-size": 2, + "indent-style": "space" + } + }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Ergebnis\\PhpCsFixer\\Config\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Andreas Möller", + "email": "am@localheinz.com", + "homepage": "https://localheinz.com" } ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "time": "2015-06-21T13:50:34+00:00" + "description": "Provides a configuration factory and rule set factories for friendsofphp/php-cs-fixer.", + "homepage": "https://github.com/ergebnis/php-cs-fixer-config", + "support": { + "issues": "https://github.com/ergebnis/php-cs-fixer-config/issues", + "security": "https://github.com/ergebnis/php-cs-fixer-config/blob/main/.github/SECURITY.md", + "source": "https://github.com/ergebnis/php-cs-fixer-config" + }, + "time": "2025-10-01T13:54:12+00:00" }, { - "name": "phpunit/php-timer", - "version": "2.1.2", + "name": "erickskrauch/php-cs-fixer-custom-fixers", + "version": "1.3.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "1038454804406b0b5f5f520358e78c1c2f71501e" + "url": "https://github.com/erickskrauch/php-cs-fixer-custom-fixers.git", + "reference": "36fb7f8204c1e17d9b8a24910e2147d0a3973b9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1038454804406b0b5f5f520358e78c1c2f71501e", - "reference": "1038454804406b0b5f5f520358e78c1c2f71501e", + "url": "https://api.github.com/repos/erickskrauch/php-cs-fixer-custom-fixers/zipball/36fb7f8204c1e17d9b8a24910e2147d0a3973b9c", + "reference": "36fb7f8204c1e17d9b8a24910e2147d0a3973b9c", "shasum": "" }, "require": { - "php": "^7.1" + "friendsofphp/php-cs-fixer": "^3", + "php": "^7.4 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "ely/php-code-style": "^1", + "ergebnis/composer-normalize": "^2.28", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", + "phpspec/prophecy": "^1.15", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/extension-installer": "^1.3", + "phpstan/phpstan": "^1.11.x-dev", + "phpstan/phpstan-phpunit": "^1.3", + "phpstan/phpstan-strict-rules": "^1.5", + "phpunit/phpunit": "^9.5", + "phpunitgoodpractices/polyfill": "^1.5", + "phpunitgoodpractices/traits": "^1.9.1", + "symfony/phpunit-bridge": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "1.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "ErickSkrauch\\PhpCsFixer\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "ErickSkrauch", + "email": "erickskrauch@ely.by" } ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", + "description": "A set of custom fixers for PHP-CS-Fixer", + "homepage": "https://github.com/erickskrauch/php-cs-fixer-custom-fixers", "keywords": [ - "timer" + "Code style", + "dev", + "php-cs-fixer" ], - "time": "2019-06-07T04:22:29+00:00" + "support": { + "issues": "https://github.com/erickskrauch/php-cs-fixer-custom-fixers/issues", + "source": "https://github.com/erickskrauch/php-cs-fixer-custom-fixers/tree/1.3.0" + }, + "time": "2024-06-21T20:19:52+00:00" }, { - "name": "phpunit/php-token-stream", - "version": "3.1.1", + "name": "evenement/evenement", + "version": "v3.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff" + "url": "https://github.com/igorw/evenement.git", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/995192df77f63a59e47f025390d2d1fdf8f425ff", - "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff", + "url": "https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": "^7.1" + "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^9 || ^6" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Evenement\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" } ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "description": "Événement is a very simple event dispatching library for PHP", "keywords": [ - "tokenizer" + "event-dispatcher", + "event-emitter" ], - "abandoned": true, - "time": "2019-09-17T06:23:10+00:00" + "support": { + "issues": "https://github.com/igorw/evenement/issues", + "source": "https://github.com/igorw/evenement/tree/v3.0.2" + }, + "time": "2023-08-08T05:53:35+00:00" }, { - "name": "phpunit/phpunit", - "version": "8.5.8", + "name": "fidry/cpu-core-counter", + "version": "1.3.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "34c18baa6a44f1d1fbf0338907139e9dce95b997" + "url": "https://github.com/theofidry/cpu-core-counter.git", + "reference": "db9508f7b1474469d9d3c53b86f817e344732678" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/34c18baa6a44f1d1fbf0338907139e9dce95b997", - "reference": "34c18baa6a44f1d1fbf0338907139e9dce95b997", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678", + "reference": "db9508f7b1474469d9d3c53b86f817e344732678", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.2.0", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.9.1", - "phar-io/manifest": "^1.0.3", - "phar-io/version": "^2.0.1", - "php": "^7.2", - "phpspec/prophecy": "^1.8.1", - "phpunit/php-code-coverage": "^7.0.7", - "phpunit/php-file-iterator": "^2.0.2", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^2.1.2", - "sebastian/comparator": "^3.0.2", - "sebastian/diff": "^3.0.2", - "sebastian/environment": "^4.2.2", - "sebastian/exporter": "^3.1.1", - "sebastian/global-state": "^3.0.0", - "sebastian/object-enumerator": "^3.0.3", - "sebastian/resource-operations": "^2.0.1", - "sebastian/type": "^1.1.3", - "sebastian/version": "^2.0.1" + "php": "^7.2 || ^8.0" }, "require-dev": { - "ext-pdo": "*" - }, - "suggest": { - "ext-soap": "*", - "ext-xdebug": "*", - "phpunit/php-invoker": "^2.0.0" + "fidry/makefile": "^0.2.0", + "fidry/php-cs-fixer-config": "^1.1.2", + "phpstan/extension-installer": "^1.2.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-deprecation-rules": "^2.0.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^8.5.31 || ^9.5.26", + "webmozarts/strict-phpunit": "^7.5" }, - "bin": [ - "phpunit" - ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "8.5-dev" - } - }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Fidry\\CpuCoreCounter\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com" } ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", + "description": "Tiny utility to get the number of CPU cores.", "keywords": [ - "phpunit", - "testing", - "xunit" + "CPU", + "core" ], + "support": { + "issues": "https://github.com/theofidry/cpu-core-counter/issues", + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0" + }, "funding": [ { - "url": "https://phpunit.de/donate.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/theofidry", "type": "github" } ], - "time": "2020-06-22T07:06:58+00:00" + "time": "2025-08-14T07:29:31+00:00" }, { - "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.1", + "name": "friendsofphp/php-cs-fixer", + "version": "v3.88.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" + "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", + "reference": "a8d15584bafb0f0d9d938827840060fd4a3ebc99" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/a8d15584bafb0f0d9d938827840060fd4a3ebc99", + "reference": "a8d15584bafb0f0d9d938827840060fd4a3ebc99", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "clue/ndjson-react": "^1.3", + "composer/semver": "^3.4", + "composer/xdebug-handler": "^3.0.5", + "ext-filter": "*", + "ext-hash": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "fidry/cpu-core-counter": "^1.3", + "php": "^7.4 || ^8.0", + "react/child-process": "^0.6.6", + "react/event-loop": "^1.5", + "react/promise": "^3.3", + "react/socket": "^1.16", + "react/stream": "^1.4", + "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0", + "symfony/console": "^5.4.47 || ^6.4.24 || ^7.0", + "symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0", + "symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0", + "symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0", + "symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0", + "symfony/polyfill-mbstring": "^1.33", + "symfony/polyfill-php80": "^1.33", + "symfony/polyfill-php81": "^1.33", + "symfony/polyfill-php84": "^1.33", + "symfony/process": "^5.4.47 || ^6.4.24 || ^7.2", + "symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.0" + "facile-it/paraunit": "^1.3.1 || ^2.7", + "infection/infection": "^0.31.0", + "justinrainbow/json-schema": "^6.5", + "keradus/cli-executor": "^2.2", + "mikey179/vfsstream": "^1.6.12", + "php-coveralls/php-coveralls": "^2.8", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6", + "phpunit/phpunit": "^9.6.25 || ^10.5.53 || ^11.5.34", + "symfony/var-dumper": "^5.4.48 || ^6.4.24 || ^7.3.2", + "symfony/yaml": "^5.4.45 || ^6.4.24 || ^7.3.2" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } + "suggest": { + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters." }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", "autoload": { - "classmap": [ - "src/" + "psr-4": { + "PhpCsFixer\\": "src/" + }, + "exclude-from-classmap": [ + "src/Fixer/Internal/*" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "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", + "keywords": [ + "Static code analysis", + "fixer", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.88.2" + }, + "funding": [ + { + "url": "https://github.com/keradus", + "type": "github" } ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2017-03-04T06:30:41+00:00" + "time": "2025-09-27T00:24:15+00:00" }, { - "name": "sebastian/comparator", - "version": "3.0.2", + "name": "justinrainbow/json-schema", + "version": "6.6.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" + "url": "https://github.com/jsonrainbow/json-schema.git", + "reference": "68ba7677532803cc0c5900dd5a4d730537f2b2f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", - "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/68ba7677532803cc0c5900dd5a4d730537f2b2f3", + "reference": "68ba7677532803cc0c5900dd5a4d730537f2b2f3", "shasum": "" }, "require": { - "php": "^7.1", - "sebastian/diff": "^3.0", - "sebastian/exporter": "^3.1" + "ext-json": "*", + "marc-mabe/php-enum": "^4.0", + "php": "^7.2 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^7.1" + "friendsofphp/php-cs-fixer": "3.3.0", + "json-schema/json-schema-test-suite": "^23.2", + "marc-mabe/php-enum-phpstan": "^2.0", + "phpspec/prophecy": "^1.19", + "phpstan/phpstan": "^1.12", + "phpunit/phpunit": "^8.5" }, + "bin": [ + "bin/validate-json" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "6.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "JsonSchema\\": "src/JsonSchema/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" + "name": "Bruno Prieto Reis", + "email": "bruno.p.reis@gmail.com" }, { - "name": "Volker Dusch", - "email": "github@wallbash.com" + "name": "Justin Rainbow", + "email": "justin.rainbow@gmail.com" }, { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" }, { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Robert Schönthal", + "email": "seroscho@googlemail.com" } ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", + "description": "A library to validate a json schema.", + "homepage": "https://github.com/jsonrainbow/json-schema", "keywords": [ - "comparator", - "compare", - "equality" + "json", + "schema" ], - "time": "2018-07-12T15:12:46+00:00" + "support": { + "issues": "https://github.com/jsonrainbow/json-schema/issues", + "source": "https://github.com/jsonrainbow/json-schema/tree/6.6.0" + }, + "time": "2025-10-10T11:34:09+00:00" }, { - "name": "sebastian/diff", - "version": "3.0.2", + "name": "kubawerlos/php-cs-fixer-custom-fixers", + "version": "v3.35.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29" + "url": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers.git", + "reference": "2a35f80ae24ca77443a7af1599c3a3db1b6bd395" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29", - "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29", + "url": "https://api.github.com/repos/kubawerlos/php-cs-fixer-custom-fixers/zipball/2a35f80ae24ca77443a7af1599c3a3db1b6bd395", + "reference": "2a35f80ae24ca77443a7af1599c3a3db1b6bd395", "shasum": "" }, "require": { - "php": "^7.1" + "ext-filter": "*", + "ext-tokenizer": "*", + "friendsofphp/php-cs-fixer": "^3.87", + "php": "^7.4 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.0", - "symfony/process": "^2 || ^3.3 || ^4" + "phpunit/phpunit": "^9.6.24 || ^10.5.51 || ^11.5.32" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "PhpCsFixerCustomFixers\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Kuba Werłos", + "email": "werlos@gmail.com" } ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" + "description": "A set of custom fixers for PHP CS Fixer", + "support": { + "issues": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers/issues", + "source": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers/tree/v3.35.1" + }, + "funding": [ + { + "url": "https://github.com/kubawerlos", + "type": "github" + } ], - "time": "2019-02-04T06:01:07+00:00" + "time": "2025-09-28T18:43:35+00:00" }, { - "name": "sebastian/environment", - "version": "4.2.3", + "name": "localheinz/diff", + "version": "1.3.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368" + "url": "https://github.com/localheinz/diff.git", + "reference": "33bd840935970cda6691c23fc7d94ae764c0734c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/464c90d7bdf5ad4e8a6aea15c091fec0603d4368", - "reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368", + "url": "https://api.github.com/repos/localheinz/diff/zipball/33bd840935970cda6691c23fc7d94ae764c0734c", + "reference": "33bd840935970cda6691c23fc7d94ae764c0734c", "shasum": "" }, "require": { - "php": "^7.1" + "php": "~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "require-dev": { - "phpunit/phpunit": "^7.5" - }, - "suggest": { - "ext-posix": "*" + "phpunit/phpunit": "^7.5.0 || ^8.5.23", + "symfony/process": "^4.2 || ^5" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.2-dev" - } - }, "autoload": { "classmap": [ "src/" @@ -1035,48 +1313,63 @@ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" } ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", + "description": "Fork of sebastian/diff for use with ergebnis/composer-normalize", + "homepage": "https://github.com/localheinz/diff", "keywords": [ - "Xdebug", - "environment", - "hhvm" + "diff", + "udiff", + "unidiff", + "unified diff" ], - "time": "2019-11-20T08:46:58+00:00" + "support": { + "issues": "https://github.com/localheinz/diff/issues", + "source": "https://github.com/localheinz/diff/tree/1.3.0" + }, + "time": "2025-08-30T09:44:18+00:00" }, { - "name": "sebastian/exporter", - "version": "3.1.2", + "name": "marc-mabe/php-enum", + "version": "v4.7.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e" + "url": "https://github.com/marc-mabe/php-enum.git", + "reference": "bb426fcdd65c60fb3638ef741e8782508fda7eef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/68609e1261d215ea5b21b7987539cbfbe156ec3e", - "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e", + "url": "https://api.github.com/repos/marc-mabe/php-enum/zipball/bb426fcdd65c60fb3638ef741e8782508fda7eef", + "reference": "bb426fcdd65c60fb3638ef741e8782508fda7eef", "shasum": "" }, "require": { - "php": "^7.0", - "sebastian/recursion-context": "^3.0" + "ext-reflection": "*", + "php": "^7.1 | ^8.0" }, "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^6.0" + "phpbench/phpbench": "^0.16.10 || ^1.0.4", + "phpstan/phpstan": "^1.3.1", + "phpunit/phpunit": "^7.5.20 | ^8.5.22 | ^9.5.11", + "vimeo/psalm": "^4.17.0 | ^5.26.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-3.x": "3.2-dev", + "dev-master": "4.7-dev" } }, "autoload": { + "psr-4": { + "MabeEnum\\": "src/" + }, "classmap": [ - "src/" + "stubs/Stringable.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1085,120 +1378,131 @@ ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" + "name": "Marc Bennewitz", + "email": "dev@mabe.berlin", + "homepage": "https://mabe.berlin/", + "role": "Lead" } ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", + "description": "Simple and fast implementation of enumerations with native PHP", + "homepage": "https://github.com/marc-mabe/php-enum", "keywords": [ - "export", - "exporter" + "enum", + "enum-map", + "enum-set", + "enumeration", + "enumerator", + "enummap", + "enumset", + "map", + "set", + "type", + "type-hint", + "typehint" ], - "time": "2019-09-14T09:02:43+00:00" + "support": { + "issues": "https://github.com/marc-mabe/php-enum/issues", + "source": "https://github.com/marc-mabe/php-enum/tree/v4.7.2" + }, + "time": "2025-09-14T11:18:39+00:00" }, { - "name": "sebastian/global-state", - "version": "3.0.0", + "name": "myclabs/deep-copy", + "version": "1.13.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4" + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4", - "reference": "edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", "shasum": "" }, "require": { - "php": "^7.2", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" + "php": "^7.1 || ^8.0" }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^8.0" + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, - "suggest": { - "ext-uopz": "*" + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, "autoload": { - "classmap": [ - "src/" - ] + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", + "description": "Create deep copies (clones) of your objects", "keywords": [ - "global state" + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } ], - "time": "2019-02-01T05:30:01+00:00" + "time": "2025-08-01T08:46:24+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "3.0.3", + "name": "nikic/php-parser", + "version": "v5.6.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "3a454ca033b9e06b63282ce19562e892747449bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/3a454ca033b9e06b63282ce19562e892747449bb", + "reference": "3a454ca033b9e06b63282ce19562e892747449bb", "shasum": "" }, "require": { - "php": "^7.0", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" }, + "bin": [ + "bin/php-parse" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "5.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1206,38 +1510,46 @@ ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Nikita Popov" } ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-08-03T12:35:26+00:00" + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.2" + }, + "time": "2025-10-21T19:32:17+00:00" }, { - "name": "sebastian/object-reflector", - "version": "1.1.1", + "name": "phar-io/manifest", + "version": "2.0.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "773f97c67f28de00d397be301821b06708fca0be" + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", - "reference": "773f97c67f28de00d397be301821b06708fca0be", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", "shasum": "" }, "require": { - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1250,41 +1562,53 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "Developer" } ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "time": "2017-03-29T09:07:27+00:00" + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" }, { - "name": "sebastian/recursion-context", - "version": "3.0.0", + "name": "phar-io/version", + "version": "3.2.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" + "php": "^7.2 || ^8.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - }, "autoload": { "classmap": [ "src/" @@ -1296,88 +1620,120 @@ ], "authors": [ { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" }, { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" }, { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" } ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2017-03-03T06:23:57+00:00" + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" }, { - "name": "sebastian/resource-operations", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9" - }, + "name": "phpstan/phpstan", + "version": "2.1.31", "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9", - "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/ead89849d879fe203ce9292c6ef5e7e76f867b96", + "reference": "ead89849d879fe203ce9292c6ef5e7e76f867b96", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.4|^8.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } + "conflict": { + "phpstan/phpstan-shim": "*" }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", "autoload": { - "classmap": [ - "src/" + "files": [ + "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], - "authors": [ + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" } ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2018-10-04T04:07:39+00:00" + "time": "2025-10-10T14:14:11+00:00" }, { - "name": "sebastian/type", - "version": "1.1.3", + "name": "phpunit/php-code-coverage", + "version": "12.4.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "3aaaa15fa71d27650d62a948be022fe3b48541a3" + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "67e8aed88f93d0e6e1cb7effe1a2dfc2fee6022c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/3aaaa15fa71d27650d62a948be022fe3b48541a3", - "reference": "3aaaa15fa71d27650d62a948be022fe3b48541a3", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/67e8aed88f93d0e6e1cb7effe1a2dfc2fee6022c", + "reference": "67e8aed88f93d0e6e1cb7effe1a2dfc2fee6022c", "shasum": "" }, "require": { - "php": "^7.2" + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^5.6.1", + "php": ">=8.3", + "phpunit/php-file-iterator": "^6.0", + "phpunit/php-text-template": "^5.0", + "sebastian/complexity": "^5.0", + "sebastian/environment": "^8.0.3", + "sebastian/lines-of-code": "^4.0", + "sebastian/version": "^6.0", + "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^8.2" + "phpunit/phpunit": "^12.3.7" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-main": "12.4.x-dev" } }, "autoload": { @@ -1396,31 +1752,62 @@ "role": "lead" } ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "time": "2019-07-02T08:10:15+00:00" + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.4.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage", + "type": "tidelift" + } + ], + "time": "2025-09-24T13:44:41+00:00" }, { - "name": "sebastian/version", - "version": "2.0.1", + "name": "phpunit/php-file-iterator", + "version": "6.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "961bc913d42fe24a257bfff826a5068079ac7782" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/961bc913d42fe24a257bfff826a5068079ac7782", + "reference": "961bc913d42fe24a257bfff826a5068079ac7782", "shasum": "" }, "require": { - "php": ">=5.6" + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -1439,107 +1826,115 @@ "role": "lead" } ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03T07:35:21+00:00" + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:58:37+00:00" }, { - "name": "symfony/polyfill-ctype", - "version": "v1.18.1", + "name": "phpunit/php-invoker", + "version": "6.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "1c302646f6efc070cd46856e600e5e0684d6b454" + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "12b54e689b07a25a9b41e57736dfab6ec9ae5406" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/1c302646f6efc070cd46856e600e5e0684d6b454", - "reference": "1c302646f6efc070cd46856e600e5e0684d6b454", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/12b54e689b07a25a9b41e57736dfab6ec9ae5406", + "reference": "12b54e689b07a25a9b41e57736dfab6ec9ae5406", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=8.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^12.0" }, "suggest": { - "ext-ctype": "For best performance" + "ext-pcntl": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.18-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "dev-main": "6.0-dev" } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, - "files": [ - "bootstrap.php" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" + "process" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/6.0.0" + }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2020-07-14T12:35:20+00:00" + "time": "2025-02-07T04:58:58+00:00" }, { - "name": "theseer/tokenizer", - "version": "1.2.0", + "name": "phpunit/php-text-template", + "version": "5.0.0", "source": { "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "75a63c33a8577608444246075ea0af0d052e452a" + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "e1367a453f0eda562eedb4f659e13aa900d66c53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/75a63c33a8577608444246075ea0af0d052e452a", - "reference": "75a63c33a8577608444246075ea0af0d052e452a", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/e1367a453f0eda562eedb4f659e13aa900d66c53", + "reference": "e1367a453f0eda562eedb4f659e13aa900d66c53", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -1551,49 +1946,372 @@ ], "authors": [ { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/5.0.0" + }, "funding": [ { - "url": "https://github.com/theseer", + "url": "https://github.com/sebastianbergmann", "type": "github" } ], - "time": "2020-07-12T23:59:07+00:00" + "time": "2025-02-07T04:59:16+00:00" }, { - "name": "webmozart/assert", - "version": "1.9.1", + "name": "phpunit/php-timer", + "version": "8.0.0", "source": { "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc", + "reference": "f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0 || ^8.0", - "symfony/polyfill-ctype": "^1.8" + "php": ">=8.3" }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<3.9.1" + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/8.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:59:38+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "12.4.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "fc5413a2e6d240d2f6d9317bdf7f0a24e73de194" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fc5413a2e6d240d2f6d9317bdf7f0a24e73de194", + "reference": "fc5413a2e6d240d2f6d9317bdf7f0a24e73de194", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.13.4", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.3", + "phpunit/php-code-coverage": "^12.4.0", + "phpunit/php-file-iterator": "^6.0.0", + "phpunit/php-invoker": "^6.0.0", + "phpunit/php-text-template": "^5.0.0", + "phpunit/php-timer": "^8.0.0", + "sebastian/cli-parser": "^4.2.0", + "sebastian/comparator": "^7.1.3", + "sebastian/diff": "^7.0.0", + "sebastian/environment": "^8.0.3", + "sebastian/exporter": "^7.0.2", + "sebastian/global-state": "^8.0.2", + "sebastian/object-enumerator": "^7.0.0", + "sebastian/type": "^6.0.3", + "sebastian/version": "^6.0.0", + "staabm/side-effects-detector": "^1.0.5" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "12.4-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/12.4.1" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2025-10-09T14:08:29+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "react/cache", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/cache.git", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/cache/zipball/d47c472b64aa5608225f47965a484b75c7817d5b", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "react/promise": "^3.0 || ^2.0 || ^1.1" }, "require-dev": { - "phpunit/phpunit": "^4.8.36 || ^7.5.13" + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35" }, "type": "library", "autoload": { "psr-4": { - "Webmozart\\Assert\\": "src/" + "React\\Cache\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1602,25 +2320,3903 @@ ], "authors": [ { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" } ], - "description": "Assertions to validate method input/output with nice error messages.", + "description": "Async, Promise-based cache interface for ReactPHP", "keywords": [ - "assert", - "check", - "validate" + "cache", + "caching", + "promise", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/cache/issues", + "source": "https://github.com/reactphp/cache/tree/v1.2.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2022-11-30T15:59:55+00:00" + }, + { + "name": "react/child-process", + "version": "v0.6.6", + "source": { + "type": "git", + "url": "https://github.com/reactphp/child-process.git", + "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/child-process/zipball/1721e2b93d89b745664353b9cfc8f155ba8a6159", + "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.0", + "react/event-loop": "^1.2", + "react/stream": "^1.4" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/socket": "^1.16", + "sebastian/environment": "^5.0 || ^3.0 || ^2.0 || ^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\ChildProcess\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven library for executing child processes with ReactPHP.", + "keywords": [ + "event-driven", + "process", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/child-process/issues", + "source": "https://github.com/reactphp/child-process/tree/v0.6.6" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2025-01-01T16:37:48+00:00" + }, + { + "name": "react/dns", + "version": "v1.13.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/dns.git", + "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/dns/zipball/eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "react/cache": "^1.0 || ^0.6 || ^0.5", + "react/event-loop": "^1.2", + "react/promise": "^3.2 || ^2.7 || ^1.2.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4.3 || ^3 || ^2", + "react/promise-timer": "^1.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Dns\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async DNS resolver for ReactPHP", + "keywords": [ + "async", + "dns", + "dns-resolver", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/dns/issues", + "source": "https://github.com/reactphp/dns/tree/v1.13.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-06-13T14:18:03+00:00" + }, + { + "name": "react/event-loop", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/event-loop.git", + "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "suggest": { + "ext-pcntl": "For signal handling support when using the StreamSelectLoop" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\EventLoop\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.", + "keywords": [ + "asynchronous", + "event-loop" + ], + "support": { + "issues": "https://github.com/reactphp/event-loop/issues", + "source": "https://github.com/reactphp/event-loop/tree/v1.5.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2023-11-13T13:48:05+00:00" + }, + { + "name": "react/promise", + "version": "v3.3.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise.git", + "reference": "23444f53a813a3296c1368bb104793ce8d88f04a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise/zipball/23444f53a813a3296c1368bb104793ce8d88f04a", + "reference": "23444f53a813a3296c1368bb104793ce8d88f04a", + "shasum": "" + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "phpstan/phpstan": "1.12.28 || 1.4.10", + "phpunit/phpunit": "^9.6 || ^7.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "React\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "keywords": [ + "promise", + "promises" + ], + "support": { + "issues": "https://github.com/reactphp/promise/issues", + "source": "https://github.com/reactphp/promise/tree/v3.3.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2025-08-19T18:57:03+00:00" + }, + { + "name": "react/socket", + "version": "v1.16.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/socket.git", + "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/socket/zipball/23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.0", + "react/dns": "^1.13", + "react/event-loop": "^1.2", + "react/promise": "^3.2 || ^2.6 || ^1.2.1", + "react/stream": "^1.4" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4.3 || ^3.3 || ^2", + "react/promise-stream": "^1.4", + "react/promise-timer": "^1.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Socket\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP", + "keywords": [ + "Connection", + "Socket", + "async", + "reactphp", + "stream" + ], + "support": { + "issues": "https://github.com/reactphp/socket/issues", + "source": "https://github.com/reactphp/socket/tree/v1.16.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-07-26T10:38:09+00:00" + }, + { + "name": "react/stream", + "version": "v1.4.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/stream.git", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/stream/zipball/1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.8", + "react/event-loop": "^1.2" + }, + "require-dev": { + "clue/stream-filter": "~1.2", + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Stream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP", + "keywords": [ + "event-driven", + "io", + "non-blocking", + "pipe", + "reactphp", + "readable", + "stream", + "writable" + ], + "support": { + "issues": "https://github.com/reactphp/stream/issues", + "source": "https://github.com/reactphp/stream/tree/v1.4.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-06-11T12:45:25+00:00" + }, + { + "name": "roave/security-advisories", + "version": "dev-latest", + "source": { + "type": "git", + "url": "https://github.com/Roave/SecurityAdvisories.git", + "reference": "d76fe05e57166d21b7b1e3da6f7f3895c3c5db46" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/d76fe05e57166d21b7b1e3da6f7f3895c3c5db46", + "reference": "d76fe05e57166d21b7b1e3da6f7f3895c3c5db46", + "shasum": "" + }, + "conflict": { + "3f/pygmentize": "<1.2", + "adaptcms/adaptcms": "<=1.3", + "admidio/admidio": "<4.3.12", + "adodb/adodb-php": "<=5.22.9", + "aheinze/cockpit": "<2.2", + "aimeos/ai-admin-graphql": ">=2022.04.1,<2022.10.10|>=2023.04.1,<2023.10.6|>=2024.04.1,<2024.07.2", + "aimeos/ai-admin-jsonadm": "<2020.10.13|>=2021.04.1,<2021.10.6|>=2022.04.1,<2022.10.3|>=2023.04.1,<2023.10.4|==2024.04.1", + "aimeos/ai-client-html": ">=2020.04.1,<2020.10.27|>=2021.04.1,<2021.10.22|>=2022.04.1,<2022.10.13|>=2023.04.1,<2023.10.15|>=2024.04.1,<2024.04.7", + "aimeos/ai-controller-frontend": "<2020.10.15|>=2021.04.1,<2021.10.8|>=2022.04.1,<2022.10.8|>=2023.04.1,<2023.10.9|==2024.04.1", + "aimeos/aimeos-core": ">=2022.04.1,<2022.10.17|>=2023.04.1,<2023.10.17|>=2024.04.1,<2024.04.7", + "aimeos/aimeos-typo3": "<19.10.12|>=20,<20.10.5", + "airesvsg/acf-to-rest-api": "<=3.1", + "akaunting/akaunting": "<2.1.13", + "akeneo/pim-community-dev": "<5.0.119|>=6,<6.0.53", + "alextselegidis/easyappointments": "<1.5.2.0-beta1", + "alt-design/alt-redirect": "<1.6.4", + "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1", + "amazing/media2click": ">=1,<1.3.3", + "ameos/ameos_tarteaucitron": "<1.2.23", + "amphp/artax": "<1.0.6|>=2,<2.0.6", + "amphp/http": "<=1.7.2|>=2,<=2.1", + "amphp/http-client": ">=4,<4.4", + "anchorcms/anchor-cms": "<=0.12.7", + "andreapollastri/cipi": "<=3.1.15", + "andrewhaine/silverstripe-form-capture": ">=0.2,<=0.2.3|>=1,<1.0.2|>=2,<2.2.5", + "aoe/restler": "<1.7.1", + "apache-solr-for-typo3/solr": "<2.8.3", + "apereo/phpcas": "<1.6", + "api-platform/core": "<3.4.17|>=4,<4.0.22|>=4.1,<4.1.5", + "api-platform/graphql": "<3.4.17|>=4,<4.0.22|>=4.1,<4.1.5", + "appwrite/server-ce": "<=1.2.1", + "arc/web": "<3", + "area17/twill": "<1.2.5|>=2,<2.5.3", + "artesaos/seotools": "<0.17.2", + "asymmetricrypt/asymmetricrypt": "<9.9.99", + "athlon1600/php-proxy": "<=5.1", + "athlon1600/php-proxy-app": "<=3", + "athlon1600/youtube-downloader": "<=4", + "austintoddj/canvas": "<=3.4.2", + "auth0/auth0-php": ">=3.3,<=8.16", + "auth0/login": "<=7.18", + "auth0/symfony": "<=5.4.1", + "auth0/wordpress": "<=5.3", + "automad/automad": "<2.0.0.0-alpha5", + "automattic/jetpack": "<9.8", + "awesome-support/awesome-support": "<=6.0.7", + "aws/aws-sdk-php": "<3.288.1", + "azuracast/azuracast": "<0.18.3", + "b13/seo_basics": "<0.8.2", + "backdrop/backdrop": "<1.27.3|>=1.28,<1.28.2", + "backpack/crud": "<3.4.9", + "backpack/filemanager": "<2.0.2|>=3,<3.0.9", + "bacula-web/bacula-web": "<9.7.1", + "badaso/core": "<=2.9.11", + "bagisto/bagisto": "<=2.3.7", + "barrelstrength/sprout-base-email": "<1.2.7", + "barrelstrength/sprout-forms": "<3.9", + "barryvdh/laravel-translation-manager": "<0.6.8", + "barzahlen/barzahlen-php": "<2.0.1", + "baserproject/basercms": "<=5.1.1", + "bassjobsen/bootstrap-3-typeahead": ">4.0.2", + "bbpress/bbpress": "<2.6.5", + "bcit-ci/codeigniter": "<3.1.3", + "bcosca/fatfree": "<3.7.2", + "bedita/bedita": "<4", + "bednee/cooluri": "<1.0.30", + "bigfork/silverstripe-form-capture": ">=3,<3.1.1", + "billz/raspap-webgui": "<3.3.6", + "binarytorch/larecipe": "<2.8.1", + "bk2k/bootstrap-package": ">=7.1,<7.1.2|>=8,<8.0.8|>=9,<9.0.4|>=9.1,<9.1.3|>=10,<10.0.10|>=11,<11.0.3", + "blueimp/jquery-file-upload": "==6.4.4", + "bmarshall511/wordpress_zero_spam": "<5.2.13", + "bolt/bolt": "<3.7.2", + "bolt/core": "<=4.2", + "born05/craft-twofactorauthentication": "<3.3.4", + "bottelet/flarepoint": "<2.2.1", + "bref/bref": "<2.1.17", + "brightlocal/phpwhois": "<=4.2.5", + "brotkrueml/codehighlight": "<2.7", + "brotkrueml/schema": "<1.13.1|>=2,<2.5.1", + "brotkrueml/typo3-matomo-integration": "<1.3.2", + "buddypress/buddypress": "<7.2.1", + "bugsnag/bugsnag-laravel": ">=2,<2.0.2", + "bvbmedia/multishop": "<2.0.39", + "bytefury/crater": "<6.0.2", + "cachethq/cachet": "<2.5.1", + "cakephp/cakephp": "<3.10.3|>=4,<4.0.10|>=4.1,<4.1.4|>=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", + "cakephp/database": ">=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", + "cardgate/magento2": "<2.0.33", + "cardgate/woocommerce": "<=3.1.15", + "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4", + "cart2quote/module-quotation-encoded": ">=4.1.6,<=4.4.5|>=5,<5.4.4", + "cartalyst/sentry": "<=2.1.6", + "catfan/medoo": "<1.7.5", + "causal/oidc": "<4", + "cecil/cecil": "<7.47.1", + "centreon/centreon": "<22.10.15", + "cesnet/simplesamlphp-module-proxystatistics": "<3.1", + "chriskacerguis/codeigniter-restserver": "<=2.7.1", + "chrome-php/chrome": "<1.14", + "civicrm/civicrm-core": ">=4.2,<4.2.9|>=4.3,<4.3.3", + "ckeditor/ckeditor": "<4.25", + "clickstorm/cs-seo": ">=6,<6.8|>=7,<7.5|>=8,<8.4|>=9,<9.3", + "co-stack/fal_sftp": "<0.2.6", + "cockpit-hq/cockpit": "<2.11.4", + "codeception/codeception": "<3.1.3|>=4,<4.1.22", + "codeigniter/framework": "<3.1.10", + "codeigniter4/framework": "<4.6.2", + "codeigniter4/shield": "<1.0.0.0-beta8", + "codiad/codiad": "<=2.8.4", + "codingms/additional-tca": ">=1.7,<1.15.17|>=1.16,<1.16.9", + "commerceteam/commerce": ">=0.9.6,<0.9.9", + "components/jquery": ">=1.0.3,<3.5", + "composer/composer": "<1.10.27|>=2,<2.2.24|>=2.3,<2.7.7", + "concrete5/concrete5": "<9.4.3", + "concrete5/core": "<8.5.8|>=9,<9.1", + "contao-components/mediaelement": ">=2.14.2,<2.21.1", + "contao/comments-bundle": ">=2,<4.13.40|>=5.0.0.0-RC1-dev,<5.3.4", + "contao/contao": ">=3,<3.5.37|>=4,<4.4.56|>=4.5,<4.13.56|>=5,<5.3.38|>=5.4.0.0-RC1-dev,<5.6.1", + "contao/core": "<3.5.39", + "contao/core-bundle": "<4.13.56|>=5,<5.3.38|>=5.4,<5.6.1", + "contao/listing-bundle": ">=3,<=3.5.30|>=4,<4.4.8", + "contao/managed-edition": "<=1.5", + "corveda/phpsandbox": "<1.3.5", + "cosenary/instagram": "<=2.3", + "couleurcitron/tarteaucitron-wp": "<0.3", + "craftcms/cms": "<=4.16.5|>=5,<=5.8.6", + "croogo/croogo": "<4", + "cuyz/valinor": "<0.12", + "czim/file-handling": "<1.5|>=2,<2.3", + "czproject/git-php": "<4.0.3", + "damienharper/auditor-bundle": "<5.2.6", + "dapphp/securimage": "<3.6.6", + "darylldoyle/safe-svg": "<1.9.10", + "datadog/dd-trace": ">=0.30,<0.30.2", + "datahihi1/tiny-env": "<1.0.3|>=1.0.9,<1.0.11", + "datatables/datatables": "<1.10.10", + "david-garcia/phpwhois": "<=4.3.1", + "dbrisinajumi/d2files": "<1", + "dcat/laravel-admin": "<=2.1.3|==2.2.0.0-beta|==2.2.2.0-beta", + "derhansen/fe_change_pwd": "<2.0.5|>=3,<3.0.3", + "derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1|>=7,<7.4", + "desperado/xml-bundle": "<=0.1.7", + "dev-lancer/minecraft-motd-parser": "<=1.0.5", + "devgroup/dotplant": "<2020.09.14-dev", + "digimix/wp-svg-upload": "<=1", + "directmailteam/direct-mail": "<6.0.3|>=7,<7.0.3|>=8,<9.5.2", + "dl/yag": "<3.0.1", + "dmk/webkitpdf": "<1.1.4", + "dnadesign/silverstripe-elemental": "<5.3.12", + "doctrine/annotations": "<1.2.7", + "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2", + "doctrine/common": "<2.4.3|>=2.5,<2.5.1", + "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2|>=3,<3.1.4", + "doctrine/doctrine-bundle": "<1.5.2", + "doctrine/doctrine-module": "<0.7.2", + "doctrine/mongodb-odm": "<1.0.2", + "doctrine/mongodb-odm-bundle": "<3.0.1", + "doctrine/orm": ">=1,<1.2.4|>=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4", + "dolibarr/dolibarr": "<21.0.3", + "dompdf/dompdf": "<2.0.4", + "doublethreedigital/guest-entries": "<3.1.2", + "drupal-pattern-lab/unified-twig-extensions": "<=0.1", + "drupal/admin_audit_trail": "<1.0.5", + "drupal/ai": "<1.0.5", + "drupal/alogin": "<2.0.6", + "drupal/cache_utility": "<1.2.1", + "drupal/commerce_alphabank_redirect": "<1.0.3", + "drupal/commerce_eurobank_redirect": "<2.1.1", + "drupal/config_split": "<1.10|>=2,<2.0.2", + "drupal/core": ">=6,<6.38|>=7,<7.102|>=8,<10.3.14|>=10.4,<10.4.5|>=11,<11.0.13|>=11.1,<11.1.5", + "drupal/core-recommended": ">=7,<7.102|>=8,<10.2.11|>=10.3,<10.3.9|>=11,<11.0.8", + "drupal/drupal": ">=5,<5.11|>=6,<6.38|>=7,<7.102|>=8,<10.2.11|>=10.3,<10.3.9|>=11,<11.0.8", + "drupal/formatter_suite": "<2.1", + "drupal/gdpr": "<3.0.1|>=3.1,<3.1.2", + "drupal/google_tag": "<1.8|>=2,<2.0.8", + "drupal/ignition": "<1.0.4", + "drupal/lightgallery": "<1.6", + "drupal/link_field_display_mode_formatter": "<1.6", + "drupal/matomo": "<1.24", + "drupal/oauth2_client": "<4.1.3", + "drupal/oauth2_server": "<2.1", + "drupal/obfuscate": "<2.0.1", + "drupal/quick_node_block": "<2", + "drupal/rapidoc_elements_field_formatter": "<1.0.1", + "drupal/spamspan": "<3.2.1", + "drupal/tfa": "<1.10", + "duncanmcclean/guest-entries": "<3.1.2", + "dweeves/magmi": "<=0.7.24", + "ec-cube/ec-cube": "<2.4.4|>=2.11,<=2.17.1|>=3,<=3.0.18.0-patch4|>=4,<=4.1.2", + "ecodev/newsletter": "<=4", + "ectouch/ectouch": "<=2.7.2", + "egroupware/egroupware": "<23.1.20240624", + "elefant/cms": "<2.0.7", + "elgg/elgg": "<3.3.24|>=4,<4.0.5", + "elijaa/phpmemcacheadmin": "<=1.3", + "elmsln/haxcms": "<11.0.14", + "encore/laravel-admin": "<=1.8.19", + "endroid/qr-code-bundle": "<3.4.2", + "enhavo/enhavo-app": "<=0.13.1", + "enshrined/svg-sanitize": "<0.22", + "erusev/parsedown": "<1.7.2", + "ether/logs": "<3.0.4", + "evolutioncms/evolution": "<=3.2.3", + "exceedone/exment": "<4.4.3|>=5,<5.0.3", + "exceedone/laravel-admin": "<2.2.3|==3", + "ezsystems/demobundle": ">=5.4,<5.4.6.1-dev", + "ezsystems/ez-support-tools": ">=2.2,<2.2.3", + "ezsystems/ezdemo-ls-extension": ">=5.4,<5.4.2.1-dev", + "ezsystems/ezfind-ls": ">=5.3,<5.3.6.1-dev|>=5.4,<5.4.11.1-dev|>=2017.12,<2017.12.0.1-dev", + "ezsystems/ezplatform": "<=1.13.6|>=2,<=2.5.24", + "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6|>=1.5,<1.5.29|>=2.3,<2.3.39|>=3.3,<3.3.39", + "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1|>=5.3.0.0-beta1,<5.3.5", + "ezsystems/ezplatform-graphql": ">=1.0.0.0-RC1-dev,<1.0.13|>=2.0.0.0-beta1,<2.3.12", + "ezsystems/ezplatform-http-cache": "<2.3.16", + "ezsystems/ezplatform-kernel": "<1.2.5.1-dev|>=1.3,<1.3.35", + "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<1.3.8", + "ezsystems/ezplatform-richtext": ">=2.3,<2.3.26|>=3.3,<3.3.40", + "ezsystems/ezplatform-solr-search-engine": ">=1.7,<1.7.12|>=2,<2.0.2|>=3.3,<3.3.15", + "ezsystems/ezplatform-user": ">=1,<1.0.1", + "ezsystems/ezpublish-kernel": "<6.13.8.2-dev|>=7,<7.5.31", + "ezsystems/ezpublish-legacy": "<=2017.12.7.3|>=2018.6,<=2019.03.5.1", + "ezsystems/platform-ui-assets-bundle": ">=4.2,<4.2.3", + "ezsystems/repository-forms": ">=2.3,<2.3.2.1-dev|>=2.5,<2.5.15", + "ezyang/htmlpurifier": "<=4.2", + "facade/ignition": "<1.16.15|>=2,<2.4.2|>=2.5,<2.5.2", + "facturascripts/facturascripts": "<=2022.08", + "fastly/magento2": "<1.2.26", + "feehi/cms": "<=2.1.1", + "feehi/feehicms": "<=2.1.1", + "fenom/fenom": "<=2.12.1", + "filament/actions": ">=3.2,<3.2.123", + "filament/infolists": ">=3,<3.2.115", + "filament/tables": ">=3,<3.2.115", + "filegator/filegator": "<7.8", + "filp/whoops": "<2.1.13", + "fineuploader/php-traditional-server": "<=1.2.2", + "firebase/php-jwt": "<6", + "fisharebest/webtrees": "<=2.1.18", + "fixpunkt/fp-masterquiz": "<2.2.1|>=3,<3.5.2", + "fixpunkt/fp-newsletter": "<1.1.1|>=1.2,<2.1.2|>=2.2,<3.2.6", + "flarum/core": "<1.8.10", + "flarum/flarum": "<0.1.0.0-beta8", + "flarum/framework": "<1.8.10", + "flarum/mentions": "<1.6.3", + "flarum/sticky": ">=0.1.0.0-beta14,<=0.1.0.0-beta15", + "flarum/tags": "<=0.1.0.0-beta13", + "floriangaerber/magnesium": "<0.3.1", + "fluidtypo3/vhs": "<5.1.1", + "fof/byobu": ">=0.3.0.0-beta2,<1.1.7", + "fof/upload": "<1.2.3", + "foodcoopshop/foodcoopshop": ">=3.2,<3.6.1", + "fooman/tcpdf": "<6.2.22", + "forkcms/forkcms": "<5.11.1", + "fossar/tcpdf-parser": "<6.2.22", + "francoisjacquet/rosariosis": "<=11.5.1", + "frappant/frp-form-answers": "<3.1.2|>=4,<4.0.2", + "friendsofsymfony/oauth2-php": "<1.3", + "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", + "friendsofsymfony/user-bundle": ">=1,<1.3.5", + "friendsofsymfony1/swiftmailer": ">=4,<5.4.13|>=6,<6.2.5", + "friendsofsymfony1/symfony1": ">=1.1,<1.5.19", + "friendsoftypo3/mediace": ">=7.6.2,<7.6.5", + "friendsoftypo3/openid": ">=4.5,<4.5.31|>=4.7,<4.7.16|>=6,<6.0.11|>=6.1,<6.1.6", + "froala/wysiwyg-editor": "<=4.3", + "froxlor/froxlor": "<=2.2.5", + "frozennode/administrator": "<=5.0.12", + "fuel/core": "<1.8.1", + "funadmin/funadmin": "<=5.0.2", + "gaoming13/wechat-php-sdk": "<=1.10.2", + "genix/cms": "<=1.1.11", + "georgringer/news": "<1.3.3", + "geshi/geshi": "<=1.0.9.1", + "getformwork/formwork": "<1.13.1|>=2.0.0.0-beta1,<2.0.0.0-beta4", + "getgrav/grav": "<1.7.46", + "getkirby/cms": "<3.9.8.3-dev|>=3.10,<3.10.1.2-dev|>=4,<4.7.1", + "getkirby/kirby": "<3.9.8.3-dev|>=3.10,<3.10.1.2-dev|>=4,<4.7.1", + "getkirby/panel": "<2.5.14", + "getkirby/starterkit": "<=3.7.0.2", + "gilacms/gila": "<=1.15.4", + "gleez/cms": "<=1.3|==2", + "globalpayments/php-sdk": "<2", + "goalgorilla/open_social": "<12.3.11|>=12.4,<12.4.10|>=13.0.0.0-alpha1,<13.0.0.0-alpha11", + "gogentooss/samlbase": "<1.2.7", + "google/protobuf": "<3.4", + "gos/web-socket-bundle": "<1.10.4|>=2,<2.6.1|>=3,<3.3", + "gp247/core": "<1.1.24", + "gree/jose": "<2.2.1", + "gregwar/rst": "<1.0.3", + "grumpydictator/firefly-iii": "<6.1.17", + "gugoan/economizzer": "<=0.9.0.0-beta1", + "guzzlehttp/guzzle": "<6.5.8|>=7,<7.4.5", + "guzzlehttp/oauth-subscriber": "<0.8.1", + "guzzlehttp/psr7": "<1.9.1|>=2,<2.4.5", + "haffner/jh_captcha": "<=2.1.3|>=3,<=3.0.2", + "handcraftedinthealps/goodby-csv": "<1.4.3", + "harvesthq/chosen": "<1.8.7", + "helloxz/imgurl": "<=2.31", + "hhxsv5/laravel-s": "<3.7.36", + "hillelcoren/invoice-ninja": "<5.3.35", + "himiklab/yii2-jqgrid-widget": "<1.0.8", + "hjue/justwriting": "<=1", + "hov/jobfair": "<1.0.13|>=2,<2.0.2", + "httpsoft/http-message": "<1.0.12", + "hyn/multi-tenant": ">=5.6,<5.7.2", + "ibexa/admin-ui": ">=4.2,<4.2.3|>=4.6,<4.6.25|>=5,<5.0.3", + "ibexa/admin-ui-assets": ">=4.6.0.0-alpha1,<4.6.21", + "ibexa/core": ">=4,<4.0.7|>=4.1,<4.1.4|>=4.2,<4.2.3|>=4.5,<4.5.6|>=4.6,<4.6.2", + "ibexa/fieldtype-richtext": ">=4.6,<4.6.25|>=5,<5.0.3", + "ibexa/graphql": ">=2.5,<2.5.31|>=3.3,<3.3.28|>=4.2,<4.2.3", + "ibexa/http-cache": ">=4.6,<4.6.14", + "ibexa/post-install": "<1.0.16|>=4.6,<4.6.14", + "ibexa/solr": ">=4.5,<4.5.4", + "ibexa/user": ">=4,<4.4.3|>=5,<5.0.3", + "icecoder/icecoder": "<=8.1", + "idno/known": "<=1.3.1", + "ilicmiljan/secure-props": ">=1.2,<1.2.2", + "illuminate/auth": "<5.5.10", + "illuminate/cookie": ">=4,<=4.0.11|>=4.1,<6.18.31|>=7,<7.22.4", + "illuminate/database": "<6.20.26|>=7,<7.30.5|>=8,<8.40", + "illuminate/encryption": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15", + "illuminate/view": "<6.20.42|>=7,<7.30.6|>=8,<8.75", + "imdbphp/imdbphp": "<=5.1.1", + "impresscms/impresscms": "<=1.4.5", + "impresspages/impresspages": "<1.0.13", + "in2code/femanager": "<6.4.2|>=7,<7.5.3|>=8,<8.3.1", + "in2code/ipandlanguageredirect": "<5.1.2", + "in2code/lux": "<17.6.1|>=18,<24.0.2", + "in2code/powermail": "<7.5.1|>=8,<8.5.1|>=9,<10.9.1|>=11,<12.5.3|==13", + "innologi/typo3-appointments": "<2.0.6", + "intelliants/subrion": "<4.2.2", + "inter-mediator/inter-mediator": "==5.5", + "ipl/web": "<0.10.1", + "islandora/crayfish": "<4.1", + "islandora/islandora": ">=2,<2.4.1", + "ivankristianto/phpwhois": "<=4.3", + "jackalope/jackalope-doctrine-dbal": "<1.7.4", + "jambagecom/div2007": "<0.10.2", + "james-heinrich/getid3": "<1.9.21", + "james-heinrich/phpthumb": "<=1.7.23", + "jasig/phpcas": "<1.3.3", + "jbartels/wec-map": "<3.0.3", + "jcbrand/converse.js": "<3.3.3", + "joelbutcher/socialstream": "<5.6|>=6,<6.2", + "johnbillion/wp-crontrol": "<1.16.2|>=1.17,<1.19.2", + "joomla/application": "<1.0.13", + "joomla/archive": "<1.1.12|>=2,<2.0.1", + "joomla/database": ">=1,<2.2|>=3,<3.4", + "joomla/filesystem": "<1.6.2|>=2,<2.0.1", + "joomla/filter": "<2.0.6|>=3,<3.0.5|==4", + "joomla/framework": "<1.5.7|>=2.5.4,<=3.8.12", + "joomla/input": ">=2,<2.0.2", + "joomla/joomla-cms": "<3.9.12|>=4,<4.4.13|>=5,<5.2.6", + "joomla/joomla-platform": "<1.5.4", + "joomla/session": "<1.3.1", + "joyqi/hyper-down": "<=2.4.27", + "jsdecena/laracom": "<2.0.9", + "jsmitty12/phpwhois": "<5.1", + "juzaweb/cms": "<=3.4.2", + "jweiland/events2": "<8.3.8|>=9,<9.0.6", + "jweiland/kk-downloader": "<1.2.2", + "kazist/phpwhois": "<=4.2.6", + "kelvinmo/simplexrd": "<3.1.1", + "kevinpapst/kimai2": "<1.16.7", + "khodakhah/nodcms": "<=3", + "kimai/kimai": "<=2.20.1", + "kitodo/presentation": "<3.2.3|>=3.3,<3.3.4", + "klaviyo/magento2-extension": ">=1,<3", + "knplabs/knp-snappy": "<=1.4.2", + "kohana/core": "<3.3.3", + "koillection/koillection": "<1.6.12", + "krayin/laravel-crm": "<=1.3", + "kreait/firebase-php": ">=3.2,<3.8.1", + "kumbiaphp/kumbiapp": "<=1.1.1", + "la-haute-societe/tcpdf": "<6.2.22", + "laminas/laminas-diactoros": "<2.18.1|==2.19|==2.20|==2.21|==2.22|==2.23|>=2.24,<2.24.2|>=2.25,<2.25.2", + "laminas/laminas-form": "<2.17.1|>=3,<3.0.2|>=3.1,<3.1.1", + "laminas/laminas-http": "<2.14.2", + "lara-zeus/artemis": ">=1,<=1.0.6", + "lara-zeus/dynamic-dashboard": ">=3,<=3.0.1", + "laravel/fortify": "<1.11.1", + "laravel/framework": "<10.48.29|>=11,<11.44.1|>=12,<12.1.1", + "laravel/laravel": ">=5.4,<5.4.22", + "laravel/pulse": "<1.3.1", + "laravel/reverb": "<1.4", + "laravel/socialite": ">=1,<2.0.10", + "latte/latte": "<2.10.8", + "lavalite/cms": "<=9|==10.1", + "lavitto/typo3-form-to-database": "<2.2.5|>=3,<3.2.2|>=4,<4.2.3|>=5,<5.0.2", + "lcobucci/jwt": ">=3.4,<3.4.6|>=4,<4.0.4|>=4.1,<4.1.5", + "league/commonmark": "<2.7", + "league/flysystem": "<1.1.4|>=2,<2.1.1", + "league/oauth2-server": ">=8.3.2,<8.4.2|>=8.5,<8.5.3", + "leantime/leantime": "<3.3", + "lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3", + "libreform/libreform": ">=2,<=2.0.8", + "librenms/librenms": "<2017.08.18", + "liftkit/database": "<2.13.2", + "lightsaml/lightsaml": "<1.3.5", + "limesurvey/limesurvey": "<6.5.12", + "livehelperchat/livehelperchat": "<=3.91", + "livewire/livewire": "<2.12.7|>=3.0.0.0-beta1,<3.6.4", + "livewire/volt": "<1.7", + "lms/routes": "<2.1.1", + "localizationteam/l10nmgr": "<7.4|>=8,<8.7|>=9,<9.2", + "lomkit/laravel-rest-api": "<2.13", + "luracast/restler": "<3.1", + "luyadev/yii-helpers": "<1.2.1", + "macropay-solutions/laravel-crud-wizard-free": "<3.4.17", + "maestroerror/php-heic-to-jpg": "<1.0.5", + "magento/community-edition": "<2.4.6.0-patch13|>=2.4.7.0-beta1,<2.4.7.0-patch8|>=2.4.8.0-beta1,<2.4.8.0-patch3|>=2.4.9.0-alpha1,<2.4.9.0-alpha3|==2.4.9", + "magento/core": "<=1.9.4.5", + "magento/magento1ce": "<1.9.4.3-dev", + "magento/magento1ee": ">=1,<1.14.4.3-dev", + "magento/product-community-edition": "<2.4.4.0-patch9|>=2.4.5,<2.4.5.0-patch8|>=2.4.6,<2.4.6.0-patch6|>=2.4.7,<2.4.7.0-patch1", + "magento/project-community-edition": "<=2.0.2", + "magneto/core": "<1.9.4.4-dev", + "mahocommerce/maho": "<25.9", + "maikuolan/phpmussel": ">=1,<1.6", + "mainwp/mainwp": "<=4.4.3.3", + "manogi/nova-tiptap": "<=3.2.6", + "mantisbt/mantisbt": "<=2.26.3", + "marcwillmann/turn": "<0.3.3", + "marshmallow/nova-tiptap": "<5.7", + "matomo/matomo": "<1.11", + "matyhtf/framework": "<3.0.6", + "mautic/core": "<5.2.8|>=6.0.0.0-alpha,<6.0.5", + "mautic/core-lib": ">=1.0.0.0-beta,<4.4.13|>=5.0.0.0-alpha,<5.1.1", + "maximebf/debugbar": "<1.19", + "mdanter/ecc": "<2", + "mediawiki/abuse-filter": "<1.39.9|>=1.40,<1.41.3|>=1.42,<1.42.2", + "mediawiki/cargo": "<3.8.3", + "mediawiki/core": "<1.39.5|==1.40", + "mediawiki/data-transfer": ">=1.39,<1.39.11|>=1.41,<1.41.3|>=1.42,<1.42.2", + "mediawiki/matomo": "<2.4.3", + "mediawiki/semantic-media-wiki": "<4.0.2", + "mehrwert/phpmyadmin": "<3.2", + "melisplatform/melis-asset-manager": "<5.0.1", + "melisplatform/melis-cms": "<5.3.4", + "melisplatform/melis-cms-slider": "<5.3.1", + "melisplatform/melis-core": "<5.3.11", + "melisplatform/melis-front": "<5.0.1", + "mezzio/mezzio-swoole": "<3.7|>=4,<4.3", + "mgallegos/laravel-jqgrid": "<=1.3", + "microsoft/microsoft-graph": ">=1.16,<1.109.1|>=2,<2.0.1", + "microsoft/microsoft-graph-beta": "<2.0.1", + "microsoft/microsoft-graph-core": "<2.0.2", + "microweber/microweber": "<=2.0.19", + "mikehaertl/php-shellcommand": "<1.6.1", + "miniorange/miniorange-saml": "<1.4.3", + "mittwald/typo3_forum": "<1.2.1", + "mobiledetect/mobiledetectlib": "<2.8.32", + "modx/revolution": "<=3.1", + "mojo42/jirafeau": "<4.4", + "mongodb/mongodb": ">=1,<1.9.2", + "monolog/monolog": ">=1.8,<1.12", + "moodle/moodle": "<4.3.12|>=4.4,<4.4.8|>=4.5.0.0-beta,<4.5.4", + "moonshine/moonshine": "<=3.12.5", + "mos/cimage": "<0.7.19", + "movim/moxl": ">=0.8,<=0.10", + "movingbytes/social-network": "<=1.2.1", + "mpdf/mpdf": "<=7.1.7", + "munkireport/comment": "<4.1", + "munkireport/managedinstalls": "<2.6", + "munkireport/munki_facts": "<1.5", + "munkireport/munkireport": ">=2.5.3,<5.6.3", + "munkireport/reportdata": "<3.5", + "munkireport/softwareupdate": "<1.6", + "mustache/mustache": ">=2,<2.14.1", + "mwdelaney/wp-enable-svg": "<=0.2", + "namshi/jose": "<2.2", + "nasirkhan/laravel-starter": "<11.11", + "nategood/httpful": "<1", + "neoan3-apps/template": "<1.1.1", + "neorazorx/facturascripts": "<2022.04", + "neos/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", + "neos/form": ">=1.2,<4.3.3|>=5,<5.0.9|>=5.1,<5.1.3", + "neos/media-browser": "<7.3.19|>=8,<8.0.16|>=8.1,<8.1.11|>=8.2,<8.2.11|>=8.3,<8.3.9", + "neos/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<5.3.10|>=7,<7.0.9|>=7.1,<7.1.7|>=7.2,<7.2.6|>=7.3,<7.3.4|>=8,<8.0.2", + "neos/swiftmailer": "<5.4.5", + "nesbot/carbon": "<2.72.6|>=3,<3.8.4", + "netcarver/textile": "<=4.1.2", + "netgen/tagsbundle": ">=3.4,<3.4.11|>=4,<4.0.15", + "nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6", + "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13", + "nilsteampassnet/teampass": "<3.1.3.1-dev", + "nitsan/ns-backup": "<13.0.1", + "nonfiction/nterchange": "<4.1.1", + "notrinos/notrinos-erp": "<=0.7", + "noumo/easyii": "<=0.9", + "novaksolutions/infusionsoft-php-sdk": "<1", + "novosga/novosga": "<=2.2.12", + "nukeviet/nukeviet": "<4.5.02", + "nyholm/psr7": "<1.6.1", + "nystudio107/craft-seomatic": "<3.4.12", + "nzedb/nzedb": "<0.8", + "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", + "october/backend": "<1.1.2", + "october/cms": "<1.0.469|==1.0.469|==1.0.471|==1.1.1", + "october/october": "<3.7.5", + "october/rain": "<1.0.472|>=1.1,<1.1.2", + "october/system": "<3.7.5", + "oliverklee/phpunit": "<3.5.15", + "omeka/omeka-s": "<4.0.3", + "onelogin/php-saml": "<2.10.4", + "oneup/uploader-bundle": ">=1,<1.9.3|>=2,<2.1.5", + "open-web-analytics/open-web-analytics": "<1.8.1", + "opencart/opencart": ">=0", + "openid/php-openid": "<2.3", + "openmage/magento-lts": "<20.12.3", + "opensolutions/vimbadmin": "<=3.0.15", + "opensource-workshop/connect-cms": "<1.8.7|>=2,<2.4.7", + "orchid/platform": ">=8,<14.43", + "oro/calendar-bundle": ">=4.2,<=4.2.6|>=5,<=5.0.6|>=5.1,<5.1.1", + "oro/commerce": ">=4.1,<5.0.11|>=5.1,<5.1.1", + "oro/crm": ">=1.7,<1.7.4|>=3.1,<4.1.17|>=4.2,<4.2.7", + "oro/crm-call-bundle": ">=4.2,<=4.2.5|>=5,<5.0.4|>=5.1,<5.1.1", + "oro/customer-portal": ">=4.1,<=4.1.13|>=4.2,<=4.2.10|>=5,<=5.0.11|>=5.1,<=5.1.3", + "oro/platform": ">=1.7,<1.7.4|>=3.1,<3.1.29|>=4.1,<4.1.17|>=4.2,<=4.2.10|>=5,<=5.0.12|>=5.1,<=5.1.3", + "oveleon/contao-cookiebar": "<1.16.3|>=2,<2.1.3", + "oxid-esales/oxideshop-ce": "<=7.0.5", + "oxid-esales/paymorrow-module": ">=1,<1.0.2|>=2,<2.0.1", + "packbackbooks/lti-1-3-php-library": "<5", + "padraic/humbug_get_contents": "<1.1.2", + "pagarme/pagarme-php": "<3", + "pagekit/pagekit": "<=1.0.18", + "paragonie/ecc": "<2.0.1", + "paragonie/random_compat": "<2", + "passbolt/passbolt_api": "<4.6.2", + "paypal/adaptivepayments-sdk-php": "<=3.9.2", + "paypal/invoice-sdk-php": "<=3.9", + "paypal/merchant-sdk-php": "<3.12", + "paypal/permissions-sdk-php": "<=3.9.1", + "pear/archive_tar": "<1.4.14", + "pear/auth": "<1.2.4", + "pear/crypt_gpg": "<1.6.7", + "pear/http_request2": "<2.7", + "pear/pear": "<=1.10.1", + "pegasus/google-for-jobs": "<1.5.1|>=2,<2.1.1", + "personnummer/personnummer": "<3.0.2", + "phanan/koel": "<5.1.4", + "phenx/php-svg-lib": "<0.5.2", + "php-censor/php-censor": "<2.0.13|>=2.1,<2.1.5", + "php-mod/curl": "<2.3.2", + "phpbb/phpbb": "<3.3.11", + "phpems/phpems": ">=6,<=6.1.3", + "phpfastcache/phpfastcache": "<6.1.5|>=7,<7.1.2|>=8,<8.0.7", + "phpmailer/phpmailer": "<6.5", + "phpmussel/phpmussel": ">=1,<1.6", + "phpmyadmin/phpmyadmin": "<5.2.2", + "phpmyfaq/phpmyfaq": "<3.2.5|==3.2.5|>=3.2.10,<=4.0.1", + "phpoffice/common": "<0.2.9", + "phpoffice/math": "<=0.2", + "phpoffice/phpexcel": "<=1.8.2", + "phpoffice/phpspreadsheet": "<1.30|>=2,<2.1.12|>=2.2,<2.4|>=3,<3.10|>=4,<5", + "phpseclib/phpseclib": "<2.0.47|>=3,<3.0.36", + "phpservermon/phpservermon": "<3.6", + "phpsysinfo/phpsysinfo": "<3.4.3", + "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5.0.10,<5.6.3", + "phpwhois/phpwhois": "<=4.2.5", + "phpxmlrpc/extras": "<0.6.1", + "phpxmlrpc/phpxmlrpc": "<4.9.2", + "pi/pi": "<=2.5", + "pimcore/admin-ui-classic-bundle": "<1.7.6", + "pimcore/customer-management-framework-bundle": "<4.2.1", + "pimcore/data-hub": "<1.2.4", + "pimcore/data-importer": "<1.8.9|>=1.9,<1.9.3", + "pimcore/demo": "<10.3", + "pimcore/ecommerce-framework-bundle": "<1.0.10", + "pimcore/perspective-editor": "<1.5.1", + "pimcore/pimcore": "<11.5.4", + "piwik/piwik": "<1.11", + "pixelfed/pixelfed": "<0.12.5", + "plotly/plotly.js": "<2.25.2", + "pocketmine/bedrock-protocol": "<8.0.2", + "pocketmine/pocketmine-mp": "<5.32.1", + "pocketmine/raklib": ">=0.14,<0.14.6|>=0.15,<0.15.1", + "pressbooks/pressbooks": "<5.18", + "prestashop/autoupgrade": ">=4,<4.10.1", + "prestashop/blockreassurance": "<=5.1.3", + "prestashop/blockwishlist": ">=2,<2.1.1", + "prestashop/contactform": ">=1.0.1,<4.3", + "prestashop/gamification": "<2.3.2", + "prestashop/prestashop": "<8.2.3", + "prestashop/productcomments": "<5.0.2", + "prestashop/ps_checkout": "<4.4.1|>=5,<5.0.5", + "prestashop/ps_contactinfo": "<=3.3.2", + "prestashop/ps_emailsubscription": "<2.6.1", + "prestashop/ps_facetedsearch": "<3.4.1", + "prestashop/ps_linklist": "<3.1", + "privatebin/privatebin": "<1.4|>=1.5,<1.7.4", + "processwire/processwire": "<=3.0.246", + "propel/propel": ">=2.0.0.0-alpha1,<=2.0.0.0-alpha7", + "propel/propel1": ">=1,<=1.7.1", + "pterodactyl/panel": "<=1.11.10", + "ptheofan/yii2-statemachine": ">=2.0.0.0-RC1-dev,<=2", + "ptrofimov/beanstalk_console": "<1.7.14", + "pubnub/pubnub": "<6.1", + "punktde/pt_extbase": "<1.5.1", + "pusher/pusher-php-server": "<2.2.1", + "pwweb/laravel-core": "<=0.3.6.0-beta", + "pxlrbt/filament-excel": "<1.1.14|>=2.0.0.0-alpha,<2.3.3", + "pyrocms/pyrocms": "<=3.9.1", + "qcubed/qcubed": "<=3.1.1", + "quickapps/cms": "<=2.0.0.0-beta2", + "rainlab/blog-plugin": "<1.4.1", + "rainlab/debugbar-plugin": "<3.1", + "rainlab/user-plugin": "<=1.4.5", + "rankmath/seo-by-rank-math": "<=1.0.95", + "rap2hpoutre/laravel-log-viewer": "<0.13", + "react/http": ">=0.7,<1.9", + "really-simple-plugins/complianz-gdpr": "<6.4.2", + "redaxo/source": "<5.18.3", + "remdex/livehelperchat": "<4.29", + "renolit/reint-downloadmanager": "<4.0.2|>=5,<5.0.1", + "reportico-web/reportico": "<=8.1", + "rhukster/dom-sanitizer": "<1.0.7", + "rmccue/requests": ">=1.6,<1.8", + "robrichards/xmlseclibs": ">=1,<3.0.4", + "roots/soil": "<4.1", + "roundcube/roundcubemail": "<1.5.10|>=1.6,<1.6.11", + "rudloff/alltube": "<3.0.3", + "rudloff/rtmpdump-bin": "<=2.3.1", + "s-cart/core": "<=9.0.5", + "s-cart/s-cart": "<6.9", + "sabberworm/php-css-parser": ">=1,<1.0.1|>=2,<2.0.1|>=3,<3.0.1|>=4,<4.0.1|>=5,<5.0.9|>=5.1,<5.1.3|>=5.2,<5.2.1|>=6,<6.0.2|>=7,<7.0.4|>=8,<8.0.1|>=8.1,<8.1.1|>=8.2,<8.2.1|>=8.3,<8.3.1", + "sabre/dav": ">=1.6,<1.7.11|>=1.8,<1.8.9", + "samwilson/unlinked-wikibase": "<1.42", + "scheb/two-factor-bundle": "<3.26|>=4,<4.11", + "sensiolabs/connect": "<4.2.3", + "serluck/phpwhois": "<=4.2.6", + "setasign/fpdi": "<2.6.4", + "sfroemken/url_redirect": "<=1.2.1", + "sheng/yiicms": "<1.2.1", + "shopware/core": "<6.6.10.7-dev|>=6.7,<6.7.3.1-dev", + "shopware/platform": "<6.6.10.7-dev|>=6.7,<6.7.3.1-dev", + "shopware/production": "<=6.3.5.2", + "shopware/shopware": "<=5.7.17|>=6.7,<6.7.2.1-dev", + "shopware/storefront": "<=6.4.8.1|>=6.5.8,<6.5.8.7-dev", + "shopxo/shopxo": "<=6.4", + "showdoc/showdoc": "<2.10.4", + "shuchkin/simplexlsx": ">=1.0.12,<1.1.13", + "silverstripe-australia/advancedreports": ">=1,<=2", + "silverstripe/admin": "<1.13.19|>=2,<2.1.8", + "silverstripe/assets": ">=1,<1.11.1", + "silverstripe/cms": "<4.11.3", + "silverstripe/comments": ">=1.3,<3.1.1", + "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", + "silverstripe/framework": "<5.3.23", + "silverstripe/graphql": ">=2,<2.0.5|>=3,<3.8.2|>=4,<4.3.7|>=5,<5.1.3", + "silverstripe/hybridsessions": ">=1,<2.4.1|>=2.5,<2.5.1", + "silverstripe/recipe-cms": ">=4.5,<4.5.3", + "silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1", + "silverstripe/reports": "<5.2.3", + "silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4|>=2.1,<2.1.2", + "silverstripe/silverstripe-omnipay": "<2.5.2|>=3,<3.0.2|>=3.1,<3.1.4|>=3.2,<3.2.1", + "silverstripe/subsites": ">=2,<2.6.1", + "silverstripe/taxonomy": ">=1.3,<1.3.1|>=2,<2.0.1", + "silverstripe/userforms": "<3|>=5,<5.4.2", + "silverstripe/versioned-admin": ">=1,<1.11.1", + "simogeo/filemanager": "<=2.5", + "simple-updates/phpwhois": "<=1", + "simplesamlphp/saml2": "<=4.16.15|>=5.0.0.0-alpha1,<=5.0.0.0-alpha19", + "simplesamlphp/saml2-legacy": "<=4.16.15", + "simplesamlphp/simplesamlphp": "<1.18.6", + "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1", + "simplesamlphp/simplesamlphp-module-openid": "<1", + "simplesamlphp/simplesamlphp-module-openidprovider": "<0.9", + "simplesamlphp/xml-common": "<1.20", + "simplesamlphp/xml-security": "==1.6.11", + "simplito/elliptic-php": "<1.0.6", + "sitegeist/fluid-components": "<3.5", + "sjbr/sr-feuser-register": "<2.6.2|>=5.1,<12.5", + "sjbr/sr-freecap": "<2.4.6|>=2.5,<2.5.3", + "sjbr/static-info-tables": "<2.3.1", + "slim/psr7": "<1.4.1|>=1.5,<1.5.1|>=1.6,<1.6.1", + "slim/slim": "<2.6", + "slub/slub-events": "<3.0.3", + "smarty/smarty": "<4.5.3|>=5,<5.1.1", + "snipe/snipe-it": "<8.1.18", + "socalnick/scn-social-auth": "<1.15.2", + "socialiteproviders/steam": "<1.1", + "solspace/craft-freeform": ">=5,<5.10.16", + "soosyze/soosyze": "<=2", + "spatie/browsershot": "<5.0.5", + "spatie/image-optimizer": "<1.7.3", + "spencer14420/sp-php-email-handler": "<1", + "spipu/html2pdf": "<5.2.8", + "spoon/library": "<1.4.1", + "spoonity/tcpdf": "<6.2.22", + "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", + "ssddanbrown/bookstack": "<24.05.1", + "starcitizentools/citizen-skin": ">=1.9.4,<3.9", + "starcitizentools/short-description": ">=4,<4.0.1", + "starcitizentools/tabber-neue": ">=1.9.1,<2.7.2|>=3,<3.1.1", + "starcitizenwiki/embedvideo": "<=4", + "statamic/cms": "<=5.16", + "stormpath/sdk": "<9.9.99", + "studio-42/elfinder": "<=2.1.64", + "studiomitte/friendlycaptcha": "<0.1.4", + "subhh/libconnect": "<7.0.8|>=8,<8.1", + "sukohi/surpass": "<1", + "sulu/form-bundle": ">=2,<2.5.3", + "sulu/sulu": "<1.6.44|>=2,<2.5.25|>=2.6,<2.6.9|>=3.0.0.0-alpha1,<3.0.0.0-alpha3", + "sumocoders/framework-user-bundle": "<1.4", + "superbig/craft-audit": "<3.0.2", + "svewap/a21glossary": "<=0.4.10", + "swag/paypal": "<5.4.4", + "swiftmailer/swiftmailer": "<6.2.5", + "swiftyedit/swiftyedit": "<1.2", + "sylius/admin-bundle": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", + "sylius/grid": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1", + "sylius/grid-bundle": "<1.10.1", + "sylius/paypal-plugin": "<1.6.2|>=1.7,<1.7.2|>=2,<2.0.2", + "sylius/resource-bundle": ">=1,<1.3.14|>=1.4,<1.4.7|>=1.5,<1.5.2|>=1.6,<1.6.4", + "sylius/sylius": "<1.12.19|>=1.13.0.0-alpha1,<1.13.4", + "symbiote/silverstripe-multivaluefield": ">=3,<3.1", + "symbiote/silverstripe-queuedjobs": ">=3,<3.0.2|>=3.1,<3.1.4|>=4,<4.0.7|>=4.1,<4.1.2|>=4.2,<4.2.4|>=4.3,<4.3.3|>=4.4,<4.4.3|>=4.5,<4.5.1|>=4.6,<4.6.4", + "symbiote/silverstripe-seed": "<6.0.3", + "symbiote/silverstripe-versionedfiles": "<=2.0.3", + "symfont/process": ">=0", + "symfony/cache": ">=3.1,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8", + "symfony/dependency-injection": ">=2,<2.0.17|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/error-handler": ">=4.4,<4.4.4|>=5,<5.0.4", + "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", + "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7|>=5.3.14,<5.3.15|>=5.4.3,<5.4.4|>=6.0.3,<6.0.4", + "symfony/http-client": ">=4.3,<5.4.47|>=6,<6.4.15|>=7,<7.1.8", + "symfony/http-foundation": "<5.4.46|>=6,<6.4.14|>=7,<7.1.7", + "symfony/http-kernel": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", + "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", + "symfony/maker-bundle": ">=1.27,<1.29.2|>=1.30,<1.31.1", + "symfony/mime": ">=4.3,<4.3.8", + "symfony/phpunit-bridge": ">=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/polyfill": ">=1,<1.10", + "symfony/polyfill-php55": ">=1,<1.10", + "symfony/process": "<5.4.46|>=6,<6.4.14|>=7,<7.1.7", + "symfony/proxy-manager-bridge": ">=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/routing": ">=2,<2.0.19", + "symfony/runtime": ">=5.3,<5.4.46|>=6,<6.4.14|>=7,<7.1.7", + "symfony/security": ">=2,<2.7.51|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.8", + "symfony/security-bundle": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.4.10|>=7,<7.0.10|>=7.1,<7.1.3", + "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.9", + "symfony/security-csrf": ">=2.4,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", + "symfony/security-guard": ">=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8", + "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7|>=5.1,<5.2.8|>=5.3,<5.4.47|>=6,<6.4.15|>=7,<7.1.8", + "symfony/serializer": ">=2,<2.0.11|>=4.1,<4.4.35|>=5,<5.3.12", + "symfony/symfony": "<5.4.47|>=6,<6.4.15|>=7,<7.1.8", + "symfony/translation": ">=2,<2.0.17", + "symfony/twig-bridge": ">=2,<4.4.51|>=5,<5.4.31|>=6,<6.3.8", + "symfony/ux-autocomplete": "<2.11.2", + "symfony/ux-live-component": "<2.25.1", + "symfony/ux-twig-component": "<2.25.1", + "symfony/validator": "<5.4.43|>=6,<6.4.11|>=7,<7.1.4", + "symfony/var-exporter": ">=4.2,<4.2.12|>=4.3,<4.3.8", + "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4", + "symfony/webhook": ">=6.3,<6.3.8", + "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7|>=2.2.0.0-beta1,<2.2.0.0-beta2", + "symphonycms/symphony-2": "<2.6.4", + "t3/dce": "<0.11.5|>=2.2,<2.6.2", + "t3g/svg-sanitizer": "<1.0.3", + "t3s/content-consent": "<1.0.3|>=2,<2.0.2", + "tastyigniter/tastyigniter": "<4", + "tcg/voyager": "<=1.8", + "tecnickcom/tc-lib-pdf-font": "<2.6.4", + "tecnickcom/tcpdf": "<6.8", + "terminal42/contao-tablelookupwizard": "<3.3.5", + "thelia/backoffice-default-template": ">=2.1,<2.1.2", + "thelia/thelia": ">=2.1,<2.1.3", + "theonedemon/phpwhois": "<=4.2.5", + "thinkcmf/thinkcmf": "<6.0.8", + "thorsten/phpmyfaq": "<=4.0.1|>=4.0.7,<4.0.13", + "tikiwiki/tiki-manager": "<=17.1", + "timber/timber": ">=0.16.6,<1.23.1|>=1.24,<1.24.1|>=2,<2.1", + "tinymce/tinymce": "<7.2", + "tinymighty/wiki-seo": "<1.2.2", + "titon/framework": "<9.9.99", + "tltneon/lgsl": "<7", + "tobiasbg/tablepress": "<=2.0.0.0-RC1", + "topthink/framework": "<6.0.17|>=6.1,<=8.0.4", + "topthink/think": "<=6.1.1", + "topthink/thinkphp": "<=3.2.3|>=6.1.3,<=8.0.4", + "torrentpier/torrentpier": "<=2.4.3", + "tpwd/ke_search": "<4.0.3|>=4.1,<4.6.6|>=5,<5.0.2", + "tribalsystems/zenario": "<=9.7.61188", + "truckersmp/phpwhois": "<=4.3.1", + "ttskch/pagination-service-provider": "<1", + "twbs/bootstrap": "<3.4.1|>=4,<4.3.1", + "twig/twig": "<3.11.2|>=3.12,<3.14.1|>=3.16,<3.19", + "typo3/cms": "<9.5.29|>=10,<10.4.35|>=11,<11.5.23|>=12,<12.2", + "typo3/cms-backend": "<4.1.14|>=4.2,<4.2.15|>=4.3,<4.3.7|>=4.4,<4.4.4|>=7,<=7.6.50|>=8,<=8.7.39|>=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/cms-belog": ">=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", + "typo3/cms-beuser": ">=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/cms-core": "<=8.7.56|>=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/cms-dashboard": ">=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/cms-extbase": "<6.2.24|>=7,<7.6.8|==8.1.1", + "typo3/cms-extensionmanager": ">=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", + "typo3/cms-felogin": ">=4.2,<4.2.3", + "typo3/cms-fluid": "<4.3.4|>=4.4,<4.4.1", + "typo3/cms-form": ">=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", + "typo3/cms-frontend": "<4.3.9|>=4.4,<4.4.5", + "typo3/cms-indexed-search": ">=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", + "typo3/cms-install": "<4.1.14|>=4.2,<4.2.16|>=4.3,<4.3.9|>=4.4,<4.4.5|>=12.2,<12.4.8|==13.4.2", + "typo3/cms-lowlevel": ">=11,<=11.5.41", + "typo3/cms-recordlist": ">=11,<11.5.48", + "typo3/cms-recycler": ">=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/cms-rte-ckeditor": ">=9.5,<9.5.42|>=10,<10.4.39|>=11,<11.5.30", + "typo3/cms-scheduler": ">=11,<=11.5.41", + "typo3/cms-setup": ">=9,<=9.5.50|>=10,<=10.4.49|>=11,<=11.5.43|>=12,<=12.4.30|>=13,<=13.4.11", + "typo3/cms-webhooks": ">=12,<=12.4.30|>=13,<=13.4.11", + "typo3/cms-workspaces": ">=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", + "typo3/html-sanitizer": ">=1,<=1.5.2|>=2,<=2.1.3", + "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.3.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3", + "typo3/phar-stream-wrapper": ">=1,<2.1.1|>=3,<3.1.1", + "typo3/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", + "typo3fluid/fluid": ">=2,<2.0.8|>=2.1,<2.1.7|>=2.2,<2.2.4|>=2.3,<2.3.7|>=2.4,<2.4.4|>=2.5,<2.5.11|>=2.6,<2.6.10", + "ua-parser/uap-php": "<3.8", + "uasoft-indonesia/badaso": "<=2.9.7", + "unisharp/laravel-filemanager": "<2.9.1", + "universal-omega/dynamic-page-list3": "<3.6.4", + "unopim/unopim": "<=0.3", + "userfrosting/userfrosting": ">=0.3.1,<4.6.3", + "usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2", + "uvdesk/community-skeleton": "<=1.1.1", + "uvdesk/core-framework": "<=1.1.1", + "vanilla/safecurl": "<0.9.2", + "verbb/comments": "<1.5.5", + "verbb/formie": "<=2.1.43", + "verbb/image-resizer": "<2.0.9", + "verbb/knock-knock": "<1.2.8", + "verot/class.upload.php": "<=2.1.6", + "vertexvaar/falsftp": "<0.2.6", + "villagedefrance/opencart-overclocked": "<=1.11.1", + "vova07/yii2-fileapi-widget": "<0.1.9", + "vrana/adminer": "<=4.8.1", + "vufind/vufind": ">=2,<9.1.1", + "waldhacker/hcaptcha": "<2.1.2", + "wallabag/tcpdf": "<6.2.22", + "wallabag/wallabag": "<2.6.11", + "wanglelecc/laracms": "<=1.0.3", + "wapplersystems/a21glossary": "<=0.4.10", + "web-auth/webauthn-framework": ">=3.3,<3.3.4|>=4.5,<4.9", + "web-auth/webauthn-lib": ">=4.5,<4.9", + "web-feet/coastercms": "==5.5", + "web-tp3/wec_map": "<3.0.3", + "webbuilders-group/silverstripe-kapost-bridge": "<0.4", + "webcoast/deferred-image-processing": "<1.0.2", + "webklex/laravel-imap": "<5.3", + "webklex/php-imap": "<5.3", + "webpa/webpa": "<3.1.2", + "webreinvent/vaahcms": "<=2.3.1", + "wikibase/wikibase": "<=1.39.3", + "wikimedia/parsoid": "<0.12.2", + "willdurand/js-translation-bundle": "<2.1.1", + "winter/wn-backend-module": "<1.2.4", + "winter/wn-cms-module": "<1.0.476|>=1.1,<1.1.11|>=1.2,<1.2.7", + "winter/wn-dusk-plugin": "<2.1", + "winter/wn-system-module": "<1.2.4", + "wintercms/winter": "<=1.2.3", + "wireui/wireui": "<1.19.3|>=2,<2.1.3", + "woocommerce/woocommerce": "<6.6|>=8.8,<8.8.5|>=8.9,<8.9.3", + "wp-cli/wp-cli": ">=0.12,<2.5", + "wp-graphql/wp-graphql": "<=1.14.5", + "wp-premium/gravityforms": "<2.4.21", + "wpanel/wpanel4-cms": "<=4.3.1", + "wpcloud/wp-stateless": "<3.2", + "wpglobus/wpglobus": "<=1.9.6", + "wwbn/avideo": "<14.3", + "xataface/xataface": "<3", + "xpressengine/xpressengine": "<3.0.15", + "yab/quarx": "<2.4.5", + "yeswiki/yeswiki": "<=4.5.4", + "yetiforce/yetiforce-crm": "<6.5", + "yidashi/yii2cmf": "<=2", + "yii2mod/yii2-cms": "<1.9.2", + "yiisoft/yii": "<1.1.31", + "yiisoft/yii2": "<2.0.52", + "yiisoft/yii2-authclient": "<2.2.15", + "yiisoft/yii2-bootstrap": "<2.0.4", + "yiisoft/yii2-dev": "<=2.0.45", + "yiisoft/yii2-elasticsearch": "<2.0.5", + "yiisoft/yii2-gii": "<=2.2.4", + "yiisoft/yii2-jui": "<2.0.4", + "yiisoft/yii2-redis": "<2.0.20", + "yikesinc/yikes-inc-easy-mailchimp-extender": "<6.8.6", + "yoast-seo-for-typo3/yoast_seo": "<7.2.3", + "yourls/yourls": "<=1.8.2", + "yuan1994/tpadmin": "<=1.3.12", + "z-push/z-push-dev": "<2.7.6", + "zencart/zencart": "<=1.5.7.0-beta", + "zendesk/zendesk_api_client_php": "<2.2.11", + "zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3", + "zendframework/zend-captcha": ">=2,<2.4.9|>=2.5,<2.5.2", + "zendframework/zend-crypt": ">=2,<2.4.9|>=2.5,<2.5.2", + "zendframework/zend-db": "<2.2.10|>=2.3,<2.3.5", + "zendframework/zend-developer-tools": ">=1.2.2,<1.2.3", + "zendframework/zend-diactoros": "<1.8.4", + "zendframework/zend-feed": "<2.10.3", + "zendframework/zend-form": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-http": "<2.8.1", + "zendframework/zend-json": ">=2.1,<2.1.6|>=2.2,<2.2.6", + "zendframework/zend-ldap": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.8|>=2.3,<2.3.3", + "zendframework/zend-mail": "<2.4.11|>=2.5,<2.7.2", + "zendframework/zend-navigation": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-session": ">=2,<2.2.9|>=2.3,<2.3.4", + "zendframework/zend-validator": ">=2.3,<2.3.6", + "zendframework/zend-view": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-xmlrpc": ">=2.1,<2.1.6|>=2.2,<2.2.6", + "zendframework/zendframework": "<=3", + "zendframework/zendframework1": "<1.12.20", + "zendframework/zendopenid": "<2.0.2", + "zendframework/zendrest": "<2.0.2", + "zendframework/zendservice-amazon": "<2.0.3", + "zendframework/zendservice-api": "<1", + "zendframework/zendservice-audioscrobbler": "<2.0.2", + "zendframework/zendservice-nirvanix": "<2.0.2", + "zendframework/zendservice-slideshare": "<2.0.2", + "zendframework/zendservice-technorati": "<2.0.2", + "zendframework/zendservice-windowsazure": "<2.0.2", + "zendframework/zendxml": ">=1,<1.0.1", + "zenstruck/collection": "<0.2.1", + "zetacomponents/mail": "<1.8.2", + "zf-commons/zfc-user": "<1.2.2", + "zfcampus/zf-apigility-doctrine": ">=1,<1.0.3", + "zfr/zfr-oauth2-server-module": "<0.1.2", + "zoujingli/thinkadmin": "<=6.1.53" + }, + "default-branch": true, + "type": "metapackage", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "role": "maintainer" + }, + { + "name": "Ilya Tribusean", + "email": "slash3b@gmail.com", + "role": "maintainer" + } + ], + "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", + "keywords": [ + "dev" + ], + "support": { + "issues": "https://github.com/Roave/SecurityAdvisories/issues", + "source": "https://github.com/Roave/SecurityAdvisories/tree/latest" + }, + "funding": [ + { + "url": "https://github.com/Ocramius", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/roave/security-advisories", + "type": "tidelift" + } + ], + "time": "2025-10-21T21:05:51+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "4.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "90f41072d220e5c40df6e8635f5dafba2d9d4d04" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/90f41072d220e5c40df6e8635f5dafba2d9d4d04", + "reference": "90f41072d220e5c40df6e8635f5dafba2d9d4d04", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/4.2.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/cli-parser", + "type": "tidelift" + } + ], + "time": "2025-09-14T09:36:45+00:00" + }, + { + "name": "sebastian/comparator", + "version": "7.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "dc904b4bb3ab070865fa4068cd84f3da8b945148" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/dc904b4bb3ab070865fa4068cd84f3da8b945148", + "reference": "dc904b4bb3ab070865fa4068cd84f3da8b945148", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.3", + "sebastian/diff": "^7.0", + "sebastian/exporter": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^12.2" + }, + "suggest": { + "ext-bcmath": "For comparing BcMath\\Number objects" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/7.1.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" + } + ], + "time": "2025-08-20T11:27:00+00:00" + }, + { + "name": "sebastian/complexity", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "bad4316aba5303d0221f43f8cee37eb58d384bbb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/bad4316aba5303d0221f43f8cee37eb58d384bbb", + "reference": "bad4316aba5303d0221f43f8cee37eb58d384bbb", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:55:25+00:00" + }, + { + "name": "sebastian/diff", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "7ab1ea946c012266ca32390913653d844ecd085f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7ab1ea946c012266ca32390913653d844ecd085f", + "reference": "7ab1ea946c012266ca32390913653d844ecd085f", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0", + "symfony/process": "^7.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/7.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:55:46+00:00" + }, + { + "name": "sebastian/environment", + "version": "8.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "24a711b5c916efc6d6e62aa65aa2ec98fef77f68" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/24a711b5c916efc6d6e62aa65aa2ec98fef77f68", + "reference": "24a711b5c916efc6d6e62aa65aa2ec98fef77f68", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/8.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/environment", + "type": "tidelift" + } + ], + "time": "2025-08-12T14:11:56+00:00" + }, + { + "name": "sebastian/exporter", + "version": "7.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "016951ae10980765e4e7aee491eb288c64e505b7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/016951ae10980765e4e7aee491eb288c64e505b7", + "reference": "016951ae10980765e4e7aee491eb288c64e505b7", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.3", + "sebastian/recursion-context": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/7.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", + "type": "tidelift" + } + ], + "time": "2025-09-24T06:16:11+00:00" + }, + { + "name": "sebastian/global-state", + "version": "8.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "ef1377171613d09edd25b7816f05be8313f9115d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/ef1377171613d09edd25b7816f05be8313f9115d", + "reference": "ef1377171613d09edd25b7816f05be8313f9115d", + "shasum": "" + }, + "require": { + "php": ">=8.3", + "sebastian/object-reflector": "^5.0", + "sebastian/recursion-context": "^7.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/8.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/global-state", + "type": "tidelift" + } + ], + "time": "2025-08-29T11:29:25+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "97ffee3bcfb5805568d6af7f0f893678fc076d2f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/97ffee3bcfb5805568d6af7f0f893678fc076d2f", + "reference": "97ffee3bcfb5805568d6af7f0f893678fc076d2f", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:57:28+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "1effe8e9b8e068e9ae228e542d5d11b5d16db894" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1effe8e9b8e068e9ae228e542d5d11b5d16db894", + "reference": "1effe8e9b8e068e9ae228e542d5d11b5d16db894", + "shasum": "" + }, + "require": { + "php": ">=8.3", + "sebastian/object-reflector": "^5.0", + "sebastian/recursion-context": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/7.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:57:48+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "4bfa827c969c98be1e527abd576533293c634f6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/4bfa827c969c98be1e527abd576533293c634f6a", + "reference": "4bfa827c969c98be1e527abd576533293c634f6a", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:58:17+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "7.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "0b01998a7d5b1f122911a66bebcb8d46f0c82d8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/0b01998a7d5b1f122911a66bebcb8d46f0c82d8c", + "reference": "0b01998a7d5b1f122911a66bebcb8d46f0c82d8c", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/7.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", + "type": "tidelift" + } + ], + "time": "2025-08-13T04:44:59+00:00" + }, + { + "name": "sebastian/type", + "version": "6.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "e549163b9760b8f71f191651d22acf32d56d6d4d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/e549163b9760b8f71f191651d22acf32d56d6d4d", + "reference": "e549163b9760b8f71f191651d22acf32d56d6d4d", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/6.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/type", + "type": "tidelift" + } + ], + "time": "2025-08-09T06:57:12+00:00" + }, + { + "name": "sebastian/version", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "3e6ccf7657d4f0a59200564b08cead899313b53c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/3e6ccf7657d4f0a59200564b08cead899313b53c", + "reference": "3e6ccf7657d4f0a59200564b08cead899313b53c", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T05:00:38+00:00" + }, + { + "name": "staabm/side-effects-detector", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2024-10-20T05:08:20+00:00" + }, + { + "name": "symfony/console", + "version": "v7.3.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "2b9c5fafbac0399a20a2e82429e2bd735dcfb7db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/2b9c5fafbac0399a20a2e82429e2bd735dcfb7db", + "reference": "2b9c5fafbac0399a20a2e82429e2bd735dcfb7db", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^7.2" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v7.3.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-09-22T15:31:00+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b7dc69e71de420ac04bc9ab830cf3ffebba48191", + "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/event-dispatcher-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/service-contracts": "<2.5" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-13T11:49:31+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/edcbb768a186b5c3f25d0643159a787d3e63b7fd", + "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "require-dev": { + "symfony/process": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-07T08:17:47+00:00" + }, + { + "name": "symfony/finder", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe", + "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/filesystem": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-15T13:41:35+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/0ff2f5c3df08a395232bbc3c2eb7e84912df911d", + "reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-05T10:16:07+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-06-27T09:58:17+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "3833d7255cc303546435cb650316bff708a1c75c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-12-23T08:48:59+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-01-02T08:10:11+00:00" + }, + { + "name": "symfony/polyfill-php81", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php84", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php84.git", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php84\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-06-24T13:30:11+00:00" + }, + { + "name": "symfony/process", + "version": "v7.3.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "f24f8f316367b30810810d4eb30c543d7003ff3b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/f24f8f316367b30810810d4eb30c543d7003ff3b", + "reference": "f24f8f316367b30810810d4eb30c543d7003ff3b", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v7.3.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-09-11T10:12:26+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-25T09:37:31+00:00" + }, + { + "name": "symfony/stopwatch", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd", + "reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/service-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a way to profile code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-02-24T10:49:57+00:00" + }, + { + "name": "symfony/string", + "version": "v7.3.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "f96476035142921000338bad71e5247fbc138872" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/f96476035142921000338bad71e5247fbc138872", + "reference": "f96476035142921000338bad71e5247fbc138872", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/emoji": "^7.1", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v7.3.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-09-11T14:36:48+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } ], - "time": "2020-07-08T17:02:28+00:00" + "time": "2024-03-03T12:36:25+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "roave/security-advisories": 20 + }, "prefer-stable": false, "prefer-lowest": false, - "platform": [], - "platform-dev": [], - "plugin-api-version": "1.1.0" + "platform": { + "php": ">=8.1", + "ext-pdo": "*" + }, + "platform-dev": {}, + "plugin-api-version": "2.6.0" } diff --git a/readme.md b/readme.md index 228db07..8b4982a 100644 --- a/readme.md +++ b/readme.md @@ -1,7 +1,21 @@ -# FluentPDO [![Build Status](https://secure.travis-ci.org/envms/fluentpdo.png?branch=master)](http://travis-ci.org/envms/fluentpdo) [![Maintainability](https://api.codeclimate.com/v1/badges/19210ca91c7055b89705/maintainability)](https://codeclimate.com/github/fpdo/fluentpdo/maintainability) +# FluentPDO - PHP 8.1+ Edition + +**A modernized fork of the original FluentPDO project, updated for PHP 8.1+ with modern type declarations and enhanced features.** FluentPDO is a PHP SQL query builder using PDO. It's a quick and light library featuring a smart join builder, which automatically creates table joins for you. +## About This Fork + +This is a modernized fork of the original [envms/fluentpdo](https://github.com/envms/fluentpdo) project. Since the original project has been inactive for 3+ years (last commit in 2021), this fork provides: + +- **PHP 8.1+ compatibility** with modern type declarations +- **Strict typing** throughout the codebase +- **Union types** and **mixed types** where appropriate +- **Typed properties** for better IDE support +- **Array parameter handling** with automatic JSON serialization +- **Enhanced error handling** and debugging capabilities +- **Updated dependencies** and development tools + ## Features - Easy interface for creating robust queries @@ -9,25 +23,22 @@ FluentPDO is a PHP SQL query builder using PDO. It's a quick and light library f - Ability to build complex SELECT, INSERT, UPDATE & DELETE queries with little code - Type hinting for magic methods with code completion in smart IDEs -## Versions +## PHP Version Requirements -#### Version 2.x +**This fork requires PHP 8.1 or higher.** -The stable release of FluentPDO and actively maintained. Officially supports PHP 7.3 to PHP 8.0, -but it can work with previous versions of PHP 7. +### What's New in This PHP 8.1+ Edition -#### Version 1.x +- **Modern Type System**: Full use of PHP 8.1+ type declarations including union types +- **Strict Types**: All files use `declare(strict_types=1)` for better type safety +- **Array Handling**: Automatic JSON serialization of array parameters to prevent SQL errors +- **Enhanced Performance**: Better memory usage and performance through strict typing +- **Developer Experience**: Improved IDE support with proper type hints and autocomplete +- **Future Ready**: Prepared for upcoming PHP versions -The legacy release of FluentPDO. It is no longer supported and will not be maintained or updated. -This version works with PHP 5.4 to 7.1. +### Migrating from Original FluentPDO -#### Version 3.x - alpha - -This version is a full rewrite of Fluent from the ground up. Its main advantage is -significantly less memory usage and much greater performance in query building. It also places -a few additional restrictions to make queries easier to read and maintain. Documentation has also -been a very common request, and version 3 is being fully documented alongside development. -Details and metrics will be posted once available. +If you're upgrading from the original FluentPDO (v2.x), this version maintains API compatibility while requiring PHP 8.1+. The main changes are internal improvements and type safety enhancements. ## Reference @@ -37,34 +48,42 @@ Details and metrics will be posted once available. ### Composer -The preferred way to install FluentPDO is via [composer](http://getcomposer.org/). - -Add the following line in your `composer.json` file: +The preferred way to install this PHP 8.1+ edition of FluentPDO is via [composer](http://getcomposer.org/). - "require": { - ... - "envms/fluentpdo": "^2.2.0" - } +```bash +composer require vitexsoftware/fluentpdo +``` -update your dependencies with `composer update`, and you're done! +Or add the following line in your `composer.json` file: -### Download Zip +```json +{ + "require": { + "vitexsoftware/fluentpdo": "^3.0" + } +} +``` -If you prefer not to use composer, download the latest release, create the directory `Envms/FluentPDO` in your library directory, and drop this repository into it. Finally, add: +Then run `composer update` and you're done! -```php -require '[lib-dir]/Envms/FluentPDO/src/Query.php'; -``` +### Requirements -to the top of your application. **Note:** You will need an autoloader to use FluentPDO without changing its source code. +- **PHP 8.1+** (required) +- **PDO extension** (required) +- Any PDO-compatible database (MySQL, PostgreSQL, SQLite, etc.) ## Getting Started Create a new PDO instance, and pass the instance to FluentPDO: ```php +insertInto('article', $values)->execute(); // shorter version ##### UPDATE ```php -$set = array('published_at' => new FluentLiteral('NOW()')); +use Envms\FluentPDO\Literal; + +$set = ['published_at' => new Literal('NOW()')]; $query = $fluent->update('article')->set($set)->where('id', 1)->execute(); $query = $fluent->update('article', $set, 1)->execute(); // shorter version if updating one row by primary key @@ -174,6 +195,43 @@ $query = $fluent->deleteFrom('article', 1)->execute(); // shorter version if del ***Note**: INSERT, UPDATE and DELETE queries will only run after you call `->execute()`* +## Modern PHP 8.1+ Features + +### Array Parameter Handling + +This edition automatically handles array parameters by converting them to JSON strings: + +```php +// Arrays are automatically converted to JSON +$data = [ + 'name' => 'John Doe', + 'tags' => ['php', 'mysql', 'programming'], // Automatically converts to JSON + 'metadata' => ['created' => '2025-01-01', 'active' => true] +]; + +$fluent->insertInto('users', $data)->execute(); +``` + +### Strict Type Declarations + +All classes use strict typing for better performance and error detection: + +```php + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Envms\FluentPDO; /** - * Class Exception + * Class Exception. */ class Exception extends \Exception { - } diff --git a/src/Literal.php b/src/Literal.php index 57bc755..a157cb7 100644 --- a/src/Literal.php +++ b/src/Literal.php @@ -1,34 +1,38 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Envms\FluentPDO; /** - * SQL literal value + * SQL literal value. */ class Literal { - - /** @var string */ - protected $value = ''; + protected string $value = ''; /** - * Create literal value - * - * @param string $value + * Create literal value. */ - function __construct($value) + public function __construct(string $value) { $this->value = $value; } /** - * Get literal value - * - * @return string + * Get literal value. */ - function __toString() + public function __toString(): string { return $this->value; } - } diff --git a/src/Queries/Base.php b/src/Queries/Base.php index 52a986d..e394d8a 100644 --- a/src/Queries/Base.php +++ b/src/Queries/Base.php @@ -1,56 +1,64 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Envms\FluentPDO\Queries; -use DateTime, IteratorAggregate, PDO, PDOStatement; -use Envms\FluentPDO\{Exception, Literal, Query, Regex, Structure, Utilities}; +use Envms\FluentPDO\Exception; +use Envms\FluentPDO\Literal; +use Envms\FluentPDO\Query; +use Envms\FluentPDO\Regex; +use Envms\FluentPDO\Structure; +use Envms\FluentPDO\Utilities; +use IteratorAggregate; +use PDO; +use PDOStatement; /** - * Base query builder + * Base query builder. */ -abstract class Base implements IteratorAggregate +abstract class Base implements \IteratorAggregate { + protected Query $fluent; - /** @var float */ - private $totalTime; + protected null|bool|\PDOStatement $result; + + /** + * @var array - definition clauses + */ + protected array $clauses = []; - /** @var float */ - private $executionTime; + protected array $statements = []; - /** @var bool */ - private $object = false; + protected array $parameters = []; - /** @var Query */ - protected $fluent; + protected Regex $regex; - /** @var PDOStatement|null|bool */ - protected $result; + protected string $message = ''; - /** @var array - definition clauses */ - protected $clauses = []; - /** @var array */ - protected $statements = []; - /** @var array */ - protected $parameters = []; + protected int $currentFetchMode; - /** @var Regex */ - protected $regex; + private float $totalTime; - /** @var string */ - protected $message = ''; + private float $executionTime; - /** @var int */ - protected $currentFetchMode; + private bool $object = false; /** * BaseQuery constructor. - * - * @param Query $fluent - * @param $clauses */ protected function __construct(Query $fluent, $clauses) { - $this->currentFetchMode = defined('PDO::FETCH_DEFAULT') ? PDO::FETCH_DEFAULT : PDO::FETCH_BOTH; + $this->currentFetchMode = \defined('PDO::FETCH_DEFAULT') ? \PDO::FETCH_DEFAULT : \PDO::FETCH_BOTH; $this->fluent = $fluent; $this->clauses = $clauses; $this->result = null; @@ -62,11 +70,11 @@ protected function __construct(Query $fluent, $clauses) /** * Return formatted query when request class representation - * ie: echo $query - * - * @return string - formatted query + * ie: echo $query. * * @throws Exception + * + * @return string - formatted query */ public function __toString() { @@ -74,104 +82,11 @@ public function __toString() } /** - * Initialize statement and parameter clauses. - */ - private function initClauses(): void - { - foreach ($this->clauses as $clause => $value) { - if ($value) { - $this->statements[$clause] = []; - $this->parameters[$clause] = []; - } else { - $this->statements[$clause] = null; - $this->parameters[$clause] = null; - } - } - } - - /** - * Add statement for all clauses except WHERE - * - * @param $clause - * @param $statement - * @param array $parameters - * - * @return $this - */ - protected function addStatement($clause, $statement, $parameters = []) - { - if ($statement === null) { - return $this->resetClause($clause); - } - - if ($this->clauses[$clause]) { - if (is_array($statement)) { - $this->statements[$clause] = array_merge($this->statements[$clause], $statement); - } else { - $this->statements[$clause][] = $statement; - } - - $this->parameters[$clause] = array_merge($this->parameters[$clause], $parameters); - } else { - $this->statements[$clause] = $statement; - $this->parameters[$clause] = $parameters; - } - - return $this; - } - - /** - * Add statement for all kind of clauses - * - * @param $statement - * @param string $separator - should be AND or OR - * @param array $parameters - * - * @return $this - */ - protected function addWhereStatement($statement, string $separator = 'AND', $parameters = []) - { - if ($statement === null) { - return $this->resetClause('WHERE'); - } - - if (is_array($statement)) { - foreach ($statement as $s) { - $this->statements['WHERE'][] = [$separator, $s]; - } - } else { - $this->statements['WHERE'][] = [$separator, $statement]; - } - - $this->parameters['WHERE'] = array_merge($this->parameters['WHERE'], $parameters); - - return $this; - } - - /** - * Remove all prev defined statements - * - * @param $clause - * - * @return $this - */ - protected function resetClause($clause) - { - $this->statements[$clause] = null; - $this->parameters[$clause] = []; - if (isset($this->clauses[$clause]) && $this->clauses[$clause]) { - $this->statements[$clause] = []; - } - - return $this; - } - - /** - * Implements method from IteratorAggregate - * - * @return PDOStatement + * Implements method from IteratorAggregate. * * @throws Exception + * + * @return \PDOStatement */ #[\ReturnTypeWillChange] public function getIterator(): \Traversable @@ -180,11 +95,11 @@ public function getIterator(): \Traversable } /** - * Execute query with earlier added parameters - * - * @return PDOStatement + * Execute query with earlier added parameters. * * @throws Exception + * + * @return \PDOStatement */ public function execute() { @@ -208,17 +123,9 @@ public function execute() } /** - * @return Structure - */ - protected function getStructure(): Structure - { - return $this->fluent->getStructure(); - } - - /** - * Get PDOStatement result + * Get PDOStatement result. * - * @return PDOStatement|null|bool + * @return null|bool|\PDOStatement */ public function getResult() { @@ -226,43 +133,30 @@ public function getResult() } /** - * Get query parameters - * - * @return array + * Get query parameters. */ public function getParameters(): array { return $this->buildParameters(); } - /** - * @return array - */ public function getRawClauses(): array { return $this->clauses; } - /** - * @return array - */ public function getRawStatements(): array { return $this->statements; } - /** - * @return array - */ public function getRawParameters(): array { return $this->parameters; } /** - * Gets the total time of query building, preparation and execution - * - * @return float + * Gets the total time of query building, preparation and execution. */ public function getTotalTime(): float { @@ -270,29 +164,23 @@ public function getTotalTime(): float } /** - * Gets the query execution time - * - * @return float + * Gets the query execution time. */ public function getExecutionTime(): float { return $this->executionTime; } - /** - * @return string - */ public function getMessage(): string { return $this->message; } /** - * Get query string + * Get query string. * * @param bool $formatted - Return formatted query * - * @return string * @throws Exception */ public function getQuery(bool $formatted = true): string @@ -307,11 +195,11 @@ public function getQuery(bool $formatted = true): string } /** - * Select an item as object + * Select an item as object. * - * @param object|boolean $object If set to true, items are returned as stdClass, otherwise a class - * name can be passed and a new instance of this class is returned. - * Can be set to false to return items as an associative array. + * @param bool|object $object If set to true, items are returned as stdClass, otherwise a class + * name can be passed and a new instance of this class is returned. + * Can be set to false to return items as an associative array. * * @return $this */ @@ -323,16 +211,94 @@ public function asObject($object = true) } /** - * Converts php null values to Literal instances to be inserted into a database + * Add statement for all clauses except WHERE. + * + * @param array $parameters + * + * @return $this + */ + protected function addStatement($clause, $statement, $parameters = []) + { + if ($statement === null) { + return $this->resetClause($clause); + } + + if ($this->clauses[$clause]) { + if (\is_array($statement)) { + $this->statements[$clause] = array_merge($this->statements[$clause], $statement); + } else { + $this->statements[$clause][] = $statement; + } + + $this->parameters[$clause] = array_merge($this->parameters[$clause], $parameters); + } else { + $this->statements[$clause] = $statement; + $this->parameters[$clause] = $parameters; + } + + return $this; + } + + /** + * Add statement for all kind of clauses. + * + * @param string $separator - should be AND or OR + * @param array $parameters + * + * @return $this + */ + protected function addWhereStatement($statement, string $separator = 'AND', $parameters = []) + { + if ($statement === null) { + return $this->resetClause('WHERE'); + } + + if (\is_array($statement)) { + foreach ($statement as $s) { + $this->statements['WHERE'][] = [$separator, $s]; + } + } else { + $this->statements['WHERE'][] = [$separator, $statement]; + } + + $this->parameters['WHERE'] = array_merge($this->parameters['WHERE'], $parameters); + + return $this; + } + + /** + * Remove all prev defined statements. + * + * @return $this + */ + protected function resetClause($clause) + { + $this->statements[$clause] = null; + $this->parameters[$clause] = []; + + if (isset($this->clauses[$clause]) && $this->clauses[$clause]) { + $this->statements[$clause] = []; + } + + return $this; + } + + protected function getStructure(): Structure + { + return $this->fluent->getStructure(); + } + + /** + * Converts php null values to Literal instances to be inserted into a database. */ protected function convertNullValues(): void { $filterList = ['VALUES', 'ON DUPLICATE KEY UPDATE', 'SET']; foreach ($this->statements as $clause => $statement) { - if (in_array($clause, $filterList)) { + if (\in_array($clause, $filterList, true)) { if (isset($statement[0])) { - for ($i = 0, $iMax = count($statement); $i < $iMax; $i++) { + for ($i = 0, $iMax = \count($statement); $i < $iMax; ++$i) { foreach ($statement[$i] as $key => $value) { $this->statements[$clause][$i][$key] = Utilities::nullToLiteral($value); } @@ -347,10 +313,11 @@ protected function convertNullValues(): void } /** - * Generate query + * Generate query. * - * @return string * @throws Exception + * + * @return string */ protected function buildQuery() { @@ -362,14 +329,14 @@ protected function buildQuery() foreach ($this->clauses as $clause => $separator) { if ($this->clauseNotEmpty($clause)) { - if (is_string($separator)) { - $query .= " {$clause} " . implode($separator, $this->statements[$clause]); + if (\is_string($separator)) { + $query .= " {$clause} ".implode($separator, $this->statements[$clause]); } elseif ($separator === null) { $query .= " {$clause} {$this->statements[$clause]}"; - } elseif (is_callable($separator)) { + } elseif (\is_callable($separator)) { $query .= $separator(); } else { - throw new Exception("Clause '$clause' is incorrectly set to '$separator'."); + throw new Exception("Clause '{$clause}' is incorrectly set to '{$separator}'."); } } } @@ -377,25 +344,23 @@ protected function buildQuery() return trim(str_replace(['\.', '\:'], ['.', ':'], $query)); } - /** - * @return array - */ protected function buildParameters(): array { $parameters = []; + foreach ($this->parameters as $clauses) { if ($this->fluent->convertWrite === true) { $clauses = Utilities::convertSqlWriteValues($clauses); } - if (is_array($clauses)) { + if (\is_array($clauses)) { foreach ($clauses as $key => $value) { // Convert arrays to JSON strings for PDO compatibility - if (is_array($value)) { + if (\is_array($value)) { $value = json_encode($value); } - - if (strpos($key, ':') === 0) { // these are named params e.g. (':name' => 'Mark') + + if (str_starts_with($key, ':')) { // these are named params e.g. (':name' => 'Mark') $parameters += [$key => $value]; } else { $parameters[] = $value; @@ -403,9 +368,10 @@ protected function buildParameters(): array } } elseif ($clauses !== false && $clauses !== null) { // Convert arrays to JSON strings for PDO compatibility - if (is_array($clauses)) { + if (\is_array($clauses)) { $clauses = json_encode($clauses); } + $parameters[] = $clauses; } } @@ -414,23 +380,22 @@ protected function buildParameters(): array } /** - * @param $value - * * @return string */ protected function quote($value) { if (!isset($value)) { - return "NULL"; + return 'NULL'; } - if (is_array($value)) { // (a, b) IN ((1, 2), (3, 4)) - return "(" . implode(", ", array_map([$this, 'quote'], $value)) . ")"; + if (\is_array($value)) { // (a, b) IN ((1, 2), (3, 4)) + return '('.implode(', ', array_map([$this, 'quote'], $value)).')'; } - $value = $this->formatValue($value); - if (is_float($value)) { - return sprintf("%F", $value); // otherwise depends on setlocale() + $value = self::formatValue($value); + + if (\is_float($value)) { + return sprintf('%F', $value); // otherwise depends on setlocale() } if ($value === true) { @@ -441,25 +406,39 @@ protected function quote($value) return 0; } - if (is_int($value) || $value instanceof Literal) { // number or SQL code - for example "NOW()" - return (string)$value; + if (\is_int($value) || $value instanceof Literal) { // number or SQL code - for example "NOW()" + return (string) $value; } return $this->fluent->getPdo()->quote($value); } /** - * @param $clause - * + * Initialize statement and parameter clauses. + */ + private function initClauses(): void + { + foreach ($this->clauses as $clause => $value) { + if ($value) { + $this->statements[$clause] = []; + $this->parameters[$clause] = []; + } else { + $this->statements[$clause] = null; + $this->parameters[$clause] = null; + } + } + } + + /** * @return bool */ private function clauseNotEmpty($clause) { - if ((Utilities::isCountable($this->statements[$clause])) && $this->clauses[$clause]) { - return (bool)count($this->statements[$clause]); + if (Utilities::isCountable($this->statements[$clause]) && $this->clauses[$clause]) { + return (bool) \count($this->statements[$clause]); } - return (bool)$this->statements[$clause]; + return (bool) $this->statements[$clause]; } /** @@ -467,9 +446,9 @@ private function clauseNotEmpty($clause) * * @return mixed */ - private function formatValue($val) + private static function formatValue($val) { - if ($val instanceof DateTime) { + if ($val instanceof \DateTime) { return $val->format('Y-m-d H:i:s'); // may be driver specific } @@ -493,7 +472,7 @@ private function prepareQuery($query): void prepare function until we call PDOStatement::execute() below. If PDO::prepare() was consistent, this is where we would check for prepare errors, such as invalid SQL. - */ + */ if ($this->result === false) { $error = $this->fluent->getPdo()->errorInfo(); @@ -529,41 +508,38 @@ private function executeQuery($parameters, $startTime, $execTime): void } } - /** - * @param PDOStatement $result - */ - private function setObjectFetchMode(PDOStatement $result): void + private function setObjectFetchMode(\PDOStatement $result): void { if ($this->object !== false) { if (class_exists($this->object)) { - $this->currentFetchMode = PDO::FETCH_CLASS; + $this->currentFetchMode = \PDO::FETCH_CLASS; $result->setFetchMode($this->currentFetchMode, $this->object); } else { - $this->currentFetchMode = PDO::FETCH_OBJ; + $this->currentFetchMode = \PDO::FETCH_OBJ; $result->setFetchMode($this->currentFetchMode); } - } elseif ($this->fluent->getPdo()->getAttribute(PDO::ATTR_DEFAULT_FETCH_MODE) === PDO::FETCH_BOTH) { - $this->currentFetchMode = PDO::FETCH_ASSOC; + } elseif ($this->fluent->getPdo()->getAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE) === \PDO::FETCH_BOTH) { + $this->currentFetchMode = \PDO::FETCH_ASSOC; $result->setFetchMode($this->currentFetchMode); } } /** - * Echo/pass a debug string + * Echo/pass a debug string. * * @throws Exception */ - private function debug() + private function debug(): void { if (!empty($this->fluent->debug)) { - if (!is_callable($this->fluent->debug)) { + if (!\is_callable($this->fluent->debug)) { $backtrace = ''; $query = $this->getQuery(); $parameters = $this->getParameters(); $debug = ''; if ($parameters) { - $debug = '# parameters: ' . implode(', ', array_map([$this, 'quote'], $parameters)) . "\n"; + $debug = '# parameters: '.implode(', ', array_map([$this, 'quote'], $parameters))."\n"; } $debug .= $query; @@ -575,13 +551,13 @@ private function debug() } } - $time = sprintf('%0.3f', $this->totalTime * 1000) . 'ms'; + $time = sprintf('%0.3f', $this->totalTime * 1000).'ms'; $rows = ($this->result) ? $this->result->rowCount() : 0; $finalString = "# {$backtrace['file']}:{$backtrace['line']} ({$time}; rows = {$rows})\n{$debug}\n\n"; // if STDERR is set, send there, otherwise just output the string - if (defined('STDERR') && is_resource(STDERR)) { - fwrite(STDERR, $finalString); + if (\defined('STDERR') && \is_resource(\STDERR)) { + fwrite(\STDERR, $finalString); } else { echo $finalString; } diff --git a/src/Queries/Common.php b/src/Queries/Common.php index fefd253..d84c0e3 100644 --- a/src/Queries/Common.php +++ b/src/Queries/Common.php @@ -1,33 +1,57 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Envms\FluentPDO\Queries; -use Envms\FluentPDO\{Exception, Literal, Utilities}; +use Envms\FluentPDO\Exception; +use Envms\FluentPDO\Literal; +use Envms\FluentPDO\Utilities; /** - * CommonQuery add JOIN and WHERE clauses for (SELECT, UPDATE, DELETE) + * CommonQuery add JOIN and WHERE clauses for (SELECT, UPDATE, DELETE). * - * @method $this from(string $table) - add FROM to DELETE query - * @method $this leftJoin(string $statement) - add LEFT JOIN to query - * $statement can be the 'table' name only or 'table:' to back reference the join - * @method $this rightJoin(string $statement) - add RIGHT JOIN to query - * @method $this innerJoin(string $statement) - add INNER JOIN to query - * @method $this outerJoin(string $statement) - add OUTER JOIN to query - * @method $this fullJoin(string $statement) - add FULL JOIN to query - * @method $this group(string $column) - add GROUP BY to query - * @method $this groupBy(string $column) - add GROUP BY to query - * @method $this having(string $column) - add HAVING query - * @method $this order(string $column) - add ORDER BY to query - * @method $this orderBy(string $column) - add ORDER BY to query - * @method $this limit(int $limit) - add LIMIT to query - * @method $this offset(int $offset) - add OFFSET to query * @method $this comment(string $comment) - add COMMENT (--) to query + * @method $this from(string $table) - add FROM to DELETE query + * @method $this fullJoin(string $statement) - add FULL JOIN to query + * @method $this group(string $column) - add GROUP BY to query + * @method $this groupBy(string $column) - add GROUP BY to query + * @method $this having(string $column) - add HAVING query + * @method $this innerJoin(string $statement) - add INNER JOIN to query + * @method $this leftJoin(string $statement) - add LEFT JOIN to query + * $statement can be the 'table' name only or 'table:' to back reference the join + * @method $this limit(int $limit) - add LIMIT to query + * @method $this offset(int $offset) - add OFFSET to query + * @method $this order(string $column) - add ORDER BY to query + * @method $this orderBy(string $column) - add ORDER BY to query + * @method $this outerJoin(string $statement) - add OUTER JOIN to query + * @method $this rightJoin(string $statement) - add RIGHT JOIN to query */ abstract class Common extends Base { + /** + * @var array - Query tables (also include table from clause FROM) + */ + protected array $joins = []; - /** @var array - methods which are allowed to be called by the magic method __call() */ - private $validMethods = [ + /** + * @var bool - Disable adding undefined joins to query? + */ + protected bool $isSmartJoinEnabled = true; + + /** + * @var array - methods which are allowed to be called by the magic method __call() + */ + private array $validMethods = [ 'comment', 'from', 'fullJoin', @@ -42,15 +66,9 @@ abstract class Common extends Base 'order', 'orderBy', 'outerJoin', - 'rightJoin' + 'rightJoin', ]; - /** @var array - Query tables (also include table from clause FROM) */ - protected $joins = []; - - /** @var bool - Disable adding undefined joins to query? */ - protected $isSmartJoinEnabled = true; - /** * @param string $name * @param array $parameters - first is $statement followed by $parameters @@ -59,29 +77,38 @@ abstract class Common extends Base */ public function __call($name, $parameters = []) { - if (!in_array($name, $this->validMethods)) { - trigger_error("Call to invalid method " . get_class($this) . "::{$name}()", E_USER_ERROR); + if (!\in_array($name, $this->validMethods, true)) { + trigger_error('Call to invalid method '.\get_class($this)."::{$name}()", \E_USER_ERROR); } $clause = Utilities::toUpperWords($name); - if ($clause == 'GROUP' || $clause == 'ORDER') { + if ($clause === 'GROUP' || $clause === 'ORDER') { $clause = "{$clause} BY"; } - if ($clause == 'COMMENT') { + if ($clause === 'COMMENT') { $clause = "\n--"; } $statement = array_shift($parameters); - if (strpos($clause, 'JOIN') !== false) { + if (str_contains($clause, 'JOIN')) { return $this->addJoinStatements($clause, $statement, $parameters); } return $this->addStatement($clause, $statement, $parameters); } + public function __clone() + { + foreach ($this->clauses as $clause => $value) { + if (\is_array($value) && $value[0] instanceof self) { + $this->clauses[$clause][0] = $this; + } + } + } + /** * @return $this */ @@ -111,11 +138,11 @@ public function isSmartJoinEnabled() } /** - * Add where condition, defaults to appending with AND + * Add where condition, defaults to appending with AND. * - * @param string|array $condition - possibly containing ? or :name (PDO syntax) + * @param array|string $condition - possibly containing ? or :name (PDO syntax) * @param mixed $parameters - * @param string $separator - should be AND or OR + * @param string $separator - should be AND or OR * * @return $this */ @@ -129,7 +156,7 @@ public function where($condition, $parameters = [], $separator = 'AND') return $this; } - if (is_array($condition)) { // where(["column1 > ?" => 1, "column2 < ?" => 2]) + if (\is_array($condition)) { // where(["column1 > ?" => 1, "column2 < ?" => 2]) foreach ($condition as $key => $val) { $this->where($key, $val); } @@ -137,7 +164,7 @@ public function where($condition, $parameters = [], $separator = 'AND') return $this; } - $args = func_get_args(); + $args = \func_get_args(); if ($parameters === []) { return $this->addWhereStatement($condition, $separator); @@ -148,16 +175,20 @@ public function where($condition, $parameters = [], $separator = 'AND') * a parameter (? or :name), add them; it's up to the dev to be valid sql. Otherwise it's probably * just an identifier, so construct a new condition based on the passed parameter value. */ - if (count($args) >= 2 && !$this->regex->sqlParameter($condition)) { + if (\count($args) >= 2 && !$this->regex->sqlParameter($condition)) { // condition is column only - if (is_null($parameters)) { - return $this->addWhereStatement("$condition IS NULL", $separator); - } elseif ($args[1] === []) { + if (null === $parameters) { + return $this->addWhereStatement("{$condition} IS NULL", $separator); + } + + if ($args[1] === []) { return $this->addWhereStatement('FALSE', $separator); - } elseif (is_array($args[1])) { + } + + if (\is_array($args[1])) { $in = $this->quote($args[1]); - return $this->addWhereStatement("$condition IN $in", $separator); + return $this->addWhereStatement("{$condition} IN {$in}", $separator); } // don't parameterize the value if it's an instance of Literal @@ -165,15 +196,15 @@ public function where($condition, $parameters = [], $separator = 'AND') $condition = "{$condition} = {$parameters}"; return $this->addWhereStatement($condition, $separator); - } else { - $condition = "$condition = ?"; } + + $condition = "{$condition} = ?"; } $args = [0 => $args[1]]; // parameters can be passed as [1, 2, 3] and it will fill a condition like: id IN (?, ?, ?) - if (is_array($parameters) && !empty($parameters)) { + if (\is_array($parameters) && !empty($parameters)) { $args = $parameters; } @@ -181,7 +212,7 @@ public function where($condition, $parameters = [], $separator = 'AND') } /** - * Add where appending with OR + * Add where appending with OR. * * @param string $condition - possibly containing ? or :name (PDO syntax) * @param mixed $parameters @@ -190,7 +221,7 @@ public function where($condition, $parameters = [], $separator = 'AND') */ public function whereOr($condition, $parameters = []) { - if (is_array($condition)) { // where(["column1 > ?" => 1, "column2 < ?" => 2]) + if (\is_array($condition)) { // where(["column1 > ?" => 1, "column2 < ?" => 2]) foreach ($condition as $key => $val) { $this->whereOr($key, $val); } @@ -212,7 +243,8 @@ protected function getClauseJoin() /** * @return string */ - protected function getClauseWhere() { + protected function getClauseWhere() + { $firstStatement = array_shift($this->statements['WHERE']); $query = " WHERE {$firstStatement[1]}"; // append first statement to WHERE without condition @@ -229,10 +261,39 @@ protected function getClauseWhere() { } /** - * Statement can contain more tables (e.g. "table1.table2:table3:") + * @throws Exception + * + * @return string + */ + protected function buildQuery() + { + // first create extra join from statements with columns with referenced tables + $statementsWithReferences = ['WHERE', 'SELECT', 'GROUP BY', 'ORDER BY']; + + foreach ($statementsWithReferences as $clause) { + if (\array_key_exists($clause, $this->statements)) { + $this->statements[$clause] = array_map([$this, 'createUndefinedJoins'], $this->statements[$clause]); + } + } + + return parent::buildQuery(); + } + + /** + * @return bool + */ + protected function isEscapedJoin($statement) + { + if (\is_array($statement)) { + $statement = $statement[1]; + } + + return !$this->isSmartJoinEnabled || str_contains($statement, '\.') || str_contains($statement, '\:'); + } + + /** + * Statement can contain more tables (e.g. "table1.table2:table3:"). * - * @param $clause - * @param $statement * @param array $parameters * * @return $this @@ -245,20 +306,20 @@ private function addJoinStatements($clause, $statement, $parameters = []) return $this->resetClause('JOIN'); } - if (array_search(substr($statement, 0, -1), $this->joins) !== false) { + if (array_search(substr($statement, 0, -1), $this->joins, true) !== false) { return $this; } - list($joinAlias, $joinTable) = $this->setJoinNameAlias($statement); + [$joinAlias, $joinTable] = $this->setJoinNameAlias($statement); - if (strpos(strtoupper($statement), ' ON ') !== false || strpos(strtoupper($statement), ' USING') !== false) { + if (str_contains(strtoupper($statement), ' ON ') || str_contains(strtoupper($statement), ' USING')) { return $this->addRawJoins($clause, $statement, $parameters, $joinAlias, $joinTable); } $mainTable = $this->setMainTable(); // if $joinTable does not end with a dot or colon, append one - if (!in_array(substr($joinTable, -1), ['.', ':'])) { + if (!\in_array(substr($joinTable, -1), ['.', ':'], true)) { $joinTable .= '.'; } @@ -266,10 +327,10 @@ private function addJoinStatements($clause, $statement, $parameters = []) // used for applying the table alias $lastItem = array_pop($matches[1]); - array_push($matches[1], $lastItem); + $matches[1][] = $lastItem; foreach ($matches[1] as $joinItem) { - if ($this->matchTableWithJoin($mainTable, $joinItem)) { + if (self::matchTableWithJoin($mainTable, $joinItem)) { // this is still the same table so we don't need to add the same join continue; } @@ -281,18 +342,15 @@ private function addJoinStatements($clause, $statement, $parameters = []) } /** - * Create join string + * Create join string. * - * @param $clause - * @param $mainTable - * @param $joinTable * @param string $joinAlias * * @return string */ private function createJoinStatement($clause, $mainTable, $joinTable, $joinAlias = '') { - if (in_array(substr($mainTable, -1), [':', '.'])) { + if (\in_array(substr($mainTable, -1), [':', '.'], true)) { $mainTable = substr($mainTable, 0, -1); } @@ -301,32 +359,32 @@ private function createJoinStatement($clause, $mainTable, $joinTable, $joinAlias $asJoinAlias = ''; if (!empty($joinAlias)) { - $asJoinAlias = " AS $joinAlias"; + $asJoinAlias = " AS {$joinAlias}"; } else { $joinAlias = $joinTable; } - if (in_array($joinAlias, $this->joins)) { // if the join exists don't create it again + if (\in_array($joinAlias, $this->joins, true)) { // if the join exists don't create it again return ''; - } else { - $this->joins[] = $joinAlias; } - if ($referenceDirection == ':') { // back reference + $this->joins[] = $joinAlias; + + if ($referenceDirection === ':') { // back reference $primaryKey = $this->getStructure()->getPrimaryKey($mainTable); $foreignKey = $this->getStructure()->getForeignKey($mainTable); - return " $clause $joinTable$asJoinAlias ON $joinAlias.$foreignKey = $mainTable.$primaryKey"; - } else { - $primaryKey = $this->getStructure()->getPrimaryKey($joinTable); - $foreignKey = $this->getStructure()->getForeignKey($joinTable); - - return " $clause $joinTable$asJoinAlias ON $joinAlias.$primaryKey = $mainTable.$foreignKey"; + return " {$clause} {$joinTable}{$asJoinAlias} ON {$joinAlias}.{$foreignKey} = {$mainTable}.{$primaryKey}"; } + + $primaryKey = $this->getStructure()->getPrimaryKey($joinTable); + $foreignKey = $this->getStructure()->getForeignKey($joinTable); + + return " {$clause} {$joinTable}{$asJoinAlias} ON {$joinAlias}.{$primaryKey} = {$mainTable}.{$foreignKey}"; } /** - * Create undefined joins from statement with column with referenced tables + * Create undefined joins from statement with column with referenced tables. * * @param string $statement * @@ -339,8 +397,9 @@ private function createUndefinedJoins($statement) } $separator = null; + // if we're in here, this is a where clause - if (is_array($statement)) { + if (\is_array($statement)) { $separator = $statement[0]; $statement = $statement[1]; } @@ -351,19 +410,19 @@ private function createUndefinedJoins($statement) foreach ($matches[1] as $join) { // remove the trailing dot and compare with the joins we already have - if (!in_array(substr($join, 0, -1), $this->joins)) { + if (!\in_array(substr($join, 0, -1), $this->joins, true)) { $this->addJoinStatements('LEFT JOIN', $join); } } // don't rewrite table from other databases foreach ($this->joins as $join) { - if (strpos($join, '.') !== false && strpos($statement, $join) === 0) { + if (str_contains($join, '.') && str_starts_with($statement, $join)) { // rebuild the where statement if ($separator !== null) { $statement = [$separator, $statement]; } - + return $statement; } } @@ -379,41 +438,6 @@ private function createUndefinedJoins($statement) } /** - * @throws Exception - * - * @return string - */ - protected function buildQuery() - { - // first create extra join from statements with columns with referenced tables - $statementsWithReferences = ['WHERE', 'SELECT', 'GROUP BY', 'ORDER BY']; - - foreach ($statementsWithReferences as $clause) { - if (array_key_exists($clause, $this->statements)) { - $this->statements[$clause] = array_map([$this, 'createUndefinedJoins'], $this->statements[$clause]); - } - } - - return parent::buildQuery(); - } - - /** - * @param $statement - * - * @return bool - */ - protected function isEscapedJoin($statement) - { - if (is_array($statement)) { - $statement = $statement[1]; - } - - return !$this->isSmartJoinEnabled || strpos($statement, '\.') !== false || strpos($statement, '\:') !== false; - } - - /** - * @param $statement - * * @return array */ private function setJoinNameAlias($statement) @@ -424,7 +448,8 @@ private function setJoinNameAlias($statement) if ($matches) { $joinTable = $matches[1]; - if (isset($matches[4]) && !in_array(strtoupper($matches[4]), ['ON', 'USING'])) { + + if (isset($matches[4]) && !\in_array(strtoupper($matches[4]), ['ON', 'USING'], true)) { $joinAlias = $matches[4]; } } @@ -433,23 +458,14 @@ private function setJoinNameAlias($statement) } /** - * @param $table - * @param $joinItem - * * @return bool */ - private function matchTableWithJoin($table, $joinItem) + private static function matchTableWithJoin($table, $joinItem) { - return $table == substr($joinItem, 0, -1); + return $table === substr($joinItem, 0, -1); } /** - * @param $clause - * @param $statement - * @param $parameters - * @param $joinAlias - * @param $joinTable - * * @return $this */ private function addRawJoins($clause, $statement, $parameters, $joinAlias, $joinTable) @@ -458,14 +474,14 @@ private function addRawJoins($clause, $statement, $parameters, $joinAlias, $join $joinAlias = $joinTable; } - if (in_array($joinAlias, $this->joins)) { + if (\in_array($joinAlias, $this->joins, true)) { return $this; - } else { - $this->joins[] = $joinAlias; - $statement = " $clause $statement"; - - return $this->addStatement('JOIN', $statement, $parameters); } + + $this->joins[] = $joinAlias; + $statement = " {$clause} {$statement}"; + + return $this->addStatement('JOIN', $statement, $parameters); } /** @@ -475,7 +491,9 @@ private function setMainTable() { if (isset($this->statements['FROM'])) { return $this->statements['FROM']; - } elseif (isset($this->statements['UPDATE'])) { + } + + if (isset($this->statements['UPDATE'])) { return $this->statements['UPDATE']; } @@ -483,20 +501,13 @@ private function setMainTable() } /** - * @param $clause - * @param $parameters - * @param $mainTable - * @param $joinItem - * @param $lastItem - * @param $joinAlias - * * @return mixed */ private function applyTableJoin($clause, $parameters, $mainTable, $joinItem, $lastItem, $joinAlias) { $alias = ''; - if ($joinItem == $lastItem) { + if ($joinItem === $lastItem) { $alias = $joinAlias; // use $joinAlias only for $lastItem } @@ -508,13 +519,4 @@ private function applyTableJoin($clause, $parameters, $mainTable, $joinItem, $la return $joinItem; } - - public function __clone() - { - foreach ($this->clauses as $clause => $value) { - if (is_array($value) && $value[0] instanceof Common) { - $this->clauses[$clause][0] = $this; - } - } - } } diff --git a/src/Queries/Delete.php b/src/Queries/Delete.php index 49c74d9..f270c69 100644 --- a/src/Queries/Delete.php +++ b/src/Queries/Delete.php @@ -1,41 +1,47 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Envms\FluentPDO\Queries; -use Envms\FluentPDO\{Exception, Query}; +use Envms\FluentPDO\Exception; +use Envms\FluentPDO\Query; /** - * DELETE query builder + * DELETE query builder. * - * @method Delete leftJoin(string $statement) add LEFT JOIN to query - * ($statement can be 'table' name only or 'table:' means back reference) - * @method Delete innerJoin(string $statement) add INNER JOIN to query - * ($statement can be 'table' name only or 'table:' means back reference) - * @method Delete from(string $table) add LIMIT to query - * @method Delete orderBy(string $column) add ORDER BY to query - * @method Delete limit(int $limit) add LIMIT to query + * @method Delete innerJoin(string $statement) add INNER JOIN to query + * ($statement can be 'table' name only or 'table:' means back reference) + * @method Delete from(string $table) add LIMIT to query + * @method Delete limit(int $limit) add LIMIT to query + * @method Delete orderBy(string $column) add ORDER BY to query */ class Delete extends Common { - - private $ignore = false; + private bool $ignore = false; /** - * Delete constructor - * - * @param Query $fluent - * @param string $table + * Delete constructor. */ public function __construct(Query $fluent, string $table) { $clauses = [ 'DELETE FROM' => [$this, 'getClauseDeleteFrom'], - 'DELETE' => [$this, 'getClauseDelete'], - 'FROM' => null, - 'JOIN' => [$this, 'getClauseJoin'], - 'WHERE' => [$this, 'getClauseWhere'], - 'ORDER BY' => ', ', - 'LIMIT' => null, + 'DELETE' => [$this, 'getClauseDelete'], + 'FROM' => null, + 'JOIN' => [$this, 'getClauseJoin'], + 'WHERE' => [$this, 'getClauseWhere'], + 'ORDER BY' => ', ', + 'LIMIT' => null, ]; parent::__construct($fluent, $clauses); @@ -45,7 +51,7 @@ public function __construct(Query $fluent, string $table) } /** - * Forces delete operation to fail silently + * Forces delete operation to fail silently. * * @return Delete */ @@ -57,23 +63,7 @@ public function ignore() } /** - * @throws Exception - * - * @return string - */ - protected function buildQuery() - { - if ($this->statements['FROM']) { - unset($this->clauses['DELETE FROM']); - } else { - unset($this->clauses['DELETE']); - } - - return parent::buildQuery(); - } - - /** - * Execute DELETE query + * Execute DELETE query. * * @throws Exception * @@ -86,6 +76,7 @@ public function execute() } $result = parent::execute(); + if ($result) { return $result->rowCount(); } @@ -93,12 +84,28 @@ public function execute() return false; } + /** + * @throws Exception + * + * @return string + */ + protected function buildQuery() + { + if ($this->statements['FROM']) { + unset($this->clauses['DELETE FROM']); + } else { + unset($this->clauses['DELETE']); + } + + return parent::buildQuery(); + } + /** * @return string */ protected function getClauseDelete() { - return 'DELETE' . ($this->ignore ? " IGNORE" : '') . ' ' . $this->statements['DELETE']; + return 'DELETE'.($this->ignore ? ' IGNORE' : '').' '.$this->statements['DELETE']; } /** @@ -106,7 +113,6 @@ protected function getClauseDelete() */ protected function getClauseDeleteFrom() { - return 'DELETE' . ($this->ignore ? " IGNORE" : '') . ' FROM ' . $this->statements['DELETE FROM']; + return 'DELETE'.($this->ignore ? ' IGNORE' : '').' FROM '.$this->statements['DELETE FROM']; } - } diff --git a/src/Queries/Insert.php b/src/Queries/Insert.php index ff0b302..10750d0 100644 --- a/src/Queries/Insert.php +++ b/src/Queries/Insert.php @@ -1,39 +1,47 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Envms\FluentPDO\Queries; -use Envms\FluentPDO\{Exception, Literal, Query}; +use Envms\FluentPDO\Exception; +use Envms\FluentPDO\Literal; +use Envms\FluentPDO\Query; -/** INSERT query builder +/** + * INSERT query builder. */ class Insert extends Base { + private array $columns = []; - /** @var array */ - private $columns = []; + private array $firstValue = []; - /** @var array */ - private $firstValue = []; + private bool $ignore = false; - /** @var bool */ - private $ignore = false; - /** @var bool */ - private $delayed = false; + private bool $delayed = false; /** * InsertQuery constructor. * - * @param Query $fluent - * @param string $table - * @param $values + * @param string $table * * @throws Exception */ public function __construct(Query $fluent, $table, $values) { $clauses = [ - 'INSERT INTO' => [$this, 'getClauseInsertInto'], - 'VALUES' => [$this, 'getClauseValues'], + 'INSERT INTO' => [$this, 'getClauseInsertInto'], + 'VALUES' => [$this, 'getClauseValues'], 'ON DUPLICATE KEY UPDATE' => [$this, 'getClauseOnDuplicateKeyUpdate'], ]; parent::__construct($fluent, $clauses); @@ -43,7 +51,7 @@ public function __construct(Query $fluent, $table, $values) } /** - * Force insert operation to fail silently + * Force insert operation to fail silently. * * @return Insert */ @@ -54,7 +62,8 @@ public function ignore() return $this; } - /** Force insert operation delay support + /** + * Force insert operation delay support. * * @return Insert */ @@ -66,24 +75,24 @@ public function delayed() } /** - * Add VALUES + * Add VALUES. * - * @param $values + * @throws Exception * * @return Insert - * @throws Exception */ public function values($values) { - if (!is_array($values)) { + if (!\is_array($values)) { throw new Exception('Param VALUES for INSERT query must be array'); } $first = current($values); - if (is_string(key($values))) { + + if (\is_string(key($values))) { // is one row array $this->addOneValue($values); - } elseif (is_array($first) && is_string(key($first))) { + } elseif (\is_array($first) && \is_string(key($first))) { // this is multi values foreach ($values as $oneValue) { $this->addOneValue($oneValue); @@ -94,7 +103,7 @@ public function values($values) } /** - * Add ON DUPLICATE KEY UPDATE + * Add ON DUPLICATE KEY UPDATE. * * @param array $values * @@ -103,20 +112,21 @@ public function values($values) public function onDuplicateKeyUpdate($values) { $this->statements['ON DUPLICATE KEY UPDATE'] = array_merge( - $this->statements['ON DUPLICATE KEY UPDATE'], $values + $this->statements['ON DUPLICATE KEY UPDATE'], + $values, ); return $this; } /** - * Execute insert query + * Execute insert query. * * @param mixed $sequence * * @throws Exception * - * @return int|bool - Last inserted primary key + * @return bool|int - Last inserted primary key */ public function execute($sequence = null) { @@ -152,7 +162,7 @@ public function executeWithoutId($sequence = null) */ protected function getClauseInsertInto() { - return 'INSERT' . ($this->ignore ? " IGNORE" : '') . ($this->delayed ? " DELAYED" : '') . ' INTO ' . $this->statements['INSERT INTO']; + return 'INSERT'.($this->ignore ? ' IGNORE' : '').($this->delayed ? ' DELAYED' : '').' INTO '.$this->statements['INSERT INTO']; } /** @@ -161,60 +171,57 @@ protected function getClauseInsertInto() protected function getClauseValues() { $valuesArray = []; + foreach ($this->statements['VALUES'] as $rows) { // literals should not be parametrized. // They are commonly used to call engine functions or literals. // Eg: NOW(), CURRENT_TIMESTAMP etc $placeholders = array_map([$this, 'parameterGetValue'], $rows); - $valuesArray[] = '(' . implode(', ', $placeholders) . ')'; + $valuesArray[] = '('.implode(', ', $placeholders).')'; } $columns = implode(', ', $this->columns); $values = implode(', ', $valuesArray); - return " ($columns) VALUES $values"; + return " ({$columns}) VALUES {$values}"; } - /** * @return string */ protected function getClauseOnDuplicateKeyUpdate() { $result = []; + foreach ($this->statements['ON DUPLICATE KEY UPDATE'] as $key => $value) { - $result[] = "$key = " . $this->parameterGetValue($value); + $result[] = "{$key} = ".$this->parameterGetValue($value); } - return ' ON DUPLICATE KEY UPDATE ' . implode(', ', $result); + return ' ON DUPLICATE KEY UPDATE '.implode(', ', $result); } /** - * @param $param - * * @return string */ protected function parameterGetValue($param) { - return $param instanceof Literal ? (string)$param : '?'; + return $param instanceof Literal ? (string) $param : '?'; } /** * Removes all Literal instances from the argument - * since they are not to be used as PDO parameters but rather injected directly into the query - * - * @param $statements + * since they are not to be used as PDO parameters but rather injected directly into the query. * * @return array */ protected function filterLiterals($statements) { - $f = function ($item) { + $f = static function ($item) { return !$item instanceof Literal; }; - return array_map(function ($item) use ($f) { - if (is_array($item)) { + return array_map(static function ($item) use ($f) { + if (\is_array($item)) { return array_filter($item, $f); } @@ -222,14 +229,11 @@ protected function filterLiterals($statements) }, array_filter($statements, $f)); } - /** - * @return array - */ protected function buildParameters(): array { $this->parameters = array_merge( $this->filterLiterals($this->statements['VALUES']), - $this->filterLiterals($this->statements['ON DUPLICATE KEY UPDATE']) + $this->filterLiterals($this->statements['ON DUPLICATE KEY UPDATE']), ); return parent::buildParameters(); @@ -240,24 +244,27 @@ protected function buildParameters(): array * * @throws Exception */ - private function addOneValue($oneValue) + private function addOneValue($oneValue): void { // check if all $keys are strings foreach ($oneValue as $key => $value) { - if (!is_string($key)) { + if (!\is_string($key)) { throw new Exception('INSERT query: All keys of value array have to be strings.'); } } + if (!$this->firstValue) { $this->firstValue = $oneValue; } + if (!$this->columns) { $this->columns = array_keys($oneValue); } - if ($this->columns != array_keys($oneValue)) { + + if ($this->columns !== array_keys($oneValue)) { throw new Exception('INSERT query: All VALUES have to same keys (columns).'); } + $this->statements['VALUES'][] = $oneValue; } - } diff --git a/src/Queries/Json.php b/src/Queries/Json.php index a37cf72..5e6b1b5 100644 --- a/src/Queries/Json.php +++ b/src/Queries/Json.php @@ -1,41 +1,46 @@ * - * @package Envms\FluentPDO\Queries + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Envms\FluentPDO\Queries; + +use Envms\FluentPDO\Query; + +/** + * Class Json. */ class Json extends Common { + protected mixed $fromTable; - /** @var mixed */ - protected $fromTable; - /** @var mixed */ - protected $fromAlias; - /** @var boolean */ - protected $convertTypes = false; + protected mixed $fromAlias; + + protected bool $convertTypes = false; /** - * Json constructor - * - * @param Query $fluent - * @param string $table + * Json constructor. */ public function __construct(Query $fluent, string $table) { $clauses = [ - 'SELECT' => ', ', - 'JOIN' => [$this, 'getClauseJoin'], - 'WHERE' => [$this, 'getClauseWhere'], + 'SELECT' => ', ', + 'JOIN' => [$this, 'getClauseJoin'], + 'WHERE' => [$this, 'getClauseWhere'], 'GROUP BY' => ',', - 'HAVING' => ' AND ', + 'HAVING' => ' AND ', 'ORDER BY' => ', ', - 'LIMIT' => null, - 'OFFSET' => null, - "\n--" => "\n--", + 'LIMIT' => null, + 'OFFSET' => null, + "\n--" => "\n--", ]; parent::__construct($fluent, $clauses); @@ -52,5 +57,4 @@ public function __construct(Query $fluent, string $table) $this->convertTypes = true; } } - -} \ No newline at end of file +} diff --git a/src/Queries/Select.php b/src/Queries/Select.php index 31ef371..3a4393b 100644 --- a/src/Queries/Select.php +++ b/src/Queries/Select.php @@ -1,39 +1,47 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Envms\FluentPDO\Queries; -use Envms\FluentPDO\{Exception, Query, Utilities}; +use Envms\FluentPDO\Exception; +use Envms\FluentPDO\Query; +use Envms\FluentPDO\Utilities; /** - * SELECT query builder + * SELECT query builder. */ class Select extends Common implements \Countable { + private mixed $fromTable; - /** @var mixed */ - private $fromTable; - /** @var mixed */ - private $fromAlias; + private mixed $fromAlias; /** * SelectQuery constructor. - * - * @param Query $fluent - * @param $from */ - function __construct(Query $fluent, $from) + public function __construct(Query $fluent, $from) { $clauses = [ - 'SELECT' => ', ', - 'FROM' => null, - 'JOIN' => [$this, 'getClauseJoin'], - 'WHERE' => [$this, 'getClauseWhere'], + 'SELECT' => ', ', + 'FROM' => null, + 'JOIN' => [$this, 'getClauseJoin'], + 'WHERE' => [$this, 'getClauseWhere'], 'GROUP BY' => ',', - 'HAVING' => ' AND ', + 'HAVING' => ' AND ', 'ORDER BY' => ', ', - 'LIMIT' => null, - 'OFFSET' => null, - "\n--" => "\n--" + 'LIMIT' => null, + 'OFFSET' => null, + "\n--" => "\n--", ]; parent::__construct($fluent, $clauses); @@ -43,13 +51,12 @@ function __construct(Query $fluent, $from) $this->fromAlias = end($fromParts); $this->statements['FROM'] = $from; - $this->statements['SELECT'][] = $this->fromAlias . '.*'; + $this->statements['SELECT'][] = $this->fromAlias.'.*'; $this->joins[] = $this->fromAlias; } /** * @param mixed $columns - * @param bool $overrideDefault * * @return $this */ @@ -67,7 +74,7 @@ public function select($columns, bool $overrideDefault = false) } /** - * Return table name from FROM clause + * Return table name from FROM clause. */ public function getFromTable() { @@ -75,7 +82,7 @@ public function getFromTable() } /** - * Return table alias from FROM clause + * Return table alias from FROM clause. */ public function getFromAlias() { @@ -83,9 +90,7 @@ public function getFromAlias() } /** - * Returns a single column - * - * @param int $columnNumber + * Returns a single column. * * @throws Exception * @@ -101,10 +106,9 @@ public function fetchColumn(int $columnNumber = 0) } /** - * Fetch first row or column + * Fetch first row or column. * * @param string $column - column name or empty string for the whole row - * @param int $cursorOrientation * * @throws Exception * @@ -127,22 +131,18 @@ public function fetch(?string $column = null, int $cursorOrientation = \PDO::FET } if ($row && $column !== null) { - if (is_object($row)) { + if (\is_object($row)) { return $row->{$column}; - } else { - return $row[$column]; } + + return $row[$column]; } return $row; } /** - * Fetch pairs - * - * @param $key - * @param $value - * @param $object + * Fetch pairs. * * @throws Exception * @@ -150,14 +150,15 @@ public function fetch(?string $column = null, int $cursorOrientation = \PDO::FET */ public function fetchPairs($key, $value, $object = false) { - if (($s = $this->select("$key, $value", true)->asObject($object)->execute()) !== false) { + if (($s = $this->select("{$key}, {$value}", true)->asObject($object)->execute()) !== false) { return $s->fetchAll(\PDO::FETCH_KEY_PAIR); } return $s; } - /** Fetch all row + /** + * Fetch all row. * * @param string $index - specify index column. Allows for data organization by field using 'field[]' * @param string $selectOnly - select columns which could be fetched @@ -175,26 +176,26 @@ public function fetchAll($index = '', $selectOnly = '') } if ($selectOnly) { - $this->select($index . ', ' . $selectOnly, true); + $this->select($index.', '.$selectOnly, true); } if ($index) { return $this->buildSelectData($index, $indexAsArray); - } else { - if (($result = $this->execute()) !== false) { - if ($this->fluent->convertRead === true) { - return Utilities::stringToNumeric($result, $result->fetchAll()); - } else { - return $result->fetchAll(); - } + } + + if (($result = $this->execute()) !== false) { + if ($this->fluent->convertRead === true) { + return Utilities::stringToNumeric($result, $result->fetchAll()); } - return false; + return $result->fetchAll(); } + + return false; } /** - * \Countable interface doesn't break current select query + * \Countable interface doesn't break current select query. * * @throws Exception * @@ -205,7 +206,7 @@ public function count() { $fluent = clone $this; - return (int)$fluent->select('COUNT(*)', true)->fetchColumn(); + return (int) $fluent->select('COUNT(*)', true)->fetchColumn(); } /** @@ -217,15 +218,12 @@ public function getIterator() { if ($this->fluent->convertRead === true) { return new \ArrayIterator($this->fetchAll()); - } else { - return $this->execute(); } + + return $this->execute(); } /** - * @param $index - * @param $indexAsArray - * * @return array */ private function buildSelectData($index, $indexAsArray) @@ -233,7 +231,7 @@ private function buildSelectData($index, $indexAsArray) $data = []; foreach ($this as $row) { - if (is_object($row)) { + if (\is_object($row)) { $key = $row->{$index}; } else { $key = $row[$index]; diff --git a/src/Queries/Update.php b/src/Queries/Update.php index d3ebd8b..08f93ea 100644 --- a/src/Queries/Update.php +++ b/src/Queries/Update.php @@ -1,37 +1,44 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Envms\FluentPDO\Queries; -use Envms\FluentPDO\{Exception, Literal, Query}; +use Envms\FluentPDO\Exception; +use Envms\FluentPDO\Literal; +use Envms\FluentPDO\Query; /** - * UPDATE query builder + * UPDATE query builder. * - * @method Update leftJoin(string $statement) add LEFT JOIN to query - * ($statement can be 'table' name only or 'table:' means back reference) - * @method Update innerJoin(string $statement) add INNER JOIN to query - * ($statement can be 'table' name only or 'table:' means back reference) - * @method Update orderBy(string $column) add ORDER BY to query - * @method Update limit(int $limit) add LIMIT to query + * @method Update innerJoin(string $statement) add INNER JOIN to query + * ($statement can be 'table' name only or 'table:' means back reference) + * @method Update limit(int $limit) add LIMIT to query + * @method Update orderBy(string $column) add ORDER BY to query */ class Update extends Common { - /** - * UpdateQuery constructor - * - * @param Query $fluent - * @param string $table + * UpdateQuery constructor. */ public function __construct(Query $fluent, string $table) { $clauses = [ - 'UPDATE' => [$this, 'getClauseUpdate'], - 'JOIN' => [$this, 'getClauseJoin'], - 'SET' => [$this, 'getClauseSet'], - 'WHERE' => [$this, 'getClauseWhere'], + 'UPDATE' => [$this, 'getClauseUpdate'], + 'JOIN' => [$this, 'getClauseJoin'], + 'SET' => [$this, 'getClauseSet'], + 'WHERE' => [$this, 'getClauseWhere'], 'ORDER BY' => ', ', - 'LIMIT' => null, + 'LIMIT' => null, ]; parent::__construct($fluent, $clauses); @@ -42,9 +49,9 @@ public function __construct(Query $fluent, string $table) } /** - * In Update's case, parameters are not assigned until the query is built, since this method + * In Update's case, parameters are not assigned until the query is built, since this method. * - * @param string|array $fieldOrArray + * @param array|string $fieldOrArray * @param bool|string $value * * @throws Exception @@ -56,15 +63,16 @@ public function set($fieldOrArray, $value = false) if (!$fieldOrArray) { return $this; } - if (is_string($fieldOrArray) && $value !== false) { + + if (\is_string($fieldOrArray) && $value !== false) { $this->statements['SET'][$fieldOrArray] = $value; } else { - if (!is_array($fieldOrArray)) { + if (!\is_array($fieldOrArray)) { throw new Exception('You must pass a value, or provide the SET list as an associative array. column => value'); - } else { - foreach ($fieldOrArray as $field => $value) { - $this->statements['SET'][$field] = $value; - } + } + + foreach ($fieldOrArray as $field => $value) { + $this->statements['SET'][$field] = $value; } } @@ -72,13 +80,13 @@ public function set($fieldOrArray, $value = false) } /** - * Execute update query + * Execute update query. * - * @param boolean $getResultAsPdoStatement true to return the pdo statement instead of row count + * @param bool $getResultAsPdoStatement true to return the pdo statement instead of row count * * @throws Exception * - * @return int|boolean|\PDOStatement + * @return bool|int|\PDOStatement */ public function execute($getResultAsPdoStatement = false) { @@ -104,7 +112,7 @@ public function execute($getResultAsPdoStatement = false) */ protected function getClauseUpdate() { - return 'UPDATE ' . $this->statements['UPDATE']; + return 'UPDATE '.$this->statements['UPDATE']; } /** @@ -113,22 +121,21 @@ protected function getClauseUpdate() protected function getClauseSet() { $setArray = []; + foreach ($this->statements['SET'] as $field => $value) { // named params are being used here - if (is_array($value) && strpos(key($value), ':') === 0) { + if (\is_array($value) && str_starts_with(key($value), ':')) { $key = key($value); - $setArray[] = $field . ' = ' . $key; + $setArray[] = $field.' = '.$key; $this->parameters['SET'][$key] = $value[$key]; - } - elseif ($value instanceof Literal) { - $setArray[] = $field . ' = ' . $value; + } elseif ($value instanceof Literal) { + $setArray[] = $field.' = '.$value; } else { - $setArray[] = $field . ' = ?'; + $setArray[] = $field.' = ?'; $this->parameters['SET'][$field] = $value; } } - return ' SET ' . implode(', ', $setArray); + return ' SET '.implode(', ', $setArray); } - } diff --git a/src/Query.php b/src/Query.php index 4c5d49d..13bf804 100644 --- a/src/Query.php +++ b/src/Query.php @@ -1,62 +1,80 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Envms\FluentPDO; +use Envms\FluentPDO\Queries\Delete; +use Envms\FluentPDO\Queries\Insert; +use Envms\FluentPDO\Queries\Select; +use Envms\FluentPDO\Queries\Update; use PDO; -use Envms\FluentPDO\Queries\{Insert, Select, Update, Delete}; /** * FluentPDO is a quick and light PHP library for rapid query building. It features a smart join builder, which automatically creates table joins. * * For more information see readme.md * - * @link https://github.com/envms/fluentpdo + * @see https://github.com/envms/fluentpdo + * * @author Chris Bornhoft, start@env.ms * @copyright 2012-2020 envms - Chris Bornhoft, Marek Lichtner * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License, version 3.0 */ /** - * Class Query + * Class Query. + * * @method debug(Queries\Base $param) */ class Query { - /** @var PDO */ - protected $pdo; - /** @var Structure */ - protected $structure; - /** @var bool|callable */ - public $debug = false; + public mixed $debug = false; + + /** + * @var bool - Determines whether to convert types when fetching rows from Select + */ + public bool $convertRead = false; + + /** + * @var bool - Determines whether to convert types within Base::buildParameters() + */ + public bool $convertWrite = false; + + /** + * @var bool - If a query errors, this determines how to handle it + */ + public bool $exceptionOnError = false; + + protected \PDO $pdo; + + protected Structure $structure; - /** @var bool - Determines whether to convert types when fetching rows from Select */ - public $convertRead = false; - /** @var bool - Determines whether to convert types within Base::buildParameters() */ - public $convertWrite = false; + protected string $table; - /** @var bool - If a query errors, this determines how to handle it */ - public $exceptionOnError = false; + protected string $prefix; - /** @var string */ - protected $table; - /** @var string */ - protected $prefix; - /** @var string */ - protected $separator; + protected string $separator; /** - * Query constructor - * - * @param PDO $pdo - * @param ?Structure $structure + * Query constructor. */ - public function __construct(PDO $pdo, ?Structure $structure = null) + public function __construct(\PDO $pdo, ?Structure $structure = null) { $this->pdo = $pdo; // if exceptions are already activated in PDO, activate them in Fluent as well - if ($this->pdo->getAttribute(PDO::ATTR_ERRMODE) === PDO::ERRMODE_EXCEPTION) { + if ($this->pdo->getAttribute(\PDO::ATTR_ERRMODE) === \PDO::ERRMODE_EXCEPTION) { $this->throwExceptionOnError(true); } @@ -64,13 +82,11 @@ public function __construct(PDO $pdo, ?Structure $structure = null) } /** - * Create SELECT query from $table + * Create SELECT query from $table. * * @param ?string $table - db table name * @param ?int $primaryKey - return one row by primary key * - * @return Select - * * @throws Exception */ public function from(?string $table = null, ?int $primaryKey = null): Select @@ -84,19 +100,16 @@ public function from(?string $table = null, ?int $primaryKey = null): Select $tableTable = $query->getFromTable(); $tableAlias = $query->getFromAlias(); $primaryKeyName = $this->structure->getPrimaryKey($tableTable); - $query = $query->where("$tableAlias.$primaryKeyName", $primaryKey); + $query = $query->where("{$tableAlias}.{$primaryKeyName}", $primaryKey); } return $query; } /** - * Create INSERT INTO query - * - * @param ?string $table - * @param array $values - accepts one or multiple rows, @see docs + * Create INSERT INTO query. * - * @return Insert + * @param array $values - accepts one or multiple rows, @see docs * * @throws Exception */ @@ -109,13 +122,9 @@ public function insertInto(?string $table = null, array $values = []): Insert } /** - * Create UPDATE query + * Create UPDATE query. * - * @param ?string $table * @param array|string $set - * @param ?int $primaryKey - * - * @return Update * * @throws Exception */ @@ -127,6 +136,7 @@ public function update(?string $table = null, $set = [], ?int $primaryKey = null $query = new Update($this, $table); $query->set($set); + if ($primaryKey) { $primaryKeyName = $this->getStructure()->getPrimaryKey($this->table); $query = $query->where($primaryKeyName, $primaryKey); @@ -136,12 +146,9 @@ public function update(?string $table = null, $set = [], ?int $primaryKey = null } /** - * Create DELETE query - * - * @param ?string $table - * @param ?int $primaryKey delete only row by primary key + * Create DELETE query. * - * @return Delete + * @param ?int $primaryKey delete only row by primary key * * @throws Exception */ @@ -161,38 +168,27 @@ public function delete(?string $table = null, ?int $primaryKey = null): Delete } /** - * Create DELETE FROM query - * - * @param ?string $table - * @param ?int $primaryKey - * - * @return Delete + * Create DELETE FROM query. */ public function deleteFrom(?string $table = null, ?int $primaryKey = null): Delete { - $args = func_get_args(); + $args = \func_get_args(); - return call_user_func_array([$this, 'delete'], $args); + return \call_user_func_array([$this, 'delete'], $args); } - /** - * @return PDO - */ - public function getPdo(): PDO + public function getPdo(): \PDO { return $this->pdo; } - /** - * @return Structure - */ public function getStructure(): Structure { return $this->structure; } /** - * Closes the \PDO connection to the database + * Closes the \PDO connection to the database. */ public function close(): void { @@ -200,17 +196,13 @@ public function close(): void } /** - * Set table name comprised of prefix.separator.table + * Set table name comprised of prefix.separator.table. * - * @param ?string $table - * @param string $prefix - * @param string $separator + * @throws Exception * * @return $this - * - * @throws Exception */ - public function setTableName(?string $table = '', string $prefix = '', string $separator = ''): Query + public function setTableName(?string $table = '', string $prefix = '', string $separator = ''): self { if ($table !== null) { $this->prefix = $prefix; @@ -225,67 +217,42 @@ public function setTableName(?string $table = '', string $prefix = '', string $s return $this; } - /** - * @return string - */ public function getFullTableName(): string { - return $this->prefix . $this->separator . $this->table; + return $this->prefix.$this->separator.$this->table; } - /** - * @return string - */ public function getPrefix(): string { return $this->prefix; } - /** - * @return string - */ public function getSeparator(): string { return $this->separator; } - /** - * @return string - */ public function getTable(): string { return $this->table; } - /** - * @param bool $flag - */ public function throwExceptionOnError(bool $flag): void { $this->exceptionOnError = $flag; } - /** - * @param bool $read - * @param bool $write - */ public function convertTypes(bool $read, bool $write): void { $this->convertRead = $read; $this->convertWrite = $write; } - /** - * @param bool $flag - */ public function convertReadTypes(bool $flag): void { $this->convertRead = $flag; } - /** - * @param bool $flag - */ public function convertWriteTypes(bool $flag): void { $this->convertWrite = $flag; diff --git a/src/Regex.php b/src/Regex.php index e24b0ca..aeef4bf 100644 --- a/src/Regex.php +++ b/src/Regex.php @@ -1,27 +1,42 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Envms\FluentPDO; /** - * Regex class + * Regex class. */ class Regex { - /** @var string - All UTF-8 letter characters */ + /** + * @var string - All UTF-8 letter characters + */ public const ALPHA = '\p{L}'; - /** @var string - All UTF-8 letter and number characters */ + + /** + * @var string - All UTF-8 letter and number characters + */ public const ALNUM = '\p{L}\p{N}'; - /** @var string - All valid SQL characters except the UTF-8 groupings with quotes and wildcards */ + + /** + * @var string - All valid SQL characters except the UTF-8 groupings with quotes and wildcards + */ public const SQLCHARS = '\p{L}\p{N}\p{Pc}\p{Pd}\p{Pf}\p{Pi}'; /** - * Replace "camelCaseMethod" with "camel Case Method" - * - * @param string $subject - * - * @return null|string|string[] + * Replace "camelCaseMethod" with "camel Case Method". */ - public function camelCaseSpaced(string $subject) + public function camelCaseSpaced(string $subject): array|string|null { return preg_replace('/(.)([A-Z]+)/', '$1 $2', $subject); } @@ -30,133 +45,90 @@ public function camelCaseSpaced(string $subject) * Replace "SELECT * FROM table WHERE column = ?" with * "SELECT * * FROM table - * WHERE column = ?" - * - * @param string $subject - * - * @return null|string|string[] + * WHERE column = ?". */ - public function splitClauses(string $subject) + public function splitClauses(string $subject): array|string|null { return preg_replace( '/\b(WHERE|FROM|GROUP BY|HAVING|ORDER BY|LIMIT|OFFSET|UNION|ON DUPLICATE KEY UPDATE|VALUES|SET)\b/', "\n$0", - $subject + $subject, ); } /** * Replace SELECT t2.id FROM t1 LEFT JOIN t2 ON t2.id = t1.t2_id" with * "SELECT t2.id FROM t1 - * LEFT JOIN t2 ON t2.id = t1.t2_id" - * - * @param string $subject - * - * @return null|string|string[] + * LEFT JOIN t2 ON t2.id = t1.t2_id". */ - public function splitSubClauses(string $subject) + public function splitSubClauses(string $subject): array|string|null { return preg_replace( '/\b(INNER|OUTER|LEFT|RIGHT|FULL|CASE|WHEN|END|ELSE|AND|OR)\b/', "\n $0", - $subject + $subject, ); } /** - * Replace "WHERE column = ? " with "WHERE column = ?" - * - * @param string $subject - * - * @return null|string|string[] + * Replace "WHERE column = ? " with "WHERE column = ?". */ - public function removeLineEndWhitespace(string $subject) + public function removeLineEndWhitespace(string $subject): array|string|null { - return preg_replace("/\s+\n/", "\n", $subject); + return preg_replace("/\\s+\n/", "\n", $subject); } /** - * Replace the string "table1.table2:column" with "table2.column" - * - * @param string $subject - * - * @return null|string|string[] + * Replace the string "table1.table2:column" with "table2.column". */ - public function removeAdditionalJoins(string $subject) + public function removeAdditionalJoins(string $subject): array|string|null { return preg_replace('/(?:[^\s]*[.:])?([^\s]+)[.:]([^\s]*)/u', '$1.$2', $subject); } /** - * Match the first file outside of the Fluent source - * - * @param string $subject - * @param ?array $matches - * @param ?string $directory - * - * @return false|int + * Match the first file outside of the Fluent source. */ - public function compareLocation(string $subject, &$matches = null, $directory = null) + public function compareLocation(string $subject, mixed &$matches = null, ?string $directory = null): false|int { $directory = ($directory === null) ? preg_quote(__DIR__, '/') : preg_quote($directory, '/'); - return preg_match('/(^' . $directory . '(\\.php$|[\/\\\\]))/', $subject, $matches); + return preg_match('/(^'.$directory.'(\\.php$|[\/\\\\]))/', $subject, $matches); } /** - * Match the string "?" or ":param" - * - * @param string $subject - * @param array|null $matches - * - * @return false|int + * Match the string "?" or ":param". */ - public function sqlParameter(string $subject, &$matches = null) + public function sqlParameter(string $subject, mixed &$matches = null): false|int { return preg_match('/(\?|:\w+)/', $subject, $matches); } /** - * Match the UTF-8 string "table AS alias" - * - * @param string $subject - * @param array|null $matches - * - * @return false|int + * Match the UTF-8 string "table AS alias". */ - public function tableAlias(string $subject, &$matches = null) + public function tableAlias(string $subject, mixed &$matches = null): false|int { return preg_match( - '/`?([' . self::SQLCHARS . ']+[.:]?[' . self::SQLCHARS . '*]*)`?(\s+AS)?(\s+`?([' . self::SQLCHARS . ']*)`?)?/ui', + '/`?(['.self::SQLCHARS.']+[.:]?['.self::SQLCHARS.'*]*)`?(\s+AS)?(\s+`?(['.self::SQLCHARS.']*)`?)?/ui', $subject, - $matches + $matches, ); } /** - * Match the UTF-8 string "table" or "table." - * - * @param string $subject - * @param array|null $matches - * - * @return false|int + * Match the UTF-8 string "table" or "table.". */ - public function tableJoin(string $subject, &$matches = null) + public function tableJoin(string $subject, mixed &$matches = null): false|int { - return preg_match_all('/([' . self::SQLCHARS . ']+[.:]?)/u', $subject, $matches); + return preg_match_all('/(['.self::SQLCHARS.']+[.:]?)/u', $subject, $matches); } /** - * Match the UTF-8 string "table." or "table.column" - * - * @param string $subject - * @param array|null $matches - * - * @return false|int + * Match the UTF-8 string "table." or "table.column". */ - public function tableJoinFull(string $subject, &$matches = null) + public function tableJoinFull(string $subject, mixed &$matches = null): false|int { - return preg_match_all('/([^[:space:]()]+[.:])[' . self::SQLCHARS . ']*/u', $subject, $matches); + return preg_match_all('/([^[:space:]()]+[.:])['.self::SQLCHARS.']*/u', $subject, $matches); } - } diff --git a/src/Structure.php b/src/Structure.php index ab45bd7..5696693 100644 --- a/src/Structure.php +++ b/src/Structure.php @@ -1,66 +1,56 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Envms\FluentPDO; /** - * Class Structure + * Class Structure. */ class Structure { + private string $primaryKey; - /** @var string */ - private $primaryKey; - /** @var string */ - private $foreignKey; + private string $foreignKey; /** - * Structure constructor - * - * @param string $primaryKey - * @param string $foreignKey + * Structure constructor. */ - function __construct($primaryKey = 'id', $foreignKey = '%s_id') + public function __construct(string $primaryKey = 'id', string $foreignKey = '%s_id') { if ($foreignKey === null) { $foreignKey = $primaryKey; } + $this->primaryKey = $primaryKey; $this->foreignKey = $foreignKey; } - /** - * @param string $table - * - * @return string - */ - public function getPrimaryKey($table) + public function getPrimaryKey(string $table): string { - return $this->key($this->primaryKey, $table); + return self::key($this->primaryKey, $table); } - /** - * @param string $table - * - * @return string - */ - public function getForeignKey($table) + public function getForeignKey(string $table): string { - return $this->key($this->foreignKey, $table); + return self::key($this->foreignKey, $table); } - /** - * @param string|callback $key - * @param string $table - * - * @return string - */ - private function key($key, $table) + private static function key(callable|string $key, string $table): string { - if (is_callable($key)) { + if (\is_callable($key)) { return $key($table); } return sprintf($key, $table); } - } diff --git a/src/Utilities.php b/src/Utilities.php index c040725..2c33e18 100644 --- a/src/Utilities.php +++ b/src/Utilities.php @@ -1,52 +1,51 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Envms\FluentPDO; /** - * Class Utilities + * Class Utilities. */ class Utilities { /** - * Convert "camelCaseWord" to "CAMEL CASE WORD" - * - * @param string $string - * - * @return string + * Convert "camelCaseWord" to "CAMEL CASE WORD". */ - public static function toUpperWords($string) + public static function toUpperWords(string $string): string { $regex = new Regex(); + return trim(strtoupper($regex->camelCaseSpaced($string))); } - /** - * @param string $query - * - * @return string - */ - public static function formatQuery($query) + public static function formatQuery(string $query): string { $regex = new Regex(); $query = $regex->splitClauses($query); $query = $regex->splitSubClauses($query); - $query = $regex->removeLineEndWhitespace($query); - return $query; + return $regex->removeLineEndWhitespace($query); } /** - * Converts columns from strings to types according to PDOStatement::columnMeta() + * Converts columns from strings to types according to PDOStatement::columnMeta(). * - * @param \PDOStatement $statement * @param array|\Traversable $rows - provided by PDOStatement::fetch with PDO::FETCH_ASSOC - * - * @return array|\Traversable */ - public static function stringToNumeric(\PDOStatement $statement, $rows) + public static function stringToNumeric(\PDOStatement $statement, mixed $rows): mixed { - for ($i = 0; ($columnMeta = $statement->getColumnMeta($i)) !== false; $i++) { + for ($i = 0; ($columnMeta = $statement->getColumnMeta($i)) !== false; ++$i) { $type = $columnMeta['native_type']; switch ($type) { @@ -60,18 +59,21 @@ public static function stringToNumeric(\PDOStatement $statement, $rows) case 'SHORT': case 'TINY': if (isset($rows[$columnMeta['name']])) { - $rows[$columnMeta['name']] = $rows[$columnMeta['name']] + 0; + $rows[$columnMeta['name']] += 0; } else { - if (is_array($rows) || $rows instanceof \Traversable) { + if (\is_array($rows) || $rows instanceof \Traversable) { foreach ($rows as &$row) { if (isset($row[$columnMeta['name']])) { - $row[$columnMeta['name']] = $row[$columnMeta['name']] + 0; + $row[$columnMeta['name']] += 0; } } + unset($row); } } + break; + default: // return as string break; @@ -81,14 +83,9 @@ public static function stringToNumeric(\PDOStatement $statement, $rows) return $rows; } - /** - * @param $value - * - * @return bool - */ - public static function convertSqlWriteValues($value) + public static function convertSqlWriteValues(mixed $value): mixed { - if (is_array($value)) { + if (\is_array($value)) { foreach ($value as $k => $v) { $value[$k] = self::convertValue($v); } @@ -99,44 +96,33 @@ public static function convertSqlWriteValues($value) return $value; } - /** - * @param $value - * - * @return int|string - */ - public static function convertValue($value) + public static function convertValue(mixed $value): mixed { - switch (gettype($value)) { + switch (\gettype($value)) { case 'boolean': $conversion = ($value) ? 1 : 0; + break; case 'array': $conversion = json_encode($value); + break; + default: $conversion = $value; + break; } return $conversion; } - /** - * @param $subject - * - * @return bool - */ - public static function isCountable($subject) + public static function isCountable(mixed $subject): bool { - return (is_array($subject) || ($subject instanceof \Countable)); + return \is_array($subject) || ($subject instanceof \Countable); } - /** - * @param $value - * - * @return Literal|mixed - */ - public static function nullToLiteral($value) + public static function nullToLiteral(mixed $value): mixed { if ($value === null) { return new Literal('NULL'); diff --git a/tests/Queries/CommonTest.php b/tests/Queries/CommonTest.php index c0ddb3e..16b0010 100644 --- a/tests/Queries/CommonTest.php +++ b/tests/Queries/CommonTest.php @@ -1,23 +1,32 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +require __DIR__.'/../_resources/init.php'; -use PHPUnit\Framework\TestCase; -use Envms\FluentTest\Model\User; use Envms\FluentPDO\Query; +use Envms\FluentTest\Model\User; +use PHPUnit\Framework\TestCase; /** - * Class CommonTest + * Class CommonTest. * * @covers \Envms\FluentPDO\Queries\Common */ class CommonTest extends TestCase { + protected Query $fluent; - /** @var Query */ - protected $fluent; - - public function setUp(): void + protected function setUp(): void { global $pdo; @@ -26,7 +35,7 @@ public function setUp(): void $this->fluent = new Query($pdo); } - public function testFullJoin() + public function testFullJoin(): void { $query = $this->fluent->from('article') ->select('user.name') @@ -34,18 +43,20 @@ public function testFullJoin() ->orderBy('article.title'); $returnValue = ''; + foreach ($query as $row) { - $returnValue .= "$row[name] - $row[title] "; + $returnValue .= "{$row['name']} - {$row['title']} "; } - self::assertEquals('SELECT article.*, user.name FROM article LEFT JOIN user ON user.id = article.user_id ORDER BY article.title', - $query->getQuery(false)); + self::assertEquals( + 'SELECT article.*, user.name FROM article LEFT JOIN user ON user.id = article.user_id ORDER BY article.title', + $query->getQuery(false), + ); self::assertEquals('Marek - article 1 Robert - article 2 Marek - article 3 Kevin - artïcle 4 Chris - article 5 Chris - სარედაქციო 6 ', $returnValue); } - public function testShortJoin() + public function testShortJoin(): void { - $query = $this->fluent->from('article')->leftJoin('user'); $query2 = $this->fluent->from('article')->leftJoin('user author'); $query3 = $this->fluent->from('article')->leftJoin('user AS author'); @@ -55,40 +66,50 @@ public function testShortJoin() self::assertEquals('SELECT article.* FROM article LEFT JOIN user AS author ON author.id = article.user_id', $query3->getQuery(false)); } - public function testJoinShortBackRef() + public function testJoinShortBackRef(): void { $query = $this->fluent->from('user')->innerJoin('article:'); $query2 = $this->fluent->from('user')->innerJoin('article: with_articles'); $query3 = $this->fluent->from('user')->innerJoin('article: AS with_articles'); self::assertEquals('SELECT user.* FROM user INNER JOIN article ON article.user_id = user.id', $query->getQuery(false)); - self::assertEquals('SELECT user.* FROM user INNER JOIN article AS with_articles ON with_articles.user_id = user.id', - $query2->getQuery(false)); - self::assertEquals('SELECT user.* FROM user INNER JOIN article AS with_articles ON with_articles.user_id = user.id', - $query3->getQuery(false)); + self::assertEquals( + 'SELECT user.* FROM user INNER JOIN article AS with_articles ON with_articles.user_id = user.id', + $query2->getQuery(false), + ); + self::assertEquals( + 'SELECT user.* FROM user INNER JOIN article AS with_articles ON with_articles.user_id = user.id', + $query3->getQuery(false), + ); } - public function testJoinShortMulti() + public function testJoinShortMulti(): void { $query = $this->fluent->from('comment') ->leftJoin('article.user'); - self::assertEquals('SELECT comment.* FROM comment LEFT JOIN article ON article.id = comment.article_id LEFT JOIN user ON user.id = article.user_id', - $query->getQuery(false)); + self::assertEquals( + 'SELECT comment.* FROM comment LEFT JOIN article ON article.id = comment.article_id LEFT JOIN user ON user.id = article.user_id', + $query->getQuery(false), + ); } - public function testJoinMultiBackRef() + public function testJoinMultiBackRef(): void { $query = $this->fluent->from('article') ->innerJoin('comment:user AS comment_user'); - self::assertEquals('SELECT article.* FROM article INNER JOIN comment ON comment.article_id = article.id INNER JOIN user AS comment_user ON comment_user.id = comment.user_id', - $query->getQuery(false)); - self::assertEquals(['id' => '1', 'user_id' => '1', 'published_at' => '2011-12-10 12:10:00', 'title' => 'article 1', 'content' => 'content 1'], - $query->fetch()); + self::assertEquals( + 'SELECT article.* FROM article INNER JOIN comment ON comment.article_id = article.id INNER JOIN user AS comment_user ON comment_user.id = comment.user_id', + $query->getQuery(false), + ); + self::assertEquals( + ['id' => '1', 'user_id' => '1', 'published_at' => '2011-12-10 12:10:00', 'title' => 'article 1', 'content' => 'content 1'], + $query->fetch(), + ); } - public function testJoinShortTwoSameTable() + public function testJoinShortTwoSameTable(): void { $query = $this->fluent->from('article') ->leftJoin('user') @@ -97,60 +118,70 @@ public function testJoinShortTwoSameTable() self::assertEquals('SELECT article.* FROM article LEFT JOIN user ON user.id = article.user_id', $query->getQuery(false)); } - public function testJoinShortTwoTables() + public function testJoinShortTwoTables(): void { $query = $this->fluent->from('comment') ->where('comment.id', 2) ->leftJoin('user comment_author')->select('comment_author.name AS comment_name') ->leftJoin('article.user AS article_author')->select('article_author.name AS author_name'); - self::assertEquals('SELECT comment.*, comment_author.name AS comment_name, article_author.name AS author_name FROM comment LEFT JOIN user AS comment_author ON comment_author.id = comment.user_id LEFT JOIN article ON article.id = comment.article_id LEFT JOIN user AS article_author ON article_author.id = article.user_id WHERE comment.id = ?', - $query->getQuery(false)); + self::assertEquals( + 'SELECT comment.*, comment_author.name AS comment_name, article_author.name AS author_name FROM comment LEFT JOIN user AS comment_author ON comment_author.id = comment.user_id LEFT JOIN article ON article.id = comment.article_id LEFT JOIN user AS article_author ON article_author.id = article.user_id WHERE comment.id = ?', + $query->getQuery(false), + ); self::assertEquals([ - 'id' => '2', - 'article_id' => '1', - 'user_id' => '2', - 'content' => 'comment 1.2', + 'id' => '2', + 'article_id' => '1', + 'user_id' => '2', + 'content' => 'comment 1.2', 'comment_name' => 'Robert', - 'author_name' => 'Marek' + 'author_name' => 'Marek', ], $query->fetch()); } - public function testJoinInWhere() + public function testJoinInWhere(): void { $query = $this->fluent->from('article')->where('comment:content <> "" AND user.country.id = ?', 1); - self::assertEquals('SELECT article.* FROM article LEFT JOIN comment ON comment.article_id = article.id LEFT JOIN user ON user.id = article.user_id LEFT JOIN country ON country.id = user.country_id WHERE comment.content <> "" AND country.id = ?', - $query->getQuery(false)); + self::assertEquals( + 'SELECT article.* FROM article LEFT JOIN comment ON comment.article_id = article.id LEFT JOIN user ON user.id = article.user_id LEFT JOIN country ON country.id = user.country_id WHERE comment.content <> "" AND country.id = ?', + $query->getQuery(false), + ); } - public function testJoinInSelect() + public function testJoinInSelect(): void { $query = $this->fluent->from('article')->select('user.name AS author'); self::assertEquals('SELECT article.*, user.name AS author FROM article LEFT JOIN user ON user.id = article.user_id', $query->getQuery(false)); } - public function testJoinInOrderBy() + public function testJoinInOrderBy(): void { $query = $this->fluent->from('article')->orderBy('user.name, article.title'); - self::assertEquals('SELECT article.* FROM article LEFT JOIN user ON user.id = article.user_id ORDER BY user.name, article.title', - $query->getQuery(false)); + self::assertEquals( + 'SELECT article.* FROM article LEFT JOIN user ON user.id = article.user_id ORDER BY user.name, article.title', + $query->getQuery(false), + ); } - public function testJoinInGroupBy() + public function testJoinInGroupBy(): void { $query = $this->fluent->from('article')->groupBy('user.type') ->select(null)->select('user.type, count(article.id) AS article_count'); - self::assertEquals('SELECT user.type, count(article.id) AS article_count FROM article LEFT JOIN user ON user.id = article.user_id GROUP BY user.type', - $query->getQuery(false)); - self::assertEquals(['0' => ['type' => 'admin', 'article_count' => '4'], '1' => ['type' => 'author', 'article_count' => '2']], - $query->fetchAll()); + self::assertEquals( + 'SELECT user.type, count(article.id) AS article_count FROM article LEFT JOIN user ON user.id = article.user_id GROUP BY user.type', + $query->getQuery(false), + ); + self::assertEquals( + ['0' => ['type' => 'admin', 'article_count' => '4'], '1' => ['type' => 'author', 'article_count' => '2']], + $query->fetchAll(), + ); } - public function testEscapeJoin() + public function testEscapeJoin(): void { $query = $this->fluent->from('article') ->where('user\.name = ?', 'Chris'); @@ -161,11 +192,13 @@ public function testEscapeJoin() ->where('comment.id = :id', 1) ->where('user\.name = :name', 'Chris'); - self::assertEquals('SELECT article.* FROM article LEFT JOIN comment ON comment.id = article.comment_id WHERE comment.id = :id AND user.name = :name', - $query->getQuery(false)); + self::assertEquals( + 'SELECT article.* FROM article LEFT JOIN comment ON comment.id = article.comment_id WHERE comment.id = :id AND user.name = :name', + $query->getQuery(false), + ); } - public function testDontCreateDuplicateJoins() + public function testDontCreateDuplicateJoins(): void { $query = $this->fluent->from('article') ->innerJoin('user AS author ON article.user_id = author.id') @@ -183,35 +216,43 @@ public function testDontCreateDuplicateJoins() ->innerJoin('user ON article.user_id = user.id') ->select('user.country.name'); - self::assertEquals('SELECT article.*, author.name FROM article INNER JOIN user AS author ON article.user_id = author.id', - $query->getQuery(false)); + self::assertEquals( + 'SELECT article.*, author.name FROM article INNER JOIN user AS author ON article.user_id = author.id', + $query->getQuery(false), + ); self::assertEquals('SELECT article.*, user.name FROM article INNER JOIN user ON article.user_id = user.id', $query2->getQuery(false)); - self::assertEquals('SELECT article.*, country.name FROM article INNER JOIN user AS author ON article.user_id = author.id LEFT JOIN country ON country.id = author.country_id', - $query3->getQuery(false)); - self::assertEquals('SELECT article.*, country.name FROM article INNER JOIN user ON article.user_id = user.id LEFT JOIN country ON country.id = user.country_id', - $query4->getQuery(false)); + self::assertEquals( + 'SELECT article.*, country.name FROM article INNER JOIN user AS author ON article.user_id = author.id LEFT JOIN country ON country.id = author.country_id', + $query3->getQuery(false), + ); + self::assertEquals( + 'SELECT article.*, country.name FROM article INNER JOIN user ON article.user_id = user.id LEFT JOIN country ON country.id = user.country_id', + $query4->getQuery(false), + ); } - public function testClauseWithRefBeforeJoin() + public function testClauseWithRefBeforeJoin(): void { $query = $this->fluent->from('article')->select('user.name')->innerJoin('user'); $query2 = $this->fluent->from('article')->select('author.name')->innerJoin('user AS author'); $query3 = $this->fluent->from('user')->select('article:title')->innerJoin('article:'); self::assertEquals('SELECT article.*, user.name FROM article INNER JOIN user ON user.id = article.user_id', $query->getQuery(false)); - self::assertEquals('SELECT article.*, author.name FROM article INNER JOIN user AS author ON author.id = article.user_id', - $query2->getQuery(false)); + self::assertEquals( + 'SELECT article.*, author.name FROM article INNER JOIN user AS author ON author.id = article.user_id', + $query2->getQuery(false), + ); self::assertEquals('SELECT user.*, article.title FROM user INNER JOIN article ON article.user_id = user.id', $query3->getQuery(false)); } - public function testFromOtherDB() + public function testFromOtherDB(): void { $queryPrint = $this->fluent->from('db2.user')->where('db2.user.name', 'name')->order('db2.user.name')->getQuery(false); self::assertEquals('SELECT db2.user.* FROM db2.user WHERE db2.user.name = ? ORDER BY db2.user.name', $queryPrint); } - public function testJoinTableWithUsing() + public function testJoinTableWithUsing(): void { $query = $this->fluent->from('article') ->innerJoin('user USING (user_id)') @@ -233,13 +274,13 @@ public function testJoinTableWithUsing() self::assertEquals('SELECT article.*, u.* FROM article INNER JOIN user AS u USING (user_id)', $query3); } - public function testDisableSmartJoin() + public function testDisableSmartJoin(): void { $query = $this->fluent->from('comment') ->select('user.name') ->orderBy('article.published_at') ->getQuery(false); - $printQuery = "-- Plain: $query"; + $printQuery = "-- Plain: {$query}"; $query2 = $this->fluent->from('comment') ->select('user.name') @@ -247,7 +288,7 @@ public function testDisableSmartJoin() ->orderBy('article.published_at') ->getQuery(false); - $printQuery2 = "-- Disable: $query2"; + $printQuery2 = "-- Disable: {$query2}"; $query3 = $this->fluent->from('comment') ->disableSmartJoin() @@ -255,16 +296,20 @@ public function testDisableSmartJoin() ->enableSmartJoin() ->orderBy('article.published_at') ->getQuery(false); - $printQuery3 = "-- Disable and enable: $query3"; + $printQuery3 = "-- Disable and enable: {$query3}"; - self::assertEquals('-- Plain: SELECT comment.*, user.name FROM comment LEFT JOIN user ON user.id = comment.user_id LEFT JOIN article ON article.id = comment.article_id ORDER BY article.published_at', - $printQuery); + self::assertEquals( + '-- Plain: SELECT comment.*, user.name FROM comment LEFT JOIN user ON user.id = comment.user_id LEFT JOIN article ON article.id = comment.article_id ORDER BY article.published_at', + $printQuery, + ); self::assertEquals('-- Disable: SELECT comment.*, user.name FROM comment ORDER BY article.published_at', $printQuery2); - self::assertEquals('-- Disable and enable: SELECT comment.*, user.name FROM comment LEFT JOIN user ON user.id = comment.user_id LEFT JOIN article ON article.id = comment.article_id ORDER BY article.published_at', - $printQuery3); + self::assertEquals( + '-- Disable and enable: SELECT comment.*, user.name FROM comment LEFT JOIN user ON user.id = comment.user_id LEFT JOIN article ON article.id = comment.article_id ORDER BY article.published_at', + $printQuery3, + ); } - public function testPDOFetchObj() + public function testPDOFetchObj(): void { $query = $this->fluent->from('user')->where('id > ?', 0)->orderBy('name'); $query = $query->where('name = ?', 'Marek'); @@ -280,7 +325,7 @@ public function testPDOFetchObj() self::assertEquals($expectObj, $query->fetch()); } - public function testFromIdAsObject() + public function testFromIdAsObject(): void { $query = $this->fluent->from('user', 2)->asObject(); @@ -294,7 +339,7 @@ public function testFromIdAsObject() self::assertEquals($expectObj, $query->fetch()); } - public function testFromIdAsObjectUser() + public function testFromIdAsObjectUser(): void { $expectedUser = new User(); $expectedUser->id = 2; @@ -308,5 +353,4 @@ public function testFromIdAsObjectUser() self::assertEquals('SELECT user.* FROM user WHERE user.id = ?', $query->getQuery(false)); self::assertEquals($expectedUser, $user); } - } diff --git a/tests/Queries/DeleteTest.php b/tests/Queries/DeleteTest.php index 5abd677..a5960c5 100644 --- a/tests/Queries/DeleteTest.php +++ b/tests/Queries/DeleteTest.php @@ -1,22 +1,31 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +require __DIR__.'/../_resources/init.php'; -use PHPUnit\Framework\TestCase; use Envms\FluentPDO\Query; +use PHPUnit\Framework\TestCase; /** - * Class DeleteTest + * Class DeleteTest. * * @covers \Envms\FluentPDO\Queries\Delete */ class DeleteTest extends TestCase { + protected Query $fluent; - /** @var Query */ - protected $fluent; - - public function setUp(): void + protected function setUp(): void { global $pdo; @@ -25,7 +34,7 @@ public function setUp(): void $this->fluent = new Query($pdo); } - public function testDelete() + public function testDelete(): void { $query = $this->fluent->deleteFrom('user') ->where('id', 1); @@ -34,7 +43,7 @@ public function testDelete() self::assertEquals(['0' => '1'], $query->getParameters()); } - public function testDeleteIgnore() + public function testDeleteIgnore(): void { $query = $this->fluent->deleteFrom('user') ->ignore() @@ -44,7 +53,7 @@ public function testDeleteIgnore() self::assertEquals(['0' => '1'], $query->getParameters()); } - public function testDeleteOrderLimit() + public function testDeleteOrderLimit(): void { $query = $this->fluent->deleteFrom('user') ->where('id', 2) @@ -55,7 +64,7 @@ public function testDeleteOrderLimit() self::assertEquals(['0' => '2'], $query->getParameters()); } - public function testDeleteExpanded() + public function testDeleteExpanded(): void { $query = $this->fluent->delete('t1, t2') ->from('t1') @@ -63,12 +72,14 @@ public function testDeleteExpanded() ->innerJoin('t3 ON t2.id = t3.id') ->where('t1.id', 1); - self::assertEquals('DELETE t1, t2 FROM t1 INNER JOIN t2 ON t1.id = t2.id INNER JOIN t3 ON t2.id = t3.id WHERE t1.id = ?', - $query->getQuery(false)); + self::assertEquals( + 'DELETE t1, t2 FROM t1 INNER JOIN t2 ON t1.id = t2.id INNER JOIN t3 ON t2.id = t3.id WHERE t1.id = ?', + $query->getQuery(false), + ); self::assertEquals(['0' => '1'], $query->getParameters()); } - public function testDeleteShortcut() + public function testDeleteShortcut(): void { $query = $this->fluent->deleteFrom('user', 1); @@ -76,11 +87,11 @@ public function testDeleteShortcut() self::assertEquals(['0' => '1'], $query->getParameters()); } - public function testAddFromAfterDelete() + public function testAddFromAfterDelete(): void { $query = $this->fluent->delete('user', 1)->from('user'); self::assertEquals('DELETE user FROM user WHERE id = ?', $query->getQuery(false)); self::assertEquals(['0' => '1'], $query->getParameters()); } -} \ No newline at end of file +} diff --git a/tests/Queries/InsertTest.php b/tests/Queries/InsertTest.php index 73d2de0..f074c16 100644 --- a/tests/Queries/InsertTest.php +++ b/tests/Queries/InsertTest.php @@ -1,22 +1,31 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +require __DIR__.'/../_resources/init.php'; -use PHPUnit\Framework\TestCase; use Envms\FluentPDO\Query; +use PHPUnit\Framework\TestCase; /** - * Class InsertTest + * Class InsertTest. * * @covers \Envms\FluentPDO\Queries\Insert */ class InsertTest extends TestCase { + protected Envms\FluentPDO\Query $fluent; - /** @var Envms\FluentPDO\Query */ - protected $fluent; - - public function setUp(): void + protected function setUp(): void { global $pdo; @@ -25,25 +34,25 @@ public function setUp(): void $this->fluent = new Query($pdo); } - public function testInsertStatement() + public function testInsertStatement(): void { $query = $this->fluent->insertInto('article', [ 'user_id' => 1, - 'title' => 'new title', - 'content' => 'new content' + 'title' => 'new title', + 'content' => 'new content', ]); self::assertEquals('INSERT INTO article (user_id, title, content) VALUES (?, ?, ?)', $query->getQuery(false)); self::assertEquals(['0' => '1', '1' => 'new title', '2' => 'new content'], $query->getParameters()); } - public function testInsertUpdate() + public function testInsertUpdate(): void { $query = $this->fluent->insertInto('article', ['id' => 1]) ->onDuplicateKeyUpdate([ 'published_at' => '2011-12-10 12:10:00', - 'title' => 'article 1b', - 'content' => new Envms\FluentPDO\Literal('abs(-1)') // let's update with a literal and a parameter value + 'title' => 'article 1b', + 'content' => new Envms\FluentPDO\Literal('abs(-1)'), // let's update with a literal and a parameter value ]); $q = $this->fluent->from('article', 1); @@ -51,7 +60,7 @@ public function testInsertUpdate() $query2 = $this->fluent->insertInto('article', ['id' => 1]) ->onDuplicateKeyUpdate([ 'published_at' => '2011-12-10 12:10:00', - 'title' => 'article 1', + 'title' => 'article 1', 'content' => 'content 1', ]); @@ -59,38 +68,46 @@ public function testInsertUpdate() self::assertEquals('INSERT INTO article (id) VALUES (?) ON DUPLICATE KEY UPDATE published_at = ?, title = ?, content = abs(-1)', $query->getQuery(false)); self::assertEquals([0 => '1', 1 => '2011-12-10 12:10:00', 2 => 'article 1b'], $query->getParameters()); - self::assertEquals('last_inserted_id = 1', 'last_inserted_id = ' . $query->execute()); - self::assertEquals(['id' => '1', 'user_id' => '1', 'published_at' => '2011-12-10 12:10:00', 'title' => 'article 1b', 'content' => '1'], - $q->fetch()); - self::assertEquals('last_inserted_id = 1', 'last_inserted_id = ' . $query2->execute()); - self::assertEquals(['id' => '1', 'user_id' => '1', 'published_at' => '2011-12-10 12:10:00', 'title' => 'article 1', 'content' => 'content 1'], - $q2->fetch()); + self::assertEquals('last_inserted_id = 1', 'last_inserted_id = '.$query->execute()); + self::assertEquals( + ['id' => '1', 'user_id' => '1', 'published_at' => '2011-12-10 12:10:00', 'title' => 'article 1b', 'content' => '1'], + $q->fetch(), + ); + self::assertEquals('last_inserted_id = 1', 'last_inserted_id = '.$query2->execute()); + self::assertEquals( + ['id' => '1', 'user_id' => '1', 'published_at' => '2011-12-10 12:10:00', 'title' => 'article 1', 'content' => 'content 1'], + $q2->fetch(), + ); } - public function testInsertWithLiteral() + public function testInsertWithLiteral(): void { - $query = $this->fluent->insertInto('article', + $query = $this->fluent->insertInto( + 'article', [ - 'user_id' => 1, + 'user_id' => 1, 'updated_at' => new Envms\FluentPDO\Literal('NOW()'), - 'title' => 'new title', - 'content' => 'new content', - ]); + 'title' => 'new title', + 'content' => 'new content', + ], + ); self::assertEquals('INSERT INTO article (user_id, updated_at, title, content) VALUES (?, NOW(), ?, ?)', $query->getQuery(false)); self::assertEquals(['0' => '1', '1' => 'new title', '2' => 'new content'], $query->getParameters()); } - public function testInsertIgnore() + public function testInsertIgnore(): void { - $query = $this->fluent->insertInto('article', + $query = $this->fluent->insertInto( + 'article', [ 'user_id' => 1, - 'title' => 'new title', + 'title' => 'new title', 'content' => 'new content', - ])->ignore(); + ], + )->ignore(); self::assertEquals('INSERT IGNORE INTO article (user_id, title, content) VALUES (?, ?, ?)', $query->getQuery(false)); self::assertEquals(['0' => '1', '1' => 'new title', '2' => 'new content'], $query->getParameters()); } -} \ No newline at end of file +} diff --git a/tests/Queries/SelectTest.php b/tests/Queries/SelectTest.php index ea22d69..ddefd2c 100644 --- a/tests/Queries/SelectTest.php +++ b/tests/Queries/SelectTest.php @@ -1,22 +1,31 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +require __DIR__.'/../_resources/init.php'; -use PHPUnit\Framework\TestCase; use Envms\FluentPDO\Query; +use PHPUnit\Framework\TestCase; /** - * Class SelectTest + * Class SelectTest. * * @covers \Envms\FluentPDO\Queries\Select */ class SelectTest extends TestCase { + protected Query $fluent; - /** @var Query */ - protected $fluent; - - public function setUp(): void + protected function setUp(): void { global $pdo; @@ -25,7 +34,7 @@ public function setUp(): void $this->fluent = new Query($pdo); } - public function testBasicQuery() + public function testBasicQuery(): void { $query = $this->fluent ->from('user') @@ -39,9 +48,8 @@ public function testBasicQuery() self::assertEquals([0 => 0, 1 => 'Marek'], $query->getParameters()); } - public function testReturnQueryWithHaving() + public function testReturnQueryWithHaving(): void { - $query = $this->fluent ->from('user') ->select(null) @@ -51,11 +59,13 @@ public function testReturnQueryWithHaving() ->having('type_count > ?', 1) ->orderBy('name'); - self::assertEquals("SELECT type, count(id) AS type_count FROM user WHERE id > ? GROUP BY type HAVING type_count > ? ORDER BY name", - $query->getQuery(false)); + self::assertEquals( + 'SELECT type, count(id) AS type_count FROM user WHERE id > ? GROUP BY type HAVING type_count > ? ORDER BY name', + $query->getQuery(false), + ); } - public function testReturnParameterWithId() + public function testReturnParameterWithId(): void { $query = $this->fluent ->from('user', 2); @@ -64,7 +74,7 @@ public function testReturnParameterWithId() self::assertEquals('SELECT user.* FROM user WHERE user.id = ?', $query->getQuery(false)); } - public function testFromWithAlias() + public function testFromWithAlias(): void { $query = $this->fluent->from('user author')->getQuery(false); $query2 = $this->fluent->from('user AS author')->getQuery(false); @@ -77,20 +87,20 @@ public function testFromWithAlias() self::assertEquals('SELECT author.*, country.name FROM user AS author LEFT JOIN country ON country.id = user AS author.country_id', $query4); } - public function testWhereArrayParameter() + public function testWhereArrayParameter(): void { $query = $this->fluent ->from('user') ->where([ 'id' => 2, - 'type' => 'author' + 'type' => 'author', ]); self::assertEquals('SELECT user.* FROM user WHERE id = ? AND type = ?', $query->getQuery(false)); self::assertEquals([0 => 2, 1 => 'author'], $query->getParameters()); } - public function testWhereColumnValue() + public function testWhereColumnValue(): void { $query = $this->fluent->from('user') ->where('type', 'author'); @@ -99,7 +109,7 @@ public function testWhereColumnValue() self::assertEquals([0 => 'author'], $query->getParameters()); } - public function testWhereColumnNull() + public function testWhereColumnNull(): void { $query = $this->fluent ->from('user') @@ -108,7 +118,7 @@ public function testWhereColumnNull() self::assertEquals('SELECT user.* FROM user WHERE type IS NULL', $query->getQuery(false)); } - public function testWhereColumnArray() + public function testWhereColumnArray(): void { $query = $this->fluent ->from('user') @@ -118,7 +128,7 @@ public function testWhereColumnArray() self::assertEquals([], $query->getParameters()); } - public function testWherePreparedArray() + public function testWherePreparedArray(): void { $query = $this->fluent ->from('user') @@ -128,13 +138,14 @@ public function testWherePreparedArray() self::assertEquals([0 => 1, 1 => 2, 2 => 3], $query->getParameters()); } - public function testWhereColumnName() + public function testWhereColumnName(): void { $query = $this->fluent->from('user') ->where('type = :type', [':type' => 'author']) ->where('id > :id AND name <> :name', [':id' => 3, ':name' => 'Marek']); $returnValue = ''; + foreach ($query as $row) { $returnValue = $row['name']; } @@ -144,18 +155,20 @@ public function testWhereColumnName() self::assertEquals('Kevin', $returnValue); } - public function testWhereOr() + public function testWhereOr(): void { $query = $this->fluent->from('comment') ->where('comment.id = :id', [':id' => 1]) ->whereOr('user.id = :userId', [':userId' => 2]); - self::assertEquals('SELECT comment.* FROM comment LEFT JOIN user ON user.id = comment.user_id WHERE comment.id = :id OR user.id = :userId', - $query->getQuery(false)); + self::assertEquals( + 'SELECT comment.* FROM comment LEFT JOIN user ON user.id = comment.user_id WHERE comment.id = :id OR user.id = :userId', + $query->getQuery(false), + ); self::assertEquals([':id' => '1', ':userId' => '2'], $query->getParameters()); } - public function testWhereReset() + public function testWhereReset(): void { $query = $this->fluent->from('user')->where('id > ?', 0)->orderBy('name'); $query = $query->where(null)->where('name = ?', 'Marek'); @@ -165,9 +178,7 @@ public function testWhereReset() self::assertEquals(['id' => '1', 'country_id' => '1', 'type' => 'admin', 'name' => 'Marek'], $query->fetch()); } - - - public function testSelectArrayParam() + public function testSelectArrayParam(): void { $query = $this->fluent ->from('user') @@ -180,7 +191,7 @@ public function testSelectArrayParam() self::assertEquals(['id' => '1', 'name' => 'Marek'], $query->fetch()); } - public function testGroupByArrayParam() + public function testGroupByArrayParam(): void { $query = $this->fluent ->from('user') @@ -192,7 +203,7 @@ public function testGroupByArrayParam() self::assertEquals(['total_count' => '1'], $query->fetch()); } - public function testCountable() + public function testCountable(): void { $articles = $this->fluent ->from('article') @@ -201,26 +212,27 @@ public function testCountable() ->where('id > 1') ->where('id < 4'); - $count = count($articles); + $count = \count($articles); self::assertEquals(2, $count); self::assertEquals([0 => ['title' => 'article 2'], 1 => ['title' => 'article 3']], $articles->fetchAll()); } - public function testWhereNotArray() + public function testWhereNotArray(): void { $query = $this->fluent->from('article')->where('NOT id', [1, 2]); self::assertEquals('SELECT article.* FROM article WHERE NOT id IN (1, 2)', $query->getQuery(false)); } - public function testWhereColNameEscaped() + public function testWhereColNameEscaped(): void { $query = $this->fluent->from('user') ->where('`type` = :type', [':type' => 'author']) ->where('`id` > :id AND `name` <> :name', [':id' => 3, ':name' => 'Marek']); $rowDisplay = ''; + foreach ($query as $row) { $rowDisplay = $row['name']; } @@ -230,14 +242,14 @@ public function testWhereColNameEscaped() self::assertEquals('Kevin', $rowDisplay); } - public function testAliasesForClausesGroupbyOrderBy() + public function testAliasesForClausesGroupbyOrderBy(): void { $query = $this->fluent->from('article')->group('user_id')->order('id'); self::assertEquals('SELECT article.* FROM article GROUP BY user_id ORDER BY id', $query->getQuery(false)); } - public function testFetch() + public function testFetch(): void { $queryPrint = $this->fluent->from('user', 1)->fetch('name'); $queryPrint2 = $this->fluent->from('user', 1)->fetch(); @@ -246,11 +258,11 @@ public function testFetch() self::assertEquals('Marek', $queryPrint); self::assertEquals(['id' => '1', 'country_id' => '1', 'type' => 'admin', 'name' => 'Marek'], $queryPrint2); - self::assertEquals(false, $statement); - self::assertEquals(false, $statement2); + self::assertFalse($statement); + self::assertFalse($statement2); } - public function testFetchPairsFetchAll() + public function testFetchPairsFetchAll(): void { $result = $this->fluent->from('user')->fetchPairs('id', 'name'); $result2 = $this->fluent->from('user')->fetchAll(); @@ -260,20 +272,22 @@ public function testFetchPairsFetchAll() 0 => ['id' => '1', 'country_id' => '1', 'type' => 'admin', 'name' => 'Marek'], 1 => ['id' => '2', 'country_id' => '1', 'type' => 'author', 'name' => 'Robert'], 2 => ['id' => '3', 'country_id' => '2', 'type' => 'admin', 'name' => 'Chris'], - 3 => ['id' => '4', 'country_id' => '2', 'type' => 'author', 'name' => 'Kevin'] + 3 => ['id' => '4', 'country_id' => '2', 'type' => 'author', 'name' => 'Kevin'], ], $result2); } - public function testFetchAllWithParams() + public function testFetchAllWithParams(): void { $result = $this->fluent->from('user')->fetchAll('id', 'type, name'); - self::assertEquals([1 => ['id' => '1', 'type' => 'admin', 'name' => 'Marek'], 2 => ['id' => '2', 'type' => 'author', 'name' => 'Robert'], - 3 => ['id' => '3', 'type' => 'admin', 'name' => 'Chris'], 4 => ['id' => '4', 'type' => 'author', 'name' => 'Kevin']], - $result); + self::assertEquals( + [1 => ['id' => '1', 'type' => 'admin', 'name' => 'Marek'], 2 => ['id' => '2', 'type' => 'author', 'name' => 'Robert'], + 3 => ['id' => '3', 'type' => 'admin', 'name' => 'Chris'], 4 => ['id' => '4', 'type' => 'author', 'name' => 'Kevin']], + $result, + ); } - public function testFetchColumn() + public function testFetchColumn(): void { $printColumn = $this->fluent->from('user', 3)->fetchColumn(); $printColumn2 = $this->fluent->from('user', 3)->fetchColumn(3); @@ -282,7 +296,7 @@ public function testFetchColumn() self::assertEquals(3, $printColumn); self::assertEquals('Chris', $printColumn2); - self::assertEquals(false, $statement); - self::assertEquals(false, $statement2); + self::assertFalse($statement); + self::assertFalse($statement2); } -} \ No newline at end of file +} diff --git a/tests/Queries/UpdateTest.php b/tests/Queries/UpdateTest.php index 4e231d5..c4d6d29 100644 --- a/tests/Queries/UpdateTest.php +++ b/tests/Queries/UpdateTest.php @@ -1,22 +1,31 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +require __DIR__.'/../_resources/init.php'; -use PHPUnit\Framework\TestCase; use Envms\FluentPDO\Query; +use PHPUnit\Framework\TestCase; /** - * Class UpdateTest + * Class UpdateTest. * * @covers \Envms\FluentPDO\Queries\Update */ class UpdateTest extends TestCase { + protected Query $fluent; - /** @var Query */ - protected $fluent; - - public function setUp(): void + protected function setUp(): void { global $pdo; @@ -25,7 +34,7 @@ public function setUp(): void $this->fluent = new Query($pdo); } - public function testUpdate() + public function testUpdate(): void { $query = $this->fluent->update('country')->set('name', 'aikavolS')->where('id', 1); $query->execute(); @@ -42,7 +51,7 @@ public function testUpdate() self::assertEquals(['id' => '1', 'name' => 'Slovakia', 'details' => '{"gdp": 90.75, "pop": 5456300, "name": "Slovensko"}'], $query3->fetch()); } - public function testUpdateLiteral() + public function testUpdateLiteral(): void { $query = $this->fluent->update('article')->set('published_at', new Envms\FluentPDO\Literal('NOW()'))->where('user_id', 1); @@ -50,7 +59,7 @@ public function testUpdateLiteral() self::assertEquals(['0' => '1'], $query->getParameters()); } - public function testUpdateFromArray() + public function testUpdateFromArray(): void { $query = $this->fluent->update('user')->set(['name' => 'keraM', '`type`' => 'author'])->where('id', 1); @@ -58,30 +67,34 @@ public function testUpdateFromArray() self::assertEquals([0 => 'keraM', 1 => 'author', 2 => '1'], $query->getParameters()); } - public function testUpdateLeftJoin() + public function testUpdateLeftJoin(): void { $query = $this->fluent->update('user') ->outerJoin('country ON country.id = user.country_id') ->set(['name' => 'keraM', '`type`' => 'author']) ->where('id', 1); - self::assertEquals('UPDATE user OUTER JOIN country ON country.id = user.country_id SET name = ?, `type` = ? WHERE id = ?', - $query->getQuery(false)); + self::assertEquals( + 'UPDATE user OUTER JOIN country ON country.id = user.country_id SET name = ?, `type` = ? WHERE id = ?', + $query->getQuery(false), + ); self::assertEquals([0 => 'keraM', 1 => 'author', 2 => '1'], $query->getParameters()); } - public function testUpdateSmartJoin() + public function testUpdateSmartJoin(): void { $query = $this->fluent->update('user') ->set(['type' => 'author']) ->where('country.id', 1); - self::assertEquals('UPDATE user LEFT JOIN country ON country.id = user.country_id SET type = ? WHERE country.id = ?', - $query->getQuery(false)); + self::assertEquals( + 'UPDATE user LEFT JOIN country ON country.id = user.country_id SET type = ? WHERE country.id = ?', + $query->getQuery(false), + ); self::assertEquals([0 => 'author', 1 => '1'], $query->getParameters()); } - public function testUpdateOrderLimit() + public function testUpdateOrderLimit(): void { $query = $this->fluent->update('user') ->set(['type' => 'author']) @@ -93,7 +106,7 @@ public function testUpdateOrderLimit() self::assertEquals([0 => 'author', 1 => '2'], $query->getParameters()); } - public function testUpdateShortCut() + public function testUpdateShortCut(): void { $query = $this->fluent->update('user', ['type' => 'admin'], 1); @@ -101,7 +114,7 @@ public function testUpdateShortCut() self::assertEquals([0 => 'admin', 1 => '1'], $query->getParameters()); } - public function testUpdateZero() + public function testUpdateZero(): void { $this->fluent->update('article')->set('content', '')->where('id', 1)->execute(); $user = $this->fluent->from('article')->where('id', 1)->fetch(); @@ -118,35 +131,40 @@ public function testUpdateZero() self::assertEquals('ID: 1 - content: content 1', $printQuery2); } - public function testUpdateWhere() + public function testUpdateWhere(): void { $query = $this->fluent->update('users') - ->set("`users`.`active`", 1) - ->where("`country`.`name`", 'Slovakia') - ->where("`users`.`name`", 'Marek'); + ->set('`users`.`active`', 1) + ->where('`country`.`name`', 'Slovakia') + ->where('`users`.`name`', 'Marek'); $query2 = $this->fluent->update('users') - ->set("[users].[active]", 1) - ->where("[country].[name]", 'Slovakia') - ->where("[users].[name]", 'Marek'); - - self::assertEquals('UPDATE users LEFT JOIN country ON country.id = users.country_id SET `users`.`active` = ? WHERE `country`.`name` = ? AND `users`.`name` = ?', - $query->getQuery(false)); + ->set('[users].[active]', 1) + ->where('[country].[name]', 'Slovakia') + ->where('[users].[name]', 'Marek'); + + self::assertEquals( + 'UPDATE users LEFT JOIN country ON country.id = users.country_id SET `users`.`active` = ? WHERE `country`.`name` = ? AND `users`.`name` = ?', + $query->getQuery(false), + ); self::assertEquals([0 => '1', 1 => 'Slovakia', 2 => 'Marek'], $query->getParameters()); - self::assertEquals('UPDATE users LEFT JOIN country ON country.id = users.country_id SET [users].[active] = ? WHERE [country].[name] = ? AND [users].[name] = ?', - $query2->getQuery(false)); + self::assertEquals( + 'UPDATE users LEFT JOIN country ON country.id = users.country_id SET [users].[active] = ? WHERE [country].[name] = ? AND [users].[name] = ?', + $query2->getQuery(false), + ); self::assertEquals([0 => '1', 1 => 'Slovakia', 2 => 'Marek'], $query2->getParameters()); } - public function testUpdateNamedParameters() + public function testUpdateNamedParameters(): void { $query = $this->fluent->update('users') - ->set("`users`.`active`", [':active' => 1]) - ->where("`country`.`name` = :country", [':country' => 'Slovakia']); + ->set('`users`.`active`', [':active' => 1]) + ->where('`country`.`name` = :country', [':country' => 'Slovakia']); - self::assertEquals('UPDATE users LEFT JOIN country ON country.id = users.country_id SET `users`.`active` = :active WHERE `country`.`name` = :country', - $query->getQuery(false)); + self::assertEquals( + 'UPDATE users LEFT JOIN country ON country.id = users.country_id SET `users`.`active` = :active WHERE `country`.`name` = :country', + $query->getQuery(false), + ); self::assertEquals([':active' => '1', ':country' => 'Slovakia'], $query->getParameters()); } - } diff --git a/tests/RegexTest.php b/tests/RegexTest.php index 3cbd82c..12eb223 100644 --- a/tests/RegexTest.php +++ b/tests/RegexTest.php @@ -1,115 +1,124 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +require __DIR__.'/_resources/init.php'; -use PHPUnit\Framework\TestCase; use Envms\FluentPDO\Regex; +use PHPUnit\Framework\TestCase; /** - * Class StructureTest + * Class StructureTest. * * @covers \Envms\FluentPDO\Structure */ class RegexTest extends TestCase { - /** @var Regex */ - protected $regex; + protected Regex $regex; - public function setUp(): void + protected function setUp(): void { $this->regex = new Regex(); } - public function testCamelCasedSpaced() + public function testCamelCasedSpaced(): void { - $name = $this->regex->camelCaseSpaced("magicCallMethod"); + $name = $this->regex->camelCaseSpaced('magicCallMethod'); - self::assertEquals("magic Call Method", $name); + self::assertEquals('magic Call Method', $name); } - public function testSplitClauses() + public function testSplitClauses(): void { - $query = $this->regex->splitClauses("SELECT * FROM user WHERE id = 1 OR id = 2 ORDER BY id ASC"); + $query = $this->regex->splitClauses('SELECT * FROM user WHERE id = 1 OR id = 2 ORDER BY id ASC'); self::assertEquals("SELECT * \nFROM user \nWHERE id = 1 OR id = 2 \nORDER BY id ASC", $query); } - public function testSplitSubClauses() + public function testSplitSubClauses(): void { - $query = $this->regex->splitSubClauses("SELECT * FROM user LEFT JOIN article WHERE 1 OR 2"); + $query = $this->regex->splitSubClauses('SELECT * FROM user LEFT JOIN article WHERE 1 OR 2'); self::assertEquals("SELECT * FROM user \n LEFT JOIN article WHERE 1 \n OR 2", $query); } - public function testRemoveLineEndWhitespace() + public function testRemoveLineEndWhitespace(): void { $query = $this->regex->removeLineEndWhitespace("SELECT * \n FROM user \n"); self::assertEquals("SELECT *\n FROM user\n", $query); } - public function testRemoveAdditionalJoins() + public function testRemoveAdditionalJoins(): void { - $join = $this->regex->removeAdditionalJoins("user.article:id"); + $join = $this->regex->removeAdditionalJoins('user.article:id'); - self::assertEquals("article.id", $join); + self::assertEquals('article.id', $join); } - public function testSqlParameter() + public function testSqlParameter(): void { - $isParam = $this->regex->sqlParameter("id = :id"); + $isParam = $this->regex->sqlParameter('id = :id'); self::assertEquals(1, $isParam); - $isParam = $this->regex->sqlParameter("name = ?"); + $isParam = $this->regex->sqlParameter('name = ?'); self::assertEquals(1, $isParam); - $isParam = $this->regex->sqlParameter("count IN (22, 77)"); + $isParam = $this->regex->sqlParameter('count IN (22, 77)'); self::assertEquals(0, $isParam); } - public function testTableAlias() + public function testTableAlias(): void { - $isAlias = $this->regex->tableAlias("user AS u"); + $isAlias = $this->regex->tableAlias('user AS u'); self::assertEquals(1, $isAlias); - $isAlias = $this->regex->tableAlias("user.*"); + $isAlias = $this->regex->tableAlias('user.*'); self::assertEquals(1, $isAlias); - $isAlias = $this->regex->tableAlias(" "); + $isAlias = $this->regex->tableAlias(' '); self::assertEquals(0, $isAlias); - $isAlias = $this->regex->tableAlias("0.00 AS ཎ"); + $isAlias = $this->regex->tableAlias('0.00 AS ཎ'); self::assertEquals(1, $isAlias); } - public function testTableJoin() + public function testTableJoin(): void { - $join = $this->regex->tableJoin("user"); + $join = $this->regex->tableJoin('user'); self::assertEquals(1, $join); - $join = $this->regex->tableJoin("`user`."); + $join = $this->regex->tableJoin('`user`.'); self::assertEquals(1, $join); $join = $this->regex->tableJoin("'''"); self::assertEquals(0, $join); - $join = $this->regex->tableJoin("ឃឡឱ."); + $join = $this->regex->tableJoin('ឃឡឱ.'); self::assertEquals(1, $join); } - public function testTableJoinFull() + public function testTableJoinFull(): void { - $join = $this->regex->tableJoinFull("user."); + $join = $this->regex->tableJoinFull('user.'); self::assertEquals(1, $join); - $join = $this->regex->tableJoinFull("`user`.`column`"); + $join = $this->regex->tableJoinFull('`user`.`column`'); self::assertEquals(1, $join); - $join = $this->regex->tableJoinFull("user .column"); + $join = $this->regex->tableJoinFull('user .column'); self::assertEquals(0, $join); - $join = $this->regex->tableJoinFull("ㇽㇺㇴ.ㇱ"); + $join = $this->regex->tableJoinFull('ㇽㇺㇴ.ㇱ'); self::assertEquals(1, $join); } - } diff --git a/tests/StructureTest.php b/tests/StructureTest.php index c02dbf2..04956bd 100644 --- a/tests/StructureTest.php +++ b/tests/StructureTest.php @@ -1,19 +1,29 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +require __DIR__.'/_resources/init.php'; -use PHPUnit\Framework\TestCase; use Envms\FluentPDO\Structure; +use PHPUnit\Framework\TestCase; /** - * Class StructureTest + * Class StructureTest. * * @covers \Envms\FluentPDO\Structure */ class StructureTest extends TestCase { - - public function testBasicKey() + public function testBasicKey(): void { $structure = new Structure(); @@ -21,7 +31,7 @@ public function testBasicKey() self::assertEquals('user_id', $structure->getForeignKey('user')); } - public function testCustomKey() + public function testCustomKey(): void { $structure = new Structure('whatAnId', '%s_\xid'); @@ -29,7 +39,7 @@ public function testCustomKey() self::assertEquals('user_\xid', $structure->getForeignKey('user')); } - public function testMethodKey() + public function testMethodKey(): void { $structure = new Structure('id', ['StructureTest', 'suffix']); @@ -38,13 +48,10 @@ public function testMethodKey() } /** - * @param $table - * * @return string */ public static function suffix($table) { - return $table . '_id'; + return $table.'_id'; } - } diff --git a/tests/UtilitiesTest.php b/tests/UtilitiesTest.php index 87ce580..afdc95a 100644 --- a/tests/UtilitiesTest.php +++ b/tests/UtilitiesTest.php @@ -1,20 +1,30 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +require __DIR__.'/_resources/init.php'; + +use Envms\FluentPDO\Query; +use Envms\FluentPDO\Utilities; use PHPUnit\Framework\TestCase; -use Envms\FluentPDO\{Query,Utilities}; /** - * Class UtilitiesTest + * Class UtilitiesTest. */ class UtilitiesTest extends TestCase { + protected Envms\FluentPDO\Query $fluent; - /** @var Envms\FluentPDO\Query */ - protected $fluent; - - public function setUp(): void + protected function setUp(): void { global $pdo; @@ -23,9 +33,8 @@ public function setUp(): void $this->fluent = new Query($pdo); } - public function testFluentUtil() + public function testFluentUtil(): void { - $value = Utilities::toUpperWords('one'); $value2 = Utilities::toUpperWords(' one '); $value3 = Utilities::toUpperWords('oneTwo'); @@ -41,7 +50,7 @@ public function testFluentUtil() self::assertEquals('ONE TWO THREE', $value6); } - public function testFormatQuery() + public function testFormatQuery(): void { $query = $this->fluent ->from('user') @@ -53,7 +62,7 @@ public function testFormatQuery() self::assertEquals("SELECT user.*\nFROM user\nWHERE id > ?\nORDER BY name", $formattedQuery); } - public function testConvertToNativeType() + public function testConvertToNativeType(): void { $query = $this->fluent ->from('user') @@ -69,7 +78,7 @@ public function testConvertToNativeType() self::assertEquals(['id' => 1], $forceInt); } - public function testConvertSqlWriteValues() + public function testConvertSqlWriteValues(): void { $valueArray = Utilities::convertSqlWriteValues(['string', 1, 2, false, true, null, 'false']); $value1 = Utilities::convertSqlWriteValues(false); @@ -80,7 +89,7 @@ public function testConvertSqlWriteValues() self::assertEquals(1, $value2); } - public function testisCountable() + public function testisCountable(): void { $selectQuery = $this->fluent ->from('user') @@ -92,8 +101,7 @@ public function testisCountable() ->deleteFrom('user') ->where('id', 1); - self::assertEquals(true, Utilities::isCountable($selectQuery)); - self::assertEquals(false, Utilities::isCountable($deleteQuery)); + self::assertTrue(Utilities::isCountable($selectQuery)); + self::assertFalse(Utilities::isCountable($deleteQuery)); } - -} \ No newline at end of file +} diff --git a/tests/_resources/init.php b/tests/_resources/init.php index b639ca2..f303a47 100644 --- a/tests/_resources/init.php +++ b/tests/_resources/init.php @@ -1,11 +1,20 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + if (getenv('TRAVIS')) { - $pdo = new PDO("mysql:dbname=fluentdb;host=localhost;charset=utf8", "root"); -} -else { - $pdo = new PDO("mysql:dbname=fluentdb;host=localhost;charset=utf8", "vagrant", "vagrant"); + $pdo = new PDO('mysql:dbname=fluentdb;host=localhost;charset=utf8', 'root'); +} else { + $pdo = new PDO('mysql:dbname=fluentdb;host=localhost;charset=utf8', 'vagrant', 'vagrant'); } $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); From fed2e255f2ea09189f9b1c0dc3f5352173844eed Mon Sep 17 00:00:00 2001 From: CyberVitexus Date: Wed, 22 Oct 2025 00:39:48 +0200 Subject: [PATCH 4/4] Add Debian packaging for FluentPDO with CI pipelines Introduces initial Debian packaging for FluentPDO, a modernized PHP library requiring PHP 8.1+. Includes metadata, control files, and scripts for building, testing, and distributing the package. Adds Jenkins pipelines for parallel builds and artifact management across multiple distributions, as well as integration with Aptly for publishing. Provides essential documentation, including README files and changelog, and sets up automated CI tests using Salsa CI. Enhances maintainability and distribution readiness for FluentPDO. --- .gitignore | 6 + debian/Jenkinsfile | 133 +++++++++++++++++++++ debian/Jenkinsfile.release | 117 ++++++++++++++++++ debian/README.Debian | 8 ++ debian/README.source | 14 +++ debian/changelog | 9 ++ debian/clean | 1 + debian/composer.json | 50 ++++++++ debian/control | 35 ++++++ debian/copyright | 48 ++++++++ debian/dirs | 2 + debian/files | 2 + debian/gbp.conf | 1 + debian/links | 2 + debian/maintscript.ex | 7 ++ debian/php-vitexsoftware-fluentpdo.install | 5 + debian/postinst.ex | 7 ++ debian/postrm.ex | 7 ++ debian/preinst.ex | 7 ++ debian/prerm.ex | 7 ++ debian/rules | 15 +++ debian/salsa-ci.yml | 25 ++++ debian/source/format | 1 + debian/tests/control | 9 ++ debian/tmp/composer.json | 51 ++++++++ debian/upstream/metadata | 16 +++ debian/watch | 3 + 27 files changed, 588 insertions(+) create mode 100644 debian/Jenkinsfile create mode 100644 debian/Jenkinsfile.release create mode 100644 debian/README.Debian create mode 100644 debian/README.source create mode 100644 debian/changelog create mode 100644 debian/clean create mode 100644 debian/composer.json create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/dirs create mode 100644 debian/files create mode 100644 debian/gbp.conf create mode 100644 debian/links create mode 100644 debian/maintscript.ex create mode 100644 debian/php-vitexsoftware-fluentpdo.install create mode 100644 debian/postinst.ex create mode 100644 debian/postrm.ex create mode 100644 debian/preinst.ex create mode 100644 debian/prerm.ex create mode 100755 debian/rules create mode 100644 debian/salsa-ci.yml create mode 100644 debian/source/format create mode 100644 debian/tests/control create mode 100644 debian/tmp/composer.json create mode 100644 debian/upstream/metadata create mode 100644 debian/watch diff --git a/.gitignore b/.gitignore index f7f8ac3..b228ad7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,8 @@ /.idea/ /vendor/ +/nbproject/ +/debian/debhelper-build-stamp +/debian/php-vitexsoftware-fluentpdo.debhelper.log +/debian/php-vitexsoftware-fluentpdo.substvars +/debian/.debhelper/ +/debian/php-vitexsoftware-fluentpdo/ diff --git a/debian/Jenkinsfile b/debian/Jenkinsfile new file mode 100644 index 0000000..89ef9f8 --- /dev/null +++ b/debian/Jenkinsfile @@ -0,0 +1,133 @@ +#!groovy + +// Aktuální verze Pipeline: https://github.com/VitexSoftware/BuildImages/blob/main/Test/Jenkinsfile-parael + +String[] distributions = [ + 'debian:bookworm', + 'debian:trixie', + 'debian:forky', + 'ubuntu:jammy', + 'ubuntu:noble' +] + +String vendor = 'vitexsoftware' +String imagePrefix = 'multiflexi-' + +properties([ + copyArtifactPermission('*') +]) + +node { + ansiColor('xterm') { + stage('SCM Checkout') { + checkout scm + } + } +} + +def branches = [:] + +distributions.each { distro -> + branches[distro] = { + def (distroFamily, distroCode) = distro.split(':') + def imageName = "${vendor}/${imagePrefix}${distroCode}:latest" + def buildImage + def artifacts = [] + def buildVer + + node { + ansiColor('xterm') { + stage("Checkout ${distro}") { + checkout scm + buildImage = docker.image(imageName) + + sh 'git checkout debian/changelog' + buildVer = sh( + script: "dpkg-parsechangelog --show-field Version", + returnStdout: true + ).trim() + ".${env.BUILD_NUMBER}~${distroCode}" + } + + stage("Build ${distro}") { + buildImage.inside { + sh """ + dch -b -v ${buildVer} "${env.BUILD_TAG}" + sudo apt-get update --allow-releaseinfo-change + sudo chown jenkins:jenkins .. + debuild-pbuilder -i -us -uc -b + mkdir -p \$WORKSPACE/dist/debian/ + rm -rf \$WORKSPACE/dist/debian/* + for deb in \$(awk '{print \$1}' debian/files); do + mv "../\$deb" \$WORKSPACE/dist/debian/ + done + """ + artifacts = sh( + script: "awk '{print \$1}' debian/files", + returnStdout: true + ).trim().split('\n') + } + } + + stage("Test ${distro}") { + buildImage.inside { + def debconf_debug = 0 + sh """ + cd \$WORKSPACE/dist/debian/ + dpkg-scanpackages . /dev/null > Packages + gzip -9c Packages > Packages.gz + cd \$WORKSPACE + echo "deb [trusted=yes] file://///\$WORKSPACE/dist/debian/ ./" | sudo tee /etc/apt/sources.list.d/local.list + sudo apt-get update --allow-releaseinfo-change + """ + artifacts.each { deb_file -> + if (deb_file.endsWith('.deb')) { + def pkgName = deb_file.tokenize('/')[-1].replaceFirst(/_.*/, '') + def distroCodename = sh( + script: "lsb_release -sc", + returnStdout: true + ).trim() + echo "Installing ${pkgName} on ${distroCodename}" + sh """ + sudo DEBIAN_FRONTEND=noninteractive DEBCONF_DEBUG=${debconf_debug} \ + apt-get -y install ${pkgName} \ + || sudo apt-get -y -f install + """ + } + } + } + } + + stage("Archive artifacts ${distro}") { + buildImage.inside { + artifacts.each { deb_file -> + println "Archiving artifact: ${deb_file}" + archiveArtifacts artifacts: "dist/debian/${deb_file}" + } + + sh ''' + set -e + if [ -f debian/files ]; then + while read -r file _; do + [ -n "$file" ] || continue + rm -f "dist/debian/$file" || true + rm -f "../$file" || true + rm -f "$WORKSPACE/$file" || true + done < debian/files + fi + ''' + } + } + + } + } + } +} + + +parallel branches + +node { + stage('Publish to Aptly') { + publishDebToAptly() + } +} diff --git a/debian/Jenkinsfile.release b/debian/Jenkinsfile.release new file mode 100644 index 0000000..450c50f --- /dev/null +++ b/debian/Jenkinsfile.release @@ -0,0 +1,117 @@ +#!groovy + +// Current version of this Pipeline https://raw.githubusercontent.com/VitexSoftware/multiflexi-buildimages/refs/heads/main/Test/multiflexi-halloworld/Jenkinsfile + +String[] distributions = ['debian:bookworm', 'debian:trixie', 'debian:forky', 'ubuntu:jammy', 'ubuntu:noble'] + +String vendor = 'vitexsoftware' +String imagePrefix = 'multiflexi-' +//String distroFamily = '' + +properties([ + copyArtifactPermission('*') +]) +node() { + ansiColor('xterm') { + stage('SCM Checkout') { + checkout scm + } + } +} + +def branches = [:] +distributions.each { distro -> + branches[distro] = { + def distroName = distro + println "Dist:" + distroName + + def dist = distroName.split(':') + def distroCode = dist[1] + def buildImage = '' + def artifacts = [] + def buildVer = '' + + node { + ansiColor('xterm') { + stage('Checkout ' + distroName) { + checkout scm + def imageName = vendor + '/' + imagePrefix + distroCode + ':latest' + buildImage = docker.image(imageName) + sh 'git checkout debian/changelog' + def version = sh ( + script: 'dpkg-parsechangelog --show-field Version', + returnStdout: true + ).trim() + buildVer = version + '.' + env.BUILD_NUMBER + '~' + distroCode + } + stage('Build ' + distroName) { + buildImage.inside { + sh 'dch -b -v ' + buildVer + ' "' + env.BUILD_TAG + '"' + sh 'sudo apt-get update --allow-releaseinfo-change' + sh 'sudo chown jenkins:jenkins ..' + sh 'debuild-pbuilder -i -us -uc -b' + sh 'mkdir -p $WORKSPACE/dist/debian/ ; rm -rf $WORKSPACE/dist/debian/* ; for deb in $(cat debian/files | awk \'{print $1}\'); do mv "../$deb" $WORKSPACE/dist/debian/; done' + artifacts = sh ( + script: "cat debian/files | awk '{print \$1}'", + returnStdout: true + ).trim().split('\n') + } + } + + stage('Test ' + distroName) { + buildImage.inside { + def debconf_debug = 0 //Set to "5" or "developer" to debug debconf + sh 'cd $WORKSPACE/dist/debian/ ; dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz; cd $WORKSPACE' + sh 'echo "deb [trusted=yes] file://///$WORKSPACE/dist/debian/ ./" | sudo tee /etc/apt/sources.list.d/local.list' + sh 'sudo apt-get update --allow-releaseinfo-change' + sh 'echo "INSTALATION"' + artifacts.each { deb_file -> + if (deb_file.endsWith('.deb')) { + sh 'echo -e "${GREEN} installing ' + deb_file + ' on `lsb_release -sc` ${ENDCOLOR} "' + sh 'sudo DEBIAN_FRONTEND=noninteractive DEBCONF_DEBUG=' + debconf_debug + ' apt-get -y install $WORKSPACE/dist/debian/' + deb_file + } + } + } + } + stage('Archive artifacts ' + distroName ) { + // Only run if previous stages (Build and Test) succeeded + buildImage.inside { + // Archive all produced artifacts listed in debian/files + artifacts.each { deb_file -> + println "Archiving artifact: " + deb_file + archiveArtifacts artifacts: 'dist/debian/' + deb_file + } + + // Cleanup: remove any produced files named in debian/files + // Try both the dist location and any potential original locations referenced by debian/files + sh ''' + set -e + if [ -f debian/files ]; then + while read -r file _; do + [ -n "$file" ] || continue + rm -f "dist/debian/$file" || true + rm -f "../$file" || true + rm -f "$WORKSPACE/$file" || true + done < debian/files + fi + ''' + } + } + } + } + } +} +parallel branches + +if (!currentBuild.result || currentBuild.result == 'SUCCESS') { + build job: 'MultiFlexi-publish', + wait: false, + parameters: [ + string(name: 'UPSTREAM_JOB', value: env.JOB_NAME), + string(name: 'UPSTREAM_BUILD', value: env.BUILD_NUMBER), + string(name: 'REMOTE_SSH', value: 'multirepo@repo.multiflexi.eu'), + string(name: 'REMOTE_REPO_DIR', value: '/srv/repo'), + string(name: 'COMPONENT', value: 'main'), + string(name: 'DEB_DIST', value: '') + ] +} diff --git a/debian/README.Debian b/debian/README.Debian new file mode 100644 index 0000000..ec29b5d --- /dev/null +++ b/debian/README.Debian @@ -0,0 +1,8 @@ +php-vitexsoftware-fluentpdo for Debian + +Please edit this to provide information specific to +this php-vitexsoftware-fluentpdo Debian package. + + (Automatically generated by debmake Version 4.5.1) + + -- Vítězslav Dvořák Tue, 21 Oct 2025 23:54:19 +0200 diff --git a/debian/README.source b/debian/README.source new file mode 100644 index 0000000..c6a982c --- /dev/null +++ b/debian/README.source @@ -0,0 +1,14 @@ +php-vitexsoftware-fluentpdo for Debian + +See Debian policy manual section 4.14. + https://www.debian.org/doc/debian-policy/ch-source.html#source-package-handling-debian-readme-source + +If running dpkg-source -x on a source package doesn’t produce the source of the +package, ready for editing, and allow one to make changes and run +dpkg-buildpackage to produce a modified package without taking any additional +steps, creating this file explain how to do all of these is recommended. +Otherwise, remove this file. + + (Automatically generated by debmake Version 4.5.1) + + -- Vítězslav Dvořák Tue, 21 Oct 2025 23:54:19 +0200 diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..1de5b29 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,9 @@ +php-vitexsoftware-fluentpdo (3.0.0-1) unstable; urgency=medium + + * Initial Debian packaging of FluentPDO - PHP 8.1+ Edition + * Modernized fork of FluentPDO with strict typing and union types + * Requires PHP 8.1+ with PDO extension + * Smart join builder with automatic table joins + * Modern type declarations and enhanced features + + -- Vítězslav Dvořák Mon, 21 Oct 2024 22:18:00 +0000 diff --git a/debian/clean b/debian/clean new file mode 100644 index 0000000..4a97dfa --- /dev/null +++ b/debian/clean @@ -0,0 +1 @@ +# You must remove unused comment lines for the released package. diff --git a/debian/composer.json b/debian/composer.json new file mode 100644 index 0000000..1300db0 --- /dev/null +++ b/debian/composer.json @@ -0,0 +1,50 @@ +{ + "name": "deb/fluentpdo", + "description": "FluentPDO - PHP 8.1+ Edition. A modernized fork with strict typing, union types, and enhanced features. Quick and light PHP library for rapid query building with smart join builder.", + "type": "library", + "keywords": [ + "db", + "database", + "dbal", + "pdo", + "fluent", + "query", + "builder", + "mysql", + "oracle", + "mssql", + "php8", + "php81", + "strict-types", + "union-types", + "modern-php" + ], + "homepage": "https://github.com/VitexSoftware/php-vitexsoftware-fluentpdo", + "license": [ + "Apache-2.0", + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "envms", + "homepage": "https://env.ms" + }, + { + "name": "vitex", + "homepage": "https://vitexsoftware.com" + } + ], + "autoload": { + "psr-4": { + "Envms\\FluentPDO\\": "./", + "Envms\\FluentPDO\\QueriesPDO\\": "./Queries/" + } + }, + "require": { + "php": ">=8.1", + "ext-pdo": "*" + }, + "replace": { + "envms/fluentpdo": "^2.2" + } +} diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..7bcef08 --- /dev/null +++ b/debian/control @@ -0,0 +1,35 @@ +Source: php-vitexsoftware-fluentpdo +Section: php +Priority: optional +Maintainer: Vítězslav Dvořák +Build-Depends: + debhelper-compat (= 13), + php-cli, + composer, +Standards-Version: 4.7.0 +Homepage: https://github.com/VitexSoftware/php-vitexsoftware-fluentpdo +Rules-Requires-Root: no +Vcs-Git: https://github.com/VitexSoftware/php-vitexsoftware-fluentpdo.git +Vcs-Browser: https://github.com/VitexSoftware/php-vitexsoftware-fluentpdo + +Package: php-vitexsoftware-fluentpdo +Architecture: all +Multi-Arch: foreign +Depends: + ${misc:Depends}, + php-cli (>= 8.1), + php-pdo, +Suggests: + php-mysql | php-sqlite3 | php-pgsql, +Description: FluentPDO - PHP 8.1+ Edition with modern features + FluentPDO is a modernized PHP SQL query builder library using PDO with a smart + join builder that automatically creates table joins. This version (3.x) requires + PHP 8.1+ and includes modern type declarations, strict typing, and enhanced + features. + . + Key features: + - Smart Join Builder: Automatically creates JOINs based on column references + - Fluent Interface: Method chaining for building queries + - PDO Integration: Built on top of PDO for database portability + - Type Safety: Modern PHP 8.1+ with strict typing throughout + - Union Types: Uses modern PHP union types where appropriate diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..64c6d41 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,48 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: php-vitexsoftware-fluentpdo +Upstream-Contact: Vítězslav Dvořák +Source: https://github.com/VitexSoftware/php-vitexsoftware-fluentpdo + +Files: * +Copyright: 2024 Vítězslav Dvořák + Original FluentPDO by envms +License: Apache-2.0 or GPL-2.0+ + +Files: src/* +Copyright: 2024 Vítězslav Dvořák + Original FluentPDO by envms +License: Apache-2.0 or GPL-2.0+ + +License: Apache-2.0 + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + . + http://www.apache.org/licenses/LICENSE-2.0 + . + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + . + On Debian systems, the complete text of the Apache License 2.0 + can be found in "/usr/share/common-licenses/Apache-2.0". + +License: GPL-2.0+ + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + . + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + . + On Debian systems, the complete text of the GNU General Public License + can be found in "/usr/share/common-licenses/GPL-2". \ No newline at end of file diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 0000000..522e345 --- /dev/null +++ b/debian/dirs @@ -0,0 +1,2 @@ + +# You must remove unused comment lines for the released package. diff --git a/debian/files b/debian/files new file mode 100644 index 0000000..dff631b --- /dev/null +++ b/debian/files @@ -0,0 +1,2 @@ +php-vitexsoftware-fluentpdo_3.0.0-1_all.deb php optional +php-vitexsoftware-fluentpdo_3.0.0-1_amd64.buildinfo php optional diff --git a/debian/gbp.conf b/debian/gbp.conf new file mode 100644 index 0000000..4a97dfa --- /dev/null +++ b/debian/gbp.conf @@ -0,0 +1 @@ +# You must remove unused comment lines for the released package. diff --git a/debian/links b/debian/links new file mode 100644 index 0000000..522e345 --- /dev/null +++ b/debian/links @@ -0,0 +1,2 @@ + +# You must remove unused comment lines for the released package. diff --git a/debian/maintscript.ex b/debian/maintscript.ex new file mode 100644 index 0000000..34601ea --- /dev/null +++ b/debian/maintscript.ex @@ -0,0 +1,7 @@ +# see: dh_installdeb(1), dpkg-maintscript-helper(1) +# For renaming a conffile, you are advised to uncomment and edit the following +#dpkg-maintscript-helper mv_conffile old-conffile new-conffile prior-version package +# For switching a symlink to directory, you are advised to uncomment and edit the following +#dpkg-maintscript-helper symlink_to_dir pathname old-target prior-version package +# For switching a directory to symlink, you are advised to uncomment and edit the following +#dpkg-maintscript-helper dir_to_symlink pathname new-target prior-version package diff --git a/debian/php-vitexsoftware-fluentpdo.install b/debian/php-vitexsoftware-fluentpdo.install new file mode 100644 index 0000000..191a060 --- /dev/null +++ b/debian/php-vitexsoftware-fluentpdo.install @@ -0,0 +1,5 @@ +src/*.php usr/share/php/FluentPDO/ +src/Queries/*.php usr/share/php/FluentPDO/Queries/ +debian/tmp/composer.json usr/share/php/FluentPDO/ +readme.md usr/share/doc/php-vitexsoftware-fluentpdo/ +CHANGELOG.md usr/share/doc/php-vitexsoftware-fluentpdo/ diff --git a/debian/postinst.ex b/debian/postinst.ex new file mode 100644 index 0000000..220990b --- /dev/null +++ b/debian/postinst.ex @@ -0,0 +1,7 @@ +#!/bin/sh +# If no user provided script is activated in this file, you should remove this file. +set -e + +#DEBHELPER# + +exit 0 diff --git a/debian/postrm.ex b/debian/postrm.ex new file mode 100644 index 0000000..220990b --- /dev/null +++ b/debian/postrm.ex @@ -0,0 +1,7 @@ +#!/bin/sh +# If no user provided script is activated in this file, you should remove this file. +set -e + +#DEBHELPER# + +exit 0 diff --git a/debian/preinst.ex b/debian/preinst.ex new file mode 100644 index 0000000..220990b --- /dev/null +++ b/debian/preinst.ex @@ -0,0 +1,7 @@ +#!/bin/sh +# If no user provided script is activated in this file, you should remove this file. +set -e + +#DEBHELPER# + +exit 0 diff --git a/debian/prerm.ex b/debian/prerm.ex new file mode 100644 index 0000000..220990b --- /dev/null +++ b/debian/prerm.ex @@ -0,0 +1,7 @@ +#!/bin/sh +# If no user provided script is activated in this file, you should remove this file. +set -e + +#DEBHELPER# + +exit 0 diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..14168b0 --- /dev/null +++ b/debian/rules @@ -0,0 +1,15 @@ +#!/usr/bin/make -f + +%: + dh $@ + +override_dh_auto_build: + # No build step needed for pure PHP library + +override_dh_auto_test: + # Skip tests during package build to avoid dependency issues + +override_dh_auto_install: + mkdir -p debian/tmp + jq '.version = "'`dpkg-parsechangelog | sed -n 's/^Version: //p'| sed 's/~.*//' `'"' debian/composer.json |sponge debian/tmp/composer.json + dh_auto_install diff --git a/debian/salsa-ci.yml b/debian/salsa-ci.yml new file mode 100644 index 0000000..661e26b --- /dev/null +++ b/debian/salsa-ci.yml @@ -0,0 +1,25 @@ +# For more information on what jobs are run see: +# https://salsa.debian.org/salsa-ci-team/pipeline +# +# To enable the jobs, go to your repository (at salsa.debian.org) +# and click over Settings > CI/CD > Expand (in General pipelines). +# In "CI/CD configuration file" write debian/salsa-ci.yml and click +# in "Save Changes". The CI tests will run after the next commit. +--- +include: + - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/recipes/debian.yml + +# # This commented-out sample disables all default tests, only disable those +# # CI tests that is required to get the CI process to succeed. +# +# variables: +# SALSA_CI_DISABLE_APTLY: 1 +# SALSA_CI_DISABLE_AUTOPKGTEST: 1 +# SALSA_CI_DISABLE_BLHC: 1 +# SALSA_CI_DISABLE_LINTIAN: 1 +# SALSA_CI_DISABLE_PIUPARTS: 1 +# SALSA_CI_DISABLE_REPROTEST: 1 +# SALSA_CI_DISABLE_BUILD_PACKAGE_ALL: 1 +# SALSA_CI_DISABLE_BUILD_PACKAGE_ANY: 1 +# SALSA_CI_DISABLE_BUILD_PACKAGE_I386: 1 +# SALSA_CI_DISABLE_CROSSBUILD_ARM64: 1 diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/debian/tests/control b/debian/tests/control new file mode 100644 index 0000000..f61fd44 --- /dev/null +++ b/debian/tests/control @@ -0,0 +1,9 @@ +# +# DEP-8: autopkgtest - automatic as-installed package testing +# Please check * https://dep-team.pages.debian.net/deps/dep8/ +# * /usr/share/doc/autopkgtest +# +# !!! Please make sure to edit this to a valid test, otherwise build will fails +# +#Tests: testcode.sh +#Restrictions: allow-stderr, breaks-testbed, needs-internet, needs-root diff --git a/debian/tmp/composer.json b/debian/tmp/composer.json new file mode 100644 index 0000000..68b1216 --- /dev/null +++ b/debian/tmp/composer.json @@ -0,0 +1,51 @@ +{ + "name": "deb/fluentpdo", + "description": "FluentPDO - PHP 8.1+ Edition. A modernized fork with strict typing, union types, and enhanced features. Quick and light PHP library for rapid query building with smart join builder.", + "type": "library", + "keywords": [ + "db", + "database", + "dbal", + "pdo", + "fluent", + "query", + "builder", + "mysql", + "oracle", + "mssql", + "php8", + "php81", + "strict-types", + "union-types", + "modern-php" + ], + "homepage": "https://github.com/VitexSoftware/php-vitexsoftware-fluentpdo", + "license": [ + "Apache-2.0", + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "envms", + "homepage": "https://env.ms" + }, + { + "name": "vitex", + "homepage": "https://vitexsoftware.com" + } + ], + "autoload": { + "psr-4": { + "Envms\\FluentPDO\\": "./", + "Envms\\FluentPDO\\QueriesPDO\\": "./Queries/" + } + }, + "require": { + "php": ">=8.1", + "ext-pdo": "*" + }, + "replace": { + "envms/fluentpdo": "^2.2" + }, + "version": "3.0.0-1" +} diff --git a/debian/upstream/metadata b/debian/upstream/metadata new file mode 100644 index 0000000..dc2feb0 --- /dev/null +++ b/debian/upstream/metadata @@ -0,0 +1,16 @@ +# +# DEP-12: Per-package machine-readable metadata about Upstream +# Please check * https://dep-team.pages.debian.net/deps/dep12/ +# * https://wiki.debian.org/UpstreamMetadata +Reference: + Author: + Title: + Journal: + Year: + Volume: + Number: + Pages: + DOI: + PMID: + URL: + eprint: diff --git a/debian/watch b/debian/watch new file mode 100644 index 0000000..6ebdc86 --- /dev/null +++ b/debian/watch @@ -0,0 +1,3 @@ +# You must remove unused comment lines for the released package. +# Compulsory line, this is a version 4 file +version=4