Example #1
0
 public function appendTo(SymphonyDOMElement $wrapper)
 {
     $this->layout->setAttribute('class', $this->class);
     ###
     # Delegate: LayoutPreGenerate
     # Description: Allows developers to access the layout content
     #			   before it is appended to the page.
     Extension::notify('LayoutPreGenerate', '/administration/', $this->layout);
     if ($wrapper->tagName == 'form') {
         $this->layout->setAttribute('id', 'layout');
     }
     $wrapper->appendChild($this->layout);
 }
Example #2
0
 public function render(Register $Parameters, XMLDocument &$Document = NULL, DocumentHeaders &$Headers = NULL)
 {
     $ParameterOutput = new Register();
     if (!is_null($Headers)) {
         $Headers->append('Content-Type', $this->{'content-type'});
     } else {
         header('Content-Type: ' . $this->{'content-type'});
     }
     if (is_null($Document)) {
         $Document = new XMLDocument();
         $Document->appendChild($Document->createElement('data'));
     }
     $root = $Document->documentElement;
     $datasources = $events = array();
     $events_wrapper = $Document->createElement('events');
     $root->appendChild($events_wrapper);
     if (is_array($this->about()->{'events'}) && !empty($this->about()->{'events'})) {
         $events = $this->about()->{'events'};
     }
     if (is_array($this->about()->{'data-sources'}) && !empty($this->about()->{'data-sources'})) {
         $datasources = $this->about()->{'data-sources'};
     }
     ####
     # Delegate: FrontendEventsAppend
     # Description: Append additional Events.
     # Global: Yes
     Extension::notify('FrontendEventsAppend', '/frontend/', array('events' => &$events));
     if (!empty($events)) {
         $postdata = General::getPostData();
         $events_ordered = array();
         foreach ($events as $handle) {
             $events_ordered[] = Event::loadFromHandle($handle);
         }
         uasort($events_ordered, array($this, '__cbSortEventsByPriority'));
         foreach ($events_ordered as $e) {
             if (!$e->canTrigger($postdata)) {
                 continue;
             }
             $fragment = $e->trigger($ParameterOutput, $postdata);
             if ($fragment instanceof DOMDocument && !is_null($fragment->documentElement)) {
                 $node = $Document->importNode($fragment->documentElement, true);
                 $events_wrapper->appendChild($node);
             }
         }
     }
     ####
     # Delegate: FrontendDataSourceAppend
     # Description: Append additional DataSources.
     # Global: Yes
     Extension::notify('FrontendDataSourcesAppend', '/frontend/', array('datasources' => &$datasources));
     //	Find dependancies and order accordingly
     $datasource_pool = array();
     $dependency_list = array();
     $datasources_ordered = array();
     $all_dependencies = array();
     foreach ($datasources as $handle) {
         $datasource_pool[$handle] = Datasource::loadFromHandle($handle);
         $dependency_list[$handle] = $datasource_pool[$handle]->parameters()->dependencies;
     }
     $datasources_ordered = $this->__sortByDependencies($dependency_list);
     if (!empty($datasources_ordered)) {
         foreach ($datasources_ordered as $handle) {
             $ds = $datasource_pool[$handle];
             try {
                 $fragment = $ds->render($ParameterOutput);
             } catch (FrontendPageNotFoundException $e) {
                 FrontendPageNotFoundExceptionHandler::render($e);
             }
             if ($fragment instanceof DOMDocument && !is_null($fragment->documentElement)) {
                 $node = $Document->importNode($fragment->documentElement, true);
                 $root->appendChild($node);
             }
         }
     }
     if ($ParameterOutput->length() > 0) {
         foreach ($ParameterOutput as $p) {
             $Parameters->{$p->key} = $p->value;
         }
     }
     ####
     # Delegate: FrontendParamsPostResolve
     # Description: Access to the resolved param pool, including additional parameters provided by Data Source outputs
     # Global: Yes
     Extension::notify('FrontendParamsPostResolve', '/frontend/', array('params' => $Parameters));
     $element = $Document->createElement('parameters');
     $root->appendChild($element);
     foreach ($Parameters as $key => $parameter) {
         if (is_array($parameter->value) && count($parameter->value) > 1) {
             $p = $Document->createElement($key);
             $p->setAttribute('value', (string) $parameter);
             foreach ($parameter->value as $v) {
                 $p->appendChild($Document->createElement('item', (string) $v));
             }
             $element->appendChild($p);
         } else {
             $element->appendChild($Document->createElement($key, (string) $parameter));
         }
     }
     $template = $this->template;
     ####
     # Delegate: FrontendTemplatePreRender
     # Description: Access to the template source, before it is rendered.
     # Global: Yes
     Extension::notify('FrontendTemplatePreRender', '/frontend/', array('document' => $Document, 'template' => &$template));
     $this->template = $template;
     // When the XSLT executes, it uses the CWD as set here
     $cwd = getcwd();
     chdir(WORKSPACE);
     $output = XSLProc::transform($Document, $this->template, XSLProc::XML, $Parameters->toArray(), array());
     chdir($cwd);
     if (XSLProc::hasErrors()) {
         throw new XSLProcException('Transformation Failed');
     }
     /*
     header('Content-Type: text/plain; charset=utf-8');
     $Document->formatOutput = true;
     print $Document->saveXML();
     die();
     */
     return $output;
 }
 public function action()
 {
     if (isset($_POST['items'])) {
         $checked = array_keys($_POST['items']);
     }
     try {
         if (isset($_POST['action']['apply']) && isset($_POST['with-selected']) && is_array($checked) && !empty($checked)) {
             $action = $_POST['with-selected'];
             if (method_exists('Extension', $action)) {
                 ###
                 # Delegate: {name of the action} (enable|disable|uninstall)
                 # Description: Notifies of enabling, disabling or uninstalling of an Extension. Array of selected extensions is provided.
                 #              This can be modified.
                 Extension::notify($action, getCurrentPage(), array('extensions' => &$checked));
                 foreach ($checked as $handle) {
                     call_user_func(array('Extension', $action), $handle);
                 }
             }
             redirect(Administration::instance()->getCurrentPageURL());
         } elseif (isset($_POST['action'])) {
             $action = end(array_keys($_POST['action']));
             $handle = end(array_keys($_POST['action'][$action]));
             if (method_exists('Extension', $action)) {
                 ###
                 # Delegate: {name of the action} (enable|disable|uninstall)
                 # Description: Notifies of enabling, disabling or uninstalling of an Extension. Extension handle is provided
                 #              This can be modified.
                 Extension::notify($action, getCurrentPage(), array('extensions' => &$handle));
                 call_user_func(array('Extension', $action), $handle);
                 redirect(Administration::instance()->getCurrentPageURL());
             }
         }
     } catch (ExtensionException $e) {
         $extension = Extension::load($handle);
         $about = $extension->about();
         switch ($action) {
             case 'enable':
                 $message = "%s could not be enabled. <a class='more'>Show more information.</a>";
                 break;
             case 'disable':
                 $message = "%s could not be disabled. <a class='more'>Show more information.</a>";
                 break;
             case 'uninstall':
                 $message = "%s could not be uninstalled. <a class='more'>Show more information.</a>";
                 break;
         }
         $this->alerts()->append(__($message, array(isset($about) ? $about->{'name'} : $name)), AlertStack::ERROR, $e);
         return false;
     }
 }
 protected function login(MessageStack $errors, Register $parameter_output, array $data)
 {
     $section = Section::loadFromHandle($this->parameters()->{'section'});
     $wheres = array();
     $joins = null;
     // Find fields:
     foreach ($section->fields as $field) {
         if ($field instanceof FieldMemberName) {
             $field_name = $field;
             $handle_name = $field->{'element-name'};
         } else {
             if ($field instanceof FieldMemberEmail) {
                 $field_email = $field;
                 $handle_email = $field->{'element-name'};
             } else {
                 if ($field instanceof FieldMemberPassword) {
                     $field_password = $field;
                     $handle_password = $field->{'element-name'};
                 }
             }
         }
     }
     if (!isset($field_email) or !isset($field_password)) {
         throw new Exception(__('Section does not contain required fields.'));
     }
     // Simulate data from cookie:
     if (empty($data) and $this->readSession()) {
         $session = $this->readSession();
         $fields = array($field_email->{'element-name'} => $session->email, $field_password->{'element-name'} => $session->login);
     } else {
         $this->deleteSession();
         $fields = $data['fields'];
     }
     // Apply default values:
     foreach ($this->parameters()->{'defaults'} as $name => $value) {
         if (!isset($fields[$name])) {
             $fields[$name] = $value;
         } else {
             if (is_string($fields[$name]) and $fields[$name] == '') {
                 $fields[$name] = $value;
             } else {
                 if (is_array($fields[$name]) and empty($fields[$name])) {
                     $fields[$name] = array($value);
                 }
             }
         }
     }
     // Apply override values:
     foreach ($this->parameters()->{'overrides'} as $name => $value) {
         if (is_array($fields[$name])) {
             $fields[$name] = array($value);
         } else {
             $fields[$name] = $value;
         }
     }
     // Find values:
     if (isset($field_name)) {
         $value_name = (isset($fields[$handle_name]) and strlen($fields[$handle_name]) > 0) ? $fields[$handle_name] : null;
     }
     if (isset($field_email)) {
         $value_email = (isset($fields[$handle_email]) and strlen($fields[$handle_email]) > 0) ? $fields[$handle_email] : null;
     }
     if (isset($field_password)) {
         $value_password = (isset($fields[$handle_password]) and strlen($fields[$handle_password]) > 0) ? $fields[$handle_password] : null;
     }
     if (is_null($value_email) and is_null($value_name) or is_null($value_password)) {
         throw new Exception(__('Missing login credentials.'));
     }
     // Build query:
     $where_password = array();
     $value_password = array('value' => $value_password, 'type' => 'is');
     $field_password->buildFilterQuery($value_password, $joins, $where_password, $parameter_output);
     if (isset($field_email) and !is_null($value_email)) {
         $where_email = $where_password;
         $value_email = array('value' => $value_email, 'type' => 'is');
         $field_email->buildFilterQuery($value_email, $joins, $where_email, $parameter_output);
         $wheres[] = '(' . implode("\nAND ", $where_email) . ')';
     }
     if (isset($field_name) and !is_null($value_name)) {
         $where_name = $where_password;
         $value_name = array('value' => $value_name, 'type' => 'is');
         $field_name->buildFilterQuery($value_name, $joins, $where_name, $parameter_output);
         $wheres[] = '(' . implode("\nAND ", $where_name) . ')';
     }
     array_unshift($wheres, null);
     $wheres = implode("\nOR ", $wheres);
     $query = "\nSELECT DISTINCT\n\te.*\nFROM\n\t`tbl_entries` AS e{$joins}\nWHERE\n\tFALSE{$wheres}\n\t\t\t";
     //echo '<pre>', htmlentities($query), '</pre>'; exit;
     // Find entry:
     $result = Symphony::Database()->query($query, array(), 'EntryResult');
     if (!$result->valid()) {
         throw new Exception(__('Invalid login credentials.'));
     }
     $entry = $result->current();
     $email = $entry->data()->{$handle_email}->value;
     $code = $entry->data()->{$handle_password}->code;
     $login = $this->driver->createToken($code, 'login');
     if ($this->parameters()->{'create-cookie'} == true) {
         $this->writeCookie($login, $email);
     }
     $event_name = $this->parameters()->{'root-element'};
     $parameter_output->{"event-{$event_name}.system.id"} = $entry->id;
     $parameter_output->{"event-{$event_name}.member.email"} = $email;
     $parameter_output->{"event-{$event_name}.member.login"} = $login;
     // Remove login fields:
     unset($fields[$handle_name], $fields[$handle_email], $fields[$handle_password]);
     // Set password as optional:
     $fields[$handle_password] = array('validate' => array('optional' => $this->driver->createToken($code, 'validate')), 'change' => array('optional' => $this->driver->createToken($code, 'change')));
     // Update fields:
     $entry->setFieldDataFromFormArray($fields);
     ###
     # Delegate: EntryPreCreate
     # Description: Just prior to creation of an Entry. Entry object provided
     Extension::notify('EntryPreCreate', '/frontend/', array('entry' => &$entry));
     $status = Entry::save($entry, $errors);
     if ($status != Entry::STATUS_OK) {
         throw new Exception(__('Entry encountered errors when saving.'));
     }
     ###
     # Delegate: EntryPostCreate
     # Description: Creation of an Entry. New Entry object is provided.
     Extension::notify('EntryPostCreate', '/frontend/', array('entry' => $entry));
 }
 public function __actionIndex()
 {
     if (!is_writable(CONF)) {
         return;
     }
     if (isset($_POST['action']['save'])) {
         $settings = $_POST['settings'];
         ###
         # Delegate: Save
         # Description: Saving of system preferences.
         Extension::notify('Save', '/system/settings/', array('settings' => &$settings, 'errors' => &$this->errors));
         // Site name
         if (strlen(trim($settings['symphony']['sitename'])) == 0) {
             $this->errors->append('symphony::sitename', __("'%s' is a required field.", array('Site Name')));
         }
         // Date format
         // TODO: Figure out a way to check date formats to ensure they are valid
         if (strlen(trim($settings['region']['date-format'])) == 0) {
             $this->errors->append('region::date-format', __("'%s' is a required field.", array('Date Format')));
         }
         //elseif(!date_parse(DateTimeObj::get($settings['region']['date-format'] . 'H:m:s'))){
         //	$this->errors->append('region::date-format', __("Invalid date format specified."));
         //}
         // Time format
         // TODO: Figure out a way to check time formats to ensure they are valid
         if (strlen(trim($settings['region']['time-format'])) == 0) {
             $this->errors->append('region::time-format', __("'%s' is a required field.", array('Time Format')));
         }
         //elseif(!date_parse(DateTimeObj::get('Y-m-d' . $settings['region']['time-format']))){
         //	$this->errors->append('region::time-format', __("Invalid time format specified."));
         //}
         if ($this->errors->length() <= 0) {
             if (is_array($settings) && !empty($settings)) {
                 foreach ($settings as $set => $values) {
                     foreach ($values as $key => $val) {
                         Symphony::Configuration()->core()->{$set}->{$key} = $val;
                     }
                 }
             }
             Symphony::Configuration()->save();
             redirect(ADMIN_URL . '/system/settings/:saved/');
         } else {
             $this->alerts()->append(__('An error occurred while processing this form. <a href="#error">See below for details.</a>'), AlertStack::ERROR, $this->errors);
         }
     }
 }
