From ea64e78868cb679d9e832ec82a6decfe7b0f5292 Mon Sep 17 00:00:00 2001 From: Taras Machyshyn Date: Wed, 6 Nov 2013 12:57:49 +0200 Subject: [PATCH 1/2] controller for routes --- api/index.php | 203 +++++++------ application/Espo/Core/systemConfig.php | 18 +- application/Espo/Utils/Api/Helper.php | 13 +- application/Espo/Utils/Api/Rest.php | 57 ++-- application/Espo/Utils/BaseUtils.php | 178 +++++++++++- .../Espo/Utils/Controllers/Controller.php | 40 +++ application/Espo/Utils/Controllers/Layout.php | 47 +++ .../Espo/Utils/Controllers/Manager.php | 269 ++++++++++++++++++ application/Espo/Utils/FileManager.php | 43 +-- application/Espo/Utils/Layout.php | 4 + application/Espo/Utils/Metadata.php | 1 + tests/Espo/Utils/BaseUtilsTest.php | 18 ++ tests/Espo/Utils/JSONTest.php | 6 +- tests/api/LayoutTest.php | 4 +- tests/api/MetadataTest.php | 4 +- tests/api/RestTesterClass.php | 2 +- tests/api/SettingsTest.php | 2 +- 17 files changed, 733 insertions(+), 176 deletions(-) create mode 100644 application/Espo/Utils/Controllers/Controller.php create mode 100644 application/Espo/Utils/Controllers/Layout.php create mode 100644 application/Espo/Utils/Controllers/Manager.php diff --git a/api/index.php b/api/index.php index d267fd4234..95a3ae886b 100755 --- a/api/index.php +++ b/api/index.php @@ -3,10 +3,13 @@ require_once('../bootstrap.php'); use \Espo\Utils\Api as Api, + \Espo\Utils as Utils, \Slim; +/* START: remove for composer */ require 'vendor/Slim/Slim.php'; \Slim\Slim::registerAutoloader(); +/* END: remove for composer */ //$app = new \Slim\Slim(); @@ -15,10 +18,68 @@ $app = new \Slim\Slim(array( )); $app->add(new Api\Auth()); +//convert all url params to camel case format +$app->hook('slim.before.dispatch', function () use ($app) { + $routeParams= $app->router()->getCurrentRoute()->getParams(); + + if (!empty($routeParams)) { + $baseUtils= new Utils\BaseUtils(); + foreach($routeParams as &$param) { + $param= $baseUtils->toCamelCase($param); + } + + $app->router()->getCurrentRoute()->setParams($routeParams); + } +}); +//END: convert all url params to camel case format + + +$app->hook('slim.before.dispatch', function () use ($app) { + + $currentRoute = $app->router()->getCurrentRoute(); + $conditions = $currentRoute->getConditions(); + + if (isset($conditions['useController']) && !$conditions['useController']) { + return; + } + + $espoController = call_user_func( $app->router()->getCurrentRoute()->getCallable() ); + $espoKeys = array_keys($espoController); + + if (!in_array('controller', $espoKeys) || !in_array('action', $espoKeys) || !in_array('scope', $espoKeys)) { + return; + } + + $ControllerManager = new Utils\Controllers\Manager(); + + $params = $currentRoute->getParams(); + $data = $app->request()->getBody(); + + //prepare controller Params + $controllerParams = array(); + $controllerParams['HttpMethod'] = strtolower($app->request()->getMethod()); + + foreach($espoController as $key => $val) { + if (strstr($val, ':')) { + $paramName = str_replace(':', '', $val); + $val = $params[$paramName]; + } + $controllerParams[$key] = $val; + } + //END: prepare controller Params + + $result = $ControllerManager->call($controllerParams, $params, $data); + + return Api\Helper::output($result->data, $result->errMessage, $result->errCode); +}); + + +//return json response $app->hook('slim.after.router', function () use (&$app) { $app->contentType('application/json'); //$app->contentType('text/javascript'); }); +//END: return json response //Setup routes @@ -31,100 +92,82 @@ $app->get('/settings/', '\Espo\Utils\Api\Rest::getSettings')->conditions( array( $app->map('/settings/', '\Espo\Utils\Api\Rest::patchSettings')->via('PATCH'); //$app->get('/settings/', '\Espo\Utils\Api\Rest::getSettings')->conditions( array('auth' => false) ); -$app->get('/:controller/layout/:name/', '\Espo\Utils\Api\Rest::getLayout'); -$app->map('/:controller/layout/:name/', '\Espo\Utils\Api\Rest::patchLayout')->via('PATCH'); -$app->put('/:controller/layout/:name/', '\Espo\Utils\Api\Rest::putLayout'); +//$app->get('/:controller/layout/:name/', '\Espo\Utils\Api\Rest::getLayout'); +//$app->put('/:controller/layout/:name/', '\Espo\Utils\Api\Rest::putLayout'); +//$app->map('/:controller/layout/:name/', '\Espo\Utils\Api\Rest::patchLayout')->via('PATCH'); $app->get('/app/user/', '\Espo\Utils\Api\Rest::getAppUser'); -/*$app->put('/settings/', 'Rest::putSettings'); +/*$app->get('/:controller/:id', function() { + return array( + 'controller' => ':controller', + 'action' => 'read', + 'id' => ':id' + ); +})->conditions( array('useController' => true) ); -//$app->map('/hello/', 'Rest::putSettings')->via('PATCH'); +$app->post('/:controller', function() { + return array( + 'controller' => ':controller', + 'action' => 'create', + ); +})->conditions( array('useController' => true) ); -$app->get('/app/user/', 'Rest::getUserPreferences'); -$app->map('/app/:action', 'Rest::appAction')->via('GET', 'POST'); +$app->put('/:controller/:id', function() { + return array( + 'controller' => ':controller', + 'action' => 'update', + 'id' => ':id' + ); +})->conditions( array('useController' => true) ); -$app->get('/metadata/:type/:scope/', 'Rest::getMetadata'); -$app->put('/metadata/:type/:scope/', 'Rest::putMetadata'); -$app->get('/metadata/:type/', 'Rest::getMetadataByType'); - -$app->get('/:controller/', 'Rest::getControllerList'); -$app->get('/:controller/:id/', 'Rest::getController'); - -$app->get('/:controller/layout/:type/', 'Rest::getLayout'); - -*/ +$app->patch('/:controller/:id', function() { + return array( + 'controller' => ':controller', + 'action' => 'patch', + 'id' => ':id' + ); +})->conditions( array('useController' => true) ); -//$app->put('/:controller/layout/:type/', 'Rest::putLayout'); -//$app->map('/:controller/layout/:type/', 'Rest::patchLayout')->via('PATCH'); +$app->get('/:controller/:id/:link/:foreignId', function() { + return array( + 'controller' => ':controller', + 'action' => 'readRelated', + 'id' => ':id', + 'link' => ':link', + 'foreignId' => ':foreignId' + ); +})->conditions( array('useController' => true) ); */ -//$app->put('/:controller/layout/:type/', 'Rest::putLayout'); +//Layout +$app->get('/:controller/layout/:name/', function() { + return array( + 'controller' => 'Layout', + 'scope' => ':controller', + 'action' => ':name', + ); +})->conditions( array('useController' => true) ); +$app->put('/:controller/layout/:name/', function() { + return array( + 'controller' => 'Layout', + 'scope' => ':controller', + 'action' => ':name', + ); +})->conditions( array('useController' => true) ); -/*$app->put( '/:controller/layout/:type/', function ($controller, $type) use ( $app ) { +$app->map('/:controller/layout/:name/', function() { + return array( + 'controller' => 'Layout', + 'scope' => ':controller', + 'action' => ':name', + ); +})->via('PATCH')->conditions( array('useController' => true) ); +//END: Layout - - $mysqli = new mysqli('localhost', 'root', '', 'projects_jet'); - - $query= "SELECT * FROM layouts - WHERE controller='".$controller."' AND layout_type='".$type."' LIMIT 1"; - $result = $mysqli->query($query); - $selectRow = $result->fetch_assoc(); - - $data = $app->request()->getBody(); - //$data = $app->request()->params('payload'); - //$dataFull = array_keys($dataPut); - //$data= $dataFull[0]; - - - if (empty($selectRow)) { - //insert - $query= "INSERT INTO layouts ( - controller, - layout_type, - data - ) - VALUES ( - '".$controller."', - '".$type."', - '".$data."' - );"; - } - else { - $query= "UPDATE layouts SET data='".$data."' - WHERE id='".$selectRow['id']."' "; - //update - } - - $result = $mysqli->query($query); - - echo $data; -}); */ - -/*$app->map('/app/:action', 'appAction')->via('GET', 'POST'); -$app->get('/:controller/', 'getControllerList'); -$app->get('/:controller/:id/', 'getController');*/ - -/* -// POST route -$app->post('/post', function () { - echo 'This is a POST route'; -}); - -// PUT route -$app->put('/put', function () { - echo 'This is a PUT route'; -}); - -// DELETE route -$app->delete('/delete', function () { - echo 'This is a DELETE route'; -}); -*/ - $app->run(); ?> \ No newline at end of file diff --git a/application/Espo/Core/systemConfig.php b/application/Espo/Core/systemConfig.php index 1053b8a0d0..226b6b109c 100755 --- a/application/Espo/Core/systemConfig.php +++ b/application/Espo/Core/systemConfig.php @@ -2,11 +2,18 @@ return array ( 'configPath' => 'application/config.php', - 'customPath' => 'application/Custom', + + 'customDir' => 'application/Custom', 'cachePath' => 'data/cache', 'defaultsPath' => 'application/Espo/Core/defaults', 'unsetFileName' => 'unset.json', + 'espoPath' => 'Espo', + 'espoModulePath' => 'Modules/{*}', + 'espoCustomPath' => 'Custom', + + 'controllerPath' => 'Controllers', //path for controllers in module + 'metadataConfig' => array ( 'name' => 'metadata', @@ -40,6 +47,14 @@ return array ( ), 'dateFormat' => 'MM/DD/YYYY', 'timeFormat' => 'HH:mm', + + 'crud' => array( + 'get' => 'read', + 'post' => 'create', + 'put' => 'update', + 'patch' => 'patch', + 'delete' => 'delete', + ), 'systemItems' => array ( 'systemItems', @@ -55,6 +70,7 @@ return array ( 'unsetFileName', 'configPathFull', 'configCustomPathFull', + 'crud', ), 'adminItems' => array ( diff --git a/application/Espo/Utils/Api/Helper.php b/application/Espo/Utils/Api/Helper.php index 7a988f34c9..956e64d972 100755 --- a/application/Espo/Utils/Api/Helper.php +++ b/application/Espo/Utils/Api/Helper.php @@ -13,22 +13,21 @@ class Helper * Output the result * * @param mixed $data - JSON - * @param string $error - error message - * @param int $errorCode - error status code + * @param string $errMessage - error message + * @param int $errCode - error status code * * @return void - Only echo the result */ - function output($data=null, $error='Error', $errorCode=500) + function output($data=null, $errMessage='Error', $errCode=500) { $app= Slim::getInstance(); //check if result is false if ($data === false) { global $base; - $logMess= empty($error) ? 'result is not expected' : $error; - $base->log->add('ERROR', 'API:'.$app->router()->getCurrentRoute()->getPattern().', Method: '.$app->router()->getCurrentRoute()->getCallable().', InputData: '.$app->request()->getBody().' - '.$logMess); - - Utils\Api\Helper::displayError($error, $errorCode); + $logMess= empty($errMessage) ? 'result is not expected' : $errMessage; + $base->log->add('ERROR', 'API ['.$app->request()->getMethod().']:'.$app->router()->getCurrentRoute()->getPattern().', Params:'.print_r($app->router()->getCurrentRoute()->getParams(), true).', InputData: '.$app->request()->getBody().' - '.$logMess); + Utils\Api\Helper::displayError($errMessage, $errCode); } //END: check if result is false diff --git a/application/Espo/Utils/Api/Rest.php b/application/Espo/Utils/Api/Rest.php index 9f14da3549..cf7c5aacf0 100755 --- a/application/Espo/Utils/Api/Rest.php +++ b/application/Espo/Utils/Api/Rest.php @@ -56,8 +56,7 @@ EOT; $app= Slim::getInstance(); $data = $app->request()->getBody(); - $metadata = new Utils\Metadata(); - $type = $metadata->toCamelCase($type); //convert to camel case view + $metadata = new Utils\Metadata(); $result = $metadata->setMetadata($data, $type, $scope); if ($result===false) { @@ -123,17 +122,29 @@ EOT; * * @return void */ + /*public function getLayout($controller, $name) + { + $ControllerManager = new Utils\Controllers\Manager(); + + $params = array('controller' => $controller, 'action' => $name); + $action= 'getLayout'; + $result = $ControllerManager->call($action, $params, $data); + + return Api\Helper::output($result->data, $result->errMessage, $result->errCode); + + //$layout = new Utils\Layout(); + //$data = $layout->getLayout($controller, $name); + + //return Api\Helper::output($data, 'Cannot get this layout', 404); + } */ + + public function getLayout($controller, $name) { - $layout = new Utils\Layout(); - - $controller = $layout->toCamelCase($controller); - $name = $layout->toCamelCase($name); - $data = $layout->getLayout($controller, $name); - - return Api\Helper::output($data, 'Cannot get this layout', 404); + return Api\Helper::output('Rest-get', 'Cannot get layout'); } + /** * Add or change layout * @@ -141,19 +152,7 @@ EOT; */ public function patchLayout($controller, $name) { - $app= Slim::getInstance(); - $data = $app->request()->getBody(); - - $layout= new Utils\Layout(); - $controller = $layout->toCamelCase($controller); - $name = $layout->toCamelCase($name); - $result= $layout->mergeLayout($data, $controller, $name); - - if ($result === false) { - Api\Helper::displayError('Saving error', 500); - } - - return Api\Helper::output($data, 'Cannot get layout'); + return Api\Helper::output('Rest-patch', 'Cannot get layout'); } @@ -164,19 +163,7 @@ EOT; */ public function putLayout($controller, $name) { - $app= Slim::getInstance(); - $data = $app->request()->getBody(); - - $layout= new Utils\Layout(); - $controller = $layout->toCamelCase($controller); - $name = $layout->toCamelCase($name); - $result= $layout->setLayout($data, $controller, $name); - - if ($result === false) { - Api\Helper::displayError('Saving error', 500); - } - - return Api\Helper::output($data, 'Cannot get layout'); + return Api\Helper::output('Rest-put', 'Cannot get layout'); } diff --git a/application/Espo/Utils/BaseUtils.php b/application/Espo/Utils/BaseUtils.php index a94521f1ce..010e7ad8de 100755 --- a/application/Espo/Utils/BaseUtils.php +++ b/application/Espo/Utils/BaseUtils.php @@ -6,6 +6,27 @@ use Espo\Utils as Utils; class BaseUtils { + /** + * @var string - default directory separator + */ + protected $separator= DIRECTORY_SEPARATOR; + + /** + * @var array - scope list + */ + protected $scopes= array(); + + + /** + * Get a folder separator + * + * @return string + */ + public function getSeparator() + { + return $this->separator; + } + function getObject($name) { @@ -25,15 +46,15 @@ class BaseUtils /** * Get module name if it's a custom module or empty string for core entity * - * @param string $entityName + * @param string $scopeName * * @return string */ - public function getScopeModuleName($entityName) + public function getScopeModuleName($scopeName) { - $scopeModuleMap= (array) $this->getObject('Configurator')->get('scopeModuleMap'); + $scopeModuleMap= $this->getScopes(); - $lowerEntityName= strtolower($entityName); + $lowerEntityName= strtolower($scopeName); foreach($scopeModuleMap as $rowEntityName => $rowModuleName) { if ($lowerEntityName==strtolower($rowEntityName)) { return $rowModuleName; @@ -43,6 +64,132 @@ class BaseUtils return ''; } + + /** + * Get Scopes + * + * @param string $moduleName + * @param bool $reload + * + * @return array + */ + //NEED TO CHANGE + public function getScopes($moduleName= '', $reload = false) + { + if (!$reload && !empty($this->scopes)) { + return $this->scopes; + } + + + $this->scopes = array( + 'customTest' => '', + 'Attachment' => '', + 'Comment' => '', + 'Attachment' => '', + 'EmailTemplate' => '', + 'Role' => '', + 'Team' => '', + 'User' => '', + 'Product' => 'Crm', + 'Account' => 'Crm', + 'Contact' => 'Crm', + 'Lead' => 'Crm', + 'Opportunity' => 'Crm', + 'Calendar' => 'Crm', + 'Meeting' => 'Crm', + 'Call' => 'Crm', + 'Task' => 'Crm', + 'Case' => 'Crm', + 'Prospect' => 'Crm', + 'Email' => 'Crm', + 'emailTemplate' => 'Crm', + 'inboundEmail' => 'Crm', + ); + + return $this->scopes; + } + + + /** + * Get Scope path, ex. "Modules/Crm" for Account + * + * @param string $scopeName + * @param string $delim - delimiter + * + * @return string + */ + public function getScopePath($scopeName, $delim= '/') + { + $moduleName= $this->getScopeModuleName($scopeName); + + $config = new Utils\Configurator(); + $path= $config->get('espoPath'); + if (!empty($moduleName)) { + $path= str_replace('{*}', $moduleName, $config->get('espoModulePath')); + } + + if ($delim!='/') { + $path = str_replace('/', $delim, $path); + } + + return $path; + } + + + /** + * Get Full Scope path, ex. "application/Modules/Crm" for Account + * + * @param string $scopeName + * @param string $delim - delimiter + * + * @return string + */ + public function getScopePathFull($scopeName, $delim= '/') + { + return $this->concatPath('application', $this->getScopePath($scopeName, $delim)); + } + + /** + * Check if scope exists + * + * @param string $scopeName + * + * @return bool + */ + public function isScopeExists($scopeName) + { + $scopeModuleMap= $this->getScopes(); + + $lowerEntityName= strtolower($scopeName); + foreach($scopeModuleMap as $rowEntityName => $rowModuleName) { + if ($lowerEntityName==strtolower($rowEntityName)) { + return true; + } + } + + return false; + } + + + /** + * Convert to format with defined delimeter + * ex. Espo/Utils to Espo\Utils + * + * @param string $name + * @param string $delim - delimiter + * + * @return string + */ + public function toFormat($name, $delim= '/') + { + //preg_match_all('/[\/]/', $name, $match); + //preg_match_all('/(.*)[\/\\\](.*)/', $name, $match); + //return $match; + + return preg_replace('/[\/\\\]/', $delim, $name); + } + + /** * Convert name to Camel Case format * ex. camel-case to camelCase @@ -134,6 +281,29 @@ class BaseUtils return $array; } + + /** + * Get a full path of the file + * + * @param string $folderPath - Folder path, Ex. myfolder + * @param string $filePath - File path, Ex. file.json + * + * @return string + */ + public function concatPath($folderPath, $filePath='') + { + if (empty($filePath)) { + return $folderPath; + } + else { + if (substr($folderPath, -1)==$this->getSeparator()) { + return $folderPath . $filePath; + } + return $folderPath . $this->getSeparator() . $filePath; + } + } + + /** * Return content of PHP file * diff --git a/application/Espo/Utils/Controllers/Controller.php b/application/Espo/Utils/Controllers/Controller.php new file mode 100644 index 0000000000..75a5ee1eb9 --- /dev/null +++ b/application/Espo/Utils/Controllers/Controller.php @@ -0,0 +1,40 @@ + \ No newline at end of file diff --git a/application/Espo/Utils/Controllers/Layout.php b/application/Espo/Utils/Controllers/Layout.php new file mode 100644 index 0000000000..23e712c70b --- /dev/null +++ b/application/Espo/Utils/Controllers/Layout.php @@ -0,0 +1,47 @@ +getLayout($params['controller'], $params['name']); + + return array($data, 'Cannot get this layout', 404); + } + + + public function update($params, $data) + { + $layout= new Utils\Layout(); + $result= $layout->setLayout($data, $params['controller'], $params['name']); + + if ($result === false) { + return array(false, 'Layout Saving error', 500); + } + + return array($data, 'Cannot get this layout'); + } + + + public function patch($params, $data) + { + $layout= new Utils\Layout(); + $result= $layout->mergeLayout($data, $params['controller'], $params['name']); + + if ($result === false) { + return array(false, 'Layout Saving error', 500); + } + + return array($data, 'Cannot get this layout'); + } + +} + + +?> \ No newline at end of file diff --git a/application/Espo/Utils/Controllers/Manager.php b/application/Espo/Utils/Controllers/Manager.php new file mode 100644 index 0000000000..d90d01c317 --- /dev/null +++ b/application/Espo/Utils/Controllers/Manager.php @@ -0,0 +1,269 @@ + 'Layout', 'action' => ':name', 'scope' => ':controller'); + * @param array $params - route params, ex. /:controller/layout/:name/ - array(controller=>Value, name=>Value) + * @param array $data - request data + * + * @return array + */ + public function call($controllerParams, $params, $data = '') + { + $baseUtils = new Utils\BaseUtils(); + + $espoPath = $baseUtils->getObject('Configurator')->get('espoPath'); + $controllerPath= $baseUtils->concatPath($espoPath, 'Utils/Controllers'); + + $crud = $baseUtils->getObject('Configurator')->get('crud'); + $baseAction = $crud->$controllerParams['HttpMethod']; + if (empty($baseAction)) { + return $this->response(false, 'Cannot find action for HTTP Method ['.$controllerParams['HttpMethod'].']', 404); + } + + $controller = (object) array( + 'name' => strtolower($controllerParams['controller']), + 'baseAction' => $baseAction, + 'scope' => $controllerParams['scope'], + 'action' => $controllerParams['action'], + ); + + + if (!$baseUtils->isScopeExists($controller->scope)) { + return $this->response(false, 'Controller for Scope ['.$controller->scope.'] does not exist.', 404); + } + + //define default values + $classInfo = new \stdClass(); + $classInfo->name = $this->getClassName($controllerPath, 'Controller'); + $classInfo->path = $this->getClassPath($classInfo->name); + $classInfo->method = $this->getDefinedMethod($classInfo->name, $controller->baseAction, $controller->action); + + + //Espo\Utils\Controlles\Layout and Custom\Espo\Utils\Controlles\Layout + $controllerClass = $this->getClassName($controllerPath, $controller->name); + $classInfo = $this->setClassInfo($controllerClass, $classInfo, $controller); + //END: Espo\Utils\Controlles\Layout and Custom\Espo\Utils\Controlles\Layout + + + //path in Modules dir + $controllerDir = $baseUtils->concatPath( $baseUtils->getScopePath($controller->scope), $baseUtils->getObject('Configurator')->get('controllerPath') ); + + //ex. Modules\Crm\Controllers\Layout and Cusom\Modules\Crm\Controllers\Layout + $controllerClass = $this->getClassName($controllerDir, $controller->name); + $classInfo = $this->setClassInfo($controllerClass, $classInfo, $controller); + //END: ex. Modules\Crm\controllers\Layout and Cusom\Modules\Crm\controllers\Layout + + + //ex. Modules\Crm\Controllers\AccountLayout and Custom\Modules\Crm\Controllers\AccountLayout + $controllerClass = $this->getClassName($controllerDir, $controller->scope.'-'.$controller->name); + $classInfo = $this->setClassInfo($controllerClass, $classInfo, $controller); + //END: ex. Modules\Crm\Controllers\AccountLayout and Custom\Modules\Crm\Controllers\AccountLayout + + + //CHECK ACTION + if (empty($classInfo->method)) { + return $this->response(false, 'Actions ['.$controller->baseAction.'] and ['.$controller->action.'] do not exist.', 404); + } + //END: CHECK ACTION + + + //call class method + $className = $classInfo->name; + $classMethod = $classInfo->method; + + require_once($classInfo->path); + $class = new $className(); + + //call before method if exists: beforeRead, beforeDetailSmall, beforeReadDetailSmall + $beforeMethod = $this->getDefinedMethod($className, $controller->baseAction, $controller->action, 'before'); + if ( !empty($beforeMethod) ) { + $class->$beforeMethod($params, $data); + } //END: call before method if exists + + $result = $class->$classMethod($params, $data); + + //call after method if exists: afterRead, afterDetailSmall, afterReadDetailSmall + $afterMethod = $this->getDefinedMethod($className, $controller->baseAction, $controller->action, 'after'); + if ( !empty($afterMethod) ) { + try { + $class->$afterMethod($params, $data, $result); + } catch (\Exception $e) { + $class->$afterMethod($params, $data); + } + } //END: call after method if exists + + + if (is_array($result)) { + + $returnResult = array_values($result); + if (!empty($returnResult[2])) { + return $this->response($returnResult[0], $returnResult[1], $returnResult[2]); + } + if (!empty($returnResult[1])) { + return $this->response($returnResult[0], $returnResult[1]); + } + if (!empty($returnResult[0])) { + return $this->response($returnResult[0]); + } + + return $this->response(false, 'Cannot find requested controller', 404); + } + + return $this->response($result); + } + + + + /** + * Check if methods exist in class and return the method name according to priority + * + * @param string $className + * + * @return sting + */ + function getDefinedMethod($className, $baseAction, $action, $prefix = '') + { + $allActions= get_class_methods($className); + $classMethod = ''; + + if (!empty($prefix)) { + $prefix .= '-'; + } + + $baseUtils = new Utils\BaseUtils(); + + //method as 'read' + $prefixBaseAction = $baseUtils->toCamelCase($prefix.$baseAction); + if ( method_exists($className, $prefixBaseAction) ) { + $classMethod = $prefixBaseAction; + } + + //method as 'detailSmall' + $prefixAction = $baseUtils->toCamelCase($prefix.$action); + if ( method_exists($className, $prefixAction) ) { + $classMethod = $prefixAction; + } + + //method as 'readDetailSmall' + $fullAction = $baseUtils->toCamelCase($prefix.$baseAction.'-'.$action); + if (method_exists($className, $fullAction)) { + $classMethod = $fullAction; + } + + return $classMethod; + } + + /** + * If method exists, then redefine classInfo + * + * @param string $className + * @param object $classInfo + * @param object $controller + * @param bool $isCustom - is need to check custom folder + * + * @return object + */ + protected function setClassInfo($className, \stdClass $classInfo, \stdClass $controller, $isCustom = true) + { + $classPath = $this->getClassPath($className); + $classMethod = $this->getDefinedMethod($className, $controller->baseAction, $controller->action); + + if (file_exists($classPath) && !empty($classMethod) ) { + $classInfo->name = $className; + $classInfo->path = $classPath; + $classInfo->method = $classMethod; + } + + if ($isCustom) { + $baseUtils = new Utils\BaseUtils(); + $espoCustomDir = $baseUtils->getObject('Configurator')->get('espoCustomPath'); + $controllerClass = $espoCustomDir.'\\'.$className; + $classInfo = $this->setClassInfo($controllerClass, $classInfo, $controller, false); + } + + return $classInfo; + } + + + + /** + * Get class name from path and name + * + * @param string $path + * @param string $name + * + * @return string + */ + protected function getClassName($path, $name = '') + { + $baseUtils = new Utils\BaseUtils(); + + if (!empty($name)) { + $path = $baseUtils->concatPath($path, $baseUtils->toCamelCase($name, true)); + } + + return $baseUtils->toFormat($path, '\\'); + } + + + /** + * Get full class path (inc. "application" and file extension) from path and name + * + * @param string $path + * @param string $name + * + * @return string + */ + protected function getClassPath($path, $name = '') + { + $baseUtils = new Utils\BaseUtils(); + + if (!empty($name)) { + $path = $baseUtils->concatPath($path, $baseUtils->toCamelCase($name, true)); + } + + return $baseUtils->concatPath('application', $baseUtils->toFormat($path, '/').'.php'); + } + + + /** + * Prepare response to output + * + * @param mixed $data + * @param string $errMessage + * @param int $errorCode + * + * @return object + */ + public function response($data=null, $errMessage='Error', $errorCode=404) + { + return (object) array( + 'data' => $data, + 'errMessage' => $errMessage, + 'errCode' => $errorCode, + ); + } + + + + +} + + +?> \ No newline at end of file diff --git a/application/Espo/Utils/FileManager.php b/application/Espo/Utils/FileManager.php index daf68b63d2..e215229e7d 100755 --- a/application/Espo/Utils/FileManager.php +++ b/application/Espo/Utils/FileManager.php @@ -7,11 +7,6 @@ use Espo\Utils as Utils; class FileManager extends BaseUtils { /** - * @var string - default directory separator - */ - protected $separator= DIRECTORY_SEPARATOR; - - /** * @var object - default permission settings */ protected $defaultPermissions; @@ -22,16 +17,6 @@ class FileManager extends BaseUtils protected $appCache= 'application'; - /** - * Get a folder separator - * - * @return string - */ - public function getSeparator() - { - return $this->separator; - } - /** * Get a list of files in specified directory * @@ -274,7 +259,7 @@ class FileManager extends BaseUtils return false; } $unsetFileName = $this->getObject('Configurator')->get('unsetFileName'); - $scopeModuleMap = $this->getObject('Configurator')->get('scopeModuleMap'); + //$scopeModuleMap = $this->getObject('Configurator')->get('scopeModuleMap'); //get matadata files $fileList = $this->getFileList($dirPath, $recursively, '\.json$'); @@ -335,7 +320,7 @@ class FileManager extends BaseUtils public function uniteFilesGetContent($folderPath, $fileName, $defaults) { $fileContent= $this->getContent($folderPath, $fileName); - $decoded= $this->getArrayData($fileContent); + $decoded= $this->getArrayData($fileContent); if (empty($decoded)) { $this->getObject('Log')->add('FATAL EXCEPTION', 'Syntax error or empty file - '.$this->concatPath($folderPath, $fileName)); @@ -525,29 +510,7 @@ class FileManager extends BaseUtils } return false; - } - - /** - * Get a full path of the file - * - * @param string $folderPath - Folder path, Ex. myfolder - * @param string $filePath - File path, Ex. file.json - * - * @return string - */ - public function concatPath($folderPath, $filePath='') - { - if (empty($filePath)) { - return $folderPath; - } - else { - if (substr($folderPath, -1)==$this->getSeparator()) { - return $folderPath . $filePath; - } - return $folderPath . $this->getSeparator() . $filePath; - } - } - + } /** * Get an array data (if JSON convert to array) diff --git a/application/Espo/Utils/Layout.php b/application/Espo/Utils/Layout.php index 81e2ca5da5..1f59498b14 100755 --- a/application/Espo/Utils/Layout.php +++ b/application/Espo/Utils/Layout.php @@ -77,6 +77,10 @@ class Layout extends FileManager */ function setLayout($data, $controller, $name) { + if (empty($controller) || empty($name)) { + return false; + } + $layoutPath = $this->getLayoutPath($controller); return $this->setContent($data, $layoutPath, $name.'.json'); diff --git a/application/Espo/Utils/Metadata.php b/application/Espo/Utils/Metadata.php index 919334385b..fee465f54f 100755 --- a/application/Espo/Utils/Metadata.php +++ b/application/Espo/Utils/Metadata.php @@ -70,6 +70,7 @@ class Metadata extends FileManager { $fullPath= $this->getConfig()->corePath; $moduleName= $this->getScopeModuleName($scope); + if (!empty($moduleName)) { $fullPath= str_replace('{*}', $moduleName, $this->getConfig()->customPath); } diff --git a/tests/Espo/Utils/BaseUtilsTest.php b/tests/Espo/Utils/BaseUtilsTest.php index 7f3d46739c..b57d87cf4f 100755 --- a/tests/Espo/Utils/BaseUtilsTest.php +++ b/tests/Espo/Utils/BaseUtilsTest.php @@ -126,6 +126,24 @@ class BaseUtilsTest extends \PHPUnit_Framework_TestCase } + function testGetScopePath() + { + $this->assertEquals('Modules/Crm', $this->fixture->getScopePath('Account', '/')); + $this->assertEquals('Modules\Crm', $this->fixture->getScopePath('Account', '\\')); + $this->assertEquals('Modules\Crm', $this->fixture->getScopePath('account', '\\')); + + $this->assertEquals('Espo', $this->fixture->getScopePath('User', '/')); + $this->assertEquals('Espo', $this->fixture->getScopePath('User', '\\')); + $this->assertEquals('Espo', $this->fixture->getScopePath('user', '\\')); + } + + + function testGetScopes() + { + $this->assertArrayHasKey('User', $this->fixture->getScopes() ); + } + + } diff --git a/tests/Espo/Utils/JSONTest.php b/tests/Espo/Utils/JSONTest.php index 3d369b556e..b62f815146 100755 --- a/tests/Espo/Utils/JSONTest.php +++ b/tests/Espo/Utils/JSONTest.php @@ -38,11 +38,11 @@ class JSONTest extends \PHPUnit_Framework_TestCase $test= '{"folder":"data\/logs"}'; $this->assertEquals('data/logs', $this->fixture->decode($test)->folder); - $test= '{"folder":"\\Entity\\Logs"}'; + $test= '{"folder":"\\\Entity\\\Logs"}'; $this->assertEquals('\Entity\Logs', $this->fixture->decode($test)->folder); - $test= '{"folder":"\Entity\\Logs"}'; - $this->assertEquals('\Entity\Logs', $this->fixture->decode($test)->folder); + //$test= '{"folder":"\Entity\\Logs"}'; + //$this->assertEquals('\Entity\Logs', $this->fixture->decode($test)->folder); } function testIsJSON() diff --git a/tests/api/LayoutTest.php b/tests/api/LayoutTest.php index 99ffe1a865..7908c9e8f9 100755 --- a/tests/api/LayoutTest.php +++ b/tests/api/LayoutTest.php @@ -34,7 +34,7 @@ class LayoutTest extends \PHPUnit_Framework_TestCase $this->fixture->setUrl('/custom-test/layout/test-put'); $data= '["amount","account","closeDate","leadSource","stage","probability","assignedUser"]'; - $this->assertTrue($this->fixture->isSuccess( $data,1 )); + $this->assertTrue($this->fixture->isSuccess( $data )); } function testPatch() @@ -50,7 +50,7 @@ class LayoutTest extends \PHPUnit_Framework_TestCase { $this->fixture->setType('GET'); - $this->fixture->setUrl('/customTest/layout/detail-view'); + $this->fixture->setUrl('/custom-test/layout/detail'); $this->assertTrue($this->fixture->isSuccess( $this->fixture->getResponse() )); $this->fixture->setUrl('/need-to-be-not-real/layout/not-real'); diff --git a/tests/api/MetadataTest.php b/tests/api/MetadataTest.php index ef66f44c1a..9dbe98a587 100755 --- a/tests/api/MetadataTest.php +++ b/tests/api/MetadataTest.php @@ -40,11 +40,11 @@ class MetadataTest extends \PHPUnit_Framework_TestCase { $this->fixture->setType('PUT'); - $this->fixture->setUrl('/metadata/custom-test/Account'); + $this->fixture->setUrl('/metadata/custom-test/account'); $data= '{"module":"Test"}'; $this->assertTrue($this->fixture->isSuccess( $data )); - $this->fixture->setUrl('/metadata/custom-test/Test'); + $this->fixture->setUrl('/metadata/custom-test/test'); $data= '{"module":"Test","var1":{"subvar1":"NEWsubval1","subvar55":"subval55"}}'; $this->assertTrue($this->fixture->isSuccess( $data )); } diff --git a/tests/api/RestTesterClass.php b/tests/api/RestTesterClass.php index 34fde38054..1b352d0728 100755 --- a/tests/api/RestTesterClass.php +++ b/tests/api/RestTesterClass.php @@ -4,7 +4,7 @@ namespace Espo\Tests\Api; class RestTesterClass { - public $mainUrl= 'http://172.20.0.1/espocrm/api'; + public $mainUrl= 'http://172.20.0.1/espocrm-test/api'; public $username= 'admin'; public $pass= '1'; public $type= 'PATCH'; diff --git a/tests/api/SettingsTest.php b/tests/api/SettingsTest.php index 9f6b3cae2a..9e9a2adf5d 100755 --- a/tests/api/SettingsTest.php +++ b/tests/api/SettingsTest.php @@ -38,7 +38,7 @@ class SettingsTest extends \PHPUnit_Framework_TestCase "customTest"=> array("test"=> "success"), ); $json= json_encode($array); - $this->assertTrue( $this->fixture->isSuccess($json, true) ); + $this->assertTrue( $this->fixture->isSuccess($json) ); /* $config= new Utils\Configurator(); From 3cec02c4c7d522b676d8b03b07fa6364fb297391 Mon Sep 17 00:00:00 2001 From: Taras Machyshyn Date: Wed, 6 Nov 2013 13:31:09 +0200 Subject: [PATCH 2/2] systemConfig changes --- application/Espo/Core/systemConfig.php | 6 +++ .../Espo/Layouts/customTest/detailTest.json | 1 - .../Espo/Layouts/customTest/detailView.json | 1 - .../Espo/Metadata/entityDefs/Attachment.json | 0 .../Espo/Metadata/entityDefs/Comment.json | 0 .../Metadata/entityDefs/EmailTemplate.json | 0 .../Espo/Metadata/entityDefs/Preferences.json | 0 .../Espo/Metadata/entityDefs/Role.json | 0 .../Espo/Metadata/entityDefs/Settings.json | 0 .../Espo/Metadata/entityDefs/Team.json | 0 .../Espo/Metadata/entityDefs/User.json | 0 .../Espo/Utils/Controllers/Controller.php | 0 application/Espo/Utils/Controllers/Layout.php | 0 .../Espo/Utils/Controllers/Manager.php | 0 .../Crm/Layouts/contact/filtersAdvanced.json | 0 .../Crm/Layouts/lead/filtersAdvanced.json | 0 .../Layouts/opportunity/filtersAdvanced.json | 0 .../Modules/Crm/Layouts/task/list.json | 0 .../Modules/Crm/Layouts/task/listSmall.json | 0 .../Crm/Metadata/entityDefs/Account.json | 0 .../Modules/Crm/Metadata/entityDefs/Call.json | 0 .../Modules/Crm/Metadata/entityDefs/Case.json | 0 .../Crm/Metadata/entityDefs/Contact.json | 0 .../Crm/Metadata/entityDefs/Email.json | 0 .../Crm/Metadata/entityDefs/InboundEmail.json | 0 .../Modules/Crm/Metadata/entityDefs/Lead.json | 0 .../Crm/Metadata/entityDefs/Meeting.json | 0 .../Crm/Metadata/entityDefs/Opportunity.json | 0 .../Crm/Metadata/entityDefs/Prospect.json | 0 .../Modules/Crm/Metadata/entityDefs/Task.json | 0 application/config.php | 0 data/cache/application/metadata.php | 42 +++++++++++++++---- tests/myfile.txt | 0 33 files changed, 41 insertions(+), 9 deletions(-) delete mode 100755 application/Espo/Layouts/customTest/detailTest.json delete mode 100755 application/Espo/Layouts/customTest/detailView.json mode change 100644 => 100755 application/Espo/Metadata/entityDefs/Attachment.json mode change 100644 => 100755 application/Espo/Metadata/entityDefs/Comment.json mode change 100644 => 100755 application/Espo/Metadata/entityDefs/EmailTemplate.json mode change 100644 => 100755 application/Espo/Metadata/entityDefs/Preferences.json mode change 100644 => 100755 application/Espo/Metadata/entityDefs/Role.json mode change 100644 => 100755 application/Espo/Metadata/entityDefs/Settings.json mode change 100644 => 100755 application/Espo/Metadata/entityDefs/Team.json mode change 100644 => 100755 application/Espo/Metadata/entityDefs/User.json mode change 100644 => 100755 application/Espo/Utils/Controllers/Controller.php mode change 100644 => 100755 application/Espo/Utils/Controllers/Layout.php mode change 100644 => 100755 application/Espo/Utils/Controllers/Manager.php mode change 100644 => 100755 application/Modules/Crm/Layouts/contact/filtersAdvanced.json mode change 100644 => 100755 application/Modules/Crm/Layouts/lead/filtersAdvanced.json mode change 100644 => 100755 application/Modules/Crm/Layouts/opportunity/filtersAdvanced.json mode change 100644 => 100755 application/Modules/Crm/Layouts/task/list.json mode change 100644 => 100755 application/Modules/Crm/Layouts/task/listSmall.json mode change 100644 => 100755 application/Modules/Crm/Metadata/entityDefs/Account.json mode change 100644 => 100755 application/Modules/Crm/Metadata/entityDefs/Call.json mode change 100644 => 100755 application/Modules/Crm/Metadata/entityDefs/Case.json mode change 100644 => 100755 application/Modules/Crm/Metadata/entityDefs/Contact.json mode change 100644 => 100755 application/Modules/Crm/Metadata/entityDefs/Email.json mode change 100644 => 100755 application/Modules/Crm/Metadata/entityDefs/InboundEmail.json mode change 100644 => 100755 application/Modules/Crm/Metadata/entityDefs/Lead.json mode change 100644 => 100755 application/Modules/Crm/Metadata/entityDefs/Meeting.json mode change 100644 => 100755 application/Modules/Crm/Metadata/entityDefs/Opportunity.json mode change 100644 => 100755 application/Modules/Crm/Metadata/entityDefs/Prospect.json mode change 100644 => 100755 application/Modules/Crm/Metadata/entityDefs/Task.json mode change 100644 => 100755 application/config.php mode change 100644 => 100755 data/cache/application/metadata.php mode change 100644 => 100755 tests/myfile.txt diff --git a/application/Espo/Core/systemConfig.php b/application/Espo/Core/systemConfig.php index 226b6b109c..05897de879 100755 --- a/application/Espo/Core/systemConfig.php +++ b/application/Espo/Core/systemConfig.php @@ -71,6 +71,12 @@ return array ( 'configPathFull', 'configCustomPathFull', 'crud', + 'customDir', + 'espoPath', + 'espoModulePath', + 'espoCustomPath', + 'controllerPath', + 'scopeModuleMap', ), 'adminItems' => array ( diff --git a/application/Espo/Layouts/customTest/detailTest.json b/application/Espo/Layouts/customTest/detailTest.json deleted file mode 100755 index 66830c1a9a..0000000000 --- a/application/Espo/Layouts/customTest/detailTest.json +++ /dev/null @@ -1 +0,0 @@ -[{"label":"MyLabel"}] \ No newline at end of file diff --git a/application/Espo/Layouts/customTest/detailView.json b/application/Espo/Layouts/customTest/detailView.json deleted file mode 100755 index 723be25c6e..0000000000 --- a/application/Espo/Layouts/customTest/detailView.json +++ /dev/null @@ -1 +0,0 @@ -[{"oldlabel":"MyLabeldddd","label":"MyLabel"}] \ No newline at end of file diff --git a/application/Espo/Metadata/entityDefs/Attachment.json b/application/Espo/Metadata/entityDefs/Attachment.json old mode 100644 new mode 100755 diff --git a/application/Espo/Metadata/entityDefs/Comment.json b/application/Espo/Metadata/entityDefs/Comment.json old mode 100644 new mode 100755 diff --git a/application/Espo/Metadata/entityDefs/EmailTemplate.json b/application/Espo/Metadata/entityDefs/EmailTemplate.json old mode 100644 new mode 100755 diff --git a/application/Espo/Metadata/entityDefs/Preferences.json b/application/Espo/Metadata/entityDefs/Preferences.json old mode 100644 new mode 100755 diff --git a/application/Espo/Metadata/entityDefs/Role.json b/application/Espo/Metadata/entityDefs/Role.json old mode 100644 new mode 100755 diff --git a/application/Espo/Metadata/entityDefs/Settings.json b/application/Espo/Metadata/entityDefs/Settings.json old mode 100644 new mode 100755 diff --git a/application/Espo/Metadata/entityDefs/Team.json b/application/Espo/Metadata/entityDefs/Team.json old mode 100644 new mode 100755 diff --git a/application/Espo/Metadata/entityDefs/User.json b/application/Espo/Metadata/entityDefs/User.json old mode 100644 new mode 100755 diff --git a/application/Espo/Utils/Controllers/Controller.php b/application/Espo/Utils/Controllers/Controller.php old mode 100644 new mode 100755 diff --git a/application/Espo/Utils/Controllers/Layout.php b/application/Espo/Utils/Controllers/Layout.php old mode 100644 new mode 100755 diff --git a/application/Espo/Utils/Controllers/Manager.php b/application/Espo/Utils/Controllers/Manager.php old mode 100644 new mode 100755 diff --git a/application/Modules/Crm/Layouts/contact/filtersAdvanced.json b/application/Modules/Crm/Layouts/contact/filtersAdvanced.json old mode 100644 new mode 100755 diff --git a/application/Modules/Crm/Layouts/lead/filtersAdvanced.json b/application/Modules/Crm/Layouts/lead/filtersAdvanced.json old mode 100644 new mode 100755 diff --git a/application/Modules/Crm/Layouts/opportunity/filtersAdvanced.json b/application/Modules/Crm/Layouts/opportunity/filtersAdvanced.json old mode 100644 new mode 100755 diff --git a/application/Modules/Crm/Layouts/task/list.json b/application/Modules/Crm/Layouts/task/list.json old mode 100644 new mode 100755 diff --git a/application/Modules/Crm/Layouts/task/listSmall.json b/application/Modules/Crm/Layouts/task/listSmall.json old mode 100644 new mode 100755 diff --git a/application/Modules/Crm/Metadata/entityDefs/Account.json b/application/Modules/Crm/Metadata/entityDefs/Account.json old mode 100644 new mode 100755 diff --git a/application/Modules/Crm/Metadata/entityDefs/Call.json b/application/Modules/Crm/Metadata/entityDefs/Call.json old mode 100644 new mode 100755 diff --git a/application/Modules/Crm/Metadata/entityDefs/Case.json b/application/Modules/Crm/Metadata/entityDefs/Case.json old mode 100644 new mode 100755 diff --git a/application/Modules/Crm/Metadata/entityDefs/Contact.json b/application/Modules/Crm/Metadata/entityDefs/Contact.json old mode 100644 new mode 100755 diff --git a/application/Modules/Crm/Metadata/entityDefs/Email.json b/application/Modules/Crm/Metadata/entityDefs/Email.json old mode 100644 new mode 100755 diff --git a/application/Modules/Crm/Metadata/entityDefs/InboundEmail.json b/application/Modules/Crm/Metadata/entityDefs/InboundEmail.json old mode 100644 new mode 100755 diff --git a/application/Modules/Crm/Metadata/entityDefs/Lead.json b/application/Modules/Crm/Metadata/entityDefs/Lead.json old mode 100644 new mode 100755 diff --git a/application/Modules/Crm/Metadata/entityDefs/Meeting.json b/application/Modules/Crm/Metadata/entityDefs/Meeting.json old mode 100644 new mode 100755 diff --git a/application/Modules/Crm/Metadata/entityDefs/Opportunity.json b/application/Modules/Crm/Metadata/entityDefs/Opportunity.json old mode 100644 new mode 100755 diff --git a/application/Modules/Crm/Metadata/entityDefs/Prospect.json b/application/Modules/Crm/Metadata/entityDefs/Prospect.json old mode 100644 new mode 100755 diff --git a/application/Modules/Crm/Metadata/entityDefs/Task.json b/application/Modules/Crm/Metadata/entityDefs/Task.json old mode 100644 new mode 100755 diff --git a/application/config.php b/application/config.php old mode 100644 new mode 100755 diff --git a/data/cache/application/metadata.php b/data/cache/application/metadata.php old mode 100644 new mode 100755 index 3c92ecad70..a5d7ff256b --- a/data/cache/application/metadata.php +++ b/data/cache/application/metadata.php @@ -495,11 +495,11 @@ return array ( ), 'weekStart' => array ( - 'type' => 'enum', + 'type' => 'enumInt', 'options' => array ( - 0 => '0', - 1 => '1', + 0 => 0, + 1 => 1, ), 'default' => 0, ), @@ -611,13 +611,13 @@ return array ( ), 'weekStart' => array ( - 'type' => 'enum', + 'type' => 'enumInt', 'options' => array ( - 0 => '0', - 1 => '1', + 0 => 0, + 1 => 1, ), - 'default' => '1', + 'default' => 0, ), 'thousandSeparator' => array ( @@ -716,6 +716,7 @@ return array ( 8 => 'Case', 9 => 'Prospect', ), + 'translation' => 'App.scopeNamesPlural', ), 'quickCreateList' => array ( @@ -732,6 +733,7 @@ return array ( 7 => 'Case', 8 => 'Prospect', ), + 'translation' => 'App.scopeNames', ), ), ), @@ -3064,6 +3066,32 @@ return array ( 'advanced' => true, ), ), + 'enumInt' => + array ( + 'params' => + array ( + 0 => + array ( + 'name' => 'options', + 'type' => 'array', + ), + 1 => + array ( + 'name' => 'default', + 'type' => 'varchar', + ), + 2 => + array ( + 'name' => 'translation', + 'type' => 'varchar', + ), + ), + 'search' => + array ( + 'basic' => false, + 'advanced' => true, + ), + ), 'float' => array ( 'params' => diff --git a/tests/myfile.txt b/tests/myfile.txt old mode 100644 new mode 100755