Added Extension Manager

This commit is contained in:
Taras Machyshyn
2014-09-29 17:14:55 +03:00
parent a565b9c981
commit 9e0e743dc5
22 changed files with 1604 additions and 368 deletions

1
.gitignore vendored
View File

@@ -2,6 +2,7 @@
/data/cache/*
/data/upload/*
/data/preferences/*
/data/.backup/*
/data/config.php
/custom
/application/Espo/Resources/metadata/scopes/CustomTest.json

View File

@@ -72,7 +72,7 @@ class Admin extends \Espo\Core\Controllers\Base
{
$upgradeManager = new \Espo\Core\UpgradeManager($this->getContainer());
$upgradeManager->run($data['id']);
$upgradeManager->install($data['id']);
return true;
}

View File

@@ -33,13 +33,13 @@ class Extension extends \Espo\Core\Controllers\Record
throw new Forbidden();
}
}
public function actionUpload($params, $data, $request)
{
if (!$request->isPost()) {
throw new Forbidden();
throw new Forbidden();
}
$manager = new \Espo\Core\ExtensionManager($this->getContainer());
$id = $manager->upload($data);
@@ -56,22 +56,22 @@ class Extension extends \Espo\Core\Controllers\Record
public function actionInstall($params, $data, $request)
{
if (!$request->isPost()) {
throw new Forbidden();
throw new Forbidden();
}
$manager = new \Espo\Core\ExtensionManager($this->getContainer());
$manager->run($data['id']);
$manager->install($data['id']);
return true;
}
public function actionUninstall($params, $data, $request)
{
if (!$request->isPost()) {
throw new Forbidden();
}
throw new Forbidden();
}
$manager = new \Espo\Core\ExtensionManager($this->getContainer());
$manager->uninstall($data['id']);
@@ -98,30 +98,30 @@ class Extension extends \Espo\Core\Controllers\Record
{
throw new Forbidden();
}
public function actionDelete()
{
throw new Forbidden();
}
public function actionMassUpdate()
{
throw new Forbidden();
}
public function actionMassDelete()
{
throw new Forbidden();
}
public function actionCreateLink()
{
throw new Forbidden();
}
public function actionRemoveLink()
{
throw new Forbidden();
}
}
}

View File

@@ -22,15 +22,20 @@
namespace Espo\Core;
use Espo\Core\Exceptions\Error;
class ExtensionManager extends Upgrades\Base
{
protected $packagePath = 'data/upload/extensions';
protected $name = 'Extension';
protected $scriptNames = array(
'before' => 'BeforeUpgrade',
'after' => 'AfterUpgrade',
protected $params = array(
'packagePath' => 'data/upload/extensions',
'backupPath' => 'data/.backup/extensions',
'scriptNames' => array(
'before' => 'BeforeInstall',
'after' => 'AfterInstall',
'beforeUninstall' => 'BeforeUninstall',
'afterUninstall' => 'AfterUninstall',
)
);
}

View File

@@ -26,11 +26,14 @@ use Espo\Core\Exceptions\Error;
class UpgradeManager extends Upgrades\Base
{
protected $packagePath = 'data/upload/upgrades';
protected $name = 'Upgrade';
protected $scriptNames = array(
'before' => 'BeforeUpgrade',
'after' => 'AfterUpgrade',
protected $params = array(
'packagePath' => 'data/upload/upgrades',
'scriptNames' => array(
'before' => 'BeforeUpgrade',
'after' => 'AfterUpgrade',
)
);
}

View File

@@ -0,0 +1,102 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://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/.
************************************************************************/
namespace Espo\Core\Upgrades;
use Espo\Core\Exceptions\Error;
class ActionManager
{
private $managerName;
private $container;
private $objects;
protected $currentAction;
protected $params;
public function __construct($managerName, $container, $params)
{
$this->managerName = $managerName;
$this->container = $container;
$params['name'] = $managerName;
$this->params = $params;
}
protected function getManagerName()
{
return $this->managerName;
}
protected function getContainer()
{
return $this->container;
}
public function setAction($action)
{
$this->currentAction = $action;
}
protected function getAction()
{
return $this->currentAction;
}
protected function getParams()
{
return $this->params;
}
public function run($data)
{
$object = $this->getObject();
return $object->run($data);
}
public function getManifest()
{
return $this->getObject()->getManifest();
}
protected function getObject()
{
$managerName = $this->getManagerName();
$actionName = $this->getAction();
if (!isset($this->objects[$managerName][$actionName])) {
$class = '\Espo\Core\Upgrades\Actions\\' . ucfirst($managerName) . '\\' . ucfirst($actionName);
if (!class_exists($class)) {
throw new Error('Could not find class ['.$class.'].');
}
$this->objects[$managerName][$actionName] = new $class($this->container, $this->getParams());
}
return $this->objects[$managerName][$actionName];
}
}

View File

@@ -0,0 +1,445 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://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/.
************************************************************************/
namespace Espo\Core\Upgrades\Actions;
use Espo\Core\Utils\Util,
Espo\Core\Utils\Json,
Espo\Core\Exceptions\Error;
abstract class Base
{
private $container;
private $zipUtil;
private $fileManager;
private $config;
private $entityManager;
protected $data;
private $params = null;
protected $processId = null;
protected $manifestName = 'manifest.json';
protected $packagePostfix = 'z';
/**
* Directory name of files in a package
*/
const FILES = 'files';
/**
* Directory name of scripts in a package
*/
const SCRIPTS = 'scripts';
/**
* Statuses of Extension Entity
*/
const DISABLED = 'Disabled';
/**
* Statuses of Extension Entity
*/
const ENABLED = 'Enabled';
/**
* Package types
*/
protected $packageTypes = array(
'upgrade' => 'upgrade',
'extension' => 'extension',
);
/**
* Default package type
*/
protected $defaultPackageType = 'extension';
public function __construct($container, $params)
{
$this->container = $container;
$this->params = $params;
$this->zipUtil = new \Espo\Core\Utils\File\ZipArchive($container->get('fileManager'));
}
public function __destruct()
{
$this->processId = null;
$this->data = null;
}
protected function getContainer()
{
return $this->container;
}
protected function getParams($name = null)
{
if (isset($this->params[$name])) {
return $this->params[$name];
}
return $this->params;
}
protected function getZipUtil()
{
return $this->zipUtil;
}
protected function getFileManager()
{
if (!isset($this->fileManager)) {
$this->fileManager = $this->getContainer()->get('fileManager');
}
return $this->fileManager;
}
protected function getConfig()
{
if (!isset($this->config)) {
$this->config = $this->getContainer()->get('config');
}
return $this->config;
}
protected function getEntityManager()
{
if (!isset($this->entityManager)) {
$this->entityManager = $this->getContainer()->get('entityManager');
}
return $this->entityManager;
}
protected function throwErrorWithDetelePackage($errorMessage = '')
{
$this->deletePackageFiles();
$this->deletePackageArchive();
throw new Error($errorMessage);
}
abstract public function run($data);
protected function createProcessId()
{
if (isset($this->processId)) {
throw new Error('Another installation process is currently running.');
}
$this->processId = uniqid();
return $this->processId;
}
protected function getProcessId()
{
if (!isset($this->processId)) {
throw new Error('Installation ID was not specified.');
}
return $this->processId;
}
protected function setProcessId($processId)
{
$this->processId = $processId;
}
/**
* Check if version of upgrade/extension is acceptable to current version of EspoCRM
*
* @param string $version
* @return boolean
*/
protected function isAcceptable()
{
$res = $this->checkPackageType();
$res &= $this->checkVersions();
return $res;
}
protected function checkVersions()
{
$manifest = $this->getManifest();
/** check acceptable versions */
$version = $manifest['acceptableVersions'];
$currentVersion = $this->getConfig()->get('version');
if (is_string($version)) {
$version = (array) $version;
}
foreach ($version as $strVersion) {
$strVersion = trim($strVersion);
if ($strVersion == $currentVersion) {
return true;
}
$strVersion = str_replace('\\', '', $strVersion);
$strVersion = preg_quote($strVersion);
$strVersion = str_replace('\\*', '+', $strVersion);
if (preg_match('/^'.$strVersion.'/', $currentVersion)) {
return true;
}
}
$this->throwErrorWithDetelePackage('Your EspoCRM version doesn\'t match for this installation package.');
}
protected function checkPackageType()
{
$manifest = $this->getManifest();
/** check package type */
$type = strtolower( $this->getParams('name') );
$manifestType = isset($manifest['type']) ? strtolower($manifest['type']) : $this->defaultPackageType;
if (!in_array($manifestType, $this->packageTypes)) {
$this->throwErrorWithDetelePackage('Unknown package type.');
}
if ($type != $manifestType) {
$this->throwErrorWithDetelePackage('Wrong package type. You cannot install '.$manifestType.' package via '.ucfirst($type).' Manager.');
}
return true;
}
/**
* Run scripts by type
* @param string $type Ex. "before", "after"
* @return void
*/
protected function runScript($type)
{
$packagePath = $this->getPath('packagePath');
$scriptNames = $this->getParams('scriptNames');
$scriptName = $scriptNames[$type];
if (!isset($scriptName)) {
return;
}
$beforeInstallScript = Util::concatPath( array($packagePath, self::SCRIPTS, $scriptName) ) . '.php';
if (file_exists($beforeInstallScript)) {
require_once($beforeInstallScript);
$script = new $scriptName();
$script->run($this->getContainer());
}
}
/**
* Get package path
*
* @param string $processId
* @return string
*/
protected function getPath($name = 'packagePath', $isPackage = false)
{
$postfix = $isPackage ? $this->packagePostfix : '';
$processId = $this->getProcessId();
$path = Util::concatPath($this->getParams($name), $processId);
return $path . $postfix;
}
/**
* Get a list of files defined in manifest.json
*
* @return [type] [description]
*/
protected function getDeleteFileList()
{
$manifest = $this->getManifest();
if (!empty($manifest['delete'])) {
return $manifest['delete'];
}
return array();
}
/**
* Delete files defined in a manifest
*
* @return boolen
*/
protected function deleteFiles()
{
$deleteFileList = $this->getDeleteFileList();
if (!empty($deleteFileList)) {
return $this->getFileManager()->remove($deleteFileList);
}
return true;
}
protected function getCopyFileList()
{
if (!isset($this->data['fileList'])) {
$packagePath = $this->getPath('packagePath');
$filesPath = Util::concatPath($packagePath, self::FILES);
$this->data['fileList'] = $this->getFileManager()->getFileList($filesPath, true, '', 'all', true);
}
return $this->data['fileList'];
}
/**
* Copy files from upgrade/extension package
*
* @param string $processId
* @return boolean
*/
protected function copyFiles()
{
$packagePath = $this->getPath('packagePath');
$filesPath = Util::concatPath($packagePath, self::FILES);
return $this->getFileManager()->copy($filesPath, '', true);
}
public function getManifest()
{
if (!isset($this->data['manifest'])) {
$packagePath = $this->getPath('packagePath');
$manifestPath = Util::concatPath($packagePath, $this->manifestName);
if (!file_exists($manifestPath)) {
throw new Error('It\'s not an Installation package.');
}
$manifestJson = $this->getFileManager()->getContents($manifestPath);
$this->data['manifest'] = Json::decode($manifestJson, true);
if (!$this->data['manifest']) {
throw new Error('Syntax error in manifest.json.');
}
if (!$this->checkManifest($this->data['manifest'])) {
throw new Error('Unsupported package.');
}
}
return $this->data['manifest'];
}
/**
* Check if the manifest is correct
*
* @param array $manifest
* @return boolean
*/
protected function checkManifest(array $manifest)
{
$requiredFields = array(
'name',
'version',
'acceptableVersions',
);
foreach ($requiredFields as $fieldName) {
if (empty($manifest[$fieldName])) {
return false;
}
}
return true;
}
/**
* Unzip a package archieve
*
* @return void
*/
protected function unzipArchive()
{
$packagePath = $this->getPath('packagePath');
$packageArchivePath = $this->getPath('packagePath', true);
$res = $this->getZipUtil()->unzip($packageArchivePath, $packagePath);
if ($res === false) {
throw new Error('Unnable to unzip the file - '.$packagePath.'.');
}
}
/**
* Delete temporary package files
*
* @return boolean
*/
protected function deletePackageFiles()
{
$packagePath = $this->getPath('packagePath');
$res = $this->getFileManager()->removeInDir($packagePath, true);
return $res;
}
/**
* Delete temporary package archive
*
* @return boolean
*/
protected function deletePackageArchive()
{
$packageArchive = $this->getPath('packagePath', true);
$res = $this->getFileManager()->removeFile($packageArchive);
return $res;
}
protected function systemRebuild()
{
return $this->getContainer()->get('dataManager')->rebuild();
}
protected function beforeRunAction()
{
}
protected function afterRunAction()
{
}
}

View File

@@ -0,0 +1,55 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://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/.
************************************************************************/
namespace Espo\Core\Upgrades\Actions\Base;
class Delete extends \Espo\Core\Upgrades\Actions\Base
{
public function run($processId)
{
$GLOBALS['log']->debug('Delete package process ['.$processId.']: start run.');
if (empty($processId)) {
throw new Error('Delete package package ID was not specified.');
}
$this->setProcessId($processId);
$this->beforeRunAction();
/* delete a package */
$this->deletePackage();
$this->afterRunAction();
$GLOBALS['log']->debug('Delete package process ['.$processId.']: end run.');
}
protected function deletePackage()
{
$packageArchivePath = $this->getPath('packagePath', true);
$res = $this->getFileManager()->removeFile($packageArchivePath);
return $res;
}
}

View File

@@ -0,0 +1,81 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://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/.
************************************************************************/
namespace Espo\Core\Upgrades\Actions\Base;
use Espo\Core\Exceptions\Error;
class Install extends \Espo\Core\Upgrades\Actions\Base
{
/**
* Main installation process
*
* @param string $processId Upgrade/Extension ID, gotten in upload stage
* @return bool
*/
public function run($processId)
{
$GLOBALS['log']->debug('Installation process ['.$processId.']: start run.');
if (empty($processId)) {
throw new Error('Installation package ID was not specified.');
}
$this->setProcessId($processId);
/** check if an archive is unzipped, if no then unzip */
$packagePath = $this->getPath('packagePath');
if (!file_exists($packagePath)) {
$this->unzipArchive();
$this->isAcceptable();
}
$this->beforeRunAction();
/* run before install script */
$this->runScript('before');
/* remove files defined in a manifest */
if (!$this->deleteFiles()) {
throw new Error('Permission denied to delete files.');
}
/* copy files from directory "Files" to EspoCRM files */
if (!$this->copyFiles()) {
throw new Error('Cannot copy files.');
}
if (!$this->systemRebuild()) {
throw new Error('Error occurred while EspoCRM rebuild.');
}
/* run before install script */
$this->runScript('after');
$this->afterRunAction();
/* delete unziped files */
$this->deletePackageFiles();
$GLOBALS['log']->debug('Installation process ['.$processId.']: end run.');
}
}

View File

@@ -0,0 +1,103 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://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/.
************************************************************************/
namespace Espo\Core\Upgrades\Actions\Base;
use Espo\Core\Exceptions\Error;
class Uninstall extends \Espo\Core\Upgrades\Actions\Base
{
public function run($processId)
{
$GLOBALS['log']->debug('Uninstallation process ['.$processId.']: start run.');
if (empty($processId)) {
throw new Error('Uninstallation package ID was not specified.');
}
$this->setProcessId($processId);
$this->beforeRunAction();
/* run before install script */
$this->runScript('beforeUninstall');
/* remove extension files, saved in fileList */
if (!$this->deleteFiles()) {
throw new Error('Permission denied to delete files.');
}
/* copy core files */
if (!$this->copyFiles()) {
throw new Error('Cannot copy files.');
}
if (!$this->systemRebuild()) {
throw new Error('Error occurred while EspoCRM rebuild.');
}
/* run before install script */
$this->runScript('afterUninstall');
$this->afterRunAction();
/* delete backup files */
$this->deletePackageFiles();
$GLOBALS['log']->debug('Uninstallation process ['.$processId.']: end run.');
}
protected function getDeleteFileList()
{
$extensionEntity = $this->getExtensionEntity();
return $extensionEntity->get('fileList');
}
protected function copyFiles()
{
$backupPath = $this->getPath('backupPath');
$res = $this->getFileManager()->copy(array($backupPath, self::FILES), '', true);
return $res;
}
/**
* Get backup path
*
* @param string $processId
* @return string
*/
protected function getPath($name = 'packagePath', $isPackage = false)
{
$name = ($name == 'packagePath') ? 'backupPath' : $name;
return parent::getPath($name, $isPackage);
}
protected function deletePackageFiles()
{
$backupPath = $this->getPath('backupPath');
$res = $this->getFileManager()->removeInDir($backupPath, true);
return $res;
}
}

View File

@@ -0,0 +1,62 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://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/.
************************************************************************/
namespace Espo\Core\Upgrades\Actions\Base;
use Espo\Core\Exceptions\Error;
class Upload extends \Espo\Core\Upgrades\Actions\Base
{
/**
* Upload an upgrade/extension package
*
* @param [type] $contents
* @return string ID of upgrade/extension process
*/
public function run($data)
{
$processId = $this->createProcessId();
$GLOBALS['log']->debug('Installation process ['.$processId.']: start upload the package.');
$packagePath = $this->getPath('packagePath');
$packageArchivePath = $this->getPath('packagePath', true);
if (!empty($data)) {
list($prefix, $contents) = explode(',', $data);
$contents = base64_decode($contents);
}
$res = $this->getFileManager()->putContents($packageArchivePath, $contents);
if ($res === false) {
throw new Error('Could not upload the package.');
}
$this->unzipArchive();
$this->isAcceptable();
$GLOBALS['log']->debug('Installation process ['.$processId.']: end upload the package.');
return $processId;
}
}

View File

@@ -0,0 +1,75 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://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/.
************************************************************************/
namespace Espo\Core\Upgrades\Actions\Extension;
use Espo\Core\Exceptions\Error;
class Delete extends \Espo\Core\Upgrades\Actions\Base\Delete
{
protected $extensionEntity;
/**
* Get entity of this extension
*
* @return \Espo\Entities\Extension
*/
protected function getExtensionEntity()
{
return $this->extensionEntity;
}
/**
* Set Extension Entity
*
* @param \Espo\Entities\Extension $extensionEntity
*/
protected function setExtensionEntity(\Espo\Entities\Extension $extensionEntity)
{
$this->extensionEntity = $extensionEntity;
}
protected function beforeRunAction()
{
$processId = $this->getProcessId();
/** get extension entity */
$extensionEntity = $this->getEntityManager()->getEntity('Extension', $processId);
if (!isset($extensionEntity)) {
throw new Error('Extension Entity not found.');
}
$this->setExtensionEntity($extensionEntity);
/** check if extension archive exsists */
$packageArchivePath = $this->getPath('packagePath', true);
if (!file_exists($packageArchivePath)) {
throw new Error('Extension Archive doesn\'t exist.');
}
}
protected function afterRunAction()
{
/** Delete extension entity */
$extensionEntity = $this->getExtensionEntity();
$this->getEntityManager()->removeEntity($extensionEntity);
}
}

View File

@@ -0,0 +1,166 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://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/.
************************************************************************/
namespace Espo\Core\Upgrades\Actions\Extension;
use Espo\Core\Exceptions\Error;
class Install extends \Espo\Core\Upgrades\Actions\Base\Install
{
protected $extensionEntity = null;
protected function beforeRunAction()
{
$this->findExtension();
$this->compareVersion();
$this->copyExistingFiles();
}
protected function afterRunAction()
{
$this->storeExtension();
}
/**
* Copy Existing files to backup directory
*
* @return bool
*/
protected function copyExistingFiles()
{
$fileList = $this->getCopyFileList();
$backupPath = $this->getPath('backupPath');
$res = $this->getFileManager()->copy('', array($backupPath, self::FILES), false, $fileList);
/** copy scripts files */
$packagePath = $this->getPath('packagePath');
$res &= $this->getFileManager()->copy(array($packagePath, self::SCRIPTS), array($backupPath, self::SCRIPTS), true);
return $res;
}
protected function isNew()
{
$extensionEntity = $this->getExtensionEntity();
if (isset($extensionEntity)) {
$id = $this->getExtensionEntity()->get('id');
}
return isset($id) ? false : true;
}
/**
* Get extension ID. It's an ID of existing entity (if available) or Installation ID
*
* @return string
*/
protected function getExtensionId()
{
$extensionEntity = $this->getExtensionEntity();
if (isset($extensionEntity)) {
$extensionEntityId = $extensionEntity->get('id');
}
if (!isset($extensionEntityId)) {
return $this->getProcessId();
}
return $extensionEntityId;
}
/**
* Get entity of this extension
*
* @return \Espo\Entities\Extension
*/
protected function getExtensionEntity()
{
return $this->extensionEntity;
}
/**
* Find Extension entity
*
* @return \Espo\Entities\Extension
*/
protected function findExtension()
{
$manifest = $this->getManifest();
$this->extensionEntity = $this->getEntityManager()->getRepository('Extension')->where(array(
'name' => $manifest['name'],
'isInstalled' => true,
))->findOne();
return $this->extensionEntity;
}
/**
* Create a record of Extension Entity
*
* @return bool
*/
protected function storeExtension()
{
$entityManager = $this->getEntityManager();
$extensionEntity = $entityManager->getEntity('Extension');
$manifest = $this->getManifest();
$fileList = $this->getCopyFileList();
$data = array(
'id' => $this->getProcessId(),
'name' => $manifest['name'],
'status' => self::ENABLED,
'isInstalled' => true,
'version' => $manifest['version'],
'fileList' => $fileList,
'description' => $manifest['description'],
);
$extensionEntity->set($data);
return $entityManager->saveEntity($extensionEntity);
}
/**
* Compare version between installed and a new extensions
*
* @return void
*/
protected function compareVersion()
{
$manifest = $this->getManifest();
$extensionEntity = $this->getExtensionEntity();
if (isset($extensionEntity)) {
$comparedVersion = version_compare($manifest['version'], $extensionEntity->get('version'));
if ($comparedVersion <= 0) {
$this->throwErrorWithDetelePackage('You cannot install an older version of this extension.');
}
}
}
}