Example #6
0
 private function __save(Role $role)
 {
     $fields = $_POST['fields'];
     $role->name = $fields['name'];
     $role->description = $fields['description'];
     $role->flushPermissions();
     foreach ($fields['permissions'] as $key => $p) {
         foreach ($p as $type => $level) {
             $role->permissions()->{"{$key}.{$type}"} = (int) $level;
         }
     }
     ###
     # Delegate: AACRolePreCreate
     # Description: Just before creation of a new Role. Role object, fields array and error stack provided
     Extension::notify('AACRolePreCreate', '/extension/aac/roles/new/', array('fields' => $fields, 'role' => &$role, 'errors' => &$this->errors));
     $this->role = $role;
     try {
         $result = Role::save($this->role, $this->errors);
         if (!isset($this->role->id)) {
             $this->role->id = $result;
         }
         ###
         # Delegate: AACRolePostCreate
         # Description: After creation of a new Role. Role object provided
         Extension::notify('AACRolePostCreate', '/extension/aac/roles/new/', array('role' => $this->role));
         redirect(sprintf("%s/extension/aac/roles/edit/%d/:%s/", ADMIN_URL, $this->role->id, isset($role->id) ? 'saved' : 'created'));
     } catch (RoleException $e) {
         $this->alerts()->append(__('There were some problems while attempting to save. Please check below for problem fields.'), AlertStack::ERROR, $this->errors);
     } catch (Exception $e) {
         $this->alerts()->append(__('An unknown error has occurred. <a class="more">Show trace information.</a>'), AlertStack::ERROR, $e);
     }
 }
 public function __actionDelete(array $sections, $redirect)
 {
     $success = true;
     $callback = Administration::instance()->getPageCallback();
     $current_page = $callback['pageroot'] . (isset($callback['context'][0]) && $callback['context'][0] != 'index' ? $callback['context'][0] . '/' : NULL);
     foreach ($sections as $handle) {
         try {
             Section::delete(Section::loadFromHandle($handle));
             ###
             # Delegate: SectionPostDelete
             Extension::notify('SectionPostDelete', $current_page, array('handle' => $handle));
         } catch (SectionException $e) {
             $success = false;
             $this->alerts()->append($e->getMessage(), AlertStack::ERROR, $e);
         } catch (Exception $e) {
             $success = false;
             $this->alerts()->append(__('An unknown error has occurred. <a class="more">Show trace information.</a>'), AlertStack::ERROR, $e);
         }
     }
     if ($success) {
         redirect($redirect);
     }
 }
 public function display($url = NULL)
 {
     self::$Parameters = new Register();
     // Default headers. Can be overwritten later
     //self::$Headers->append('HTTP/1.0 200 OK');
     self::$Headers->append('Content-Type', 'text/html;charset=utf-8');
     self::$Headers->append('Expires', 'Mon, 12 Dec 1982 06:14:00 GMT');
     self::$Headers->append('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT');
     self::$Headers->append('Cache-Control', 'no-cache, must-revalidate, max-age=0');
     self::$Headers->append('Pragma', 'no-cache');
     ####
     # Delegate: FrontendPreInitialise
     # Description: TODO
     # Global: Yes
     Extension::notify('FrontendPreInitialise', '/frontend/', array('view' => &self::$view, 'url' => &$url));
     if (!self::$view instanceof View) {
         $this->resolve($url);
     }
     ####
     # Delegate: FrontendPostInitialise
     Extension::notify('FrontendPostInitialise', '/frontend/', array('view' => &self::$view));
     // SETTING UP PARAMETERS --------------------------
     $root_page = array_shift(explode('/', self::$view->parent()->path));
     $current_path = explode(dirname($_SERVER['SCRIPT_NAME']), $_SERVER['REQUEST_URI'], 2);
     $current_path = '/' . ltrim(end($current_path), '/');
     self::$Parameters->register(array('today' => DateTimeObj::get('Y-m-d'), 'current-time' => DateTimeObj::get('H:i'), 'this-year' => DateTimeObj::get('Y'), 'this-month' => DateTimeObj::get('m'), 'this-day' => DateTimeObj::get('d'), 'timezone' => date_default_timezone_get(), 'website-name' => Symphony::Configuration()->core()->symphony->sitename, 'symphony-version' => Symphony::Configuration()->core()->symphony->version, 'upload-limit' => min(ini_size_to_bytes(ini_get('upload_max_filesize')), Symphony::Configuration()->core()->symphony->{'maximum-upload-size'}), 'root' => URL, 'workspace' => URL . '/workspace', 'page-title' => self::$view->title, 'root-page' => !is_null($root_page) ? $root_page : self::$view->handle, 'current-page' => self::$view->handle, 'current-path' => $current_path, 'parent-path' => '/' . self::$view->path, 'current-url' => URL . $current_path));
     if (isset(self::$view->{'url-parameters'}) && is_array(self::$view->{'url-parameters'})) {
         foreach (self::$view->{'url-parameters'} as $p) {
             self::$Parameters->{$p} = NULL;
         }
         foreach (self::$view->parameters() as $p => $v) {
             self::$Parameters->{$p} = str_replace(' ', '+', $v);
         }
     }
     if (is_array($_GET) && !empty($_GET)) {
         foreach ($_GET as $key => $val) {
             if (in_array($key, array('symphony-page', 'debug', 'profile'))) {
                 continue;
             }
             // self::$Parameters->{"url-{$key}"} = $val; "url" is not prepended by $_GET params
             self::$Parameters->{$key} = $val;
         }
     }
     if (is_array($_COOKIE[__SYM_COOKIE_PREFIX__]) && !empty($_COOKIE[__SYM_COOKIE_PREFIX__])) {
         foreach ($_COOKIE[__SYM_COOKIE_PREFIX__] as $key => $val) {
             self::$Parameters->{"cookie-{$key}"} = $val;
         }
     }
     // RENDER THE VIEW --------------------------
     // Can ask the view to operate on an existing
     // Document. Useful if we pass it around beyond
     // the scope of View::render()
     ####
     # Delegate: FrontendPreRender
     # Description: TODO
     # Global: Yes
     Extension::notify('FrontendPreRender', '/frontend/', array('view' => &self::$view, 'parameters' => &self::$Parameters, 'document' => &self::$Document, 'headers' => &self::$Headers));
     $output = self::$view->render(self::$Parameters, self::$Document, self::$Headers);
     ####
     # Delegate: FrontendPostRender
     # Description: TODO
     # Global: Yes
     Extension::notify('FrontendPostRender', '/frontend/', array('output' => &$output, 'headers' => &self::$Headers));
     self::Headers()->render();
     return $output;
 }
 public function display($page)
 {
     // Default headers. Can be overwritten later
     //self::$Headers->append('HTTP/1.0 200 OK');
     self::$Headers->append('Content-Type', 'text/html;charset=utf-8');
     self::$Headers->append('Expires', 'Mon, 12 Dec 1982 06:14:00 GMT');
     self::$Headers->append('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT');
     self::$Headers->append('Cache-Control', 'no-cache, must-revalidate, max-age=0');
     self::$Headers->append('Pragma', 'no-cache');
     $this->isLoggedIn();
     if (empty($page)) {
         if (!$this->isLoggedIn()) {
             $page = '/login';
         } else {
             $section_handle = $this->User->default_section;
             // Make sure section exists:
             try {
                 $section = Section::loadFromHandle($section_handle);
                 redirect(ADMIN_URL . "/publish/{$section_handle}/");
             } catch (Exception $e) {
                 redirect(ADMIN_URL . '/blueprints/sections/');
             }
         }
     }
     if (!($this->_callback = $this->getPageCallback($page))) {
         throw new AdministrationPageNotFoundException($page);
     }
     include_once (isset($this->_callback['driverlocation']) ? $this->_callback['driverlocation'] : CONTENT) . '/content.' . $this->_callback['driver'] . '.php';
     $this->Page = new $this->_callback['classname']();
     // Widget class needs a document in order to create elements
     Widget::init($this->Page);
     ####
     # Delegate: AdminPagePreBuild
     # Description: Immediately before building the admin page. Provided with the page and callback
     # Global: Yes
     Extension::notify('AdminPagePreBuild', '/administration/', array('page' => &$this->Page, 'callback' => &$this->_callback));
     if (!$this->isLoggedIn() && $this->_callback['driver'] != 'login') {
         if (is_callable(array($this->Page, 'handleFailedAuthorisation'))) {
             $this->Page->handleFailedAuthorisation();
         } else {
             include_once CONTENT . '/content.login.php';
             $this->Page = new contentLogin();
             $this->Page->build();
         }
     } else {
         $this->Page->build($this->_callback['context']);
     }
     ####
     # Delegate: AdminPagePreGenerate
     # Description: Immediately before generating the admin page. Provided with the page object
     # Global: Yes
     Extension::notify('AdminPagePreGenerate', '/administration/', array('page' => &$this->Page));
     $output = (string) $this->Page;
     ####
     # Delegate: AdminPagePostGenerate
     # Description: Immediately after generating the admin page. Provided with string containing page source
     # Global: Yes
     Extension::notify('AdminPagePostGenerate', '/administration/', array('output' => &$output));
     self::Headers()->render();
     return $output;
 }
Example #10
0
 public function trigger(Register $ParameterOutput, array $postdata)
 {
     $result = new XMLDocument();
     $result->appendChild($result->createElement($this->parameters()->{'root-element'}));
     $root = $result->documentElement;
     // Apply default values:
     foreach ($this->parameters()->{'defaults'} as $name => $value) {
         if (!isset($postdata['fields'][$name])) {
             $postdata['fields'][$name] = $value;
         } else {
             if (is_string($postdata['fields'][$name]) and $postdata['fields'][$name] == '') {
                 $postdata['fields'][$name] = $value;
             } else {
                 if (is_array($postdata['fields'][$name]) and empty($postdata['fields'][$name])) {
                     $postdata['fields'][$name] = array($value);
                 }
             }
         }
     }
     // Apply override values:
     foreach ($this->parameters()->{'overrides'} as $name => $value) {
         if (is_array($postdata['fields'][$name])) {
             $postdata['fields'][$name] = array($value);
         } else {
             $postdata['fields'][$name] = $value;
         }
     }
     if (isset($postdata['id'])) {
         $entry = Entry::loadFromID($postdata['id']);
         $type = 'edit';
     } else {
         $entry = new Entry();
         $entry->section = $this->parameters()->{'section'};
         if (isset(Frontend::instance()->User) && Frontend::instance()->User instanceof User) {
             $entry->user_id = Frontend::instance()->User->id;
         } else {
             $entry->user_id = (int) Symphony::Database()->query("SELECT `id` FROM `tbl_users` ORDER BY `id` ASC LIMIT 1")->current()->id;
         }
         $type = 'create';
     }
     if (isset($postdata['fields']) && is_array($postdata['fields']) && !empty($postdata['fields'])) {
         $entry->setFieldDataFromFormArray($postdata['fields']);
     }
     $root->setAttribute('type', $type);
     ###
     # Delegate: EntryPreCreate
     # Description: Just prior to creation of an Entry. Entry object provided
     Extension::notify('EntryPreCreate', '/frontend/', array('entry' => &$entry));
     $errors = new MessageStack();
     $status = Entry::save($entry, $errors);
     if ($status == Entry::STATUS_OK) {
         ###
         # Delegate: EntryPostCreate
         # Description: Creation of an Entry. New Entry object is provided.
         Extension::notify('EntryPostCreate', '/frontend/', array('entry' => $entry));
         if ($this->parameters()->{'output-id-on-save'} == true) {
             $ParameterOutput->{sprintf('event-%s-id', $this->parameters()->{'root-element'})} = $entry->id;
         }
         $root->setAttribute('result', 'success');
         $root->setAttribute('id', $entry->id);
         $root->appendChild($result->createElement('message', __("Entry %s successfully.", array($type == 'edit' ? __('edited') : __('created')))));
     } else {
         $root->setAttribute('result', 'error');
         $root->appendChild($result->createElement('message', __('Entry encountered errors when saving.')));
         if (!isset($postdata['fields']) || !is_array($postdata['fields'])) {
             $postdata['fields'] = array();
         }
         $element = $result->createElement('errors');
         $this->appendMessages($element, $errors);
         $root->appendChild($element);
     }
     $messages = new MessageStack();
     ###
     # Delegate: EventPostSaveFilter
     # Description: After saving entry from the front-end. This delegate will not force the Events to terminate if it populates the error
     #              array reference. Provided with the event, message stack, postdata and entry object.
     Extension::notify('EventPostSaveFilter', '/frontend/', array('event' => $this, 'messages' => $messages, 'fields' => $postdata, 'entry' => $entry));
     if ($messages->valid()) {
         $filter = $result->createElement('filters');
         $this->appendMessages($filter, $messages);
         $root->appendChild($filter);
     }
     $element = $result->createElement('values');
     $this->appendValues($element, is_array($postdata['fields']) ? $postdata['fields'] : array());
     $root->appendChild($element);
     return $result;
 }
 protected function __buildNavigation()
 {
     $nav = array();
     $xml = simplexml_load_file(ASSETS . '/navigation.xml');
     foreach ($xml->xpath('/navigation/group') as $n) {
         $index = (string) $n->attributes()->index;
         $children = $n->xpath('children/item');
         $content = $n->attributes();
         if (isset($nav[$index])) {
             do {
                 $index++;
             } while (isset($nav[$index]));
         }
         $nav[$index] = array('name' => __(strval($content->name)), 'index' => $index, 'children' => array());
         if (strlen(trim((string) $content->limit)) > 0) {
             $nav[$index]['limit'] = (string) $content->limit;
         }
         if (count($children) > 0) {
             foreach ($children as $child) {
                 $limit = (string) $child->attributes()->limit;
                 $item = array('link' => (string) $child->attributes()->link, 'name' => __(strval($child->attributes()->name)), 'visible' => (string) $child->attributes()->visible == 'no' ? 'no' : 'yes');
                 if (strlen(trim($limit)) > 0) {
                     $item['limit'] = $limit;
                 }
                 $nav[$index]['children'][] = $item;
             }
         }
     }
     foreach (new SectionIterator() as $s) {
         $group_index = self::__navigationFindGroupIndex($nav, $s->{'navigation-group'});
         if ($group_index === false) {
             $group_index = General::array_find_available_index($nav, 0);
             $nav[$group_index] = array('name' => $s->{'navigation-group'}, 'index' => $group_index, 'children' => array(), 'limit' => NULL);
         }
         $nav[$group_index]['children'][] = array('link' => '/publish/' . $s->handle . '/', 'name' => $s->name, 'type' => 'section', 'section' => array('id' => $s->guid, 'handle' => $s->handle), 'visible' => $s->{'hidden-from-publish-menu'} == 'no' ? 'yes' : 'no');
     }
     //			$extensions = ExtensionManager::instance()->listInstalledHandles();
     foreach (new ExtensionIterator(ExtensionIterator::FLAG_STATUS, Extension::STATUS_ENABLED) as $e) {
         if (!method_exists($e, 'fetchNavigation')) {
             continue;
         }
         $e_navigation = $e->fetchNavigation();
         if (isset($e_navigation) && is_array($e_navigation) && !empty($e_navigation)) {
             foreach ($e_navigation as $item) {
                 $type = isset($item['children']) ? Extension::NAVIGATION_GROUP : Extension::NAVIGATION_CHILD;
                 switch ($type) {
                     case Extension::NAVIGATION_GROUP:
                         $index = General::array_find_available_index($nav, $item['location']);
                         $nav[$index] = array('name' => $item['name'], 'index' => $index, 'children' => array(), 'limit' => !is_null($item['limit']) ? $item['limit'] : NULL);
                         foreach ($item['children'] as $child) {
                             if (!isset($child['relative']) || $child['relative'] == true) {
                                 $link = '/extension/' . Extension::getHandleFromPath(Extension::getPathFromClass(get_class($e))) . '/' . ltrim($child['link'], '/');
                             } else {
                                 $link = '/' . ltrim($child['link'], '/');
                             }
                             $nav[$index]['children'][] = array('link' => $link, 'name' => $child['name'], 'visible' => $child['visible'] == 'no' ? 'no' : 'yes', 'limit' => !is_null($child['limit']) ? $child['limit'] : NULL);
                         }
                         break;
                     case Extension::NAVIGATION_CHILD:
                         if (!isset($item['relative']) || $item['relative'] == true) {
                             $link = '/extension/' . Extension::getHandleFromPath(Extension::getPathFromClass(get_class($e))) . '/' . ltrim($item['link'], '/');
                         } else {
                             $link = '/' . ltrim($item['link'], '/');
                         }
                         if (!is_numeric($item['location'])) {
                             // is a navigation group
                             $group_name = $item['location'];
                             $group_index = $this->__findLocationIndexFromName($nav, $item['location']);
                         } else {
                             // is a legacy numeric index
                             $group_index = $item['location'];
                         }
                         $child = array('link' => $link, 'name' => $item['name'], 'visible' => $item['visible'] == 'no' ? 'no' : 'yes', 'limit' => !is_null($item['limit']) ? $item['limit'] : NULL);
                         if ($group_index === false) {
                             // add new navigation group
                             $nav[] = array('name' => $group_name, 'index' => $group_index, 'children' => array($child), 'limit' => !is_null($item['limit']) ? $item['limit'] : NULL);
                         } else {
                             // add new location by index
                             $nav[$group_index]['children'][] = $child;
                         }
                         break;
                 }
             }
         }
     }
     ####
     # Delegate: ExtensionsAddToNavigation
     # Description: After building the Navigation properties array. This is specifically
     # 			for extentions to add their groups to the navigation or items to groups,
     # 			already in the navigation. Note: THIS IS FOR ADDING ONLY! If you need
     #			to edit existing navigation elements, use the 'NavigationPreRender' delegate.
     # Global: Yes
     Extension::notify('ExtensionsAddToNavigation', '/administration/', array('navigation' => &$nav));
     $pageCallback = Administration::instance()->getPageCallback();
     $pageRoot = $pageCallback['pageroot'] . (isset($pageCallback['context'][0]) ? $pageCallback['context'][0] . '/' : '');
     $found = $this->__findActiveNavigationGroup($nav, $pageRoot);
     ## Normal searches failed. Use a regular expression using the page root. This is less
     ## efficent and should never really get invoked unless something weird is going on
     if (!$found) {
         $this->__findActiveNavigationGroup($nav, '/^' . str_replace('/', '\\/', $pageCallback['pageroot']) . '/i', true);
     }
     ksort($nav);
     $this->_navigation = $nav;
 }
