diff --git a/gulliver/system/class.bootstrap.php b/gulliver/system/class.bootstrap.php index 8144b0009..ad5fc1211 100644 --- a/gulliver/system/class.bootstrap.php +++ b/gulliver/system/class.bootstrap.php @@ -66,7 +66,7 @@ class Bootstrap return; } - public function registerDir($name, $dir) + public static function registerDir($name, $dir) { BootStrap::$includePaths[$name] = $dir; } @@ -1108,19 +1108,16 @@ class Bootstrap */ $pmOauthClientId = 'x-pm-local-client'; - // load Api class - G::loadClass('api'); - - // Load Api ini file for Rest Service - + /* + * Load Api ini file for Rest Service + */ $apiIniConf = array(); - if (file_exists($apiIniFile)) { $apiIniConf = self::parseIniFile($apiIniFile); } // Setting current workspace to Api class - \ProcessMaker\Api::setWorkspace(SYS_SYS); + \ProcessMaker\Services\Api::setWorkspace(SYS_SYS); // TODO remove this setting on the future, it is not needed, but if it is not present is throwing a warning Luracast\Restler\Format\HtmlFormat::$viewPath = $servicesDir . 'oauth2/views'; @@ -1144,33 +1141,56 @@ class Bootstrap $rest->setOverridingFormats('HtmlFormat', 'JsonFormat', 'UploadFormat'); // Override $_SERVER['REQUEST_URI'] to Restler handles the current url correctly - $_SERVER['REQUEST_URI'] = $uri; - // scan all api directory to find api classes - $classesList = Bootstrap::rglob('*', 0, $apiDir); + $isPluginRequest = strpos($uri, '/plugin-') !== false ? true : false; - foreach ($classesList as $classFile) { - if (pathinfo($classFile, PATHINFO_EXTENSION) === 'php') { - $namespace = '\\Services\\' . str_replace( - DIRECTORY_SEPARATOR, - '\\', - str_replace('.php', '', str_replace($servicesDir, '', $classFile)) - ); - //var_dump($namespace); - $rest->addAPIClass($namespace); - } + if ($isPluginRequest) { + $tmp = explode('/', $uri); + array_shift($tmp); + $tmp = array_shift($tmp); + $tmp = explode('-', $tmp); + $pluginName = $tmp[1]; + $uri = str_replace('/plugin-'.$pluginName, '', $uri); } - // adding aliases for Restler - - if (array_key_exists('alias', $apiIniConf)) { - //print_r($apiIniConf['alias']); die; - foreach ($apiIniConf['alias'] as $alias => $aliasData) { - if (is_array($aliasData)) { - foreach ($aliasData as $label => $namespace) { - $namespace = '\\' . ltrim($namespace, '\\'); - //var_dump($namespace, $alias); - $rest->addAPIClass($namespace, $alias); + $_SERVER['REQUEST_URI'] = $uri; + + if (! $isPluginRequest) { // if it is not a request for a plugin endpoint + // scan all api directory to find api classes + $classesList = Bootstrap::rglob('*', 0, $apiDir); + + foreach ($classesList as $classFile) { + if (pathinfo($classFile, PATHINFO_EXTENSION) === 'php') { + $namespace = '\\Services\\' . str_replace( + DIRECTORY_SEPARATOR, + '\\', + str_replace('.php', '', str_replace($servicesDir, '', $classFile)) + ); + //var_dump($namespace); + $rest->addAPIClass($namespace); + } + } + + // adding aliases for Restler + if (array_key_exists('alias', $apiIniConf)) { + foreach ($apiIniConf['alias'] as $alias => $aliasData) { + if (is_array($aliasData)) { + foreach ($aliasData as $label => $namespace) { + $namespace = '\\' . ltrim($namespace, '\\'); + $rest->addAPIClass($namespace, $alias); + } + } + } + } + } else { + // hook to get rest api classes from plugins + if (class_exists('PMPluginRegistry')) { + $pluginRegistry = & PMPluginRegistry::getSingleton(); + $plugins = $pluginRegistry->getRegisteredRestServices(); + + if (is_array($plugins) && array_key_exists($pluginName, $plugins)) { + foreach ($plugins[$pluginName] as $class) { + $rest->addAPIClass($class['namespace']); } } } diff --git a/workflow/engine/classes/class.plugin.php b/workflow/engine/classes/class.plugin.php index 986d773d0..215998a2c 100755 --- a/workflow/engine/classes/class.plugin.php +++ b/workflow/engine/classes/class.plugin.php @@ -341,10 +341,10 @@ class PMPlugin * @param array/string $pluginJsFile * @return void */ - function registerRestService($classname, $path = '') + function registerRestService() { $oPluginRegistry =& PMPluginRegistry::getSingleton(); - $oPluginRegistry->registerRestService($this->sNamespace, $classname, $path); + $oPluginRegistry->registerRestService($this->sNamespace); } /** @@ -360,6 +360,12 @@ class PMPlugin $oPluginRegistry =& PMPluginRegistry::getSingleton(); $oPluginRegistry->unregisterRestService($this->sNamespace, $classname, $path); } + + function enableRestService($enable) + { + $oPluginRegistry =& PMPluginRegistry::getSingleton(); + $oPluginRegistry->enableRestService($this->sNamespace, $enable); + } } class menuDetail diff --git a/workflow/engine/classes/class.pluginRegistry.php b/workflow/engine/classes/class.pluginRegistry.php index 81ee5b68b..89e6bcc7b 100755 --- a/workflow/engine/classes/class.pluginRegistry.php +++ b/workflow/engine/classes/class.pluginRegistry.php @@ -108,6 +108,8 @@ class PMPluginRegistry */ private $_restServices = array (); + private $_restServiceEnabled = array(); + private static $instance = null; /** @@ -240,6 +242,27 @@ class PMPluginRegistry if (method_exists( $oPlugin, 'enable' )) { $oPlugin->enable(); } + + /* + * 1. register /src directory for autoloading + * 2. verify if rest service is enabled + * 3. register rest service directory + */ + $pluginSrcDir = PATH_PLUGINS . $detail->sNamespace . PATH_SEP . 'src'; + + if (is_dir($pluginSrcDir)) { + Bootstrap::registerDir($detail->sNamespace.'/src', $pluginSrcDir); + } + + if (array_key_exists($detail->sNamespace, $this->_restServiceEnabled) + && $this->_restServiceEnabled[$detail->sNamespace] == true + ) { + $oPlugin->registerRestService(); + ProcessMaker\Util\Logger::log("plugin ".$detail->sNamespace." -> rest enabled"); + } else { + ProcessMaker\Util\Logger::log("plugin ".$detail->sNamespace." -> rest not enabled"); + } + return true; } } @@ -1339,27 +1362,39 @@ class PMPluginRegistry * @param string $path (optional) the class file path, if it is not set the system will try resolve the * file path from its classname. */ - public function registerRestService ($sNamespace, $classname, $path = '') + public function registerRestService($sNamespace) { - $restService = new StdClass(); - $restService->sNamespace = $sNamespace; - $restService->classname = $classname; + $baseSrcPluginPath = PATH_PLUGINS . $sNamespace . PATH_SEP . "src"; + $apiPath = PATH_SEP . "Services" . PATH_SEP . "Api" . PATH_SEP . ucfirst($sNamespace); + $classesList = Bootstrap::rglob('*', 0, $baseSrcPluginPath . $apiPath); - if (empty( $path )) { - $path = PATH_PLUGINS . $restService->sNamespace . "/services/rest/$classname.php"; + foreach ($classesList as $classFile) { + if (pathinfo($classFile, PATHINFO_EXTENSION) === 'php') { - if (! file_exists( $path )) { - $path = PATH_PLUGINS . $restService->sNamespace . "/services/rest/crud/$classname.php"; + $ns = str_replace( + DIRECTORY_SEPARATOR, + '\\', + str_replace('.php', '', str_replace($baseSrcPluginPath, '', $classFile)) + ); + + ProcessMaker\Util\Logger::log("Namespace found: " . $ns); + + // Ensure that is registering only existent classes. + if (class_exists($ns)) { + $this->_restServices[strtolower($sNamespace)][] = array( + "filepath" => $classFile, + "namespace" => $ns + ); + ProcessMaker\Util\Logger::log("class exists: YES"); + } else { + ProcessMaker\Util\Logger::log("class exists: NO"); + } + + + ProcessMaker\Util\Logger::log($this->_restServices); } } - if (! file_exists( $path )) { - return false; - } - - $restService->path = $path; - $this->_restServices[] = $restService; - return true; } @@ -1370,31 +1405,14 @@ class PMPluginRegistry */ public function unregisterRestService ($sNamespace) { - foreach ($this->_restServices as $i => $service) { - if ($sNamespace == $service->sNamespace) { - unset( $this->_restServices[$i] ); - } - } - // Re-index when all js were unregistered - $this->_restServices = array_values( $this->_restServices ); + unset($this->_restServices[$sNamespace]); } - public function getRegisteredRestServices () + public function getRegisteredRestServices() { return $this->_restServices; } - public function getRegisteredRestClassFiles () - { - $restClassFiles = array (); - - foreach ($this->_restServices as $restService) { - $restClassFiles[] = $restService->path; - } - - return $restClassFiles; - } - /** * return all dashboard pages * @@ -1435,6 +1453,16 @@ class PMPluginRegistry } $language->updateLanguagePlugin($namePlugin, SYS_LANG); } - } + } + + /** + * Function to enable rest service for plugins + * @param string $sNamespace + * @param bool $enable + */ + function enableRestService($sNamespace, $enable) + { + $this->_restServiceEnabled[$sNamespace] = $enable; + } } diff --git a/workflow/engine/classes/class.api.php b/workflow/engine/src/ProcessMaker/Services/Api.php similarity index 83% rename from workflow/engine/classes/class.api.php rename to workflow/engine/src/ProcessMaker/Services/Api.php index 88ec29fdf..e84fc532f 100644 --- a/workflow/engine/classes/class.api.php +++ b/workflow/engine/src/ProcessMaker/Services/Api.php @@ -1,5 +1,5 @@ logFile = sys_get_temp_dir() . '/processmaker.log'; + $this->fp = fopen($this->logFile, "a+"); + } + + public static function getInstance() + { + if (is_null(self::$instance)) { + self::$instance = new Logger(); + } + + return self::$instance; + } + + public function setLog($data) + { + if (! is_string($data)) { + $data = print_r($data, true); + } + + fwrite($this->fp, "PM LOG: ".date('Y-m-d H:i:s') . " " . $data . PHP_EOL); + } + + public static function log($data) + { + $me = Logger::getInstance(); + $me->setLog($data); + } +} \ No newline at end of file diff --git a/workflow/engine/src/Services/Api/ProcessMaker/Process.php b/workflow/engine/src/Services/Api/ProcessMaker/Process.php index 26ee2c3e1..5e1500344 100644 --- a/workflow/engine/src/Services/Api/ProcessMaker/Process.php +++ b/workflow/engine/src/Services/Api/ProcessMaker/Process.php @@ -1,7 +1,7 @@