View File

@@ -0,0 +1,78 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://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/.
************************************************************************/
namespace Espo\Core\Upgrades\Actions\Extension;
use Espo\Core\Exceptions\Error;
class Uninstall extends \Espo\Core\Upgrades\Actions\Base\Uninstall
{
protected $extensionEntity;
/**
* Get entity of this extension
*
* @return \Espo\Entities\Extension
*/
protected function getExtensionEntity()
{
return $this->extensionEntity;
}
/**
* Set Extension Entity
*
* @param \Espo\Entities\Extension $extensionEntity [description]
*/
protected function setExtensionEntity(\Espo\Entities\Extension $extensionEntity)
{
$this->extensionEntity = $extensionEntity;
}
protected function beforeRunAction()
{
$processId = $this->getProcessId();
/** get extension entity */
$extensionEntity = $this->getEntityManager()->getEntity('Extension', $processId);
if (!isset($extensionEntity)) {
throw new Error('Extension Entity not found.');
}
$this->setExtensionEntity($extensionEntity);
/** check if backup of the extension exsists */
$backupPath = $this->getPath('backupPath');
if (!file_exists($backupPath)) {
throw new Error('Backup files don\'t exist.');
}
}
protected function afterRunAction()
{
/** Set extension entity, isInstalled = false */
$extensionEntity = $this->getExtensionEntity();
$extensionEntity->set('status', self::DISABLED);
$extensionEntity->set('isInstalled', false);
$this->getEntityManager()->saveEntity($extensionEntity);
}
}

View File

@@ -0,0 +1,28 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://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/.
************************************************************************/
namespace Espo\Core\Upgrades\Actions\Extension;
class Upload extends \Espo\Core\Upgrades\Actions\Base\Upload
{
}

View File

@@ -0,0 +1,52 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://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/.
************************************************************************/
namespace Espo\Core\Upgrades\Actions\Upgrade;
class Install extends \Espo\Core\Upgrades\Actions\Base\Install
{
protected function systemRebuild()
{
$manifest = $this->getManifest();
$res = $this->getConfig()->set('version', $manifest['version']);
if (method_exists($this->getConfig(), 'save')) {
$res = $this->getConfig()->save();
}
$res &= parent::systemRebuild();
return $res;
}
/**
* Delete temporary package files
*
* @return boolean
*/
protected function deletePackageFiles()
{
$res = parent::deletePackageFiles();
$res &= $this->deletePackageArchive();
return $res;
}
}

View File

@@ -0,0 +1,28 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://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/.
************************************************************************/
namespace Espo\Core\Upgrades\Actions\Upgrade;
class Upload extends \Espo\Core\Upgrades\Actions\Base\Upload
{
}

View File