Example #12
0
 public function appendFormattedElement(SymphonyDOMElement $wrapper, $data, $encode = false, $mode = null, Entry $entry = null)
 {
     if (!$this->sanitizeDataArray($data)) {
         return null;
     }
     $document = $wrapper->ownerDocument;
     $meta = unserialize($data->meta);
     if (!is_array($meta)) {
         $meta = array();
     }
     $meta['size'] = General::formatFilesize($data->size);
     $meta['type'] = $data->type;
     ksort($meta);
     $field = $document->createElement($this->{'element-name'});
     $field->appendChild($document->createElement('file', $data->name, array('path' => trim($data->path, '/'), 'name' => $data->file)));
     $element = $document->createElement('meta');
     foreach ($meta as $key => $value) {
         if ($key == 'creation' or $key == 'type') {
             $element->setAttribute($key, $value);
         } else {
             if ($key == 'size') {
                 $bits = explode(' ', $value);
                 if (count($bits) != 2) {
                     continue;
                 }
                 $element->appendChild($document->createElement('size', $bits[0], array('unit' => $bits[1])));
             } else {
                 if (is_array($value)) {
                     $element->appendChild($document->createElement($key, null, $value));
                 } else {
                     $element->appendChild($document->createElement($key, (string) $value));
                 }
             }
         }
     }
     $field->appendChild($element);
     ###
     # Delegate: UploadField_AppendFormattedElement
     # Description: Allow other extensions to add media previews.
     Extension::notify('UploadField_AppendFormattedElement', '/publish/', array('data' => $data, 'entry' => $entry, 'field' => $this, 'wrapper' => $field));
     $wrapper->appendChild($field);
 }
Example #13
0
 public function trigger(Register $ParameterOutput, array $postdata)
 {
     $result = new XMLDocument();
     $result->appendChild($result->createElement($this->parameters()->{'root-element'}));
     $root = $result->documentElement;
     if (isset($postdata['id'])) {
         $entry = Entry::loadFromID($postdata['id']);
         $type = 'edit';
     } else {
         $entry = new Entry();
         $entry->section = $this->parameters()->{'section'};
         if (isset(Frontend::instance()->User) && Frontend::instance()->User instanceof User) {
             $entry->user_id = Frontend::instance()->User->id;
         } else {
             $entry->user_id = (int) Symphony::Database()->query("SELECT `id` FROM `tbl_users` ORDER BY `id` ASC LIMIT 1")->current()->id;
         }
         $type = 'create';
     }
     if (isset($postdata['fields']) && is_array($postdata['fields']) && !empty($postdata['fields'])) {
         $entry->setFieldDataFromFormArray($postdata['fields']);
     }
     $root->setAttribute('type', $type);
     ###
     # Delegate: EntryPreCreate
     # Description: Just prior to creation of an Entry. Entry object provided
     Extension::notify('EntryPreCreate', '/frontend/', array('entry' => &$entry));
     $errors = new MessageStack();
     $status = Entry::save($entry, $errors);
     if ($status == Entry::STATUS_OK) {
         ###
         # Delegate: EntryPostCreate
         # Description: Creation of an Entry. New Entry object is provided.
         Extension::notify('EntryPostCreate', '/frontend/', array('entry' => $entry));
         if ($this->parameters()->{'output-id-on-save'} == true) {
             $ParameterOutput->{sprintf('event-%s-id', $this->parameters()->{'root-element'})} = $entry->id;
         }
         $root->setAttribute('result', 'success');
         $root->appendChild($result->createElement('message', __("Entry %s successfully.", array($type == 'edit' ? __('edited') : __('created')))));
     } else {
         $root->setAttribute('result', 'error');
         $root->appendChild($result->createElement('message', __('Entry encountered errors when saving.')));
         if (!isset($postdata['fields']) || !is_array($postdata['fields'])) {
             $postdata['fields'] = array();
         }
         $element = $result->createElement('values');
         $this->appendValues($element, $postdata['fields']);
         $root->appendChild($element);
         $element = $result->createElement('errors');
         $this->appendMessages($element, $errors);
         $root->appendChild($element);
     }
     return $result;
 }
