From fb25e9d05ece4d8549d929c6767a9549d2842e6f Mon Sep 17 00:00:00 2001 From: Nikolaos Dimopoulos Date: Wed, 8 Apr 2026 15:57:46 -0500 Subject: [PATCH 1/2] correcting dockerfile --- resources/docker/develop/Dockerfile | 48 ++++++++++++++--------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/resources/docker/develop/Dockerfile b/resources/docker/develop/Dockerfile index 022831d..5a68a02 100644 --- a/resources/docker/develop/Dockerfile +++ b/resources/docker/develop/Dockerfile @@ -15,36 +15,36 @@ COPY --from=ghcr.io/php/pie:bin /pie /usr/bin/pie # Add user and group RUN groupadd -g "${GID}" "${GROUP}" \ - && RUN useradd -l -m -u "${UID}" -g "${GID}" "${USER}" \ - && RUN usermod -s /bin/bash "${USER}" \ - && RUN mkdir /app \ - && RUN chown "${USER}":"${GROUP}" /app \ - && RUN chmod 0770 /app \ + && useradd -l -m -u "${UID}" -g "${GID}" "${USER}" \ + && usermod -s /bin/bash "${USER}" \ + && mkdir /app \ + && chown "${USER}":"${GROUP}" /app \ + && chmod 0770 /app \ # Install needed packages \ - && RUN apt update -y \ - && RUN apt install -yq --no-install-recommends apt-utils git locales nano sudo unzip wget zip \ + && apt update -y \ + && apt install -yq --no-install-recommends apt-utils git locales nano sudo unzip wget zip \ # Configure locales \ - && RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen \ - && RUN dpkg-reconfigure --frontend=noninteractive locales \ - && RUN update-locale LANG=en_US.UTF-8 \ + && sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen \ + && dpkg-reconfigure --frontend=noninteractive locales \ + && update-locale LANG=en_US.UTF-8 \ # Install xdebug for code coverage \ - && RUN apt install -yq --no-install-recommends $PHPIZE_DEPS \ - && RUN pie install xdebug/xdebug \ - && RUN apt-get purge -y --auto-remove $PHPIZE_DEPS \ + && apt install -yq --no-install-recommends $PHPIZE_DEPS \ + && pie install xdebug/xdebug \ + && apt-get purge -y --auto-remove $PHPIZE_DEPS \ # Copy ini file \ - && RUN mv /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini \ + && mv /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini \ # Set correct pid file location and permissions \ - && RUN mkdir -p /run/php \ - && RUN chown "${USER}":"${GROUP}" /run/php \ - && RUN chmod 0770 /run/php \ + && mkdir -p /run/php \ + && chown "${USER}":"${GROUP}" /run/php \ + && chmod 0770 /run/php \ # Cleanup \ - && RUN apt-get autoremove --purge -y \ - && RUN apt-get autoclean -y \ - && RUN apt-get clean -y \ - && RUN rm -rf /tmp/* /var/tmp/* \ - && RUN find /var/cache/apt/archives /var/lib/apt/lists -not -name lock -type f -delete \ - && RUN find /var/cache -type f -delete \ - && RUN find /var/log -type f -delete \ + && apt-get autoremove --purge -y \ + && apt-get autoclean -y \ + && apt-get clean -y \ + && rm -rf /tmp/* /var/tmp/* \ + && find /var/cache/apt/archives /var/lib/apt/lists -not -name lock -type f -delete \ + && find /var/cache -type f -delete \ + && find /var/log -type f -delete \ COPY resources/docker/develop/.bashrc /home/${USER}/.bashrc COPY resources/docker/develop/extra.ini /usr/local/etc/php/conf.d/ From cc93b8fcc9941dc47171fdf87a51c8f668276f71 Mon Sep 17 00:00:00 2001 From: Nikolaos Dimopoulos Date: Wed, 8 Apr 2026 16:17:24 -0500 Subject: [PATCH 2/2] updating composer and tests --- composer.lock | 55 +++++++- phpstan.neon | 4 + phpunit.xml | 5 +- tests/AbstractUnitTestCase.php | 19 +++ tests/unit/Parser/PhqlParserTest.php | 193 +++++++++++++++++++++++++++ 5 files changed, 272 insertions(+), 4 deletions(-) create mode 100644 phpstan.neon create mode 100644 tests/AbstractUnitTestCase.php create mode 100644 tests/unit/Parser/PhqlParserTest.php diff --git a/composer.lock b/composer.lock index c3cba04..6a56b5f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ef93e7890c8849fe9123c4c557e58e45", + "content-hash": "3449d9f432f7ba89aa4794432fe52259", "packages": [], "packages-dev": [ { @@ -243,6 +243,59 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "phpstan/phpstan", + "version": "2.1.46", + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/a193923fc2d6325ef4e741cf3af8c3e8f54dbf25", + "reference": "a193923fc2d6325ef4e741cf3af8c3e8f54dbf25", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "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": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2026-04-01T09:25:14+00:00" + }, { "name": "phpunit/php-code-coverage", "version": "10.1.16", diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..16f0d34 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,4 @@ +parameters: + paths: + - src + level: max diff --git a/phpunit.xml b/phpunit.xml index 9b873f6..c217093 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -3,13 +3,13 @@ xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true" - cacheDirectory=".phpunit.cache" + cacheDirectory="tests/_output/.phpunit.result.cache" beStrictAboutOutputDuringTests="false" failOnRisky="false" failOnWarning="true"> - tests + tests/unit @@ -19,4 +19,3 @@ - diff --git a/tests/AbstractUnitTestCase.php b/tests/AbstractUnitTestCase.php new file mode 100644 index 0000000..f3de57a --- /dev/null +++ b/tests/AbstractUnitTestCase.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +declare(strict_types=1); + +namespace Phalcon\Phql\Tests; + +use PHPUnit\Framework\TestCase; + +abstract class AbstractUnitTestCase extends TestCase +{ +} diff --git a/tests/unit/Parser/PhqlParserTest.php b/tests/unit/Parser/PhqlParserTest.php new file mode 100644 index 0000000..b7b479f --- /dev/null +++ b/tests/unit/Parser/PhqlParserTest.php @@ -0,0 +1,193 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Phalcon\Phql\Tests\Unit\Parser; + +use Phalcon\Phql\Parser\Parser; +use Phalcon\Phql\Tests\AbstractUnitTestCase; + +final class PhqlParserTest extends AbstractUnitTestCase +{ + private Parser $parser; + + protected function setUp(): void + { + $this->parser = new Parser(); + } + + /** + * Test: Select with limit + * Original: tests-old/001.phpt + */ + public function testSelectWithLimit(): void + { + $phql = 'SELECT r.* FROM Robots r LIMIT 10'; + $result = $this->parser->parse($phql); + + $this->assertIsArray($result); + $this->assertEquals(309, $result['type']); + $this->assertArrayHasKey('select', $result); + $this->assertArrayHasKey('limit', $result); + + $this->assertArrayHasKey('columns', $result['select']); + $this->assertIsArray($result['select']['columns']); + $this->assertCount(1, $result['select']['columns']); + + $this->assertEquals(353, $result['select']['columns'][0]['type']); + $this->assertEquals('r', $result['select']['columns'][0]['column']); + + $this->assertArrayHasKey('tables', $result['select']); + $this->assertEquals('Robots', $result['select']['tables']['qualifiedName']['name']); + $this->assertEquals('r', $result['select']['tables']['alias']); + + $this->assertEquals('10', $result['limit']['number']['value']); + } + + /** + * Test: Select with BETWEEN + * Original: tests-old/002.phpt + */ + public function testSelectWithBetween(): void + { + $phql = <<parser->parse($phql); + + $this->assertIsArray($result); + $this->assertEquals(309, $result['type']); + $this->assertArrayHasKey('select', $result); + $this->assertArrayHasKey('where', $result); + + $this->assertEquals('column_name', $result['select']['columns'][0]['column']['name']); + $this->assertEquals('table_name', $result['select']['tables']['qualifiedName']['name']); + $this->assertEquals('column_name', $result['where']['left']['name']); + $this->assertEquals('value1', $result['where']['right']['left']['name']); + $this->assertEquals('value2', $result['where']['right']['right']['name']); + } + + /** + * Test: Using FQCN for source model + * Original: tests-old/003.phpt + */ + public function testUsingFQCNForSourceModel(): void + { + $phql = <<parser->parse($phql); + + $this->assertIsArray($result); + $this->assertEquals(309, $result['type']); + $this->assertArrayHasKey('select', $result); + + $this->assertEquals('AVG', $result['select']['columns'][0]['column']['name']); + $this->assertEquals('inv_total', $result['select']['columns'][0]['column']['arguments'][0]['name']); + $this->assertEquals('average', $result['select']['columns'][0]['alias']); + + $this->assertEquals('[Phalcon\\Tests\\Models\\Invoices]', $result['select']['tables']['qualifiedName']['name']); + } + + /** + * Test: Select with NOT BETWEEN + * Original: tests-old/bug14253.phpt + */ + public function testSelectWithNotBetween(): void + { + $phql = <<parser->parse($phql); + + $this->assertIsArray($result); + $this->assertEquals(309, $result['type']); + $this->assertArrayHasKey('select', $result); + $this->assertArrayHasKey('where', $result); + + $this->assertCount(3, $result['select']['columns']); + $this->assertEquals('Id', $result['select']['columns'][0]['column']['name']); + $this->assertEquals('ProductName', $result['select']['columns'][1]['column']['name']); + $this->assertEquals('UnitPrice', $result['select']['columns'][2]['column']['name']); + $this->assertEquals('Product', $result['select']['tables']['qualifiedName']['name']); + + $this->assertEquals(332, $result['where']['type']); // NOT BETWEEN type + $this->assertEquals('UnitPrice', $result['where']['left']['name']); + $this->assertEquals('5', $result['where']['right']['left']['value']); + $this->assertEquals('100', $result['where']['right']['right']['value']); + } + + /** + * Test: Using spaces in column alias + * Original: tests-old/bug14535.phpt + */ + public function testUsingSpacesInColumnAlias(): void + { + $phql = <<parser->parse($phql); + + $this->assertIsArray($result); + $this->assertEquals(309, $result['type']); + $this->assertArrayHasKey('select', $result); + + $this->assertCount(2, $result['select']['columns']); + $this->assertEquals('People', $result['select']['columns'][0]['column']['domain']); + $this->assertEquals('firstName', $result['select']['columns'][0]['column']['name']); + $this->assertEquals('[First Name]', $result['select']['columns'][0]['alias']); + + $this->assertEquals('People', $result['select']['columns'][1]['column']['domain']); + $this->assertEquals('lastName', $result['select']['columns'][1]['column']['name']); + $this->assertEquals('[Last Name]', $result['select']['columns'][1]['alias']); + + $this->assertEquals('People', $result['select']['tables']['qualifiedName']['name']); + } + + /** + * Test: Delete with WHERE conditions using AND/OR + */ + public function testDeleteWithWhereAndOr(): void + { + $phql = "DELETE FROM co_invoices " + . "WHERE inv_total > :test: " + . "AND inv_cst_id = 2 " + . "OR inv_status_flag = 3 "; + + $parser = new Parser(true); + $result = $parser->parse($phql); + + $this->assertIsArray($result); + $this->assertArrayHasKey('type', $result); + $this->assertArrayHasKey('delete', $result); + + $this->assertArrayHasKey('tables', $result['delete']); + $this->assertEquals('co_invoices', $result['delete']['tables']['qualifiedName']['name']); + + $this->assertArrayHasKey('where', $result); + } +} \ No newline at end of file