Skip to content

Support PHP 7.4 #3184

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jun 3, 2025
Merged

Support PHP 7.4 #3184

merged 7 commits into from
Jun 3, 2025

Conversation

jiru
Copy link
Member

@jiru jiru commented May 17, 2025

This is part of the work needed to get #3166 solved.

This is mostly fixes to get the unit tests pass without any warning/notice. Some minor bugs got solved in the process.

PHP 7.3 → 7.4 does not bring breaking changes, it is more of a preparation for PHP 8, as code that will error in PHP 8 is made to produce a warning in 7.4.

jiru added 6 commits March 24, 2025 15:37
This fixes a very strange bug caused by some new internal behavior of PHP 7.4.

The symptom is that the following tests fail:

- EditLicensesCommandTest::testExecute_severalScenarios()
- EditLanguagesCommandTest::testExecute_changesLanguage()
- EditOwnersCommandTest::testExecute_severalScenarios()

They all fail because the iterator returned by readIdsFromFile() acts strange:
when used in a foreach loop, the loop is exited after the first iteration is
completed. The reason is that the internal state of that iterator is
unintentionally modified by some other code in Aura/Intl.

Whenever __() is called for the first time (which may happen in many places),
CakePHP instantiates a I18n translator. This process calls Aura/Intl
init code, which uses an exception mechanism to alert when a translation
package is not registered. This exception is caught by CakePHP and all is
well, however the mere action of instanciating a new exception triggers,
for some reason, some kind of stringification of the call stack, which calls
->__debugInfo() on our iterator, which in turn calls ->count(), which resets
the iterator.

For reference, here is a call stack at the point the iterator gets modified:

.1  Cake\Collection\Collection->optimizeUnwrap() called at [vendor/cakephp/cakephp/src/Collection/Collection.php:80]
.2  Cake\Collection\Collection->count() called at [vendor/cakephp/cakephp/src/Collection/Collection.php:108]
.3  Cake\Collection\Collection->__debugInfo() called at [vendor/aura/intl/src/PackageLocator.php:96]
.4  Aura\Intl\PackageLocator->get() called at [vendor/aura/intl/src/TranslatorLocator.php:180]
.5  Aura\Intl\TranslatorLocator->get() called at [vendor/cakephp/cakephp/src/I18n/TranslatorRegistry.php:167]
.6  Cake\I18n\TranslatorRegistry->_getTranslator() called at [vendor/cakephp/cakephp/src/I18n/TranslatorRegistry.php:149]
.7  Cake\I18n\TranslatorRegistry->get() called at [vendor/cakephp/cakephp/src/I18n/I18n.php:209]
.8  Cake\I18n\I18n::getTranslator() called at [vendor/cakephp/cakephp/src/I18n/functions.php:35]
.9  __() called at [src/Lib/Licenses.php:61]
.10 App\Lib\Licenses::getSentenceLicenses() called at [src/Model/Table/SentencesTable.php:118]
.11 App\Model\Table\SentencesTable->validationDefault() called at [vendor/cakephp/cakephp/src/Validation/ValidatorAwareTrait.php:177]
.12 Cake\ORM\Table->createValidator() called at [vendor/cakephp/cakephp/src/Validation/ValidatorAwareTrait.php:150]
.13 Cake\ORM\Table->getValidator() called at [vendor/cakephp/cakephp/src/ORM/Marshaller.php:246]
.14 Cake\ORM\Marshaller->_validate() called at [vendor/cakephp/cakephp/src/ORM/Marshaller.php:569]
.15 Cake\ORM\Marshaller->merge() called at [vendor/cakephp/cakephp/src/ORM/Table.php:2730]
.16 Cake\ORM\Table->patchEntity() called at [src/Model/Table/SentencesTable.php:1302]
.17 App\Model\Table\SentencesTable->editSentence() called at [src/Command/EditLanguagesCommand.php:26]
.18 App\Command\EditLanguagesCommand->editLanguage() called at [src/Command/EditLanguagesCommand.php:51]
.19 App\Command\EditLanguagesCommand->execute() called at [vendor/cakephp/cakephp/src/Console/Command.php:187]
.20 Cake\Console\Command->run() called at [vendor/cakephp/cakephp/src/Console/CommandRunner.php:367]
.21 Cake\Console\CommandRunner->runCommand() called at [vendor/cakephp/cakephp/src/Console/CommandRunner.php:165]
.22 Cake\Console\CommandRunner->run() called at [vendor/cakephp/cakephp/src/TestSuite/ConsoleIntegrationTestTrait.php:91]
.23 App\Test\TestCase\Command\EditLanguagesCommandTest->exec() called at [tests/TestCase/Command/EditLanguagesCommandTest.php:58]
.24 App\Test\TestCase\Command\EditLanguagesCommandTest->testExecute_changesLanguage()
.25 ReflectionMethod->invokeArgs() called at [vendor/phpunit/phpunit/src/Framework/TestCase.php:1071]
.26 PHPUnit\Framework\TestCase->runTest() called at [vendor/phpunit/phpunit/src/Framework/TestCase.php:939]
.27 PHPUnit\Framework\TestCase->runBare() called at [vendor/phpunit/phpunit/src/Framework/TestResult.php:698]
.28 PHPUnit\Framework\TestResult->run() called at [vendor/phpunit/phpunit/src/Framework/TestCase.php:894]
.29 PHPUnit\Framework\TestCase->run() called at [vendor/phpunit/phpunit/src/Framework/TestSuite.php:755]
.30 PHPUnit\Framework\TestSuite->run() called at [vendor/phpunit/phpunit/src/Framework/TestSuite.php:755]
.31 PHPUnit\Framework\TestSuite->run() called at [vendor/phpunit/phpunit/src/TextUI/TestRunner.php:545]
.32 PHPUnit\TextUI\TestRunner->doRun() called at [vendor/phpunit/phpunit/src/TextUI/Command.php:195]
.33 PHPUnit\TextUI\Command->run() called at [vendor/phpunit/phpunit/src/TextUI/Command.php:148]
.34 PHPUnit\TextUI\Command::main() called at [vendor/phpunit/phpunit/phpunit:53]
PHP 7.4 more strict checking of array access revealed notices such as:

Notice (8): Trying to access array offset on value of type null in [/home/vagrant/Tatoeba/src/View/Helper/PrivateMessagesHelper.php, line 188]

This turned out to be the cause labels ("from/to <user>" or "draft")
of messages listed in the Trash folder were incorrectly displayed.
PHP 7.4 revealed the following error:

Notice Error: Trying to access array offset on value of type null in [/home/vagrant/Tatoeba/src/Model/Table/SentencesTable.php, line 541]

The return value of getSeveralRandomIds(), when failing, is null, not false.
These only result in errors when the unit tests are executed individually.
@jiru jiru added the maintenance Issue that keeps the code base clean and does not change anything from the users point of view. label May 17, 2025
@jiru jiru merged commit 2607255 into dev Jun 3, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
maintenance Issue that keeps the code base clean and does not change anything from the users point of view.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant