ci =& get_instance(); // Loads helper message to manage returning messages $this->ci->load->helper("message"); $this->ci->load->library("PermissionLib"); } /** * Everything starts here... */ public function start($callParameters, $permissionType) { $result = null; $parameters = $this->_getParameters($callParameters); $validation = $this->_validateCall($parameters); // If the validation was passed if ($validation->error == EXIT_SUCCESS) { $loaded = null; // If the given resource is a model if (strpos($parameters->resourceName, PCRMLib::MODEL_PREFIX) !== false) { // Try to load the model $result = $this->_loadModel($parameters->resourcePath, $parameters->resourceName); if ($result->error == EXIT_SUCCESS) { $loaded = $result->retval; } } // If the given resource is a library else if (strpos($parameters->resourceName, PCRMLib::LIB_PREFIX) !== false) { // Check if the resource is already loaded, it works only with libraries and drivers $isLoaded = $this->ci->load->is_loaded($parameters->resourceName); // If not loaded then load it if ($isLoaded === false) { // Checks if the operation is permitted by the API caller // Only for libraries, permissions are automatically handled by models $result = $this->checkLibraryPermission( $parameters->resourcePath, $parameters->resourceName, $parameters->function, $permissionType ); if ($result->error == EXIT_ERROR) { $loaded = null; } else { // Try to load the library $result = $this->_loadLibrary($parameters->resourcePath, $parameters->resourceName); if ($result->error == EXIT_SUCCESS) { $loaded = $result->retval; } } } // If it is already loaded $isLoaded contains the instance of the library else { $loaded = $isLoaded; } } // Wrong selection! else { $result = $this->_error("Neither a lib nor model: " . $parameters->resourcePath . $parameters->resourceName); } // If the resource was found and loaded if (!is_null($loaded)) { $result = $this->_callThis($parameters->resourceName, $parameters->function, $parameters->parameters); } else { // Resource not loaded } } else { $result = $validation; } return $result; } /** * Gets the parameters from the call */ private function _getParameters($parametersArray) { $parameters = new stdClass(); $parameters->parameters = array(); $count = 0; foreach ($parametersArray as $parameterName => $parameterValue) { // The name of the resource, path included if ($parameterName == PCRMLib::RESOURCE_PARAMETER) { // Separates the resource path from the resource name $splittedResource = preg_split(PCRMLib::REG_SPLIT_EXPR, $parameterValue); $parameters->resourceName = $splittedResource[count($splittedResource) - 1]; $parameters->resourcePath = str_replace($parameters->resourceName, "", $parameterValue); } // The name of the function else if ($parameterName == PCRMLib::FUNCTION_PARAMETER) { $parameters->function = $parameterValue; } // It is assumed that all other parameters are the parameters to be passed to the function // They will be passed to the function in the same order in which they are passed to // this controller else { $parameters->parameters[$count++] = $parameterValue; } } return $parameters; } /** * Validate the given parameters */ private function _validateCall($parameters) { if (!is_object($parameters)) { return $this->_error("Parameter is not an object"); } if (!isset($parameters->resourcePath)) { return $this->_error("Resource path is not specified"); } if (!isset($parameters->resourceName)) { return $this->_error("Resource name is not specified"); } if (!isset($parameters->function)) { return $this->_error("Function is not specified"); } if (!is_array($parameters->parameters)) { return $this->_error("Parameters are not specified"); } if (in_array($parameters->resourceName, PCRMLib::$RESOURCES_BLACK_LIST)) { return $this->_error("You are trying to access to unauthorized resources"); } return $this->_success("Input data are valid"); } /** * Loads a model using the given path and name * * NOTE: the models automatically handle the permissions */ private function _loadModel($resourcePath, $resourceName) { $loaded = null; $result = null; try { $loaded = $this->ci->load->model($resourcePath . $resourceName); } catch (Exception $e) { // Errors while loading the model $result = $this->_error("Errors while loading the model: " . $e->getMessage()); } if (!is_null($loaded)) { $result = $this->_success($loaded); } return $result; } private function checkLibraryPermission($resourcePath, $resourceName, $function, $permissionType) { $result = null; $permissionPath = ""; if ($resourcePath != "") { $permissionPath = $resourcePath; } $permissionPath .= $resourceName . "." . $function; if ($this->ci->permissionlib->hasPermission($permissionPath, $permissionType) === false) { $result = $this->_error(lang("fhc_".FHC_NORIGHT)." -> ".$permissionPath, FHC_NORIGHT); } else { $result = $this->_success("Has permission"); } return $result; } /** * Loads a library using the given path and name * * The method "library" of the class CI_Loader provided by CI has some limitations, * so to be able to check errors was used a workaround. * It consists in: * - Checking if the file (identified by parameters $resourcePath and $resourceName) exists * - If exists it will be loaded using the method "file" from CI_Loader * - Checks if the loaded file contains a class identified by parameter $resourceName * * If one of the previous tests fails, it will be returned a null value */ private function _loadLibrary($resourcePath, $resourceName) { $loaded = null; try { // Gets all the configured resources paths $packagePaths = $this->ci->load->get_package_paths(); // Looking for a file in every paths with the same name of the resource $found = null; for ($i = 0; $i < count($packagePaths) && is_null($found); $i++) { $file = $packagePaths[$i] . PCRMLib::LIBS_PATH . DIRECTORY_SEPARATOR . $resourcePath . $resourceName . PCRMLib::LIB_FILE_EXTENSION; if (file_exists($file)) { $found = $file; } } // If the file was found if (!is_null($found)) { // Load the file $loaded = $this->ci->load->file($found); // If the resource is not present inside the file if (!class_exists($resourceName)) { $loaded = null; // Same phrase error as load->model() provided by CI $result = $this->_error($found . " exists, but doesn't declare class " . $resourceName); } } else { $loaded = null; // Same phrase error as load->model() provided by CI $result = $this->_error("Unable to load the requested class: " . $resourceName); } } catch (Exception $e) { // Errors while loading the library $result = $this->_error("Errors while loading the library: " . $e->getMessage()); } if (!is_null($loaded)) { $result = $this->_success($loaded); } return $result; } /** * Calls a method of a class with the given parameters and returns its result * * @param string $resourceName identifies the class name * @param string $function identifies the method name * @param array $parameters contains the parameters to be passed to the method */ private function _callThis($resourceName, $function, $parameters) { $result = null; try { // Get informations about the function $reflectionMethod = new ReflectionMethod($resourceName, $function); // If the number of given parameters is greater or equal to the number of // parameters required by the function if (count($parameters) >= $reflectionMethod->getNumberOfRequiredParameters()) { // If the function is static if ($reflectionMethod->isStatic() === true) { $classMethod = $resourceName . "::" . $function; } // If the function is not static else { $classMethod = array(new $resourceName(), $function); } // If the resource's function is callable if (is_callable($classMethod)) { // Call resource->function() // @ was applied to prevent really ugly and unmanageable errors $resultCall = @call_user_func_array($classMethod, $parameters); // If errors occurred while running it // NOTE: if the called function via call_user_func_array returns a boolean set as false, // it will be recognized like a running error. A little bit tricky ;) if ($resultCall === false) { $result = $this->_error("Error running " . $resourceName . "->" . $function . "()"); } // Returns the result of resource->function() else { $result = $this->_success($resultCall); } } else { $result = $this->_error($resourceName . "->" . $function . "() is not callable!"); } } else { $result = $this->_error( "Number of required parameters: " . $reflectionMethod->getNumberOfRequiredParameters() . ". Given: " . count($parameters) ); } } catch (Exception $e) { $result = $this->_error($e->getMessage()); } return $result; } /* * */ private function _error($retval = '', $message = EXIT_ERROR) { return error($retval, $message); } /* * */ private function _success($retval, $message = EXIT_SUCCESS) { return success($retval, $message); } }