Beispiel #1
0
 /**
  * Display a link to the Sitegear website.
  *
  * @param \Sitegear\View\ViewInterface $view
  */
 public function sitegearLinkComponent(ViewInterface $view)
 {
     LoggerRegistry::debug('VersionModule::sitegearLinkComponent()');
     $view['link-url'] = $this->getEngine()->getApplicationInfo()->getSitegearHomepage();
     $view['link-tooltip'] = sprintf('Running version: %s', $this->getEngine()->getApplicationInfo()->getSitegearVersionIdentifier());
     $view['display-name'] = $this->getEngine()->getApplicationInfo()->getSitegearDisplayName();
 }
 /**
  * @param \Sitegear\Engine\SitegearEngine $engine
  * @param string|null $filename
  */
 public function __construct(SitegearEngine $engine, $filename = null)
 {
     LoggerRegistry::debug('new SitegearApplicationInfoProvider({engine}, {filename})', array('engine' => TypeUtilities::describe($engine), 'filename' => TypeUtilities::describe($filename)));
     $this->engine = $engine;
     $filename = $filename ?: sprintf('%s/%s', dirname($this->getSitegearRoot()), $filename ?: 'composer.json');
     $this->data = file_exists($filename) ? json_decode(file_get_contents($filename), true) : array();
 }
 /**
  * Controller to display the image data.
  *
  * @return Response
  */
 public function imageController()
 {
     LoggerRegistry::debug('LocationsModule::imageController()');
     ob_start();
     $this->getCaptcha()->writeImage();
     return new Response(ob_get_clean(), 200);
 }
 /**
  * Setup the route parameters.
  *
  * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
  *
  * @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
  * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
  */
 public function onKernelRequest(GetResponseEvent $event)
 {
     LoggerRegistry::debug('EngineRouterListener performing start() on REQUEST event');
     $this->setRoutingAttributes($event->getRequest());
     $this->setTemplateAttributes($event->getRequest());
     LoggerRegistry::debug('EngineRouterListener will proceed with standard rendering');
 }
Beispiel #5
0
 /**
  * @inheritdoc
  */
 public function upload($selector)
 {
     LoggerRegistry::debug('FileModule::upload({selector})', array('selector' => TypeUtilities::describe($selector)));
     $filename = sprintf('%s/%s', $this->getEngine()->getSiteInfo()->getSiteRoot(), ltrim($selector, '/'));
     mkdir(dirname($filename), 0777, true);
     // TODO Implement me
 }
Beispiel #6
0
 /**
  * Display the breadcrumbs navigation helper component.
  *
  * @param \Sitegear\View\ViewInterface $view
  * @param \Symfony\Component\HttpFoundation\Request $request
  * @param string|null $url Allows breadcrumb to be displayed for a different page; if null, the URL is taken from
  *   the passed-in Request object.
  *
  * @return null|boolean
  */
 public function breadcrumbsComponent(ViewInterface $view, Request $request, $url = null)
 {
     LoggerRegistry::debug('NavigationModule::breadcrumbsComponent([view], [request], {url})', array('url' => TypeUtilities::describe($url)));
     $url = trim(!is_null($url) ? $url : $request->getPathInfo(), '/');
     if (empty($url) && !$this->config('components.breadcrumbs.show-on-homepage')) {
         // This is the home page, and we are configured not to show the breadcrumbs here.
         return false;
     }
     $data = $this->getData(MountableModuleInterface::NAVIGATION_DATA_MODE_EXPANDED);
     $path = $this->getNavigationPath($url, $data);
     if (is_null($path)) {
         // The URL cannot be found in the navigation, don't show the breadcrumb because there is nothing to show.
         return false;
     }
     $trail = array();
     $breadcrumbKeys = array('url' => true, 'label' => true);
     if (strlen($url) > 0 && $this->config('components.breadcrumbs.prepend-homepage')) {
         $trail[] = array_intersect_key($this->getNavigationItem('', $data), $breadcrumbKeys);
     }
     foreach ($path as $pathItem) {
         $trail[] = array_intersect_key($data[$pathItem], $breadcrumbKeys);
         $data = isset($data[$pathItem]['children']) ? $data[$pathItem]['children'] : array();
     }
     $view['trail'] = $trail;
     return null;
 }
Beispiel #7
0
 /**
  * @inheritdoc
  */
 public function load($args)
 {
     LoggerRegistry::debug('JsonFileLoader::load({args})', array('args' => TypeUtilities::describe($args)));
     if (!$this->supports($args)) {
         throw new \InvalidArgumentException(sprintf('JsonFileLoader attempting to load unsupported config file "%s".', $args));
     }
     return json_decode(file_get_contents($args), true);
 }
Beispiel #8
0
 /**
  * @inheritdoc
  */
 public function decorate($content, ViewInterface $view = null, Request $request = null)
 {
     $renderTime = $this->formatTime($view->getEngine()->getTimestamp());
     $version = $view->getEngine()->getApplicationInfo()->getSitegearVersionIdentifier();
     $userManager = $view->getEngine()->getUserManager();
     $comment = sprintf('<!-- %s%s :: %s :: %s -->%s<!-- %s :: %s :: %s -->', $request->getUri(), is_null($view->getEngine()->getEnvironmentInfo()->getEnvironment()) ? '' : sprintf(' :: %s environment', $view->getEngine()->getEnvironmentInfo()->getEnvironment()), $userManager->isLoggedIn() ? 'logged in as ' . ($userManager->getLoggedInUserEmail() ?: 'guest') : 'not logged in', $renderTime, PHP_EOL, $view->getEngine()->getApplicationInfo()->getSitegearHomepage(), $version, $this->formatNow());
     LoggerRegistry::log($this->logLevel(), '{pathInfo} {renderTime} by {version}', array('pathInfo' => $request->getPathInfo(), 'renderTime' => $renderTime, 'version' => $version));
     return $content . $comment . PHP_EOL;
 }
Beispiel #9
0
 /**
  * @inheritdoc
  */
 public function load($args)
 {
     LoggerRegistry::debug('PhpFileLoader::load({args})', array('args' => TypeUtilities::describe($args)));
     if (!$this->supports($args)) {
         throw new \InvalidArgumentException(sprintf('PhpFileLoader attempting to load unsupported config file "%s".', $args));
     }
     /** @noinspection PhpIncludeInspection */
     return require $args;
 }
Beispiel #10
0
 /**
  * @inheritdoc
  */
 public function render($path, ViewInterface $view)
 {
     LoggerRegistry::debug('RendererRegistry::render({path}, [view])', array('path' => TypeUtilities::describe($path)));
     $result = null;
     foreach ($this->registry as $renderer) {
         /** @var \Sitegear\View\Renderer\RendererInterface $renderer */
         if (is_null($result) && $renderer->supports($path)) {
             $result = $renderer->render($path, $view);
         }
     }
     return $result;
 }
 /**
  * Perform standard rendering.  This event only fires if the previous (REQUEST) event did not generate a response.
  *
  * @param \Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent $event
  */
 public function onKernelView(GetResponseForControllerResultEvent $event)
 {
     LoggerRegistry::debug('EngineRendererListener performing render() on VIEW event');
     $request = $event->getRequest();
     $path = explode(':', $request->attributes->get('_route'));
     // Set the module attribute.
     $request->attributes->set('_module', $path[0]);
     // Use either the controller result or the 'natural' name of the view based on the route specifier.
     $request->attributes->set('_view', is_null($event->getControllerResult()) ? $path[1] : $event->getControllerResult());
     // Let the engine render the response and add instrumentation headers; set back to the event.
     $response = $this->getEngine()->renderPage($request);
     $event->setResponse($this->getEngine()->instrumentResponse($response));
 }
Beispiel #12
0
 /**
  * @inheritdoc
  */
 public function render($path, ViewInterface $view)
 {
     LoggerRegistry::debug('PhpRenderer::render({path}, [view])', array('path' => TypeUtilities::describe($path)));
     $renderPath = null;
     foreach ($this->getExtensions() as $extension) {
         if (is_null($renderPath) && file_exists($path . $extension)) {
             $renderPath = $path . $extension;
         }
     }
     if (is_null($renderPath)) {
         throw new \InvalidArgumentException(sprintf('The path "%s" cannot be rendered by PhpRenderer', $path));
     }
     return PhpRendererEvaluationSandbox::render($renderPath, $view);
 }
 /**
  * @inheritdoc
  */
 public function checkCredentials($email, array $credentials)
 {
     LoggerRegistry::debug('PlainTextPasswordAuthenticator::checkCredentials({email}, [credentials])', array('email' => TypeUtilities::describe($email)));
     if (!isset($credentials['password'])) {
         throw new \InvalidArgumentException('PlainTextPasswordAuthenticator expects "password" credential key, insufficient credentials supplied.');
     }
     $result = null;
     if ($this->getStorage()->hasUser($email)) {
         $data = $this->getStorage()->getData($email);
         if (isset($data['password']) && $data['password'] === $credentials['password']) {
             $result = $email;
         }
     }
     return $result;
 }
 /**
  * @inheritdoc
  */
 public function guess($path)
 {
     LoggerRegistry::debug('ExtensionMimeTypeGuesser::guess({path})', array('path' => TypeUtilities::describe($path)));
     if (!is_file($path)) {
         throw new FileNotFoundException($path);
     }
     if (!is_readable($path)) {
         throw new AccessDeniedException($path);
     }
     if (empty($this->data)) {
         throw new \LogicException('The data file could not be loaded or contains no data');
     }
     $extension = pathinfo($path, PATHINFO_EXTENSION);
     return is_string($extension) && isset($this->data[$extension]) ? $this->data[$extension] : null;
 }
 /**
  * Start the engine and bootstrap the modules specified by the engine's bootstrap sequence.
  *
  * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
  *
  * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
  * @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
  */
 public function onKernelRequest(GetResponseEvent $event)
 {
     LoggerRegistry::debug('EngineBootstrapListener responding to REQUEST kernel event');
     // Start the engine.
     $request = $event->getRequest();
     /** @var \Symfony\Component\HttpFoundation\Request $request */
     $response = $this->getEngine()->start($request);
     if (!is_null($response)) {
         // Set the response directly; prevent further processing.
         $this->getEngine()->instrumentResponse($response);
         $event->setResponse($response);
         $event->stopPropagation();
         LoggerRegistry::debug('EngineBootstrapListener received Response from bootstrap');
     }
 }
 /**
  * @inheritdoc
  */
 public function resourceController(Request $request)
 {
     LoggerRegistry::debug('ResourcesIntegrationModule::resourceController()');
     $location = $request->attributes->get('location');
     switch ($location) {
         case self::LOCATION_ATTRIBUTE_ENGINE:
             $path = $this->getEngine()->getSiteInfo()->getPublicPath(ResourceLocations::RESOURCE_LOCATION_ENGINE, $request->attributes->get('path'));
             break;
         case self::LOCATION_ATTRIBUTE_VENDOR:
             $path = $this->getEngine()->getSiteInfo()->getPublicPath(ResourceLocations::RESOURCE_LOCATION_VENDOR, $request->attributes->get('path'));
             break;
         default:
             $path = $this->getEngine()->getSiteInfo()->getPublicPath(ResourceLocations::RESOURCE_LOCATION_MODULE, $request->attributes->get('path'), $this->getEngine()->getModule($location));
     }
     if (!file_exists($path)) {
         throw new FileNotFoundException($path);
     }
     return $this->getEngine()->createFileResponse($request, $path);
 }
 /**
  * Handle exceptions that occur during the request handling process.
  *
  * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
  *
  * @throws \Exception|\Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException|\Symfony\Component\HttpKernel\Exception\HttpException
  *   As a fallback behaviour only, if a sensible error page cannot be generated.
  */
 public function onKernelException(GetResponseForExceptionEvent $event)
 {
     LoggerRegistry::debug('EngineExceptionListener performing handleException() on EXCEPTION event');
     $exception = $event->getException();
     try {
         // Delete any buffered page content.
         while (ob_get_level() > 1) {
             ob_end_clean();
         }
         // Determine the status code to use for the error page (and which error page is displayed).
         $statusCode = $exception instanceof HttpException ? $exception->getStatusCode() : ($exception instanceof FileNotFoundException ? 404 : 500);
         // Set route and template attributes to error page defaults.
         $event->getRequest()->attributes->add(array('_status' => $statusCode, '_route' => $this->getEngine()->getErrorRoute($statusCode), '_route_params' => array('exception' => $exception, 'statusCode' => $statusCode), '_template' => $this->getEngine()->getErrorTemplate()));
         // Store the exception and status code in the top-level view data.
         $page = $this->getEngine()->getViewFactory()->getPage();
         $page['exception'] = $exception;
         $page['status-code'] = $statusCode;
         // Perform standard rendering using a proxy event.
         $renderer = new EngineRendererListener($this->getEngine());
         $viewScript = sprintf('error-%3d', $statusCode);
         // TODO Handle view scripts that don't exist, default back to 500 or 404
         $renderEvent = new GetResponseForControllerResultEvent($event->getKernel(), $event->getRequest(), HttpKernelInterface::SUB_REQUEST, $viewScript);
         $renderer->onKernelView($renderEvent);
         // Copy the response from the proxy event back to the event being handled.
         $event->setResponse($renderEvent->getResponse());
     } catch (\Exception $e) {
         try {
             // Delete any buffered page content.
             while (ob_get_level() > 1) {
                 ob_end_clean();
             }
             // If there is an error above, try to display the fallback error page, i.e. black-and-white error
             // message.
             $event->setResponse(Response::create(HtmlUtilities::exception($exception, $this->getEngine()->getSiteInfo()->getAdministratorName(), $this->getEngine()->getSiteInfo()->getAdministratorEmail())));
         } catch (\Exception $e2) {
             // If another error occurs, the best thing to do is throw the original error.
             throw $exception;
         }
     }
 }