@@ -30,44 +30,23 @@ abstract class Base
{
private $container;
private $zipUtil;
protected $name = null;
private $fileManager;
protected $params = array();
private $config;
const UPLOAD = 'upload';
protected $upgradeId = null;
const INSTALL = 'install';
protected $manifestName = 'manifest.json';
protected $data;
protected $packagePath = null;
protected $packagePostfix = 'z';
protected $scriptNames = array(
'before' => 'Before',
'after' => 'After',
);
protected $paths = array(
'files' => 'files',
'scripts' => 'scripts',
);
const UNINSTALL = 'uninstall';
const DELETE = 'delete';
public function __construct($container)
{
$this->container = $container;
$this->zipUtil = new \Espo\Core\Utils\File\ZipArchive($container->get('fileManager'));
}
public function __destruct()
{
$this->upgradeId = null;
$this->data = null;
$this->actionManager = new ActionManager($this->name, $container, $this->params);
}
protected function getContainer()
@@ -75,319 +54,41 @@ abstract class Base
return $this->container;
}
protected function getZipUtil()
protected function getActionManager()
{
return $this->zipUtil;
}
protected function getFileManager()
{
if (!isset($this->fileManager)) {
$this->fileManager = $this->getContainer()->get('fileManager');
}
return $this->fileManager;
}
protected function getConfig()
{
if (!isset($this->config)) {
$this->config = $this->getContainer()->get('config');
}
return $this->config;
}
/**
* Upload an upgrade package
*
* @param [type] $contents
* @return string ID of upgrade process
*/
public function upload($data)
{
$upgradeId = $this->createUpgradeId();
$GLOBALS['log']->debug('Upgrade process ['.$upgradeId.']: start upload the package.');
$upgradePath = $this->getUpgradePath();
$upgradePackagePath = $this->getUpgradePath(true);
if (!empty($data)) {
list($prefix, $contents) = explode(',', $data);
$contents = base64_decode($contents);
}
$res = $this->getFileManager()->putContents($upgradePackagePath, $contents);
if ($res === false) {
throw new Error('Could not upload the package.');
}
$res = $this->getZipUtil()->unzip($upgradePackagePath, $upgradePath);
if ($res === false) {
throw new Error('Unnable to unzip the file - '.$upgradePath.'.');
}
if (!$this->isAcceptable()) {
throw new Error("Your EspoCRM version doesn't match for this upgrade package.");
}
$GLOBALS['log']->debug('Upgrade process ['.$upgradeId.']: end upload the package.');
return $upgradeId;
}
/**
* Main upgrade process
*
* @param string $upgradeId Upgrade ID, gotten in upload stage
* @return bool
*/
public function run($upgradeId)
{
$GLOBALS['log']->debug('Upgrade process ['.$upgradeId.']: start run.');
if (empty($upgradeId)) {
throw new Error('Upgrade ID was not specified.');
}
$this->setUpgradeId($upgradeId);
/* run before install script */
$this->runScript('before');
/* remove files defined in a manifest */
if (!$this->deleteFiles()) {
throw new Error('Permission denied to delete files.');
}
/* copy files from directory "Files" to EspoCRM files */
if (!$this->copyFiles()) {
throw new Error('Cannot copy files.');
}
if (!$this->systemRebuild()) {
throw new Error('Error occurred while EspoCRM rebuild.');
}
/* run before install script */
$this->runScript('after');
/* delete unziped files */
$this->deletePackageFiles();
$GLOBALS['log']->debug('Upgrade process ['.$upgradeId.']: end run.');
}
protected function createUpgradeId()
{
if (isset($this->upgradeId)) {
throw new Error('Another upgrade process is currently running.');
}
$this->upgradeId = uniqid();
return $this->upgradeId;
}
protected function getUpgradeId()
{
if (!isset($this->upgradeId)) {
throw new Error("Upgrade ID was not specified.");
}
return $this->upgradeId;
}
protected function setUpgradeId($upgradeId)
{
$this->upgradeId = $upgradeId;
}
/**
* Check if version of upgrade is acceptable to current version of EspoCRM
*
* @param string $version
* @return boolean
*/
protected function isAcceptable()
{
$manifest = $this->getManifest();
$version = $manifest['acceptableVersions'];
$currentVersion = $this->getConfig()->get('version');
if (is_string($version)) {
$version = (array) $version;
}
foreach ($version as $strVersion) {
$strVersion = trim($strVersion);
if ($strVersion == $currentVersion) {
return true;
}
$strVersion = str_replace('\\', '', $strVersion);
$strVersion = preg_quote($strVersion);
$strVersion = str_replace('\\*', '+', $strVersion);
if (preg_match('/^'.$strVersion.'/', $currentVersion)) {
return true;
}
}
return false;
}
/**
* Run scripts by type
* @param string $type Ex. "before", "after"
* @return void
*/
protected function runScript($type)
{
$upgradePath = $this->getUpgradePath();
$scriptName = $this->scriptNames[$type];
if (!isset($scriptName)) {
return;
}
$beforeInstallScript = Util::concatPath( array($upgradePath, $this->paths['scripts'], $scriptName) ) . '.php';
if (file_exists($beforeInstallScript)) {
require_once($beforeInstallScript);
$script = new $scriptName();
$script->run($this->getContainer());
}
}
/**
* Get upgrade path
*
* @param string $upgradeId
* @return string
*/
protected function getUpgradePath($isPackage = false)
{
$postfix = $isPackage ? $this->packagePostfix : '';
if (!isset($this->data['upgradePath'])) {
$upgradeId = $this->getUpgradeId();
$this->data['upgradePath'] = Util::concatPath($this->packagePath, $upgradeId);
}
return $this->data['upgradePath'] . $postfix;
}
/**
* Delete files defined in a manifest
*
* @return boolen
*/
protected function deleteFiles()
{
$manifest = $this->getManifest();
if (!empty($manifest['delete'])) {
return $this->getFileManager()->remove($manifest['delete']);
}
return true;
}
/**
* Copy files from upgrade package
*
* @param string $upgradeId
* @return boolean
*/
protected function copyFiles()
{
$upgradePath = $this->getUpgradePath();
$filesPath = Util::concatPath($upgradePath, $this->paths['files']);
return $this->getFileManager()->copy($filesPath, '', true);
return $this->actionManager;
}
public function getManifest()
{
if (!isset($this->data['manifest'])) {
$upgradePath = $this->getUpgradePath();
$manifestPath = Util::concatPath($upgradePath, $this->manifestName);
if (!file_exists($manifestPath)) {
throw new Error('It\'s not an upgrade package.');
}
$manifestJson = $this->getFileManager()->getContents($manifestPath);
$this->data['manifest'] = Json::decode($manifestJson, true);
if (!$this->data['manifest']) {
throw new Error('Syntax error in manifest.json.');
}
if (!$this->checkManifest($this->data['manifest'])) {
throw new Error('Unsupported package.');
}
}
return $this->data['manifest'];
return $this->getActionManager()->getManifest();
}
/**
* Check if the manifest is correct
*
* @param array $manifest
* @return boolean
*/
protected function checkManifest(array $manifest)
public function upload($data)
{
$requiredFields = array(
'name',
'version',
'acceptableVersions',
);
$this->getActionManager()->setAction(self::UPLOAD);
foreach ($requiredFields as $fieldName) {
if (empty($manifest[$fieldName])) {
return false;
}
}
return true;
return $this->getActionManager()->run($data);
}
/**
* Delete temporary package files
*
* @return boolean
*/
protected function deletePackageFiles()
public function install($processId)
{
$upgradePath = $this->getUpgradePath();
$upgradePackagePath = $this->getUpgradePath(true);
$this->getActionManager()->setAction(self::INSTALL);
$res = $this->getFileManager()->removeInDir($upgradePath, true);
$res &= $this->getFileManager()->removeFile($upgradePackagePath);
return $res;
return $this->getActionManager()->run($processId);
}
protected function systemRebuild()
public function uninstall($processId)
{
$manifest = $this->getManifest();
$this->getActionManager()->setAction(self::UNINSTALL);
$res = $this->getConfig()->set('version', $manifest['version']);
if (method_exists($this->getConfig(), 'save')) {
$res = $this->getConfig()->save();
}
$res &= $this->getContainer()->get('dataManager')->rebuild();
return $res;
return $this->getActionManager()->run($processId);
}
public function delete($processId)
{
$this->getActionManager()->setAction(self::DELETE);
return $this->getActionManager()->run($processId);
}
}