Example #14
0
 public function displayPublishPanel(SymphonyDOMElement $wrapper, MessageStack $errors, Entry $entry = NULL, $data = NULL)
 {
     $document = $wrapper->ownerDocument;
     $driver = Extension::load('field_textbox');
     $driver->addPublishHeaders($document);
     $sortorder = $this->{'sortorder'};
     $element_name = $this->{'element-name'};
     $classes = array();
     $label = Widget::Label(isset($this->{'publish-label'}) && strlen(trim($this->{'publish-label'})) > 0 ? $this->{'publish-label'} : $this->name);
     $optional = '';
     if ($this->{'required'} != 'yes') {
         if ((int) $this->{'text-length'} > 0) {
             $optional = $document->createDocumentFragment();
             $optional->appendChild($document->createTextNode(__('$1 of $2 remaining') . ' '));
             $optional->appendChild($document->createEntityReference('ndash'));
             $optional->appendChild($document->createTextNode(' ' . __('Optional')));
         } else {
             $optional = __('Optional');
         }
     } else {
         if ((int) $this->{'text-length'} > 0) {
             $optional = __('$1 of $2 remaining');
         }
     }
     if ($optional) {
         $label->appendChild($wrapper->ownerDocument->createElement('em', $optional));
     }
     // Input box:
     if ($this->{'text-size'} == 'single') {
         $input = Widget::Input("fields[{$element_name}]", $data->value);
         ###
         # Delegate: ModifyTextBoxInlineFieldPublishWidget
         # Description: Allows developers modify the textbox before it is rendered in the publish forms
         $delegate = 'ModifyTextBoxInlineFieldPublishWidget';
     } else {
         $input = Widget::Textarea("fields[{$element_name}]", $data->value, array('rows' => 20, 'cols' => 50));
         ###
         # Delegate: ModifyTextBoxFullFieldPublishWidget
         # Description: Allows developers modify the textbox before it is rendered in the publish forms
         $delegate = 'ModifyTextBoxFullFieldPublishWidget';
     }
     // Add classes:
     $classes[] = 'size-' . $this->{'text-size'};
     if ($this->{'text-formatter'} != 'none') {
         $classes[] = $this->{'text-formatter'};
     }
     $input->setAttribute('class', implode(' ', $classes));
     $input->setAttribute('length', (int) $this->{'text-length'});
     Extension::notify($delegate, '/administration/', array('field' => &$this, 'label' => &$label, 'input' => &$input));
     if (is_null($label)) {
         return;
     }
     $label->appendChild($input);
     if ($errors->valid()) {
         $label = Widget::wrapFormElementWithError($label, $errors->current()->message);
     }
     $wrapper->appendChild($label);
 }
 public function __actionEdit()
 {
     $callback = Administration::instance()->getPageCallback();
     $entry_id = (int) $callback['context']['entry_id'];
     if (@array_key_exists('save', $_POST['action']) || @array_key_exists("done", $_POST['action'])) {
         $entry = Entry::loadFromID($entry_id);
         $post = General::getPostData();
         $fields = array();
         if (isset($post['fields']) and !empty($post['fields'])) {
             $fields = $post['fields'];
         }
         $entry->setFieldDataFromFormArray($fields);
         ###
         # Delegate: EntryPreEdit
         # Description: Just prior to editing of an Entry.
         Extension::notify('EntryPreEdit', '/publish/edit/', array('entry' => &$entry));
         $this->errors->flush();
         $status = Entry::save($entry, $this->errors);
         if ($status == Entry::STATUS_OK) {
             // Check if there is a field to prepopulate
             if (isset($_REQUEST['prepopulate']) && strlen(trim($_REQUEST['prepopulate'])) > 0) {
                 $field_handle = key($_REQUEST['prepopulate']);
                 $value = stripslashes(rawurldecode($_REQUEST['prepopulate'][$field_handle]));
                 $prepopulate_filter = "?prepopulate[{$field_handle}]=" . rawurlencode($value);
             } else {
                 $prepopulate_filter = null;
             }
             ###
             # Delegate: EntryPostEdit
             # Description: Editing an entry. Entry object is provided.
             Extension::notify('EntryPostEdit', '/publish/edit/', array('entry' => $entry));
             ## WOOT
             redirect(sprintf('%s/symphony/publish/%s/edit/%d/:saved/%s', URL, $entry->section, $entry->id, $prepopulate_filter));
         }
         // Oh dear
         $this->entry = $entry;
         $this->alerts()->append(__('An error occurred while processing this form. <a href="#error">See below for details.</a> <a class="more">Show a list of errors.</a>'), AlertStack::ERROR);
         return;
     } elseif (@array_key_exists('delete', $_POST['action']) && is_numeric($entry_id)) {
         $callback = Administration::instance()->getPageCallback();
         ###
         # Delegate: Delete
         # Description: Prior to deleting an entry. Entry ID is provided, as an
         # array to remain compatible with other Delete delegate call
         Extension::notify('Delete', '/publish/', array('entry_id' => $entry_id));
         Entry::delete($entry_id);
         redirect(ADMIN_URL . '/publish/' . $callback['context']['section_handle'] . '/');
     }
 }