Beispiel #18
0
 /**
  * @param \Sitegear\Engine\EngineInterface $engine Container.
  */
 public function __construct(EngineInterface $engine)
 {
     LoggerRegistry::debug('new AbstractModule()');
     $this->engine = $engine;
 }
 /**
  * @inheritdoc
  */
 public function checkCredentials($email, array $credentials)
 {
     LoggerRegistry::debug('SaltedPasswordAuthenticator::checkCredentials({email}, [credentials])', array('email' => TypeUtilities::describe($email)));
     // TODO Implement me
     throw new \InvalidArgumentException('Not implemented');
 }
Beispiel #20
0
 /**
  * @inheritdoc
  */
 public function clearTargets()
 {
     LoggerRegistry::debug('AbstractView::clearTargets()');
     $this->targets = array();
     return $this;
 }
Beispiel #21
0
 /**
  * Show a componentised view of the latest headlines.
  *
  * @param \Sitegear\View\ViewInterface $view
  * @param int|null $itemLimit Number of items to display, or null to use the value from the configuration.
  * @param int|null $excerptLength Number of characters of the news item text to display in each preview, or null to
  *   use the value from the configuration.
  * @param string|null $readMore Text to use for "read more" links
  */
 public function latestHeadlinesComponent(ViewInterface $view, $itemLimit = null, $excerptLength = null, $readMore = null)
 {
     LoggerRegistry::debug('NewsModule::latestHeadlinesComponent([view], %d, %d, %s)', array('itemLimit' => TypeUtilities::describe($itemLimit), 'excerptLength' => TypeUtilities::describe($excerptLength), 'readMore' => TypeUtilities::describe($readMore)));
     $itemLimit = intval(!is_null($itemLimit) ? $itemLimit : $this->config('component.latest-headlines.item-limit'));
     $view['items'] = $this->getRepository('Item')->findLatestItems($itemLimit);
     $view['date-format'] = $this->config('component.latest-headlines.date-format');
     $view['excerpt-length'] = !is_null($excerptLength) ? $excerptLength : $this->config('component.latest-headlines.excerpt-length');
     if ($readMore) {
         $view['read-more'] = $readMore;
     }
 }
Beispiel #22
0
 /**
  * Instantiate a module instance for this engine.
  *
  * @param string $name Module to load.
  *
  * @return \Sitegear\Module\ModuleInterface
  *
  * @throws \InvalidArgumentException If the named module does not exist.
  * @throws \DomainException If the named module does not implement ModuleInterface.
  */
 protected function createModule($name)
 {
     LoggerRegistry::debug('AbstractEngine::createModule({name})', array('name' => TypeUtilities::describe($name)));
     try {
         return TypeUtilities::buildTypeCheckedObject($this->getModuleClassName($name) ?: '', 'module', null, '\\Sitegear\\Module\\ModuleInterface', array($this));
     } catch (\DomainException $e) {
         throw new \InvalidArgumentException(sprintf('AbstractEngine cannot create module "%s" because it does not exist', $name), 0, $e);
     }
 }
 /**
  * Apply all children of the given config key from this module, as values stored in the given view.  This is a
  * handy shortcut for making all the top-level configuration items available to the view without requiring an
  * additional parent key.
  *
  * @param string $configKey
  * @param \Sitegear\View\ViewInterface $view
  */
 protected function applyConfigToView($configKey, ViewInterface $view)
 {
     LoggerRegistry::debug('AbstractConfigurableModule::applyConfigToView({configKey}, [view])', array('configKey' => TypeUtilities::describe($configKey)));
     if (is_array($config = $this->config($configKey))) {
         foreach ($config as $key => $value) {
             $view[$key] = $value;
         }
     }
 }