View File

@@ -362,40 +362,67 @@ class Manager
/**
* Copy files from one direcoty to another
* Ex. $sourcePath = 'data/uploads/extensions/file.json', $destPath = 'data/uploads/backup', result will be data/uploads/backup/data/uploads/backup/file.json.
*
* @param string $sourcePath
* @param string $destPath
* @param boolean $recursively
* @param array $fileList - list of files that should be copied
* @param boolean $copyOnlyFiles - copy only files, instead of full path with directories, Ex. $sourcePath = 'data/uploads/extensions/file.json', $destPath = 'data/uploads/backup', result will be 'data/uploads/backup/file.json'
* @return boolen
*/
public function copy($sourcePath, $destPath, $recursively = false)
public function copy($sourcePath, $destPath, $recursively = false, array $fileList = null, $copyOnlyFiles = false)
{
$sourcePath = $this->concatPaths($sourcePath);
$destPath = $this->concatPaths($destPath);
if (is_file($sourcePath)) {
$fileList = (array) $sourcePath;
if (isset($fileList)) {
if (!empty($sourcePath)) {
foreach ($fileList as &$fileName) {
$fileName = $this->concatPaths(array($sourcePath, $fileName));
}
}
} else {
$fileList = $this->getFileList($sourcePath, $recursively, '', 'all', true);
$fileList = is_file($sourcePath) ? (array) $sourcePath : $this->getFileList($sourcePath, $recursively, '', 'all', true);
}
/** Check permission before copying */
$permissionDeniedList = array();
foreach ($fileList as $file) {
if ($copyOnlyFiles) {
$file = pathinfo($file, PATHINFO_BASENAME);
}
$destFile = $this->concatPaths(array($destPath, $file));
if ($this->checkCreateFile($destFile) === false) {
$permissionDeniedList[] = $destFile;
}
}
/** END */
if (!empty($permissionDeniedList)) {
$betterPermissionList = $this->getPermissionUtils()->arrangePermissionList($permissionDeniedList);
throw new Error("Permission denied in <br>". implode(", <br>", $betterPermissionList));
}
$res = true;
foreach ($fileList as $file) {
$sourceFile = $this->concatPaths(array($sourcePath, $file));
$destFile = $this->concatPaths(array($destPath, $file));
if ($this->checkCreateFile($destFile) === false) {
throw new Error('Permission denied in '. $destFile);
if ($copyOnlyFiles) {
$file = pathinfo($file, PATHINFO_BASENAME);
}
$sourceFile = is_file($sourcePath) ? $sourcePath : $this->concatPaths(array($sourcePath, $file));
$destFile = $this->concatPaths(array($destPath, $file));
$res &= copy($sourceFile, $destFile);
}
return $res;
}
/**
* Create a new file if not exists with all folders in the path.
*
@@ -566,7 +593,6 @@ class Manager
return $pathInfo['dirname'];
}
/**
* Return content of PHP file
*

View File

@@ -535,6 +535,71 @@ class Permission
return $this->permissionErrorRules;
}
/**
* Arrange permission file list
* e.g. array('application/Espo/Controllers/Email.php', 'application/Espo/Controllers/Import.php'), result is array('application/Espo/Controllers')
*
* @param array $fileList
* @return array
*/
public function arrangePermissionList($fileList)
{
$betterList = array();
foreach ($fileList as $fileName) {
$pathInfo = pathinfo($fileName);
$dirname = $pathInfo['dirname'];
$currentPath = $fileName;
if ($this->getSearchCount($dirname, $fileList) > 1) {
$currentPath = $dirname;
}
if (!$this->isItemIncludes($currentPath, $betterList)) {
$betterList[] = $currentPath;
}
}
return $betterList;
}
/**
* Get count of a search string in a array
*
* @param string $search
* @param array $array
* @return bool
*/
protected function getSearchCount($search, array $array)
{
$search = $this->getPregQuote($search);
$number = 0;
foreach ($array as $value) {
if (preg_match('/^'.$search.'/', $value)) {
$number++;
}
}
return $number;
}
protected function isItemIncludes($item, $array)
{
foreach ($array as $value) {
$value = $this->getPregQuote($value);
if (preg_match('/^'.$value.'/', $item)) {
return true;
}
}
return false;
}
protected function getPregQuote($string)
{
return preg_quote($string, '/-+=.');
}
}

View File

@@ -2,7 +2,7 @@
"fields": {
"name": {
"type": "varchar",
"required": true
"required": true
},
"status": {
"type": "enum",
@@ -11,13 +11,17 @@
"version": {
"type": "varchar",
"required": true,
"maxLength": 50
"maxLength": 50
},
"fileList": {
"type": "jsonArray"
},
"type": "jsonArray"
},
"description": {
"type": "text"
"type": "text"
},
"isInstalled": {
"type": "bool",
"default": false
},
"createdAt": {
"type": "datetime",

View File

@@ -0,0 +1,156 @@
<?php
namespace tests\Espo\Core\Utils\File;
use tests\ReflectionHelper;
class PermissionTest extends \PHPUnit_Framework_TestCase
{
protected $object;
protected $objects;
protected $reflection;
protected $fileList;
protected function setUp()
{
$this->objects['fileManager'] = $this->getMockBuilder('\Espo\Core\Utils\File\Manager')->disableOriginalConstructor()->getMock();
$this->object = new \Espo\Core\Utils\File\Permission($this->objects['fileManager']);
$this->reflection = new ReflectionHelper($this->object);
$this->fileList = array(
'application/Espo/Controllers/Email.php',
'application/Espo/Controllers/EmailAccount.php',
'application/Espo/Controllers/EmailAddress.php',
'application/Espo/Controllers/ExternalAccount.php',
'application/Espo/Controllers/Import.php',
'application/Espo/Controllers/Integration.php',
'application/Espo/Modules/Crm/Resources/i18n/pl_PL/Calendar.json',
'application/Espo/Modules/Crm/Resources/i18n/pl_PL/Call.json',
'application/Espo/Modules/Crm/Resources/i18n/pl_PL/Case.json',
'application/Espo/Modules/Crm/Resources/i18n/pl_PL/Contact.json',
'application/Espo/Modules/Crm/Resources/i18n/pl_PL/Global.json',
'application/Espo/Resources/layouts/User/filters.json',
'application/Espo/Resources/metadata/app/acl.json',
'application/Espo/Resources/metadata/app/defaultDashboardLayout.json'
);
}
protected function tearDown()
{
$this->object = NULL;
}
public function testGetSearchCount()
{
$search = 'application/Espo/Controllers/';
$methodResult = $this->reflection->invokeMethod('getSearchCount', array($search, $this->fileList));
$result = 6;
$this->assertEquals($result, $methodResult);
$search = 'application/Espo/Controllers/Email.php';
$methodResult = $this->reflection->invokeMethod('getSearchCount', array($search, $this->fileList));
$result = 1;
$this->assertEquals($result, $methodResult);
$search = 'application/Espo/Controllers/NotReal';
$methodResult = $this->reflection->invokeMethod('getSearchCount', array($search, $this->fileList));
$result = 0;
$this->assertEquals($result, $methodResult);
}
public function testArrangePermissionList()
{
$result = array(
'application/Espo/Controllers',
'application/Espo/Modules/Crm/Resources/i18n/pl_PL',
'application/Espo/Resources/layouts/User/filters.json',
'application/Espo/Resources/metadata/app',
);
$this->assertEquals( $result, $this->object->arrangePermissionList($this->fileList) );
}
/*public function bestPossibleList()
{
$fileList = array(
'application/Espo/Controllers',
'application/Espo/Core',
'application/Espo/Core/Cron',
'application/Espo/Core/Loaders',
'application/Espo/Core/Mail',
'application/Espo/Core/Mail/Storage/Imap.php',
'application/Espo/Core/SelectManagers/Base.php',
'application/Espo/Core/Utils/Database/Orm',
'application/Espo/Core/Utils/Database/Orm/Fields',
'application/Espo/Core/Utils/Database/Orm/Relations',
'application/Espo/Core/Utils',
'application/Espo/Core/defaults/config.php',
'application/Espo/Entities',
'application/Espo/Hooks/Common/Stream.php',
'application/Espo/Modules/Crm/Controllers/Opportunity.php',
'application/Espo/Modules/Crm/Jobs/CheckInboundEmails.php',
'application/Espo/Modules/Crm/Resources/i18n/de_DE',
'application/Espo/Modules/Crm/Resources/i18n/en_US',
'application/Espo/Modules/Crm/Resources/i18n/nl_NL',
'application/Espo/Modules/Crm/Resources/i18n/pl_PL',
'application/Espo/Modules/Crm/Resources/layouts/InboundEmail',
'application/Espo/Modules/Crm/Resources/metadata/clientDefs/InboundEmail.json',
'application/Espo/Modules/Crm/Resources/metadata/entityDefs',
'application/Espo/Modules/Crm/Services',
'application/Espo/Repositories',
'application/Espo/Resources/i18n/de_DE',
'application/Espo/Resources/i18n/en_US',
'application/Espo/Resources/i18n/nl_NL',
'application/Espo/Resources/i18n/pl_PL',
'application/Espo/Resources/layouts/Email',
'application/Espo/Resources/layouts/EmailAccount',
'application/Espo/Resources/layouts/User/filters.json',
'application/Espo/Resources/metadata/app',
'application/Espo/Resources/metadata/clientDefs',
'application/Espo/Resources/metadata/entityDefs',
'application/Espo/Resources/metadata/integrations/Google.json',
'application/Espo/Resources/metadata/scopes',
'application/Espo/SelectManagers/EmailAccount.php',
'application/Espo/Services',
'install/core',
'install/core/actions/settingsTest.php',
'install/core/i18n/de_DE/install.json',
'install/core/i18n/en_US/install.json',
'install/core/i18n/es_ES/install.json',
'install/core/i18n/nl_NL/install.json',
'install/core/i18n/pl_PL/install.json',
'install/core/i18n/ro_RO/install.json',
'install/core/i18n/tr_TR/install.json',
'install/js/install.js',
);
$result = array(
'application/Espo/Controllers',
'application/Espo/Core',
'application/Espo/Entities',
'application/Espo/Hooks/Common/Stream.php',
'application/Espo/Modules/Crm',
'application/Espo/Repositories',
'application/Espo/Resources',
'application/Espo/SelectManagers/EmailAccount.php',
'application/Espo/Services',
'install/core',
'install/js/install.js',
);
}*/
}
?>