diff --git a/app/modules/api/Controllers/Account/SearchController.php b/app/modules/api/Controllers/Account/SearchController.php
index 863727f7..3c446535 100644
--- a/app/modules/api/Controllers/Account/SearchController.php
+++ b/app/modules/api/Controllers/Account/SearchController.php
@@ -25,16 +25,36 @@
namespace SP\Modules\Api\Controllers\Account;
use Exception;
+use Klein\Klein;
+use SP\Core\Acl\Acl;
use SP\Core\Acl\ActionsInterface;
-use SP\Domain\Account\Services\AccountSearchFilter;
+use SP\Core\Application;
+use SP\Domain\Account\AccountSearchServiceInterface;
+use SP\Domain\Account\Search\AccountSearchConstants;
+use SP\Domain\Account\Search\AccountSearchFilter;
+use SP\Domain\Api\ApiServiceInterface;
use SP\Domain\Api\Services\ApiResponse;
-use SP\Mvc\Model\QueryCondition;
+use SP\Modules\Api\Controllers\ControllerBase;
/**
* Class SearchController
*/
-final class SearchController extends AccountBase
+final class SearchController extends ControllerBase
{
+ private AccountSearchServiceInterface $accountSearchService;
+
+ public function __construct(
+ Application $application,
+ Klein $router,
+ ApiServiceInterface $apiService,
+ Acl $acl,
+ AccountSearchServiceInterface $accountSearchService
+ ) {
+ parent::__construct($application, $router, $apiService, $acl);
+
+ $this->accountSearchService = $accountSearchService;
+ }
+
/**
* searchAction
*/
@@ -46,7 +66,9 @@ final class SearchController extends AccountBase
$accountSearchFilter = $this->buildAccountSearchFilter();
$this->returnResponse(
- ApiResponse::makeSuccess($this->accountService->getByFilter($accountSearchFilter)->getDataAsArray())
+ ApiResponse::makeSuccess(
+ $this->accountSearchService->getByFilter($accountSearchFilter)->getDataAsArray()
+ )
);
} catch (Exception $e) {
processException($e);
@@ -56,40 +78,33 @@ final class SearchController extends AccountBase
}
/**
- * @return \SP\Domain\Account\Services\AccountSearchFilter
+ * @return \SP\Domain\Account\Search\AccountSearchFilter
* @throws \SP\Domain\Common\Services\ServiceException
*/
private function buildAccountSearchFilter(): AccountSearchFilter
{
- $accountSearchFilter = new AccountSearchFilter();
- $accountSearchFilter->setCleanTxtSearch($this->apiService->getParamString('text'));
- $accountSearchFilter->setCategoryId($this->apiService->getParamInt('categoryId'));
- $accountSearchFilter->setClientId($this->apiService->getParamInt('clientId'));
+ $filter = AccountSearchFilter::build($this->apiService->getParamString('text'))
+ ->setCategoryId($this->apiService->getParamInt('categoryId'))
+ ->setClientId($this->apiService->getParamInt('clientId'))
+ ->setTagsId(array_map('intval', $this->apiService->getParamArray('tagsId', false, [])))
+ ->setLimitCount($this->apiService->getParamInt('count', false, 50))
+ ->setSortOrder(
+ $this->apiService->getParamInt('order', false, AccountSearchConstants::SORT_DEFAULT)
+ );
- $tagsId = array_map('intval', $this->apiService->getParamArray('tagsId', false, []));
-
- if (count($tagsId) !== 0) {
- $accountSearchFilter->setTagsId($tagsId);
- }
-
- $op = $this->apiService->getParamString('op');
+ $op = $this->apiService->getParamString('op', false, AccountSearchConstants::FILTER_CHAIN_AND);
if ($op !== null) {
switch ($op) {
- case 'and':
- $accountSearchFilter->setFilterOperator(QueryCondition::CONDITION_AND);
+ case AccountSearchConstants::FILTER_CHAIN_AND:
+ $filter->setFilterOperator(AccountSearchConstants::FILTER_CHAIN_AND);
break;
- case 'or':
- $accountSearchFilter->setFilterOperator(QueryCondition::CONDITION_OR);
+ case AccountSearchConstants::FILTER_CHAIN_OR:
+ $filter->setFilterOperator(AccountSearchConstants::FILTER_CHAIN_OR);
break;
}
}
- $accountSearchFilter->setLimitCount($this->apiService->getParamInt('count', false, 50));
- $accountSearchFilter->setSortOrder(
- $this->apiService->getParamInt('order', false, AccountSearchFilter::SORT_DEFAULT)
- );
-
- return $accountSearchFilter;
+ return $filter;
}
}
\ No newline at end of file
diff --git a/app/modules/web/Controllers/AccountManager/SearchController.php b/app/modules/web/Controllers/AccountManager/SearchController.php
index 2450c468..d506e2fb 100644
--- a/app/modules/web/Controllers/AccountManager/SearchController.php
+++ b/app/modules/web/Controllers/AccountManager/SearchController.php
@@ -28,7 +28,7 @@ use SP\Core\Acl\ActionsInterface;
use SP\Core\Application;
use SP\Domain\Account\AccountSearchServiceInterface;
use SP\Domain\Account\AccountServiceInterface;
-use SP\Domain\Account\Services\AccountSearchFilter;
+use SP\Domain\Account\Search\AccountSearchFilter;
use SP\Html\DataGrid\DataGridInterface;
use SP\Http\JsonResponse;
use SP\Modules\Web\Controllers\ControllerBase;
@@ -51,6 +51,10 @@ final class SearchController extends ControllerBase
private AccountSearchServiceInterface $accountSearchService;
private AccountGrid $accountGrid;
+ /**
+ * @throws \SP\Core\Exceptions\SessionTimeout
+ * @throws \SP\Domain\Auth\Services\AuthException
+ */
public function __construct(
Application $application,
WebControllerHelper $webControllerHelper,
@@ -67,7 +71,6 @@ final class SearchController extends ControllerBase
/**
* @return bool
- * @throws \JsonException
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
* @throws \SP\Core\Exceptions\SPException
@@ -100,19 +103,12 @@ final class SearchController extends ControllerBase
{
$itemSearchData = $this->getSearchData($this->configData->getAccountCount(), $this->request);
- $filter = new AccountSearchFilter();
- $filter->setLimitCount($itemSearchData->getLimitCount());
- $filter->setLimitStart($itemSearchData->getLimitStart());
-
- if (!empty($itemSearchData->getSeachString())) {
- $filter->setStringFilters(
- $this->accountSearchService->analyzeQueryFilters($itemSearchData->getSeachString())
- );
- $filter->setCleanTxtSearch($this->accountSearchService->getCleanString());
- }
+ $filter = AccountSearchFilter::build($itemSearchData->getSeachString())
+ ->setLimitCount($itemSearchData->getLimitCount())
+ ->setLimitStart($itemSearchData->getLimitStart());
return $this->accountGrid->updatePager(
- $this->accountGrid->getGrid($this->accountService->getByFilter($filter)),
+ $this->accountGrid->getGrid($this->accountSearchService->getByFilter($filter)),
$itemSearchData
);
}
diff --git a/app/modules/web/Controllers/Helpers/Account/AccountSearchHelper.php b/app/modules/web/Controllers/Helpers/Account/AccountSearchHelper.php
index 7ac0c859..934e89b9 100644
--- a/app/modules/web/Controllers/Helpers/Account/AccountSearchHelper.php
+++ b/app/modules/web/Controllers/Helpers/Account/AccountSearchHelper.php
@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
- * @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org
+ * @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -35,7 +35,8 @@ use SP\Core\Exceptions\SPException;
use SP\DataModel\ProfileData;
use SP\DataModel\UserPreferencesData;
use SP\Domain\Account\AccountSearchServiceInterface;
-use SP\Domain\Account\Services\AccountSearchFilter;
+use SP\Domain\Account\Search\AccountSearchConstants;
+use SP\Domain\Account\Search\AccountSearchFilter;
use SP\Domain\Account\Services\AccountSearchItem;
use SP\Domain\Category\CategoryServiceInterface;
use SP\Domain\Client\ClientServiceInterface;
@@ -178,7 +179,7 @@ final class AccountSearchHelper extends HelperBase
}
$dataGrid = $this->getGrid();
- $dataGrid->getData()->setData($this->accountSearchService->processSearchResults($this->accountSearchFilter));
+ $dataGrid->getData()->setData($this->accountSearchService->getByFilter($this->accountSearchFilter));
$dataGrid->updatePager();
$dataGrid->setTime(round(getElapsedTime($this->queryTimeStart), 5));
@@ -275,35 +276,35 @@ final class AccountSearchHelper extends HelperBase
$gridSortCustomer = new DataGridSort();
$gridSortCustomer->setName(__('Client'))
->setTitle(__('Sort by Client'))
- ->setSortKey(AccountSearchFilter::SORT_CLIENT)
+ ->setSortKey(AccountSearchConstants::SORT_CLIENT)
->setIconUp($icons->getIconUp())
->setIconDown($icons->getIconDown());
$gridSortName = new DataGridSort();
$gridSortName->setName(__('Name'))
->setTitle(__('Sort by Name'))
- ->setSortKey(AccountSearchFilter::SORT_NAME)
+ ->setSortKey(AccountSearchConstants::SORT_NAME)
->setIconUp($icons->getIconUp())
->setIconDown($icons->getIconDown());
$gridSortCategory = new DataGridSort();
$gridSortCategory->setName(__('Category'))
->setTitle(__('Sort by Category'))
- ->setSortKey(AccountSearchFilter::SORT_CATEGORY)
+ ->setSortKey(AccountSearchConstants::SORT_CATEGORY)
->setIconUp($icons->getIconUp())
->setIconDown($icons->getIconDown());
$gridSortLogin = new DataGridSort();
$gridSortLogin->setName(__('User'))
->setTitle(__('Sort by Username'))
- ->setSortKey(AccountSearchFilter::SORT_LOGIN)
+ ->setSortKey(AccountSearchConstants::SORT_LOGIN)
->setIconUp($icons->getIconUp())
->setIconDown($icons->getIconDown());
$gridSortUrl = new DataGridSort();
$gridSortUrl->setName(__('URL / IP'))
->setTitle(__('Sort by URL / IP'))
- ->setSortKey(AccountSearchFilter::SORT_URL)
+ ->setSortKey(AccountSearchConstants::SORT_URL)
->setIconUp($icons->getIconUp())
->setIconDown($icons->getIconDown());
@@ -350,7 +351,7 @@ final class AccountSearchHelper extends HelperBase
/**
* Set search filters
*
- * @return AccountSearchFilter
+ * @return \SP\Domain\Account\Search\AccountSearchFilter
*/
private function getFilters(): AccountSearchFilter
{
diff --git a/composer.json b/composer.json
index daec1c4f..22952958 100644
--- a/composer.json
+++ b/composer.json
@@ -41,7 +41,8 @@
"league/fractal": "^0.19.2",
"symfony/console": "^v5.1.2",
"symfony/lock": "^v5.0",
- "ocramius/proxy-manager": "~2.0"
+ "ocramius/proxy-manager": "~2.0",
+ "aura/sqlquery": "~2.8"
},
"require-dev": {
"roave/security-advisories": "dev-latest",
diff --git a/composer.lock b/composer.lock
index d6bedf6c..009c0e09 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "6fd1ed6990aa4d5a83ef253a9b84f18e",
+ "content-hash": "8c72e7f9e5d3131fbc6492b91398897c",
"packages": [
{
"name": "ademarre/binary-to-text-php",
@@ -56,6 +56,77 @@
},
"time": "2015-02-27T05:11:22+00:00"
},
+ {
+ "name": "aura/sqlquery",
+ "version": "2.8.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/auraphp/Aura.SqlQuery.git",
+ "reference": "3cadc8bbdeb6cde5fde01349bbd5c4b0fbc1287e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/auraphp/Aura.SqlQuery/zipball/3cadc8bbdeb6cde5fde01349bbd5c4b0fbc1287e",
+ "reference": "3cadc8bbdeb6cde5fde01349bbd5c4b0fbc1287e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.9"
+ },
+ "require-dev": {
+ "yoast/phpunit-polyfills": "~1.0"
+ },
+ "suggest": {
+ "aura/sql": "Provides an extension to the native PDO along with a profiler and connection locator. Use version 2.*."
+ },
+ "type": "library",
+ "extra": {
+ "aura": {
+ "type": "library"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Aura\\SqlQuery\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-2-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Aura.SqlQuery Contributors",
+ "homepage": "https://github.com/auraphp/Aura.SqlQuery/contributors"
+ }
+ ],
+ "description": "Object-oriented query builders for MySQL, Postgres, SQLite, and SQLServer; can be used with any database connection library.",
+ "homepage": "https://github.com/auraphp/Aura.SqlQuery",
+ "keywords": [
+ "database",
+ "db",
+ "delete",
+ "dml",
+ "insert",
+ "mysql",
+ "pdo",
+ "pgsql",
+ "postgres",
+ "postgresql",
+ "query",
+ "select",
+ "sql",
+ "sql server",
+ "sqlite",
+ "sqlserver",
+ "update"
+ ],
+ "support": {
+ "issues": "https://github.com/auraphp/Aura.SqlQuery/issues",
+ "source": "https://github.com/auraphp/Aura.SqlQuery/tree/2.8.0"
+ },
+ "time": "2022-05-21T13:30:53+00:00"
+ },
{
"name": "defuse/php-encryption",
"version": "v2.3.1",
@@ -124,16 +195,16 @@
},
{
"name": "doctrine/annotations",
- "version": "1.13.2",
+ "version": "1.13.3",
"source": {
"type": "git",
"url": "https://github.com/doctrine/annotations.git",
- "reference": "5b668aef16090008790395c02c893b1ba13f7e08"
+ "reference": "648b0343343565c4a056bfc8392201385e8d89f0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/annotations/zipball/5b668aef16090008790395c02c893b1ba13f7e08",
- "reference": "5b668aef16090008790395c02c893b1ba13f7e08",
+ "url": "https://api.github.com/repos/doctrine/annotations/zipball/648b0343343565c4a056bfc8392201385e8d89f0",
+ "reference": "648b0343343565c4a056bfc8392201385e8d89f0",
"shasum": ""
},
"require": {
@@ -145,9 +216,10 @@
"require-dev": {
"doctrine/cache": "^1.11 || ^2.0",
"doctrine/coding-standard": "^6.0 || ^8.1",
- "phpstan/phpstan": "^0.12.20",
+ "phpstan/phpstan": "^1.4.10 || ^1.8.0",
"phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5",
- "symfony/cache": "^4.4 || ^5.2"
+ "symfony/cache": "^4.4 || ^5.2",
+ "vimeo/psalm": "^4.10"
},
"type": "library",
"autoload": {
@@ -190,9 +262,9 @@
],
"support": {
"issues": "https://github.com/doctrine/annotations/issues",
- "source": "https://github.com/doctrine/annotations/tree/1.13.2"
+ "source": "https://github.com/doctrine/annotations/tree/1.13.3"
},
- "time": "2021-08-05T19:00:23+00:00"
+ "time": "2022-07-02T10:48:51+00:00"
},
{
"name": "doctrine/cache",
@@ -295,26 +367,27 @@
},
{
"name": "doctrine/collections",
- "version": "1.6.8",
+ "version": "1.8.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/collections.git",
- "reference": "1958a744696c6bb3bb0d28db2611dc11610e78af"
+ "reference": "2b44dd4cbca8b5744327de78bafef5945c7e7b5e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/collections/zipball/1958a744696c6bb3bb0d28db2611dc11610e78af",
- "reference": "1958a744696c6bb3bb0d28db2611dc11610e78af",
+ "url": "https://api.github.com/repos/doctrine/collections/zipball/2b44dd4cbca8b5744327de78bafef5945c7e7b5e",
+ "reference": "2b44dd4cbca8b5744327de78bafef5945c7e7b5e",
"shasum": ""
},
"require": {
+ "doctrine/deprecations": "^0.5.3 || ^1",
"php": "^7.1.3 || ^8.0"
},
"require-dev": {
- "doctrine/coding-standard": "^9.0",
- "phpstan/phpstan": "^0.12",
+ "doctrine/coding-standard": "^9.0 || ^10.0",
+ "phpstan/phpstan": "^1.4.8",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.1.5",
- "vimeo/psalm": "^4.2.1"
+ "vimeo/psalm": "^4.22"
},
"type": "library",
"autoload": {
@@ -358,9 +431,9 @@
],
"support": {
"issues": "https://github.com/doctrine/collections/issues",
- "source": "https://github.com/doctrine/collections/tree/1.6.8"
+ "source": "https://github.com/doctrine/collections/tree/1.8.0"
},
- "time": "2021-08-10T18:51:53+00:00"
+ "time": "2022-09-01T20:12:10+00:00"
},
{
"name": "doctrine/common",
@@ -464,38 +537,79 @@
"time": "2020-06-05T16:46:05+00:00"
},
{
- "name": "doctrine/event-manager",
- "version": "1.1.1",
+ "name": "doctrine/deprecations",
+ "version": "v1.0.0",
"source": {
"type": "git",
- "url": "https://github.com/doctrine/event-manager.git",
- "reference": "41370af6a30faa9dc0368c4a6814d596e81aba7f"
+ "url": "https://github.com/doctrine/deprecations.git",
+ "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/event-manager/zipball/41370af6a30faa9dc0368c4a6814d596e81aba7f",
- "reference": "41370af6a30faa9dc0368c4a6814d596e81aba7f",
+ "url": "https://api.github.com/repos/doctrine/deprecations/zipball/0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de",
+ "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de",
"shasum": ""
},
"require": {
+ "php": "^7.1|^8.0"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^9",
+ "phpunit/phpunit": "^7.5|^8.5|^9.5",
+ "psr/log": "^1|^2|^3"
+ },
+ "suggest": {
+ "psr/log": "Allows logging deprecations via PSR-3 logger implementation"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.",
+ "homepage": "https://www.doctrine-project.org/",
+ "support": {
+ "issues": "https://github.com/doctrine/deprecations/issues",
+ "source": "https://github.com/doctrine/deprecations/tree/v1.0.0"
+ },
+ "time": "2022-05-02T15:47:09+00:00"
+ },
+ {
+ "name": "doctrine/event-manager",
+ "version": "1.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/event-manager.git",
+ "reference": "95aa4cb529f1e96576f3fda9f5705ada4056a520"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/event-manager/zipball/95aa4cb529f1e96576f3fda9f5705ada4056a520",
+ "reference": "95aa4cb529f1e96576f3fda9f5705ada4056a520",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/deprecations": "^0.5.3 || ^1",
"php": "^7.1 || ^8.0"
},
"conflict": {
- "doctrine/common": "<2.9@dev"
+ "doctrine/common": "<2.9"
},
"require-dev": {
- "doctrine/coding-standard": "^6.0",
- "phpunit/phpunit": "^7.0"
+ "doctrine/coding-standard": "^9 || ^10",
+ "phpstan/phpstan": "~1.4.10 || ^1.8.8",
+ "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
+ "vimeo/psalm": "^4.24"
},
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0.x-dev"
- }
- },
"autoload": {
"psr-4": {
- "Doctrine\\Common\\": "lib/Doctrine/Common"
+ "Doctrine\\Common\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -539,7 +653,7 @@
],
"support": {
"issues": "https://github.com/doctrine/event-manager/issues",
- "source": "https://github.com/doctrine/event-manager/tree/1.1.x"
+ "source": "https://github.com/doctrine/event-manager/tree/1.2.0"
},
"funding": [
{
@@ -555,7 +669,7 @@
"type": "tidelift"
}
],
- "time": "2020-05-29T18:28:51+00:00"
+ "time": "2022-10-12T20:51:15+00:00"
},
{
"name": "doctrine/inflector",
@@ -1026,16 +1140,16 @@
},
{
"name": "guzzlehttp/promises",
- "version": "1.5.1",
+ "version": "1.5.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
- "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da"
+ "reference": "b94b2807d85443f9719887892882d0329d1e2598"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/promises/zipball/fe752aedc9fd8fcca3fe7ad05d419d32998a06da",
- "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/b94b2807d85443f9719887892882d0329d1e2598",
+ "reference": "b94b2807d85443f9719887892882d0329d1e2598",
"shasum": ""
},
"require": {
@@ -1090,7 +1204,7 @@
],
"support": {
"issues": "https://github.com/guzzle/promises/issues",
- "source": "https://github.com/guzzle/promises/tree/1.5.1"
+ "source": "https://github.com/guzzle/promises/tree/1.5.2"
},
"funding": [
{
@@ -1106,7 +1220,7 @@
"type": "tidelift"
}
],
- "time": "2021-10-22T20:56:57+00:00"
+ "time": "2022-08-28T14:55:35+00:00"
},
{
"name": "guzzlehttp/psr7",
@@ -1415,16 +1529,16 @@
},
{
"name": "laminas/laminas-zendframework-bridge",
- "version": "1.5.0",
+ "version": "1.6.1",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-zendframework-bridge.git",
- "reference": "7f049390b756d34ba5940a8fb47634fbb51f79ab"
+ "reference": "e112dd2c099f4f6142c16fc65fda89a638e06885"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/7f049390b756d34ba5940a8fb47634fbb51f79ab",
- "reference": "7f049390b756d34ba5940a8fb47634fbb51f79ab",
+ "url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/e112dd2c099f4f6142c16fc65fda89a638e06885",
+ "reference": "e112dd2c099f4f6142c16fc65fda89a638e06885",
"shasum": ""
},
"require": {
@@ -1473,29 +1587,30 @@
"type": "community_bridge"
}
],
- "time": "2022-02-22T22:17:01+00:00"
+ "time": "2022-07-29T13:28:29+00:00"
},
{
"name": "laravel/serializable-closure",
- "version": "v1.2.0",
+ "version": "v1.2.2",
"source": {
"type": "git",
"url": "https://github.com/laravel/serializable-closure.git",
- "reference": "09f0e9fb61829f628205b7c94906c28740ff9540"
+ "reference": "47afb7fae28ed29057fdca37e16a84f90cc62fae"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/09f0e9fb61829f628205b7c94906c28740ff9540",
- "reference": "09f0e9fb61829f628205b7c94906c28740ff9540",
+ "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/47afb7fae28ed29057fdca37e16a84f90cc62fae",
+ "reference": "47afb7fae28ed29057fdca37e16a84f90cc62fae",
"shasum": ""
},
"require": {
"php": "^7.3|^8.0"
},
"require-dev": {
- "pestphp/pest": "^1.18",
- "phpstan/phpstan": "^0.12.98",
- "symfony/var-dumper": "^5.3"
+ "nesbot/carbon": "^2.61",
+ "pestphp/pest": "^1.21.3",
+ "phpstan/phpstan": "^1.8.2",
+ "symfony/var-dumper": "^5.4.11"
},
"type": "library",
"extra": {
@@ -1532,7 +1647,7 @@
"issues": "https://github.com/laravel/serializable-closure/issues",
"source": "https://github.com/laravel/serializable-closure"
},
- "time": "2022-05-16T17:09:47+00:00"
+ "time": "2022-09-08T13:45:54+00:00"
},
{
"name": "league/fractal",
@@ -2067,16 +2182,16 @@
},
{
"name": "phpmailer/phpmailer",
- "version": "v6.6.3",
+ "version": "v6.6.5",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
- "reference": "9400f305a898f194caff5521f64e5dfa926626f3"
+ "reference": "8b6386d7417526d1ea4da9edb70b8352f7543627"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/9400f305a898f194caff5521f64e5dfa926626f3",
- "reference": "9400f305a898f194caff5521f64e5dfa926626f3",
+ "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/8b6386d7417526d1ea4da9edb70b8352f7543627",
+ "reference": "8b6386d7417526d1ea4da9edb70b8352f7543627",
"shasum": ""
},
"require": {
@@ -2100,8 +2215,8 @@
"hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication",
"league/oauth2-google": "Needed for Google XOAUTH2 authentication",
"psr/log": "For optional PSR-3 debug logging",
- "stevenmaguire/oauth2-microsoft": "Needed for Microsoft XOAUTH2 authentication",
- "symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)"
+ "symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)",
+ "thenetworg/oauth2-azure": "Needed for Microsoft XOAUTH2 authentication"
},
"type": "library",
"autoload": {
@@ -2133,7 +2248,7 @@
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"support": {
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
- "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.6.3"
+ "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.6.5"
},
"funding": [
{
@@ -2141,33 +2256,37 @@
"type": "github"
}
],
- "time": "2022-06-20T09:21:02+00:00"
+ "time": "2022-10-07T12:23:10+00:00"
},
{
"name": "phpoption/phpoption",
- "version": "1.8.1",
+ "version": "1.9.0",
"source": {
"type": "git",
"url": "https://github.com/schmittjoh/php-option.git",
- "reference": "eab7a0df01fe2344d172bff4cd6dbd3f8b84ad15"
+ "reference": "dc5ff11e274a90cc1c743f66c9ad700ce50db9ab"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/eab7a0df01fe2344d172bff4cd6dbd3f8b84ad15",
- "reference": "eab7a0df01fe2344d172bff4cd6dbd3f8b84ad15",
+ "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/dc5ff11e274a90cc1c743f66c9ad700ce50db9ab",
+ "reference": "dc5ff11e274a90cc1c743f66c9ad700ce50db9ab",
"shasum": ""
},
"require": {
- "php": "^7.0 || ^8.0"
+ "php": "^7.2.5 || ^8.0"
},
"require-dev": {
- "bamarni/composer-bin-plugin": "^1.4.1",
- "phpunit/phpunit": "^6.5.14 || ^7.5.20 || ^8.5.19 || ^9.5.8"
+ "bamarni/composer-bin-plugin": "^1.8",
+ "phpunit/phpunit": "^8.5.28 || ^9.5.21"
},
"type": "library",
"extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
+ },
"branch-alias": {
- "dev-master": "1.8-dev"
+ "dev-master": "1.9-dev"
}
},
"autoload": {
@@ -2200,7 +2319,7 @@
],
"support": {
"issues": "https://github.com/schmittjoh/php-option/issues",
- "source": "https://github.com/schmittjoh/php-option/tree/1.8.1"
+ "source": "https://github.com/schmittjoh/php-option/tree/1.9.0"
},
"funding": [
{
@@ -2212,20 +2331,20 @@
"type": "tidelift"
}
],
- "time": "2021-12-04T23:24:31+00:00"
+ "time": "2022-07-30T15:51:26+00:00"
},
{
"name": "phpseclib/phpseclib",
- "version": "2.0.37",
+ "version": "2.0.39",
"source": {
"type": "git",
"url": "https://github.com/phpseclib/phpseclib.git",
- "reference": "c812fbb4d6b4d7f30235ab7298a12f09ba13b37c"
+ "reference": "f3a0e2b715c40cf1fd270d444901b63311725d63"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/c812fbb4d6b4d7f30235ab7298a12f09ba13b37c",
- "reference": "c812fbb4d6b4d7f30235ab7298a12f09ba13b37c",
+ "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/f3a0e2b715c40cf1fd270d444901b63311725d63",
+ "reference": "f3a0e2b715c40cf1fd270d444901b63311725d63",
"shasum": ""
},
"require": {
@@ -2240,7 +2359,8 @@
"ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
"ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
- "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
+ "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations.",
+ "ext-xml": "Install the XML extension to load XML formatted public keys."
},
"type": "library",
"autoload": {
@@ -2305,7 +2425,7 @@
],
"support": {
"issues": "https://github.com/phpseclib/phpseclib/issues",
- "source": "https://github.com/phpseclib/phpseclib/tree/2.0.37"
+ "source": "https://github.com/phpseclib/phpseclib/tree/2.0.39"
},
"funding": [
{
@@ -2321,7 +2441,7 @@
"type": "tidelift"
}
],
- "time": "2022-04-04T04:57:45+00:00"
+ "time": "2022-10-24T10:49:03+00:00"
},
{
"name": "psr/cache",
@@ -2569,16 +2689,16 @@
},
{
"name": "symfony/console",
- "version": "v5.4.9",
+ "version": "v5.4.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "829d5d1bf60b2efeb0887b7436873becc71a45eb"
+ "reference": "ea59bb0edfaf9f28d18d8791410ee0355f317669"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/829d5d1bf60b2efeb0887b7436873becc71a45eb",
- "reference": "829d5d1bf60b2efeb0887b7436873becc71a45eb",
+ "url": "https://api.github.com/repos/symfony/console/zipball/ea59bb0edfaf9f28d18d8791410ee0355f317669",
+ "reference": "ea59bb0edfaf9f28d18d8791410ee0355f317669",
"shasum": ""
},
"require": {
@@ -2648,7 +2768,7 @@
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v5.4.9"
+ "source": "https://github.com/symfony/console/tree/v5.4.15"
},
"funding": [
{
@@ -2664,11 +2784,11 @@
"type": "tidelift"
}
],
- "time": "2022-05-18T06:17:34+00:00"
+ "time": "2022-10-26T21:41:52+00:00"
},
{
"name": "symfony/deprecation-contracts",
- "version": "v2.5.1",
+ "version": "v2.5.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
@@ -2715,7 +2835,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.1"
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2"
},
"funding": [
{
@@ -2735,16 +2855,16 @@
},
{
"name": "symfony/lock",
- "version": "v5.4.7",
+ "version": "v5.4.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/lock.git",
- "reference": "a16279554621453840eb8af14d12cfa24c10b8d3"
+ "reference": "109a20faa6119578b46457ef8cffb9389e20e5ca"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/lock/zipball/a16279554621453840eb8af14d12cfa24c10b8d3",
- "reference": "a16279554621453840eb8af14d12cfa24c10b8d3",
+ "url": "https://api.github.com/repos/symfony/lock/zipball/109a20faa6119578b46457ef8cffb9389e20e5ca",
+ "reference": "109a20faa6119578b46457ef8cffb9389e20e5ca",
"shasum": ""
},
"require": {
@@ -2794,7 +2914,7 @@
"semaphore"
],
"support": {
- "source": "https://github.com/symfony/lock/tree/v5.4.7"
+ "source": "https://github.com/symfony/lock/tree/v5.4.15"
},
"funding": [
{
@@ -2810,7 +2930,7 @@
"type": "tidelift"
}
],
- "time": "2022-03-22T15:31:03+00:00"
+ "time": "2022-10-27T07:55:40+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -3469,16 +3589,16 @@
},
{
"name": "symfony/service-contracts",
- "version": "v2.5.1",
+ "version": "v2.5.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
- "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c"
+ "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/service-contracts/zipball/24d9dc654b83e91aa59f9d167b131bc3b5bea24c",
- "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
+ "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
"shasum": ""
},
"require": {
@@ -3532,7 +3652,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/service-contracts/tree/v2.5.1"
+ "source": "https://github.com/symfony/service-contracts/tree/v2.5.2"
},
"funding": [
{
@@ -3548,20 +3668,20 @@
"type": "tidelift"
}
],
- "time": "2022-03-13T20:07:29+00:00"
+ "time": "2022-05-30T19:17:29+00:00"
},
{
"name": "symfony/string",
- "version": "v5.4.9",
+ "version": "v5.4.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "985e6a9703ef5ce32ba617c9c7d97873bb7b2a99"
+ "reference": "571334ce9f687e3e6af72db4d3b2a9431e4fd9ed"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/985e6a9703ef5ce32ba617c9c7d97873bb7b2a99",
- "reference": "985e6a9703ef5ce32ba617c9c7d97873bb7b2a99",
+ "url": "https://api.github.com/repos/symfony/string/zipball/571334ce9f687e3e6af72db4d3b2a9431e4fd9ed",
+ "reference": "571334ce9f687e3e6af72db4d3b2a9431e4fd9ed",
"shasum": ""
},
"require": {
@@ -3618,7 +3738,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v5.4.9"
+ "source": "https://github.com/symfony/string/tree/v5.4.15"
},
"funding": [
{
@@ -3634,20 +3754,20 @@
"type": "tidelift"
}
],
- "time": "2022-04-19T10:40:37+00:00"
+ "time": "2022-10-05T15:16:54+00:00"
},
{
"name": "vlucas/phpdotenv",
- "version": "v4.2.2",
+ "version": "v4.3.0",
"source": {
"type": "git",
"url": "https://github.com/vlucas/phpdotenv.git",
- "reference": "77e974614d2ead521f18069dccc571696f52b8dc"
+ "reference": "67a491df68208bef8c37092db11fa3885008efcf"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/77e974614d2ead521f18069dccc571696f52b8dc",
- "reference": "77e974614d2ead521f18069dccc571696f52b8dc",
+ "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/67a491df68208bef8c37092db11fa3885008efcf",
+ "reference": "67a491df68208bef8c37092db11fa3885008efcf",
"shasum": ""
},
"require": {
@@ -3659,7 +3779,7 @@
"bamarni/composer-bin-plugin": "^1.4.1",
"ext-filter": "*",
"ext-pcre": "*",
- "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.21"
+ "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.30"
},
"suggest": {
"ext-filter": "Required to use the boolean validator.",
@@ -3667,8 +3787,12 @@
},
"type": "library",
"extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
+ },
"branch-alias": {
- "dev-master": "4.2-dev"
+ "dev-master": "4.3-dev"
}
},
"autoload": {
@@ -3700,7 +3824,7 @@
],
"support": {
"issues": "https://github.com/vlucas/phpdotenv/issues",
- "source": "https://github.com/vlucas/phpdotenv/tree/v4.2.2"
+ "source": "https://github.com/vlucas/phpdotenv/tree/v4.3.0"
},
"funding": [
{
@@ -3712,7 +3836,7 @@
"type": "tidelift"
}
],
- "time": "2021-12-12T23:07:53+00:00"
+ "time": "2022-10-16T00:51:09+00:00"
},
{
"name": "webimpress/safe-writer",
@@ -3777,16 +3901,16 @@
"packages-dev": [
{
"name": "dg/bypass-finals",
- "version": "v1.3.1",
+ "version": "v1.4.1",
"source": {
"type": "git",
"url": "https://github.com/dg/bypass-finals.git",
- "reference": "495f5bc762e7bf30a13ed8253f44bb3a701767bb"
+ "reference": "4c424c3ed359220fce044f35cdf9f48b0089b2ca"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/dg/bypass-finals/zipball/495f5bc762e7bf30a13ed8253f44bb3a701767bb",
- "reference": "495f5bc762e7bf30a13ed8253f44bb3a701767bb",
+ "url": "https://api.github.com/repos/dg/bypass-finals/zipball/4c424c3ed359220fce044f35cdf9f48b0089b2ca",
+ "reference": "4c424c3ed359220fce044f35cdf9f48b0089b2ca",
"shasum": ""
},
"require": {
@@ -3824,9 +3948,9 @@
],
"support": {
"issues": "https://github.com/dg/bypass-finals/issues",
- "source": "https://github.com/dg/bypass-finals/tree/v1.3.1"
+ "source": "https://github.com/dg/bypass-finals/tree/v1.4.1"
},
- "time": "2021-04-09T10:42:55+00:00"
+ "time": "2022-09-13T17:27:26+00:00"
},
{
"name": "doctrine/instantiator",
@@ -4117,16 +4241,16 @@
},
{
"name": "nikic/php-parser",
- "version": "v4.14.0",
+ "version": "v4.15.1",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1"
+ "reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/34bea19b6e03d8153165d8f30bba4c3be86184c1",
- "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
+ "reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
"shasum": ""
},
"require": {
@@ -4167,9 +4291,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
- "source": "https://github.com/nikic/PHP-Parser/tree/v4.14.0"
+ "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1"
},
- "time": "2022-05-31T20:59:12+00:00"
+ "time": "2022-09-04T07:30:47+00:00"
},
{
"name": "phar-io/manifest",
@@ -4282,252 +4406,25 @@
},
"time": "2022-02-21T01:04:05+00:00"
},
- {
- "name": "phpdocumentor/reflection-common",
- "version": "2.2.0",
- "source": {
- "type": "git",
- "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
- "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b",
- "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b",
- "shasum": ""
- },
- "require": {
- "php": "^7.2 || ^8.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-2.x": "2.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "phpDocumentor\\Reflection\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Jaap van Otterdijk",
- "email": "opensource@ijaap.nl"
- }
- ],
- "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
- "homepage": "http://www.phpdoc.org",
- "keywords": [
- "FQSEN",
- "phpDocumentor",
- "phpdoc",
- "reflection",
- "static analysis"
- ],
- "support": {
- "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues",
- "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x"
- },
- "time": "2020-06-27T09:03:43+00:00"
- },
- {
- "name": "phpdocumentor/reflection-docblock",
- "version": "5.3.0",
- "source": {
- "type": "git",
- "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
- "reference": "622548b623e81ca6d78b721c5e029f4ce664f170"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170",
- "reference": "622548b623e81ca6d78b721c5e029f4ce664f170",
- "shasum": ""
- },
- "require": {
- "ext-filter": "*",
- "php": "^7.2 || ^8.0",
- "phpdocumentor/reflection-common": "^2.2",
- "phpdocumentor/type-resolver": "^1.3",
- "webmozart/assert": "^1.9.1"
- },
- "require-dev": {
- "mockery/mockery": "~1.3.2",
- "psalm/phar": "^4.8"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "5.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "phpDocumentor\\Reflection\\": "src"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Mike van Riel",
- "email": "me@mikevanriel.com"
- },
- {
- "name": "Jaap van Otterdijk",
- "email": "account@ijaap.nl"
- }
- ],
- "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
- "support": {
- "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
- "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0"
- },
- "time": "2021-10-19T17:43:47+00:00"
- },
- {
- "name": "phpdocumentor/type-resolver",
- "version": "1.6.1",
- "source": {
- "type": "git",
- "url": "https://github.com/phpDocumentor/TypeResolver.git",
- "reference": "77a32518733312af16a44300404e945338981de3"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3",
- "reference": "77a32518733312af16a44300404e945338981de3",
- "shasum": ""
- },
- "require": {
- "php": "^7.2 || ^8.0",
- "phpdocumentor/reflection-common": "^2.0"
- },
- "require-dev": {
- "ext-tokenizer": "*",
- "psalm/phar": "^4.8"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-1.x": "1.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "phpDocumentor\\Reflection\\": "src"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Mike van Riel",
- "email": "me@mikevanriel.com"
- }
- ],
- "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
- "support": {
- "issues": "https://github.com/phpDocumentor/TypeResolver/issues",
- "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1"
- },
- "time": "2022-03-15T21:29:03+00:00"
- },
- {
- "name": "phpspec/prophecy",
- "version": "v1.15.0",
- "source": {
- "type": "git",
- "url": "https://github.com/phpspec/prophecy.git",
- "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13",
- "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13",
- "shasum": ""
- },
- "require": {
- "doctrine/instantiator": "^1.2",
- "php": "^7.2 || ~8.0, <8.2",
- "phpdocumentor/reflection-docblock": "^5.2",
- "sebastian/comparator": "^3.0 || ^4.0",
- "sebastian/recursion-context": "^3.0 || ^4.0"
- },
- "require-dev": {
- "phpspec/phpspec": "^6.0 || ^7.0",
- "phpunit/phpunit": "^8.0 || ^9.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Prophecy\\": "src/Prophecy"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Konstantin Kudryashov",
- "email": "ever.zet@gmail.com",
- "homepage": "http://everzet.com"
- },
- {
- "name": "Marcello Duarte",
- "email": "marcello.duarte@gmail.com"
- }
- ],
- "description": "Highly opinionated mocking framework for PHP 5.3+",
- "homepage": "https://github.com/phpspec/prophecy",
- "keywords": [
- "Double",
- "Dummy",
- "fake",
- "mock",
- "spy",
- "stub"
- ],
- "support": {
- "issues": "https://github.com/phpspec/prophecy/issues",
- "source": "https://github.com/phpspec/prophecy/tree/v1.15.0"
- },
- "time": "2021-12-08T12:19:24+00:00"
- },
{
"name": "phpunit/php-code-coverage",
- "version": "9.2.15",
+ "version": "9.2.18",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f"
+ "reference": "12fddc491826940cf9b7e88ad9664cf51f0f6d0a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2e9da11878c4202f97915c1cb4bb1ca318a63f5f",
- "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/12fddc491826940cf9b7e88ad9664cf51f0f6d0a",
+ "reference": "12fddc491826940cf9b7e88ad9664cf51f0f6d0a",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-xmlwriter": "*",
- "nikic/php-parser": "^4.13.0",
+ "nikic/php-parser": "^4.14",
"php": ">=7.3",
"phpunit/php-file-iterator": "^3.0.3",
"phpunit/php-text-template": "^2.0.2",
@@ -4576,7 +4473,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
- "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.15"
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.18"
},
"funding": [
{
@@ -4584,7 +4481,7 @@
"type": "github"
}
],
- "time": "2022-03-07T09:28:20+00:00"
+ "time": "2022-10-27T13:35:33+00:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -4829,16 +4726,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "9.5.21",
+ "version": "9.5.26",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "0e32b76be457de00e83213528f6bb37e2a38fcb1"
+ "reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0e32b76be457de00e83213528f6bb37e2a38fcb1",
- "reference": "0e32b76be457de00e83213528f6bb37e2a38fcb1",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/851867efcbb6a1b992ec515c71cdcf20d895e9d2",
+ "reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2",
"shasum": ""
},
"require": {
@@ -4853,7 +4750,6 @@
"phar-io/manifest": "^2.0.3",
"phar-io/version": "^3.0.2",
"php": ">=7.3",
- "phpspec/prophecy": "^1.12.1",
"phpunit/php-code-coverage": "^9.2.13",
"phpunit/php-file-iterator": "^3.0.5",
"phpunit/php-invoker": "^3.1.1",
@@ -4861,19 +4757,16 @@
"phpunit/php-timer": "^5.0.2",
"sebastian/cli-parser": "^1.0.1",
"sebastian/code-unit": "^1.0.6",
- "sebastian/comparator": "^4.0.5",
+ "sebastian/comparator": "^4.0.8",
"sebastian/diff": "^4.0.3",
"sebastian/environment": "^5.1.3",
- "sebastian/exporter": "^4.0.3",
+ "sebastian/exporter": "^4.0.5",
"sebastian/global-state": "^5.0.1",
"sebastian/object-enumerator": "^4.0.3",
"sebastian/resource-operations": "^3.0.3",
- "sebastian/type": "^3.0",
+ "sebastian/type": "^3.2",
"sebastian/version": "^3.0.2"
},
- "require-dev": {
- "phpspec/prophecy-phpunit": "^2.0.1"
- },
"suggest": {
"ext-soap": "*",
"ext-xdebug": "*"
@@ -4915,7 +4808,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.21"
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.26"
},
"funding": [
{
@@ -4925,9 +4818,13 @@
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
+ "type": "tidelift"
}
],
- "time": "2022-06-19T12:14:25+00:00"
+ "time": "2022-10-28T06:00:21+00:00"
},
{
"name": "roave/security-advisories",
@@ -4935,18 +4832,19 @@
"source": {
"type": "git",
"url": "https://github.com/Roave/SecurityAdvisories.git",
- "reference": "880f953435f266cf634bb81fa8888e66fa7814f6"
+ "reference": "3adb9cc9ab821d31bcb426ee3cad4c865899349a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/880f953435f266cf634bb81fa8888e66fa7814f6",
- "reference": "880f953435f266cf634bb81fa8888e66fa7814f6",
+ "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/3adb9cc9ab821d31bcb426ee3cad4c865899349a",
+ "reference": "3adb9cc9ab821d31bcb426ee3cad4c865899349a",
"shasum": ""
},
"conflict": {
"3f/pygmentize": "<1.2",
"admidio/admidio": "<4.1.9",
"adodb/adodb-php": "<=5.20.20|>=5.21,<=5.21.3",
+ "aheinze/cockpit": "<=2.2.1",
"akaunting/akaunting": "<2.1.13",
"alextselegidis/easyappointments": "<=1.4.3",
"alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1",
@@ -4960,7 +4858,9 @@
"appwrite/server-ce": "<0.11.1|>=0.12,<0.12.2",
"area17/twill": "<1.2.5|>=2,<2.5.3",
"asymmetricrypt/asymmetricrypt": ">=0,<9.9.99",
+ "awesome-support/awesome-support": "<=6.0.7",
"aws/aws-sdk-php": ">=3,<3.2.1",
+ "badaso/core": "<2.6.1",
"bagisto/bagisto": "<0.1.5",
"barrelstrength/sprout-base-email": "<1.2.7",
"barrelstrength/sprout-forms": "<3.9",
@@ -4985,24 +4885,25 @@
"cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4",
"cartalyst/sentry": "<=2.1.6",
"catfan/medoo": "<1.7.5",
- "centreon/centreon": "<20.10.7",
+ "centreon/centreon": "<21.4.16|>=21.10,<21.10.8|>=22,<22.4.1",
"cesnet/simplesamlphp-module-proxystatistics": "<3.1",
"codeception/codeception": "<3.1.3|>=4,<4.1.22",
"codeigniter/framework": "<=3.0.6",
- "codeigniter4/framework": "<4.1.9",
+ "codeigniter4/framework": "<4.2.7",
+ "codeigniter4/shield": "= 1.0.0-beta",
"codiad/codiad": "<=2.8.4",
"composer/composer": "<1.10.26|>=2-alpha.1,<2.2.12|>=2.3,<2.3.5",
"concrete5/concrete5": "<9",
- "concrete5/core": "<8.5.7",
+ "concrete5/core": "<8.5.8|>=9,<9.1",
"contao-components/mediaelement": ">=2.14.2,<2.21.1",
"contao/contao": ">=4,<4.4.56|>=4.5,<4.9.18|>=4.10,<4.11.7|>=4.13,<4.13.3",
"contao/core": ">=2,<3.5.39",
"contao/core-bundle": "<4.9.18|>=4.10,<4.11.7|>=4.13,<4.13.3|= 4.10.0",
"contao/listing-bundle": ">=4,<4.4.8",
"contao/managed-edition": "<=1.5",
- "craftcms/cms": "<3.7.36",
+ "craftcms/cms": "<3.7.55.2|>= 4.0.0-RC1, < 4.2.1",
"croogo/croogo": "<3.0.7",
- "cuyz/valinor": ">=0.5,<0.7",
+ "cuyz/valinor": "<0.12",
"czproject/git-php": "<4.0.3",
"darylldoyle/safe-svg": "<1.9.10",
"datadog/dd-trace": ">=0.30,<0.30.2",
@@ -5019,17 +4920,20 @@
"doctrine/mongodb-odm-bundle": ">=2,<3.0.1",
"doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4",
"dolibarr/dolibarr": "<16|= 12.0.5|>= 3.3.beta1, < 13.0.2",
- "dompdf/dompdf": "<1.2.1",
- "drupal/core": ">=7,<7.88|>=8,<9.2.13|>=9.3,<9.3.6",
+ "dompdf/dompdf": "<2.0.1",
+ "drupal/core": ">=7,<7.91|>=8,<9.3.19|>=9.4,<9.4.3",
"drupal/drupal": ">=7,<7.80|>=8,<8.9.16|>=9,<9.1.12|>=9.2,<9.2.4",
"dweeves/magmi": "<=0.7.24",
"ecodev/newsletter": "<=4",
"ectouch/ectouch": "<=2.7.2",
+ "elefant/cms": "<1.3.13",
"elgg/elgg": "<3.3.24|>=4,<4.0.5",
"endroid/qr-code-bundle": "<3.4.2",
"enshrined/svg-sanitize": "<0.15",
"erusev/parsedown": "<1.7.2",
"ether/logs": "<3.0.4",
+ "exceedone/exment": "<4.4.3|>=5,<5.0.3",
+ "exceedone/laravel-admin": "= 3.0.0|<2.2.3",
"ezsystems/demobundle": ">=5.4,<5.4.6.1",
"ezsystems/ez-support-tools": ">=2.2,<2.2.3",
"ezsystems/ezdemo-ls-extension": ">=5.4,<5.4.2.1",
@@ -5049,7 +4953,7 @@
"facade/ignition": "<1.16.15|>=2,<2.4.2|>=2.5,<2.5.2",
"facturascripts/facturascripts": "<=2022.8",
"feehi/cms": "<=2.1.1",
- "feehi/feehicms": "<=0.1.3",
+ "feehi/feehicms": "<=2.0.1.1",
"fenom/fenom": "<=2.12.1",
"filegator/filegator": "<7.8",
"firebase/php-jwt": "<2",
@@ -5057,23 +4961,25 @@
"flarum/sticky": ">=0.1-beta.14,<=0.1-beta.15",
"flarum/tags": "<=0.1-beta.13",
"fluidtypo3/vhs": "<5.1.1",
+ "fof/byobu": ">=0.3-beta.2,<1.1.7",
"fof/upload": "<1.2.3",
"fooman/tcpdf": "<6.2.22",
"forkcms/forkcms": "<5.11.1",
"fossar/tcpdf-parser": "<6.2.22",
- "francoisjacquet/rosariosis": "<9.1",
+ "francoisjacquet/rosariosis": "<10.1",
"friendsofsymfony/oauth2-php": "<1.3",
"friendsofsymfony/rest-bundle": ">=1.2,<1.2.2",
"friendsofsymfony/user-bundle": ">=1.2,<1.3.5",
"friendsoftypo3/mediace": ">=7.6.2,<7.6.5",
"froala/wysiwyg-editor": "<3.2.7",
- "froxlor/froxlor": "<=0.10.22",
+ "froxlor/froxlor": "<0.10.38",
"fuel/core": "<1.8.1",
"gaoming13/wechat-php-sdk": "<=1.10.2",
"genix/cms": "<=1.1.11",
- "getgrav/grav": "<1.7.33",
- "getkirby/cms": "<3.5.8",
+ "getgrav/grav": "<1.7.34",
+ "getkirby/cms": "= 3.8.0|<3.5.8.2|>=3.6,<3.6.6.2|>=3.7,<3.7.5.1",
"getkirby/panel": "<2.5.14",
+ "getkirby/starterkit": "<=3.7.0.2",
"gilacms/gila": "<=1.11.4",
"globalpayments/php-sdk": "<2",
"google/protobuf": "<3.15",
@@ -5091,6 +4997,7 @@
"ibexa/core": ">=4,<4.0.7|>=4.1,<4.1.4",
"ibexa/post-install": "<=1.0.4",
"icecoder/icecoder": "<=8.1",
+ "idno/known": "<=1.3.1",
"illuminate/auth": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.10",
"illuminate/cookie": ">=4,<=4.0.11|>=4.1,<=4.1.99999|>=4.2,<=4.2.99999|>=5,<=5.0.99999|>=5.1,<=5.1.99999|>=5.2,<=5.2.99999|>=5.3,<=5.3.99999|>=5.4,<=5.4.99999|>=5.5,<=5.5.49|>=5.6,<=5.6.99999|>=5.7,<=5.7.99999|>=5.8,<=5.8.99999|>=6,<6.18.31|>=7,<7.22.4",
"illuminate/database": "<6.20.26|>=7,<7.30.5|>=8,<8.40",
@@ -5098,7 +5005,9 @@
"illuminate/view": "<6.20.42|>=7,<7.30.6|>=8,<8.75",
"impresscms/impresscms": "<=1.4.3",
"in2code/femanager": "<5.5.1|>=6,<6.3.1",
+ "in2code/lux": "<17.6.1|>=18,<24.0.2",
"intelliants/subrion": "<=4.2.1",
+ "islandora/islandora": ">=2,<2.4.1",
"ivankristianto/phpwhois": "<=4.3",
"jackalope/jackalope-doctrine-dbal": "<1.7.4",
"james-heinrich/getid3": "<1.9.21",
@@ -5107,6 +5016,7 @@
"joomla/filter": "<1.4.4|>=2,<2.0.1",
"joomla/input": ">=2,<2.0.2",
"joomla/session": "<1.3.1",
+ "joyqi/hyper-down": "<=2.4.27",
"jsdecena/laracom": "<2.0.9",
"jsmitty12/phpwhois": "<5.1",
"kazist/phpwhois": "<=4.2.6",
@@ -5116,11 +5026,11 @@
"krayin/laravel-crm": "<1.2.2",
"kreait/firebase-php": ">=3.2,<3.8.1",
"la-haute-societe/tcpdf": "<6.2.22",
+ "laminas/laminas-diactoros": "<2.11.1",
"laminas/laminas-form": "<2.17.1|>=3,<3.0.2|>=3.1,<3.1.1",
"laminas/laminas-http": "<2.14.2",
"laravel/fortify": "<1.11.1",
"laravel/framework": "<6.20.42|>=7,<7.30.6|>=8,<8.75",
- "laravel/laravel": "<=9.1.8",
"laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10",
"latte/latte": "<2.10.8",
"lavalite/cms": "<=5.8",
@@ -5128,7 +5038,7 @@
"league/commonmark": "<0.18.3",
"league/flysystem": "<1.1.4|>=2,<2.1.1",
"lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3",
- "librenms/librenms": "<22.4",
+ "librenms/librenms": "<=22.8",
"limesurvey/limesurvey": "<3.27.19",
"livehelperchat/livehelperchat": "<=3.91",
"livewire/livewire": ">2.2.4,<2.2.6",
@@ -5143,7 +5053,11 @@
"matyhtf/framework": "<3.0.6",
"mautic/core": "<4.3|= 2.13.1",
"mediawiki/core": ">=1.27,<1.27.6|>=1.29,<1.29.3|>=1.30,<1.30.2|>=1.31,<1.31.9|>=1.32,<1.32.6|>=1.32.99,<1.33.3|>=1.33.99,<1.34.3|>=1.34.99,<1.35",
- "microweber/microweber": "<1.3",
+ "melisplatform/melis-asset-manager": "<5.0.1",
+ "melisplatform/melis-cms": "<5.0.1",
+ "melisplatform/melis-front": "<5.0.1",
+ "mezzio/mezzio-swoole": "<3.7|>=4,<4.3",
+ "microweber/microweber": "<=1.3.1",
"miniorange/miniorange-saml": "<1.4.3",
"mittwald/typo3_forum": "<1.2.1",
"modx/revolution": "<= 2.8.3-pl|<2.8",
@@ -5162,6 +5076,7 @@
"nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6",
"nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13",
"nilsteampassnet/teampass": "<=2.1.27.36",
+ "notrinos/notrinos-erp": "<=0.7",
"noumo/easyii": "<=0.9",
"nukeviet/nukeviet": "<4.5.2",
"nystudio107/craft-seomatic": "<3.4.12",
@@ -5170,7 +5085,7 @@
"october/cms": "= 1.1.1|= 1.0.471|= 1.0.469|>=1.0.319,<1.0.469",
"october/october": ">=1.0.319,<1.0.466|>=2.1,<2.1.12",
"october/rain": "<1.0.472|>=1.1,<1.1.2",
- "october/system": "<1.0.475|>=1.1,<1.1.11|>=2,<2.1.27",
+ "october/system": "<1.0.476|>=1.1,<1.1.12|>=2,<2.2.34|>=3,<3.0.66",
"onelogin/php-saml": "<2.10.4",
"oneup/uploader-bundle": "<1.9.3|>=2,<2.1.5",
"open-web-analytics/open-web-analytics": "<1.7.4",
@@ -5178,8 +5093,10 @@
"openid/php-openid": "<2.3",
"openmage/magento-lts": "<19.4.15|>=20,<20.0.13",
"orchid/platform": ">=9,<9.4.4",
+ "oro/commerce": ">=4.1,<5.0.6",
"oro/crm": ">=1.7,<1.7.4|>=3.1,<4.1.17|>=4.2,<4.2.7",
"oro/platform": ">=1.7,<1.7.4|>=3.1,<3.1.29|>=4.1,<4.1.17|>=4.2,<4.2.8",
+ "packbackbooks/lti-1-3-php-library": "<5",
"padraic/humbug_get_contents": "<1.1.2",
"pagarme/pagarme-php": ">=0,<3",
"pagekit/pagekit": "<=1.0.18",
@@ -5195,6 +5112,7 @@
"phpmailer/phpmailer": "<6.5",
"phpmussel/phpmussel": ">=1,<1.6",
"phpmyadmin/phpmyadmin": "<5.1.3",
+ "phpmyfaq/phpmyfaq": "<=3.1.7",
"phpoffice/phpexcel": "<1.8",
"phpoffice/phpspreadsheet": "<1.16",
"phpseclib/phpseclib": "<2.0.31|>=3,<3.0.7",
@@ -5203,16 +5121,16 @@
"phpwhois/phpwhois": "<=4.2.5",
"phpxmlrpc/extras": "<0.6.1",
"pimcore/data-hub": "<1.2.4",
- "pimcore/pimcore": "<10.4.4",
+ "pimcore/pimcore": "<10.5.9",
"pocketmine/bedrock-protocol": "<8.0.2",
- "pocketmine/pocketmine-mp": ">= 4.0.0-BETA5, < 4.4.2|<4.2.10",
+ "pocketmine/pocketmine-mp": "<4.7.2|>= 4.0.0-BETA5, < 4.4.2",
"pressbooks/pressbooks": "<5.18",
"prestashop/autoupgrade": ">=4,<4.10.1",
"prestashop/blockwishlist": ">=2,<2.1.1",
- "prestashop/contactform": ">1.0.1,<4.3",
+ "prestashop/contactform": ">=1.0.1,<4.3",
"prestashop/gamification": "<2.3.2",
- "prestashop/prestashop": ">=1.7,<=1.7.8.2",
- "prestashop/productcomments": ">=4,<4.2.1",
+ "prestashop/prestashop": ">=1.6.0.10,<1.7.8.7",
+ "prestashop/productcomments": "<5.0.2",
"prestashop/ps_emailsubscription": "<2.6.1",
"prestashop/ps_facetedsearch": "<3.4.1",
"prestashop/ps_linklist": "<3.1",
@@ -5224,6 +5142,8 @@
"pusher/pusher-php-server": "<2.2.1",
"pwweb/laravel-core": "<=0.3.6-beta",
"rainlab/debugbar-plugin": "<3.1",
+ "rankmath/seo-by-rank-math": "<=1.0.95",
+ "react/http": ">=0.7,<1.7",
"remdex/livehelperchat": "<3.99",
"rmccue/requests": ">=1.6,<1.8",
"robrichards/xmlseclibs": "<3.0.4",
@@ -5238,17 +5158,18 @@
"shopware/core": "<=6.4.9",
"shopware/platform": "<=6.4.9",
"shopware/production": "<=6.3.5.2",
- "shopware/shopware": "<5.7.12",
+ "shopware/shopware": "<=5.7.14",
"shopware/storefront": "<=6.4.8.1",
"shopxo/shopxo": "<2.2.6",
"showdoc/showdoc": "<2.10.4",
"silverstripe/admin": ">=1,<1.8.1",
- "silverstripe/assets": ">=1,<1.4.7|>=1.5,<1.5.2",
+ "silverstripe/assets": ">=1,<1.10.1",
"silverstripe/cms": "<4.3.6|>=4.4,<4.4.4",
"silverstripe/comments": ">=1.3,<1.9.99|>=2,<2.9.99|>=3,<3.1.1",
"silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3",
- "silverstripe/framework": "<4.10.1",
+ "silverstripe/framework": "<4.10.9",
"silverstripe/graphql": "<3.5.2|>=4-alpha.1,<4-alpha.2|= 4.0.0-alpha1",
+ "silverstripe/hybridsessions": ">=1,<2.4.1|>=2.5,<2.5.1",
"silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1",
"silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4",
"silverstripe/silverstripe-omnipay": "<2.5.2|>=3,<3.0.2|>=3.1,<3.1.4|>=3.2,<3.2.1",
@@ -5261,8 +5182,8 @@
"simplesamlphp/simplesamlphp-module-infocard": "<1.0.1",
"simplito/elliptic-php": "<1.0.6",
"slim/slim": "<2.6",
- "smarty/smarty": "<3.1.45|>=4,<4.1.1",
- "snipe/snipe-it": "<5.4.4|>= 6.0.0-RC-1, <= 6.0.0-RC-5",
+ "smarty/smarty": "<3.1.47|>=4,<4.2.1",
+ "snipe/snipe-it": "<6.0.11|>= 6.0.0-RC-1, <= 6.0.0-RC-5",
"socalnick/scn-social-auth": "<1.15.2",
"socialiteproviders/steam": "<1.1",
"spipu/html2pdf": "<5.2.4",
@@ -5321,25 +5242,28 @@
"thelia/backoffice-default-template": ">=2.1,<2.1.2",
"thelia/thelia": ">=2.1-beta.1,<2.1.3",
"theonedemon/phpwhois": "<=4.2.5",
+ "thinkcmf/thinkcmf": "<=5.1.7",
+ "thorsten/phpmyfaq": "<=3.1.7",
"tinymce/tinymce": "<5.10",
"titon/framework": ">=0,<9.9.99",
- "topthink/framework": "<6.0.12",
+ "topthink/framework": "<=6.0.13",
"topthink/think": "<=6.0.9",
"topthink/thinkphp": "<=3.2.3",
"tribalsystems/zenario": "<9.2.55826",
"truckersmp/phpwhois": "<=4.3.1",
- "twig/twig": "<1.38|>=2,<2.14.11|>=3,<3.3.8",
- "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.38|>=9,<9.5.29|>=10,<10.4.29|>=11,<11.5.11",
+ "twig/twig": "<1.44.7|>=2,<2.15.3|>=3,<3.4.3",
+ "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.38|>=9,<9.5.29|>=10,<10.4.32|>=11,<11.5.16",
"typo3/cms-backend": ">=7,<=7.6.50|>=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1",
- "typo3/cms-core": ">=6.2,<=6.2.56|>=7,<7.6.57|>=8,<8.7.47|>=9,<9.5.35|>=10,<10.4.29|>=11,<11.5.11",
+ "typo3/cms-core": ">=6.2,<=6.2.56|>=7,<7.6.58|>=8,<8.7.48|>=9,<9.5.37|>=10,<10.4.32|>=11,<11.5.16",
"typo3/cms-form": ">=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1",
"typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6",
+ "typo3/html-sanitizer": ">=1,<1.0.7|>=2,<2.0.16",
"typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.3.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3",
"typo3/phar-stream-wrapper": ">=1,<2.1.1|>=3,<3.1.1",
"typo3/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5",
"typo3fluid/fluid": ">=2,<2.0.8|>=2.1,<2.1.7|>=2.2,<2.2.4|>=2.3,<2.3.7|>=2.4,<2.4.4|>=2.5,<2.5.11|>=2.6,<2.6.10",
"ua-parser/uap-php": "<3.8",
- "unisharp/laravel-filemanager": "<=2.3",
+ "unisharp/laravel-filemanager": "<=2.5.1",
"userfrosting/userfrosting": ">=0.3.1,<4.6.3",
"usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2",
"vanilla/safecurl": "<0.9.2",
@@ -5351,12 +5275,14 @@
"webcoast/deferred-image-processing": "<1.0.2",
"wikimedia/parsoid": "<0.12.2",
"willdurand/js-translation-bundle": "<2.1.1",
+ "wintercms/winter": "<1.0.475|>=1.1,<1.1.10|>=1.2,<1.2.1",
+ "woocommerce/woocommerce": "<6.6",
"wp-cli/wp-cli": "<2.5",
"wp-graphql/wp-graphql": "<0.3.5",
"wpanel/wpanel4-cms": "<=4.3.1",
"wwbn/avideo": "<=11.6",
"yeswiki/yeswiki": "<4.1",
- "yetiforce/yetiforce-crm": "<6.4",
+ "yetiforce/yetiforce-crm": "<=6.4",
"yidashi/yii2cmf": "<=2",
"yii2mod/yii2-cms": "<1.9.2",
"yiisoft/yii": ">=1.1.14,<1.1.15",
@@ -5430,7 +5356,7 @@
"type": "tidelift"
}
],
- "time": "2022-06-25T08:04:47+00:00"
+ "time": "2022-10-29T01:33:46+00:00"
},
{
"name": "sebastian/cli-parser",
@@ -5601,16 +5527,16 @@
},
{
"name": "sebastian/comparator",
- "version": "4.0.6",
+ "version": "4.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
- "reference": "55f4261989e546dc112258c7a75935a81a7ce382"
+ "reference": "fa0f136dd2334583309d32b62544682ee972b51a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382",
- "reference": "55f4261989e546dc112258c7a75935a81a7ce382",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a",
+ "reference": "fa0f136dd2334583309d32b62544682ee972b51a",
"shasum": ""
},
"require": {
@@ -5663,7 +5589,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/comparator/issues",
- "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6"
+ "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8"
},
"funding": [
{
@@ -5671,7 +5597,7 @@
"type": "github"
}
],
- "time": "2020-10-26T15:49:45+00:00"
+ "time": "2022-09-14T12:41:17+00:00"
},
{
"name": "sebastian/complexity",
@@ -5861,16 +5787,16 @@
},
{
"name": "sebastian/exporter",
- "version": "4.0.4",
+ "version": "4.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
- "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9"
+ "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9",
- "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
+ "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
"shasum": ""
},
"require": {
@@ -5926,7 +5852,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/exporter/issues",
- "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4"
+ "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5"
},
"funding": [
{
@@ -5934,7 +5860,7 @@
"type": "github"
}
],
- "time": "2021-11-11T14:18:36+00:00"
+ "time": "2022-09-14T06:03:37+00:00"
},
{
"name": "sebastian/global-state",
@@ -6289,16 +6215,16 @@
},
{
"name": "sebastian/type",
- "version": "3.0.0",
+ "version": "3.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/type.git",
- "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad"
+ "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b233b84bc4465aff7b57cf1c4bc75c86d00d6dad",
- "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad",
+ "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
+ "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
"shasum": ""
},
"require": {
@@ -6310,7 +6236,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.0-dev"
+ "dev-master": "3.2-dev"
}
},
"autoload": {
@@ -6333,7 +6259,7 @@
"homepage": "https://github.com/sebastianbergmann/type",
"support": {
"issues": "https://github.com/sebastianbergmann/type/issues",
- "source": "https://github.com/sebastianbergmann/type/tree/3.0.0"
+ "source": "https://github.com/sebastianbergmann/type/tree/3.2.0"
},
"funding": [
{
@@ -6341,7 +6267,7 @@
"type": "github"
}
],
- "time": "2022-03-15T09:54:48+00:00"
+ "time": "2022-09-12T14:47:03+00:00"
},
{
"name": "sebastian/version",
@@ -6398,16 +6324,16 @@
},
{
"name": "symfony/browser-kit",
- "version": "v5.4.3",
+ "version": "v5.4.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/browser-kit.git",
- "reference": "18e73179c6a33d520de1b644941eba108dd811ad"
+ "reference": "081fe28a26b6bd671dea85ef3a4b5003f3c88027"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/browser-kit/zipball/18e73179c6a33d520de1b644941eba108dd811ad",
- "reference": "18e73179c6a33d520de1b644941eba108dd811ad",
+ "url": "https://api.github.com/repos/symfony/browser-kit/zipball/081fe28a26b6bd671dea85ef3a4b5003f3c88027",
+ "reference": "081fe28a26b6bd671dea85ef3a4b5003f3c88027",
"shasum": ""
},
"require": {
@@ -6450,7 +6376,7 @@
"description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/browser-kit/tree/v5.4.3"
+ "source": "https://github.com/symfony/browser-kit/tree/v5.4.11"
},
"funding": [
{
@@ -6466,20 +6392,20 @@
"type": "tidelift"
}
],
- "time": "2022-01-02T09:53:40+00:00"
+ "time": "2022-07-27T15:50:05+00:00"
},
{
"name": "symfony/css-selector",
- "version": "v5.4.3",
+ "version": "v5.4.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
- "reference": "b0a190285cd95cb019237851205b8140ef6e368e"
+ "reference": "c1681789f059ab756001052164726ae88512ae3d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/css-selector/zipball/b0a190285cd95cb019237851205b8140ef6e368e",
- "reference": "b0a190285cd95cb019237851205b8140ef6e368e",
+ "url": "https://api.github.com/repos/symfony/css-selector/zipball/c1681789f059ab756001052164726ae88512ae3d",
+ "reference": "c1681789f059ab756001052164726ae88512ae3d",
"shasum": ""
},
"require": {
@@ -6516,7 +6442,7 @@
"description": "Converts CSS selectors to XPath expressions",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/css-selector/tree/v5.4.3"
+ "source": "https://github.com/symfony/css-selector/tree/v5.4.11"
},
"funding": [
{
@@ -6532,7 +6458,7 @@
"type": "tidelift"
}
],
- "time": "2022-01-02T09:53:40+00:00"
+ "time": "2022-06-27T16:58:25+00:00"
},
{
"name": "symfony/debug",
@@ -6605,16 +6531,16 @@
},
{
"name": "symfony/dom-crawler",
- "version": "v5.4.9",
+ "version": "v5.4.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/dom-crawler.git",
- "reference": "a213cbc80382320b0efdccdcdce232f191fafe3a"
+ "reference": "b8fd0ff9a0f00d944f1534f6d21e84f92eda7258"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/a213cbc80382320b0efdccdcdce232f191fafe3a",
- "reference": "a213cbc80382320b0efdccdcdce232f191fafe3a",
+ "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/b8fd0ff9a0f00d944f1534f6d21e84f92eda7258",
+ "reference": "b8fd0ff9a0f00d944f1534f6d21e84f92eda7258",
"shasum": ""
},
"require": {
@@ -6660,7 +6586,7 @@
"description": "Eases DOM navigation for HTML and XML documents",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/dom-crawler/tree/v5.4.9"
+ "source": "https://github.com/symfony/dom-crawler/tree/v5.4.15"
},
"funding": [
{
@@ -6676,7 +6602,7 @@
"type": "tidelift"
}
],
- "time": "2022-05-04T14:46:32+00:00"
+ "time": "2022-10-27T08:04:35+00:00"
},
{
"name": "theseer/tokenizer",
@@ -6727,64 +6653,6 @@
}
],
"time": "2021-07-28T10:34:58+00:00"
- },
- {
- "name": "webmozart/assert",
- "version": "1.11.0",
- "source": {
- "type": "git",
- "url": "https://github.com/webmozarts/assert.git",
- "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
- "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
- "shasum": ""
- },
- "require": {
- "ext-ctype": "*",
- "php": "^7.2 || ^8.0"
- },
- "conflict": {
- "phpstan/phpstan": "<0.12.20",
- "vimeo/psalm": "<4.6.1 || 4.6.2"
- },
- "require-dev": {
- "phpunit/phpunit": "^8.5.13"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.10-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Webmozart\\Assert\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Bernhard Schussek",
- "email": "bschussek@gmail.com"
- }
- ],
- "description": "Assertions to validate method input/output with nice error messages.",
- "keywords": [
- "assert",
- "check",
- "validate"
- ],
- "support": {
- "issues": "https://github.com/webmozarts/assert/issues",
- "source": "https://github.com/webmozarts/assert/tree/1.11.0"
- },
- "time": "2022-06-03T18:03:27+00:00"
}
],
"aliases": [],
diff --git a/lib/SP/Core/Context/SessionContext.php b/lib/SP/Core/Context/SessionContext.php
index 403aac44..7f228ba7 100644
--- a/lib/SP/Core/Context/SessionContext.php
+++ b/lib/SP/Core/Context/SessionContext.php
@@ -27,7 +27,7 @@ namespace SP\Core\Context;
use SP\Core\Crypt\Vault;
use SP\DataModel\Dto\AccountCache;
use SP\DataModel\ProfileData;
-use SP\Domain\Account\Services\AccountSearchFilter;
+use SP\Domain\Account\Search\AccountSearchFilter;
use SP\Domain\User\Services\UserLoginResponse;
/**
@@ -189,7 +189,7 @@ class SessionContext extends ContextBase
}
/**
- * @param AccountSearchFilter $searchFilters
+ * @param \SP\Domain\Account\Search\AccountSearchFilter $searchFilters
*/
public function setSearchFilters(AccountSearchFilter $searchFilters): void
{
diff --git a/lib/SP/Core/Definitions/CoreDefinitions.php b/lib/SP/Core/Definitions/CoreDefinitions.php
index 19e62c62..607319e1 100644
--- a/lib/SP/Core/Definitions/CoreDefinitions.php
+++ b/lib/SP/Core/Definitions/CoreDefinitions.php
@@ -24,6 +24,7 @@
namespace SP\Core\Definitions;
+use Aura\SqlQuery\QueryFactory;
use Monolog\Logger;
use PHPMailer\PHPMailer\PHPMailer;
use Psr\Container\ContainerInterface;
@@ -188,6 +189,8 @@ final class CoreDefinitions
$c->get(NotificationHandler::class)
);
}),
+ QueryFactory::class => create(QueryFactory::class)
+ ->constructor('mysql', QueryFactory::COMMON),
];
}
}
\ No newline at end of file
diff --git a/lib/SP/Domain/Account/AccountHistoryServiceInterface.php b/lib/SP/Domain/Account/AccountHistoryServiceInterface.php
index 93ab4e2c..5b62d12d 100644
--- a/lib/SP/Domain/Account/AccountHistoryServiceInterface.php
+++ b/lib/SP/Domain/Account/AccountHistoryServiceInterface.php
@@ -34,6 +34,7 @@ use SP\DataModel\ItemData;
use SP\DataModel\ItemSearchData;
use SP\Domain\Account\Services\AccountPasswordRequest;
use SP\Domain\Common\Services\ServiceException;
+use SP\Infrastructure\Common\Repositories\NoSuchItemException;
use SP\Infrastructure\Database\QueryResult;
/**
@@ -46,8 +47,7 @@ interface AccountHistoryServiceInterface
/**
* Returns the item for given id
*
- * @throws SPException
- * @throws SPException
+ * @throws NoSuchItemException
*/
public function getById(int $id): AccountHistoryData;
diff --git a/lib/SP/Domain/Account/AccountSearchServiceInterface.php b/lib/SP/Domain/Account/AccountSearchServiceInterface.php
index f4a0fc11..a8135f93 100644
--- a/lib/SP/Domain/Account/AccountSearchServiceInterface.php
+++ b/lib/SP/Domain/Account/AccountSearchServiceInterface.php
@@ -28,9 +28,8 @@ namespace SP\Domain\Account;
use SP\Core\Exceptions\ConstraintException;
use SP\Core\Exceptions\QueryException;
use SP\Core\Exceptions\SPException;
-use SP\Domain\Account\Services\AccountSearchFilter;
+use SP\Domain\Account\Search\AccountSearchFilter;
use SP\Infrastructure\Database\QueryResult;
-use SP\Mvc\Model\QueryCondition;
/**
* Class AccountSearchService para la gestión de búsquedas de cuentas
@@ -45,13 +44,13 @@ interface AccountSearchServiceInterface
* @throws QueryException
* @throws SPException
*/
- public function processSearchResults(AccountSearchFilter $accountSearchFilter): QueryResult;
+ public function getByFilter(AccountSearchFilter $accountSearchFilter): QueryResult;
/**
* Analizar la cadena de consulta por eqituetas especiales y devolver un objeto
* QueryCondition con los filtros
*/
- public function analyzeQueryFilters(string $string): QueryCondition;
+ public function analyzeQueryFilters(string $string): void;
public function getCleanString(): ?string;
}
\ No newline at end of file
diff --git a/lib/SP/Domain/Account/In/AccountRepositoryInterface.php b/lib/SP/Domain/Account/In/AccountRepositoryInterface.php
index c27ac77f..9da9960c 100644
--- a/lib/SP/Domain/Account/In/AccountRepositoryInterface.php
+++ b/lib/SP/Domain/Account/In/AccountRepositoryInterface.php
@@ -28,9 +28,10 @@ namespace SP\Domain\Account\In;
use SP\Core\Exceptions\ConstraintException;
use SP\Core\Exceptions\QueryException;
use SP\Core\Exceptions\SPException;
+use SP\DataModel\AccountHistoryData;
+use SP\Domain\Account\Search\AccountSearchFilter;
use SP\Domain\Account\Services\AccountPasswordRequest;
use SP\Domain\Account\Services\AccountRequest;
-use SP\Domain\Account\Services\AccountSearchFilter;
use SP\Domain\Common\In\RepositoryInterface;
use SP\Domain\Common\Out\SimpleModel;
use SP\Infrastructure\Database\QueryResult;
@@ -53,22 +54,21 @@ interface AccountRepositoryInterface extends RepositoryInterface
/**
* @param int $id
- * @param QueryCondition $queryCondition
*
* @return QueryResult
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
- public function getPasswordForId(int $id, QueryCondition $queryCondition): QueryResult;
+ public function getPasswordForId(int $id): QueryResult;
/**
- * @param QueryCondition $queryCondition
+ * @param int $id
*
* @return QueryResult
- * @throws ConstraintException
- * @throws QueryException
+ * @throws \SP\Core\Exceptions\ConstraintException
+ * @throws \SP\Core\Exceptions\QueryException
*/
- public function getPasswordHistoryForId(QueryCondition $queryCondition): QueryResult;
+ public function getPasswordHistoryForId(int $id): QueryResult;
/**
* Incrementa el contador de vista de clave de una cuenta en la BBDD
@@ -106,14 +106,14 @@ interface AccountRepositoryInterface extends RepositoryInterface
/**
* Restaurar una cuenta desde el histórico.
*
- * @param int $historyId El Id del registro en el histórico
+ * @param \SP\DataModel\AccountHistoryData $accountHistoryData
* @param int $userId User's Id
*
* @return bool
- * @throws ConstraintException
- * @throws QueryException
+ * @throws \SP\Core\Exceptions\ConstraintException
+ * @throws \SP\Core\Exceptions\QueryException
*/
- public function editRestore(int $historyId, int $userId): bool;
+ public function editRestore(AccountHistoryData $accountHistoryData, int $userId): bool;
/**
* Updates an item for bulk action
@@ -148,35 +148,22 @@ interface AccountRepositoryInterface extends RepositoryInterface
public function getDataForLink(int $id): QueryResult;
/**
- * Obtener las cuentas de una búsqueda.
- *
- * @param AccountSearchFilter $accountSearchFilter
- * @param QueryCondition $queryFilterUser
+ * @param int|null $accountId
*
* @return QueryResult
- * @throws ConstraintException
- * @throws QueryException
- * @throws SPException
+ * @throws \SP\Core\Exceptions\ConstraintException
+ * @throws \SP\Core\Exceptions\QueryException
*/
- public function getByFilter(AccountSearchFilter $accountSearchFilter, QueryCondition $queryFilterUser): QueryResult;
+ public function getForUser(?int $accountId = null): QueryResult;
/**
- * @param QueryCondition $queryFilter
+ * @param int $accountId
*
* @return QueryResult
- * @throws ConstraintException
- * @throws QueryException
+ * @throws \SP\Core\Exceptions\ConstraintException
+ * @throws \SP\Core\Exceptions\QueryException
*/
- public function getForUser(QueryCondition $queryFilter): QueryResult;
-
- /**
- * @param QueryCondition $queryFilter
- *
- * @return QueryResult
- * @throws ConstraintException
- * @throws QueryException
- */
- public function getLinked(QueryCondition $queryFilter): QueryResult;
+ public function getLinked(int $accountId): QueryResult;
/**
* Obtener los datos relativos a la clave de todas las cuentas.
diff --git a/lib/SP/Domain/Account/Search/AccountSearchConstants.php b/lib/SP/Domain/Account/Search/AccountSearchConstants.php
new file mode 100644
index 00000000..55771394
--- /dev/null
+++ b/lib/SP/Domain/Account/Search/AccountSearchConstants.php
@@ -0,0 +1,56 @@
+.
+ */
+
+namespace SP\Domain\Account\Search;
+
+/**
+ * Interface AccountSearchConstants
+ */
+interface AccountSearchConstants
+{
+ public const FILTER_OWNER = 'owner';
+ public const FILTER_MAIN_GROUP = 'mainGroup';
+ public const FILTER_CATEGORY_NAME = 'categoryName';
+ public const FILTER_FILE_NAME = 'fileName';
+ public const FILTER_ACCOUNT_ID = 'accountId';
+ public const FILTER_USER_NAME = 'userName';
+ public const FILTER_ACCOUNT_NAME_REGEX = 'accountNameRegex';
+ public const FILTER_CLIENT_NAME = 'clientName';
+ public const FILTER_GROUP_NAME = 'groupName';
+ public const FILTER_CHAIN_AND = 'and';
+ public const FILTER_CHAIN_OR = 'or';
+ public const FILTER_IS_PRIVATE = 'is:private';
+ public const FILTER_NOT_PRIVATE = 'not:private';
+ public const FILTER_IS_EXPIRED = 'is:expired';
+ public const FILTER_NOT_EXPIRED = 'is:expired';
+
+ public const SORT_DIR_ASC = 0;
+ public const SORT_DIR_DESC = 1;
+ public const SORT_CATEGORY = 2;
+ public const SORT_DEFAULT = 0;
+ public const SORT_LOGIN = 3;
+ public const SORT_URL = 4;
+ public const SORT_NAME = 1;
+ public const SORT_CLIENT = 5;
+}
\ No newline at end of file
diff --git a/lib/SP/Domain/Account/Services/AccountSearchFilter.php b/lib/SP/Domain/Account/Search/AccountSearchFilter.php
similarity index 65%
rename from lib/SP/Domain/Account/Services/AccountSearchFilter.php
rename to lib/SP/Domain/Account/Search/AccountSearchFilter.php
index 20306bf8..9818c390 100644
--- a/lib/SP/Domain/Account/Services/AccountSearchFilter.php
+++ b/lib/SP/Domain/Account/Search/AccountSearchFilter.php
@@ -22,7 +22,7 @@
* along with sysPass. If not, see .
*/
-namespace SP\Domain\Account\Services;
+namespace SP\Domain\Account\Search;
use SP\Mvc\Model\QueryCondition;
@@ -30,21 +30,19 @@ use SP\Mvc\Model\QueryCondition;
/**
* Class AccountSearchFilter
*
- * @package SP\Account
+ * @package SP\Domain\Account\Filters
*/
final class AccountSearchFilter
{
/**
- * Constantes de ordenación
+ * @param string $txtSearch
+ *
+ * @return \SP\Domain\Account\Search\AccountSearchFilter
*/
- public const SORT_DIR_ASC = 0;
- public const SORT_DIR_DESC = 1;
- public const SORT_LOGIN = 3;
- public const SORT_URL = 4;
- public const SORT_CATEGORY = 2;
- public const SORT_CLIENT = 5;
- public const SORT_NAME = 1;
- public const SORT_DEFAULT = 0;
+ public static function build(string $txtSearch): AccountSearchFilter
+ {
+ return (new self())->setTxtSearch($txtSearch);
+ }
/**
* @var int|null El número de registros de la última consulta
@@ -55,18 +53,17 @@ final class AccountSearchFilter
/**
* @var string|null Search string without special filters
*/
- private ?string $cleanTxtSearch = null;
- private ?int $clientId = null;
- private ?int $categoryId = null;
- private ?array $tagsId = null;
- private int $sortOrder = self::SORT_DEFAULT;
- private int $sortKey = self::SORT_DIR_ASC;
- private int $limitStart = 0;
- private ?int $limitCount = null;
- private ?bool $sortViews = null;
- private bool $searchFavorites = false;
- private ?QueryCondition $stringFilters = null;
- private ?string $filterOperator = null;
+ private ?string $cleanTxtSearch = null;
+ private ?int $clientId = null;
+ private ?int $categoryId = null;
+ private ?array $tagsId = null;
+ private int $sortOrder = AccountSearchConstants::SORT_DEFAULT;
+ private int $sortKey = AccountSearchConstants::SORT_DIR_ASC;
+ private int $limitStart = 0;
+ private ?int $limitCount = null;
+ private ?bool $sortViews = null;
+ private bool $searchFavorites = false;
+ private ?string $filterOperator = null;
public function isSearchFavorites(): bool
{
@@ -181,57 +178,6 @@ final class AccountSearchFilter
return null !== $this->tagsId && count($this->tagsId) !== 0;
}
- public function getStringFilters(): QueryCondition
- {
- return $this->stringFilters ?? new QueryCondition();
- }
-
- public function setStringFilters(?QueryCondition $stringFilters): void
- {
- $this->stringFilters = $stringFilters;
- }
-
- /**
- * Devuelve la cadena de ordenación de la consulta
- */
- public function getOrderString(): string
- {
- switch ($this->sortKey) {
- case self::SORT_NAME:
- $orderKey[] = 'Account.name';
- break;
- case self::SORT_CATEGORY:
- $orderKey[] = 'Account.categoryName';
- break;
- case self::SORT_LOGIN:
- $orderKey[] = 'Account.login';
- break;
- case self::SORT_URL:
- $orderKey[] = 'Account.url';
- break;
- case self::SORT_CLIENT:
- $orderKey[] = 'Account.clientName';
- break;
- case self::SORT_DEFAULT:
- default:
- $orderKey[] = 'Account.clientName, Account.name';
- break;
- }
-
- if ($this->isSortViews() && !$this->getSortKey()) {
- array_unshift($orderKey, 'Account.countView DESC');
- $this->setSortOrder(self::SORT_DIR_DESC);
- }
-
- $orderDir = $this->sortOrder === self::SORT_DIR_ASC ? 'ASC' : 'DESC';
-
- return sprintf(
- '%s %s',
- implode(',', $orderKey),
- $orderDir
- );
- }
-
public function isSortViews(): bool
{
return $this->sortViews ?? false;
@@ -292,7 +238,7 @@ final class AccountSearchFilter
$this->limitCount = null;
$this->sortViews = null;
$this->searchFavorites = false;
- $this->sortOrder = self::SORT_DEFAULT;
- $this->sortKey = self::SORT_DIR_ASC;
+ $this->sortOrder = AccountSearchConstants::SORT_DEFAULT;
+ $this->sortKey = AccountSearchConstants::SORT_DIR_ASC;
}
}
\ No newline at end of file
diff --git a/lib/SP/Domain/Account/Search/AccountSearchTokenizer.php b/lib/SP/Domain/Account/Search/AccountSearchTokenizer.php
new file mode 100644
index 00000000..2faa9f55
--- /dev/null
+++ b/lib/SP/Domain/Account/Search/AccountSearchTokenizer.php
@@ -0,0 +1,148 @@
+.
+ */
+
+namespace SP\Domain\Account\Search;
+
+use SP\Util\Filter;
+
+/**
+ * Class AccountSearchTokenizer
+ */
+final class AccountSearchTokenizer
+{
+ private const SEARCH_REGEX = /** @lang RegExp */
+ '/(?(?[a-zа-я_]+):(?!\s]*)"?(?[^":]+)"?/u';
+
+ private const FILTERS = [
+ 'condition' => [
+ 'subject' => ['is', 'not'],
+ 'condition' => ['expired', 'private'],
+ ],
+ 'items' => [
+ 'subject' => [
+ 'id' => AccountSearchConstants::FILTER_ACCOUNT_ID,
+ 'user' => AccountSearchConstants::FILTER_USER_NAME,
+ 'group' => AccountSearchConstants::FILTER_GROUP_NAME,
+ 'file' => AccountSearchConstants::FILTER_FILE_NAME,
+ 'owner' => AccountSearchConstants::FILTER_OWNER,
+ 'maingroup' => AccountSearchConstants::FILTER_MAIN_GROUP,
+ 'client' => AccountSearchConstants::FILTER_CLIENT_NAME,
+ 'category' => AccountSearchConstants::FILTER_CATEGORY_NAME,
+ 'name_regex' => AccountSearchConstants::FILTER_ACCOUNT_NAME_REGEX,
+ ],
+ 'condition' => null,
+ ],
+ 'operator' => [
+ 'subject' => ['op'],
+ 'condition' => [AccountSearchConstants::FILTER_CHAIN_AND, AccountSearchConstants::FILTER_CHAIN_OR],
+ ],
+ ];
+
+ /**
+ * @param string $search
+ *
+ * @return AccountSearchTokens|null
+ */
+ public function tokenizeFrom(string $search): ?AccountSearchTokens
+ {
+ $match = preg_match_all(self::SEARCH_REGEX, $search, $filters);
+
+ if (empty($match)) {
+ return null;
+ }
+
+ $filtersAndValues = array_filter(array_combine($filters['filter_subject'], $filters['filter_condition']));
+
+ return new AccountSearchTokens(
+ Filter::safeSearchString(trim($filters['search'][0] ?? '')),
+ $this->getConditions($filtersAndValues),
+ $this->getItems($filtersAndValues),
+ $this->getOperator($filtersAndValues)[0],
+ );
+ }
+
+ /**
+ * @param array $filters
+ *
+ * @return array
+ */
+ private function getConditions(array $filters): array
+ {
+ return array_filter(
+ array_map(
+ static function ($subject, $condition) {
+ if (in_array($subject, self::FILTERS['condition']['subject'], true)
+ && in_array($condition, self::FILTERS['condition']['condition'], true)
+ ) {
+ return sprintf("%s:%s", $subject, $condition);
+ }
+
+ return null;
+ },
+ $filters['filter_subject'],
+ $filters['filter_condition']
+ )
+ );
+ }
+
+ /**
+ * @param array $filtersAndValues
+ *
+ * @return array
+ */
+ private function getItems(array $filtersAndValues): array
+ {
+ $items = array_filter(
+ $filtersAndValues,
+ static function ($value, $key) {
+ return in_array($key, array_keys(self::FILTERS['items']['subject']), true) && !empty($value);
+ },
+ ARRAY_FILTER_USE_BOTH
+ );
+
+ return array_combine(
+ array_map(function ($key) {
+ return self::FILTERS['items']['subject'][$key];
+ }, array_keys($items)),
+ array_values($items)
+ );
+ }
+
+ /**
+ * @param array $filtersAndValues
+ *
+ * @return array
+ */
+ private function getOperator(array $filtersAndValues): array
+ {
+ return array_filter(
+ $filtersAndValues,
+ static function ($value, $key) {
+ return in_array($key, self::FILTERS['operator']['subject'], true)
+ && in_array($value, self::FILTERS['operator']['condition'], true);
+ },
+ ARRAY_FILTER_USE_BOTH
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/SP/Domain/Account/Search/AccountSearchTokens.php b/lib/SP/Domain/Account/Search/AccountSearchTokens.php
new file mode 100644
index 00000000..c58cbb3c
--- /dev/null
+++ b/lib/SP/Domain/Account/Search/AccountSearchTokens.php
@@ -0,0 +1,70 @@
+.
+ */
+
+namespace SP\Domain\Account\Search;
+
+/**
+ * Class AccountSearchTokens
+ */
+final class AccountSearchTokens
+{
+ private string $search;
+ private array $conditions;
+ private array $items;
+ private string $operator;
+
+ /**
+ * @param string $search
+ * @param array $conditions
+ * @param array $items
+ * @param string $operator
+ */
+ public function __construct(string $search, array $conditions, array $items, string $operator)
+ {
+ $this->search = $search;
+ $this->conditions = $conditions;
+ $this->items = $items;
+ $this->operator = $operator;
+ }
+
+ public function getConditions(): array
+ {
+ return $this->conditions;
+ }
+
+ public function getItems(): array
+ {
+ return $this->items;
+ }
+
+ public function getOperator(): string
+ {
+ return $this->operator;
+ }
+
+ public function getSearch(): string
+ {
+ return $this->search;
+ }
+}
\ No newline at end of file
diff --git a/lib/SP/Domain/Account/Services/AccountFilterUser.php b/lib/SP/Domain/Account/Services/AccountFilterUser.php
index e46d4f43..84c58b4b 100644
--- a/lib/SP/Domain/Account/Services/AccountFilterUser.php
+++ b/lib/SP/Domain/Account/Services/AccountFilterUser.php
@@ -24,128 +24,137 @@
namespace SP\Domain\Account\Services;
+use Aura\SqlQuery\Common\SelectInterface;
+use Aura\SqlQuery\QueryFactory;
use SP\Core\Context\ContextInterface;
use SP\DataModel\ProfileData;
+use SP\Domain\Account\Search\AccountSearchConstants;
use SP\Domain\Config\In\ConfigDataInterface;
use SP\Domain\User\Services\UserLoginResponse;
-use SP\Mvc\Model\QueryCondition;
defined('APP_ROOT') || die();
/**
- * Class AccountUtil con utilidades para la gestión de cuentas
+ * Class AccountFilterUser
*/
final class AccountFilterUser
{
private ConfigDataInterface $configData;
private ContextInterface $context;
- private ?ProfileData $userProfile = null;
- private ?UserLoginResponse $userData = null;
+ private QueryFactory $queryFactory;
public function __construct(
ContextInterface $context,
- ConfigDataInterface $configData
+ ConfigDataInterface $configData,
+ QueryFactory $queryFactory
) {
$this->context = $context;
$this->configData = $configData;
+ $this->queryFactory = $queryFactory;
}
/**
* Devuelve el filtro para la consulta SQL de cuentas que un usuario puede acceder
*/
- public function getFilterHistory(bool $useGlobalSearch = false): QueryCondition
+ public function buildFilterHistory(bool $useGlobalSearch = false, ?SelectInterface $query = null): SelectInterface
{
- $this->setUp();
+ $userData = $this->context->getUserData();
+ $userProfile = $this->context->getUserProfile();
- $queryFilter = new QueryCondition();
+ if ($query === null) {
+ $query = $this->queryFactory->newSelect()->from('AccountHistory');
+ }
- if (!$this->userData->getIsAdminApp()
- && !$this->userData->getIsAdminAcc()
- && !($this->configData->isGlobalSearch() && $useGlobalSearch && $this->userProfile->isAccGlobalSearch())
- ) {
- // Filtro usuario y grupo
- $filter = '(AccountHistory.userId = ?
- OR AccountHistory.userGroupId = ?
- OR AccountHistory.accountId IN (SELECT accountId AS accountId FROM AccountToUser WHERE accountId = AccountHistory.accountId AND userId = ? UNION ALL SELECT accountId FROM AccountToUserGroup WHERE accountId = AccountHistory.accountId AND userGroupId = ?)
- OR AccountHistory.userGroupId IN (SELECT userGroupId FROM UserToUserGroup WHERE userGroupId = AccountHistory.userGroupId AND userId = ?))';
-
- $params = [
- $this->userData->getId(),
- $this->userData->getUserGroupId(),
- $this->userData->getId(),
- $this->userData->getUserGroupId(),
- $this->userData->getId(),
+ if ($this->isFilterByAdminAndGlobalSearch($userData, $useGlobalSearch, $userProfile)) {
+ $where = [
+ 'AccountHistory.userId = :userId',
+ 'AccountHistory.userGroupId = :userGroupId',
+ 'AccountHistory.accountId IN (SELECT accountId AS accountId FROM AccountToUser WHERE accountId = AccountHistory.accountId AND userId = :userId UNION ALL SELECT accountId FROM AccountToUserGroup WHERE accountId = AccountHistory.accountId AND userGroupId = :userGroupId',
+ 'AccountHistory.userGroupId IN (SELECT userGroupId FROM UserToUserGroup WHERE userGroupId = AccountHistory.userGroupId AND userId = :userId)',
];
if ($this->configData->isAccountFullGroupAccess()) {
// Filtro de grupos secundarios en grupos que incluyen al usuario
- $filter .= PHP_EOL
- .'OR AccountHistory.accountId = (SELECT accountId FROM AccountToUserGroup aug INNER JOIN UserToUserGroup uug ON uug.userGroupId = aug.userGroupId WHERE aug.accountId = AccountHistory.accountId AND uug.userId = ? LIMIT 1)';
- $params[] = $this->userData->getId();
+ $where[] =
+ 'AccountHistory.accountId = (SELECT accountId FROM AccountToUserGroup aug INNER JOIN UserToUserGroup uug ON uug.userGroupId = aug.userGroupId WHERE aug.accountId = AccountHistory.accountId AND uug.userId = :userId LIMIT 1)';
}
- $queryFilter->addFilter($filter, $params);
+ $query->where(sprintf('(%s)', join(sprintf(' %s ', AccountSearchConstants::FILTER_CHAIN_OR), $where)));
}
- $queryFilter->addFilter(
- '(AccountHistory.isPrivate IS NULL OR AccountHistory.isPrivate = 0 OR (AccountHistory.isPrivate = 1 AND AccountHistory.userId = ?)) AND (AccountHistory.isPrivateGroup IS NULL OR AccountHistory.isPrivateGroup = 0 OR (AccountHistory.isPrivateGroup = 1 AND AccountHistory.userGroupId = ?))',
- [$this->userData->getId(), $this->userData->getUserGroupId()]
+ $query->where(
+ '(AccountHistory.isPrivate IS NULL OR AccountHistory.isPrivate = 0 OR (AccountHistory.isPrivate = 1 AND AccountHistory.userId = :userId))'
+ );
+ $query->where(
+ '(AccountHistory.isPrivateGroup IS NULL OR AccountHistory.isPrivateGroup = 0 OR (AccountHistory.isPrivateGroup = 1 AND AccountHistory.userGroupId = :userGroupId))'
);
- return $queryFilter;
- }
+ $query->bindValues([
+ 'userId' => $userData->getId(),
+ 'userGroupId' => $userData->getUserGroupId(),
+ ]);
- /**
- * setUp
- */
- private function setUp(): void
- {
- $this->userData = $this->context->getUserData();
- $this->userProfile = $this->context->getUserProfile();
+ return $query;
}
/**
* Devuelve el filtro para la consulta SQL de cuentas que un usuario puede acceder
*/
- public function getFilter(bool $useGlobalSearch = false): QueryCondition
+ public function buildFilter(bool $useGlobalSearch = false, ?SelectInterface $query = null): SelectInterface
{
- $this->setUp();
+ $userData = $this->context->getUserData();
+ $userProfile = $this->context->getUserProfile();
- $queryFilter = new QueryCondition();
+ if ($query === null) {
+ $query = $this->queryFactory->newSelect()->from('Account');
+ }
- if (!$this->userData->getIsAdminApp()
- && !$this->userData->getIsAdminAcc()
- && !($this->configData->isGlobalSearch() && $useGlobalSearch && $this->userProfile->isAccGlobalSearch())
- ) {
- // Filtro usuario y grupo
- $filter = '(Account.userId = ?
- OR Account.userGroupId = ?
- OR Account.id IN (SELECT accountId AS accountId FROM AccountToUser WHERE accountId = Account.id AND userId = ? UNION ALL SELECT accountId FROM AccountToUserGroup WHERE accountId = Account.id AND userGroupId = ?)
- OR Account.userGroupId IN (SELECT userGroupId FROM UserToUserGroup WHERE userGroupId = Account.userGroupId AND userId = ?))';
-
- $params = [
- $this->userData->getId(),
- $this->userData->getUserGroupId(),
- $this->userData->getId(),
- $this->userData->getUserGroupId(),
- $this->userData->getId(),
+ if ($this->isFilterByAdminAndGlobalSearch($userData, $useGlobalSearch, $userProfile)) {
+ $where = [
+ 'Account.userId = :userId',
+ 'Account.userGroupId = :userGroupId',
+ 'Account.id IN (SELECT accountId AS accountId FROM AccountToUser WHERE accountId = Account.id AND userId = :userId UNION ALL SELECT accountId FROM AccountToUserGroup WHERE accountId = Account.id AND userGroupId = :userGroupId)',
+ 'Account.userGroupId IN (SELECT userGroupId FROM UserToUserGroup WHERE userGroupId = Account.userGroupId AND userId = :userId)',
];
if ($this->configData->isAccountFullGroupAccess()) {
// Filtro de grupos secundarios en grupos que incluyen al usuario
- $filter .= PHP_EOL
- .'OR Account.id = (SELECT accountId FROM AccountToUserGroup aug INNER JOIN UserToUserGroup uug ON uug.userGroupId = aug.userGroupId WHERE aug.accountId = Account.id AND uug.userId = ? LIMIT 1)';
- $params[] = $this->userData->getId();
+ $where[] =
+ 'Account.id = (SELECT accountId FROM AccountToUserGroup aug INNER JOIN UserToUserGroup uug ON uug.userGroupId = aug.userGroupId WHERE aug.accountId = Account.id AND uug.userId = :userId LIMIT 1)';
}
- $queryFilter->addFilter($filter, $params);
+ $query->where(sprintf('(%s)', join(sprintf(' %s ', AccountSearchConstants::FILTER_CHAIN_OR), $where)));
}
- $queryFilter->addFilter(
- '(Account.isPrivate IS NULL OR Account.isPrivate = 0 OR (Account.isPrivate = 1 AND Account.userId = ?)) AND (Account.isPrivateGroup IS NULL OR Account.isPrivateGroup = 0 OR (Account.isPrivateGroup = 1 AND Account.userGroupId = ?))',
- [$this->userData->getId(), $this->userData->getUserGroupId()]
+ $query->where(
+ 'Account.isPrivate IS NULL OR Account.isPrivate = 0 OR (Account.isPrivate = 1 AND Account.userId = :userId)'
+ );
+ $query->where(
+ 'Account.isPrivateGroup IS NULL OR Account.isPrivateGroup = 0 OR (Account.isPrivateGroup = 1 AND Account.userGroupId = :userGroupId)'
);
- return $queryFilter;
+ $query->bindValues([
+ 'userId' => $userData->getId(),
+ 'userGroupId' => $userData->getUserGroupId(),
+ ]);
+
+ return $query;
+ }
+
+ /**
+ * @param \SP\Domain\User\Services\UserLoginResponse $userData
+ * @param bool $useGlobalSearch
+ * @param \SP\DataModel\ProfileData|null $userProfile
+ *
+ * @return bool
+ */
+ private function isFilterByAdminAndGlobalSearch(
+ UserLoginResponse $userData,
+ bool $useGlobalSearch,
+ ?ProfileData $userProfile
+ ): bool {
+ return !$userData->getIsAdminApp()
+ && !$userData->getIsAdminAcc()
+ && !($this->configData->isGlobalSearch() && $useGlobalSearch && $userProfile->isAccGlobalSearch());
}
}
\ No newline at end of file
diff --git a/lib/SP/Domain/Account/Services/AccountHistoryService.php b/lib/SP/Domain/Account/Services/AccountHistoryService.php
index 86e84c78..b8022fa9 100644
--- a/lib/SP/Domain/Account/Services/AccountHistoryService.php
+++ b/lib/SP/Domain/Account/Services/AccountHistoryService.php
@@ -68,8 +68,7 @@ final class AccountHistoryService extends Service implements AccountHistoryServi
/**
* Returns the item for given id
*
- * @throws SPException
- * @throws SPException
+ * @throws NoSuchItemException
*/
public function getById(int $id): AccountHistoryData
{
diff --git a/lib/SP/Domain/Account/Services/AccountSearchService.php b/lib/SP/Domain/Account/Services/AccountSearchService.php
index 19b6f1a9..1eb9239c 100644
--- a/lib/SP/Domain/Account/Services/AccountSearchService.php
+++ b/lib/SP/Domain/Account/Services/AccountSearchService.php
@@ -36,19 +36,21 @@ use SP\DataModel\Dto\AccountCache;
use SP\Domain\Account\AccountAclServiceInterface;
use SP\Domain\Account\AccountSearchServiceInterface;
use SP\Domain\Account\AccountToFavoriteServiceInterface;
-use SP\Domain\Account\In\AccountRepositoryInterface;
use SP\Domain\Account\In\AccountToTagRepositoryInterface;
use SP\Domain\Account\In\AccountToUserGroupRepositoryInterface;
use SP\Domain\Account\In\AccountToUserRepositoryInterface;
+use SP\Domain\Account\Search\AccountSearchConstants;
+use SP\Domain\Account\Search\AccountSearchFilter;
+use SP\Domain\Account\Search\AccountSearchTokenizer;
use SP\Domain\Common\Services\Service;
use SP\Domain\Config\In\ConfigDataInterface;
use SP\Domain\User\UserGroupServiceInterface;
use SP\Domain\User\UserServiceInterface;
+use SP\Infrastructure\Account\Repositories\AccountSearchRepositoryInterface;
use SP\Infrastructure\Database\QueryResult;
use SP\Infrastructure\File\FileCache;
use SP\Infrastructure\File\FileCacheInterface;
use SP\Infrastructure\File\FileException;
-use SP\Mvc\Model\QueryCondition;
use SP\Util\Filter;
defined('APP_ROOT') || die();
@@ -58,24 +60,6 @@ defined('APP_ROOT') || die();
*/
final class AccountSearchService extends Service implements AccountSearchServiceInterface
{
- /**
- * Regex filters for special searching
- */
- private const FILTERS = [
- 'condition' => [
- 'subject' => ['is', 'not'],
- 'condition' => ['expired', 'private'],
- ],
- 'items' => [
- 'subject' => ['id', 'user', 'group', 'file', 'owner', 'maingroup', 'client', 'category', 'name_regex'],
- 'condition' => null,
- ],
- 'operator' => [
- 'subject' => ['op'],
- 'condition' => ['and', 'or'],
- ],
- ];
-
private const COLORS_CACHE_FILE = CACHE_PATH.DIRECTORY_SEPARATOR.'colors.cache';
/**
@@ -100,7 +84,6 @@ final class AccountSearchService extends Service implements AccountSearchService
'673AB7',
'3F51B5',
];
- private AccountFilterUser $accountFilterUser;
private AccountAclServiceInterface $accountAclService;
private ConfigDataInterface $configData;
private AccountToTagRepositoryInterface $accountToTagRepository;
@@ -110,7 +93,7 @@ final class AccountSearchService extends Service implements AccountSearchService
private UserServiceInterface $userService;
private UserGroupServiceInterface $userGroupService;
private FileCacheInterface $colorCache;
- private AccountRepositoryInterface $accountRepository;
+ private AccountSearchRepositoryInterface $accountSearchRepository;
private ?array $accountColor = null;
private ?string $cleanString = null;
private ?string $filterOperator = null;
@@ -124,8 +107,7 @@ final class AccountSearchService extends Service implements AccountSearchService
AccountToFavoriteServiceInterface $accountToFavoriteService,
UserServiceInterface $userService,
UserGroupServiceInterface $userGroupService,
- AccountRepositoryInterface $accountRepository,
- AccountFilterUser $accountFilterUser
+ AccountSearchRepositoryInterface $accountSearchRepository,
) {
parent::__construct($application);
$this->accountAclService = $accountAclService;
@@ -135,8 +117,7 @@ final class AccountSearchService extends Service implements AccountSearchService
$this->accountToTagRepository = $accountToTagRepository;
$this->accountToUserRepository = $accountToUserRepository;
$this->accountToUserGroupRepository = $accountToUserGroupRepository;
- $this->accountRepository = $accountRepository;
- $this->accountFilterUser = $accountFilterUser;
+ $this->accountSearchRepository = $accountSearchRepository;
// TODO: use IoC
$this->colorCache = new FileCache(self::COLORS_CACHE_FILE);
@@ -168,16 +149,13 @@ final class AccountSearchService extends Service implements AccountSearchService
* @throws QueryException
* @throws SPException
*/
- public function processSearchResults(
- AccountSearchFilter $accountSearchFilter
- ): QueryResult {
+ public function getByFilter(AccountSearchFilter $accountSearchFilter): QueryResult
+ {
if (!empty($accountSearchFilter->getTxtSearch())) {
- $accountSearchFilter->setStringFilters($this->analyzeQueryFilters($accountSearchFilter->getTxtSearch()));
+ $this->analyzeQueryFilters($accountSearchFilter->getTxtSearch());
}
- if ($this->filterOperator !== null
- || $accountSearchFilter->getFilterOperator() === null
- ) {
+ if ($this->filterOperator !== null || $accountSearchFilter->getFilterOperator() === null) {
$accountSearchFilter->setFilterOperator($this->filterOperator);
}
@@ -185,224 +163,65 @@ final class AccountSearchService extends Service implements AccountSearchService
$accountSearchFilter->setCleanTxtSearch($this->cleanString);
}
- $queryResult = $this->accountRepository->getByFilter(
- $accountSearchFilter,
- $this->accountFilterUser->getFilter($accountSearchFilter->getGlobalSearch())
- );
+ $queryResult = $this->accountSearchRepository->getByFilter($accountSearchFilter);
- // Variables de configuración
- $maxTextLength = $this->configData->isResultsAsCards() ? 40 : 60;
-
- $accountLinkEnabled = $this->context->getUserData()->getPreferences()->isAccountLink()
- || $this->configData->isAccountLink();
- $favorites = $this->accountToFavoriteService->getForUserId($this->context->getUserData()->getId());
-
- $accountsData = [];
-
- /** @var AccountSearchVData $accountSearchData */
- foreach ($queryResult->getDataAsArray() as $accountSearchData) {
- $cache = $this->getCacheForAccount($accountSearchData);
-
- // Obtener la ACL de la cuenta
- $accountAcl = $this->accountAclService->getAcl(
- ActionsInterface::ACCOUNT_SEARCH,
- AccountAclDto::makeFromAccountSearch(
- $accountSearchData,
- $cache->getUsers(),
- $cache->getUserGroups()
- )
- );
-
- // Propiedades de búsqueda de cada cuenta
- $accountsSearchItem = new AccountSearchItem(
- $accountSearchData,
- $accountAcl,
- $this->configData
- );
-
- if (!$accountSearchData->getIsPrivate()) {
- $accountsSearchItem->setUsers($cache->getUsers());
- $accountsSearchItem->setUserGroups($cache->getUserGroups());
- }
-
- $accountsSearchItem->setTags(
- $this->accountToTagRepository
- ->getTagsByAccountId($accountSearchData->getId())
- ->getDataAsArray()
- );
- $accountsSearchItem->setTextMaxLength($maxTextLength);
- $accountsSearchItem->setColor(
- $this->pickAccountColor($accountSearchData->getClientId())
- );
- $accountsSearchItem->setLink($accountLinkEnabled);
- $accountsSearchItem->setFavorite(
- isset($favorites[$accountSearchData->getId()])
- );
-
- $accountsData[] = $accountsSearchItem;
- }
-
- return QueryResult::fromResults($accountsData, $queryResult->getTotalNumRows());
+ return QueryResult::fromResults($this->buildAccountsData($queryResult), $queryResult->getTotalNumRows());
}
/**
* Analizar la cadena de consulta por eqituetas especiales y devolver un objeto
* QueryCondition con los filtros
*/
- public function analyzeQueryFilters(string $string): QueryCondition
+ public function analyzeQueryFilters(string $string): void
{
- $this->cleanString = null;
- $this->filterOperator = null;
+ $tokenizer = new AccountSearchTokenizer();
+ $tokens = $tokenizer->tokenizeFrom($string);
- $queryCondition = new QueryCondition();
+ $this->cleanString = $tokens->getSearch();
+ $this->filterOperator = $tokens->getOperator();
- $match = preg_match_all(
- '/(?(?[a-zа-я_]+):(?!\s]*)"?(?[^":]+)"?/u',
- $string,
- $filters
- );
-
- if ($match !== false && $match > 0) {
- if (!empty($filters['search'][0])) {
- $this->cleanString = Filter::safeSearchString(trim($filters['search'][0]));
- }
-
- $filtersAndValues = array_filter(
- array_combine(
- $filters['filter_subject'],
- $filters['filter_condition']
- )
- );
-
- if (!empty($filtersAndValues)) {
- $filtersItem = array_filter(
- $filtersAndValues,
- static function ($value, $key) {
- return in_array($key, self::FILTERS['items']['subject'], true)
- && $value !== '';
- },
- ARRAY_FILTER_USE_BOTH
- );
-
- if (!empty($filtersItem)) {
- $this->processFilterItems($filtersItem, $queryCondition);
- }
-
- $filtersOperator = array_filter(
- $filtersAndValues,
- static function ($value, $key) {
- return in_array($key, self::FILTERS['operator']['subject'], true)
- && in_array($value, self::FILTERS['operator']['condition'], true);
- },
- ARRAY_FILTER_USE_BOTH
- );
-
- if (!empty($filtersOperator)) {
- $this->processFilterOperator($filtersOperator);
- }
-
- $filtersCondition = array_filter(
- array_map(
- static function ($subject, $condition) {
- if (in_array($subject, self::FILTERS['condition']['subject'], true)
- && in_array($condition, self::FILTERS['condition']['condition'], true)
- ) {
- return $subject.':'.$condition;
- }
-
- return null;
- },
- $filters['filter_subject'],
- $filters['filter_condition']
- )
- );
-
- if (count($filtersCondition) !== 0) {
- $this->processFilterIs($filtersCondition, $queryCondition);
- }
- }
- }
-
- return $queryCondition;
+ $this->processFilterItems($tokens->getItems());
+ $this->processFilterConditions($tokens->getConditions());
}
- private function processFilterItems(
- array $filters,
- QueryCondition $queryCondition
- ): void {
+ private function processFilterItems(array $filters): void
+ {
foreach ($filters as $filter => $text) {
try {
switch ($filter) {
- case 'user':
+ case AccountSearchConstants::FILTER_USER_NAME:
$userData = $this->userService->getByLogin(Filter::safeSearchString($text));
- if (null !== $userData) {
- $queryCondition->addFilter(
- 'Account.userId = ? OR Account.userGroupId = ? OR Account.id IN
- (SELECT AccountToUser.accountId FROM AccountToUser WHERE AccountToUser.accountId = Account.id AND AccountToUser.userId = ?
- UNION
- SELECT AccountToUserGroup.accountId FROM AccountToUserGroup WHERE AccountToUserGroup.accountId = Account.id AND AccountToUserGroup.userGroupId = ?)',
- [
- $userData->getId(),
- $userData->getUserGroupId(),
- $userData->getId(),
- $userData->getUserGroupId(),
- ]
- );
- }
- break;
- case 'owner':
- $text = '%'.Filter::safeSearchString($text).'%';
- $queryCondition->addFilter(
- 'Account.userLogin LIKE ? OR Account.userName LIKE ?',
- [$text, $text]
+ $this->accountSearchRepository->withFilterForUser(
+ $userData->getId(),
+ $userData->getUserGroupId()
);
break;
- case 'group':
+ case AccountSearchConstants::FILTER_OWNER:
+ $this->accountSearchRepository->withFilterForOwner($text);
+ break;
+ case AccountSearchConstants::FILTER_GROUP_NAME:
$userGroupData = $this->userGroupService->getByName(Filter::safeSearchString($text));
- if (is_object($userGroupData)) {
- $queryCondition->addFilter(
- 'Account.userGroupId = ? OR Account.id IN (SELECT AccountToUserGroup.accountId FROM AccountToUserGroup WHERE AccountToUserGroup.accountId = id AND AccountToUserGroup.userGroupId = ?)',
- [$userGroupData->getId(), $userGroupData->getId()]
- );
- }
+ $this->accountSearchRepository->withFilterForGroup($userGroupData->getId());
break;
- case 'maingroup':
- $queryCondition->addFilter(
- 'Account.userGroupName LIKE ?',
- ['%'.Filter::safeSearchString($text).'%']
- );
+ case AccountSearchConstants::FILTER_MAIN_GROUP:
+ $this->accountSearchRepository->withFilterForMainGroup($text);
break;
- case 'file':
- $queryCondition->addFilter(
- 'Account.id IN (SELECT AccountFile.accountId FROM AccountFile WHERE AccountFile.name LIKE ?)',
- ['%'.$text.'%']
- );
+ case AccountSearchConstants::FILTER_FILE_NAME:
+ $this->accountSearchRepository->withFilterForFile($text);
break;
- case 'id':
- $queryCondition->addFilter(
- 'Account.id = ?',
- [(int)$text]
- );
+ case AccountSearchConstants::FILTER_ACCOUNT_ID:
+ $this->accountSearchRepository->withFilterForAccountId((int)$text);
break;
- case 'client':
- $queryCondition->addFilter(
- 'Account.clientName LIKE ?',
- ['%'.Filter::safeSearchString($text).'%']
- );
+ case AccountSearchConstants::FILTER_CLIENT_NAME:
+ $this->accountSearchRepository->withFilterForClient($text);
break;
- case 'category':
- $queryCondition->addFilter(
- 'Account.categoryName LIKE ?',
- ['%'.Filter::safeSearchString($text).'%']
- );
+ case AccountSearchConstants::FILTER_CATEGORY_NAME:
+ $this->accountSearchRepository->withFilterForCategory($text);
break;
- case 'name_regex':
- $queryCondition->addFilter(
- 'Account.name REGEXP ?',
- [$text]
- );
+ case AccountSearchConstants::FILTER_ACCOUNT_NAME_REGEX:
+ $this->accountSearchRepository->withFilterForAccountNameRegex($text);
break;
}
} catch (Exception $e) {
@@ -411,46 +230,24 @@ final class AccountSearchService extends Service implements AccountSearchService
}
}
- private function processFilterOperator(array $filters): void
+ private function processFilterConditions(array $filters,): void
{
- switch ($filters['op']) {
- case 'and':
- $this->filterOperator = QueryCondition::CONDITION_AND;
- break;
- case 'or':
- $this->filterOperator = QueryCondition::CONDITION_OR;
- break;
- }
- }
-
- private function processFilterIs(
- array $filters,
- QueryCondition $queryCondition
- ): void {
foreach ($filters as $filter) {
switch ($filter) {
- case 'is:expired':
- $queryCondition->addFilter(
- 'Account.passDateChange > 0 AND UNIX_TIMESTAMP() > Account.passDateChange',
- []
+ case AccountSearchConstants::FILTER_IS_EXPIRED:
+ $this->accountSearchRepository->withFilterForIsExpired();
+ break;
+ case AccountSearchConstants::FILTER_NOT_EXPIRED:
+ $this->accountSearchRepository->withFilterForIsNotExpired();
+ break;
+ case AccountSearchConstants::FILTER_IS_PRIVATE:
+ $this->accountSearchRepository->withFilterForIsPrivate(
+ $this->context->getUserData()->getId(),
+ $this->context->getUserData()->getUserGroupId()
);
break;
- case 'not:expired':
- $queryCondition->addFilter(
- 'Account.passDateChange = 0 OR Account.passDateChange IS NULL OR UNIX_TIMESTAMP() < Account.passDateChange',
- []
- );
- break;
- case 'is:private':
- $queryCondition->addFilter(
- '(Account.isPrivate = 1 AND Account.userId = ?) OR (Account.isPrivateGroup = 1 AND Account.userGroupId = ?)',
- [$this->context->getUserData()->getId(), $this->context->getUserData()->getUserGroupId()]
- );
- break;
- case 'not:private':
- $queryCondition->addFilter(
- '(Account.isPrivate = 0 OR Account.isPrivate IS NULL) AND (Account.isPrivateGroup = 0 OR Account.isPrivateGroup IS NULL)'
- );
+ case AccountSearchConstants::FILTER_NOT_PRIVATE:
+ $this->accountSearchRepository->withFilterForIsNotPrivate();
break;
}
}
@@ -462,9 +259,8 @@ final class AccountSearchService extends Service implements AccountSearchService
* @throws ConstraintException
* @throws QueryException
*/
- protected function getCacheForAccount(
- AccountSearchVData $accountSearchData
- ): AccountCache {
+ private function getCacheForAccount(AccountSearchVData $accountSearchData): AccountCache
+ {
$accountId = $accountSearchData->getId();
/** @var AccountCache[] $cache */
@@ -522,4 +318,65 @@ final class AccountSearchService extends Service implements AccountSearchService
{
return $this->cleanString;
}
+
+ /**
+ * @param \SP\Infrastructure\Database\QueryResult $queryResult
+ *
+ * @return array
+ * @throws \SP\Core\Exceptions\ConstraintException
+ * @throws \SP\Core\Exceptions\QueryException
+ */
+ private function buildAccountsData(QueryResult $queryResult): array
+ {
+ $maxTextLength = $this->configData->isResultsAsCards() ? 40 : 60;
+ $accountLinkEnabled = $this->context->getUserData()->getPreferences()->isAccountLink()
+ || $this->configData->isAccountLink();
+ $favorites = $this->accountToFavoriteService->getForUserId($this->context->getUserData()->getId());
+ $accountsData = [];
+
+ /** @var AccountSearchVData $accountSearchData */
+ foreach ($queryResult->getDataAsArray() as $accountSearchData) {
+ $cache = $this->getCacheForAccount($accountSearchData);
+
+ // Obtener la ACL de la cuenta
+ $accountAcl = $this->accountAclService->getAcl(
+ ActionsInterface::ACCOUNT_SEARCH,
+ AccountAclDto::makeFromAccountSearch(
+ $accountSearchData,
+ $cache->getUsers(),
+ $cache->getUserGroups()
+ )
+ );
+
+ // Propiedades de búsqueda de cada cuenta
+ $accountsSearchItem = new AccountSearchItem(
+ $accountSearchData,
+ $accountAcl,
+ $this->configData
+ );
+
+ if (!$accountSearchData->getIsPrivate()) {
+ $accountsSearchItem->setUsers($cache->getUsers());
+ $accountsSearchItem->setUserGroups($cache->getUserGroups());
+ }
+
+ $accountsSearchItem->setTags(
+ $this->accountToTagRepository
+ ->getTagsByAccountId($accountSearchData->getId())
+ ->getDataAsArray()
+ );
+ $accountsSearchItem->setTextMaxLength($maxTextLength);
+ $accountsSearchItem->setColor(
+ $this->pickAccountColor($accountSearchData->getClientId())
+ );
+ $accountsSearchItem->setLink($accountLinkEnabled);
+ $accountsSearchItem->setFavorite(
+ isset($favorites[$accountSearchData->getId()])
+ );
+
+ $accountsData[] = $accountsSearchItem;
+ }
+
+ return $accountsData;
+ }
}
\ No newline at end of file
diff --git a/lib/SP/Domain/Account/Services/AccountService.php b/lib/SP/Domain/Account/Services/AccountService.php
index 25e539d9..09d8b9d2 100644
--- a/lib/SP/Domain/Account/Services/AccountService.php
+++ b/lib/SP/Domain/Account/Services/AccountService.php
@@ -164,9 +164,7 @@ final class AccountService extends Service implements AccountServiceInterface
*/
public function getPasswordForId(int $id): AccountPassData
{
- $queryFilter = $this->accountFilterUser->getFilter();
-
- $result = $this->accountRepository->getPasswordForId($id, $queryFilter);
+ $result = $this->accountRepository->getPasswordForId($id);
if ($result->getNumRows() === 0) {
throw new NoSuchItemException(__u('Account not found'));
@@ -418,7 +416,7 @@ final class AccountService extends Service implements AccountServiceInterface
*/
public function update(AccountRequest $accountRequest): void
{
- $this->transactionAware(
+ $this->accountRepository->transactionAware(
function () use ($accountRequest) {
$userData = $this->context->getUserData();
$userProfile = $this->context->getUserProfile() ?? new ProfileData();
@@ -535,7 +533,7 @@ final class AccountService extends Service implements AccountServiceInterface
*/
public function updateBulk(AccountBulkRequest $request): void
{
- $this->transactionAware(
+ $this->accountRepository->transactionAware(
function () use ($request) {
foreach ($request->getItemsId() as $itemId) {
$accountRequest = $request->getAccountRequestForId($itemId);
@@ -557,16 +555,18 @@ final class AccountService extends Service implements AccountServiceInterface
*/
public function editPassword(AccountRequest $accountRequest): void
{
- $this->transactionAware(function () use ($accountRequest) {
- $this->addHistory($accountRequest->id);
+ $this->accountRepository->transactionAware(
+ function () use ($accountRequest) {
+ $this->addHistory($accountRequest->id);
- $pass = $this->getPasswordEncrypted($accountRequest->pass);
+ $pass = $this->getPasswordEncrypted($accountRequest->pass);
- $accountRequest->pass = $pass['pass'];
- $accountRequest->key = $pass['key'];
+ $accountRequest->pass = $pass['pass'];
+ $accountRequest->key = $pass['key'];
- $this->accountRepository->editPassword($accountRequest);
- });
+ $this->accountRepository->editPassword($accountRequest);
+ }
+ );
}
/**
@@ -585,14 +585,17 @@ final class AccountService extends Service implements AccountServiceInterface
* @param int $accountId
*
* @throws \SP\Domain\Common\Services\ServiceException
+ * @throws \SP\Infrastructure\Common\Repositories\NoSuchItemException
*/
public function editRestore(int $historyId, int $accountId): void
{
- $this->transactionAware(
+ $accountHistoryData = $this->accountHistoryService->getById($historyId);
+
+ $this->accountRepository->transactionAware(
function () use ($historyId, $accountId) {
$this->addHistory($accountId);
- if (!$this->accountRepository->editRestore($historyId, $this->context->getUserData()->getId())) {
+ if (!$this->accountRepository->editRestore($accountHistoryData, $this->context->getUserData()->getId())) {
throw new ServiceException(__u('Error on restoring the account'));
}
}
@@ -604,13 +607,15 @@ final class AccountService extends Service implements AccountServiceInterface
*/
public function delete(int $id): AccountService
{
- $this->transactionAware(function () use ($id) {
- $this->addHistory($id, 1);
+ $this->accountRepository->transactionAware(
+ function () use ($id) {
+ $this->addHistory($id, 1);
- if ($this->accountRepository->delete($id) === 0) {
- throw new NoSuchItemException(__u('Account not found'));
+ if ($this->accountRepository->delete($id) === 0) {
+ throw new NoSuchItemException(__u('Account not found'));
+ }
}
- });
+ );
return $this;
}
@@ -634,18 +639,9 @@ final class AccountService extends Service implements AccountServiceInterface
* @throws QueryException
* @throws ConstraintException
*/
- public function getForUser(int $accountId = null): array
+ public function getForUser(?int $accountId = null): array
{
- $queryFilter = $this->accountFilterUser->getFilter();
-
- if (null !== $accountId) {
- $queryFilter->addFilter(
- 'Account.id <> ? AND (Account.parentId = 0 OR Account.parentId IS NULL)',
- [$accountId]
- );
- }
-
- return $this->accountRepository->getForUser($queryFilter)->getDataAsArray();
+ return $this->accountRepository->getForUser($accountId)->getDataAsArray();
}
/**
@@ -654,11 +650,7 @@ final class AccountService extends Service implements AccountServiceInterface
*/
public function getLinked(int $accountId): array
{
- $queryFilter = $this->accountFilterUser->getFilter();
-
- $queryFilter->addFilter('Account.parentId = ?', [$accountId]);
-
- return $this->accountRepository->getLinked($queryFilter)->getDataAsArray();
+ return $this->accountRepository->getLinked($accountId)->getDataAsArray();
}
/**
@@ -668,10 +660,7 @@ final class AccountService extends Service implements AccountServiceInterface
*/
public function getPasswordHistoryForId(int $id): AccountPassData
{
- $queryFilter = $this->accountFilterUser->getFilterHistory();
- $queryFilter->addFilter('AccountHistory.id = ?', [$id]);
-
- $result = $this->accountRepository->getPasswordHistoryForId($queryFilter);
+ $result = $this->accountRepository->getPasswordHistoryForId($id);
if ($result->getNumRows() === 0) {
throw new NoSuchItemException(__u('The account doesn\'t exist'));
@@ -739,22 +728,4 @@ final class AccountService extends Service implements AccountServiceInterface
{
return $this->accountRepository->getAccountsPassData()->getDataAsArray();
}
-
- /**
- * Obtener las cuentas de una búsqueda.
- *
- * @param \SP\Domain\Account\Services\AccountSearchFilter $accountSearchFilter
- *
- * @return \SP\Infrastructure\Database\QueryResult
- * @throws \SP\Core\Exceptions\ConstraintException
- * @throws \SP\Core\Exceptions\QueryException
- * @throws \SP\Core\Exceptions\SPException
- */
- public function getByFilter(AccountSearchFilter $accountSearchFilter): QueryResult
- {
- return $this->accountRepository->getByFilter(
- $accountSearchFilter,
- $this->accountFilterUser->getFilter($accountSearchFilter->getGlobalSearch())
- );
- }
}
\ No newline at end of file
diff --git a/lib/SP/Domain/Client/Services/ClientService.php b/lib/SP/Domain/Client/Services/ClientService.php
index 5d63c011..4d4ea0c4 100644
--- a/lib/SP/Domain/Client/Services/ClientService.php
+++ b/lib/SP/Domain/Client/Services/ClientService.php
@@ -185,6 +185,6 @@ final class ClientService extends Service implements ClientServiceInterface
*/
public function getAllForUser(): array
{
- return $this->clientRepository->getAllForFilter($this->accountFilterUser->getFilter())->getDataAsArray();
+ return $this->clientRepository->getAllForFilter($this->accountFilterUser->buildFilter())->getDataAsArray();
}
}
\ No newline at end of file
diff --git a/lib/SP/Infrastructure/Account/Repositories/AccountRepository.php b/lib/SP/Infrastructure/Account/Repositories/AccountRepository.php
index 9279e5ee..c0d7159c 100644
--- a/lib/SP/Infrastructure/Account/Repositories/AccountRepository.php
+++ b/lib/SP/Infrastructure/Account/Repositories/AccountRepository.php
@@ -24,29 +24,25 @@
namespace SP\Infrastructure\Account\Repositories;
+use Aura\SqlQuery\QueryFactory;
use RuntimeException;
+use SP\Core\Context\ContextInterface;
+use SP\Core\Events\EventDispatcherInterface;
use SP\Core\Exceptions\ConstraintException;
use SP\Core\Exceptions\QueryException;
use SP\Core\Exceptions\SPException;
-use SP\DataModel\AccountExtData;
-use SP\DataModel\AccountSearchVData;
-use SP\DataModel\AccountVData;
-use SP\DataModel\ItemData;
+use SP\DataModel\AccountHistoryData;
use SP\DataModel\ItemSearchData;
use SP\Domain\Account\In\AccountRepositoryInterface;
-use SP\Domain\Account\Out\AccountData;
-use SP\Domain\Account\Out\AccountPassData;
+use SP\Domain\Account\Services\AccountFilterUser;
use SP\Domain\Account\Services\AccountPasswordRequest;
use SP\Domain\Account\Services\AccountRequest;
-use SP\Domain\Account\Services\AccountSearchFilter;
use SP\Domain\Common\Out\SimpleModel;
use SP\Infrastructure\Common\Repositories\Repository;
use SP\Infrastructure\Common\Repositories\RepositoryItemTrait;
+use SP\Infrastructure\Database\DatabaseInterface;
use SP\Infrastructure\Database\QueryData;
use SP\Infrastructure\Database\QueryResult;
-use SP\Mvc\Model\QueryAssignment;
-use SP\Mvc\Model\QueryCondition;
-use SP\Mvc\Model\QueryJoin;
/**
* Class AccountRepository
@@ -57,64 +53,77 @@ final class AccountRepository extends Repository implements AccountRepositoryInt
{
use RepositoryItemTrait;
+ private AccountFilterUser $accountFilterUser;
+
+ public function __construct(
+ DatabaseInterface $database,
+ ContextInterface $session,
+ QueryFactory $queryFactory,
+ EventDispatcherInterface $eventDispatcher,
+ AccountFilterUser $accountFilterUser
+ ) {
+ parent::__construct($database, $session, $eventDispatcher, $queryFactory);
+
+ $this->accountFilterUser = $accountFilterUser;
+ }
+
/**
* Devolver el número total de cuentas
*/
public function getTotalNumAccounts(): SimpleModel
{
- $queryData = new QueryData();
- $queryData->setMapClassName(SimpleModel::class);
- $queryData->setQuery(AccountRepositorySql::TOTAL_NUM_ACCOUNTS);
+ $query = $this->queryFactory
+ ->newSelect()
+ ->cols(['SUM(n) AS num'])
+ ->fromSubSelect('SELECT COUNT(*) AS n FROM Account UNION SELECT COUNT(*) AS n FROM AccountHistory', 'a');
- return $this->db->doSelect($queryData)->getData();
+ return $this->db->doSelect(QueryData::build($query))->getData();
}
/**
* @param int $id
- * @param QueryCondition $queryCondition
*
* @return QueryResult
*/
- public function getPasswordForId(int $id, QueryCondition $queryCondition): QueryResult
+ public function getPasswordForId(int $id): QueryResult
{
- $queryCondition->addFilter('Account.id = ?', [$id]);
+ $query = $this->accountFilterUser
+ ->buildFilter()
+ ->cols([
+ 'Account.id,',
+ 'Account.name',
+ 'Account.login',
+ 'Account.pass',
+ 'Account.key',
+ 'Account.parentId',
+ ])
+ ->where('Account.id = :id', ['id' => $id])
+ ->limit(1);
- $queryData = new QueryData();
- $queryData->setMapClassName(AccountPassData::class);
- $queryData->setLimit(1);
- $queryData->setSelect('Account.id, Account.name, Account.login, Account.pass, Account.key, Account.parentId');
- $queryData->setFrom('Account');
- $queryData->setWhere($queryCondition->getFilters());
- $queryData->setParams($queryCondition->getParams());
-
- return $this->db->doSelect($queryData);
+ return $this->db->doSelect(QueryData::build($query));
}
/**
- * @param QueryCondition $queryCondition
+ * @param int $id
*
* @return QueryResult
*/
- public function getPasswordHistoryForId(QueryCondition $queryCondition): QueryResult
+ public function getPasswordHistoryForId(int $id): QueryResult
{
- $query = /** @lang SQL */
- 'SELECT
- AccountHistory.id,
- AccountHistory.name,
- AccountHistory.login,
- AccountHistory.pass,
- AccountHistory.key,
- AccountHistory.parentId,
- AccountHistory.mPassHash
- FROM AccountHistory
- WHERE '.$queryCondition->getFilters();
+ $query = $this->accountFilterUser
+ ->buildFilterHistory()
+ ->cols([
+ 'AccountHistory.id,',
+ 'AccountHistory.name',
+ 'AccountHistory.login',
+ 'AccountHistory.pass',
+ 'AccountHistory.key',
+ 'AccountHistory.parentId',
+ 'AccountHistory.mPassHash',
+ ])
+ ->where('AccountHistory.id = :id', ['id' => $id]);
- $queryData = new QueryData();
- $queryData->setMapClassName(AccountPassData::class);
- $queryData->setQuery($query);
- $queryData->setParams($queryCondition->getParams());
-
- return $this->db->doSelect($queryData);
+ return $this->db->doSelect(QueryData::build($query));
}
/**
@@ -128,11 +137,13 @@ final class AccountRepository extends Repository implements AccountRepositoryInt
*/
public function incrementDecryptCounter(int $id): bool
{
- $queryData = new QueryData();
- $queryData->setQuery(AccountRepositorySql::INCREMENT_DECRYPT_COUNTER);
- $queryData->addParam($id);
+ $query = $this->queryFactory
+ ->newUpdate()
+ ->table('Account')
+ ->set('countDecrypt', '(countDecrypt + 1)')
+ ->where('id = :id', ['id' => $id]);
- return $this->db->doQuery($queryData)->getAffectedNumRows() === 1;
+ return $this->db->doQuery(QueryData::build($query))->getAffectedNumRows() === 1;
}
/**
@@ -146,26 +157,30 @@ final class AccountRepository extends Repository implements AccountRepositoryInt
*/
public function create($itemData): int
{
- $queryData = new QueryData();
- $queryData->setQuery(AccountRepositorySql::CREATE);
- $queryData->setParams([
- $itemData->clientId,
- $itemData->categoryId,
- $itemData->name,
- $itemData->login,
- $itemData->url,
- $itemData->pass,
- $itemData->key,
- $itemData->notes,
- $itemData->userId,
- $itemData->userGroupId,
- $itemData->userId,
- $itemData->isPrivate,
- $itemData->isPrivateGroup,
- $itemData->passDateChange,
- $itemData->parentId,
- ]);
- $queryData->setOnErrorMessage(__u('Error while creating the account'));
+ $query = $this->queryFactory
+ ->newInsert()
+ ->into('Account')
+ ->cols([
+ 'clientId' => $itemData->clientId,
+ 'categoryId' => $itemData->categoryId,
+ 'name' => $itemData->name,
+ 'login' => $itemData->login,
+ 'url' => $itemData->url,
+ 'pass' => $itemData->pass,
+ 'key' => $itemData->key,
+ 'notes' => $itemData->notes,
+ 'userId' => $itemData->userId,
+ 'userGroupId' => $itemData->userGroupId,
+ 'userEditId' => $itemData->userId,
+ 'isPrivate' => $itemData->isPrivate,
+ 'isPrivateGroup' => $itemData->isPrivateGroup,
+ 'passDateChange' => $itemData->passDateChange,
+ 'parentId' => $itemData->parentId,
+ ])
+ ->set('dateAdd', 'NOW()')
+ ->set('passDate', 'UNIX_TIMESTAMP()');
+
+ $queryData = QueryData::build($query)->setOnErrorMessage(__u('Error while creating the account'));
return $this->db->doQuery($queryData)->getLastId();
}
@@ -181,16 +196,20 @@ final class AccountRepository extends Repository implements AccountRepositoryInt
*/
public function editPassword(AccountRequest $accountRequest): int
{
- $queryData = new QueryData();
- $queryData->setQuery(AccountRepositorySql::EDIT_PASSWORD);
- $queryData->setParams([
- $accountRequest->pass,
- $accountRequest->key,
- $accountRequest->userEditId,
- $accountRequest->passDateChange,
- $accountRequest->id,
- ]);
- $queryData->setOnErrorMessage(__u('Error while updating the password'));
+ $query = $this->queryFactory
+ ->newUpdate()
+ ->table('Account')
+ ->cols([
+ 'pass' => $accountRequest->pass,
+ 'key' => $accountRequest->key,
+ 'userEditId' => $accountRequest->userEditId,
+ 'passDateChange' => $accountRequest->passDateChange,
+ ])
+ ->set('dateEdit', 'NOW()')
+ ->set('passDate', 'UNIX_TIMESTAMP()')
+ ->where('id = :id', ['id' => $accountRequest->id]);
+
+ $queryData = QueryData::build($query)->setOnErrorMessage(__u('Error while updating the password'));
return $this->db->doQuery($queryData)->getAffectedNumRows();
}
@@ -206,10 +225,13 @@ final class AccountRepository extends Repository implements AccountRepositoryInt
*/
public function updatePassword(AccountPasswordRequest $request): bool
{
- $queryData = new QueryData();
- $queryData->setQuery(AccountRepositorySql::UPDATE_PASSWORD);
- $queryData->setParams([$request->pass, $request->key, $request->id]);
- $queryData->setOnErrorMessage(__u('Error while updating the password'));
+ $query = $this->queryFactory
+ ->newUpdate()
+ ->table('Account')
+ ->cols(['pass' => $request->pass, 'key' => $request->key])
+ ->where('id = :id', ['id' => $request->id]);
+
+ $queryData = QueryData::build($query)->setOnErrorMessage(__u('Error while updating the password'));
return $this->db->doQuery($queryData)->getAffectedNumRows() === 1;
}
@@ -217,19 +239,39 @@ final class AccountRepository extends Repository implements AccountRepositoryInt
/**
* Restaurar una cuenta desde el histórico.
*
- * @param int $historyId El Id del registro en el histórico
+ * @param \SP\DataModel\AccountHistoryData $accountHistoryData
* @param int $userId User's Id
*
* @return bool
- * @throws ConstraintException
- * @throws QueryException
+ * @throws \SP\Core\Exceptions\ConstraintException
+ * @throws \SP\Core\Exceptions\QueryException
*/
- public function editRestore(int $historyId, int $userId): bool
+ public function editRestore(AccountHistoryData $accountHistoryData, int $userId): bool
{
- $queryData = new QueryData();
- $queryData->setQuery(AccountRepositorySql::EDIT_RESTORE);
- $queryData->setParams([$historyId, $userId]);
- $queryData->setOnErrorMessage(__u('Error on restoring the account'));
+ $query = $this->queryFactory
+ ->newUpdate()
+ ->table('Account')
+ ->cols([
+ 'clientId' => $accountHistoryData->getClientId(),
+ 'categoryId' => $accountHistoryData->getCategoryId(),
+ 'name' => $accountHistoryData->getName(),
+ 'login' => $accountHistoryData->getLogin(),
+ 'url' => $accountHistoryData->getUrl(),
+ 'notes' => $accountHistoryData->getNotes(),
+ 'userGroupId' => $accountHistoryData->getUserGroupId(),
+ 'userEditId' => $userId,
+ 'pass' => $accountHistoryData->getPass(),
+ 'key' => $accountHistoryData->getKey(),
+ 'passDate' => $accountHistoryData->getPassDate(),
+ 'passDateChange' => $accountHistoryData->getPassDateChange(),
+ 'parentId' => $accountHistoryData->getParentId(),
+ 'isPrivate' => $accountHistoryData->getIsPrivate(),
+ 'isPrivateGroup' => $accountHistoryData->getIsPrivateGroup(),
+ ])
+ ->set('dateEdit', 'NOW()')
+ ->where('id = :id', ['id' => $accountHistoryData->getAccountId()]);
+
+ $queryData = QueryData::build($query)->setOnErrorMessage(__u('Error on restoring the account'));
return $this->db->doQuery($queryData)->getAffectedNumRows() === 1;
}
@@ -245,10 +287,12 @@ final class AccountRepository extends Repository implements AccountRepositoryInt
*/
public function delete(int $id): int
{
- $queryData = new QueryData();
- $queryData->setQuery(AccountRepositorySql::DELETE);
- $queryData->addParam($id);
- $queryData->setOnErrorMessage(__u('Error while deleting the account'));
+ $query = $this->queryFactory
+ ->newDelete()
+ ->from('Account')
+ ->where('id = :id', ['id' => $id]);
+
+ $queryData = QueryData::build($query)->setOnErrorMessage(__u('Error while deleting the account'));
return $this->db->doQuery($queryData)->getAffectedNumRows();
}
@@ -263,53 +307,34 @@ final class AccountRepository extends Repository implements AccountRepositoryInt
*/
public function update($itemData): int
{
- $queryAssignment = new QueryAssignment();
-
- $queryAssignment->setFields([
- 'clientId',
- 'categoryId',
- 'name',
- 'login',
- 'url',
- 'notes',
- 'userEditId',
- 'dateEdit = NOW()',
- 'passDateChange',
- 'isPrivate',
- 'isPrivateGroup',
- 'parentId',
- ], [
- $itemData->clientId,
- $itemData->categoryId,
- $itemData->name,
- $itemData->login,
- $itemData->url,
- $itemData->notes,
- $itemData->userEditId,
- $itemData->passDateChange,
- $itemData->isPrivate,
- $itemData->isPrivateGroup,
- $itemData->parentId,
- ]);
-
-
- $queryData = new QueryData();
+ $query = $this->queryFactory
+ ->newUpdate()
+ ->table('Account')
+ ->where('id = :id', ['id' => $itemData->id])
+ ->cols([
+ 'clientId' => $itemData->clientId,
+ 'categoryId' => $itemData->categoryId,
+ 'name' => $itemData->name,
+ 'login' => $itemData->login,
+ 'url' => $itemData->url,
+ 'notes' => $itemData->notes,
+ 'userEditId' => $itemData->userEditId,
+ 'passDateChange' => $itemData->passDateChange,
+ 'isPrivate' => $itemData->isPrivate,
+ 'isPrivateGroup' => $itemData->isPrivateGroup,
+ 'parentId' => $itemData->parentId,
+ ])
+ ->set('dateEdit', 'NOW()');
if ($itemData->changeUserGroup) {
- $queryAssignment->addField('userGroupId', $itemData->userGroupId);
+ $query->col('userGroupId', $itemData->userGroupId);
}
if ($itemData->changeOwner) {
- $queryAssignment->addField('userId', $itemData->userId);
+ $query->col('userId', $itemData->userId);
}
- $query = /** @lang SQL */
- 'UPDATE Account SET '.$queryAssignment->getAssignments().' WHERE id = ?';
-
- $queryData->setQuery($query);
- $queryData->setParams($queryAssignment->getValues());
- $queryData->addParam($itemData->id);
- $queryData->setOnErrorMessage(__u('Error while updating the account'));
+ $queryData = QueryData::build($query)->setOnErrorMessage(__u('Error while updating the account'));
return $this->db->doQuery($queryData)->getAffectedNumRows();
}
@@ -324,16 +349,14 @@ final class AccountRepository extends Repository implements AccountRepositoryInt
*/
public function updateBulk(AccountRequest $itemData): int
{
- $queryAssignment = new QueryAssignment();
-
- $queryAssignment->setFields([
- 'userEditId',
- 'dateEdit = NOW()',
- ], [
- $itemData->userEditId,
- ]);
-
- $queryData = new QueryData();
+ $query = $this->queryFactory
+ ->newUpdate()
+ ->table('Account')
+ ->where('id = :id', ['id' => $itemData->id])
+ ->cols([
+ 'userEditId' => $itemData->userEditId,
+ ])
+ ->set('dateEdit', 'NOW()');
$optional = ['clientId', 'categoryId', 'userId', 'userGroupId', 'passDateChange'];
@@ -341,7 +364,7 @@ final class AccountRepository extends Repository implements AccountRepositoryInt
foreach ($optional as $field) {
if (isset($itemData->{$field}) && !empty($itemData->{$field})) {
- $queryAssignment->addField($field, $itemData->{$field});
+ $query->col($field, $itemData->{$field});
$optionalCount++;
} else {
logger(sprintf('Field \'%s\' not found in $itemData', $field), 'ERROR');
@@ -352,13 +375,7 @@ final class AccountRepository extends Repository implements AccountRepositoryInt
return 0;
}
- $query = /** @lang SQL */
- 'UPDATE Account SET '.$queryAssignment->getAssignments().' WHERE id = ?';
-
- $queryData->setQuery($query);
- $queryData->setParams($queryAssignment->getValues());
- $queryData->addParam($itemData->id);
- $queryData->setOnErrorMessage(__u('Error while updating the account'));
+ $queryData = QueryData::build($query)->setOnErrorMessage(__u('Error while updating the account'));
return $this->db->doQuery($queryData)->getAffectedNumRows();
}
@@ -372,11 +389,13 @@ final class AccountRepository extends Repository implements AccountRepositoryInt
*/
public function getById(int $id): QueryResult
{
- $queryData = new QueryData();
- $queryData->setQuery(AccountRepositorySql::EDIT_BY_ID);
- $queryData->setMapClassName(AccountVData::class);
- $queryData->addParam($id);
- $queryData->setOnErrorMessage(__u('Error while retrieving account\'s data'));
+ $query = $this->queryFactory
+ ->newSelect()
+ ->from('account_data_v')
+ ->where('id = :id', ['id' => $id])
+ ->limit(1);
+
+ $queryData = QueryData::build($query)->setOnErrorMessage(__u('Error while retrieving account\'s data'));
return $this->db->doSelect($queryData);
}
@@ -388,11 +407,9 @@ final class AccountRepository extends Repository implements AccountRepositoryInt
*/
public function getAll(): QueryResult
{
- $queryData = new QueryData();
- $queryData->setMapClassName(AccountData::class);
- $queryData->setQuery(AccountRepositorySql::GET_ALL);
+ $query = $this->queryFactory->newSelect()->from('Account');
- return $this->db->doSelect($queryData);
+ return $this->db->doSelect(QueryData::build($query));
}
/**
@@ -420,11 +437,11 @@ final class AccountRepository extends Repository implements AccountRepositoryInt
return 0;
}
- $queryData = new QueryData();
-
- $queryData->setQuery('DELETE FROM Account WHERE id IN ('.$this->getParamsFromArray($ids).')');
- $queryData->setParams($ids);
- $queryData->setOnErrorMessage(__u('Error while deleting the accounts'));
+ $query = $this->queryFactory
+ ->newDelete()
+ ->from('Account')
+ ->where('id IN (:id)', $ids);
+ $queryData = QueryData::build($query)->setOnErrorMessage(__u('Error while deleting the accounts'));
return $this->db->doQuery($queryData)->getAffectedNumRows();
}
@@ -468,34 +485,41 @@ final class AccountRepository extends Repository implements AccountRepositoryInt
*/
public function search(ItemSearchData $itemSearchData): QueryResult
{
- $queryData = new QueryData();
- $queryData->setSelect('id, name, clientName, categoryName, userName, userGroupName');
- $queryData->setFrom('account_search_v');
- $queryData->setOrder('name, clientName');
+ $query = $this->queryFactory
+ ->newSelect()
+ ->from('account_search_v')
+ ->cols([
+ 'id',
+ 'name',
+ 'clientName',
+ 'categoryName',
+ 'userName',
+ 'userGroupName',
+
+ ])
+ ->orderBy(['name ASC', 'clientName ASC'])
+ ->limit($itemSearchData->getLimitCount())
+ ->offset($itemSearchData->getLimitStart());
if (!empty($itemSearchData->getSeachString())) {
- $queryData->setWhere(
- 'name LIKE ?
- OR clientName LIKE ?
- OR categoryName LIKE ?
- OR userName LIKE ?
- OR userGroupName LIKE ?'
- );
+ $query->where('name LIKE :name')
+ ->orWhere('clientName LIKE :clientName')
+ ->orWhere('categoryName LIKE :categoryName')
+ ->orWhere('userName LIKE :userName')
+ ->orWhere('userGroupName LIKE :userGroupName');
$search = '%'.$itemSearchData->getSeachString().'%';
- $queryData->addParam($search);
- $queryData->addParam($search);
- $queryData->addParam($search);
- $queryData->addParam($search);
- $queryData->addParam($search);
+
+ $query->bindValues([
+ 'name' => $search,
+ 'clientName' => $search,
+ 'categoryName' => $search,
+ 'userName' => $search,
+ 'userGroupName' => $search,
+ ]);
}
- $queryData->setLimit(
- '?,?',
- [$itemSearchData->getLimitStart(), $itemSearchData->getLimitCount()]
- );
-
- return $this->db->doSelect($queryData, true);
+ return $this->db->doSelect(QueryData::build($query), true);
}
/**
@@ -509,11 +533,13 @@ final class AccountRepository extends Repository implements AccountRepositoryInt
*/
public function incrementViewCounter(int $id): bool
{
- $queryData = new QueryData();
- $queryData->setQuery(AccountRepositorySql::INCREMENT_VIEW_COUNTER);
- $queryData->addParam($id);
+ $query = $this->queryFactory
+ ->newUpdate()
+ ->table('Account')
+ ->set('countView', '(countView + 1)')
+ ->where('id = :id', ['id' => $id]);
- return $this->db->doQuery($queryData)->getAffectedNumRows() === 1;
+ return $this->db->doQuery(QueryData::build($query))->getAffectedNumRows() === 1;
}
/**
@@ -525,164 +551,76 @@ final class AccountRepository extends Repository implements AccountRepositoryInt
*/
public function getDataForLink(int $id): QueryResult
{
- $queryData = new QueryData();
- $queryData->setQuery(AccountRepositorySql::GET_DATA_FOR_LINK);
- $queryData->setMapClassName(AccountExtData::class);
- $queryData->addParam($id);
- $queryData->setOnErrorMessage(__u('Error while retrieving account\'s data'));
+ $query = $this->queryFactory
+ ->newSelect()
+ ->from('Account')
+ ->join('INNER', 'Client', 'Account.clientId = Client.id')
+ ->join('INNER', 'Category', 'Account.categoryId = Category.id')
+ ->cols([
+ 'Account.name',
+ 'Account.login',
+ 'Account.pass',
+ 'Account.key',
+ 'Account.url',
+ 'Account.notes',
+ 'Client.name AS clientName',
+ 'Category.name AS categoryName',
+ ])
+ ->where('Account.id = :id', ['id' => $id]);
+
+ $queryData = QueryData::build($query)->setOnErrorMessage(__u('Error while retrieving account\'s data'));
return $this->db->doSelect($queryData);
}
/**
- * Obtener las cuentas de una búsqueda.
- *
- * @param AccountSearchFilter $accountSearchFilter
- * @param QueryCondition $queryFilterUser
+ * @param int|null $accountId
*
* @return QueryResult
*/
- public function getByFilter(
- AccountSearchFilter $accountSearchFilter,
- QueryCondition $queryFilterUser
- ): QueryResult {
- $queryFilters = new QueryCondition();
-
- // Sets the search text depending on if special search filters are being used
- $searchText = $accountSearchFilter->getCleanTxtSearch();
-
- if (!empty($searchText)) {
- $queryFilters->addFilter(
- 'Account.name LIKE ? OR Account.login LIKE ? OR Account.url LIKE ? OR Account.notes LIKE ?',
- array_fill(0, 4, '%'.$searchText.'%')
- );
- }
-
- // Gets special search filters
- $stringFilters = $accountSearchFilter->getStringFilters();
-
- if ($stringFilters->hasFilters()) {
- $queryFilters->addFilter(
- $stringFilters->getFilters($accountSearchFilter->getFilterOperator()),
- $stringFilters->getParams()
- );
- }
-
- if ($accountSearchFilter->getCategoryId() !== null) {
- $queryFilters->addFilter(
- 'Account.categoryId = ?',
- [$accountSearchFilter->getCategoryId()]
- );
- }
-
- if ($accountSearchFilter->getClientId() !== null) {
- $queryFilters->addFilter(
- 'Account.clientId = ?',
- [$accountSearchFilter->getClientId()]
- );
- }
-
- $where = [];
-
- if ($queryFilterUser->hasFilters()) {
- $where[] = $queryFilterUser->getFilters();
- }
-
- $queryData = new QueryData();
- $queryJoins = new QueryJoin();
-
- if ($accountSearchFilter->isSearchFavorites() === true) {
- $queryJoins->addJoin(
- 'INNER JOIN AccountToFavorite ON (AccountToFavorite.accountId = Account.id AND AccountToFavorite.userId = ?)',
- [$this->context->getUserData()->getId()]
- );
- }
-
- if ($accountSearchFilter->hasTags()) {
- $queryJoins->addJoin('INNER JOIN AccountToTag ON AccountToTag.accountId = Account.id');
- $queryFilters->addFilter(
- 'AccountToTag.tagId IN ('.$this->getParamsFromArray($accountSearchFilter->getTagsId()).')',
- $accountSearchFilter->getTagsId()
- );
-
- if (QueryCondition::CONDITION_AND === $accountSearchFilter->getFilterOperator()) {
- $groupBy = sprintf(
- 'Account.id HAVING COUNT(DISTINCT AccountToTag.tagId) = %d',
- count($accountSearchFilter->getTagsId())
- );
-
- $queryData->setGroupBy($groupBy);
- }
- }
-
- if ($queryFilters->hasFilters()) {
- $where[] = $queryFilters->getFilters($accountSearchFilter->getFilterOperator());
- }
-
- $queryData->setWhere($where);
- $queryData->setParams(
- array_merge(
- $queryJoins->getParams(),
- $queryFilterUser->getParams(),
- $queryFilters->getParams()
+ public function getForUser(?int $accountId = null): QueryResult
+ {
+ $query = $this->accountFilterUser
+ ->buildFilter()
+ ->cols(
+ [
+ 'Account.id',
+ 'Account.name',
+ 'C.name AS clientName',
+ ]
)
- );
- $queryData->setSelect('DISTINCT Account.*');
- $queryData->setFrom('account_search_v Account '.$queryJoins->getJoins());
- $queryData->setOrder($accountSearchFilter->getOrderString());
+ ->join('LEFT', 'Client AS C', 'Account.clientId = C.id')
+ ->orderBy(['Account.name ASC']);
- if ($accountSearchFilter->getLimitCount() > 0) {
- $queryLimit = '?, ?';
-
- $queryData->addParam($accountSearchFilter->getLimitStart());
- $queryData->addParam($accountSearchFilter->getLimitCount());
- $queryData->setLimit($queryLimit);
+ if ($accountId) {
+ $query->where('Account.id <> :id', ['id' => $accountId]);
+ $query->where('Account.parentId = 0 OR Account.parentId IS NULL');
}
- $queryData->setMapClassName(AccountSearchVData::class);
-
- return $this->db->doSelect($queryData, true);
+ return $this->db->doSelect(QueryData::build($query));
}
/**
- * @param QueryCondition $queryFilter
+ * @param int $accountId
*
* @return QueryResult
*/
- public function getForUser(QueryCondition $queryFilter): QueryResult
+ public function getLinked(int $accountId): QueryResult
{
- $query = /** @lang SQL */
- 'SELECT Account.id, Account.name, C.name AS clientName
- FROM Account
- LEFT JOIN Client C ON Account.clientId = C.id
- WHERE '.$queryFilter->getFilters().' ORDER BY name';
+ $query = $this->accountFilterUser
+ ->buildFilter()
+ ->cols(
+ [
+ 'Account.id',
+ 'Account.name',
+ 'Client.name AS clientName',
+ ]
+ )
+ ->join('INNER', 'Client', 'Account.clientId = Client.id')
+ ->where('Account.parentId = :parentId', ['parentId' => $accountId])
+ ->orderBy(['Account.name ASC']);
- $queryData = new QueryData();
- $queryData->setMapClassName(ItemData::class);
- $queryData->setQuery($query);
- $queryData->setParams($queryFilter->getParams());
-
- return $this->db->doSelect($queryData);
- }
-
- /**
- * @param QueryCondition $queryFilter
- *
- * @return QueryResult
- */
- public function getLinked(QueryCondition $queryFilter): QueryResult
- {
- $query = /** @lang SQL */
- 'SELECT Account.id, Account.name, Client.name AS clientName
- FROM Account
- INNER JOIN Client ON Account.clientId = Client.id
- WHERE '.$queryFilter->getFilters().' ORDER BY Account.name';
-
- $queryData = new QueryData();
- $queryData->setQuery($query);
- $queryData->setParams($queryFilter->getParams());
-
- return $this->db->doSelect($queryData);
+ return $this->db->doSelect(QueryData::build($query));
}
/**
@@ -692,9 +630,19 @@ final class AccountRepository extends Repository implements AccountRepositoryInt
*/
public function getAccountsPassData(): QueryResult
{
- $queryData = new QueryData();
- $queryData->setQuery(AccountRepositorySql::GET_ACCOUNT_PASS_DATA);
+ $query = $this->queryFactory
+ ->newSelect()
+ ->from('Account')
+ ->cols(
+ [
+ 'id',
+ 'name',
+ 'pass',
+ 'key',
+ ]
+ )
+ ->where('BIT_LENGTH(pass) > 0');
- return $this->db->doSelect($queryData);
+ return $this->db->doSelect(QueryData::build($query));
}
}
\ No newline at end of file
diff --git a/lib/SP/Infrastructure/Account/Repositories/AccountRepositorySql.php b/lib/SP/Infrastructure/Account/Repositories/AccountRepositorySql.php
deleted file mode 100644
index 3f301d39..00000000
--- a/lib/SP/Infrastructure/Account/Repositories/AccountRepositorySql.php
+++ /dev/null
@@ -1,114 +0,0 @@
-.
- */
-
-namespace SP\Infrastructure\Account\Repositories;
-
-
-/**
- * Class AccountRepositorySql
- */
-final class AccountRepositorySql
-{
- public const TOTAL_NUM_ACCOUNTS = 'SELECT SUM(n) AS num FROM
- (SELECT COUNT(*) AS n FROM Account UNION SELECT COUNT(*) AS n FROM AccountHistory) a';
-
- public const INCREMENT_DECRYPT_COUNTER = 'UPDATE Account SET countDecrypt = (countDecrypt + 1) WHERE id = ? LIMIT 1';
-
- public const CREATE = 'INSERT INTO Account SET
- clientId = ?,
- categoryId = ?,
- `name` = ?,
- login = ?,
- url = ?,
- pass = ?,
- `key` = ?,
- notes = ?,
- dateAdd = NOW(),
- userId = ?,
- userGroupId = ?,
- userEditId = ?,
- isPrivate = ?,
- isPrivateGroup = ?,
- passDate = UNIX_TIMESTAMP(),
- passDateChange = ?,
- parentId = ?';
-
- public const EDIT_PASSWORD = 'UPDATE Account SET
- pass = ?,
- `key` = ?,
- userEditId = ?,
- dateEdit = NOW(),
- passDate = UNIX_TIMESTAMP(),
- passDateChange = ?
- WHERE id = ?';
-
- public const UPDATE_PASSWORD = 'UPDATE Account SET
- pass = ?,
- `key` = ?
- WHERE id = ?';
-
- public const EDIT_RESTORE = 'UPDATE Account dst,
- (SELECT * FROM AccountHistory AH WHERE AH.id = ?) src SET
- dst.clientId = src.clientId,
- dst.categoryId = src.categoryId,
- dst.name = src.name,
- dst.login = src.login,
- dst.url = src.url,
- dst.notes = src.notes,
- dst.userGroupId = src.userGroupId,
- dst.userEditId = ?,
- dst.dateEdit = NOW(),
- dst.pass = src.pass,
- dst.key = src.key,
- dst.passDate = src.passDate,
- dst.passDateChange = src.passDateChange,
- dst.parentId = src.parentId,
- dst.isPrivate = src.isPrivate,
- dst.isPrivateGroup = src.isPrivateGroup
- WHERE dst.id = src.accountId';
-
- public const DELETE = 'DELETE FROM Account WHERE id = ? LIMIT 1';
-
- public const EDIT_BY_ID = 'SELECT * FROM account_data_v WHERE id = ? LIMIT 1';
-
- public const GET_ALL = 'SELECT * FROM Account ORDER BY id';
-
- public const INCREMENT_VIEW_COUNTER = 'UPDATE Account SET countView = (countView + 1) WHERE id = ? LIMIT 1';
-
- public const GET_DATA_FOR_LINK = 'SELECT Account.id,
- Account.name,
- Account.login,
- Account.pass,
- Account.key,
- Account.url,
- Account.notes,
- Client.name AS clientName,
- Category.name AS categoryName
- FROM Account
- INNER JOIN Client ON Account.clientId = Client.id
- INNER JOIN Category ON Account.categoryId = Category.id
- WHERE Account.id = ? LIMIT 1';
-
- public const GET_ACCOUNT_PASS_DATA = 'SELECT id, `name`, pass, `key` FROM Account WHERE BIT_LENGTH(pass) > 0';
-}
\ No newline at end of file
diff --git a/lib/SP/Infrastructure/Account/Repositories/AccountSearchRepository.php b/lib/SP/Infrastructure/Account/Repositories/AccountSearchRepository.php
new file mode 100644
index 00000000..b90e59e8
--- /dev/null
+++ b/lib/SP/Infrastructure/Account/Repositories/AccountSearchRepository.php
@@ -0,0 +1,391 @@
+.
+ */
+
+namespace SP\Infrastructure\Account\Repositories;
+
+
+use Aura\SqlQuery\Common\SelectInterface;
+use Aura\SqlQuery\QueryFactory;
+use SP\Core\Context\ContextInterface;
+use SP\Core\Events\EventDispatcherInterface;
+use SP\DataModel\AccountSearchVData;
+use SP\Domain\Account\Search\AccountSearchConstants;
+use SP\Domain\Account\Search\AccountSearchFilter;
+use SP\Domain\Account\Services\AccountFilterUser;
+use SP\Infrastructure\Common\Repositories\Repository;
+use SP\Infrastructure\Database\DatabaseInterface;
+use SP\Infrastructure\Database\QueryData;
+use SP\Infrastructure\Database\QueryResult;
+use SP\Util\Filter;
+
+/**
+ * Class AccountSearchRepository
+ */
+final class AccountSearchRepository extends Repository implements AccountSearchRepositoryInterface
+{
+ protected SelectInterface $query;
+ private AccountFilterUser $accountFilterUser;
+
+ public function __construct(
+ DatabaseInterface $database,
+ ContextInterface $session,
+ EventDispatcherInterface $eventDispatcher,
+ QueryFactory $queryFactory,
+ AccountFilterUser $accountFilterUser
+ ) {
+ parent::__construct($database, $session, $eventDispatcher, $queryFactory);
+
+ $this->accountFilterUser = $accountFilterUser;
+ }
+
+ /**
+ * Obtener las cuentas de una búsqueda.
+ *
+ * @param AccountSearchFilter $accountSearchFilter
+ *
+ * @return QueryResult
+ */
+ public function getByFilter(AccountSearchFilter $accountSearchFilter): QueryResult
+ {
+ $this->accountFilterUser->buildFilter($accountSearchFilter->getGlobalSearch(), $this->query);
+
+ // Sets the search text depending on whether special search filters are being used
+ $searchText = $accountSearchFilter->getCleanTxtSearch();
+
+ if (!empty($searchText)) {
+ $searchTextLike = '%'.$searchText.'%';
+
+ $this->query
+ ->where(
+ '(Account.name LIKE :name OR Account.login LIKE :login OR Account.url LIKE :url OR Account.notes LIKE :notes)',
+ [
+ 'name' => $searchTextLike,
+ 'login' => $searchTextLike,
+ 'url' => $searchTextLike,
+ 'notes' => $searchTextLike,
+ ]
+ );
+ }
+
+ if ($accountSearchFilter->getCategoryId() !== null) {
+ $this->query
+ ->where(
+ 'Account.categoryId = :categoryId',
+ [
+ 'categoryId' => $accountSearchFilter->getCategoryId(),
+ ]
+ );
+ }
+
+ if ($accountSearchFilter->getClientId() !== null) {
+ $this->query
+ ->where(
+ 'Account.categoryId = :clientId',
+ [
+ 'categoryId' => $accountSearchFilter->getClientId(),
+ ]
+ );
+ }
+
+ if ($accountSearchFilter->isSearchFavorites() === true) {
+ $this->query
+ ->join(
+ 'INNER',
+ 'AccountToFavorite',
+ 'AccountToFavorite.accountId = Account.id AND AccountToFavorite.userId = :userId',
+ [
+ 'userId' => $this->context->getUserData()->getId(),
+ ]
+ );
+ }
+
+ if ($accountSearchFilter->hasTags()) {
+ $this->query->join(
+ 'INNER',
+ 'AccountToTag',
+ 'AccountToTag.accountId = Account.id'
+ );
+
+ $this->query
+ ->where(
+ 'AccountToTag.tagId IN (:tagId)',
+ [
+ 'tagId' => $accountSearchFilter->getTagsId(),
+ ]
+ );
+
+ if (AccountSearchConstants::FILTER_CHAIN_AND === $accountSearchFilter->getFilterOperator()) {
+ $this->query
+ ->groupBy(['Account.id'])
+ ->having(
+ 'COUNT(DISTINCT AccountToTag.tagId) = :tagsCount',
+ [
+ 'tagsCount' => count($accountSearchFilter->getTagsId()),
+ ]
+ );
+ }
+ }
+
+ $this->setOrder($accountSearchFilter);
+
+ if ($accountSearchFilter->getLimitCount() > 0) {
+ $this->query->limit($accountSearchFilter->getLimitCount());
+ $this->query->offset($accountSearchFilter->getLimitStart());
+ }
+
+ return $this->db->doSelect(
+ QueryData::build($this->query)->setMapClassName(AccountSearchVData::class),
+ true
+ );
+ }
+
+ /**
+ * Devuelve la cadena de ordenación de la consulta
+ */
+ private function setOrder(AccountSearchFilter $filter): void
+ {
+ $orderKey = match ($filter->getSortKey()) {
+ AccountSearchConstants::SORT_NAME => 'Account.name',
+ AccountSearchConstants::SORT_CATEGORY => 'Account.categoryName',
+ AccountSearchConstants::SORT_LOGIN => 'Account.login',
+ AccountSearchConstants::SORT_URL => 'Account.url',
+ AccountSearchConstants::SORT_CLIENT => 'Account.clientName',
+ default => 'Account.clientName, Account.name',
+ };
+
+ if ($filter->isSortViews() && !$filter->getSortKey()) {
+ $this->query->orderBy(['Account.countView DESC']);
+ } else {
+ $sortOrder = match ($filter->getSortOrder()) {
+ AccountSearchConstants::SORT_DIR_ASC => 'ASC',
+ AccountSearchConstants::SORT_DIR_DESC => 'DESC',
+ };
+
+ $this->query->orderBy([
+ sprintf('%s %s', $orderKey, $sortOrder),
+ ]);
+ }
+ }
+
+ /**
+ * @param int $userId
+ * @param int $userGroupId
+ *
+ * @return \Aura\SqlQuery\Common\SelectInterface
+ */
+ public function withFilterForUser(int $userId, int $userGroupId): SelectInterface
+ {
+ $where = [
+ 'Account.userId = :userId',
+ 'Account.userGroupId = :userGroupId',
+ 'Account.id IN (SELECT AccountToUser.accountId FROM AccountToUser WHERE AccountToUser.accountId = Account.id AND AccountToUser.userId = :userId
+ UNION
+ SELECT AccountToUserGroup.accountId FROM AccountToUserGroup WHERE AccountToUserGroup.accountId = Account.id AND AccountToUserGroup.userGroupId = :userGroupId)',
+ ];
+
+ return $this->query
+ ->where(sprintf('(%s)', join(sprintf(' %s ', AccountSearchConstants::FILTER_CHAIN_OR), $where)))
+ ->bindValues([
+ 'userId' => $userId,
+ 'userGroupId' => $userGroupId,
+ ]);
+ }
+
+ /**
+ * @param int $userGroupId
+ *
+ * @return \Aura\SqlQuery\Common\SelectInterface
+ */
+ public function withFilterForGroup(int $userGroupId): SelectInterface
+ {
+ return $this->query
+ ->where('Account.userGroupId = :userGroupId')
+ ->orWhere(
+ '(Account.id IN (SELECT AccountToUserGroup.accountId FROM AccountToUserGroup WHERE AccountToUserGroup.accountId = id AND AccountToUserGroup.userGroupId = :userGroupId))'
+ )
+ ->bindValues([
+ 'userGroupId' => $userGroupId,
+ ]);
+
+ }
+
+ /**
+ * @param string $userGroupName
+ *
+ * @return \Aura\SqlQuery\Common\SelectInterface
+ */
+ public function withFilterForMainGroup(string $userGroupName): SelectInterface
+ {
+ $userGroupNameLike = '%'.Filter::safeSearchString($userGroupName).'%';
+
+ return $this->query
+ ->where('Account.userGroupName LIKE :userGroupName')
+ ->bindValues([
+ 'userGroupName' => $userGroupNameLike,
+ ]);
+ }
+
+ /**
+ * @param string $owner
+ *
+ * @return \Aura\SqlQuery\Common\SelectInterface
+ */
+ public function withFilterForOwner(string $owner): SelectInterface
+ {
+ $ownerLike = '%'.Filter::safeSearchString($owner).'%';
+
+ return $this->query
+ ->where('(Account.userLogin LIKE :userLogin OR Account.userName LIKE :userName)')
+ ->bindValues([
+ 'userLogin' => $ownerLike,
+ 'userName' => $ownerLike,
+ ]);
+ }
+
+ /**
+ * @param string $fileName
+ *
+ * @return \Aura\SqlQuery\Common\SelectInterface
+ */
+ public function withFilterForFile(string $fileName): SelectInterface
+ {
+ $fileNameLike = '%'.Filter::safeSearchString($fileName).'%';
+
+ return $this->query
+ ->where(
+ '(Account.id IN (SELECT AccountFile.accountId FROM AccountFile WHERE AccountFile.name LIKE :fileName))'
+ )
+ ->bindValues([
+ 'fileName' => $fileNameLike,
+ ]);
+ }
+
+ /**
+ * @param int $accountId
+ *
+ * @return \Aura\SqlQuery\Common\SelectInterface
+ */
+ public function withFilterForAccountId(int $accountId): SelectInterface
+ {
+ return $this->query
+ ->where('Account.id = :id')
+ ->bindValues([
+ 'id' => $accountId,
+ ]);
+ }
+
+ /**
+ * @param string $clientName
+ *
+ * @return \Aura\SqlQuery\Common\SelectInterface
+ */
+ public function withFilterForClient(string $clientName): SelectInterface
+ {
+ $clientNameLike = '%'.Filter::safeSearchString($clientName).'%';
+
+ return $this->query
+ ->where('Account.clientName LIKE :clientName')
+ ->bindValues([
+ 'clientName' => $clientNameLike,
+ ]);
+ }
+
+ /**
+ * @param string $categoryName
+ *
+ * @return \Aura\SqlQuery\Common\SelectInterface
+ */
+ public function withFilterForCategory(string $categoryName): SelectInterface
+ {
+ $categoryNameLike = '%'.Filter::safeSearchString($categoryName).'%';
+
+ return $this->query
+ ->where('Account.categoryName LIKE :categoryName')
+ ->bindValues([
+ 'categoryName' => $categoryNameLike,
+ ]);
+ }
+
+ /**
+ * @param string $accountName
+ *
+ * @return \Aura\SqlQuery\Common\SelectInterface
+ */
+ public function withFilterForAccountNameRegex(string $accountName): SelectInterface
+ {
+ return $this->query
+ ->where('Account.name REGEXP :name')
+ ->bindValues([
+ 'name' => $accountName,
+ ]);
+ }
+
+ public function withFilterForIsExpired(): SelectInterface
+ {
+ return $this->query
+ ->where('(Account.passDateChange > 0 AND UNIX_TIMESTAMP() > Account.passDateChange)');
+ }
+
+ public function withFilterForIsNotExpired(): SelectInterface
+ {
+ return $this->query
+ ->where(
+ '(Account.passDateChange = 0 OR Account.passDateChange IS NULL OR UNIX_TIMESTAMP() < Account.passDateChange)'
+ );
+ }
+
+ /**
+ * @param int $userId
+ * @param int $userGroupId
+ *
+ * @return \Aura\SqlQuery\Common\SelectInterface
+ */
+ public function withFilterForIsPrivate(int $userId, int $userGroupId): SelectInterface
+ {
+ return $this->query
+ ->where(
+ '(Account.isPrivate = 1 AND Account.userId = :userId) OR (Account.isPrivateGroup = 1 AND Account.userGroupId = :userGroupId)'
+ )
+ ->bindValues([
+ 'userId' => $userId,
+ 'userGroupId' => $userGroupId,
+ ]);
+ }
+
+ public function withFilterForIsNotPrivate(): SelectInterface
+ {
+ return $this->query
+ ->where(
+ '(Account.isPrivate = 0 OR Account.isPrivate IS NULL) AND (Account.isPrivateGroup = 0 OR Account.isPrivateGroup IS NULL)'
+ );
+ }
+
+ protected function initialize()
+ {
+ $this->query = $this->queryFactory
+ ->newSelect()
+ ->from('account_search_v AS Account')
+ ->distinct();
+ }
+}
\ No newline at end of file
diff --git a/lib/SP/Infrastructure/Account/Repositories/AccountSearchRepositoryInterface.php b/lib/SP/Infrastructure/Account/Repositories/AccountSearchRepositoryInterface.php
new file mode 100644
index 00000000..829827fa
--- /dev/null
+++ b/lib/SP/Infrastructure/Account/Repositories/AccountSearchRepositoryInterface.php
@@ -0,0 +1,123 @@
+.
+ */
+
+namespace SP\Infrastructure\Account\Repositories;
+
+
+use Aura\SqlQuery\Common\SelectInterface;
+use SP\Domain\Account\Search\AccountSearchFilter;
+use SP\Infrastructure\Database\QueryResult;
+
+/**
+ * Class AccountSearchRepository
+ */
+interface AccountSearchRepositoryInterface
+{
+ /**
+ * Obtener las cuentas de una búsqueda.
+ *
+ * @param AccountSearchFilter $accountSearchFilter
+ *
+ * @return QueryResult
+ */
+ public function getByFilter(AccountSearchFilter $accountSearchFilter): QueryResult;
+
+ /**
+ * @param int $userId
+ * @param int $userGroupId
+ *
+ * @return \Aura\SqlQuery\Common\SelectInterface
+ */
+ public function withFilterForUser(int $userId, int $userGroupId): SelectInterface;
+
+ /**
+ * @param int $userGroupId
+ *
+ * @return \Aura\SqlQuery\Common\SelectInterface
+ */
+ public function withFilterForGroup(int $userGroupId): SelectInterface;
+
+ /**
+ * @param string $userGroupName
+ *
+ * @return \Aura\SqlQuery\Common\SelectInterface
+ */
+ public function withFilterForMainGroup(string $userGroupName): SelectInterface;
+
+ /**
+ * @param string $owner
+ *
+ * @return \Aura\SqlQuery\Common\SelectInterface
+ */
+ public function withFilterForOwner(string $owner): SelectInterface;
+
+ /**
+ * @param string $fileName
+ *
+ * @return \Aura\SqlQuery\Common\SelectInterface
+ */
+ public function withFilterForFile(string $fileName): SelectInterface;
+
+ /**
+ * @param int $accountId
+ *
+ * @return \Aura\SqlQuery\Common\SelectInterface
+ */
+ public function withFilterForAccountId(int $accountId): SelectInterface;
+
+ /**
+ * @param string $clientName
+ *
+ * @return \Aura\SqlQuery\Common\SelectInterface
+ */
+ public function withFilterForClient(string $clientName): SelectInterface;
+
+ /**
+ * @param string $categoryName
+ *
+ * @return \Aura\SqlQuery\Common\SelectInterface
+ */
+ public function withFilterForCategory(string $categoryName): SelectInterface;
+
+ /**
+ * @param string $accountName
+ *
+ * @return \Aura\SqlQuery\Common\SelectInterface
+ */
+ public function withFilterForAccountNameRegex(string $accountName): SelectInterface;
+
+ public function withFilterForIsExpired(): SelectInterface;
+
+ public function withFilterForIsNotExpired(): SelectInterface;
+
+ /**
+ * @param int $userId
+ * @param int $userGroupId
+ *
+ * @return \Aura\SqlQuery\Common\SelectInterface
+ */
+ public function withFilterForIsPrivate(int $userId, int $userGroupId): SelectInterface;
+
+ public function withFilterForIsNotPrivate(): SelectInterface;
+}
\ No newline at end of file
diff --git a/lib/SP/Infrastructure/Common/Repositories/Repository.php b/lib/SP/Infrastructure/Common/Repositories/Repository.php
index 21a769cc..ece09840 100644
--- a/lib/SP/Infrastructure/Common/Repositories/Repository.php
+++ b/lib/SP/Infrastructure/Common/Repositories/Repository.php
@@ -24,7 +24,14 @@
namespace SP\Infrastructure\Common\Repositories;
+use Aura\SqlQuery\QueryFactory;
+use Closure;
+use Exception;
use SP\Core\Context\ContextInterface;
+use SP\Core\Events\Event;
+use SP\Core\Events\EventDispatcherInterface;
+use SP\Core\Events\EventMessage;
+use SP\Domain\Common\Services\ServiceException;
use SP\Infrastructure\Database\DatabaseInterface;
/**
@@ -34,16 +41,59 @@ use SP\Infrastructure\Database\DatabaseInterface;
*/
abstract class Repository
{
- protected ContextInterface $context;
- protected DatabaseInterface $db;
+ protected ContextInterface $context;
+ protected DatabaseInterface $db;
+ protected QueryFactory $queryFactory;
+ protected EventDispatcherInterface $eventDispatcher;
- final public function __construct(DatabaseInterface $database, ContextInterface $session)
- {
+ public function __construct(
+ DatabaseInterface $database,
+ ContextInterface $session,
+ EventDispatcherInterface $eventDispatcher,
+ QueryFactory $queryFactory
+ ) {
$this->db = $database;
$this->context = $session;
+ $this->queryFactory = $queryFactory;
+ $this->eventDispatcher = $eventDispatcher;
if (method_exists($this, 'initialize')) {
$this->initialize();
}
}
+
+ /**
+ * Bubbles a Closure in a database transaction
+ *
+ * @param \Closure $closure
+ *
+ * @return mixed
+ * @throws \SP\Domain\Common\Services\ServiceException
+ * @throws \Exception
+ */
+ final public function transactionAware(Closure $closure)
+ {
+ if ($this->db->beginTransaction()) {
+ try {
+ $result = $closure->call($this);
+
+ $this->db->endTransaction();
+
+ return $result;
+ } catch (Exception $e) {
+ $this->db->rollbackTransaction();
+
+ logger('Transaction:Rollback');
+
+ $this->eventDispatcher->notifyEvent(
+ 'database.rollback',
+ new Event($this, EventMessage::factory()->addDescription(__u('Rollback')))
+ );
+
+ throw $e;
+ }
+ } else {
+ throw new ServiceException(__u('Unable to start a transaction'));
+ }
+ }
}
\ No newline at end of file
diff --git a/lib/SP/Infrastructure/Database/Database.php b/lib/SP/Infrastructure/Database/Database.php
index eb2e837f..e54977cf 100644
--- a/lib/SP/Infrastructure/Database/Database.php
+++ b/lib/SP/Infrastructure/Database/Database.php
@@ -24,6 +24,8 @@
namespace SP\Infrastructure\Database;
+use Aura\SqlQuery\Common\SelectInterface;
+use Aura\SqlQuery\QueryInterface;
use Exception;
use PDO;
use PDOStatement;
@@ -41,12 +43,12 @@ use SP\Core\Exceptions\SPException;
*/
final class Database implements DatabaseInterface
{
+ protected DbStorageInterface $dbHandler;
protected int $numRows = 0;
protected int $numFields = 0;
protected ?array $lastResult = null;
- protected DbStorageInterface $dbHandler;
- private ?int $lastId = null;
private EventDispatcher $eventDispatcher;
+ private ?int $lastId = null;
/**
* DB constructor.
@@ -93,7 +95,7 @@ final class Database implements DatabaseInterface
*/
public function doSelect(QueryData $queryData, bool $fullCount = false): QueryResult
{
- if ($queryData->getQuery() === '') {
+ if ($queryData->getQuery()->getStatement()) {
throw new QueryException($queryData->getOnErrorMessage(), SPException::ERROR, __u('Blank query'));
}
@@ -130,14 +132,14 @@ final class Database implements DatabaseInterface
*/
public function doQuery(QueryData $queryData): QueryResult
{
- $stmt = $this->prepareQueryData($queryData);
+ $stmt = $this->prepareQueryData($queryData->getQuery());
$this->eventDispatcher->notifyEvent(
'database.query',
- new Event($this, EventMessage::factory()->addDescription($queryData->getQuery()))
+ new Event($this, EventMessage::factory()->addDescription($queryData->getQuery()->getStatement()))
);
- if (preg_match("/^(select|show)\s/i", $queryData->getQuery())) {
+ if ($queryData->getQuery() instanceof SelectInterface) {
$this->numFields = $stmt->columnCount();
return new QueryResult($this->fetch($queryData, $stmt));
@@ -149,8 +151,7 @@ final class Database implements DatabaseInterface
/**
* Asociar los parámetros de la consulta utilizando el tipo adecuado
*
- * @param QueryData $queryData Los datos de la consulta
- * @param bool $isCount Indica si es una consulta de contador de registros
+ * @param QueryInterface $query Los datos de la consulta
* @param array $options
*
* @return \PDOStatement
@@ -158,25 +159,16 @@ final class Database implements DatabaseInterface
* @throws \SP\Core\Exceptions\QueryException
*/
private function prepareQueryData(
- QueryData $queryData,
- bool $isCount = false,
+ QueryInterface $query,
array $options = []
): PDOStatement {
- $query = $queryData->getQuery();
- $params = $queryData->getParams();
-
- if ($isCount === true) {
- $query = $queryData->getQueryCount();
- $params = $this->getParamsForCount($queryData);
- }
-
try {
$connection = $this->dbHandler->getConnection();
- if (count($params) !== 0) {
- $stmt = $connection->prepare($query, $options);
+ if (count($query->getBindValues()) !== 0) {
+ $stmt = $connection->prepare($query->getStatement(), $options);
- foreach ($params as $param => $value) {
+ foreach ($query->getBindValues() as $param => $value) {
// Si la clave es un número utilizamos marcadores de posición "?" en
// la consulta. En caso contrario marcadores de nombre
$param = is_int($param) ? $param + 1 : ':'.$param;
@@ -223,6 +215,8 @@ final class Database implements DatabaseInterface
/**
* Strips out the unused params from the query count
+ *
+ * TODO: remove??
*/
private function getParamsForCount(QueryData $queryData): array
{
@@ -254,11 +248,7 @@ final class Database implements DatabaseInterface
*/
public function getFullRowCount(QueryData $queryData): int
{
- if ($queryData->getQueryCount() === '') {
- return 0;
- }
-
- $queryRes = $this->prepareQueryData($queryData, true);
+ $queryRes = $this->prepareQueryData($queryData->getQueryCount());
$num = (int)$queryRes->fetchColumn();
$queryRes->closeCursor();
@@ -290,7 +280,7 @@ final class Database implements DatabaseInterface
);
}
- return $this->prepareQueryData($queryData, false, $options);
+ return $this->prepareQueryData($queryData->getQuery(), $options);
}
/**
diff --git a/lib/SP/Infrastructure/Database/DatabaseInterface.php b/lib/SP/Infrastructure/Database/DatabaseInterface.php
index 2f036f1d..9898d3cf 100644
--- a/lib/SP/Infrastructure/Database/DatabaseInterface.php
+++ b/lib/SP/Infrastructure/Database/DatabaseInterface.php
@@ -24,6 +24,7 @@
namespace SP\Infrastructure\Database;
+use Aura\SqlQuery\QueryInterface;
use PDOStatement;
use SP\Core\Exceptions\ConstraintException;
use SP\Core\Exceptions\QueryException;
diff --git a/lib/SP/Infrastructure/Database/QueryData.php b/lib/SP/Infrastructure/Database/QueryData.php
index 6e67306e..a9b8c146 100644
--- a/lib/SP/Infrastructure/Database/QueryData.php
+++ b/lib/SP/Infrastructure/Database/QueryData.php
@@ -24,6 +24,11 @@
namespace SP\Infrastructure\Database;
+use Aura\SqlQuery\Common\Select;
+use Aura\SqlQuery\QueryInterface;
+use SP\Core\Exceptions\QueryException;
+use SP\Domain\Common\Out\SimpleModel;
+
/**
* Class QueryData
*
@@ -31,18 +36,27 @@ namespace SP\Infrastructure\Database;
*/
final class QueryData
{
- protected array $params = [];
- protected ?string $query = null;
- protected ?string $mapClassName = null;
- protected bool $useKeyPair = false;
- protected ?string $select = null;
- protected ?string $from = null;
- protected ?string $where = null;
- protected ?string $groupBy = null;
- protected ?string $order = null;
- protected ?string $limit = null;
- protected ?string $queryCount = null;
- protected ?string $onErrorMessage = null;
+ protected array $params = [];
+ protected QueryInterface $query;
+ protected ?string $mapClassName = SimpleModel::class;
+ protected bool $useKeyPair = false;
+ protected ?string $select = null;
+ protected ?string $from = null;
+ protected ?string $where = null;
+ protected ?string $groupBy = null;
+ protected ?string $order = null;
+ protected ?string $limit = null;
+ protected ?string $onErrorMessage = null;
+
+ public function __construct(QueryInterface $query)
+ {
+ $this->query = $query;
+ }
+
+ public static function build(QueryInterface $query): QueryData
+ {
+ return new self($query);
+ }
/**
* Añadir un parámetro a la consulta
@@ -69,28 +83,16 @@ final class QueryData
$this->params = $data;
}
- public function getQuery(): string
+ public function getQuery(): QueryInterface
{
- if (empty($this->query)) {
- return $this->select.
- ' '.
- $this->from.
- ' '.
- $this->where.
- ' '.
- $this->groupBy.
- ' '.
- $this->order.
- ' '.
- $this->limit;
- }
-
return $this->query;
}
- public function setQuery(string $query): void
+ public function setQuery(QueryInterface $query): QueryData
{
$this->query = $query;
+
+ return $this;
}
public function getMapClassName(): ?string
@@ -98,9 +100,11 @@ final class QueryData
return $this->mapClassName;
}
- public function setMapClassName(string $mapClassName): void
+ public function setMapClassName(string $mapClassName): QueryData
{
$this->mapClassName = $mapClassName;
+
+ return $this;
}
public function isUseKeyPair(): bool
@@ -146,13 +150,26 @@ final class QueryData
$this->params = array_merge($this->params, $params);
}
- public function getQueryCount(): string
+ /**
+ * @throws \SP\Core\Exceptions\QueryException
+ */
+ public function getQueryCount(): QueryInterface
{
- if (empty($this->queryCount)) {
- return 'SELECT COUNT(*) '.$this->from.' '.$this->where;
+ if ($this->query instanceof Select) {
+ $countQuery = (clone $this->query)
+ ->resetFlags()
+ ->resetCols()
+ ->resetOrderBy()
+ ->resetGroupBy()
+ ->resetHaving()
+ ->page(0);
+
+ $countQuery->cols(['COUNT(*)']);
+
+ return $countQuery;
}
- return $this->queryCount;
+ throw new QueryException(__u('Invalid query type for count'));
}
public function getFrom(): ?string
@@ -191,9 +208,11 @@ final class QueryData
return $this->onErrorMessage ?: __u('Error while querying');
}
- public function setOnErrorMessage(string $onErrorMessage): void
+ public function setOnErrorMessage(string $onErrorMessage): QueryData
{
$this->onErrorMessage = $onErrorMessage;
+
+ return $this;
}
public function setGroupBy(string $groupBy): void
diff --git a/tests/SP/Repositories/AccountRepositoryTest.php b/tests/SP/Repositories/AccountRepositoryTest.php
index 3daf8536..1d59bb5b 100644
--- a/tests/SP/Repositories/AccountRepositoryTest.php
+++ b/tests/SP/Repositories/AccountRepositoryTest.php
@@ -93,7 +93,7 @@ class AccountRepositoryTest extends UnitaryTestCase
->with($callback, false)
->willReturn($expected);
- $this->assertEquals($expected, $this->accountRepository->getPasswordForId(1, new QueryCondition()));
+ $this->assertEquals($expected, $this->accountRepository->getPasswordForId(1));
}
public function testGetPasswordHistoryForId(): void
diff --git a/tests/SP/Services/Account/AccountSearchServiceTest.php b/tests/SP/Services/Account/AccountSearchServiceTest.php
index 229ab255..b2651649 100644
--- a/tests/SP/Services/Account/AccountSearchServiceTest.php
+++ b/tests/SP/Services/Account/AccountSearchServiceTest.php
@@ -1,10 +1,10 @@
.
+ * along with sysPass. If not, see .
*/
namespace SP\Tests\Services\Account;
@@ -34,7 +34,7 @@ use SP\Core\Exceptions\QueryException;
use SP\Core\Exceptions\SPException;
use SP\DataModel\UserPreferencesData;
use SP\Domain\Account\AccountSearchServiceInterface;
-use SP\Domain\Account\Services\AccountSearchFilter;
+use SP\Domain\Account\Search\AccountSearchFilter;
use SP\Domain\Account\Services\AccountSearchItem;
use SP\Domain\Account\Services\AccountSearchService;
use SP\Domain\User\Services\UserLoginResponse;
@@ -154,7 +154,7 @@ class AccountSearchServiceTest extends DatabaseTestCase
$searchFilter->setCategoryId($id);
// Comprobar un Id de categoría
- $result = self::$service->processSearchResults($searchFilter);
+ $result = self::$service->getByFilter($searchFilter);
$this->assertInstanceOf(QueryResult::class, $result);
if ($rows > 0) {
@@ -181,7 +181,7 @@ class AccountSearchServiceTest extends DatabaseTestCase
$searchFilter->setLimitCount(10);
$searchFilter->setCategoryId(10);
- $result = self::$service->processSearchResults($searchFilter);
+ $result = self::$service->getByFilter($searchFilter);
$this->assertInstanceOf(QueryResult::class, $result);
$this->assertEquals(0, $result->getNumRows());
$this->assertCount(0, $result->getDataAsArray());
@@ -203,7 +203,7 @@ class AccountSearchServiceTest extends DatabaseTestCase
$searchFilter->setLimitCount(10);
$searchFilter->setClientId($id);
- $result = self::$service->processSearchResults($searchFilter);
+ $result = self::$service->getByFilter($searchFilter);
$this->assertInstanceOf(QueryResult::class, $result);
$this->assertEquals($rows, $result->getNumRows());
@@ -240,7 +240,7 @@ class AccountSearchServiceTest extends DatabaseTestCase
$searchFilter->setClientId($clientId);
$searchFilter->setCategoryId($categoryId);
- $result = self::$service->processSearchResults($searchFilter);
+ $result = self::$service->getByFilter($searchFilter);
$this->assertInstanceOf(QueryResult::class, $result);
$this->assertEquals($rows, $result->getNumRows());
@@ -264,7 +264,7 @@ class AccountSearchServiceTest extends DatabaseTestCase
$searchFilter->setLimitCount(10);
$searchFilter->setClientId(10);
- $result = self::$service->processSearchResults($searchFilter);
+ $result = self::$service->getByFilter($searchFilter);
$this->assertInstanceOf(QueryResult::class, $result);
$this->assertEquals(0, $result->getNumRows());
$this->assertCount(0, $result->getDataAsArray());
@@ -286,7 +286,7 @@ class AccountSearchServiceTest extends DatabaseTestCase
$searchFilter->setLimitCount(10);
$searchFilter->setTxtSearch($string);
- $result = self::$service->processSearchResults($searchFilter);
+ $result = self::$service->getByFilter($searchFilter);
$this->assertInstanceOf(QueryResult::class, $result);
$this->assertEquals($rows, $result->getNumRows());
@@ -315,7 +315,7 @@ class AccountSearchServiceTest extends DatabaseTestCase
$searchFilter->setLimitCount(10);
$searchFilter->setSearchFavorites(true);
- $result = self::$service->processSearchResults($searchFilter);
+ $result = self::$service->getByFilter($searchFilter);
$this->assertInstanceOf(QueryResult::class, $result);
$this->assertEquals($rows, $result->getNumRows());
@@ -347,7 +347,7 @@ class AccountSearchServiceTest extends DatabaseTestCase
$searchFilter->setFilterOperator($operator);
$searchFilter->setTagsId($tagsId);
- $result = self::$service->processSearchResults($searchFilter);
+ $result = self::$service->getByFilter($searchFilter);
$this->assertInstanceOf(QueryResult::class, $result);
/** @var AccountSearchItem[] $data */
diff --git a/tests/SP/Services/Account/AccountServiceTest.php b/tests/SP/Services/Account/AccountServiceTest.php
index 29e171f7..d2bebb31 100644
--- a/tests/SP/Services/Account/AccountServiceTest.php
+++ b/tests/SP/Services/Account/AccountServiceTest.php
@@ -40,12 +40,12 @@ use SP\DataModel\AccountVData;
use SP\DataModel\ItemSearchData;
use SP\DataModel\ProfileData;
use SP\Domain\Account\AccountHistoryServiceInterface;
+use SP\Domain\Account\Search\AccountSearchFilter;
use SP\Domain\Account\Out\AccountData;
use SP\Domain\Account\Services\AccountBulkRequest;
use SP\Domain\Account\Services\AccountHistoryService;
use SP\Domain\Account\Services\AccountPasswordRequest;
use SP\Domain\Account\Services\AccountRequest;
-use SP\Domain\Account\Services\AccountSearchFilter;
use SP\Domain\Account\Services\AccountService;
use SP\Domain\Common\Services\ServiceException;
use SP\Domain\User\Services\UserLoginResponse;
diff --git a/tests/SP/Services/Import/KeepassImportTest.php b/tests/SP/Services/Import/KeepassImportTest.php
index eb7568f5..5a6f9e98 100644
--- a/tests/SP/Services/Import/KeepassImportTest.php
+++ b/tests/SP/Services/Import/KeepassImportTest.php
@@ -1,10 +1,10 @@
.
+ * along with sysPass. If not, see .
*/
namespace SP\Tests\Services\Import;
@@ -34,7 +34,7 @@ use SP\Core\Exceptions\ConstraintException;
use SP\Core\Exceptions\QueryException;
use SP\Core\Exceptions\SPException;
use SP\DataModel\AccountSearchVData;
-use SP\Domain\Account\Services\AccountSearchFilter;
+use SP\Domain\Account\Search\AccountSearchFilter;
use SP\Domain\Account\Services\AccountService;
use SP\Domain\Category\Services\CategoryService;
use SP\Domain\Client\Services\ClientService;