Beispiel #24
0
 /**
  * @inheritdoc
  */
 public function save($selector, $value)
 {
     LoggerRegistry::debug('DoctrineModule::save({selector}, {value})', array('selector' => TypeUtilities::describe($selector), 'value' => TypeUtilities::describe($value)));
     $selector = $this->parseSelector($selector);
     $query = $this->getEntityManager()->createQuery(sprintf('update %s%s item set item.%s = :value where item.%s = :match', $selector['entity-alias'], $selector['entity-name'], $selector['value-field-name'], $selector['match-field-name']));
     $query->setParameter('value', $value);
     $query->setParameter('match', $selector['match-field-value']);
     return $query->execute() !== false;
 }
Beispiel #25
0
 /**
  * Display a form.
  *
  * @param \Sitegear\View\ViewInterface $view
  * @param \Symfony\Component\HttpFoundation\Request $request
  * @param string $formKey Unique key of the form, used for session storage and also is the key used to retrieve the
  *   form data, if it is not supplied directly.
  * @param array|null $values Values to set manually into the form before displaying it.  Note this is used for
  *   rendering the form only, these values are not set into the session.  These values are merged into the values
  *   currently stored in the session (these values take precedence).
  * @param array[]|null $errors Errors to set manually into the form before displaying it.  These errors are merged
  *   into the errors currently stored in the session (these errors take precedence).
  */
 public function formComponent(ViewInterface $view, Request $request, $formKey, array $values = null, array $errors = null)
 {
     LoggerRegistry::debug('FormsModule::formComponent()');
     // Retrieve the form object.
     $form = $this->registry()->getForm($formKey, $request);
     // Disable the back button if the previous step is not available.
     $currentStep = $this->registry()->getCurrentStep($formKey);
     $availableSteps = $this->registry()->getAvailableSteps($formKey);
     if (!in_array($currentStep - 1, $availableSteps) && is_array($form->getBackButtonAttributes())) {
         $form->setBackButtonAttributes(array_merge($form->getBackButtonAttributes(), array('disabled' => 'disabled')));
     }
     // Setup the view.
     $view['form-renderer'] = $this->createRendererFactory()->createFormRenderer($form, $currentStep);
     // TODO Something better here
     $view['form-renderer']->setRenderOption('attributes', ArrayUtilities::mergeHtmlAttributes(array('id' => $formKey . '-form'), $view['form-renderer']->getRenderOption('attributes')));
     $view['values'] = array_merge($this->registry()->getValues($formKey), $values ?: array());
     $view['errors'] = array_merge($this->registry()->getErrors($formKey), $errors ?: array());
     // Remove errors as they are about to be displayed (they are already set in the view), and we don't want to
     // show the same errors again.
     $this->registry()->clearErrors($formKey);
 }
 /**
  * @param string|null $environment
  */
 public function __construct($environment = null)
 {
     LoggerRegistry::debug('new SitegearEnvironmentInfoProvider({environment})', array('environment' => TypeUtilities::describe($environment)));
     $this->environment = $environment;
 }
Beispiel #27
0
 /**
  * The location search form.
  *
  * @param ViewInterface $view
  * @param string|null $query Previous query, to populate the value.
  * @param string|null $radius Previous radius selection, to populate the selected option.
  */
 public function searchFormComponent(ViewInterface $view, $query = null, $radius = null)
 {
     LoggerRegistry::debug('LocationsModule::searchFormComponent([view], {query}, {radius})', array('query' => TypeUtilities::describe($query), 'radius' => TypeUtilities::describe($radius)));
     $view['action-url'] = $this->getRouteUrl('search');
     if (!is_null($query)) {
         $view['query'] = $query;
     }
     if (!is_null($radius)) {
         $view['radius'] = $radius;
     }
 }