Example #16
0
 public function __actionEdit()
 {
     if (!($user_id = $this->_context[1])) {
         redirect(ADMIN_URL . '/system/users/');
     }
     if (array_key_exists('save', $_POST['action']) || array_key_exists('done', $_POST['action'])) {
         $fields = $_POST['fields'];
         $this->user = User::load($user_id);
         $this->user->id = $user_id;
         $this->user->email = $fields['email'];
         $this->user->username = $fields['username'];
         $this->user->first_name = General::sanitize($fields['first_name']);
         $this->user->last_name = General::sanitize($fields['last_name']);
         if (trim($fields['password']) != '') {
             $this->user->password = md5($fields['password']);
             $changing_password = true;
         }
         $this->user->default_section = $fields['default_section'];
         $this->user->auth_token_active = $fields['auth_token_active'] ? $fields['auth_token_active'] : 'no';
         $this->user->language = $fields['language'];
         ###
         # Delegate: UserPreSave
         # Description: Just before creation of a new User. User object, fields and error array provided
         Extension::notify('UserPreSave', '/system/users/edit/', array('fields' => $fields, 'user' => &$this->user, 'errors' => &$this->errors));
         $this->user->validate($this->errors);
         if ($this->errors->length() == 0) {
             if (($fields['password'] != '' || $fields['password-confirmation'] != '') && $fields['password'] != $fields['password-confirmation']) {
                 $this->errors->append('password', __('Passwords did not match'));
                 $this->errors->append('password-confirmation', __('Passwords did not match'));
             } elseif (User::save($this->user)) {
                 Symphony::Database()->delete('tbl_forgotpass', array(DateTimeObj::getGMT('c'), $user_id), " `expiry` < '%s' OR `user_id` = %d ");
                 // This is the logged in user, so update their session
                 if ($user_id == Administration::instance()->User->id) {
                     Administration::instance()->login($this->user->username, $this->user->password, true);
                 }
                 ###
                 # Delegate: PostSave
                 # Description: Just after creation of a new User. The ID of the User is provided.
                 Extension::notify('PostSave', '/system/users/edit/', array('user' => $this->user));
                 redirect(ADMIN_URL . "/system/users/edit/{$this->user->id}/:saved/");
             } else {
                 $this->alerts()->append(__('Unknown errors occurred while attempting to save. Please check your <a href="%s">activity log</a>.', array(ADMIN_URL . '/system/log/')), AlertStack::ERROR);
             }
         } else {
             $this->alerts()->append(__('There were some problems while attempting to save. Please check below for problem fields.'), AlertStack::ERROR, $this->errors);
         }
     } elseif (array_key_exists('delete', $_POST['action'])) {
         ## FIXME: Fix this delegate
         ###
         # Delegate: Delete
         # Description: Prior to deleting an User. ID is provided.
         //Extension::notify('Delete', getCurrentPage(), array('user_id' => $user_id));
         User::delete($user_id);
         redirect(ADMIN_URL . '/system/users/');
     }
 }
