DataCache util
This commit is contained in:
@@ -84,7 +84,7 @@ class CronManager
|
||||
|
||||
const FAILED = 'Failed';
|
||||
|
||||
protected $lastRunTime = 'data/cache/application/cronLastRunTime.php';
|
||||
protected $lastRunTimeFile = 'data/cache/application/cronLastRunTime.php';
|
||||
|
||||
protected $config;
|
||||
protected $fileManager;
|
||||
@@ -137,7 +137,7 @@ class CronManager
|
||||
|
||||
protected function getLastRunTime()
|
||||
{
|
||||
$lastRunData = $this->fileManager->getPhpContents($this->lastRunTime);
|
||||
$lastRunData = $this->fileManager->getPhpContents($this->lastRunTimeFile);
|
||||
|
||||
if (is_array($lastRunData) && !empty($lastRunData['time'])) {
|
||||
$lastRunTime = $lastRunData['time'];
|
||||
@@ -150,10 +150,11 @@ class CronManager
|
||||
|
||||
protected function setLastRunTime($time)
|
||||
{
|
||||
$data = array(
|
||||
$data = [
|
||||
'time' => $time,
|
||||
);
|
||||
return $this->fileManager->putPhpContents($this->lastRunTime, $data);
|
||||
];
|
||||
|
||||
return $this->fileManager->putPhpContents($this->lastRunTimeFile, $data, false, true);
|
||||
}
|
||||
|
||||
protected function checkLastRunTime()
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Di;
|
||||
|
||||
use Espo\Core\Utils\DataCache;
|
||||
|
||||
interface DataCacheAware
|
||||
{
|
||||
public function setDataCache(DataCache $dataCache);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Di;
|
||||
|
||||
use Espo\Core\Utils\DataCache;
|
||||
|
||||
trait DataCacheSetter
|
||||
{
|
||||
protected $dataCache;
|
||||
|
||||
public function setDataCache(DataCache $dataCache)
|
||||
{
|
||||
$this->dataCache = $dataCache;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Loaders;
|
||||
|
||||
use Espo\Core\{
|
||||
InjectableFactory,
|
||||
Utils\DataCache as DataCacheService,
|
||||
};
|
||||
|
||||
class DataCache implements Loader
|
||||
{
|
||||
protected $injectableFactory;
|
||||
|
||||
public function __construct(InjectableFactory $injectableFactory)
|
||||
{
|
||||
$this->injectableFactory = $injectableFactory;
|
||||
}
|
||||
|
||||
public function load() : DataCacheService
|
||||
{
|
||||
return $this->injectableFactory->create(DataCacheService::class);
|
||||
}
|
||||
}
|
||||
@@ -29,13 +29,19 @@
|
||||
|
||||
namespace Espo\Core\Utils;
|
||||
|
||||
use Espo\Core\Utils\Autoload\Loader;
|
||||
use Espo\Core\{
|
||||
Exceptions\Error,
|
||||
Utils\Autoload\Loader,
|
||||
Utils\DataCache,
|
||||
};
|
||||
|
||||
use Exception;
|
||||
|
||||
class Autoload
|
||||
{
|
||||
protected $data = null;
|
||||
|
||||
protected $cacheFile = 'data/cache/application/autoload.php';
|
||||
protected $cacheKey = 'autoload';
|
||||
|
||||
protected $paths = [
|
||||
'corePath' => 'application/Espo/Resources/autoload.json',
|
||||
@@ -43,19 +49,18 @@ class Autoload
|
||||
'customPath' => 'custom/Espo/Custom/Resources/autoload.json',
|
||||
];
|
||||
|
||||
protected $loader;
|
||||
|
||||
protected $config;
|
||||
protected $metadata;
|
||||
protected $fileManager;
|
||||
protected $dataCache;
|
||||
protected $loader;
|
||||
|
||||
public function __construct(Config $config, Metadata $metadata, File\Manager $fileManager)
|
||||
public function __construct(Config $config, Metadata $metadata, DataCache $dataCache, Loader $loader)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->metadata = $metadata;
|
||||
$this->fileManager = $fileManager;
|
||||
$this->dataCache = $dataCache;
|
||||
|
||||
$this->loader = new Loader($config, $fileManager);
|
||||
$this->loader = $loader;
|
||||
}
|
||||
|
||||
public function get($key = null, $returns = null)
|
||||
@@ -78,18 +83,18 @@ class Autoload
|
||||
|
||||
protected function init()
|
||||
{
|
||||
if (file_exists($this->cacheFile) && $this->config->get('useCache')) {
|
||||
$this->data = $this->fileManager->getPhpContents($this->cacheFile);
|
||||
$useCache = $this->config->get('useCache');
|
||||
|
||||
if ($useCache && $this->dataCache->has($this->cacheKey)) {
|
||||
$this->data = $this->dataCache->get($this->cacheKey);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->data = $this->unify();
|
||||
|
||||
if ($this->config->get('useCache')) {
|
||||
$result = $this->fileManager->putPhpContents($this->cacheFile, $this->data);
|
||||
if ($result == false) {
|
||||
throw new \Espo\Core\Exceptions\Error('Autoload: Cannot save unified autoload.');
|
||||
}
|
||||
if ($useCache) {
|
||||
$result = $this->dataCache->store($this->cacheKey, $this->data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,6 +104,7 @@ class Autoload
|
||||
|
||||
foreach ($this->metadata->getModuleList() as $moduleName) {
|
||||
$modulePath = str_replace('{*}', $moduleName, $this->paths['modulePath']);
|
||||
|
||||
$data = array_merge($data, $this->loadData($modulePath));
|
||||
}
|
||||
|
||||
@@ -107,16 +113,18 @@ class Autoload
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function loadData($autoloadFile, $returns = array())
|
||||
protected function loadData($autoloadFile, $returns = [])
|
||||
{
|
||||
if (file_exists($autoloadFile)) {
|
||||
$content = $this->fileManager->getContents($autoloadFile);
|
||||
|
||||
$arrayContent = Json::getArrayData($content);
|
||||
|
||||
if (!empty($arrayContent)) {
|
||||
return $this->normalizeData($arrayContent);
|
||||
}
|
||||
|
||||
$GLOBALS['log']->error('Autoload::unify() - Empty file or syntax error - ['.$autoloadFile.']');
|
||||
$GLOBALS['log']->error('Autoload: Empty file or syntax error ['.$autoloadFile.'].');
|
||||
}
|
||||
|
||||
return $returns;
|
||||
@@ -134,10 +142,12 @@ class Autoload
|
||||
case 'files':
|
||||
case 'autoloadFileList':
|
||||
$normalizedData[$key] = $value;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$normalizedData['psr-0'][$key] = $value;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -149,7 +159,8 @@ class Autoload
|
||||
{
|
||||
try {
|
||||
$autoloadList = $this->getAll();
|
||||
} catch (\Exception $e) {} //bad permissions
|
||||
}
|
||||
catch (Exception $e) {} //bad permissions
|
||||
|
||||
if (!empty($autoloadList)) {
|
||||
$this->loader->register($autoloadList);
|
||||
|
||||
@@ -29,22 +29,13 @@
|
||||
|
||||
namespace Espo\Core\Utils\Autoload;
|
||||
|
||||
use Espo\Core\Utils\Config;
|
||||
use Espo\Core\Utils\File\Manager as FileManager;
|
||||
|
||||
class Loader
|
||||
{
|
||||
protected $namespaceLoader;
|
||||
|
||||
protected $config;
|
||||
protected $fileManager;
|
||||
|
||||
public function __construct(Config $config, FileManager $fileManager)
|
||||
public function __construct(NamespaceLoader $namespaceLoader)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->fileManager = $fileManager;
|
||||
|
||||
$this->namespaceLoader = new NamespaceLoader($config, $fileManager);
|
||||
$this->namespaceLoader = $namespaceLoader;
|
||||
}
|
||||
|
||||
public function register(array $autoloadList)
|
||||
@@ -63,7 +54,9 @@ class Loader
|
||||
{
|
||||
$keyName = 'autoloadFileList';
|
||||
|
||||
if (!isset($autoloadList[$keyName])) return;
|
||||
if (!isset($autoloadList[$keyName])) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($autoloadList[$keyName] as $filePath) {
|
||||
if (file_exists($filePath)) {
|
||||
@@ -76,7 +69,9 @@ class Loader
|
||||
{
|
||||
$keyName = 'files';
|
||||
|
||||
if (!isset($autoloadList[$keyName])) return;
|
||||
if (!isset($autoloadList[$keyName])) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($autoloadList[$keyName] as $id => $filePath) {
|
||||
if (file_exists($filePath)) {
|
||||
|
||||
@@ -29,36 +29,30 @@
|
||||
|
||||
namespace Espo\Core\Utils\Autoload;
|
||||
|
||||
use Espo\Core\Utils\Util;
|
||||
|
||||
use Espo\Core\Utils\Config;
|
||||
use Espo\Core\Utils\File\Manager as FileManager;
|
||||
use Espo\Core\{
|
||||
Utils\Util,
|
||||
Utils\Config,
|
||||
Utils\DataCache,
|
||||
};
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
|
||||
use Exception;
|
||||
|
||||
class NamespaceLoader
|
||||
{
|
||||
protected $config;
|
||||
protected $fileManager;
|
||||
|
||||
protected $classLoader;
|
||||
|
||||
private $namespaces;
|
||||
|
||||
protected $autoloadFilePath = 'vendor/autoload.php';
|
||||
|
||||
/**
|
||||
* Namespace files.
|
||||
*/
|
||||
protected $namespacesPaths = [
|
||||
'psr-4' => 'vendor/composer/autoload_psr4.php',
|
||||
'psr-0' => 'vendor/composer/autoload_namespaces.php',
|
||||
'classmap' => 'vendor/composer/autoload_classmap.php',
|
||||
];
|
||||
|
||||
/**
|
||||
* Method names in ClassLoader.
|
||||
*/
|
||||
protected $methodNameMap = [
|
||||
'psr-4' => 'addPsr4',
|
||||
'psr-0' => 'add',
|
||||
@@ -67,12 +61,15 @@ class NamespaceLoader
|
||||
|
||||
protected $vendorNamespaces;
|
||||
|
||||
protected $vendorNamespacesCacheFile = 'data/cache/application/autoload-vendor-namespaces.php';
|
||||
protected $cacheKey = 'autoloadVendorNamespaces';
|
||||
|
||||
public function __construct(Config $config, FileManager $fileManager)
|
||||
protected $config;
|
||||
protected $dataCache;
|
||||
|
||||
public function __construct(Config $config, DataCache $dataCache)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->fileManager = $fileManager;
|
||||
$this->dataCache = $dataCache;
|
||||
|
||||
$this->classLoader = new ClassLoader();
|
||||
}
|
||||
@@ -80,6 +77,7 @@ class NamespaceLoader
|
||||
public function register(array $autoloadList)
|
||||
{
|
||||
$this->addListToClassLoader($this->classLoader, $autoloadList);
|
||||
|
||||
$this->classLoader->register(true);
|
||||
}
|
||||
|
||||
@@ -89,11 +87,15 @@ class NamespaceLoader
|
||||
|
||||
foreach ($this->namespacesPaths as $type => $path) {
|
||||
$mapFile = Util::concatPath($basePath, $path);
|
||||
if (file_exists($mapFile)) {
|
||||
$map = require($mapFile);
|
||||
if (!empty($map) && is_array($map)) {
|
||||
$namespaces[$type] = $map;
|
||||
}
|
||||
|
||||
if (!file_exists($mapFile)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$map = require($mapFile);
|
||||
|
||||
if (!empty($map) && is_array($map)) {
|
||||
$namespaces[$type] = $map;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,10 +150,13 @@ class NamespaceLoader
|
||||
protected function addListToClassLoader($classLoader, array $list, $skipVendorNamespaces = false)
|
||||
{
|
||||
foreach ($this->methodNameMap as $type => $methodName) {
|
||||
if (!isset($list[$type])) continue;
|
||||
if (!isset($list[$type])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!method_exists($classLoader, $methodName)) {
|
||||
$GLOBALS['log']->warning('Autoload: ClassLoader method ['. $methodName .'] is not found.');
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -167,7 +172,8 @@ class NamespaceLoader
|
||||
try {
|
||||
$classLoader->$methodName($prefix, $path);
|
||||
$this->addNamespace($type, $prefix, $path);
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$GLOBALS['log']->warning('Autoload: error adding the namespace ['. $prefix .']');
|
||||
}
|
||||
}
|
||||
@@ -177,11 +183,14 @@ class NamespaceLoader
|
||||
|
||||
protected function getVendorNamespaces($path)
|
||||
{
|
||||
$useCache = $this->config->get('useCache');
|
||||
|
||||
if (!isset($this->vendorNamespaces)) {
|
||||
$this->vendorNamespaces = [];
|
||||
|
||||
if (file_exists($this->vendorNamespacesCacheFile) && $this->config->get('useCache')) {
|
||||
$this->vendorNamespaces = $this->fileManager->getPhpContents($this->vendorNamespacesCacheFile);
|
||||
if ($useCache && $this->dataCache->has($this->cacheKey)) {
|
||||
$this->vendorNamespaces = $this->dataCache->get($this->cacheKey);
|
||||
|
||||
if (!is_array($this->vendorNamespaces)) {
|
||||
$this->vendorNamespaces = [];
|
||||
}
|
||||
@@ -190,11 +199,12 @@ class NamespaceLoader
|
||||
|
||||
if (!array_key_exists($path, $this->vendorNamespaces)) {
|
||||
$vendorPath = $this->findVendorPath($path);
|
||||
|
||||
if ($vendorPath) {
|
||||
$this->vendorNamespaces[$path] = $this->loadNamespaces($vendorPath);
|
||||
|
||||
if ($this->config->get('useCache')) {
|
||||
$this->fileManager->putPhpContents($this->vendorNamespacesCacheFile, $this->vendorNamespaces);
|
||||
if ($useCache) {
|
||||
$this->dataCache->store($this->cacheKey, $this->vendorNamespaces);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,11 +217,13 @@ class NamespaceLoader
|
||||
protected function findVendorPath($path)
|
||||
{
|
||||
$vendor = Util::concatPath($path, $this->autoloadFilePath);
|
||||
|
||||
if (file_exists($vendor)) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
$parentDir = dirname($path);
|
||||
|
||||
if (!empty($parentDir) && $parentDir != '.') {
|
||||
return $this->findVendorPath($parentDir);
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ class ClassFinder
|
||||
protected function load(string $category, bool $subDirs = false)
|
||||
{
|
||||
$path = $this->buildPaths($category);
|
||||
$cacheFile = $this->buildCacheFilePath($category);
|
||||
$cacheFile = $this->buildCacheKey($category);
|
||||
|
||||
$this->dataHash[$category] = $this->classParser->getData($path, $cacheFile, null, $subDirs);
|
||||
}
|
||||
@@ -93,10 +93,8 @@ class ClassFinder
|
||||
return $path;
|
||||
}
|
||||
|
||||
protected function buildCacheFilePath(string $category) : string
|
||||
protected function buildCacheKey(string $category) : string
|
||||
{
|
||||
$path = 'data/cache/application/classmap_' . str_replace('/', '_', strtolower($category)) . '.php';
|
||||
|
||||
return $path;
|
||||
return 'classmap' . str_replace('/', '', $category);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Utils;
|
||||
|
||||
use Espo\Core\{
|
||||
Exceptions\Error,
|
||||
Utils\File\Manager as FileManager,
|
||||
};
|
||||
|
||||
use InvalidArgumentException;
|
||||
use StdClass;
|
||||
|
||||
class DataCache
|
||||
{
|
||||
protected $fileManager;
|
||||
|
||||
protected $cacheDir = 'data/cache/application/';
|
||||
|
||||
public function __construct(FileManager $fileManager)
|
||||
{
|
||||
$this->fileManager = $fileManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether is cached.
|
||||
*/
|
||||
public function has(string $key) : bool
|
||||
{
|
||||
$cacheFile = $this->getCacheFile($key);
|
||||
|
||||
return $this->fileManager->isFile($cacheFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a stored value.
|
||||
*
|
||||
* @throws Error if is not cached.
|
||||
*
|
||||
* @return ?array|StdClass|int|float|string
|
||||
*/
|
||||
public function get(string $key)
|
||||
{
|
||||
$cacheFile = $this->getCacheFile($key);
|
||||
|
||||
$result = $this->fileManager->getPhpContents($cacheFile);
|
||||
|
||||
if ($result === false) {
|
||||
throw new Error("Could not get '{$key}'.");
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store in cache.
|
||||
*
|
||||
* @param ?array|StdClass|int|float|string $data
|
||||
*/
|
||||
public function store(string $key, $data)
|
||||
{
|
||||
if (
|
||||
! is_array($data) &&
|
||||
! $data instanceof StdClass &&
|
||||
! is_int($data) &&
|
||||
! is_float($data) &&
|
||||
! is_int($data)
|
||||
) {
|
||||
throw new InvalidArgumentException("Bad cache data type.");
|
||||
}
|
||||
|
||||
$cacheFile = $this->getCacheFile($key);
|
||||
|
||||
$result = $this->fileManager->putPhpContents($cacheFile, $data, true, true);
|
||||
|
||||
if ($result === false) {
|
||||
throw new Error("Could not store '{$key}'.");
|
||||
}
|
||||
}
|
||||
|
||||
protected function getCacheFile(string $key) : string
|
||||
{
|
||||
if (
|
||||
$key === '' ||
|
||||
preg_match('/[^a-zA-Z0-9\/]/i', $key) ||
|
||||
$key[0] === '/' ||
|
||||
substr($key, -1) === '/'
|
||||
) {
|
||||
throw new InvalidArgumentException("Bad cache key.");
|
||||
}
|
||||
|
||||
return $this->cacheDir . $key . '.php';
|
||||
}
|
||||
}
|
||||
@@ -29,28 +29,31 @@
|
||||
|
||||
namespace Espo\Core\Utils\File;
|
||||
|
||||
use Espo\Core\Utils\Util;
|
||||
use Espo\Core\Utils\File\Manager as FileManager;
|
||||
use Espo\Core\Utils\Config;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use Espo\Core\{
|
||||
Exceptions\Error,
|
||||
Utils\Util,
|
||||
Utils\File\Manager as FileManager,
|
||||
Utils\Config,
|
||||
Utils\Metadata,
|
||||
Utils\DataCache,
|
||||
|
||||
use Espo\Core\Exceptions\Error;
|
||||
};
|
||||
|
||||
use ReflectionClass;
|
||||
|
||||
class ClassParser
|
||||
{
|
||||
private $fileManager;
|
||||
|
||||
private $config;
|
||||
|
||||
private $metadata;
|
||||
private $dataCache;
|
||||
|
||||
public function __construct(FileManager $fileManager, Config $config, Metadata $metadata)
|
||||
public function __construct(FileManager $fileManager, Config $config, Metadata $metadata, DataCache $dataCache)
|
||||
{
|
||||
$this->fileManager = $fileManager;
|
||||
$this->config = $config;
|
||||
$this->metadata = $metadata;
|
||||
$this->dataCache = $dataCache;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,10 +64,9 @@ class ClassParser
|
||||
* 'modulePath' => '',
|
||||
* 'customPath' => '',
|
||||
* ]
|
||||
* @param $cacheFile Full path for a cache file, ex. data/cache/application/entryPoints.php.
|
||||
* @param $allowedMethods If specified, classes w/o specified method will be ignored.
|
||||
*/
|
||||
public function getData($paths, ?string $cacheFile = null, ?array $allowedMethods = null, bool $subDirs = false) : array
|
||||
public function getData($paths, ?string $cacheKey = null, ?array $allowedMethods = null, bool $subDirs = false) : array
|
||||
{
|
||||
$data = null;
|
||||
|
||||
@@ -74,11 +76,12 @@ class ClassParser
|
||||
];
|
||||
}
|
||||
|
||||
if ($cacheFile && file_exists($cacheFile) && $this->config->get('useCache')) {
|
||||
$data = $this->fileManager->getPhpContents($cacheFile);
|
||||
|
||||
if ($cacheKey && $this->dataCache->has($cacheKey) && $this->config->get('useCache')) {
|
||||
$data = $this->dataCache->get($cacheKey);
|
||||
|
||||
if (!is_array($data)) {
|
||||
$GLOBALS['log']->error("ClassParser: Non-array value stored in {$cacheFile}.");
|
||||
$GLOBALS['log']->error("ClassParser: Non-array value stored in {$cacheKey}.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,12 +100,8 @@ class ClassParser
|
||||
$data = array_merge($data, $this->getClassNameHash($paths['customPath'], $allowedMethods, $subDirs));
|
||||
}
|
||||
|
||||
if ($cacheFile && $this->config->get('useCache')) {
|
||||
$result = $this->fileManager->putPhpContents($cacheFile, $data);
|
||||
|
||||
if ($result == false) {
|
||||
throw new Error("ClassParser: Could not save file {$cacheFile}.");
|
||||
}
|
||||
if ($cacheKey && $this->config->get('useCache')) {
|
||||
$this->dataCache->store($cacheKey, $data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -276,12 +276,9 @@ class Manager
|
||||
/**
|
||||
* Save PHP content to file.
|
||||
*
|
||||
* @param string | array $path
|
||||
* @param string $data
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function putPhpContents($path, $data, $withObjects = false, bool $useRenaming = false)
|
||||
public function putPhpContents(string $path, $data, bool $withObjects = false, bool $useRenaming = false)
|
||||
{
|
||||
return $this->putContents($path, $this->wrapForDataExport($data, $withObjects), LOCK_EX, $useRenaming);
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ class Module
|
||||
$this->data = $this->unifier->unify($this->paths, true);
|
||||
|
||||
if ($this->useCache) {
|
||||
$result = $this->fileManager->putPhpContents($this->cacheFile, $this->data);
|
||||
$result = $this->fileManager->putPhpContents($this->cacheFile, $this->data, false, true);
|
||||
|
||||
if ($result === false) {
|
||||
throw new Error('Module: Could not save unified module data.');
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace tests\Espo\Core\Utils;
|
||||
|
||||
use Espo\Core\{
|
||||
Utils\DataCache,
|
||||
Utils\File\Manager as FileManager,
|
||||
Exceptions\Error,
|
||||
};
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class DataCacheTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
protected function setUp() : void
|
||||
{
|
||||
$this->fileManager = $this->getMockBuilder(FileManager::class)->disableOriginalConstructor()->getMock();
|
||||
|
||||
$this->dataCache = new DataCache($this->fileManager);
|
||||
}
|
||||
|
||||
public function testHasTrue()
|
||||
{
|
||||
$this->fileManager
|
||||
->expects($this->once())
|
||||
->method('isFile')
|
||||
->with('data/cache/application/autoload.php')
|
||||
->willReturn(true);
|
||||
|
||||
$result = $this->dataCache->has('autoload');
|
||||
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
public function testHasFalse()
|
||||
{
|
||||
$this->fileManager
|
||||
->expects($this->once())
|
||||
->method('isFile')
|
||||
->with('data/cache/application/autoload.php')
|
||||
->willReturn(false);
|
||||
|
||||
$result = $this->dataCache->has('autoload');
|
||||
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
|
||||
public function testGetData()
|
||||
{
|
||||
$this->fileManager
|
||||
->expects($this->once())
|
||||
->method('getPhpContents')
|
||||
->with('data/cache/application/autoload.php')
|
||||
->willReturn(1);
|
||||
|
||||
$result = $this->dataCache->get('autoload');
|
||||
|
||||
$this->assertEquals(1, $result);
|
||||
}
|
||||
|
||||
public function testGetError()
|
||||
{
|
||||
$this->expectException(Error::class);
|
||||
|
||||
$this->fileManager
|
||||
->expects($this->once())
|
||||
->method('getPhpContents')
|
||||
->with('data/cache/application/autoload.php')
|
||||
->willReturn(false);
|
||||
|
||||
$result = $this->dataCache->get('autoload');
|
||||
}
|
||||
|
||||
public function testStoreData()
|
||||
{
|
||||
$data = [
|
||||
'test' => 1,
|
||||
];
|
||||
|
||||
$this->fileManager
|
||||
->expects($this->once())
|
||||
->method('putPhpContents')
|
||||
->with('data/cache/application/autoload.php', $data, true, true)
|
||||
->willReturn(true);
|
||||
|
||||
$this->dataCache->store('autoload', $data);
|
||||
}
|
||||
|
||||
public function testStoreError()
|
||||
{
|
||||
$this->expectException(Error::class);
|
||||
|
||||
$data = [
|
||||
'test' => 1,
|
||||
];
|
||||
|
||||
$this->fileManager
|
||||
->expects($this->once())
|
||||
->method('putPhpContents')
|
||||
->with('data/cache/application/autoload.php', $data, true, true)
|
||||
->willReturn(false);
|
||||
|
||||
$this->dataCache->store('autoload', $data);
|
||||
}
|
||||
|
||||
public function testStoreBadDataType()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$data = false;
|
||||
|
||||
$this->dataCache->store('autoload', $data);
|
||||
}
|
||||
|
||||
public function testSubDir()
|
||||
{
|
||||
$this->fileManager
|
||||
->expects($this->once())
|
||||
->method('isFile')
|
||||
->with('data/cache/application/languageTest/test0.php')
|
||||
->willReturn(true);
|
||||
|
||||
$result = $this->dataCache->has('languageTest/test0');
|
||||
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
public function testBadKey1()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$result = $this->dataCache->has('/language');
|
||||
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
public function testBadKey2()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$result = $this->dataCache->has('language/');
|
||||
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
public function testBadKey3()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$result = $this->dataCache->has('');
|
||||
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
public function testBadKey4()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$result = $this->dataCache->has('language\test');
|
||||
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,10 @@ namespace tests\unit\Espo\Core\Utils\File;
|
||||
|
||||
use tests\unit\ReflectionHelper;
|
||||
|
||||
use Espo\Core\Utils\File\ClassParser;
|
||||
use Espo\Core\Utils\DataCache;
|
||||
use Espo\Core\Utils\File\Manager as FileManager;
|
||||
|
||||
class ClassParserTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
protected $object;
|
||||
@@ -41,12 +45,16 @@ class ClassParserTest extends \PHPUnit\Framework\TestCase
|
||||
|
||||
protected function setUp() : void
|
||||
{
|
||||
$this->objects['fileManager'] = new \Espo\Core\Utils\File\Manager();
|
||||
$this->objects['fileManager'] = new FileManager();
|
||||
|
||||
$this->objects['config'] = $this->getMockBuilder('Espo\Core\Utils\Config')->disableOriginalConstructor()->getMock();
|
||||
$this->objects['metadata'] = $this->getMockBuilder('Espo\Core\Utils\Metadata')->disableOriginalConstructor()->getMock();
|
||||
|
||||
$this->object = new \Espo\Core\Utils\File\ClassParser(
|
||||
$this->objects['fileManager'], $this->objects['config'], $this->objects['metadata']);
|
||||
$this->dataCache = $this->getMockBuilder(DataCache::class)->disableOriginalConstructor()->getMock();
|
||||
|
||||
$this->object = new ClassParser(
|
||||
$this->objects['fileManager'], $this->objects['config'], $this->objects['metadata'], $this->dataCache
|
||||
);
|
||||
|
||||
$this->reflection = new ReflectionHelper($this->object);
|
||||
}
|
||||
@@ -73,29 +81,42 @@ class ClassParserTest extends \PHPUnit\Framework\TestCase
|
||||
|
||||
function testGetDataWithCache()
|
||||
{
|
||||
$result = [
|
||||
'Download' => '\\tests\\unit\\testData\\EntryPoints\\Espo\\EntryPoints\\Download',
|
||||
];
|
||||
|
||||
$this->objects['config']
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$cacheFile = 'tests/unit/testData/EntryPoints/cache/entryPoints.php';
|
||||
$cacheKey = 'entryPoints';
|
||||
|
||||
$this->dataCache
|
||||
->expects($this->once())
|
||||
->method('has')
|
||||
->with('entryPoints')
|
||||
->willReturn(true);
|
||||
|
||||
$this->dataCache
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with('entryPoints')
|
||||
->willReturn($result);
|
||||
|
||||
$paths = [
|
||||
'corePath' => '/tests/unit/testData/EntryPoints/Espo/EntryPoints',
|
||||
'modulePath' => '/tests/unit/testData/EntryPoints/Espo/Modules/{*}/EntryPoints',
|
||||
'customPath' => '/tests/unit/testData/EntryPoints/Espo/Custom/EntryPoints',
|
||||
];
|
||||
|
||||
$result = [
|
||||
'Download' => '\\tests\\unit\\testData\\EntryPoints\\Espo\\EntryPoints\\Download',
|
||||
];
|
||||
|
||||
$this->assertEquals($result, $this->reflection->invokeMethod('getData', [$paths, $cacheFile, ['run']]) );
|
||||
$this->assertEquals($result, $this->reflection->invokeMethod('getData', [$paths, $cacheKey, ['run']]) );
|
||||
}
|
||||
|
||||
function testGetDataWithNoCache()
|
||||
{
|
||||
$this->objects['config']
|
||||
->expects($this->exactly(2))
|
||||
->expects($this->exactly(1))
|
||||
->method('get')
|
||||
->will($this->returnValue(false));
|
||||
|
||||
@@ -108,7 +129,8 @@ class ClassParserTest extends \PHPUnit\Framework\TestCase
|
||||
]
|
||||
));
|
||||
|
||||
$cacheFile = 'tests/unit/testData/EntryPoints/cache/entryPoints.php';
|
||||
$cacheKey = 'entryPoints';
|
||||
|
||||
$paths = [
|
||||
'corePath' => 'tests/unit/testData/EntryPoints/Espo/EntryPoints',
|
||||
'modulePath' => 'tests/unit/testData/EntryPoints/Espo/Modules/{*}/EntryPoints',
|
||||
@@ -121,13 +143,13 @@ class ClassParserTest extends \PHPUnit\Framework\TestCase
|
||||
'InModule' => 'tests\unit\testData\EntryPoints\Espo\Modules\Crm\EntryPoints\InModule'
|
||||
];
|
||||
|
||||
$this->assertEquals($result, $this->reflection->invokeMethod('getData', [$paths, $cacheFile, ['run']]));
|
||||
$this->assertEquals($result, $this->reflection->invokeMethod('getData', [$paths, $cacheKey, ['run']]));
|
||||
}
|
||||
|
||||
function testGetDataWithNoCacheString()
|
||||
{
|
||||
$this->objects['config']
|
||||
->expects($this->exactly(2))
|
||||
->expects($this->exactly(1))
|
||||
->method('get')
|
||||
->will($this->returnValue(false));
|
||||
|
||||
@@ -140,7 +162,7 @@ class ClassParserTest extends \PHPUnit\Framework\TestCase
|
||||
]
|
||||
));
|
||||
|
||||
$cacheFile = 'tests/unit/testData/EntryPoints/cache/entryPoints.php';
|
||||
$cacheKey = 'entryPoints';
|
||||
$path = 'tests/unit/testData/EntryPoints/Espo/EntryPoints';
|
||||
|
||||
$result = [
|
||||
@@ -148,7 +170,7 @@ class ClassParserTest extends \PHPUnit\Framework\TestCase
|
||||
'Test' => 'tests\unit\testData\EntryPoints\Espo\EntryPoints\Test',
|
||||
];
|
||||
|
||||
$this->assertEquals($result, $this->reflection->invokeMethod('getData', [$path, $cacheFile, ['run']]));
|
||||
$this->assertEquals($result, $this->reflection->invokeMethod('getData', [$path, $cacheKey, ['run']]));
|
||||
}
|
||||
|
||||
function testGetDataWithCacheFalse()
|
||||
|
||||
Reference in New Issue
Block a user