feat: add filters to mainpage
This commit is contained in:
0
module/oc_telegram_shop/upload/oc_telegram_shop/bastion/Exceptions/BotTokenConfiguratorException.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/bastion/Exceptions/BotTokenConfiguratorException.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/bastion/Handlers/SettingsHandler.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/bastion/Handlers/SettingsHandler.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/bastion/Services/BotTokenConfigurator.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/bastion/Services/BotTokenConfigurator.php
Normal file → Executable file
@@ -30,6 +30,8 @@
|
||||
"require-dev": {
|
||||
"roave/security-advisories": "dev-latest",
|
||||
"phpstan/phpstan": "^2.1",
|
||||
"phpunit/phpunit": "^9.6"
|
||||
"phpunit/phpunit": "^9.6",
|
||||
"doctrine/sql-formatter": "^1.3",
|
||||
"mockery/mockery": "^1.6"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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": "7800f8b8834540a6bcbca3336bef7949",
|
||||
"content-hash": "e8ed2d3d0e11eac86a27bb2972b115cd",
|
||||
"packages": [
|
||||
{
|
||||
"name": "graham-campbell/result-type",
|
||||
@@ -1757,6 +1757,195 @@
|
||||
],
|
||||
"time": "2022-12-30T00:15:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/sql-formatter",
|
||||
"version": "1.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/sql-formatter.git",
|
||||
"reference": "3447381095d32a171fe3a58323749f44dbb5ac7d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/3447381095d32a171fe3a58323749f44dbb5ac7d",
|
||||
"reference": "3447381095d32a171fe3a58323749f44dbb5ac7d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^9.0",
|
||||
"phpstan/phpstan": "^1.0",
|
||||
"phpunit/phpunit": "^8.5 || ^9.6",
|
||||
"vimeo/psalm": "^4.11"
|
||||
},
|
||||
"bin": [
|
||||
"bin/sql-formatter"
|
||||
],
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\SqlFormatter\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jeremy Dorn",
|
||||
"email": "jeremy@jeremydorn.com",
|
||||
"homepage": "https://jeremydorn.com/"
|
||||
}
|
||||
],
|
||||
"description": "a PHP SQL highlighting library",
|
||||
"homepage": "https://github.com/doctrine/sql-formatter/",
|
||||
"keywords": [
|
||||
"highlight",
|
||||
"sql"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/doctrine/sql-formatter/issues",
|
||||
"source": "https://github.com/doctrine/sql-formatter/tree/1.3.0"
|
||||
},
|
||||
"time": "2024-05-06T21:49:18+00:00"
|
||||
},
|
||||
{
|
||||
"name": "hamcrest/hamcrest-php",
|
||||
"version": "v2.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/hamcrest/hamcrest-php.git",
|
||||
"reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487",
|
||||
"reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.4|^8.0"
|
||||
},
|
||||
"replace": {
|
||||
"cordoval/hamcrest-php": "*",
|
||||
"davedevelopment/hamcrest-php": "*",
|
||||
"kodova/hamcrest-php": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/php-file-iterator": "^1.4 || ^2.0 || ^3.0",
|
||||
"phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0 || ^9.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"hamcrest"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"description": "This is the PHP port of Hamcrest Matchers",
|
||||
"keywords": [
|
||||
"test"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/hamcrest/hamcrest-php/issues",
|
||||
"source": "https://github.com/hamcrest/hamcrest-php/tree/v2.1.1"
|
||||
},
|
||||
"time": "2025-04-30T06:54:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mockery/mockery",
|
||||
"version": "1.6.12",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mockery/mockery.git",
|
||||
"reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699",
|
||||
"reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"hamcrest/hamcrest-php": "^2.0.1",
|
||||
"lib-pcre": ">=7.0",
|
||||
"php": ">=7.3"
|
||||
},
|
||||
"conflict": {
|
||||
"phpunit/phpunit": "<8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.5 || ^9.6.17",
|
||||
"symplify/easy-coding-standard": "^12.1.14"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"library/helpers.php",
|
||||
"library/Mockery.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Mockery\\": "library/Mockery"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Pádraic Brady",
|
||||
"email": "padraic.brady@gmail.com",
|
||||
"homepage": "https://github.com/padraic",
|
||||
"role": "Author"
|
||||
},
|
||||
{
|
||||
"name": "Dave Marshall",
|
||||
"email": "dave.marshall@atstsolutions.co.uk",
|
||||
"homepage": "https://davedevelopment.co.uk",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Nathanael Esayeas",
|
||||
"email": "nathanael.esayeas@protonmail.com",
|
||||
"homepage": "https://github.com/ghostwriter",
|
||||
"role": "Lead Developer"
|
||||
}
|
||||
],
|
||||
"description": "Mockery is a simple yet flexible PHP mock object framework",
|
||||
"homepage": "https://github.com/mockery/mockery",
|
||||
"keywords": [
|
||||
"BDD",
|
||||
"TDD",
|
||||
"library",
|
||||
"mock",
|
||||
"mock objects",
|
||||
"mockery",
|
||||
"stub",
|
||||
"test",
|
||||
"test double",
|
||||
"testing"
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://docs.mockery.io/",
|
||||
"issues": "https://github.com/mockery/mockery/issues",
|
||||
"rss": "https://github.com/mockery/mockery/releases.atom",
|
||||
"security": "https://github.com/mockery/mockery/security/advisories",
|
||||
"source": "https://github.com/mockery/mockery"
|
||||
},
|
||||
"time": "2024-05-16T03:13:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "myclabs/deep-copy",
|
||||
"version": "1.13.4",
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Openguru\OpenCartFramework\CriteriaBuilder;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Rules\BaseRule;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||
|
||||
class CriteriaBuilder
|
||||
{
|
||||
private RulesRegistry $rulesRegistry;
|
||||
|
||||
public function __construct(RulesRegistry $rulesRegistry)
|
||||
{
|
||||
$this->rulesRegistry = $rulesRegistry;
|
||||
}
|
||||
|
||||
public function apply(Builder $queryBuilder, array $query): void
|
||||
{
|
||||
$operand = $query['operand'] ?? 'AND';
|
||||
$rules = $query['rules'] ?? [];
|
||||
|
||||
foreach ($rules as $ruleId => $rule) {
|
||||
if (! $this->rulesRegistry->has($ruleId)) {
|
||||
throw new InvalidArgumentException('Invalid rule: ' . $ruleId);
|
||||
}
|
||||
|
||||
$className = $this->rulesRegistry->get($ruleId);
|
||||
|
||||
$criteria = [];
|
||||
foreach ($rule['criteria'] as $name => $item) {
|
||||
$criteria[$name] = new Criterion($item['type'], $item['params']);
|
||||
}
|
||||
|
||||
/** @var BaseRule $ruleClass */
|
||||
$ruleClass = new $className($ruleId, $criteria);
|
||||
$ruleClass->apply($queryBuilder, $operand);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Openguru\OpenCartFramework\CriteriaBuilder;
|
||||
|
||||
class Criterion
|
||||
{
|
||||
public string $type;
|
||||
public ?array $params;
|
||||
|
||||
public function __construct(string $type, ?array $params)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->params = $params;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Openguru\OpenCartFramework\CriteriaBuilder\Exceptions;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class CriteriaBuilderException extends RuntimeException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Openguru\OpenCartFramework\CriteriaBuilder;
|
||||
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Rules\BaseRule;
|
||||
use ReflectionClass;
|
||||
use ReflectionProperty;
|
||||
|
||||
class RuleSerializer
|
||||
{
|
||||
public function toArray(BaseRule $rule): array
|
||||
{
|
||||
return $this->extractProperties($rule);
|
||||
}
|
||||
|
||||
public function extractProperties(object $object): array
|
||||
{
|
||||
$reflection = new ReflectionClass($object);
|
||||
$properties = $reflection->getProperties(ReflectionProperty::IS_PUBLIC);
|
||||
|
||||
$data = [];
|
||||
|
||||
foreach ($properties as $property) {
|
||||
$propertyName = $property->getName();
|
||||
$propertyValue = $property->getValue($object);
|
||||
|
||||
if (is_object($propertyValue)) {
|
||||
$data[$propertyName] = $this->extractProperties($propertyValue);
|
||||
} elseif (is_array($propertyValue)) {
|
||||
$data[$propertyName] = $this->extractArray($propertyValue);
|
||||
} else {
|
||||
$data[$propertyName] = $propertyValue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($reflection->hasMethod('metaAttributes')) {
|
||||
$data['__meta'] = $reflection->getMethod('metaAttributes')->invoke($object);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function extractArray(array $array): array
|
||||
{
|
||||
$data = [];
|
||||
foreach ($array as $key => $value) {
|
||||
if (is_object($value)) {
|
||||
$data[$key] = $this->extractProperties($value);
|
||||
} elseif (is_array($value)) {
|
||||
$data[$key] = $this->extractArray($value);
|
||||
} else {
|
||||
$data[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
namespace Openguru\OpenCartFramework\CriteriaBuilder\Rules;
|
||||
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Criterion;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||
|
||||
abstract class BaseRule
|
||||
{
|
||||
public const CRITERIA_OPTION_STRING = 'string';
|
||||
public const CRITERIA_OPTION_NUMBER = 'number';
|
||||
public const CRITERIA_OPTION_BOOLEAN = 'boolean';
|
||||
public const CRITERIA_OPTION_PRODUCT_CATEGORIES = 'product_categories';
|
||||
public const CRITERIA_OPTION_PRODUCT_MANUFACTURER = 'product_manufacturer';
|
||||
public const CRITERIA_OPTION_PRODUCT_ATTRIBUTE = 'product_attribute';
|
||||
public const CRITERIA_OPTION_PRODUCT_MODEL = 'product_model';
|
||||
public const CRITERIA_OPTION_PRODUCT_FOR_MAIN_PAGE = 'product_for_main_page';
|
||||
public const CRITERIA_OPTION_PRODUCT_OPTION = 'product_option';
|
||||
|
||||
public const CRITERIA_OPERATOR_CONTAINS = 'contains';
|
||||
public const CRITERIA_OPERATOR_NOT_CONTAINS = 'not_contains';
|
||||
public const CRITERIA_OPERATOR_GREATER_OR_EQUAL = 'greater_or_equals';
|
||||
public const CRITERIA_OPERATOR_EQUALS = 'equals';
|
||||
|
||||
protected static $numberCompareOperators = [
|
||||
'between' => 'BETWEEN',
|
||||
'equals' => '=',
|
||||
'greater' => '>',
|
||||
'greater_or_equals' => '>=',
|
||||
'less' => '<',
|
||||
'less_or_equals' => '<=',
|
||||
'not_equals' => '<>',
|
||||
];
|
||||
|
||||
protected static $stringCompareOperators = [
|
||||
'contains' => 'LIKE',
|
||||
'not_contains' => 'NOT LIKE',
|
||||
'equals' => '=',
|
||||
'not_equals' => '<>',
|
||||
'is_empty' => 'is_empty',
|
||||
'is_not_empty' => 'is_not_empty',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $id;
|
||||
/**
|
||||
* @var array<Criterion>
|
||||
*/
|
||||
public $criteria;
|
||||
|
||||
public function __construct(
|
||||
string $id,
|
||||
array $criteria
|
||||
) {
|
||||
$this->id = $id;
|
||||
$this->criteria = $criteria;
|
||||
}
|
||||
|
||||
abstract public static function initWithDefaults(): BaseRule;
|
||||
|
||||
public function metaAttributes(): array
|
||||
{
|
||||
return [
|
||||
'group' => 'other',
|
||||
];
|
||||
}
|
||||
|
||||
abstract public function apply(Builder $builder, $operand);
|
||||
|
||||
public function criterionStringCondition(
|
||||
Builder $builder,
|
||||
Criterion $criterion,
|
||||
string $field,
|
||||
string $operand,
|
||||
string $joinAlias = ''
|
||||
): void {
|
||||
$operator = static::$stringCompareOperators[$criterion->params['operator']];
|
||||
$keyword = $criterion->params['keyword'];
|
||||
|
||||
if ($operator === 'is_empty') {
|
||||
if ($joinAlias) {
|
||||
$builder->whereNested(function (Builder $query) use ($field, $joinAlias) {
|
||||
$query->whereRaw("TRIM($field) = '' OR {$joinAlias}.product_id IS NULL");
|
||||
});
|
||||
} else {
|
||||
$builder->whereRaw("TRIM($field) = ''");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($operator === 'is_not_empty') {
|
||||
$builder->whereRaw("TRIM($field) <> ''");
|
||||
return;
|
||||
}
|
||||
|
||||
if ($operator === 'LIKE' || $operator === 'NOT LIKE') {
|
||||
$keyword = "%$keyword%";
|
||||
}
|
||||
|
||||
$builder->where($field, $operator, $keyword, $operand);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Openguru\OpenCartFramework\CriteriaBuilder;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Openguru\OpenCartFramework\Support\Utils;
|
||||
|
||||
class RulesRegistry
|
||||
{
|
||||
private array $items = [];
|
||||
|
||||
public function getRuleId(string $class): string
|
||||
{
|
||||
$segments = explode('\\', $class);
|
||||
$lastSegment = end($segments);
|
||||
if (! $lastSegment) {
|
||||
throw new InvalidArgumentException("Class {$class} does not exist");
|
||||
}
|
||||
|
||||
return 'RULE_' . implode('_', array_map('mb_strtoupper', Utils::ucsplit($lastSegment)));
|
||||
}
|
||||
|
||||
public function has(string $ruleId): bool
|
||||
{
|
||||
return array_key_exists($ruleId, $this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array $ruleId
|
||||
* @param string|null $class
|
||||
* @return void
|
||||
*/
|
||||
public function register($ruleId, string $class = null): void
|
||||
{
|
||||
if (is_array($ruleId)) {
|
||||
foreach ($ruleId as $key => $value) {
|
||||
$this->register($key, $value);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->has($ruleId)) {
|
||||
throw new InvalidArgumentException("Rule '$ruleId' is already registered");
|
||||
}
|
||||
|
||||
$this->items[$ruleId] = $class;
|
||||
}
|
||||
|
||||
public function get(string $ruleId)
|
||||
{
|
||||
if (! $this->has($ruleId)) {
|
||||
throw new InvalidArgumentException("Rule '$ruleId' is not registered");
|
||||
}
|
||||
|
||||
return $this->items[$ruleId];
|
||||
}
|
||||
|
||||
public function getItems(): array
|
||||
{
|
||||
return $this->items;
|
||||
}
|
||||
}
|
||||
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Exceptions/EntityNotFoundException.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Exceptions/EntityNotFoundException.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Logger/LoggerInterface.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Logger/LoggerInterface.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Logger/OpenCartLogAdapter.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Logger/OpenCartLogAdapter.php
Normal file → Executable file
@@ -176,7 +176,13 @@ class Builder
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function whereBetween(string $column, array $values, $boolean = 'and'): Builder
|
||||
/**
|
||||
* @param RawExpression|string $column
|
||||
* @param array $values
|
||||
* @param string $boolean
|
||||
* @return $this
|
||||
*/
|
||||
public function whereBetween($column, array $values, string $boolean = 'and'): Builder
|
||||
{
|
||||
if (count($values) !== 2) {
|
||||
throw new InvalidArgumentException('Invalid number of values provided.');
|
||||
|
||||
@@ -102,9 +102,18 @@ abstract class Grammar
|
||||
return $prefix . implode(' ', $compiledConditions);
|
||||
}
|
||||
|
||||
private function getRawValue($value): string
|
||||
{
|
||||
if ($value instanceof RawExpression) {
|
||||
return $value->getValue();
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function whereBasic($condition): string
|
||||
{
|
||||
return $condition['column'] . ' ' . $condition['operator'] . ' ?';
|
||||
return $this->getRawValue($condition['column']) . ' ' . $condition['operator'] . ' ?';
|
||||
}
|
||||
|
||||
public function whereRaw($condition): string
|
||||
@@ -114,12 +123,12 @@ abstract class Grammar
|
||||
|
||||
public function whereNull($condition): string
|
||||
{
|
||||
return $condition['column'] . ' IS NULL';
|
||||
return $this->getRawValue($condition['column']) . ' IS NULL';
|
||||
}
|
||||
|
||||
public function whereNotNull($condition): string
|
||||
{
|
||||
return $condition['column'] . ' IS NOT NULL';
|
||||
return $this->getRawValue($condition['column']) . ' IS NOT NULL';
|
||||
}
|
||||
|
||||
public function whereNested($condition): string
|
||||
@@ -129,7 +138,7 @@ abstract class Grammar
|
||||
|
||||
public function whereBetween($condition): string
|
||||
{
|
||||
return $condition['column'] . ' BETWEEN ? AND ?';
|
||||
return $this->getRawValue($condition['column']) . ' BETWEEN ? AND ?';
|
||||
}
|
||||
|
||||
public function compileOrders(Builder $builder, array $orders): string
|
||||
@@ -183,6 +192,6 @@ abstract class Grammar
|
||||
$inValues = str_repeat('?, ', count($condition['value']) - 1) . '?';
|
||||
$inOperator = $condition['operator'];
|
||||
|
||||
return $condition['column'] . " $inOperator (" . $inValues . ')';
|
||||
return $this->getRawValue($condition['column']) . " $inOperator (" . $inValues . ')';
|
||||
}
|
||||
}
|
||||
|
||||
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/Commands/ChatIdCommand.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/Commands/ChatIdCommand.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/Commands/TelegramCommand.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/Commands/TelegramCommand.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/Contracts/TelegramCommandInterface.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/Contracts/TelegramCommandInterface.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/Enums/ChatAction.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/Enums/ChatAction.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/Exceptions/TelegramCommandNotFoundException.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/Exceptions/TelegramCommandNotFoundException.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/TelegramBotStateManager.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/TelegramBotStateManager.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/TelegramCommandsRegistry.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/TelegramCommandsRegistry.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Validator/ErrorBag.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Validator/ErrorBag.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Validator/ValidationRuleNotFoundException.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Validator/ValidationRuleNotFoundException.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Validator/ValidationRules/Email.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Validator/ValidationRules/Email.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Validator/ValidationRules/Required.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Validator/ValidationRules/Required.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Validator/ValidationRules/ValidationRuleInterface.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Validator/ValidationRules/ValidationRuleInterface.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Validator/ValidatorInterface.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Validator/ValidatorInterface.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Validator/ValidatorServiceProvider.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Validator/ValidatorServiceProvider.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Validator/translations/ru.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Validator/translations/ru.php
Normal file → Executable file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\FacetSearch\Filters;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Criterion;
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Rules\BaseRule;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\JoinClause;
|
||||
|
||||
class ProductAttribute extends BaseRule
|
||||
{
|
||||
public const NAME = 'RULE_PRODUCT_ATTRIBUTE';
|
||||
|
||||
public static function initWithDefaults(): BaseRule
|
||||
{
|
||||
return new static(static::NAME, [
|
||||
'product_attribute' => new Criterion(static::CRITERIA_OPTION_PRODUCT_ATTRIBUTE, [
|
||||
'attribute_id' => null,
|
||||
'operator' => static::CRITERIA_OPERATOR_CONTAINS,
|
||||
'keyword' => '',
|
||||
'language_id' => config('language_id'),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public function apply(Builder $builder, $operand): void
|
||||
{
|
||||
foreach ($this->criteria as $criterion) {
|
||||
if ($criterion->type === static::CRITERIA_OPTION_PRODUCT_ATTRIBUTE) {
|
||||
$facetHash = md5(serialize($criterion));
|
||||
$joinAlias = 'product_attributes_facet_' . $facetHash;
|
||||
if ($builder->hasJoinAlias($joinAlias)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$operator = static::$stringCompareOperators[$criterion->params['operator']];
|
||||
|
||||
$languageId = $criterion->params['language_id'] ?? null;
|
||||
if (! $languageId) {
|
||||
throw new InvalidArgumentException('language_id is required for the product attribute filter');
|
||||
}
|
||||
|
||||
$builder->leftJoin(
|
||||
db_table('product_attribute') . " AS $joinAlias",
|
||||
function (JoinClause $join) use ($criterion, $joinAlias, $operator, $languageId) {
|
||||
$join->on('products.product_id', '=', "$joinAlias.product_id")
|
||||
->where("$joinAlias.attribute_id", '=', $criterion->params['attribute_id'])
|
||||
->where("$joinAlias.language_id", '=', $languageId);
|
||||
|
||||
if ($operator !== 'is_empty' && $operator !== 'is_not_empty') {
|
||||
$this->criterionStringCondition(
|
||||
$join,
|
||||
$criterion,
|
||||
"$joinAlias.text",
|
||||
'and'
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if ($operator === 'is_empty') {
|
||||
$builder->whereNull("$joinAlias.product_id", $operand);
|
||||
} else {
|
||||
$builder->whereNotNull("$joinAlias.product_id", $operand);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace App\FacetSearch\Filters;
|
||||
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Criterion;
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Rules\BaseRule;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\JoinClause;
|
||||
|
||||
class ProductCategories extends BaseRule
|
||||
{
|
||||
public const NAME = 'RULE_PRODUCT_CATEGORIES';
|
||||
|
||||
public static function initWithDefaults(): BaseRule
|
||||
{
|
||||
return new static(static::NAME, [
|
||||
'product_category_ids' => new Criterion(static::CRITERIA_OPTION_PRODUCT_CATEGORIES, [
|
||||
'operator' => static::CRITERIA_OPERATOR_CONTAINS,
|
||||
'value' => [],
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
public function apply(Builder $builder, $operand): void
|
||||
{
|
||||
/** @var Criterion $criterion */
|
||||
foreach ($this->criteria as $criterion) {
|
||||
if ($criterion->type === static::CRITERIA_OPTION_PRODUCT_CATEGORIES) {
|
||||
$uniqHash = md5(serialize($criterion));
|
||||
$joinAlias = 'product_category_' . $uniqHash;
|
||||
if ($builder->hasJoinAlias($joinAlias)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$operator = $criterion->params['operator'];
|
||||
$categoryIds = $criterion->params['value'];
|
||||
|
||||
$builder->join(
|
||||
db_table('product_to_category') . " AS $joinAlias",
|
||||
function (JoinClause $join) use ($joinAlias, $categoryIds) {
|
||||
$join->on('products.product_id', '=', "$joinAlias.product_id");
|
||||
if ($categoryIds) {
|
||||
$join->whereIn("$joinAlias.category_id", $categoryIds);
|
||||
}
|
||||
},
|
||||
'left'
|
||||
);
|
||||
|
||||
if ($operator === 'contains' && ! $categoryIds) {
|
||||
$builder->whereNull("$joinAlias.product_id", $operand);
|
||||
} elseif ($operator === 'not_contains' && ! $categoryIds) {
|
||||
$builder->whereNotNull("$joinAlias.product_id", $operand);
|
||||
} elseif ($operator === 'contains') {
|
||||
$builder->whereNotNull("$joinAlias.product_id", $operand);
|
||||
} else {
|
||||
$builder->whereNull("$joinAlias.product_id", $operand);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\FacetSearch\Filters;
|
||||
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Criterion;
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Rules\BaseRule;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||
|
||||
class ProductForMainPage extends BaseRule
|
||||
{
|
||||
public const NAME = 'RULE_PRODUCT_FOR_MAIN_PAGE';
|
||||
|
||||
public static function initWithDefaults(): BaseRule
|
||||
{
|
||||
return new static(static::NAME, [
|
||||
'product_for_main_page' => new Criterion(static::CRITERIA_OPTION_PRODUCT_MODEL, [
|
||||
'operator' => static::CRITERIA_OPERATOR_EQUALS,
|
||||
'value' => false,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public function apply(Builder $builder, $operand): void
|
||||
{
|
||||
$criterion = $this->criteria[static::CRITERIA_OPTION_PRODUCT_FOR_MAIN_PAGE] ?? false;
|
||||
if (! $criterion || $criterion->params['value'] === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
$featuredProducts = config('featured_products', []);
|
||||
$mainpageProducts = config('mainpage_products');
|
||||
|
||||
if ($mainpageProducts === 'featured' && $featuredProducts) {
|
||||
$builder->whereIn('products.product_id', $featuredProducts);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($mainpageProducts === 'latest') {
|
||||
$builder->orders = [];
|
||||
$builder->orderBy('products.date_modified', 'DESC');
|
||||
return;
|
||||
}
|
||||
|
||||
if ($mainpageProducts === 'most_viewed') {
|
||||
$builder->orders = [];
|
||||
$builder->orderBy('products.viewed', 'DESC');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App\FacetSearch\Filters;
|
||||
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Criterion;
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Rules\BaseRule;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||
|
||||
class ProductManufacturer extends BaseRule
|
||||
{
|
||||
public const NAME = 'RULE_PRODUCT_MANUFACTURER';
|
||||
|
||||
public static function initWithDefaults(): BaseRule
|
||||
{
|
||||
return new static(static::NAME, [
|
||||
'product_manufacturer_ids' => new Criterion(static::CRITERIA_OPTION_PRODUCT_MANUFACTURER, [
|
||||
'operator' => static::CRITERIA_OPERATOR_CONTAINS,
|
||||
'value' => [],
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
public function apply(Builder $builder, $operand): void
|
||||
{
|
||||
/** @var Criterion $criterion */
|
||||
foreach ($this->criteria as $criterion) {
|
||||
if ($criterion->type === static::CRITERIA_OPTION_PRODUCT_MANUFACTURER) {
|
||||
$operator = $criterion->params['operator'];
|
||||
$ids = $criterion->params['value'];
|
||||
|
||||
if ($ids) {
|
||||
$builder->whereIn(
|
||||
'products.manufacturer_id',
|
||||
$ids,
|
||||
$operator === static::CRITERIA_OPERATOR_NOT_CONTAINS
|
||||
);
|
||||
} else {
|
||||
$builder->where(
|
||||
'products.manufacturer_id',
|
||||
'=',
|
||||
0,
|
||||
$operator === static::CRITERIA_OPERATOR_NOT_CONTAINS
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\FacetSearch\Filters;
|
||||
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Criterion;
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Rules\BaseRule;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||
|
||||
class ProductModel extends BaseRule
|
||||
{
|
||||
public const NAME = 'RULE_PRODUCT_MODEL';
|
||||
|
||||
public static function initWithDefaults(): BaseRule
|
||||
{
|
||||
return new static(static::NAME, [
|
||||
'product_model' => new Criterion(static::CRITERIA_OPTION_PRODUCT_MODEL, [
|
||||
'operator' => static::CRITERIA_OPERATOR_CONTAINS,
|
||||
'value' => [],
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
public function apply(Builder $builder, $operand): void
|
||||
{
|
||||
/** @var Criterion $criterion */
|
||||
foreach ($this->criteria as $criterion) {
|
||||
if ($criterion->type === static::CRITERIA_OPTION_PRODUCT_MODEL) {
|
||||
$operator = $criterion->params['operator'];
|
||||
$models = $criterion->params['value'] ?? [];
|
||||
|
||||
if ($models) {
|
||||
$builder->whereIn(
|
||||
'products.model',
|
||||
$models,
|
||||
$operator === static::CRITERIA_OPERATOR_NOT_CONTAINS
|
||||
);
|
||||
} else {
|
||||
$builder->whereRaw('TRUE = FALSE');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\FacetSearch\Filters;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Criterion;
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Rules\BaseRule;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\JoinClause;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\RawExpression;
|
||||
use Openguru\OpenCartFramework\Support\Arr;
|
||||
use RuntimeException;
|
||||
|
||||
class ProductPrice extends BaseRule
|
||||
{
|
||||
public const NAME = 'RULE_PRODUCT_PRICE';
|
||||
|
||||
public static function initWithDefaults(): BaseRule
|
||||
{
|
||||
return new static(static::NAME, [
|
||||
'product_price' => new Criterion(static::CRITERIA_OPTION_NUMBER, [
|
||||
'operator' => static::CRITERIA_OPERATOR_GREATER_OR_EQUAL,
|
||||
'value' => [
|
||||
'from' => 0,
|
||||
'to' => null,
|
||||
],
|
||||
]),
|
||||
'include_discounts' => new Criterion(static::CRITERIA_OPTION_BOOLEAN, [
|
||||
'value' => true,
|
||||
]),
|
||||
'include_specials' => new Criterion(static::CRITERIA_OPTION_BOOLEAN, [
|
||||
'value' => true,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function apply(Builder $builder, $operand)
|
||||
{
|
||||
$includeSpecials = Arr::get($this->criteria, 'include_specials.value', true);
|
||||
$includeDiscounts = Arr::get($this->criteria, 'include_discounts.value', false);
|
||||
|
||||
/** @var Criterion|null $productPriceCriterion */
|
||||
$productPriceCriterion = $this->criteria['product_price'] ?? null;
|
||||
|
||||
if (! $productPriceCriterion) {
|
||||
throw new RuntimeException('Invalid product price rule format. Criterion is not found. Check filter JSON.');
|
||||
}
|
||||
|
||||
if (! isset(static::$numberCompareOperators[$productPriceCriterion->params['operator']])) {
|
||||
throw new InvalidArgumentException('Invalid operator: ' . $productPriceCriterion->params['operator']);
|
||||
}
|
||||
|
||||
$column = 'products.price';
|
||||
|
||||
if ($includeSpecials) {
|
||||
$specialsFacetHash = md5(serialize($productPriceCriterion) . 'specials');
|
||||
$joinAlias = 'product_specials_' . $specialsFacetHash;
|
||||
if ($builder->hasJoinAlias($joinAlias)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$customerGroupId = config('oc_customer_group_id', 1);
|
||||
|
||||
$builder->join(
|
||||
db_table('product_special') . " AS $joinAlias",
|
||||
function (JoinClause $join) use ($joinAlias, $customerGroupId) {
|
||||
$join
|
||||
->on('products.product_id', '=', "$joinAlias.product_id")
|
||||
->where("$joinAlias.customer_group_id", '=', $customerGroupId)
|
||||
->whereRaw("
|
||||
($joinAlias.date_start = '0000-00-00' OR $joinAlias.date_start < NOW())
|
||||
AND ($joinAlias.date_end = '0000-00-00' OR $joinAlias.date_end > NOW())
|
||||
")
|
||||
->orderBy("$joinAlias.priority", 'ASC')
|
||||
->orderBy('products.price', 'ASC')
|
||||
->limit(1);
|
||||
},
|
||||
'left'
|
||||
);
|
||||
|
||||
$column = new RawExpression("COALESCE($joinAlias.price, products.price)");
|
||||
}
|
||||
|
||||
$numberOperator = static::$numberCompareOperators[$productPriceCriterion->params['operator']];
|
||||
$value = $this->prepareValue(
|
||||
$numberOperator,
|
||||
$productPriceCriterion->params['value']
|
||||
);
|
||||
|
||||
if ($numberOperator === 'BETWEEN') {
|
||||
[$min, $max] = $value; // $min = левая, $max = правая граница
|
||||
|
||||
// если обе границы не указаны — фильтр игнорируем
|
||||
if ($min === null && $max === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// если только правая граница — "меньше или равно"
|
||||
if ($min === null && $max !== null) {
|
||||
$builder->where($column, '<=', $max, $operand);
|
||||
return;
|
||||
}
|
||||
|
||||
// если только левая граница — "больше или равно"
|
||||
if ($min !== null && $max === null) {
|
||||
$builder->where($column, '>=', $min, $operand);
|
||||
return;
|
||||
}
|
||||
|
||||
// левая и правая граница равны
|
||||
if ($min !== null && $max !== null && $min === $max) {
|
||||
$builder->where($column, '=', $min, $operand);
|
||||
return;
|
||||
}
|
||||
|
||||
// если обе границы есть — классический between (min ≤ x ≤ max)
|
||||
if ($min !== null && $max !== null) {
|
||||
$builder->whereBetween($column, [$min, $max], $operand);
|
||||
}
|
||||
} else {
|
||||
$builder->where($column, $numberOperator, $value[0], $operand);
|
||||
}
|
||||
}
|
||||
|
||||
private function prepareValue($numberOperator, array $value): array
|
||||
{
|
||||
$from = null;
|
||||
$to = null;
|
||||
|
||||
if (is_numeric($value['from'])) {
|
||||
$from = (int) $value['from'];
|
||||
}
|
||||
|
||||
if (is_numeric($value['to'])) {
|
||||
$to = (int) $value['to'];
|
||||
}
|
||||
|
||||
return [$from, $to];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\FacetSearch\Filters;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Criterion;
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Exceptions\CriteriaBuilderException;
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Rules\BaseRule;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||
use RuntimeException;
|
||||
|
||||
class ProductQuantity extends BaseRule
|
||||
{
|
||||
public const NAME = 'RULE_PRODUCT_QUANTITY';
|
||||
|
||||
public static function initWithDefaults(): BaseRule
|
||||
{
|
||||
return new static(static::NAME, [
|
||||
'product_quantity' => new Criterion(static::CRITERIA_OPTION_NUMBER, [
|
||||
'operator' => static::CRITERIA_OPERATOR_GREATER_OR_EQUAL,
|
||||
'value' => [0, null],
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public function apply(Builder $builder, $operand): void
|
||||
{
|
||||
/** @var Criterion|null $productQuantityCriterion */
|
||||
$productQuantityCriterion = $this->criteria['product_quantity'] ?? null;
|
||||
|
||||
if (! $productQuantityCriterion) {
|
||||
throw new RuntimeException('Product Quantity rule criterion is not found.');
|
||||
}
|
||||
|
||||
$column = 'products.quantity';
|
||||
|
||||
if (! isset(static::$numberCompareOperators[$productQuantityCriterion->params['operator']])) {
|
||||
throw new InvalidArgumentException('Invalid operator: ' . $productQuantityCriterion->params['operator']);
|
||||
}
|
||||
|
||||
$numberOperator = static::$numberCompareOperators[$productQuantityCriterion->params['operator']];
|
||||
|
||||
$value = $this->prepareValue(
|
||||
$numberOperator,
|
||||
$productQuantityCriterion->params['value'],
|
||||
);
|
||||
|
||||
if ($numberOperator === 'BETWEEN') {
|
||||
$builder->whereBetween($column, $value, $operand);
|
||||
} else {
|
||||
$builder->where($column, $numberOperator, $value[0], $operand);
|
||||
}
|
||||
}
|
||||
|
||||
private function prepareValue($numberOperator, array $value): array
|
||||
{
|
||||
if (
|
||||
(isset($value[0]) && ! is_numeric($value[0]))
|
||||
|| ($numberOperator === 'BETWEEN' && ! $value[1])
|
||||
) {
|
||||
throw new CriteriaBuilderException('Value is required.');
|
||||
}
|
||||
|
||||
return array_map('intval', $value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\FacetSearch\Filters;
|
||||
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Criterion;
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Rules\BaseRule;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||
|
||||
class ProductStatus extends BaseRule
|
||||
{
|
||||
public const NAME = 'RULE_PRODUCT_STATUS';
|
||||
|
||||
public static function initWithDefaults(): BaseRule
|
||||
{
|
||||
return new static(static::NAME, [
|
||||
'product_status' => new Criterion(static::CRITERIA_OPTION_BOOLEAN, [
|
||||
'operator' => static::CRITERIA_OPERATOR_EQUALS,
|
||||
'value' => true,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public function apply(Builder $builder, $operand): void
|
||||
{
|
||||
/** @var Criterion $criterion */
|
||||
foreach ($this->criteria as $criterion) {
|
||||
if ($criterion->type === static::CRITERIA_OPTION_BOOLEAN) {
|
||||
$value = $criterion->params['value'];
|
||||
$builder->where('products.status', '=', $value, $operand);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,24 +29,15 @@ class ProductsHandler
|
||||
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$page = (int) $request->get('page', 1);
|
||||
$perPage = min((int) $request->get('perPage', 6), 15);
|
||||
$categoryId = (int) $request->get('categoryId', 0);
|
||||
$search = trim($request->get('search', ''));
|
||||
$forMainPage = filter_var($request->get('forMainPage', false), FILTER_VALIDATE_BOOLEAN);
|
||||
$featuredProducts = $this->settings->get('featured_products');
|
||||
$mainpageProducts = $this->settings->get('mainpage_products');
|
||||
$page = (int) $request->json('page', 1);
|
||||
$perPage = min((int) $request->json('perPage', 6), 15);
|
||||
$search = trim($request->json('search', ''));
|
||||
$filters = $request->json('filters');
|
||||
$languageId = $this->settings->get('language_id');
|
||||
|
||||
$response = $this->productsService->getProductsResponse(
|
||||
compact(
|
||||
'page',
|
||||
'perPage',
|
||||
'categoryId',
|
||||
'search',
|
||||
'forMainPage',
|
||||
'featuredProducts',
|
||||
'mainpageProducts'
|
||||
)
|
||||
compact('page', 'perPage', 'search', 'filters'),
|
||||
$languageId,
|
||||
);
|
||||
|
||||
return new JsonResponse($response);
|
||||
|
||||
@@ -3,9 +3,18 @@
|
||||
namespace App\ServiceProviders;
|
||||
|
||||
use App\Exceptions\CustomExceptionHandler;
|
||||
use App\FacetSearch\Filters\ProductAttribute;
|
||||
use App\FacetSearch\Filters\ProductCategories;
|
||||
use App\FacetSearch\Filters\ProductForMainPage;
|
||||
use App\FacetSearch\Filters\ProductManufacturer;
|
||||
use App\FacetSearch\Filters\ProductModel;
|
||||
use App\FacetSearch\Filters\ProductPrice;
|
||||
use App\FacetSearch\Filters\ProductQuantity;
|
||||
use App\FacetSearch\Filters\ProductStatus;
|
||||
use App\Telegram\LinkCommand;
|
||||
use Openguru\OpenCartFramework\Container\ServiceProvider;
|
||||
use Openguru\OpenCartFramework\Contracts\ExceptionHandlerInterface;
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\RulesRegistry;
|
||||
use Openguru\OpenCartFramework\Telegram\Commands\ChatIdCommand;
|
||||
use Openguru\OpenCartFramework\Telegram\TelegramCommandsRegistry;
|
||||
|
||||
@@ -18,6 +27,7 @@ class AppServiceProvider extends ServiceProvider
|
||||
});
|
||||
|
||||
$this->registerTelegramCommands();
|
||||
$this->registerFacetFilters();
|
||||
}
|
||||
|
||||
private function registerTelegramCommands(): void
|
||||
@@ -31,4 +41,23 @@ class AppServiceProvider extends ServiceProvider
|
||||
$registry->addCommand('id', ChatIdCommand::class, 'Возвращает ChatID текущего чата.');
|
||||
$registry->addCommand('link', LinkCommand::class, 'Генератор Telegram сообщений с кнопкой');
|
||||
}
|
||||
|
||||
private function registerFacetFilters(): void
|
||||
{
|
||||
$this->container->singleton(RulesRegistry::class, function () {
|
||||
return new RulesRegistry();
|
||||
});
|
||||
|
||||
$registry = $this->container->get(RulesRegistry::class);
|
||||
$registry->register([
|
||||
ProductAttribute::NAME => ProductAttribute::class,
|
||||
ProductCategories::NAME => ProductCategories::class,
|
||||
ProductManufacturer::NAME => ProductManufacturer::class,
|
||||
ProductModel::NAME => ProductModel::class,
|
||||
ProductPrice::NAME => ProductPrice::class,
|
||||
ProductQuantity::NAME => ProductQuantity::class,
|
||||
ProductStatus::NAME => ProductStatus::class,
|
||||
ProductForMainPage::NAME => ProductForMainPage::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ use Cart\Currency;
|
||||
use Cart\Tax;
|
||||
use Exception;
|
||||
use Openguru\OpenCartFramework\Config\Settings;
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\CriteriaBuilder;
|
||||
use Openguru\OpenCartFramework\Exceptions\EntityNotFoundException;
|
||||
use Openguru\OpenCartFramework\ImageTool\ImageToolInterface;
|
||||
use Openguru\OpenCartFramework\Logger\LoggerInterface;
|
||||
@@ -25,6 +26,7 @@ class ProductsService
|
||||
private ImageToolInterface $ocImageTool;
|
||||
private OcRegistryDecorator $oc;
|
||||
private LoggerInterface $logger;
|
||||
private CriteriaBuilder $criteriaBuilder;
|
||||
|
||||
public function __construct(
|
||||
Builder $queryBuilder,
|
||||
@@ -33,7 +35,8 @@ class ProductsService
|
||||
Settings $settings,
|
||||
ImageToolInterface $ocImageTool,
|
||||
OcRegistryDecorator $registry,
|
||||
LoggerInterface $logger
|
||||
LoggerInterface $logger,
|
||||
CriteriaBuilder $criteriaBuilder
|
||||
) {
|
||||
$this->queryBuilder = $queryBuilder;
|
||||
$this->currency = $currency;
|
||||
@@ -42,32 +45,19 @@ class ProductsService
|
||||
$this->ocImageTool = $ocImageTool;
|
||||
$this->oc = $registry;
|
||||
$this->logger = $logger;
|
||||
$this->criteriaBuilder = $criteriaBuilder;
|
||||
}
|
||||
|
||||
public function getProductsResponse(array $params): array
|
||||
public function getProductsResponse(array $params, int $languageId): array
|
||||
{
|
||||
$page = $params['page'];
|
||||
$perPage = $params['perPage'];
|
||||
$categoryId = $params['categoryId'];
|
||||
$search = $params['search'];
|
||||
$forMainPage = $params['forMainPage'];
|
||||
$featuredProducts = $params['featuredProducts'];
|
||||
$mainpageProducts = $params['mainpageProducts'];
|
||||
$status = $params['status'] ?? 1;
|
||||
$languageId = 1;
|
||||
$categoryName = '';
|
||||
$imageWidth = 300;
|
||||
$imageHeight = 300;
|
||||
$maxPages = $params['maxPages'] ?? 10;
|
||||
|
||||
if ($categoryId) {
|
||||
$categoryName = $this->queryBuilder->newQuery()
|
||||
->select(['name'])
|
||||
->from(db_table('category_description'), 'category')
|
||||
->where('language_id', '=', $languageId)
|
||||
->where('category_id', '=', $categoryId)
|
||||
->value('name');
|
||||
}
|
||||
$maxPages = $params['maxPages'] ?? 50;
|
||||
$filters = $params['filters'] ?? [];
|
||||
|
||||
$customerGroupId = (int) $this->oc->config->get('config_customer_group_id');
|
||||
$specialPriceSql = "(SELECT price
|
||||
@@ -97,34 +87,21 @@ class ProductsService
|
||||
->where('product_description.language_id', '=', $languageId);
|
||||
}
|
||||
)
|
||||
->where('products.status', '=', $status)
|
||||
->where('products.status', '=', 1)
|
||||
->whereRaw('products.date_available < NOW()')
|
||||
->when($categoryId !== 0, function (Builder $query) use ($categoryId) {
|
||||
$query->join(
|
||||
db_table('product_to_category') . ' AS product_to_category',
|
||||
function (JoinClause $join) use ($categoryId) {
|
||||
$join->on('product_to_category.product_id', '=', 'products.product_id')
|
||||
->where('product_to_category.category_id', '=', $categoryId);
|
||||
}
|
||||
);
|
||||
})
|
||||
->when(
|
||||
$forMainPage && $mainpageProducts === 'featured' && $featuredProducts,
|
||||
function (Builder $query) use ($featuredProducts) {
|
||||
$query->whereIn('products.product_id', $featuredProducts);
|
||||
}
|
||||
)
|
||||
->when($search, function (Builder $query) use ($search) {
|
||||
$query->where('product_description.name', 'LIKE', '%' . $search . '%');
|
||||
});
|
||||
|
||||
$this->criteriaBuilder->apply($productsQuery, $filters);
|
||||
|
||||
$total = $productsQuery->count();
|
||||
$lastPage = min(PaginationHelper::calculateLastPage($total, $perPage), $maxPages);
|
||||
$hasMore = $page + 1 <= $lastPage;
|
||||
|
||||
$products = $productsQuery
|
||||
->forPage($page, $perPage)
|
||||
->orderBy($mainpageProducts === 'latest' ? 'date_modified' : 'viewed', 'DESC')
|
||||
->orderBy('date_modified', 'DESC')
|
||||
->get();
|
||||
|
||||
$productIds = Arr::pluck($products, 'product_id');
|
||||
@@ -150,6 +127,13 @@ class ProductsService
|
||||
];
|
||||
}
|
||||
|
||||
$debug = [];
|
||||
if (env('APP_DEBUG')) {
|
||||
$debug = [
|
||||
'sql' => $productsQuery->toRawSql(),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'data' => array_map(function ($product) use ($productsImagesMap, $imageWidth, $imageHeight) {
|
||||
$allImages = [];
|
||||
@@ -204,6 +188,7 @@ class ProductsService
|
||||
'meta' => [
|
||||
'currentCategoryName' => $categoryName,
|
||||
'hasMore' => $hasMore,
|
||||
'debug' => $debug,
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
0
module/oc_telegram_shop/upload/oc_telegram_shop/src/Telegram/LinkCommand.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/src/Telegram/LinkCommand.php
Normal file → Executable file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Helpers;
|
||||
|
||||
use Doctrine\SqlFormatter\NullHighlighter;
|
||||
use Doctrine\SqlFormatter\SqlFormatter;
|
||||
use Mockery;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Connections\ConnectionInterface;
|
||||
use PDO;
|
||||
|
||||
trait DatabaseHelpers
|
||||
{
|
||||
public function dropAllTables(): void
|
||||
{
|
||||
/** @var ConnectionInterface $database */
|
||||
$database = $this->app->get(ConnectionInterface::class);
|
||||
$databaseName = getenv('DB_DATABASE');
|
||||
|
||||
$sql = <<<SQL
|
||||
SELECT TABLE_NAME
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema = ?
|
||||
SQL;
|
||||
|
||||
$tables = $database->select($sql, [$databaseName]);
|
||||
$tables = array_column($tables, 'TABLE_NAME');
|
||||
|
||||
foreach ($tables as $table) {
|
||||
$database->dropTable($table);
|
||||
}
|
||||
}
|
||||
|
||||
public function getPdoMock()
|
||||
{
|
||||
$pdoMock = Mockery::spy(PDO::class);
|
||||
$pdoMock->shouldReceive('quote')
|
||||
->andReturnUsing(function ($value) {
|
||||
return "'$value'";
|
||||
});
|
||||
|
||||
return $pdoMock;
|
||||
}
|
||||
|
||||
public function formatSql(string $query): string
|
||||
{
|
||||
return (new SqlFormatter(new NullHighlighter()))->format($query);
|
||||
}
|
||||
|
||||
public function createRandomTable(): string
|
||||
{
|
||||
$randomTableName = 'tbl_random_' . uniqid('', true);
|
||||
$randomTableName = str_replace('.', '_', $randomTableName);
|
||||
|
||||
/** @var ConnectionInterface $database */
|
||||
$database = $this->app->get(ConnectionInterface::class);
|
||||
$database->statement("CREATE TABLE $randomTableName (id INT AUTO_INCREMENT PRIMARY KEY)");
|
||||
|
||||
return $randomTableName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Helpers\ExampleClasses;
|
||||
|
||||
class ExampleDatabaseConnection
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Helpers\ExampleClasses;
|
||||
|
||||
class ExampleEmailWithConfig
|
||||
{
|
||||
public array $config;
|
||||
public int $rateLimit;
|
||||
|
||||
public function __construct(array $config, int $rateLimit) {
|
||||
$this->config = $config;
|
||||
$this->rateLimit = $rateLimit;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Helpers\ExampleClasses;
|
||||
|
||||
class ExamplePersonRepository
|
||||
{
|
||||
/**
|
||||
* @var ExampleDatabaseConnection
|
||||
*/
|
||||
public ExampleDatabaseConnection $connection;
|
||||
|
||||
public function __construct(ExampleDatabaseConnection $connection)
|
||||
{
|
||||
$this->connection = $connection;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Helpers\ExampleClasses;
|
||||
|
||||
class ExamplePersonService
|
||||
{
|
||||
/**
|
||||
* @var ExamplePersonRepository
|
||||
*/
|
||||
public ExamplePersonRepository $personRepository;
|
||||
|
||||
/**
|
||||
* @var ExampleSmsGateway
|
||||
*/
|
||||
public ExampleSmsGateway $smsGateway;
|
||||
|
||||
public function __construct(
|
||||
ExamplePersonRepository $personRepository,
|
||||
ExampleSmsGateway $smsGateway
|
||||
) {
|
||||
$this->personRepository = $personRepository;
|
||||
$this->smsGateway = $smsGateway;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Helpers\ExampleClasses;
|
||||
|
||||
class ExampleSmsGateway
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Helpers\ExampleClasses;
|
||||
|
||||
class ExampleUserService
|
||||
{
|
||||
/**
|
||||
* @var ExampleEmailWithConfig
|
||||
*/
|
||||
private ExampleEmailWithConfig $email;
|
||||
|
||||
public function __construct(ExampleEmailWithConfig $email)
|
||||
{
|
||||
$this->email = $email;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Helpers\ExampleClasses;
|
||||
|
||||
class FilterDTO
|
||||
{
|
||||
public string $field;
|
||||
public string $operator;
|
||||
public $value;
|
||||
|
||||
public function __construct(string $field, string $operator, $value)
|
||||
{
|
||||
$this->field = $field;
|
||||
$this->operator = $operator;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Helpers\ExampleClasses;
|
||||
|
||||
use Openguru\OpenCartFramework\Http\JsonResponse;
|
||||
use stdClass;
|
||||
|
||||
class TestClassWithMethod
|
||||
{
|
||||
public function testMethod(stdClass $dependency): JsonResponse
|
||||
{
|
||||
return new JsonResponse([]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Helpers;
|
||||
|
||||
class OpencartUrl
|
||||
{
|
||||
|
||||
}
|
||||
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Telegram/TelegramServiceTest.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Telegram/TelegramServiceTest.php
Normal file → Executable file
59
module/oc_telegram_shop/upload/oc_telegram_shop/tests/TestCase.php
Normal file → Executable file
59
module/oc_telegram_shop/upload/oc_telegram_shop/tests/TestCase.php
Normal file → Executable file
@@ -2,18 +2,69 @@
|
||||
|
||||
namespace Tests;
|
||||
|
||||
use App\ApplicationFactory;
|
||||
use Mockery;
|
||||
use Openguru\OpenCartFramework\Application;
|
||||
use Openguru\OpenCartFramework\Container\Container;
|
||||
use PHPUnit\Framework\TestCase as BaseTestCase;
|
||||
use Tests\Helpers\DatabaseHelpers;
|
||||
|
||||
class TestCase extends \PHPUnit\Framework\TestCase
|
||||
class TestCase extends BaseTestCase
|
||||
{
|
||||
protected Application $app;
|
||||
use DatabaseHelpers;
|
||||
|
||||
protected $app;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$config = [];
|
||||
$this->app = $this->bootstrapApplication();
|
||||
}
|
||||
|
||||
$this->app = new Application($config);
|
||||
public static function basePath(): string
|
||||
{
|
||||
return __DIR__;
|
||||
}
|
||||
|
||||
public static function fixturesPath(): string
|
||||
{
|
||||
return static::basePath() . DIRECTORY_SEPARATOR . 'fixtures';
|
||||
}
|
||||
|
||||
private function bootstrapApplication(): Application
|
||||
{
|
||||
$app = ApplicationFactory::create([
|
||||
'db' => [
|
||||
'prefix' => 'oc_',
|
||||
],
|
||||
]);
|
||||
|
||||
$app->boot();
|
||||
|
||||
$this->registerDependenciesForTests($app);
|
||||
|
||||
return $app;
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param class-string<T> $factoryClass
|
||||
* @param array $params
|
||||
* @return T
|
||||
*/
|
||||
public function factory(string $factoryClass, array $params = [])
|
||||
{
|
||||
return $this->app->get($factoryClass);
|
||||
}
|
||||
|
||||
private function registerDependenciesForTests(Container $container): void
|
||||
{
|
||||
$url = Mockery::mock('Url');
|
||||
$url->shouldReceive('link')->andReturn('http://localhost');
|
||||
|
||||
$container->bind(\Url::class, function () use ($url) {
|
||||
return $url;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
194
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/ArrTest.php
Executable file
194
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/ArrTest.php
Executable file
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Openguru\OpenCartFramework\Support\Arr;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ArrTest extends TestCase
|
||||
{
|
||||
public function testKeyByField(): void
|
||||
{
|
||||
$data = [
|
||||
['id' => 1, 'name' => 'Item 1'],
|
||||
['id' => 2, 'name' => 'Item 2'],
|
||||
];
|
||||
|
||||
$result = Arr::keyByField($data, 'id');
|
||||
|
||||
$this->assertArrayHasKey(1, $result);
|
||||
$this->assertArrayHasKey(2, $result);
|
||||
$this->assertEquals('Item 1', $result[1]['name']);
|
||||
$this->assertEquals('Item 2', $result[2]['name']);
|
||||
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
Arr::keyByField($data, 'nonexistent');
|
||||
}
|
||||
|
||||
public function testGroupByKey(): void
|
||||
{
|
||||
$data = [
|
||||
['category' => 'A', 'value' => 10],
|
||||
['category' => 'A', 'value' => 20],
|
||||
['category' => 'B', 'value' => 30],
|
||||
];
|
||||
|
||||
$result = Arr::groupByKey($data, 'category', 'value');
|
||||
|
||||
$this->assertEquals(['A' => [10, 20], 'B' => [30]], $result);
|
||||
}
|
||||
|
||||
public function testGet(): void
|
||||
{
|
||||
$data = ['key' => 'value', 'nested' => ['key' => 'nestedValue']];
|
||||
|
||||
$this->assertEquals('value', Arr::get($data, 'key'));
|
||||
$this->assertEquals('nestedValue', Arr::get($data, 'nested.key'));
|
||||
$this->assertNull(Arr::get($data, 'nonexistent'));
|
||||
$this->assertEquals('default', Arr::get($data, 'nonexistent', 'default'));
|
||||
}
|
||||
|
||||
public function testSet(): void
|
||||
{
|
||||
$data = [];
|
||||
|
||||
Arr::set($data, 'key', 'value');
|
||||
$this->assertEquals('value', $data['key']);
|
||||
|
||||
Arr::set($data, 'nested.key', 'nestedValue');
|
||||
$this->assertEquals('nestedValue', $data['nested']['key']);
|
||||
}
|
||||
|
||||
public function testUnset(): void
|
||||
{
|
||||
$data = ['key' => 'value', 'nested' => ['key' => 'nestedValue']];
|
||||
|
||||
Arr::unset($data, 'key');
|
||||
$this->assertArrayNotHasKey('key', $data);
|
||||
|
||||
Arr::unset($data, 'nested.key');
|
||||
$this->assertArrayNotHasKey('key', $data['nested']);
|
||||
}
|
||||
|
||||
public function testFind(): void
|
||||
{
|
||||
$data = [
|
||||
['id' => 1, 'name' => 'Item 1'],
|
||||
['id' => 2, 'name' => 'Item 2'],
|
||||
];
|
||||
|
||||
$result = Arr::find($data, function ($item) {
|
||||
return $item['id'] === 2;
|
||||
});
|
||||
$this->assertEquals(['id' => 2, 'name' => 'Item 2'], $result);
|
||||
|
||||
$result = Arr::find($data, function ($item) {
|
||||
return $item['id'] === 3;
|
||||
});
|
||||
$this->assertNull($result);
|
||||
}
|
||||
|
||||
public function testMergeArraysFlat(): void
|
||||
{
|
||||
$base = ['key1' => 'value1', 'key2' => 'value2'];
|
||||
$override = ['key2' => 'new_value2', 'key3' => 'value3'];
|
||||
|
||||
$expected = [
|
||||
'key1' => 'value1',
|
||||
'key2' => 'new_value2',
|
||||
'key3' => 'value3',
|
||||
];
|
||||
|
||||
$this->assertSame($expected, Arr::mergeArraysRecursively($base, $override));
|
||||
}
|
||||
|
||||
public function testMergeArraysNested(): void
|
||||
{
|
||||
$base = [
|
||||
'key1' => [
|
||||
'subkey1' => 'value1',
|
||||
'subkey2' => 'value2',
|
||||
],
|
||||
'key2' => 'value3',
|
||||
];
|
||||
$override = [
|
||||
'key1' => [
|
||||
'subkey2' => 'new_value2',
|
||||
'subkey3' => 'value4',
|
||||
],
|
||||
'key2' => 'new_value3',
|
||||
];
|
||||
|
||||
$expected = [
|
||||
'key1' => [
|
||||
'subkey1' => 'value1',
|
||||
'subkey2' => 'new_value2',
|
||||
'subkey3' => 'value4',
|
||||
],
|
||||
'key2' => 'new_value3',
|
||||
];
|
||||
|
||||
$this->assertSame($expected, Arr::mergeArraysRecursively($base, $override));
|
||||
}
|
||||
|
||||
public function testMergeArraysOverrideWithNonArray(): void
|
||||
{
|
||||
$base = ['key1' => ['subkey1' => 'value1']];
|
||||
$override = ['key1' => 'new_value1'];
|
||||
|
||||
$expected = ['key1' => 'new_value1'];
|
||||
|
||||
$this->assertSame($expected, Arr::mergeArraysRecursively($base, $override));
|
||||
}
|
||||
|
||||
public function testMergeArraysEmptyBase(): void
|
||||
{
|
||||
$base = [];
|
||||
$override = ['key1' => 'value1'];
|
||||
|
||||
$expected = ['key1' => 'value1'];
|
||||
|
||||
$this->assertSame($expected, Arr::mergeArraysRecursively($base, $override));
|
||||
}
|
||||
|
||||
public function testMergeArraysEmptyOverride(): void
|
||||
{
|
||||
$base = ['key1' => 'value1'];
|
||||
$override = [];
|
||||
|
||||
$expected = ['key1' => 'value1'];
|
||||
|
||||
$this->assertSame($expected, Arr::mergeArraysRecursively($base, $override));
|
||||
}
|
||||
|
||||
public function testMergeArraysWithDeepNesting(): void
|
||||
{
|
||||
$base = [
|
||||
'key1' => [
|
||||
'subkey1' => [
|
||||
'subsubkey1' => 'value1',
|
||||
],
|
||||
],
|
||||
];
|
||||
$override = [
|
||||
'key1' => [
|
||||
'subkey1' => [
|
||||
'subsubkey1' => 'new_value1',
|
||||
'subsubkey2' => 'value2',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$expected = [
|
||||
'key1' => [
|
||||
'subkey1' => [
|
||||
'subsubkey1' => 'new_value1',
|
||||
'subsubkey2' => 'value2',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertSame($expected, Arr::mergeArraysRecursively($base, $override));
|
||||
}
|
||||
}
|
||||
347
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/BuilderTest.php
Executable file
347
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/BuilderTest.php
Executable file
@@ -0,0 +1,347 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Connections\MySqlConnection;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Grammars\MySqlGrammar;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\JoinClause;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\RawExpression;
|
||||
use Tests\TestCase;
|
||||
|
||||
class BuilderTest extends TestCase
|
||||
{
|
||||
protected $builder;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$connection = new MySqlConnection($this->getPdoMock());
|
||||
|
||||
$this->builder = new Builder($connection, new MySqlGrammar());
|
||||
}
|
||||
|
||||
public function testSelect(): void
|
||||
{
|
||||
$sql = $this->builder
|
||||
->select([
|
||||
'foo',
|
||||
'boo' => 'bar',
|
||||
])
|
||||
->from('some_table')
|
||||
->toSql();
|
||||
|
||||
$this->assertEquals(/** @lang text */ 'SELECT foo, boo AS bar FROM some_table', $sql);
|
||||
}
|
||||
|
||||
public function testSelectRawExpression(): void
|
||||
{
|
||||
$sql = $this->builder
|
||||
->select([
|
||||
'foo',
|
||||
new RawExpression('IF (foobar IS NULL, TRUE, FALSE) AS alias'),
|
||||
])
|
||||
->from('some_table')
|
||||
->toSql();
|
||||
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT foo, IF (foobar IS NULL, TRUE, FALSE) AS alias FROM some_table',
|
||||
$sql
|
||||
);
|
||||
}
|
||||
|
||||
public function testFrom(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM some_table AS alias',
|
||||
$this->builder
|
||||
->from('some_table', 'alias')
|
||||
->toSql()
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM some_table',
|
||||
$this->builder
|
||||
->from('some_table')
|
||||
->toSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testWhereNotNull(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM some_table WHERE foo IS NOT NULL',
|
||||
$this->builder
|
||||
->from('some_table')
|
||||
->whereNotNull('foo')
|
||||
->toSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testWhereNull(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM some_table WHERE foo IS NULL',
|
||||
$this->builder
|
||||
->from('some_table')
|
||||
->whereNull('foo')
|
||||
->toSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testWhere(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM some_table WHERE foo = ?',
|
||||
$this->builder
|
||||
->from('some_table')
|
||||
->where('foo', '=', 'bar')
|
||||
->toSql()
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM some_table WHERE foo LIKE ?',
|
||||
$this->builder
|
||||
->newQuery()
|
||||
->from('some_table')
|
||||
->where('foo', 'LIKE', '%bar%')
|
||||
->toSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testOrWhere(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM t1 WHERE foo = ? OR bar = ?',
|
||||
$this->builder
|
||||
->from('t1')
|
||||
->where('foo', '=', 'bar')
|
||||
->orWhere('bar', '=', 'boo')
|
||||
->toSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testLimit(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM some_table LIMIT 10',
|
||||
$this->builder
|
||||
->from('some_table')
|
||||
->limit(10)
|
||||
->toSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testOffset(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM some_table OFFSET 10',
|
||||
$this->builder
|
||||
->from('some_table')
|
||||
->offset(10)
|
||||
->toSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testForPage(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM some_table LIMIT 20 OFFSET 20',
|
||||
$this->builder
|
||||
->from('some_table')
|
||||
->forPage(2, 20)
|
||||
->toSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testOrderBy(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM some_table ORDER BY foo ASC, bar DESC',
|
||||
$this->builder
|
||||
->from('some_table')
|
||||
->orderBy('foo')
|
||||
->orderBy('bar', 'DESC')
|
||||
->toSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testJoin(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM t1 INNER JOIN t2 ON t1.key = t2.key AND t1.foo IS NOT NULL OR t2.bar <> ?',
|
||||
$this->builder
|
||||
->from('t1')
|
||||
->join('t2', function (JoinClause $join) {
|
||||
$join->on('t1.key', '=', 't2.key')
|
||||
->whereNotNull('t1.foo')
|
||||
->where('t2.bar', '<>', 'value', 'or');
|
||||
})
|
||||
->toSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testLeftJoin(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM t1 LEFT JOIN t2 ON t1.key = t2.key',
|
||||
$this->builder
|
||||
->from('t1')
|
||||
->join('t2', function (JoinClause $join) {
|
||||
$join->on('t1.key', '=', 't2.key');
|
||||
}, 'left')
|
||||
->toSql()
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM t1 LEFT JOIN t2 ON t1.key = t2.key',
|
||||
$this->builder->newQuery()
|
||||
->from('t1')
|
||||
->leftJoin('t2', function (JoinClause $join) {
|
||||
$join->on('t1.key', '=', 't2.key');
|
||||
})
|
||||
->toSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testWhereNested(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM t1 WHERE (t1.foo = ? AND t2.bar = ?) OR (t1.foo = ? AND t2.bar = ?)',
|
||||
$this->builder
|
||||
->from('t1')
|
||||
->whereNested(function (Builder $builder) {
|
||||
$builder->where('t1.foo', '=', 'bar')
|
||||
->where('t2.bar', '=', 'foo');
|
||||
})
|
||||
->whereNested(function (Builder $builder) {
|
||||
$builder->where('t1.foo', '=', 'foo')
|
||||
->where('t2.bar', '=', 'bar');
|
||||
}, 'or')
|
||||
->toSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testWhereNestedEmpty(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM t1 WHERE ()',
|
||||
$this->builder
|
||||
->from('t1')
|
||||
->whereNested(function (Builder $builder) {
|
||||
})
|
||||
->toSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testWhereBetween(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM some_table WHERE foo BETWEEN 100 AND 200',
|
||||
$this->builder
|
||||
->from('some_table')
|
||||
->whereBetween('foo', [100, 200])
|
||||
->toRawSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testWhereBetweenWithOperand(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM some_table WHERE foo BETWEEN 100 AND 200 OR bar BETWEEN 10 AND 20',
|
||||
$this->builder
|
||||
->from('some_table')
|
||||
->whereBetween('foo', [100, 200])
|
||||
->whereBetween('bar', [10, 20], 'or')
|
||||
->toRawSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testWhereIn(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM some_table WHERE foo IN (1, 2, 3)',
|
||||
$this->builder
|
||||
->from('some_table')
|
||||
->whereIn('foo', [1, 2, 3])
|
||||
->toRawSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testWhereNotIn(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM some_table WHERE foo NOT IN (1, 2, 3)',
|
||||
$this->builder
|
||||
->from('some_table')
|
||||
->whereIn('foo', [1, 2, 3], true)
|
||||
->toRawSql()
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM some_table WHERE foo NOT IN (1, 2, 3)',
|
||||
$this->builder
|
||||
->newQuery()
|
||||
->from('some_table')
|
||||
->whereNotIn('foo', [1, 2, 3])
|
||||
->toRawSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testDistinct(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT DISTINCT id FROM some_table',
|
||||
$this->builder
|
||||
->select(['id'])
|
||||
->distinct()
|
||||
->from('some_table')
|
||||
->toRawSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testWhenConditionTrue(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ "SELECT id FROM some_table WHERE foo = 'bar'",
|
||||
$this->builder
|
||||
->select(['id'])
|
||||
->from('some_table')
|
||||
->when(true, function (Builder $query) {
|
||||
$query->where('foo', '=', 'bar');
|
||||
})
|
||||
->toRawSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testWhenConditionFalseWithDefault(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ "SELECT id FROM some_table WHERE foo <> 'bar'",
|
||||
$this->builder
|
||||
->select(['id'])
|
||||
->from('some_table')
|
||||
->when(false, function (Builder $query) {
|
||||
$query->where('foo', '=', 'bar');
|
||||
}, function (Builder $query) {
|
||||
$query->where('foo', '<>', 'bar');
|
||||
})
|
||||
->toRawSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testWhenConditionFalseWithoutDefault(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ "SELECT id FROM some_table",
|
||||
$this->builder
|
||||
->select(['id'])
|
||||
->from('some_table')
|
||||
->when(false, function (Builder $query) {
|
||||
$query->where('foo', '=', 'bar');
|
||||
})
|
||||
->toRawSql()
|
||||
);
|
||||
}
|
||||
}
|
||||
145
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/ContainerTest.php
Executable file
145
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/ContainerTest.php
Executable file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use Openguru\OpenCartFramework\Container\Container;
|
||||
use Openguru\OpenCartFramework\Exceptions\ContainerDependencyResolutionException;
|
||||
use Openguru\OpenCartFramework\Http\JsonResponse;
|
||||
use stdClass;
|
||||
use Tests\Helpers\ExampleClasses\TestClassWithMethod;
|
||||
use Tests\TestCase;
|
||||
use Tests\Helpers\ExampleClasses\ExampleDatabaseConnection;
|
||||
use Tests\Helpers\ExampleClasses\ExampleSmsGateway;
|
||||
use Tests\Helpers\ExampleClasses\ExamplePersonRepository;
|
||||
use Tests\Helpers\ExampleClasses\ExamplePersonService;
|
||||
use Tests\Helpers\ExampleClasses\ExampleEmailWithConfig;
|
||||
|
||||
class ContainerTest extends TestCase
|
||||
{
|
||||
private $config = [
|
||||
'key' => 'value',
|
||||
];
|
||||
|
||||
private $container;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->container = new Container($this->config);
|
||||
}
|
||||
|
||||
public function testGetConfigValue()
|
||||
{
|
||||
$this->assertEquals('value', $this->container->getConfigValue('key'));
|
||||
|
||||
$this->assertIsArray($this->container->getConfigValue());
|
||||
}
|
||||
|
||||
public function testBind(): void
|
||||
{
|
||||
$this->container->bind('abstract', function () {});
|
||||
|
||||
$this->assertTrue($this->container->has('abstract'));
|
||||
}
|
||||
|
||||
public function testResolve(): void
|
||||
{
|
||||
$this->container->bind(ExampleDatabaseConnection::class, function () {
|
||||
return new ExampleDatabaseConnection();
|
||||
});
|
||||
|
||||
$concrete1 = $this->container->get(ExampleDatabaseConnection::class);
|
||||
$concrete2 = $this->container->get(ExampleDatabaseConnection::class);
|
||||
|
||||
$this->assertInstanceOf(ExampleDatabaseConnection::class, $concrete1);
|
||||
$this->assertInstanceOf(ExampleDatabaseConnection::class, $concrete2);
|
||||
$this->assertNotSame($concrete1, $concrete2);
|
||||
}
|
||||
|
||||
public function testSingleton(): void
|
||||
{
|
||||
$this->container->singleton(ExampleDatabaseConnection::class, function () {
|
||||
return new ExampleDatabaseConnection();
|
||||
});
|
||||
|
||||
$concrete1 = $this->container->get(ExampleDatabaseConnection::class);
|
||||
$concrete2 = $this->container->get(ExampleDatabaseConnection::class);
|
||||
|
||||
$this->assertInstanceOf(ExampleDatabaseConnection::class, $concrete1);
|
||||
$this->assertInstanceOf(ExampleDatabaseConnection::class, $concrete2);
|
||||
$this->assertSame($concrete1, $concrete2);
|
||||
}
|
||||
|
||||
public function testDeepResolve(): void
|
||||
{
|
||||
$container = new Container([]);
|
||||
|
||||
$container->bind(ExampleSmsGateway::class, function () { return new ExampleSmsGateway(); });
|
||||
$container->bind(ExampleDatabaseConnection::class, function () { return new ExampleDatabaseConnection(); });
|
||||
$container->bind(ExamplePersonRepository::class, function (Container $container) {
|
||||
return new ExamplePersonRepository(
|
||||
$container->get(ExampleDatabaseConnection::class),
|
||||
);
|
||||
});
|
||||
$container->bind(ExamplePersonService::class, function (Container $container) {
|
||||
return new ExamplePersonService(
|
||||
$container->get(ExamplePersonRepository::class),
|
||||
$container->get(ExampleSmsGateway::class),
|
||||
);
|
||||
});
|
||||
|
||||
$personService = $container->get(ExamplePersonService::class);
|
||||
|
||||
$this->assertInstanceOf(ExamplePersonService::class, $personService);
|
||||
$this->assertInstanceOf(ExamplePersonRepository::class, $personService->personRepository);
|
||||
$this->assertInstanceOf(ExampleSmsGateway::class, $personService->smsGateway);
|
||||
}
|
||||
|
||||
public function testAutoResolve(): void
|
||||
{
|
||||
$personService = $this->container->get(ExamplePersonService::class);
|
||||
|
||||
$this->assertInstanceOf(ExamplePersonService::class, $personService);
|
||||
$this->assertInstanceOf(ExamplePersonRepository::class, $personService->personRepository);
|
||||
$this->assertInstanceOf(ExampleSmsGateway::class, $personService->smsGateway);
|
||||
}
|
||||
|
||||
public function testAutoResolveFailed(): void
|
||||
{
|
||||
$this->expectException(ContainerDependencyResolutionException::class);
|
||||
|
||||
$response = $this->container->get(ExampleEmailWithConfig::class);
|
||||
|
||||
$this->assertInstanceOf(ExampleEmailWithConfig::class, $response);
|
||||
}
|
||||
|
||||
public function testAutoResolveWithCustomParams(): void
|
||||
{
|
||||
$container = new Container([]);
|
||||
|
||||
$container->bind(
|
||||
ExampleEmailWithConfig::class,
|
||||
function () {
|
||||
return new ExampleEmailWithConfig(['foo' => 'bar'], 10);
|
||||
}
|
||||
);
|
||||
|
||||
/** @var ExampleEmailWithConfig $emailWithConfig */
|
||||
$emailWithConfig = $container->get(ExampleEmailWithConfig::class);
|
||||
|
||||
$this->assertInstanceOf(ExampleEmailWithConfig::class, $emailWithConfig);
|
||||
$this->assertEquals(['foo' => 'bar'], $emailWithConfig->config);
|
||||
$this->assertEquals(10, $emailWithConfig->rateLimit);
|
||||
}
|
||||
|
||||
public function testCallMethodWithDependencies(): void
|
||||
{
|
||||
$this->container->bind(stdClass::class, function () {
|
||||
return new stdClass();
|
||||
});
|
||||
|
||||
$response = $this->container->call(TestClassWithMethod::class, 'testMethod');
|
||||
$this->assertInstanceOf(JsonResponse::class, $response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use App\FacetSearch\Filters\ProductAttribute;
|
||||
use App\FacetSearch\Filters\ProductCategories;
|
||||
use App\FacetSearch\Filters\ProductForMainPage;
|
||||
use App\FacetSearch\Filters\ProductManufacturer;
|
||||
use App\FacetSearch\Filters\ProductModel;
|
||||
use App\FacetSearch\Filters\ProductPrice;
|
||||
use App\FacetSearch\Filters\ProductQuantity;
|
||||
use App\FacetSearch\Filters\ProductStatus;
|
||||
use DirectoryIterator;
|
||||
use InvalidArgumentException;
|
||||
use JsonException;
|
||||
use Mockery;
|
||||
use Openguru\OpenCartFramework\Application;
|
||||
use Openguru\OpenCartFramework\Config\Settings;
|
||||
use Openguru\OpenCartFramework\Container\Container;
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\CriteriaBuilder;
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\RulesRegistry;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Connections\ConnectionInterface;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Connections\MySqlConnection;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Grammars\MySqlGrammar;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\JoinClause;
|
||||
use Openguru\OpenCartFramework\Support\Arr;
|
||||
use Tests\TestCase;
|
||||
|
||||
class CriteriaBuilderTest extends TestCase
|
||||
{
|
||||
protected function tearDown(): void
|
||||
{
|
||||
parent::tearDown();
|
||||
|
||||
Mockery::close();
|
||||
}
|
||||
|
||||
/** @dataProvider CriteriaBuilderFixturesDataProvider */
|
||||
public function testRule($folder): void
|
||||
{
|
||||
$this->expectNotToPerformAssertions();
|
||||
|
||||
$input = $this->jsonFileToArray($folder . DIRECTORY_SEPARATOR . 'input.json');
|
||||
$outputFilename = $folder . '/output.sql';
|
||||
$settingsFilename = $folder . DIRECTORY_SEPARATOR . 'settings_override.json';
|
||||
|
||||
$settingsOverride = [];
|
||||
if (file_exists($settingsFilename)) {
|
||||
$settingsOverride = $this->jsonFileToArray($settingsFilename);
|
||||
}
|
||||
|
||||
$baseSettings = [
|
||||
'db' => [
|
||||
'prefix' => 'oc_',
|
||||
],
|
||||
];
|
||||
$config = Arr::mergeArraysRecursively($baseSettings, $settingsOverride);
|
||||
$application = new Application($config);
|
||||
$mysqlConnection = new MySqlConnection($this->getPdoMock());
|
||||
$application->boot();
|
||||
|
||||
$e = config('mainpage_products');
|
||||
|
||||
$application->bind(ConnectionInterface::class, function () use ($mysqlConnection) {
|
||||
return $mysqlConnection;
|
||||
});
|
||||
|
||||
$application->bind(Builder::class, function (Container $container) {
|
||||
return new Builder(
|
||||
$container->get(ConnectionInterface::class),
|
||||
$container->get(MySqlGrammar::class),
|
||||
);
|
||||
});
|
||||
|
||||
$application->singleton(RulesRegistry::class, function () {
|
||||
return new RulesRegistry();
|
||||
});
|
||||
|
||||
$application->singleton(Settings::class, function () {
|
||||
return new Settings();
|
||||
});
|
||||
|
||||
/** @var RulesRegistry $rulesRegistry */
|
||||
$rulesRegistry = $application->get(RulesRegistry::class);
|
||||
$rulesRegistry->register(ProductPrice::NAME, ProductPrice::class);
|
||||
$rulesRegistry->register(ProductStatus::NAME, ProductStatus::class);
|
||||
$rulesRegistry->register(ProductModel::NAME, ProductModel::class);
|
||||
$rulesRegistry->register(ProductCategories::NAME, ProductCategories::class);
|
||||
$rulesRegistry->register(ProductManufacturer::NAME, ProductManufacturer::class);
|
||||
$rulesRegistry->register(ProductQuantity::NAME, ProductQuantity::class);
|
||||
$rulesRegistry->register(ProductAttribute::NAME, ProductAttribute::class);
|
||||
$rulesRegistry->register(ProductForMainPage::NAME, ProductForMainPage::class);
|
||||
|
||||
$this->builder = $application->get(Builder::class);
|
||||
$this->criteriaBuilder = $application->get(CriteriaBuilder::class);
|
||||
$this->baseQuery = $this->builder->newQuery()
|
||||
->select([
|
||||
'products.product_id' => 'product_id',
|
||||
'products.image' => 'image',
|
||||
'product_description.name' => 'name',
|
||||
'products.model' => 'model',
|
||||
'products.price' => 'price',
|
||||
'products.quantity' => 'quantity',
|
||||
'products.status' => 'status',
|
||||
'products.noindex' => 'noindex'
|
||||
])
|
||||
->from('oc_product', 'products')
|
||||
->join(
|
||||
'oc_product_description AS product_description',
|
||||
function (JoinClause $join) {
|
||||
return $join->on('products.product_id', '=', 'product_description.product_id')
|
||||
->where('product_description.language_id', '=', 1);
|
||||
}
|
||||
);
|
||||
|
||||
$this->criteriaBuilder->apply($this->baseQuery, $input);
|
||||
|
||||
$actual = $this->formatSql($this->baseQuery->toRawSql());
|
||||
|
||||
if (! file_exists($outputFilename)) {
|
||||
file_put_contents($outputFilename, $actual);
|
||||
$this->markTestSkipped('Regenerated fixtures. Rerun the test.');
|
||||
}
|
||||
|
||||
if (file_get_contents($outputFilename) !== $actual) {
|
||||
file_put_contents($outputFilename, $actual);
|
||||
$this->markTestIncomplete('SQL changed. Please check it and regenerate fixtures.');
|
||||
}
|
||||
}
|
||||
|
||||
public static function CriteriaBuilderFixturesDataProvider(): array
|
||||
{
|
||||
return self::findDirectories(static::fixturesPath() . '/criteria_builder');
|
||||
}
|
||||
|
||||
private static function findDirectories($rootFolder, $currentLevel = 1, $maxLevel = 2): array
|
||||
{
|
||||
$directories = [];
|
||||
|
||||
if ($currentLevel > $maxLevel) {
|
||||
return $directories;
|
||||
}
|
||||
|
||||
$iterator = new DirectoryIterator($rootFolder);
|
||||
foreach ($iterator as $fileInfo) {
|
||||
if ($fileInfo->isDot()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($fileInfo->isDir()) {
|
||||
if ($currentLevel === 2) {
|
||||
$parts = array_reverse(explode('/', $fileInfo->getPathname()));
|
||||
$key = $parts[1] . '_' . $parts[0];
|
||||
$directories[$key] = [
|
||||
$fileInfo->getPathname(),
|
||||
];
|
||||
}
|
||||
|
||||
$subDirectories = self::findDirectories($fileInfo->getPathname(), $currentLevel + 1, $maxLevel);
|
||||
$directories = array_merge($directories, $subDirectories);
|
||||
}
|
||||
}
|
||||
|
||||
return $directories;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws JsonException
|
||||
*/
|
||||
private function jsonFileToArray(string $path): array
|
||||
{
|
||||
if (! file_exists($path)) {
|
||||
throw new InvalidArgumentException('Input file not found: ' . $path);
|
||||
}
|
||||
|
||||
return json_decode(
|
||||
file_get_contents($path),
|
||||
true,
|
||||
512,
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use ArrayIterator;
|
||||
use InvalidArgumentException;
|
||||
use Openguru\OpenCartFramework\Collection\Collection;
|
||||
use stdClass;
|
||||
use Tests\Helpers\ExampleClasses\FilterDTO;
|
||||
use Tests\TestCase;
|
||||
|
||||
class GenericCollectionTest extends TestCase
|
||||
{
|
||||
public function testCanAddItemsToCollection(): void
|
||||
{
|
||||
$collection = new Collection([], FilterDTO::class);
|
||||
|
||||
$filter = new FilterDTO('price', '>', 100);
|
||||
$collection->add($filter);
|
||||
|
||||
$this->assertCount(1, $collection);
|
||||
$this->assertSame($filter, $collection->all()[0]);
|
||||
}
|
||||
|
||||
public function testThrowsExceptionWhenAddingInvalidItem(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Item must be an instance of');
|
||||
|
||||
$collection = new Collection([], FilterDTO::class);
|
||||
$collection->add(new stdClass()); // Invalid item
|
||||
}
|
||||
|
||||
public function testCanFindItemByProperty(): void
|
||||
{
|
||||
$filter1 = new FilterDTO('price', '>', 100);
|
||||
$filter2 = new FilterDTO('stock', '<', 50);
|
||||
$collection = new Collection([$filter1, $filter2], FilterDTO::class);
|
||||
|
||||
$result = $collection->findByProperty('field', 'stock');
|
||||
|
||||
$this->assertNotNull($result);
|
||||
$this->assertSame($filter2, $result);
|
||||
}
|
||||
|
||||
public function testReturnsNullWhenItemNotFound(): void
|
||||
{
|
||||
$filter = new FilterDTO('price', '>', 100);
|
||||
$collection = new Collection([$filter], FilterDTO::class);
|
||||
|
||||
$result = $collection->findByProperty('field', 'nonexistent');
|
||||
|
||||
$this->assertNull($result);
|
||||
}
|
||||
|
||||
public function testCanCheckIfItemWithSpecificPropertyAndValueExists(): void
|
||||
{
|
||||
$filter = new FilterDTO('price', '>', 100);
|
||||
$collection = new Collection([$filter], FilterDTO::class);
|
||||
|
||||
$exists = $collection->hasValue('field', 'price');
|
||||
$notExists = $collection->hasValue('field', 'nonexistent');
|
||||
|
||||
$this->assertTrue($exists);
|
||||
$this->assertFalse($notExists);
|
||||
}
|
||||
|
||||
public function testImplementsCountable(): void
|
||||
{
|
||||
$filter1 = new FilterDTO('price', '>', 100);
|
||||
$filter2 = new FilterDTO('stock', '<', 50);
|
||||
$collection = new Collection([$filter1, $filter2], FilterDTO::class);
|
||||
|
||||
$this->assertCount(2, $collection);
|
||||
}
|
||||
|
||||
public function testImplementsIteratorAggregate(): void
|
||||
{
|
||||
$filter1 = new FilterDTO('price', '>', 100);
|
||||
$filter2 = new FilterDTO('stock', '<', 50);
|
||||
$collection = new Collection([$filter1, $filter2], FilterDTO::class);
|
||||
|
||||
$iterator = $collection->getIterator();
|
||||
|
||||
$this->assertInstanceOf(ArrayIterator::class, $iterator);
|
||||
$this->assertCount(2, $iterator);
|
||||
}
|
||||
|
||||
public function testImplementsArrayAccess(): void
|
||||
{
|
||||
$filter1 = new FilterDTO('price', '>', 100);
|
||||
$filter2 = new FilterDTO('stock', '<', 50);
|
||||
$collection = new Collection([], FilterDTO::class);
|
||||
|
||||
// Adding items
|
||||
$collection[] = $filter1;
|
||||
$collection[] = $filter2;
|
||||
|
||||
$this->assertCount(2, $collection);
|
||||
$this->assertSame($filter1, $collection[0]);
|
||||
$this->assertSame($filter2, $collection[1]);
|
||||
|
||||
// Modifying an item
|
||||
$collection[0] = $filter2;
|
||||
$this->assertSame($filter2, $collection[0]);
|
||||
|
||||
// Checking existence
|
||||
$this->assertTrue(isset($collection[0]));
|
||||
$this->assertFalse(isset($collection[5]));
|
||||
|
||||
// Removing an item
|
||||
unset($collection[0]);
|
||||
$this->assertFalse(isset($collection[0]));
|
||||
}
|
||||
|
||||
public function testArrayAccessThrowsExceptionForInvalidType(): void
|
||||
{
|
||||
$collection = new Collection([], FilterDTO::class);
|
||||
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Item must be an instance of');
|
||||
|
||||
$collection[] = new stdClass(); // Invalid item
|
||||
}
|
||||
|
||||
public function testConstructorValidatesItems(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$invalidItems = [new stdClass(), new FilterDTO('price', '>', 100)];
|
||||
new Collection($invalidItems, FilterDTO::class);
|
||||
}
|
||||
|
||||
public function testCanRetrieveAllItems(): void
|
||||
{
|
||||
$filter1 = new FilterDTO('price', '>', 100);
|
||||
$filter2 = new FilterDTO('stock', '<', 50);
|
||||
$collection = new Collection([$filter1, $filter2], FilterDTO::class);
|
||||
|
||||
$allItems = $collection->all();
|
||||
|
||||
$this->assertCount(2, $allItems);
|
||||
$this->assertSame($filter1, $allItems[0]);
|
||||
$this->assertSame($filter2, $allItems[1]);
|
||||
}
|
||||
|
||||
public function testCanGetValueByProperty(): void
|
||||
{
|
||||
$filter1 = new FilterDTO('price', '>', 100);
|
||||
$filter2 = new FilterDTO('category', '=', 'electronics');
|
||||
$collection = new Collection([$filter1, $filter2], FilterDTO::class);
|
||||
|
||||
$value = $collection->getValueByProperty('field', 'price');
|
||||
$this->assertSame(100, $value);
|
||||
|
||||
$value = $collection->getValueByProperty('field', 'category');
|
||||
$this->assertSame('electronics', $value);
|
||||
}
|
||||
|
||||
public function testReturnsNullIfPropertyNotFound(): void
|
||||
{
|
||||
$filter = new FilterDTO('price', '>', 100);
|
||||
$collection = new Collection([$filter], FilterDTO::class);
|
||||
|
||||
$value = $collection->getValueByProperty('field', 'nonexistent');
|
||||
$this->assertNull($value);
|
||||
}
|
||||
|
||||
public function testReturnsNullIfNoItemsInCollection(): void
|
||||
{
|
||||
$collection = new Collection([], FilterDTO::class);
|
||||
|
||||
$value = $collection->getValueByProperty('field', 'price');
|
||||
$this->assertNull($value);
|
||||
}
|
||||
}
|
||||
54
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/HelpersTest.php
Executable file
54
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/HelpersTest.php
Executable file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Tests\TestCase;
|
||||
|
||||
class HelpersTest extends TestCase
|
||||
{
|
||||
public function testDbTable(): void
|
||||
{
|
||||
$this->assertEquals('oc_some_table', db_table('some_table'));
|
||||
}
|
||||
|
||||
public function testDbColumnWithTableAndColumn(): void
|
||||
{
|
||||
$column = 'users.email';
|
||||
$expected = 'oc_users.email';
|
||||
|
||||
$this->assertEquals($expected, db_column($column));
|
||||
}
|
||||
|
||||
public function testDbColumnWithoutTable(): void
|
||||
{
|
||||
$column = 'email';
|
||||
$expected = 'email';
|
||||
|
||||
$this->assertEquals($expected, db_column($column));
|
||||
}
|
||||
|
||||
public function testDbColumnWithEmptyTable(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Invalid column reference: ');
|
||||
|
||||
db_column('.email');
|
||||
}
|
||||
|
||||
public function testDbColumnWithEmptyColumn(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Invalid column reference: ');
|
||||
|
||||
db_column('users.');
|
||||
}
|
||||
|
||||
public function testDbColumnWithEmptyTableAndColumn(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Invalid column reference: ');
|
||||
|
||||
db_column('.');
|
||||
}
|
||||
}
|
||||
222
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/MySqlGrammarTest.php
Executable file
222
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/MySqlGrammarTest.php
Executable file
@@ -0,0 +1,222 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use Mockery as m;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Grammars\MySqlGrammar;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\JoinClause;
|
||||
use Tests\TestCase;
|
||||
|
||||
class MySqlGrammarTest extends TestCase
|
||||
{
|
||||
private $grammar;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->grammar = new MySqlGrammar();
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
parent::tearDown();
|
||||
|
||||
m::close();
|
||||
}
|
||||
|
||||
public function testCompileFrom(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
'FROM foobar AS alias',
|
||||
$this->grammar->compileFrom(m::mock(Builder::class), ['table' => 'foobar', 'as' => 'alias'])
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
'FROM foobar',
|
||||
$this->grammar->compileFrom(m::mock(Builder::class), ['table' => 'foobar', 'as' => null])
|
||||
);
|
||||
}
|
||||
|
||||
public function testCompileLimit(): void
|
||||
{
|
||||
$this->assertEquals('LIMIT 10', $this->grammar->compileLimit(m::mock(Builder::class), 10));
|
||||
}
|
||||
|
||||
public function testCompileOffset(): void
|
||||
{
|
||||
$this->assertEquals('OFFSET 10', $this->grammar->compileOffset(m::mock(Builder::class), 10));
|
||||
}
|
||||
|
||||
public function testCompileColumns(): void
|
||||
{
|
||||
$this->assertEquals('SELECT *', $this->grammar->compileColumns(m::mock(Builder::class), []));
|
||||
$this->assertEquals('SELECT foo, bar', $this->grammar->compileColumns(m::mock(Builder::class), [
|
||||
['column' => 'foo', 'as' => null],
|
||||
['column' => 'bar', 'as' => null],
|
||||
]));
|
||||
$this->assertEquals('SELECT foo AS bar, xxx AS yyy', $this->grammar->compileColumns(
|
||||
m::mock(Builder::class), [
|
||||
['column' => 'foo', 'as' => 'bar'],
|
||||
['column' => 'xxx', 'as' => 'yyy'],
|
||||
]));
|
||||
}
|
||||
|
||||
public function testCompileWheres(): void
|
||||
{
|
||||
$this->assertEquals('', $this->grammar->compileWheres(m::mock(Builder::class), []));
|
||||
$this->assertEquals('WHERE foo IS NOT NULL', $this->grammar->compileWheres(m::mock(Builder::class), [
|
||||
[
|
||||
'type' => 'NotNull',
|
||||
'column' => 'foo',
|
||||
'boolean' => 'and',
|
||||
]
|
||||
]));
|
||||
$this->assertEquals('WHERE foo IS NULL', $this->grammar->compileWheres(m::mock(Builder::class), [
|
||||
[
|
||||
'type' => 'Null',
|
||||
'column' => 'foo',
|
||||
'boolean' => 'and',
|
||||
]
|
||||
]));
|
||||
|
||||
$this->assertEquals('WHERE foo = ? OR bar = ? AND xxx IS NULL', $this->grammar->compileWheres(
|
||||
m::mock(Builder::class), [
|
||||
[
|
||||
'type' => 'Basic',
|
||||
'column' => 'foo',
|
||||
'operator' => '=',
|
||||
'value' => 'val',
|
||||
'boolean' => 'and',
|
||||
],
|
||||
[
|
||||
'type' => 'Basic',
|
||||
'column' => 'bar',
|
||||
'operator' => '=',
|
||||
'value' => 'val',
|
||||
'boolean' => 'or',
|
||||
],
|
||||
[
|
||||
'type' => 'Null',
|
||||
'column' => 'xxx',
|
||||
'boolean' => 'and',
|
||||
]
|
||||
]));
|
||||
}
|
||||
|
||||
public function testCompileOrders(): void
|
||||
{
|
||||
$this->assertEquals('ORDER BY foo DESC, bar ASC', $this->grammar->compileOrders(
|
||||
m::mock(Builder::class), [
|
||||
['column' => 'foo', 'direction' => 'DESC'],
|
||||
['column' => 'bar', 'direction' => 'ASC'],
|
||||
]));
|
||||
}
|
||||
|
||||
public function testWhereNotNull(): void
|
||||
{
|
||||
$this->assertEquals('foo IS NOT NULL', $this->grammar->whereNotNull([
|
||||
'type' => 'NotNull',
|
||||
'column' => 'foo',
|
||||
'boolean' => 'and',
|
||||
]));
|
||||
}
|
||||
|
||||
public function testWhereNull(): void
|
||||
{
|
||||
$this->assertEquals('foo IS NULL', $this->grammar->whereNull([
|
||||
'type' => 'Null',
|
||||
'column' => 'foo',
|
||||
'boolean' => 'and',
|
||||
]));
|
||||
}
|
||||
|
||||
public function testWhereBasic(): void
|
||||
{
|
||||
$this->assertEquals('foo = ?', $this->grammar->whereBasic([
|
||||
'type' => 'Basic',
|
||||
'column' => 'foo',
|
||||
'operator' => '=',
|
||||
'value' => 'val',
|
||||
'boolean' => 'and',
|
||||
]));
|
||||
}
|
||||
|
||||
public function testConcatCompiled(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
/** @lang text */ 'SELECT * FROM table WHERE foo = ? LIMIT 10',
|
||||
$this->grammar->concatCompiled([
|
||||
'wheres' => 'WHERE foo = ?',
|
||||
'limit' => 'LIMIT 10',
|
||||
'columns' => 'SELECT *',
|
||||
'from' => 'FROM table',
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
public function testCompileJoins(): void
|
||||
{
|
||||
$joinClause = m::mock(JoinClause::class);
|
||||
$joinClause->table = 'table AS t';
|
||||
$joinClause->type = 'inner';
|
||||
$joinClause->first = 't.id';
|
||||
$joinClause->operator = '=';
|
||||
$joinClause->second = 'parent.id';
|
||||
$joinClause->wheres = [
|
||||
[
|
||||
'type' => 'Basic',
|
||||
'column' => 't.foo',
|
||||
'operator' => '=',
|
||||
'value' => 'bar',
|
||||
'boolean' => 'and',
|
||||
]
|
||||
];
|
||||
|
||||
$builder = m::mock(Builder::class);
|
||||
|
||||
$this->assertEquals(
|
||||
'INNER JOIN table AS t ON t.id = parent.id AND t.foo = ?',
|
||||
$this->grammar->compileJoins(
|
||||
$builder,
|
||||
[
|
||||
$joinClause,
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function testCompileWhereIn(): void
|
||||
{
|
||||
$this->assertEquals('foo IN (?, ?, ?, ?)', $this->grammar->whereIn([
|
||||
'type' => 'In',
|
||||
'column' => 'foo',
|
||||
'operator' => 'IN',
|
||||
'value' => [1, 2, 3, 4],
|
||||
'boolean' => 'and',
|
||||
]));
|
||||
}
|
||||
|
||||
public function testCompileWhereNotIn(): void
|
||||
{
|
||||
$this->assertEquals('foo NOT IN (?, ?, ?, ?)', $this->grammar->whereIn([
|
||||
'type' => 'In',
|
||||
'column' => 'foo',
|
||||
'operator' => 'NOT IN',
|
||||
'value' => [1, 2, 3, 4],
|
||||
'boolean' => 'and',
|
||||
]));
|
||||
}
|
||||
|
||||
public function testCompileDistinctColumns(): void
|
||||
{
|
||||
$mock = m::mock(Builder::class);
|
||||
$mock->distinct = true;
|
||||
|
||||
$this->assertEquals('SELECT DISTINCT foo, bar', $this->grammar->compileColumns($mock, [
|
||||
['column' => 'foo', 'as' => null],
|
||||
['column' => 'bar', 'as' => null],
|
||||
]));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use App\FacetSearch\Filters\ProductModel;
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\Criterion;
|
||||
use Openguru\OpenCartFramework\CriteriaBuilder\RuleSerializer;
|
||||
use Tests\TestCase;
|
||||
|
||||
class RuleSerializerTest extends TestCase
|
||||
{
|
||||
public function testSerialize(): void
|
||||
{
|
||||
$rulesSerializer = new RuleSerializer();
|
||||
|
||||
$productName = new ProductModel(
|
||||
ProductModel::NAME,
|
||||
[
|
||||
'product_model' => new Criterion('string', [
|
||||
'operator' => 'contains',
|
||||
'keyword' => 'foobar',
|
||||
])
|
||||
]
|
||||
);
|
||||
|
||||
$expected = [
|
||||
'id' => 'RULE_PRODUCT_MODEL',
|
||||
'criteria' => [
|
||||
'product_model' =>
|
||||
[
|
||||
'type' => 'string',
|
||||
'params' => [
|
||||
'operator' => 'contains',
|
||||
'keyword' => 'foobar',
|
||||
]
|
||||
]
|
||||
],
|
||||
'__meta' => [
|
||||
'group' => 'other',
|
||||
],
|
||||
];
|
||||
$actual = $rulesSerializer->toArray($productName);
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
}
|
||||
119
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/SettingsTest.php
Executable file
119
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Unit/SettingsTest.php
Executable file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use Openguru\OpenCartFramework\Config\Settings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class SettingsTest extends TestCase
|
||||
{
|
||||
private $settings;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->settings = new Settings([
|
||||
'app_name' => 'MyApp',
|
||||
'debug_mode' => true,
|
||||
'default_language' => 'en',
|
||||
'database' => [
|
||||
'host' => 'localhost',
|
||||
'port' => 3306,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function testGet(): void
|
||||
{
|
||||
$this->assertEquals('MyApp', $this->settings->get('app_name'));
|
||||
$this->assertTrue($this->settings->get('debug_mode'));
|
||||
$this->assertEquals('en', $this->settings->get('default_language'));
|
||||
$this->assertEquals('localhost', $this->settings->get('database.host'));
|
||||
}
|
||||
|
||||
public function testGetDefault(): void
|
||||
{
|
||||
$this->assertNull($this->settings->get('non_existent_key'));
|
||||
$this->assertEquals('default_value', $this->settings->get('non_existent_key', 'default_value'));
|
||||
$this->assertEquals('default_host', $this->settings->get('database.non_existent', 'default_host'));
|
||||
}
|
||||
|
||||
public function testSet(): void
|
||||
{
|
||||
$this->settings->set('app_name', 'NewApp');
|
||||
$this->assertEquals('NewApp', $this->settings->get('app_name'));
|
||||
|
||||
$this->settings->set('new_setting', 'new_value');
|
||||
$this->assertEquals('new_value', $this->settings->get('new_setting'));
|
||||
|
||||
$this->settings->set('database.host', '127.0.0.1');
|
||||
$this->assertEquals('127.0.0.1', $this->settings->get('database.host'));
|
||||
}
|
||||
|
||||
public function testHas(): void
|
||||
{
|
||||
$this->assertTrue($this->settings->has('app_name'));
|
||||
$this->assertTrue($this->settings->has('debug_mode'));
|
||||
$this->assertFalse($this->settings->has('non_existent_key'));
|
||||
$this->assertTrue($this->settings->has('database.host'));
|
||||
$this->assertFalse($this->settings->has('database.non_existent'));
|
||||
}
|
||||
|
||||
public function testRemove(): void
|
||||
{
|
||||
$this->settings->remove('debug_mode');
|
||||
$this->assertFalse($this->settings->has('debug_mode'));
|
||||
|
||||
$this->settings->remove('database.host');
|
||||
$this->assertFalse($this->settings->has('database.host'));
|
||||
}
|
||||
|
||||
public function testGetAll(): void
|
||||
{
|
||||
$expected = [
|
||||
'app_name' => 'MyApp',
|
||||
'debug_mode' => true,
|
||||
'default_language' => 'en',
|
||||
'database' => [
|
||||
'host' => 'localhost',
|
||||
'port' => 3306,
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $this->settings->getAll());
|
||||
}
|
||||
|
||||
public function testSetAll(): void
|
||||
{
|
||||
$newSettings = [
|
||||
'app_name' => 'NewApp',
|
||||
'theme' => 'dark',
|
||||
];
|
||||
$this->settings->setAll($newSettings);
|
||||
$this->assertEquals($newSettings, $this->settings->getAll());
|
||||
}
|
||||
|
||||
public function testDotNotationGetAndSet(): void
|
||||
{
|
||||
$this->settings->set('database.username', 'root');
|
||||
$this->assertEquals('root', $this->settings->get('database.username'));
|
||||
|
||||
$this->settings->set('app.env', 'production');
|
||||
$this->assertEquals('production', $this->settings->get('app.env'));
|
||||
}
|
||||
|
||||
public function testDotNotationHas(): void
|
||||
{
|
||||
$this->settings->set('cache.enabled', true);
|
||||
$this->assertTrue($this->settings->has('cache.enabled'));
|
||||
$this->assertFalse($this->settings->has('cache.non_existent'));
|
||||
}
|
||||
|
||||
public function testDotNotationRemove(): void
|
||||
{
|
||||
$this->settings->set('logging.level', 'debug');
|
||||
$this->assertTrue($this->settings->has('logging.level'));
|
||||
|
||||
$this->settings->remove('logging.level');
|
||||
$this->assertFalse($this->settings->has('logging.level'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use Openguru\OpenCartFramework\Translator\Translator;
|
||||
use Tests\TestCase;
|
||||
|
||||
class TranslatorTest extends TestCase
|
||||
{
|
||||
public function testBasicTranslate(): void
|
||||
{
|
||||
$translator = new Translator('ru', ['foo' => 'bar']);
|
||||
|
||||
$this->assertEquals('bar', $translator->translate('foo'));
|
||||
}
|
||||
|
||||
public function testTranslateWithParams(): void
|
||||
{
|
||||
$translator = new Translator('ru', [
|
||||
'example' => '{placeholder_1} foo {placeholder_2} bar {placeholder_3}',
|
||||
]);
|
||||
|
||||
$placeholders = ['placeholder_1' => 'a', 'placeholder_2' => 'b', 'placeholder_3' => 'c'];
|
||||
$expected = 'a foo b bar c';
|
||||
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$translator->translate('example', $placeholders)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Validator;
|
||||
namespace Tests\Unit\Validator;
|
||||
|
||||
use Openguru\OpenCartFramework\Validator\ErrorBag;
|
||||
use Tests\TestCase;
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Validator;
|
||||
namespace Tests\Unit\Validator;
|
||||
|
||||
use Openguru\OpenCartFramework\Validator\ValidationRuleNotFoundException;
|
||||
use Openguru\OpenCartFramework\Validator\ValidationRules\Required;
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"operand": "AND",
|
||||
"rules": {
|
||||
"RULE_PRODUCT_ATTRIBUTE": {
|
||||
"criteria": {
|
||||
"product_attribute": {
|
||||
"type": "product_attribute",
|
||||
"params": {
|
||||
"attribute_id": 3,
|
||||
"operator": "contains",
|
||||
"keyword": "test",
|
||||
"language_id": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
SELECT
|
||||
products.product_id AS product_id,
|
||||
products.image AS image,
|
||||
product_description.name AS name,
|
||||
products.model AS model,
|
||||
products.price AS price,
|
||||
products.quantity AS quantity,
|
||||
products.status AS STATUS,
|
||||
products.noindex AS noindex
|
||||
FROM
|
||||
oc_product AS products
|
||||
INNER JOIN oc_product_description AS product_description ON products.product_id = product_description.product_id
|
||||
AND product_description.language_id = 1
|
||||
LEFT JOIN oc_product_attribute AS product_attributes_facet_69f524aec48a647c231b774b5b3684f5 ON products.product_id = product_attributes_facet_69f524aec48a647c231b774b5b3684f5.product_id
|
||||
AND product_attributes_facet_69f524aec48a647c231b774b5b3684f5.attribute_id = 3
|
||||
AND product_attributes_facet_69f524aec48a647c231b774b5b3684f5.language_id = 1
|
||||
AND product_attributes_facet_69f524aec48a647c231b774b5b3684f5.text LIKE '%test%'
|
||||
WHERE
|
||||
product_attributes_facet_69f524aec48a647c231b774b5b3684f5.product_id IS NOT NULL
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"operand": "AND",
|
||||
"rules": {
|
||||
"RULE_PRODUCT_CATEGORIES": {
|
||||
"criteria": {
|
||||
"product_category_ids": {
|
||||
"type": "product_categories",
|
||||
"params": {
|
||||
"operator": "contains",
|
||||
"value": [
|
||||
58
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"__meta": {
|
||||
"group": "other"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
SELECT
|
||||
products.product_id AS product_id,
|
||||
products.image AS image,
|
||||
product_description.name AS name,
|
||||
products.model AS model,
|
||||
products.price AS price,
|
||||
products.quantity AS quantity,
|
||||
products.status AS STATUS,
|
||||
products.noindex AS noindex
|
||||
FROM
|
||||
oc_product AS products
|
||||
INNER JOIN oc_product_description AS product_description ON products.product_id = product_description.product_id
|
||||
AND product_description.language_id = 1
|
||||
LEFT JOIN oc_product_to_category AS product_category_599af8cd341315a88d056caf99121e59 ON products.product_id = product_category_599af8cd341315a88d056caf99121e59.product_id
|
||||
AND product_category_599af8cd341315a88d056caf99121e59.category_id IN (58)
|
||||
WHERE
|
||||
product_category_599af8cd341315a88d056caf99121e59.product_id IS NOT NULL
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"operand": "AND",
|
||||
"rules": {
|
||||
"RULE_PRODUCT_CATEGORIES": {
|
||||
"criteria": {
|
||||
"product_category_ids": {
|
||||
"type": "product_categories",
|
||||
"params": {
|
||||
"operator": "not_contains",
|
||||
"value": [
|
||||
58
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"__meta": {
|
||||
"group": "other"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
SELECT
|
||||
products.product_id AS product_id,
|
||||
products.image AS image,
|
||||
product_description.name AS name,
|
||||
products.model AS model,
|
||||
products.price AS price,
|
||||
products.quantity AS quantity,
|
||||
products.status AS STATUS,
|
||||
products.noindex AS noindex
|
||||
FROM
|
||||
oc_product AS products
|
||||
INNER JOIN oc_product_description AS product_description ON products.product_id = product_description.product_id
|
||||
AND product_description.language_id = 1
|
||||
LEFT JOIN oc_product_to_category AS product_category_ac1646c96882395073737c8da0822479 ON products.product_id = product_category_ac1646c96882395073737c8da0822479.product_id
|
||||
AND product_category_ac1646c96882395073737c8da0822479.category_id IN (58)
|
||||
WHERE
|
||||
product_category_ac1646c96882395073737c8da0822479.product_id IS NULL
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"operand": "AND",
|
||||
"rules": {
|
||||
"RULE_PRODUCT_FOR_MAIN_PAGE": {
|
||||
"criteria": {
|
||||
"product_for_main_page": {
|
||||
"type": "boolean",
|
||||
"params": {
|
||||
"operator": "equals",
|
||||
"value": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
SELECT
|
||||
products.product_id AS product_id,
|
||||
products.image AS image,
|
||||
product_description.name AS name,
|
||||
products.model AS model,
|
||||
products.price AS price,
|
||||
products.quantity AS quantity,
|
||||
products.status AS STATUS,
|
||||
products.noindex AS noindex
|
||||
FROM
|
||||
oc_product AS products
|
||||
INNER JOIN oc_product_description AS product_description ON products.product_id = product_description.product_id
|
||||
AND product_description.language_id = 1
|
||||
WHERE
|
||||
products.product_id IN (1, 2, 3)
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"mainpage_products": "featured",
|
||||
"featured_products": [1, 2, 3]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"operand": "AND",
|
||||
"rules": {
|
||||
"RULE_PRODUCT_FOR_MAIN_PAGE": {
|
||||
"criteria": {
|
||||
"product_for_main_page": {
|
||||
"type": "boolean",
|
||||
"params": {
|
||||
"operator": "equals",
|
||||
"value": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
SELECT
|
||||
products.product_id AS product_id,
|
||||
products.image AS image,
|
||||
product_description.name AS name,
|
||||
products.model AS model,
|
||||
products.price AS price,
|
||||
products.quantity AS quantity,
|
||||
products.status AS STATUS,
|
||||
products.noindex AS noindex
|
||||
FROM
|
||||
oc_product AS products
|
||||
INNER JOIN oc_product_description AS product_description ON products.product_id = product_description.product_id
|
||||
AND product_description.language_id = 1
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"mainpage_products": "featured",
|
||||
"featured_products": []
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"operand": "AND",
|
||||
"rules": {
|
||||
"RULE_PRODUCT_FOR_MAIN_PAGE": {
|
||||
"criteria": {
|
||||
"product_for_main_page": {
|
||||
"type": "boolean",
|
||||
"params": {
|
||||
"operator": "equals",
|
||||
"value": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
SELECT
|
||||
products.product_id AS product_id,
|
||||
products.image AS image,
|
||||
product_description.name AS name,
|
||||
products.model AS model,
|
||||
products.price AS price,
|
||||
products.quantity AS quantity,
|
||||
products.status AS STATUS,
|
||||
products.noindex AS noindex
|
||||
FROM
|
||||
oc_product AS products
|
||||
INNER JOIN oc_product_description AS product_description ON products.product_id = product_description.product_id
|
||||
AND product_description.language_id = 1
|
||||
ORDER BY
|
||||
products.date_modified DESC
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"mainpage_products": "latest"
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"operand": "AND",
|
||||
"rules": {
|
||||
"RULE_PRODUCT_FOR_MAIN_PAGE": {
|
||||
"criteria": {
|
||||
"product_for_main_page": {
|
||||
"type": "boolean",
|
||||
"params": {
|
||||
"operator": "equals",
|
||||
"value": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
SELECT
|
||||
products.product_id AS product_id,
|
||||
products.image AS image,
|
||||
product_description.name AS name,
|
||||
products.model AS model,
|
||||
products.price AS price,
|
||||
products.quantity AS quantity,
|
||||
products.status AS STATUS,
|
||||
products.noindex AS noindex
|
||||
FROM
|
||||
oc_product AS products
|
||||
INNER JOIN oc_product_description AS product_description ON products.product_id = product_description.product_id
|
||||
AND product_description.language_id = 1
|
||||
ORDER BY
|
||||
products.viewed DESC
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"mainpage_products": "most_viewed"
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"operand": "AND",
|
||||
"rules": {
|
||||
"RULE_PRODUCT_MANUFACTURER": {
|
||||
"criteria": {
|
||||
"product_manufacturer_ids": {
|
||||
"type": "product_manufacturer",
|
||||
"params": {
|
||||
"operator": "contains",
|
||||
"value": [
|
||||
8,
|
||||
9
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"__meta": {
|
||||
"group": "other"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
SELECT
|
||||
products.product_id AS product_id,
|
||||
products.image AS image,
|
||||
product_description.name AS name,
|
||||
products.model AS model,
|
||||
products.price AS price,
|
||||
products.quantity AS quantity,
|
||||
products.status AS STATUS,
|
||||
products.noindex AS noindex
|
||||
FROM
|
||||
oc_product AS products
|
||||
INNER JOIN oc_product_description AS product_description ON products.product_id = product_description.product_id
|
||||
AND product_description.language_id = 1
|
||||
WHERE
|
||||
products.manufacturer_id IN (8, 9)
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"operand": "AND",
|
||||
"rules": {
|
||||
"RULE_PRODUCT_MANUFACTURER": {
|
||||
"criteria": {
|
||||
"product_manufacturer_ids": {
|
||||
"type": "product_manufacturer",
|
||||
"params": {
|
||||
"operator": "not_contains",
|
||||
"value": [
|
||||
8,
|
||||
9
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"__meta": {
|
||||
"group": "other"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
SELECT
|
||||
products.product_id AS product_id,
|
||||
products.image AS image,
|
||||
product_description.name AS name,
|
||||
products.model AS model,
|
||||
products.price AS price,
|
||||
products.quantity AS quantity,
|
||||
products.status AS STATUS,
|
||||
products.noindex AS noindex
|
||||
FROM
|
||||
oc_product AS products
|
||||
INNER JOIN oc_product_description AS product_description ON products.product_id = product_description.product_id
|
||||
AND product_description.language_id = 1
|
||||
WHERE
|
||||
products.manufacturer_id NOT IN (8, 9)
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"operand": "AND",
|
||||
"rules": {
|
||||
"RULE_PRODUCT_MODEL": {
|
||||
"criteria": {
|
||||
"product_model": {
|
||||
"type": "product_model",
|
||||
"params": {
|
||||
"operator": "contains",
|
||||
"value": [
|
||||
"model1",
|
||||
"model2"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"__meta": {
|
||||
"group": "other"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
SELECT
|
||||
products.product_id AS product_id,
|
||||
products.image AS image,
|
||||
product_description.name AS name,
|
||||
products.model AS model,
|
||||
products.price AS price,
|
||||
products.quantity AS quantity,
|
||||
products.status AS STATUS,
|
||||
products.noindex AS noindex
|
||||
FROM
|
||||
oc_product AS products
|
||||
INNER JOIN oc_product_description AS product_description ON products.product_id = product_description.product_id
|
||||
AND product_description.language_id = 1
|
||||
WHERE
|
||||
products.model IN ('model1', 'model2')
|
||||
19
module/oc_telegram_shop/upload/oc_telegram_shop/tests/fixtures/criteria_builder/product_model/equals/input.json
vendored
Executable file
19
module/oc_telegram_shop/upload/oc_telegram_shop/tests/fixtures/criteria_builder/product_model/equals/input.json
vendored
Executable file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"operand": "AND",
|
||||
"rules": {
|
||||
"RULE_PRODUCT_MODEL": {
|
||||
"criteria": {
|
||||
"product_model": {
|
||||
"type": "product_model",
|
||||
"params": {
|
||||
"operator": "equals",
|
||||
"keyword": "model1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"__meta": {
|
||||
"group": "other"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
module/oc_telegram_shop/upload/oc_telegram_shop/tests/fixtures/criteria_builder/product_model/equals/output.sql
vendored
Executable file
15
module/oc_telegram_shop/upload/oc_telegram_shop/tests/fixtures/criteria_builder/product_model/equals/output.sql
vendored
Executable file
@@ -0,0 +1,15 @@
|
||||
SELECT
|
||||
products.product_id AS product_id,
|
||||
products.image AS image,
|
||||
product_description.name AS name,
|
||||
products.model AS model,
|
||||
products.price AS price,
|
||||
products.quantity AS quantity,
|
||||
products.status AS STATUS,
|
||||
products.noindex AS noindex
|
||||
FROM
|
||||
oc_product AS products
|
||||
INNER JOIN oc_product_description AS product_description ON products.product_id = product_description.product_id
|
||||
AND product_description.language_id = 1
|
||||
WHERE
|
||||
TRUE = FALSE
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"operand": "AND",
|
||||
"rules": {
|
||||
"RULE_PRODUCT_MODEL": {
|
||||
"criteria": {
|
||||
"product_model": {
|
||||
"type": "string",
|
||||
"params": {
|
||||
"operator": "is_empty",
|
||||
"keyword": "product"
|
||||
}
|
||||
}
|
||||
},
|
||||
"__meta": {
|
||||
"group": "other"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
SELECT
|
||||
products.product_id AS product_id,
|
||||
products.image AS image,
|
||||
product_description.name AS name,
|
||||
products.model AS model,
|
||||
products.price AS price,
|
||||
products.quantity AS quantity,
|
||||
products.status AS STATUS,
|
||||
products.noindex AS noindex
|
||||
FROM
|
||||
oc_product AS products
|
||||
INNER JOIN oc_product_description AS product_description ON products.product_id = product_description.product_id
|
||||
AND product_description.language_id = 1
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"operand": "AND",
|
||||
"rules": {
|
||||
"RULE_PRODUCT_MODEL": {
|
||||
"criteria": {
|
||||
"product_model": {
|
||||
"type": "string",
|
||||
"params": {
|
||||
"operator": "is_not_empty",
|
||||
"keyword": "product"
|
||||
}
|
||||
}
|
||||
},
|
||||
"__meta": {
|
||||
"group": "other"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
SELECT
|
||||
products.product_id AS product_id,
|
||||
products.image AS image,
|
||||
product_description.name AS name,
|
||||
products.model AS model,
|
||||
products.price AS price,
|
||||
products.quantity AS quantity,
|
||||
products.status AS STATUS,
|
||||
products.noindex AS noindex
|
||||
FROM
|
||||
oc_product AS products
|
||||
INNER JOIN oc_product_description AS product_description ON products.product_id = product_description.product_id
|
||||
AND product_description.language_id = 1
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"operand": "AND",
|
||||
"rules": {
|
||||
"RULE_PRODUCT_MODEL": {
|
||||
"criteria": {
|
||||
"product_model": {
|
||||
"type": "string",
|
||||
"params": {
|
||||
"operator": "not_contains",
|
||||
"keyword": "product"
|
||||
}
|
||||
}
|
||||
},
|
||||
"__meta": {
|
||||
"group": "other"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
SELECT
|
||||
products.product_id AS product_id,
|
||||
products.image AS image,
|
||||
product_description.name AS name,
|
||||
products.model AS model,
|
||||
products.price AS price,
|
||||
products.quantity AS quantity,
|
||||
products.status AS STATUS,
|
||||
products.noindex AS noindex
|
||||
FROM
|
||||
oc_product AS products
|
||||
INNER JOIN oc_product_description AS product_description ON products.product_id = product_description.product_id
|
||||
AND product_description.language_id = 1
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"operand": "AND",
|
||||
"rules": {
|
||||
"RULE_PRODUCT_MODEL": {
|
||||
"criteria": {
|
||||
"product_model": {
|
||||
"type": "string",
|
||||
"params": {
|
||||
"operator": "not_equals",
|
||||
"keyword": "product"
|
||||
}
|
||||
}
|
||||
},
|
||||
"__meta": {
|
||||
"group": "other"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user