Example #17
0
 protected function appendSidebar(DOMElement $wrapper)
 {
     $container = $this->document->createElement('div');
     $container->setAttribute('id', 'sidebar');
     // Header:
     $header = $this->document->createElement('h1');
     $header->appendChild(Widget::Anchor($this->view->title, (string) $this->url));
     $container->appendChild($header);
     $list = $this->document->createElement('ul');
     $list->setAttribute('class', 'menu');
     $root = $this->document->createElement('navigation');
     ####
     # Delegate: DevKiAppendtMenuItem
     # Description: Allow navigation XML to be manipulated before it is rendered.
     # Global: Yes
     #$this->_page->ExtensionManager->notifyMembers(
     Extension::notify('DevKiAppendtMenuItem', '/frontend/', array('wrapper' => $root));
     if ($root->hasChildNodes()) {
         foreach ($root->childNodes as $node) {
             if ($node->getAttribute('active') == 'yes') {
                 $item = $this->document->createElement('li', $node->getAttribute('name'));
             } else {
                 $handle = $node->getAttribute('handle');
                 $url = clone $this->url;
                 $url->parameters()->{$handle} = null;
                 $item = $this->document->createElement('li');
                 $item->appendChild(Widget::Anchor($node->getAttribute('name'), '?' . (string) $url));
             }
             $list->appendChild($item);
         }
     }
     $item = $this->document->createElement('li');
     $item->appendChild(Widget::Anchor(__('Edit'), ADMIN_URL . '/blueprints/views/edit/' . $this->view->handle . '/'));
     $list->prependChild($item);
     $container->appendChild($list);
     // Main:
     $fieldset = Widget::Fieldset(__('Pages'));
     $container->appendChild($fieldset);
     $wrapper->appendChild($container);
     return $container;
 }
 public function buildOutput()
 {
     $ParameterOutput = new Register();
     $root = $this->document->documentElement;
     $this->buildContextXML($root);
     $datasources = $events = array();
     $events_wrapper = $this->document->createElement('events');
     $root->appendChild($events_wrapper);
     if (is_array($this->about()->{'events'}) && !empty($this->about()->{'events'})) {
         $events = $this->about()->{'events'};
     }
     if (is_array($this->about()->{'data-sources'}) && !empty($this->about()->{'data-sources'})) {
         $datasources = $this->about()->{'data-sources'};
     }
     ####
     # Delegate: FrontendEventsAppend
     # Description: Append additional Events.
     # Global: Yes
     Extension::notify('FrontendEventsAppend', '/frontend/', array('events' => &$events));
     if (!empty($events)) {
         $postdata = General::getPostData();
         $events_ordered = array();
         foreach ($events as $handle) {
             $events_ordered[] = Event::loadFromHandle($handle);
         }
         uasort($events_ordered, array($this, '__cbSortEventsByPriority'));
         foreach ($events_ordered as $e) {
             if (!$e->canTrigger($postdata)) {
                 continue;
             }
             $fragment = $e->trigger($ParameterOutput, $postdata);
             if ($fragment instanceof DOMDocument && !is_null($fragment->documentElement)) {
                 $node = $this->document->importNode($fragment->documentElement, true);
                 $events_wrapper->appendChild($node);
             }
         }
     }
     ####
     # Delegate: FrontendDataSourceAppend
     # Description: Append additional DataSources.
     # Global: Yes
     Extension::notify('FrontendDataSourcesAppend', '/frontend/', array('datasources' => &$datasources));
     //	Find dependancies and order accordingly
     $datasource_pool = array();
     $dependency_list = array();
     $datasources_ordered = array();
     $all_dependencies = array();
     foreach ($datasources as $handle) {
         $datasource_pool[$handle] = Datasource::loadFromHandle($handle);
         $dependency_list[$handle] = $datasource_pool[$handle]->parameters()->dependencies;
     }
     $datasources_ordered = General::dependenciesSort($dependency_list);
     $data = $this->document->createElement('data');
     if (!empty($datasources_ordered)) {
         foreach ($datasources_ordered as $handle) {
             $ds = $datasource_pool[$handle];
             try {
                 $fragment = $ds->render($ParameterOutput);
             } catch (FrontendPageNotFoundException $e) {
                 FrontendPageNotFoundExceptionHandler::render($e);
             }
             if ($fragment instanceof DOMDocument && !is_null($fragment->documentElement)) {
                 $node = $this->document->importNode($fragment->documentElement, true);
                 $data->appendChild($node);
             }
         }
     }
     $root->appendChild($data);
     /*
     			if($ParameterOutput->length() > 0){
     				foreach($ParameterOutput as $p){
     					$Parameters->{$p->key} = $p->value;
     				}
     			}
     
     			####
     			# Delegate: FrontendParamsPostResolve
     			# Description: Access to the resolved param pool, including additional parameters provided by Data Source outputs
     			# Global: Yes
     			Extension::notify('FrontendParamsPostResolve', '/frontend/', array('params' => $Parameters));
     
     
     			####
     			# Delegate: FrontendTemplatePreRender
     			# Description: Access to the template source, before it is rendered.
     			# Global: Yes
     			Extension::notify(
     				'FrontendTemplatePreRender', '/frontend/', array(
     					'document'	=> $Document,
     					'template'	=> &$template
     				)
     			);
     */
     return $this->transform();
 }