Beispiel #28
0
 /**
  * Loa the data from the given location, according to any available loaders.
  *
  * If the given argument is a filename, also load the relevant environment-specific override file.
  *
  * @param array|string|\ArrayObject|\Sitegear\Config\Configuration $config Configuration data, filename or
  *   configuration object.
  *
  * @return array Loaded data.
  *
  * @throws \InvalidArgumentException If the given argument is not a string or an array.
  */
 public function load($config)
 {
     LoggerRegistry::debug('ConfigLoader::load({config})', array('config' => TypeUtilities::describe($config)));
     $result = $this->normalise($config);
     if (is_string($config) && !is_null($this->environmentInfo) && !is_null($this->environmentInfo->getEnvironment())) {
         $pathinfo = pathinfo($config);
         $dirname = array_key_exists('dirname', $pathinfo) ? strval($pathinfo['dirname']) : '';
         $filename = array_key_exists('filename', $pathinfo) ? strval($pathinfo['filename']) : '';
         $extension = array_key_exists('extension', $pathinfo) ? strval($pathinfo['extension']) : '';
         $envFilename = sprintf('%s/%s.%s.%s', $dirname, $filename, $this->environmentInfo->getEnvironment(), $extension);
         $envConfig = $this->loadFile($envFilename);
         $result = ArrayUtilities::combine($result, $envConfig);
     }
     return $result;
 }
 /**
  * @inheritdoc
  */
 protected function buildRoutes()
 {
     LoggerRegistry::debug('{class}::buildRoutes(), mounted to "{mountedUrl}"', array('class' => (new \ReflectionClass($this))->getShortName(), 'mountedUrl' => $this->getMountedUrl()));
     $routes = new RouteCollection();
     // Check for an index controller and add a route for the module root.
     if ((new \ReflectionObject($this))->hasMethod('indexController')) {
         $routes->add('index', new Route($this->getMountedUrl()));
     }
     // Load routes from file.
     $filename = sprintf('%s/%s/%s', $this->getModuleRoot(), ResourceLocations::RESOURCES_DIRECTORY, self::FILENAME_ROUTES);
     $container = new Configuration($this->getConfigLoader());
     $container->merge($filename);
     // Add a route for each record in the routes file.
     foreach ($container->all() as $name => $parameters) {
         $defaults = array();
         $requirements = array();
         $options = array();
         $path = sprintf('%s/%s', $this->getMountedUrl(), $this->config(sprintf('routes.%s', $name), $name));
         foreach ($parameters ?: array() as $parameter) {
             $parameterName = $parameter['name'];
             $path = sprintf('%s/{%s}', $path, $parameterName);
             if (isset($parameter['default'])) {
                 $defaults[$parameterName] = $parameter['default'];
             }
             if (isset($parameter['requirements'])) {
                 $requirements[$parameterName] = $parameter['requirements'];
             }
             if (isset($parameter['options'])) {
                 $options[$parameterName] = $parameter['options'];
             }
         }
         $routes->add($name, new Route($path, $defaults, $requirements, $options));
     }
     return $routes;
 }
Beispiel #30
0
 /**
  * @inheritdoc
  */
 public function render()
 {
     LoggerRegistry::debug('View::render()');
     $content = null;
     $this->rendering = true;
     if ($this->getTargetCount() === 2) {
         $request = $this->getRequest();
         // The arguments to the module definition are decorators, set them now
         call_user_func_array(array($this, 'activateDecorators'), $this->getTargetArguments(self::TARGET_LEVEL_MODULE));
         // Create a relevant context
         $context = $this->getEngine()->getViewFactory()->buildViewContext($this, $this->getRequest());
         // Check for and execute a target controller
         $targetController = $context->getTargetController($this, $request);
         $targetControllerResult = null;
         if (!is_null($targetController) && is_callable($targetController)) {
             $targetControllerResult = TypeUtilities::invokeCallable($targetController, null, array($this, $request), $this->getTargetArguments(self::TARGET_LEVEL_METHOD) ?: array());
         }
         // A result of false means don't render anything.
         if ($targetControllerResult !== false) {
             // Use the context to render the result
             $content = $context->render($this->getEngine()->getViewFactory()->getRendererRegistry(), $targetControllerResult) ?: '';
             // Decorate using active decorators
             foreach ($this->getActiveDecorators() as $active) {
                 $decorator = $this->getEngine()->getViewFactory()->getDecoratorRegistry()->getDecorator($active['name']);
                 $content = TypeUtilities::invokeCallable(array($decorator, 'decorate'), array($content), array($this, $request), $active['arguments']);
             }
         }
     } else {
         // Incorrect number of targets; exactly 2 expected
         $targets = $this->getTargetCount() === 1 ? 'target' : 'targets';
         throw new \LogicException(sprintf('Error in view script; exactly 2 targets expected ("$view->module()->method()"); %d %s encountered', $this->getTargetCount(), $targets));
     }
     // Ensure we are returning a string value
     $this->rendering = false;
     return $content ?: '';
 }