cache = $cache; } //-------------------------------------------------------------------- /** * Render a cell, returning its body as a string. * * @param string $library * @param null $params * @param integer $ttl * @param string|null $cacheName * * @return string * @throws \ReflectionException */ public function render(string $library, $params = null, int $ttl = 0, string $cacheName = null): string { list($class, $method) = $this->determineClass($library); // Is it cached? $cacheName = ! empty($cacheName) ? $cacheName : $class . $method . md5(serialize($params)); if (! empty($this->cache) && $output = $this->cache->get($cacheName)) { return $output; } // Not cached - so grab it... $instance = new $class(); if (! method_exists($instance, $method)) { throw ViewException::forInvalidCellMethod($class, $method); } // Try to match up the parameter list we were provided // with the parameter name in the callback method. $paramArray = $this->prepareParams($params); $refMethod = new ReflectionMethod($instance, $method); $paramCount = $refMethod->getNumberOfParameters(); $refParams = $refMethod->getParameters(); if ($paramCount === 0) { if (! empty($paramArray)) { throw ViewException::forMissingCellParameters($class, $method); } $output = $instance->{$method}(); } elseif (($paramCount === 1) && ( ( ! array_key_exists($refParams[0]->name, $paramArray)) || (array_key_exists($refParams[0]->name, $paramArray) && count($paramArray) !== 1) ) ) { $output = $instance->{$method}($paramArray); } else { $fireArgs = []; $method_params = []; foreach ($refParams as $arg) { $method_params[$arg->name] = true; if (array_key_exists($arg->name, $paramArray)) { $fireArgs[$arg->name] = $paramArray[$arg->name]; } } foreach ($paramArray as $key => $val) { if (! isset($method_params[$key])) { throw ViewException::forInvalidCellParameter($key); } } $output = $instance->$method(...array_values($fireArgs)); } // Can we cache it? if (! empty($this->cache) && $ttl !== 0) { $this->cache->save($cacheName, $output, $ttl); } return $output; } //-------------------------------------------------------------------- /** * Parses the params attribute. If an array, returns untouched. * If a string, it should be in the format "key1=value key2=value". * It will be split and returned as an array. * * @param $params * * @return array|null */ public function prepareParams($params) { if (empty($params) || ( ! is_string($params) && ! is_array($params))) { return []; } if (is_string($params)) { $new_params = []; $separator = ' '; if (strpos($params, ',') !== false) { $separator = ','; } $params = explode($separator, $params); unset($separator); foreach ($params as $p) { if (! empty($p)) { list($key, $val) = explode('=', $p); $new_params[trim($key)] = trim($val, ', '); } } $params = $new_params; unset($new_params); } if (is_array($params) && empty($params)) { return []; } return $params; } //-------------------------------------------------------------------- /** * Given the library string, attempts to determine the class and method * to call. * * @param string $library * * @return array */ protected function determineClass(string $library): array { // We don't want to actually call static methods // by default, so convert any double colons. $library = str_replace('::', ':', $library); list($class, $method) = explode(':', $library); if (empty($class)) { throw ViewException::forNoCellClass(); } if (! class_exists($class, true)) { throw ViewException::forInvalidCellClass($class); } if (empty($method)) { $method = 'index'; } return [ $class, $method, ]; } //-------------------------------------------------------------------- }