Merged in feature/HOR-3208 (pull request #5694)
Feature/HOR-3208 Approved-by: Julio Cesar Laura Avendaño <contact@julio-laura.com>
This commit is contained in:
committed by
Julio Cesar Laura Avendaño
commit
a9b5c1dd10
13
phpunit.xml
13
phpunit.xml
@@ -12,17 +12,6 @@
|
|||||||
bootstrap="tests/bootstrap.php"
|
bootstrap="tests/bootstrap.php"
|
||||||
>
|
>
|
||||||
<testsuites>
|
<testsuites>
|
||||||
<!-- <testsuite name="automated">
|
|
||||||
<directory>./tests/automated/</directory>
|
|
||||||
</testsuite>
|
|
||||||
|
|
||||||
<testsuite name="unit">
|
|
||||||
<directory>./tests/unit/</directory>
|
|
||||||
</testsuite>
|
|
||||||
|
|
||||||
<testsuite name="api">
|
|
||||||
<directory>./workflow/engine/src/</directory>
|
|
||||||
</testsuite>-->
|
|
||||||
<testsuite name="workflow">
|
<testsuite name="workflow">
|
||||||
<directory>./tests/workflow/engine/src/</directory>
|
<directory>./tests/workflow/engine/src/</directory>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
@@ -55,7 +44,7 @@
|
|||||||
<var name="DB_USER" value="root" />
|
<var name="DB_USER" value="root" />
|
||||||
<var name="DB_PASS" value="" />
|
<var name="DB_PASS" value="" />
|
||||||
<var name="PATH_DB" value="./test_shared/workflow_data/sites/" />
|
<var name="PATH_DB" value="./test_shared/workflow_data/sites/" />
|
||||||
<var name="PATH_DATA" value="./test_shared/workflow_data/sites/" />
|
<var name="PATH_DATA" value="./test_shared/workflow_data/" />
|
||||||
<var name="APP_HOST" value="localhost" />
|
<var name="APP_HOST" value="localhost" />
|
||||||
<var name="HTTPS" value="off" />
|
<var name="HTTPS" value="off" />
|
||||||
</php>
|
</php>
|
||||||
|
|||||||
@@ -66,6 +66,16 @@ class WorkflowTestCase extends TestCase
|
|||||||
chdir($pwd);
|
chdir($pwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean the shared folder to only have the sites.
|
||||||
|
*/
|
||||||
|
protected function cleanShared()
|
||||||
|
{
|
||||||
|
$this->rrmdir(PATH_DATA.'skins');
|
||||||
|
mkdir(PATH_DATA.'skins');
|
||||||
|
clearstatcache();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the text of and specific translated message.
|
* Set the text of and specific translated message.
|
||||||
*
|
*
|
||||||
@@ -91,4 +101,17 @@ class WorkflowTestCase extends TestCase
|
|||||||
unset($translation[$msgId]);
|
unset($translation[$msgId]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function rrmdir($dir)
|
||||||
|
{
|
||||||
|
if (!is_dir($dir)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$files = array_diff(scandir($dir), array('.', '..'));
|
||||||
|
foreach ($files as $file) {
|
||||||
|
(is_dir("$dir/$file") && !is_link($dir)) ? $this->rrmdir("$dir/$file")
|
||||||
|
: unlink("$dir/$file");
|
||||||
|
}
|
||||||
|
return rmdir($dir);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ define('PATH_DATA', realpath($GLOBALS['PATH_DATA']).'/');
|
|||||||
define('PATH_C', PATH_TRUNK.'tmp/');
|
define('PATH_C', PATH_TRUNK.'tmp/');
|
||||||
define('PATH_SMARTY_C', PATH_TRUNK.'tmp/');
|
define('PATH_SMARTY_C', PATH_TRUNK.'tmp/');
|
||||||
define('PATH_SMARTY_CACHE', PATH_TRUNK.'tmp/');
|
define('PATH_SMARTY_CACHE', PATH_TRUNK.'tmp/');
|
||||||
|
|
||||||
define('PATH_DATA_SITE', PATH_DATA.'sites/'.SYS_SYS.'/');
|
define('PATH_DATA_SITE', PATH_DATA.'sites/'.SYS_SYS.'/');
|
||||||
define('PATH_DOCUMENT', PATH_DATA_SITE.'files/');
|
define('PATH_DOCUMENT', PATH_DATA_SITE.'files/');
|
||||||
define('PATH_DATA_MAILTEMPLATES', PATH_DATA_SITE.'mailTemplates/');
|
define('PATH_DATA_MAILTEMPLATES', PATH_DATA_SITE.'mailTemplates/');
|
||||||
@@ -43,6 +42,7 @@ define('PATH_DYNAFORM', PATH_DATA_SITE.'xmlForms/');
|
|||||||
define('PATH_IMAGES_ENVIRONMENT_FILES', PATH_DATA_SITE.'usersFiles'.PATH_SEP);
|
define('PATH_IMAGES_ENVIRONMENT_FILES', PATH_DATA_SITE.'usersFiles'.PATH_SEP);
|
||||||
define('PATH_IMAGES_ENVIRONMENT_USERS',
|
define('PATH_IMAGES_ENVIRONMENT_USERS',
|
||||||
PATH_DATA_SITE.'usersPhotographies'.PATH_SEP);
|
PATH_DATA_SITE.'usersPhotographies'.PATH_SEP);
|
||||||
|
define( 'PATH_CUSTOM_SKINS', PATH_DATA . 'skins' . PATH_SEP );
|
||||||
|
|
||||||
|
|
||||||
//require PATH_HOME . 'engine' . PATH_SEP . 'config' . PATH_SEP . 'paths.php';
|
//require PATH_HOME . 'engine' . PATH_SEP . 'config' . PATH_SEP . 'paths.php';
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ProcessMaker\BusinessModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skins Tests
|
||||||
|
*/
|
||||||
|
class SkinsTest extends \WorkflowTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Skins
|
||||||
|
*/
|
||||||
|
protected $object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up the unit test.
|
||||||
|
*/
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
$this->cleanShared();
|
||||||
|
$this->setupDB();
|
||||||
|
$this->object = new Skins;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tears down the unit test.
|
||||||
|
*/
|
||||||
|
protected function tearDown()
|
||||||
|
{
|
||||||
|
$this->cleanShared();
|
||||||
|
$this->dropDB();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get default skins and one custom global skin.
|
||||||
|
*
|
||||||
|
* @covers ProcessMaker\BusinessModel\Skins::getSkins
|
||||||
|
* @covers ProcessMaker\BusinessModel\Skins::createSkin
|
||||||
|
* @category HOR-3208:1
|
||||||
|
*/
|
||||||
|
public function testGetSkins()
|
||||||
|
{
|
||||||
|
$skins = $this->object->getSkins();
|
||||||
|
$this->assertCount(2, $skins);
|
||||||
|
$this->assertEquals($skins[0]['SKIN_FOLDER_ID'], 'classic');
|
||||||
|
$this->assertEquals($skins[1]['SKIN_FOLDER_ID'], 'neoclassic');
|
||||||
|
$this->object->createSkin('test', 'test');
|
||||||
|
$skins2 = $this->object->getSkins();
|
||||||
|
$this->assertCount(3, $skins2);
|
||||||
|
$this->assertEquals($skins2[2]['SKIN_FOLDER_ID'], 'test');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get default skins, one custom global and one custom current workspace skin.
|
||||||
|
*
|
||||||
|
* @covers ProcessMaker\BusinessModel\Skins::getSkins
|
||||||
|
* @covers ProcessMaker\BusinessModel\Skins::createSkin
|
||||||
|
* @category HOR-3208:2
|
||||||
|
*/
|
||||||
|
public function testGetSkinsCurrentWorkspace()
|
||||||
|
{
|
||||||
|
$this->object->createSkin('test', 'test');
|
||||||
|
$this->object->createSkin(
|
||||||
|
'test2',
|
||||||
|
'test2',
|
||||||
|
'Second skin',
|
||||||
|
'ProcessMaker Team',
|
||||||
|
'current',
|
||||||
|
'neoclassic'
|
||||||
|
);
|
||||||
|
$skins = $this->object->getSkins();
|
||||||
|
$this->assertCount(4, $skins);
|
||||||
|
$this->assertEquals($skins[2]['SKIN_FOLDER_ID'], 'test');
|
||||||
|
$this->assertEquals($skins[3]['SKIN_FOLDER_ID'], 'test2');
|
||||||
|
$this->assertEquals($skins[3]['SKIN_WORKSPACE'], SYS_SYS);
|
||||||
|
}
|
||||||
|
}
|
||||||
181
workflow/engine/src/ProcessMaker/BusinessModel/Skins.php
Normal file
181
workflow/engine/src/ProcessMaker/BusinessModel/Skins.php
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
<?php
|
||||||
|
namespace ProcessMaker\BusinessModel;
|
||||||
|
|
||||||
|
use System;
|
||||||
|
use Exception;
|
||||||
|
use G;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skins business model
|
||||||
|
*/
|
||||||
|
class Skins
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get a list of skins.
|
||||||
|
*
|
||||||
|
* @category HOR-3208,PROD-181
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getSkins()
|
||||||
|
{
|
||||||
|
$list = System::getSkingList();
|
||||||
|
return $list['skins'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new skin.
|
||||||
|
*
|
||||||
|
* @param string $skinName
|
||||||
|
* @param string $skinFolder
|
||||||
|
* @param string $skinDescription
|
||||||
|
* @param string $skinAuthor
|
||||||
|
* @param string $skinWorkspace
|
||||||
|
* @param string $skinBase
|
||||||
|
* @return array
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function createSkin(
|
||||||
|
$skinName,
|
||||||
|
$skinFolder,
|
||||||
|
$skinDescription = '',
|
||||||
|
$skinAuthor = 'ProcessMaker Team',
|
||||||
|
$skinWorkspace = 'global',
|
||||||
|
$skinBase = 'neoclassic'
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
if (!(isset($skinName))) {
|
||||||
|
throw (new Exception(G::LoadTranslation('ID_SKIN_NAME_REQUIRED')));
|
||||||
|
}
|
||||||
|
if (!(isset($skinFolder))) {
|
||||||
|
throw (new Exception(G::LoadTranslation('ID_SKIN_FOLDER_REQUIRED')));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_dir(PATH_CUSTOM_SKINS.$skinFolder)) {
|
||||||
|
throw (new Exception(G::LoadTranslation('ID_SKIN_ALREADY_EXISTS')));
|
||||||
|
}
|
||||||
|
if (strtolower($skinFolder) == 'classic') {
|
||||||
|
throw (new Exception(G::LoadTranslation('ID_SKIN_ALREADY_EXISTS')));
|
||||||
|
}
|
||||||
|
|
||||||
|
//All validations OK then create skin
|
||||||
|
switch ($skinBase) {
|
||||||
|
//Validate skin base
|
||||||
|
case 'uxmodern':
|
||||||
|
$this->copySkinFolder(G::ExpandPath("skinEngine").'uxmodern'.PATH_SEP,
|
||||||
|
PATH_CUSTOM_SKINS.$skinFolder,
|
||||||
|
array("config.xml"
|
||||||
|
));
|
||||||
|
$pathBase = G::ExpandPath("skinEngine").'base'.PATH_SEP;
|
||||||
|
break;
|
||||||
|
case 'classic':
|
||||||
|
//Special Copy of this dir + xmlreplace
|
||||||
|
$this->copySkinFolder(G::ExpandPath("skinEngine").'base'.PATH_SEP,
|
||||||
|
PATH_CUSTOM_SKINS.$skinFolder,
|
||||||
|
array("config.xml", "baseCss"
|
||||||
|
));
|
||||||
|
$pathBase = G::ExpandPath("skinEngine").'base'.PATH_SEP;
|
||||||
|
break;
|
||||||
|
case 'neoclassic':
|
||||||
|
//Special Copy of this dir + xmlreplace
|
||||||
|
$this->copySkinFolder(G::ExpandPath("skinEngine").'neoclassic'.PATH_SEP,
|
||||||
|
PATH_CUSTOM_SKINS.$skinFolder,
|
||||||
|
array("config.xml", "baseCss"
|
||||||
|
));
|
||||||
|
$pathBase = G::ExpandPath("skinEngine").'neoclassic'.PATH_SEP;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//Commmon copy/paste of a folder + xmlrepalce
|
||||||
|
$this->copySkinFolder(PATH_CUSTOM_SKINS.$skinBase,
|
||||||
|
PATH_CUSTOM_SKINS.$skinFolder,
|
||||||
|
array("config.xml"
|
||||||
|
));
|
||||||
|
$pathBase = PATH_CUSTOM_SKINS.$skinBase.PATH_SEP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//@todo Improve this pre_replace lines
|
||||||
|
$configFileOriginal = $pathBase."config.xml";
|
||||||
|
$configFileFinal = PATH_CUSTOM_SKINS.$skinFolder.PATH_SEP.'config.xml';
|
||||||
|
|
||||||
|
$xmlConfiguration = file_get_contents($configFileOriginal);
|
||||||
|
|
||||||
|
$workspace = ($skinWorkspace == 'global') ? '' : SYS_SYS;
|
||||||
|
|
||||||
|
$xmlConfigurationObj = G::xmlParser($xmlConfiguration);
|
||||||
|
$skinInformationArray = $xmlConfigurationObj->result["skinConfiguration"]["__CONTENT__"]["information"]["__CONTENT__"];
|
||||||
|
|
||||||
|
$xmlConfiguration = preg_replace('/(<id>)(.+?)(<\/id>)/i',
|
||||||
|
'<id>'.G::generateUniqueID().'</id><!-- $2 -->',
|
||||||
|
$xmlConfiguration);
|
||||||
|
|
||||||
|
if (isset($skinInformationArray["workspace"]["__VALUE__"])) {
|
||||||
|
$workspace = ($workspace != "" && !empty($skinInformationArray["workspace"]["__VALUE__"]))
|
||||||
|
? $skinInformationArray["workspace"]["__VALUE__"]."|".$workspace
|
||||||
|
: $workspace;
|
||||||
|
|
||||||
|
$xmlConfiguration = preg_replace("/(<workspace>)(.*)(<\/workspace>)/i",
|
||||||
|
"<workspace>".$workspace."</workspace><!-- $2 -->",
|
||||||
|
$xmlConfiguration);
|
||||||
|
$xmlConfiguration = preg_replace("/(<name>)(.*)(<\/name>)/i",
|
||||||
|
"<name>".$skinName."</name><!-- $2 -->",
|
||||||
|
$xmlConfiguration);
|
||||||
|
} else {
|
||||||
|
$xmlConfiguration = preg_replace("/(<name>)(.*)(<\/name>)/i",
|
||||||
|
"<name>".$skinName."</name><!-- $2 -->\n<workspace>".$workspace."</workspace>",
|
||||||
|
$xmlConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
$xmlConfiguration = preg_replace("/(<description>)(.+?)(<\/description>)/i",
|
||||||
|
"<description>".$skinDescription."</description><!-- $2 -->",
|
||||||
|
$xmlConfiguration);
|
||||||
|
$xmlConfiguration = preg_replace("/(<author>)(.+?)(<\/author>)/i",
|
||||||
|
"<author>".$skinAuthor."</author><!-- $2 -->",
|
||||||
|
$xmlConfiguration);
|
||||||
|
$xmlConfiguration = preg_replace("/(<createDate>)(.+?)(<\/createDate>)/i",
|
||||||
|
"<createDate>".date("Y-m-d H:i:s")."</createDate><!-- $2 -->",
|
||||||
|
$xmlConfiguration);
|
||||||
|
$xmlConfiguration = preg_replace("/(<modifiedDate>)(.+?)(<\/modifiedDate>)/i",
|
||||||
|
"<modifiedDate>".date("Y-m-d H:i:s")."</modifiedDate><!-- $2 -->",
|
||||||
|
$xmlConfiguration);
|
||||||
|
|
||||||
|
file_put_contents($configFileFinal, $xmlConfiguration);
|
||||||
|
$response['success'] = true;
|
||||||
|
$response['message'] = G::LoadTranslation('ID_SKIN_SUCCESS_CREATE');
|
||||||
|
G::auditLog("CreateSkin", "Skin Name: ".$skinName);
|
||||||
|
return $response;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$response['success'] = false;
|
||||||
|
$response['message'] = $e->getMessage();
|
||||||
|
$response['error'] = $e->getMessage();
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function copySkinFolder($path, $dest, $exclude = array())
|
||||||
|
{
|
||||||
|
$defaultExcluded = array(".", "..");
|
||||||
|
$excludedItems = array_merge($defaultExcluded, $exclude);
|
||||||
|
if (is_dir($path)) {
|
||||||
|
mkdir($dest);
|
||||||
|
$objects = scandir($path);
|
||||||
|
if (sizeof($objects) > 0) {
|
||||||
|
foreach ($objects as $file) {
|
||||||
|
if (in_array($file, $excludedItems)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (is_dir($path.PATH_SEP.$file)) {
|
||||||
|
$this->copySkinFolder($path.PATH_SEP.$file,
|
||||||
|
$dest.PATH_SEP.$file, $exclude);
|
||||||
|
} else {
|
||||||
|
copy($path.PATH_SEP.$file, $dest.PATH_SEP.$file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} elseif (is_file($path)) {
|
||||||
|
return copy($path, $dest);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -102,4 +102,25 @@ class System extends Api
|
|||||||
throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage()));
|
throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of installed skins.
|
||||||
|
*
|
||||||
|
* @url GET /skins
|
||||||
|
* @return array
|
||||||
|
* @access protected
|
||||||
|
* @class AccessControl {@permission PM_FACTORY}
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
public function doGetSkins()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$model = new \ProcessMaker\BusinessModel\Skins();
|
||||||
|
$response = $model->getSkins();
|
||||||
|
return ["data" => $response];
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user