- <?php 
- /* 
-  * Copyright (C) 2017 Karmabunny Pty Ltd. 
-  * 
-  * This file is a part of SproutCMS. 
-  * 
-  * SproutCMS is free software: you can redistribute it and/or modify it under the terms 
-  * of the GNU General Public License as published by the Free Software Foundation, either 
-  * version 2 of the License, or (at your option) any later version. 
-  * 
-  * For more information, visit <http://getsproutcms.com>. 
-  */ 
-   
- namespace Sprout\Controllers\Admin; 
-   
- use DOMDocument; 
- use Exception; 
-   
- use Kohana; 
-   
- use Sprout\Controllers\PageController; 
- use karmabunny\pdb\Exceptions\QueryException; 
- use karmabunny\pdb\Exceptions\RowMissingException; 
- use Sprout\Exceptions\ValidationException; 
- use Sprout\Exceptions\WorkerJobException; 
- use Sprout\Helpers\Admin; 
- use Sprout\Helpers\AdminAuth; 
- use Sprout\Helpers\AdminError; 
- use Sprout\Helpers\AdminPerms; 
- use Sprout\Helpers\AdminSeo; 
- use Sprout\Helpers\Category; 
- use Sprout\Helpers\ColModifierDate; 
- use Sprout\Helpers\Constants; 
- use Sprout\Helpers\Cron; 
- use Sprout\Helpers\Csrf; 
- use Sprout\Helpers\DocImport\DocImport; 
- use Sprout\Helpers\Email; 
- use Sprout\Helpers\Enc; 
- use Sprout\Helpers\FileConstants; 
- use Sprout\Helpers\FileUpload; 
- use Sprout\Helpers\Form; 
- use Sprout\Helpers\FrontEndEntrance; 
- use Sprout\Helpers\Inflector; 
- use Sprout\Helpers\Itemlist; 
- use Sprout\Helpers\Json; 
- use Sprout\Helpers\Lnk; 
- use Sprout\Helpers\MultiEdit; 
- use Sprout\Helpers\Navigation; 
- use Sprout\Helpers\NavigationGroups; 
- use Sprout\Helpers\Notification; 
- use Sprout\Helpers\Page; 
- use Sprout\Helpers\Pdb; 
- use Sprout\Helpers\Preview; 
- use Sprout\Helpers\RefineBar; 
- use Sprout\Helpers\RefineWidgetTextbox; 
- use Sprout\Helpers\Register; 
- use Sprout\Helpers\Search; 
- use Sprout\Helpers\Security; 
- use Sprout\Helpers\Slug; 
- use Sprout\Helpers\Sprout; 
- use Sprout\Helpers\Subsites; 
- use Sprout\Helpers\TinyMCE4RichText; 
- use Sprout\Helpers\Treenode; 
- use Sprout\Helpers\Upload; 
- use Sprout\Helpers\Url; 
- use Sprout\Helpers\UserPerms; 
- use Sprout\Helpers\Validator; 
- use Sprout\Helpers\View; 
- use Sprout\Helpers\WidgetArea; 
- use Sprout\Helpers\WorkerCtrl; 
-   
-   
- /** 
-  * Handles admin processing for pages 
-  */ 
- class PageAdminController extends TreeAdminController 
- { 
-     protected $controller_name = 'page'; 
-     protected $friendly_name = 'Pages'; 
-     protected $main_delete = true; 
-   
-   
-     /** 
-     * Constructor 
-     **/ 
-     public function __construct() 
-     { 
-         $this->refine_bar = new RefineBar(); 
-         $this->refine_bar->setGroup('Pages'); 
-         $this->refine_bar->addWidget(new RefineWidgetTextbox('name', 'Name')); 
-   
-         $this->refine_bar->setGroup('Page content'); 
-         $this->refine_bar->addWidget(new RefineWidgetTextbox('_keyword', 'Keyword search')); 
-         $this->refine_bar->addWidget(new RefineWidgetTextbox('_phrase', 'Exact phrase')); 
-   
-         parent::__construct(); 
-   
-         $this->main_columns = [ 
-             'Name' => 'name', 
-             'Added' => [new ColModifierDate('g:ia d/m/Y'), 'date_added'] 
-         ]; 
-     } 
-   
-   
-     /** 
-      * Return the WHERE clause to use for a given key which is provided by the RefineBar 
-      * 
-      * Allows custom non-table clauses to be added. 
-      * Is only called for key names which begin with an underscore. 
-      * The base table is aliased to 'item'. 
-      * 
-      * @param string $key The key name, including underscore 
-      * @param string $val The value which is being refined. 
-      * @param array &$query_params Parameters to add to the query which will use the WHERE clause 
-      * @return string WHERE clause, e.g. "item.name LIKE CONCAT('%', ?, '%')", "item.status IN (?, ?, ?)" 
-      */ 
-     protected function-  _getRefineClause ($key, $val, array &$query_params)
 
-     { 
-   
-         switch ($key) { 
-             case '_keyword': 
-                 $query_params[] = Pdb::likeEscape($val); 
-                 return "item.id IN (SELECT record_id FROM ~page_keywords AS pk 
-                     INNER JOIN ~search_keywords AS k ON pk.keyword_id = k.id WHERE k.name LIKE ?)"; 
-   
-             case '_phrase': 
-                 $query_params[] = 'live'; 
-                 $query_params[] = Pdb::likeEscape($val); 
-                 return "item.id IN (SELECT page_id FROM ~page_revisions AS rev 
-                     WHERE rev.status = ? AND rev.text LIKE CONCAT('%', ?, '%'))"; 
-         } 
-   
-         return parent::_getRefineClause($key, $val, $query_params); 
-     } 
-   
-   
-     /** 
-     * This is called after every add, edit and delete, as well as other (i.e. bulk) actions. 
-     * Use it to clear any frontend caches. The default is an empty method. 
-     * 
-     * @param string $action The name of the action (e.g. 'add', 'edit', 'delete', etc) 
-     * @param int $item_id The item which was affected. Bulk actions (e.g. reorders) will have this set to NULL. 
-     **/ 
-     public function _invalidateCaches($action, $item_id = null) 
-     { 
-         Navigation::clearCache(); 
-     } 
-   
-   
-     /** 
-     * Returns the contents of the navigation pane for the tree 
-     **/ 
-     public function _getNavigation() 
-     { 
-         $nodes_string = ''; 
-         if (!empty($_SESSION['admin'][$this->controller_name . '_nav'])) { 
-             $nodes_string = "'" . implode ("', '", $_SESSION['admin'][$this->controller_name . '_nav']) . "'"; 
-         } 
-   
-         $q = "SELECT id FROM ~homepages WHERE subsite_id = ?"; 
-   
-         $view = new View('sprout/admin/page_navigation'); 
-         $view->home_page_id = Pdb::q($q, [$_SESSION['admin']['active_subsite']], 'val'); 
-         $view->nodes_string = $nodes_string; 
-         $view->controller_name = $this->controller_name; 
-         $view->friendly_name = $this->friendly_name; 
-         $view->record_id = Admin::getRecordId(); 
-         $view->root = Navigation::getRootNode(); 
-   
-         return $view->render(); 
-     } 
-   
-   
-     public function _getCustomAddSaveHTML() 
-     { 
-         $view = new View('sprout/admin/page_add_save'); 
-         return $view->render(); 
-     } 
-   
-   
-     /** 
-      * Return the sub-actions for adding; for spec {@see AdminController::renderSubActions} 
-      * @return array 
-      */ 
-     public function _getAddSubActions() 
-     { 
-         $actions = parent::_getAddSubActions(); 
-         // Add your actions here, like this: $actions[] = [ ... ]; 
-   
-         if (@$_GET['type'] == 'tool') { 
-             $actions[] = [ 
-                 'url' => 'admin/add/page', 
-                 'name' => 'Add a standard page', 
-             ]; 
-         } else { 
-             $actions[] = [ 
-                 'url' => 'admin/add/page?type=tool', 
-                 'name' => 'Add a tool page', 
-             ]; 
-         } 
-   
-         return $actions; 
-     } 
-   
-   
-     /** 
-     * Returns the add form for adding a page 
-     * 
-     * @return string The HTML code which represents the add form 
-     **/ 
-     public function _getAddForm() 
-     { 
-         // Defaults 
-             'active' => 1, 
-             'show_in_nav' => 1, 
-             'admin_perm_type' => Constants::PERM_INHERIT, 
-             'parent_id' => (int) @$_GET['parent_id'], 
-             'status' => 'live', 
-             'admin_perm_specific' => 0, 
-             'admin_permissions' => [], 
-             'user_perm_specific' => 0, 
-             'user_permissions' => [], 
-         ); 
-   
-         if (! AdminPerms::canAccess('access_noapproval')) { 
-             $data['status'] = 'need_approval'; 
-         } 
-   
-         // Fields in session 
-         if (!empty($_SESSION['admin']['field_values'])) { 
-             $data = $_SESSION['admin']['field_values']; 
-             unset ($_SESSION['admin']['field_values']); 
-         } 
-   
-         $errors = []; 
-         if (!empty($_SESSION['admin']['field_errors'])) { 
-             $errors = $_SESSION['admin']['field_errors']; 
-             unset($_SESSION['admin']['field_errors']); 
-         } 
-   
-         $templates = Subsites::getConfigAdmin('skin_views'); 
-         if (! $templates) $templates = array('skin/inner' => 'Inner'); 
-   
-         // Controller list for entrance dropdown 
-         $front_end_controllers = Register::getFrontEndControllers(); 
-         asort($front_end_controllers); 
-   
-         // Load entrance arguments 
-         $controller_arguments = []; 
-         if (!empty($data['controller_entrance'])) { 
-             $inst = Sprout::instance($data['controller_entrance']); 
-             if ($inst instanceof FrontEndEntrance) { 
-                 $controller_arguments = $inst->_getEntranceArguments(); 
-                 if (empty($controller_arguments)) { 
-                     $controller_arguments = ['' => '- Nothing available -']; 
-                 } 
-             } 
-         } 
-   
-         $title = 'Add a page'; 
-         if (@$_GET['type'] == 'tool') { 
-             $data['type'] = 'tool'; 
-             $title = 'Add a tool page'; 
-         } else { 
-             $data['type'] = 'standard'; 
-         } 
-         $view = new View('sprout/admin/page_add'); 
-   
-         $view->data = $data; 
-         $view->errors = $errors; 
-         $view->admin_category_options = AdminAuth::getAllCategories(); 
-         $view->user_category_options = UserPerms::getAllCategories(); 
-         $view->front_end_controllers = $front_end_controllers; 
-         $view->controller_arguments = $controller_arguments; 
-         $view->templates = $templates; 
-   
-             'title' => $title, 
-             'content' => $view->render() 
-         ); 
-     } 
-   
-     /** 
-     * Saves the provided POST data into a new page in the database 
-     * 
-     * @param int $page_id After saving, the new record id will be returned in this parameter 
-     * @param bool True on success, false on failure 
-     **/ 
-     public function _addSave(&$page_id) 
-     { 
-         // Boolean values 
-         $_POST['admin_perm_specific'] = (empty($_POST['admin_perm_specific'])-  ?  0 : 1);
 
-         $_POST['active'] = (empty($_POST['active'])-  ?  0 : 1);
 
-         $_POST['show_in_nav'] = (empty($_POST['show_in_nav'])-  ?  0 : 1);
 
-   
-         // Checkbox sets 
-         if (!isset($_POST['user_permissions'])) $_POST['user_permissions'] = []; 
-   
-         $valid = new Validator($_POST); 
-         $valid->required(['name']); 
-         $valid->check('name', 'Validity::length', 1, 200); 
-         $valid->check('meta_description', 'Validity::length', 0, 200); 
-   
-         // HACK: we should attempt to generate a unique slug rather than just failing out 
-         try { 
-             $conds = [ 
-                 'subsite_id' => $_SESSION['admin']['active_subsite'], 
-                 'parent_id' => (int)@$_POST['parent_id'] 
-             ]; 
-             Slug::unique(Enc::urlname((string)@$_POST['name'], '-'), 'pages', $conds); 
-         } catch (ValidationException $exp) { 
-             $valid->addFieldError('name', 'this will result in a conflicting URL, please try another.'); 
-         } 
-   
-         if ($_POST['type'] == 'tool') { 
-             // Validate fields specific to tool pages 
-             $valid->required(['controller_entrance']); 
-             $valid->check('controller_entrance', 'Validity::length', 1, 200); 
-             if (!self::checkControllerEntrance($_POST['controller_entrance'], $page_id)) { 
-                 $valid->addFieldError('controller_entrance', 'Invalid value'); 
-             } 
-   
-             // Tell core AdminController the right URL to redirect to upon validation error 
-             $_POST['current_url'] = 'admin/add/page?type=tool'; 
-         } 
-   
-         if ($valid->hasErrors()) { 
-             $_SESSION['admin']['field_values'] = $_POST; 
-             $_SESSION['admin']['field_errors'] = $valid->getFieldErrors(); 
-             $valid->createNotifications(); 
-             return false; 
-         } 
-   
-         if (!in_array($_POST['type'],-  Pdb ::extractEnumArr('page_revisions', 'type'))) {
 
-             return false; 
-         } 
-   
-         $operator = AdminAuth::getDetails(); 
-         if (! $operator) return false; 
-   
-         // Start transaction 
-         Pdb::transact(); 
-   
-         // Add page 
-         $update_fields = []; 
-         $update_fields['name'] = $_POST['name']; 
-         $update_fields['meta_description'] = $_POST['meta_description']; 
-         $update_fields['parent_id'] = $_POST['parent_id']; 
-         $update_fields['active'] = $_POST['active']; 
-         $update_fields['slug'] = Enc::urlname($_POST['name'], '-'); 
-         $update_fields['show_in_nav'] = $_POST['show_in_nav']; 
-         $update_fields['subsite_id'] = $_SESSION['admin']['active_subsite']; 
-         $update_fields['modified_editor'] = $operator['name']; 
-         $update_fields['alt_template'] = trim(preg_replace('![^-_a-z0-9/]!i', '', @$_POST['alt_template'])); 
-         $update_fields['menu_group'] = (int) @$_POST['menu_group']; 
-         $update_fields['date_added'] = Pdb::now(); 
-         $update_fields['date_modified'] = Pdb::now(); 
-   
-         if ($_POST['admin_perm_specific'] == 1) { 
-             $update_fields['admin_perm_type'] = Constants::PERM_SPECIFIC; 
-         } else { 
-             $update_fields['admin_perm_type'] = Constants::PERM_INHERIT; 
-         } 
-   
-         if (Register::hasFeature('users')) { 
-             if (@$_POST['user_perm_specific'] == 1) { 
-                 $update_fields['user_perm_type'] = Constants::PERM_SPECIFIC; 
-             } else { 
-                 $update_fields['user_perm_type'] = Constants::PERM_INHERIT; 
-             } 
-         } 
-   
-         $page_id = Pdb::insert('pages', $update_fields); 
-   
-         $this->fixRecordOrder($page_id); 
-   
-         // History item 
-         $res = $this->addHistoryItem($page_id, 'Created empty new page'); 
-         if (! $res) return false; 
-   
-         // Add first (blank) revision 
-         $update_fields = array(); 
-         $update_fields['page_id'] = $page_id; 
-         $update_fields['type'] = $_POST['type']; 
-         $update_fields['changes_made'] = 'New page'; 
-   
-   
-         // Normal pages have more data to add on the edit form, but tool pages go live straight away 
-         if ($_POST['type'] == 'tool') { 
-             $update_fields['status'] = 'live'; 
-   
-             $update_fields['controller_entrance'] = $_POST['controller_entrance']; 
-             $update_fields['controller_argument'] = $_POST['controller_argument']; 
-         } else { 
-             $update_fields['status'] = 'wip'; 
-         } 
-   
-         $update_fields['modified_editor'] = $operator['name']; 
-         $update_fields['date_added'] = Pdb::now(); 
-         $update_fields['date_modified'] = Pdb::now(); 
-         Pdb::insert('page_revisions', $update_fields); 
-   
-         // Admin permissions 
-         if ($_POST['admin_perm_specific'] == 1-  and  @count($_POST['admin_permissions'])) {
 
-             foreach ($_POST['admin_permissions'] as $id) { 
-                 $id = (int) $id; 
-                 if ($id == 0) continue; 
-   
-                 // Create a new permission record 
-                 $update_fields = array(); 
-                 $update_fields['item_id'] = $page_id; 
-                 $update_fields['category_id'] = $id; 
-   
-                 Pdb::insert('page_admin_permissions', $update_fields); 
-             } 
-         } 
-   
-         // User permissions 
-         if (Register::hasFeature('users')) { 
-             if (@$_POST['user_perm_specific'] == 1-  and  @count($_POST['user_permissions'])) {
 
-                 foreach ($_POST['user_permissions'] as $id) { 
-                     $id = (int) $id; 
-                     if ($id == 0) continue; 
-   
-                     // Create a new permission record 
-                     $update_fields = array(); 
-                     $update_fields['item_id'] = $page_id; 
-                     $update_fields['category_id'] = $id; 
-   
-                     Pdb::insert('page_user_permissions', $update_fields); 
-                 } 
-             } 
-         } 
-   
-         // Commit 
-         Pdb::commit(); 
-   
-         Navigation::clearCache(); 
-   
-         Notification::confirm('Your page has been created. Add your content below.'); 
-   
-         return 'admin/edit/' . $this->controller_name . '/' . $page_id . '?suppress=true'; 
-     } 
-   
-   
-     /** 
-     * Return HTML for the import upload form 
-     **/ 
-     public function _importUploadForm() 
-     { 
-         $types = []; 
-         foreach (Register::getDocImports() as $ext => $details) { 
-             $types[$details[1]] = ['name' => $details[1], 'ext' => $ext]; 
-         } 
-   
-         $list = new Itemlist(); 
-         $list->main_columns = ['Type' => 'name', 'File extension' => 'ext']; 
-         $list->items = $types; 
-   
-         $view = new View('sprout/admin/page_import_upload'); 
-         $view->list = $list->render(); 
-   
-         return $view; 
-     } 
-   
-   
-     /** 
-     * Upload and do initial processing on the file 
-     **/ 
-     public function importUploadAction() 
-     { 
-         AdminAuth::checkLogin(); 
-         Csrf::checkOrDie(); 
-   
-         // Validate upload 
-             $error = 'No file provided'; 
-         } else if (! Upload::required($_FILES['import'])) { 
-             $error = 'No file provided'; 
-         } else if (! Upload::valid($_FILES['import'])) { 
-             $error = 'File upload error'; 
-         } else if (! FileUpload::checkFilename($_FILES['import']['name'])) { 
-             $error = 'File type not allowed'; 
-         } else { 
-             $error = null; 
-         } 
-   
-         // Instantiate the importer library 
-         if (! $error) { 
-             try { 
-                 $inst = DocImport::instance($_FILES['import']['name']); 
-                 $ext = File::getExt($_FILES['import']['name']); 
-             } catch (Exception $ex) { 
-                 $error = $ex->getMessage(); 
-             } 
-         } 
-   
-         // Upload file to temp dir 
-         if (! $error) { 
-             $temporig = APPPATH . "temp/import_{$timestamp}.{$ext}"; 
-   
-             $res = @copy($_FILES['import']['tmp_name'], $temporig); 
-             if (! $res) { 
-                 $error = 'Unable to copy file to temporary directory'; 
-             } 
-         } 
-   
-         // Do file processing 
-         if (! $error) { 
-             try { 
-                 $result = $inst->load($temporig); 
-             } catch (Exception $ex) { 
-                 $error = $ex->getMessage(); 
-             } 
-   
-         } 
-   
-         // Check the result is valid XML 
-         if (! $error) { 
-             if (!($result instanceof DOMDocument)) { 
-                 $dom = new DOMDocument(); 
-                 $success = @$dom->loadXML($result); 
-                 if (! $success) { 
-                     $error = 'Conversion failed'; 
-   
-                         Notification::error($err->message . ' (' . $err->code . ') at ' . $err->line . ':' . $err->column); 
-                     } 
-   
-                     chmod(- APPPATH  . "temp/conversion_failure.xml", 0666);
 
-                 } 
-             } 
-         } 
-   
-         // Save XML file 
-         if (! $error) { 
-             $tempxml = APPPATH . "temp/import_{$timestamp}.xml"; 
-   
-             if ($result instanceof DOMDocument) { 
-                 $result->save($tempxml); 
-   
-   
-             } else { 
-                 $error = 'Unable to save temp xml'; 
-             } 
-         } 
-   
-         // Report error 
-         if ($error) { 
-             Notification::error($error); 
-             Url::redirect("admin/import_upload/page"); 
-         } 
-   
-         Url::redirect("admin/import_options/page?timestamp={$timestamp}&ext=xml"); 
-     } 
-   
-   
-     /** 
-     * Preview the pages which will be created 
-     **/ 
-     public function importPreviewAjax() 
-     { 
-         AdminAuth::checkLogin(); 
-         $_GET['timestamp'] = (int) $_GET['timestamp']; 
-         $filename = APPPATH . "temp/import_{$_GET['timestamp']}.xml"; 
-   
-         echo '<div class="info highlight-confirm">This is a preview of the pages which will be created</div>'; 
-   
-         switch ($_GET['import_type']) { 
-             case 'none': 
-                 echo '<ul>'; 
-                 echo '<li>', ($_GET['page_name'] ? Enc::html($_GET['page_name']) : '<i>Enter a page name into the field above</i>'), '</li>'; 
-                 echo '</ul>'; 
-                 break; 
-   
-             case 'heading': 
-                 $tree = DocImport::getHeadingsTree($filename, $_GET['heading_level']); 
-   
-                 if (trim($_GET['top_page_name'])) { 
-                     $tree['name'] = trim($_GET['top_page_name']); 
-                     $new_root = new Treenode(); 
-                     $new_root->children = array($tree); 
-                     $tree->parent = $new_root; 
-                     $tree = $new_root; 
-                 } 
-   
-                 echo '<ul>'; 
-                 foreach ($tree->children as $child) { 
-                     self::renderPreviewTreenode($child); 
-                 } 
-                 echo '</ul>'; 
-                 break; 
-   
-             default: 
-                 echo '<p><i>Invalid import type</i></p>'; 
-         } 
-     } 
-   
-   
-     /** 
-     * Render a single node for the preview tree we return in `import_preview_ajax` 
-     **/ 
-     private static function renderPreviewTreenode($node) 
-     { 
-         echo '<li>', Enc::html($node['name']); 
-   
-         if (count($node->children)) { 
-             echo '<ul>'; 
-             foreach ($node->children as $child) { 
-                 self::renderPreviewTreenode($child); 
-             } 
-             echo '</ul>'; 
-         } 
-   
-         echo '</li>'; 
-     } 
-   
-   
-     /** 
-     * Returns a form which contains options for doing an import 
-     **/ 
-     public function _getImport($filename) 
-     { 
-         $view = new View('sprout/admin/page_import_options'); 
-   
-             'title' => 'Document import', 
-             'content' => $view->render(), 
-         ); 
-     } 
-   
-   
-     /** 
-     * Facebox info box 
-     **/ 
-     public function importNotes($view_name) 
-     { 
-         AdminAuth::checkLogin(); 
-         $view = new View('sprout/doc_import_notes/' . $view_name); 
-   
-         echo '<div class="import-notes">'; 
-         echo $view->render(); 
-         echo '</div>'; 
-     } 
-   
-   
-     /** 
-     * Does the actual import 
-     * 
-     * @param string $filename The location of the import data, in a temporary directory 
-     **/ 
-     public function _importData($filename) 
-     { 
-   
-         $operator = AdminAuth::getDetails(); 
-         if (! $operator) return false; 
-   
-         // Basic validation 
-         if ($_POST['import_type'] != 'none' and $_POST['import_type'] != 'heading') { 
-             return false; 
-         } 
-   
-         if ($_POST['import_type'] == 'none' and !$_POST['page_name']) { 
-             return false; 
-         } 
-   
-         // Load images, save mapping into $images 
-         $cat_id = Category::lookupOrCreate('files', 'Imported document images'); 
-         $resources = DocImport::getResources($filename); 
-         foreach ($resources as $resname => $blob) { 
-             $image_filename = File::filenameMakeSane('doc_' . $resname); 
-   
-   
-             Pdb::transact(); 
-   
-             // Add file record 
-             $update_fields = array(); 
-             $update_fields['name'] = $resname; 
-             $update_fields['type'] = FileConstants::TYPE_IMAGE; 
-             $update_fields['date_added'] = Pdb::now(); 
-             $update_fields['date_modified'] = Pdb::now(); 
-             $update_fields['date_file_modified'] = Pdb::now(); 
-             $update_fields['sha1'] = hash('sha1', $blob, false); 
-   
-             $file_id = Pdb::insert('files', $update_fields); 
-             $image_filename = $file_id . '_' . $image_filename; 
-   
-             // Set filename to contain file id 
-             $update_fields = array(); 
-             $update_fields['filename'] = $image_filename; 
-             Pdb::update('files', $update_fields, ['id' => $file_id]); 
-   
-             // categorise 
-             Category::insertInto('files', $file_id, $cat_id); 
-   
-             // insert the blob of data 
-             File::putString($image_filename, $blob); 
-   
-             File::createDefaultSizes($image_filename); 
-   
-             Pdb::commit(); 
-   
-   
-             // If the image is large, auto-switch in the medium size 
-             $size = File::imageSize($image_filename); 
-             $small = File::getResizeFilename($image_filename, 'medium'); 
-             if ($size[0] > 300-  and  File::exists($small)) {
 
-                 $image_filename = $small; 
-             } 
-   
-             $images[$resname] = File::relUrl($image_filename); 
-         } 
-   
-         // Split into pages based on options 
-         switch ($_POST['import_type']) { 
-             case 'none': 
-                 $dom = new DOMDocument(); 
-                 $body = $dom->saveXML($dom->getElementsByTagName('body')->item(0)); 
-   
-                 $tree = new Treenode(); 
-                 $node = new Treenode(); 
-                 $node['name'] = $_POST['page_name']; 
-                 $node['body'] = $body; 
-                 $tree->children[] = $node; 
-   
-                 $headings[1] = 2; 
-                 break; 
-   
-             case 'heading': 
-                 $tree = DocImport::getHeadingsTree($filename, $_POST['heading_level'], true); 
-   
-                 if ($_POST['heading_level'] > 1) { 
-                     for ($i = $_POST['heading_level'] + 1; $i < 6; $i++) { 
-                         $headings[$i] = $i - 1; 
-                     } 
-                 } 
-   
-                 if (trim($_POST['top_page_name'])) { 
-                     $tree['name'] = trim($_POST['top_page_name']); 
-                     $new_root = new Treenode(); 
-                     $new_root->children = array($tree); 
-                     $tree->parent = $new_root; 
-                     $tree = $new_root; 
-                 } 
-                 break; 
-   
-             default: 
-                 throw new Exception("Invalid import type '{$_POST['import_type']}'."); 
-         } 
-   
-         // Walk page tree and create pages 
-         $count = 0; 
-         Pdb::transact(); 
-         foreach ($tree->children as $child) { 
-             $result = $this->createPageTreenode($child, (int)$_POST['parent_id'], $images, $headings, $operator); 
-             if ($result === false) return false; 
-             $count += $result; 
-         } 
-         Pdb::commit(); 
-   
-         Notification::confirm('Imported ' . $count . ' ' . Inflector::plural('page', $count)); 
-         return true; 
-     } 
-   
-   
-     /** 
-     * Create a page 
-     **/ 
-     private function createPageTreenode($node, $parent_id, $images, $headings, $operator) 
-     { 
-         $dom = new DOMDocument(); 
-         $success = $dom->loadXML('<doc><body>' . $node['body'] . '</body></doc>'); 
-         $html = DocImport::getHtml($dom, $images, $headings); 
-   
-         // Add page 
-         $update_fields = []; 
-         $update_fields['name'] = trim($node['name']); 
-         $update_fields['slug'] =-  Enc ::urlname(trim($node['name']), '-');
 
-         $update_fields['active'] = 1; 
-         $update_fields['show_in_nav'] = 1; 
-         $update_fields['parent_id'] = $parent_id; 
-         $update_fields['subsite_id'] = $_SESSION['admin']['active_subsite']; 
-         $update_fields['modified_editor'] = $operator['name']; 
-         $update_fields['date_added'] = Pdb::now(); 
-         $update_fields['date_modified'] = Pdb::now(); 
-         $page_id = Pdb::insert('pages', $update_fields); 
-   
-         $this->fixRecordOrder($page_id); 
-   
-         // Add revision 
-         $update_fields = array(); 
-         $update_fields['page_id'] = $page_id; 
-         $update_fields['type'] = 'standard'; 
-         $update_fields['changes_made'] = 'Imported page from uploaded file'; 
-         $update_fields['status'] = 'live'; 
-         $update_fields['modified_editor'] = $operator['name']; 
-         $update_fields['date_added'] = Pdb::now(); 
-         $update_fields['date_modified'] = Pdb::now(); 
-         $rev_id = Pdb::insert('page_revisions', $update_fields); 
-   
-         // Add content block 
-         $settings = [ 
-             'text' => $html, 
-         ]; 
-         $update_fields = array(); 
-         $update_fields['page_revision_id'] = $rev_id; 
-         $update_fields['area_id'] = 1; 
-         $update_fields['active'] = 1; 
-         $update_fields['type'] = 'RichText'; 
-         $update_fields['record_order'] = 1; 
-         Pdb::insert('page_widgets', $update_fields); 
-   
-         // History page 
-         $res = $this->addHistoryItem($page_id, "Imported page from uploaded file"); 
-         if (! $res) return false; 
-   
-         // Do indexing on the page text 
-         $res = $this->reindexItem($page_id, $node['name'], $html); 
-         if (! $res) return false; 
-   
-         // Children pages 
-         $count = 1; 
-         foreach ($node->children as $child) { 
-             $count += $this->createPageTreenode($child, $page_id, $images, $headings, $operator); 
-         } 
-   
-         return $count; 
-     } 
-   
-   
-     public function _getCustomEditSaveHTML($item_id) 
-     { 
-         // N.B. this is called after the edit form has been rendered 
-   
-         $user_id = AdminAuth::getId(); 
-         $q = "SELECT operators.id, operators.name 
-             FROM ~operators AS operators 
-             INNER JOIN ~operators_cat_join AS joiner ON joiner.operator_id = operators.id 
-                 AND operators.id != ? 
-             INNER JOIN ~operators_cat_list AS cat ON joiner.cat_id = cat.id 
-             WHERE cat.access_noapproval = 1 
-             ORDER BY operators.name"; 
-         $approval_admins = Pdb::q($q, [$user_id], 'map'); 
-   
-         $view = new View('sprout/admin/page_edit_save'); 
-         $view->id = (int) $item_id; 
-         $view->preview_url = Subsites::getAbsRootAdmin() . 'admin/call/page/preview/' . $item_id; 
-         $view->approval_admins = $approval_admins; 
-         $view->allow_delete = $this->_isDeleteSaved($item_id); 
-   
-         $view->type = $this->edit_type; 
-   
-         return $view->render(); 
-     } 
-   
-   
-     /** 
-      * Return the URL to use for the 'view live site' button, when editing a given record 
-      * 
-      * @param int $item_id Record which is being editied 
-      * @return string URL, either absolute or relative 
-      * @return null Default url should be used 
-      */ 
-     public function _getEditLiveUrl($item_id) 
-     { 
-         return Page::url($item_id); 
-     } 
-   
-   
-     /** 
-     * Returns the edit form for editing the specified page 
-     * 
-     * @param int $id The record to show the edit form for 
-     * @return string The HTML code which represents the edit form 
-     **/ 
-     public function _getEditForm($id) 
-     { 
-         $id = (int) $id; 
-   
-         // Get subsite info 
-         $q = "SELECT * FROM ~subsites WHERE id = ?"; 
-         try { 
-             $subsite = Pdb::q($q, [$_SESSION['admin']['active_subsite']], 'row'); 
-         } catch (QueryException $ex) { 
-             return new AdminError("Invalid id specified - current subsite does not exist"); 
-         } 
-   
-         // Load the page 
-         $q = "SELECT * FROM ~pages WHERE id = ?"; 
-         try { 
-             $page = Pdb::q($q, [$id], 'row'); 
-         } catch (QueryException $ex) { 
-             return new AdminError("Invalid id specified - page does not exist"); 
-         } 
-   
-         TinyMCE4RichText::needs(); 
-   
-         // If no slug set, create one 
-         if (empty($page['slug'])) $page['slug'] =-  Enc ::urlname($page['name']);
 
-   
-         // Check the permissions of the page - can the operator edit this page? 
-         $res = AdminPerms::checkPermissionsTree('pages', $id); 
-         if (! $res) return new AdminError("Access denied to modify this page"); 
-   
-         // Load the revisions 
-         $q = "SELECT page_revisions.*, DATE_FORMAT(date_modified, '%d/%m/%Y %h:%i %p') AS date_modified 
-             FROM ~page_revisions AS page_revisions 
-             WHERE page_id = ? 
-             ORDER BY page_revisions.date_modified DESC"; 
-         $revs = Pdb::q($q, [$id], 'arr'); 
-             return new AdminError("Invalid id specified - page does not have any revisions"); 
-         } 
-   
-         // Select the revision to edit 
-         // If there is a rev in the session, use it. 
-         // Otherwise, get the latest live revision. 
-         // If all else fails, use the latest revision 
-         $sel_rev = ['id' => 0]; 
-         $rev_num = 0; 
-         if (!empty($_SESSION['admin']['field_values']['rev_id'])) { 
-             foreach ($revs as $i => $rev) { 
-                 if ($rev['id'] == $_SESSION['admin']['field_values']['rev_id']) { 
-                     $sel_rev = $rev; 
-                     $rev_num = count($revs) - $i; 
-                     break; 
-                 } 
-             } 
-   
-         } else if (!empty($_GET['revision'])) { 
-             $rev_id = (int)$_GET['revision']; 
-             foreach ($revs as $i => $rev) { 
-                 if ($rev['id'] == $rev_id) { 
-                     $sel_rev = $rev; 
-                     $rev_num = count($revs) - $i; 
-                     break; 
-                 } 
-             } 
-   
-         } else { 
-             $sel_rev = $revs[0]; 
-             foreach ($revs as $rev) { 
-                 if ($rev['status'] == 'live') { 
-                     $sel_rev = $rev; 
-                     break; 
-                 } 
-             } 
-         } 
-   
-         // If there's no live revision, inform the user 
-         $has_live_rev = false; 
-         foreach ($revs as $rev) { 
-             if ($rev['status'] == 'live') { 
-                 $has_live_rev = true; 
-                 break; 
-             } 
-         } 
-   
-   
-         // Type override caused by clicking a sidebar 'change to' option 
-         if (in_array(@$_GET['type'],-  Pdb ::extractEnumArr('page_revisions', 'type'))) {
 
-             $data['type'] = $_GET['type']; 
-         } 
-   
-         // Remember the edit type for use in sidebar; i.e. _getCustomEditSaveHTML 
-         $this->edit_type = $data['type']; 
-   
-         if ($sel_rev['status'] != 'wip') { 
-             $data['changes_made'] = ''; 
-         } 
-   
-         if ($data['status'] != 'wip' and $data['status'] != 'auto_launch') { 
-             if (AdminPerms::canAccess('access_noapproval')) { 
-                 $data['status'] = 'live'; 
-             } else { 
-                 $data['status'] = 'need_approval'; 
-             } 
-         } 
-   
-         if ($data['type'] == 'standard') { 
-             // Load widgets and collate rich text as page text 
-             $text = ''; 
-             $widgets = []; 
-             $q = "SELECT area_id, type, settings, conditions, active, heading, template 
-                 FROM ~page_widgets 
-                 WHERE page_revision_id = ? 
-                 ORDER BY area_id, record_order"; 
-             $wids = Pdb::q($q, [$sel_rev['id']], 'arr'); 
-   
-             foreach ($wids as $widget) { 
-                 $widgets[$widget['area_id']][] = $widget; 
-   
-                 // Embedded rich text widgets 
-                 if ($widget['area_id'] == 1 and $widget['type'] == 'RichText') { 
-                     if ($text) $text .= "\n"; 
-                     $text .= $settings['text']; 
-                 } 
-             } 
-   
-   
-             // Load media 
-             $media = []; 
-             foreach ($matches[1] as $match) { 
-                 $media[] = $match; 
-             } 
-   
-             AdminSeo::setTopic($page['name']); 
-             AdminSeo::setSlug($data['slug']); 
-             AdminSeo::addContent($text); 
-             AdminSeo::addLinks(Page::determineRelatedLinks($id)); 
-   
-         } else if (in_array($data['type'], ['tool', 'redirect'])) { 
-             $widgets = []; 
-   
-         } else { 
-             return new AdminError("Invalid page type"); 
-         } 
-   
-         // Load permissions for page 
-         $admin_permissions = AdminPerms::getAccessableGroups('pages', $id); 
-         if ($data['admin_perm_type'] == Constants::PERM_SPECIFIC) { 
-             $data['admin_perm_specific'] = 1; 
-         } else { 
-             $data['admin_perm_specific'] = 0; 
-         } 
-   
-         $data['admin_permissions'] = $admin_permissions; 
-   
-         $user_permissions = UserPerms::getAccessableGroups('pages', $id); 
-         if ($data['user_perm_type'] == Constants::PERM_SPECIFIC) { 
-             $data['user_perm_specific'] = 1; 
-         } else { 
-             $data['user_perm_specific'] = 0; 
-         } 
-   
-         $data['user_permissions'] = $user_permissions; 
-   
-   
-         // Overlay session data 
-         if (!empty($_SESSION['admin']['field_values'])) { 
-             $data = array_merge($data, $_SESSION['admin']['field_values']); 
-             unset ($_SESSION['admin']['field_values']); 
-         } 
-   
-         // Load history 
-         $q = "SELECT modified_editor, changes_made, 
-                     DATE_FORMAT(date_added, '%d/%m/%Y %h:%i %p') AS date_added 
-             FROM ~page_history_items AS page_history_items 
-             WHERE page_id = ? 
-             ORDER BY page_history_items.date_added DESC"; 
-         $history = Pdb::q($q, [$id], 'arr'); 
-   
-         // Controller list for entrance dropdown 
-         $front_end_controllers = Register::getFrontEndControllers(); 
-         asort($front_end_controllers); 
-   
-         // Load entrance arguments 
-         $controller_arguments = array(); 
-         if ($data['controller_entrance']) { 
-             $inst = Sprout::instance($data['controller_entrance']); 
-             if ($inst instanceof FrontEndEntrance) { 
-                 $controller_arguments = $inst->_getEntranceArguments(); 
-                 if (empty($controller_arguments)) { 
-                     $controller_arguments = array('' => '- Nothing available -'); 
-                 } 
-             } 
-         } 
-   
-         $templates = Subsites::getConfigAdmin('skin_views'); 
-         if (! $templates) $templates = array('skin/inner' => 'Inner'); 
-   
-   
-         // Custom attributes 
-         $attributes = MultiEdit::load('page_attributes', ['page_id' => $id]); 
-         if (! isset($data['multiedit_attrs'])) { 
-             $data['multiedit_attrs'] = $attributes; 
-         } 
-   
-         // Load admin notes, if found 
-         $admin_notes = null; 
-         foreach ($attributes as $row) { 
-             if ($row['name'] == 'sprout.admin_notes') { 
-                 $admin_notes = trim($row['value']); 
-                 break; 
-             } 
-         } 
-   
-         // Special case for redirect pages 
-         if (!$admin_notes and $data['type'] == 'redirect') { 
-             if (!empty($data['redirect'])) { 
-                 $typename = Lnk::typename($data['redirect']); 
-                     $admin_notes = 'This page redirects to an ' . $typename . '. Content blocks on this page have been disabled.'; 
-                 } else { 
-                     $admin_notes = 'This page redirects to a ' . $typename . '. Content blocks on this page have been disabled.'; 
-                 } 
-             } else { 
-                 $admin_notes = 'This page will redirect. Content blocks on this page have been disabled.'; 
-             } 
-         } 
-   
-         // Richtext width and height 
-         $richtext_width = Kohana::config('sprout.admin_richtext_width'); 
-         $richtext_height = Kohana::config('sprout.admin_richtext_height'); 
-         if (!$richtext_width) $richtext_width = 700; 
-         if (!$richtext_height) $richtext_height = 500; 
-   
-         // View 
-         $view = new View('sprout/admin/page_edit'); 
-   
-         $errors = []; 
-         if (!empty($_SESSION['admin']['field_errors'])) { 
-             $errors = $_SESSION['admin']['field_errors']; 
-             unset($_SESSION['admin']['field_errors']); 
-         } 
-   
-         $view->id = $id; 
-         $view->page = $page; 
-         $view->subsite = $subsite; 
-         $view->data = $data; 
-         $view->errors = $errors; 
-         $view->widgets = $widgets; 
-         $view->history = $history; 
-         $view->admin_category_options = AdminAuth::getAllCategories(); 
-         $view->admin_permissions = $admin_permissions; 
-         $view->user_category_options = UserPerms::getAllCategories(); 
-         $view->user_permissions = $user_permissions; 
-         $view->can_approve_revisions = AdminPerms::canAccess('access_noapproval'); 
-         $view->front_end_controllers = $front_end_controllers; 
-         $view->controller_arguments = $controller_arguments; 
-         $view->templates = $templates; 
-         $view->admin_notes = $admin_notes; 
-         $view->richtext_width = $richtext_width; 
-         $view->richtext_height = $richtext_height; 
-   
-         $view->revs = $revs; 
-         $view->sel_rev_id = $sel_rev['id']; 
-         $view->has_live_rev = $has_live_rev; 
-   
-         if ($data['type'] == 'standard') { 
-             $view->text = $text; 
-             $view->media = $media; 
-         } 
-   
-         $view->show_tour = !Admin::isTourCompleted('page_edit'); 
-   
-         if ($rev_num) { 
-             $title = 'Editing revision ' . $rev_num . ' of page <strong>' . Enc::html($page['name']) . '</strong>'; 
-         } else { 
-             $title = 'Editing page <strong>' . Enc::html($page['name']) . '</strong>'; 
-         } 
-   
-             'title' => $title, 
-             'content' => $view->render() 
-         ); 
-     } 
-   
-     /** 
-     * Gets the text of a single revision 
-     * 
-     * @param int $id The revision to get the text of 
-     **/ 
-     public function ajaxGetRev($id) 
-     { 
-         $id = (int) $id; 
-   
-         $rev = Pdb::get('page_revisions', $id); 
-   
-         $out['text'] = $rev['text']; 
-         $out['date_launch'] = ''; 
-   
-         switch ($rev['status']) { 
-             case 'wip': 
-             case 'auto_launch': 
-                 $out['changes_made'] = $rev['changes_made']; 
-                 $out['status'] = $rev['status']; 
-                 $out['date_launch'] = $rev['date_launch']; 
-                 break; 
-   
-             case 'need_approval': 
-                 $out['changes_made'] = $rev['changes_made']; 
-                 $out['status'] = 'live'; 
-                 break; 
-   
-             case 'live': 
-                 $out['changes_made'] = ''; 
-                 $out['status'] = 'live'; 
-                 break; 
-   
-             case 'old': 
-             case 'rejected': 
-                 $changes = preg_replace('/ ?\(based.+/', '', $rev['changes_made']); 
-                 $out['changes_made'] = "...... (based on revision {$rev['id']}: '{$changes}')"; 
-                 $out['status'] = 'live'; 
-                 break; 
-         } 
-   
-         Json::out($out); 
-     } 
-   
-   
-     /** 
-     * Return a list of menu groups for a selected parent page 
-     **/ 
-     public function ajaxGetMenuGroups($parent_page_id) 
-     { 
-         AdminAuth::checkLogin(); 
-         $parent_page_id = (int) $parent_page_id; 
-   
-         // Special case for top-level 
-         if ($parent_page_id === 0) { 
-             return; 
-         } 
-   
-         // Find the page 
-         $root = Navigation::loadPageTree($_SESSION['admin']['active_subsite'], true); 
-         $node = $root->findNodeValue('id', $parent_page_id); 
-         if ($node === null) Json::error('Invalid parent page'); 
-   
-         // Get the groups 
-         $anc = $node->findAncestors(); 
-         $top_parent = $anc[0]; 
-         $groups = NavigationGroups::getGroupsAdmin($top_parent['id']); 
-   
-         foreach ($groups as $id => $row) { 
-             $names[$id] = $row['name']; 
-         } 
-   
-         Json ::confirm(array('groups' => $names));
-     } 
-   
-   
-     /** 
-     * Makes the provided html text be in a standard format to ensure the integrity of the change check 
-     **/ 
-     private function convertForChangeCheck($text) 
-     { 
-     } 
-   
-     /** 
-     * Saves the provided POST data into this page in the database 
-     * 
-     * @param int $page_id The record to update 
-     * @param bool True on success, false on failure 
-     **/ 
-     public function _editSave($page_id) 
-     { 
-         $res = AdminPerms::checkPermissionsTree('pages', $page_id); 
-         if (! $res) return false; 
-   
-         $page_id = (int) $page_id; 
-         $rev_id = (int) $_POST['rev_id']; 
-   
-         $q = "SELECT page.*, rev.type, rev.controller_entrance, rev.controller_argument, rev.redirect 
-             FROM ~pages AS page 
-             INNER JOIN ~page_revisions AS rev ON page.id = rev.page_id 
-                 AND rev.id = ? 
-             WHERE page.id = ?"; 
-         $orig_page = Pdb::q($q, [$rev_id, $page_id], 'row'); 
-   
-         $revision_changed = false; 
-         $page_type = (string) @$_POST['type']; 
-         if (!in_array($page_type,-  Pdb ::extractEnumArr('page_revisions', 'type'))) {
 
-             $page_type = $orig_page['type']; 
-         } 
-   
-         if ($page_type != $orig_page['type']) $revision_changed = true; 
-   
-         // Collate POSTed widgets. 
-         $new_widgets = []; 
-         if (@count($_POST['widgets'])) { 
-             foreach ($_POST['widgets'] as $area_name => $widgets) { 
-                 $area = WidgetArea::findAreaByName($area_name); 
-                 if ($area == null) continue; 
-   
-                 $order = 0; 
-                 foreach ($widgets as $info) { 
-   
-                     // If it's been deleted, then skip over all other processing 
-                     if ($_POST['widget_deleted'][$area_name][$index] == '1') { 
-                         continue; 
-                     } 
-   
-                     $settings = @$_POST['widget_settings_' . $index]; 
-                     if (!is_array($settings)) $settings = []; 
-   
-   
-                     $active = 1; 
-                     if (isset($_POST['widget_active'][$area_name][$index])) { 
-                         $active = (int) (bool) $_POST['widget_active'][$area_name][$index]; 
-                     } 
-   
-                     $conditions = ''; 
-                     if (isset($_POST['widget_conds'][$area_name][$index])) { 
-                         $conditions = $_POST['widget_conds'][$area_name][$index]; 
-                     } 
-   
-                     $heading = ''; 
-                     if (isset($_POST['widget_heading'][$area_name][$index])) { 
-                         $heading = $_POST['widget_heading'][$area_name][$index]; 
-                     } 
-   
-                     $template = ''; 
-                     if (isset($_POST['widget_template'][$area_name][$index])) { 
-                         $template = $_POST['widget_template'][$area_name][$index]; 
-                     } 
-   
-                     $new_widgets[] = [ 
-                         'area_id' => $area->getIndex(), 
-                         'active' => $active, 
-                         'type' => $type, 
-                         'settings' => $settings, 
-                         'conditions' => $conditions, 
-                         'heading' => $heading, 
-                         'template' => $template, 
-                         'record_order' => $order++, 
-                     ]; 
-                 } 
-             } 
-         } 
-   
-         // Compare new widgets with old ones -- if changed, need a new revision 
-         $q = "SELECT area_id, active, type, settings, conditions, heading, template, record_order 
-             FROM ~page_widgets 
-             WHERE page_revision_id = ? 
-             ORDER BY area_id, record_order"; 
-         $old_widgets = Pdb::query($q, [$rev_id], 'arr'); 
-             $revision_changed = true; 
-         } else { 
-             foreach ($old_widgets as $key => $widget) { 
-                 if ($widget != @$new_widgets[$key]) { 
-                     $revision_changed = true; 
-                     break; 
-                 } 
-             } 
-         } 
-   
-         // Get the original revision, see if it has changed 
-         try { 
-             $q = "SELECT rev.*, page.parent_id 
-                 FROM ~page_revisions AS rev 
-                 INNER JOIN ~pages AS page ON page.id = rev.page_id 
-                 WHERE rev.id = ?"; 
-             $orig_rev = Pdb::q($q, [$rev_id], 'row'); 
-         } catch (RowMissingException $ex) { 
-             // Pretend there's an existing revision when going a page preview 
-             $orig_rev = ['status' => null, 'date_launch' => null]; 
-         } 
-   
-         if ($_POST['status'] != $orig_rev['status']) $revision_changed = true; 
-   
-         if ($_POST['status'] == 'auto_launch') { 
-             if ($_POST['date_launch'] != $orig_rev['date_launch']) $revision_changed = true; 
-         } else { 
-             $_POST['date_launch'] = null; 
-         } 
-   
-         if ($page_type == 'standard') { 
-             if (@count($_POST['mediareplace_fr'])) { 
-                 foreach($_POST['mediareplace_fr'] as $idx => $replace_from) { 
-                     $replace_to = $_POST['mediareplace_to'][$idx]; 
-   
-                     if (! $replace_to) continue; 
-                     if ($replace_to == $replace_from) continue; 
-   
-                     $resized = File::getResizeFilename($replace_to, 'medium'); 
-                     if (File::exists($resized)) $replace_to = $resized; 
-                     $replace_to = File::relUrl($replace_to); 
-   
-                     foreach ($new_widgets as &$widget) { 
-                         if ($widget['area_id'] != 1 or $widget['type'] != 'RichText') continue; 
-                         $new_text = preg_replace('/<img(.*?)src="' . preg_quote($replace_from, '/') . '"(.*?)>/', "<img\$1src=\"{$replace_to}\"\$2/>", $settings['text']); 
-                         if ($new_text != $settings['text']) { 
-                             $settings['text'] = $new_text; 
-                             $revision_changed = true; 
-                         } 
-                     } 
-                 } 
-             } 
-         } else if ($page_type == 'tool') { 
-             if ($orig_page['controller_entrance'] != $_POST['controller_entrance']) $revision_changed = true; 
-             if ($orig_page['controller_argument'] != $_POST['controller_argument']) $revision_changed = true; 
-         } else if ($page_type == 'redirect') { 
-             if ($orig_page['redirect'] != $_POST['redirect']) $revision_changed = true; 
-         } 
-   
-         // Check if the parent changed 
-         $parent_changed = false; 
-         if ((int) $orig_page['parent_id'] != (int) $_POST['parent_id']) { 
-             $parent_changed = true; 
-         } 
-   
-         if (empty($_POST['controller_argument'])) { 
-             $_POST['controller_argument'] = ''; 
-         } 
-   
-         // Set up validation rules 
-         $valid = new Validator($_POST); 
-         $valid->setLabels([ 
-             'parent_id' => 'Parent page', 
-             'slug' => 'URL slug', 
-             'gallery_thumb' => 'Gallery thumbnail', 
-         ]); 
-   
-         $valid->required(['name', 'slug']); 
-         $valid->check('name', 'Validity::length', 1, 200); 
-         $valid->check('slug', 'Validity::length', 1, 200); 
-         $valid->check('slug', 'Slug::valid'); 
-   
-         $slug_conditions = [ 
-             'subsite_id' => $_SESSION['admin']['active_subsite'], 
-             'parent_id' => (int)$_POST['parent_id'], 
-             ['id', '!=', $page_id], 
-         ]; 
-         $valid->check('slug', 'Slug::unique', 'pages', $slug_conditions); 
-   
-         $valid->check('meta_keywords', 'Validity::length', 0, 200); 
-         $valid->check('meta_description', 'Validity::length', 0, 200); 
-         $valid->check('alt_browser_title', 'Validity::length', 0, 200); 
-         $valid->check('alt_nav_title', 'Validity::length', 0, 200); 
-   
-         if ($page_type == 'standard') { 
-             $valid->check('redirect', 'Validity::length', 0, 200); 
-   
-             if ($revision_changed) { 
-                 $valid->check('changes_made', 'Validity::length', 0, 250); 
-             } 
-   
-             if ($_POST['status'] == 'need_approval') { 
-                 $valid->required(['approval_operator_id']); 
-   
-                 try { 
-                     $q = "SELECT * FROM ~operators WHERE ID = ?"; 
-                     $approval_operator = Pdb::query($q, [(int) $_POST['approval_operator_id']], 'row'); 
-                 } catch (RowMissingException $ex) { 
-                     $valid->addFieldError('approval_operator_id', 'Invalid value'); 
-                 } 
-             } 
-   
-             if ($_POST['status'] == 'auto_launch') { 
-                 $valid->required(['date_launch']); 
-             } 
-   
-         } else if ($page_type == 'tool') { 
-             $valid->required(['controller_entrance', 'controller_argument']); 
-             $valid->check('controller_entrance', 'Validity::length', 1, 200); 
-             if (!self::checkControllerEntrance($_POST['controller_entrance'], $page_id)) { 
-                 $valid->addFieldError('controller_entrance', 'Invalid value'); 
-             } 
-         } else if ($page_type == 'redirect') { 
-             $valid->required(['redirect']); 
-             $valid->check('redirect', function($value) { 
-                 if (!Lnk::valid($_POST['redirect'])) { 
-                     throw new ValidationException('Invalid redirect target'); 
-                 } 
-             }); 
-         } 
-   
-         if ($orig_page['id'] == $_POST['parent_id']) { 
-             $valid->addFieldError('parent_id', 'A page can\'t be its own parent.'); 
-         } 
-   
-         if ($parent_changed) { 
-             $root_node = Navigation::loadPageTree($_SESSION['admin']['active_subsite'], true); 
-             $new_parent = $root_node->findNodeValue('id', $_POST['parent_id']); 
-             $ancestors = $new_parent->findAncestors(); 
-   
-             foreach ($ancestors as $anc) { 
-                 if ($anc['id'] == $page_id) { 
-                     $valid->addFieldError('parent_id', 'You can\'t set a descendent of this page as its parent'); 
-   
-                     break; 
-                 } 
-             } 
-         } 
-   
-         // Check validation 
-         if ($valid->hasErrors()) { 
-             $_SESSION['admin']['field_values'] = $_POST; 
-             $_SESSION['admin']['field_errors'] = $valid->getFieldErrors(); 
-             $valid->createNotifications(); 
-             return false; 
-         } 
-   
-         $operator = AdminAuth::getDetails(); 
-         if (! $operator) return false; 
-   
-         // Start transaction 
-         Pdb::transact(); 
-   
-         // Update page 
-         $update_fields = []; 
-         $update_fields['date_modified'] = Pdb::now(); 
-         $update_fields['name'] = $_POST['name']; 
-         $update_fields['slug'] = Enc::urlname($_POST['slug'], '-'); 
-         $update_fields['active'] = (int) (bool) @$_POST['active']; 
-         $update_fields['show_in_nav'] = (int) (bool) @$_POST['show_in_nav']; 
-         $update_fields['meta_keywords'] = $_POST['meta_keywords']; 
-         $update_fields['meta_description'] = $_POST['meta_description']; 
-   
-         if ($page_type == 'standard') { 
-             if ($_POST['stale_age'] === '') { 
-                 $update_fields['stale_age'] = null; 
-             } else { 
-                 $update_fields['stale_age'] = (int) $_POST['stale_age']; 
-             } 
-         } 
-   
-         $update_fields['alt_browser_title'] = $_POST['alt_browser_title']; 
-         $update_fields['alt_nav_title'] = $_POST['alt_nav_title']; 
-         $update_fields['date_expire'] = $_POST['date_expire']; 
-         $update_fields['modified_editor'] = $operator['name']; 
-         $update_fields['menu_group'] = (int) @$_POST['menu_group']; 
-         if (Kohana::config('page.enable_banners')) { 
-             $update_fields['banner'] = !empty($_POST['banner'])-  ?  $_POST['banner'] : null;
 
-         } 
-   
-         $update_fields['gallery_thumb'] = !empty($_POST['gallery_thumb'])-  ?  $_POST['gallery_thumb'] : null;
 
-   
-         if ($_POST['type'] == 'standard') { 
-             $update_fields['alt_template'] = trim(preg_replace('![^-_a-z0-9/]!i', '', $_POST['alt_template'])); 
-   
-   
-             if (Kohana::config('sprout.tweak_skin')) { 
-                 $update_fields['additional_css'] = trim($_POST['additional_css']); 
-             } 
-   
-         } 
-   
-         if (@$_POST['admin_perm_specific'] == 1) { 
-             $update_fields['admin_perm_type'] = Constants::PERM_SPECIFIC; 
-         } else { 
-             $update_fields['admin_perm_type'] = Constants::PERM_INHERIT; 
-         } 
-   
-         if (Register::hasFeature('users')) { 
-             if (@$_POST['user_perm_specific'] == 1) { 
-                 $update_fields['user_perm_type'] = Constants::PERM_SPECIFIC; 
-             } else { 
-                 $update_fields['user_perm_type'] = Constants::PERM_INHERIT; 
-             } 
-         } 
-   
-         if ($parent_changed) { 
-             $update_fields['parent_id'] = (int) $_POST['parent_id']; 
-             $update_fields['record_order'] = 0; 
-         } 
-   
-         Pdb::update('pages', $update_fields, ['id' => $page_id]); 
-   
-         if ($parent_changed) $this->fixRecordOrder($page_id); 
-   
-         // Update revision - if the text actually changed 
-         if ($revision_changed) { 
-   
-             $update_fields = []; 
-             $update_fields['type'] = $_POST['type']; 
-             $update_fields['status'] = $_POST['status']; 
-             $update_fields['operator_id'] = $operator['id']; 
-             $update_fields['modified_editor'] = $operator['name']; 
-             $update_fields['date_launch'] = $_POST['date_launch']; 
-             $update_fields['date_modified'] = Pdb::now(); 
-             $update_fields['changes_made'] = $_POST['changes_made']; 
-   
-             if ($_POST['type'] == 'redirect') { 
-                 $update_fields['redirect'] = $_POST['redirect']; 
-             } else if ($_POST['type'] == 'tool') { 
-                 $update_fields['controller_entrance'] = $_POST['controller_entrance']; 
-                 $update_fields['controller_argument'] = $_POST['controller_argument']; 
-             } 
-   
-             if ($orig_rev['status'] == 'wip' or $orig_rev['status'] == 'auto_launch') { 
-                 // Update the selected revision 
-                 Pdb::update('page_revisions', $update_fields, ['page_id' => $page_id, 'id' => $rev_id]); 
-   
-                 $res = $this->addHistoryItem($page_id, "Updated revision {$rev_id}"); 
-                 if (! $res) return false; 
-   
-             } else { 
-                 // Create a new revision 
-                 $update_fields['page_id'] = $page_id; 
-                 $update_fields['approval_operator_id'] = (int) @$_POST['approval_operator_id']; 
-                 $update_fields['date_added'] = Pdb::now(); 
-   
-                 $rev_id = Pdb::insert('page_revisions', $update_fields); 
-   
-                 $res = $this->addHistoryItem($page_id, "Created new revision {$rev_id}"); 
-                 if (! $res) return false; 
-             } 
-   
-             // Mark all other live revisions as being old 
-             if ($_POST['status'] == 'live') { 
-                 Page::activateRevision($rev_id); 
-             } 
-   
-             // Widgets 
-             Pdb::delete('page_widgets', ['page_revision_id' => $rev_id]); 
-   
-             foreach ($new_widgets as $widget) { 
-                 $update_fields = $widget; 
-                 $update_fields['page_revision_id'] = $rev_id; 
-                 Pdb::insert('page_widgets', $update_fields); 
-             } 
-         } 
-   
-         // If the save is also requesting approval, generate an approval code 
-         if ($_POST['status'] == 'need_approval') { 
-             $approval_code = Security::randStr(12); 
-             $update_fields = []; 
-             $update_fields['approval_code'] = $approval_code; 
-             Pdb::update('page_revisions', $update_fields, ['page_id' => $page_id, 'id' => $rev_id]); 
-         } 
-   
-         // Notification 
-         if (empty($this->in_preview)) { 
-             switch ($_POST['status']) { 
-             case 'need_approval': 
-                 Notification::confirm('Your new revision has been saved, and is pending approval'); 
-                 Notification::confirm('Now showing current live revision'); 
-                 break; 
-             case 'auto_launch': 
-                 $msg = 'Your new revision has been saved and will be published on '; 
-                 Notification::confirm($msg); 
-                 Notification::confirm('Now showing current live revision'); 
-                 break; 
-             case 'live': 
-                 Notification::confirm('Your changes have been saved and are now live'); 
-                 break; 
-             default: 
-                 Notification::confirm('Your changes have been saved'); 
-             } 
-         } 
-   
-   
-         // Admin permissions 
-         Pdb::delete('page_admin_permissions', ['item_id' => $page_id]); 
-   
-         if (@$_POST['admin_perm_specific'] == 1-  and  @count($_POST['admin_permissions'])) {
 
-             foreach ($_POST['admin_permissions'] as $id) { 
-                 $id = (int) $id; 
-                 if ($id == 0) continue; 
-   
-                 // Create a new permission record 
-                 $update_fields = array(); 
-                 $update_fields['item_id'] = $page_id; 
-                 $update_fields['category_id'] = $id; 
-   
-                 Pdb::insert('page_admin_permissions', $update_fields); 
-             } 
-         } 
-   
-   
-         // User permissions 
-         if (Register::hasFeature('users')) { 
-             Pdb::delete('page_user_permissions', ['item_id' => $page_id]); 
-   
-             if (@$_POST['user_perm_specific'] == 1-  and  @count($_POST['user_permissions'])) {
 
-                 foreach ($_POST['user_permissions'] as $id) { 
-                     $id = (int) $id; 
-                     if ($id == 0) continue; 
-   
-                     // Create a new permission record 
-                     $update_fields = array(); 
-                     $update_fields['item_id'] = $page_id; 
-                     $update_fields['category_id'] = $id; 
-   
-                     Pdb::insert('page_user_permissions', $update_fields); 
-                 } 
-             } 
-         } 
-   
-   
-         // Custom attributes 
-         Pdb::delete('page_attributes', ['page_id' => $page_id]); 
-   
-         if (@count($_POST['multiedit_attrs'])) { 
-             foreach ($_POST['multiedit_attrs'] as $idx => $data) { 
-                 if (MultiEdit::recordEmpty($data)) continue; 
-   
-                 $update_fields = array(); 
-                 $update_fields['page_id'] = (int) $page_id; 
-                 $update_fields['name'] = $data['name']; 
-                 $update_fields['value'] = $data['value']; 
-   
-                 Pdb::insert('page_attributes', $update_fields); 
-             } 
-         } 
-   
-   
-         // Do indexing on the page text, which is found in the embedded widgets 
-         $text =-  Page ::getText($page_id, $rev_id, $_SESSION['admin']['active_subsite']);
 
-   
-         if ($revision_changed) { 
-             if ($_POST['status'] == 'need_approval') { 
-                 // An email to the operator who is checking the revision 
-                 $view = new View('sprout/email/page_need_check'); 
-                 $view->page = $_POST; 
-                 $view->approval_operator = $approval_operator; 
-                 $view->request_operator = $operator; 
-                 $view->url = Sprout::absRoot() . "page/view_specific_rev/{$page_id}/{$rev_id}/{$approval_code}"; 
-                 $view->changes_made = $_POST['changes_made']; 
-   
-                 $mail = new Email(); 
-                 $mail->AddAddress($approval_operator['email']); 
-                 $mail->Subject = 'Page change approval required for ' . Kohana::config('sprout.site_title'); 
-                 $mail->SkinnedHTML($view->render()); 
-                 $mail->Send(); 
-   
-                 Notification::confirm("An email has been sent to {$approval_operator['name']}"); 
-   
-             } else if ($_POST['status'] == 'live' and Kohana::config('sprout.update_notify')) { 
-                 // A notification to all operators 
-                 $view = new View('sprout/email/page_notify'); 
-                 $view->page = $_POST; 
-                 $view->request_operator = $operator; 
-                 $view->url = Sprout::absRoot() . "page/view_specific_rev/{$page_id}/{$rev_id}"; 
-                 $view->changes_made = $_POST['changes_made']; 
-   
-                 $email_sql = $operator['email']; 
-                 $q = "SELECT email FROM ~operators WHERE email != '' AND email != ?"; 
-                 $res = Pdb::q($q, [$email_sql], 'pdo'); 
-                 foreach ($res as $row) { 
-                     $mail = new Email(); 
-                     $mail->AddAddress($row['email']); 
-                     $mail->Subject = 'Page updated on site ' . Kohana::config('sprout.site_title') . ': ' . $_POST['name']; 
-                     $mail->SkinnedHTML($view->render()); 
-                     $mail->Send(); 
-                 } 
-                 $res->closeCursor(); 
-             } 
-         } 
-   
-         $res = $this->reindexItem($page_id, $_POST['name'], $text); 
-         if (!$res) Notification::error('Failed to index page text'); 
-   
-   
-         if ($page_type != $orig_page['type']) { 
-             $this->addHistoryItem($page_id, "Changed the page type"); 
-             if (empty($this->in_preview))-  Notification ::confirm('Page type has been changed.');
 
-         } 
-   
-   
-         // Commit 
-         Pdb::commit(); 
-   
-         Navigation::clearCache(); 
-   
-         // Make sure operator is sent to revision they just modified, 
-         // instead of going to the current live revision 
-         if (empty($this->in_preview)) { 
-             return "admin/edit/page/{$page_id}?revision={$rev_id}"; 
-         } 
-   
-         return true; 
-     } 
-   
-   
-     /** 
-     * Page organisation tool 
-     * Bulk renaming, reordering and reparenting 
-     **/ 
-     public function _extraOrganise() 
-     { 
-         $view = new View('sprout/admin/tree_organise'); 
-         $view->root = Navigation::getRootNode(); 
-         $view->controller_name = $this->controller_name; 
-   
-             'title' => 'Organise pages', 
-             'content' => $view->render() 
-         ); 
-     } 
-   
-   
-     /** 
-     * Page organisation tool 
-     * Bulk renaming, reordering and reparenting 
-     **/ 
-     public function _extraMenuGroups() 
-     { 
-         $view = new View('sprout/admin/page_menu_groups'); 
-         $view->all_groups = NavigationGroups::getAllGroupsAdmin(); 
-         $view->all_extras = NavigationGroups::getAllExtrasAdmin(); 
-   
-         $enabled_extras = Subsites::getConfigAdmin('nav_extras'); 
-         if ($enabled_extras === null) { 
-             $enabled_extras = []; 
-         } 
-         $view->enabled_extras = $enabled_extras; 
-   
-             'title' => 'Manage menu groups', 
-             'content' => $view->render() 
-         ); 
-     } 
-   
-   
-     /** 
-     * Save the menu groups 
-     **/ 
-     public function menuGroupsAction() 
-     { 
-         AdminAuth::checkLogin(); 
-         Csrf::checkOrDie(); 
-   
-         $enabled_extras = Subsites::getConfigAdmin('nav_extras'); 
-         if ($enabled_extras === null) { 
-             $enabled_extras = array(); 
-         } 
-   
-         $all_groups = NavigationGroups::getAllGroupsAdmin(); 
-         foreach ($all_groups as $page_id => $groups) { 
-             foreach ($groups as $id => $name) { 
-                 $update_data['name'] = @$_POST['groups'][$id]['name']; 
-                 $update_data['date_modified'] = Pdb::now(); 
-   
-                 $conditions['subsite_id'] = (int)$_SESSION['admin']['active_subsite']; 
-                 $conditions['page_id'] = (int)$page_id; 
-                 $conditions['id'] = (int)$id; 
-   
-                 Pdb::update('menu_groups', $update_data, $conditions); 
-             } 
-   
-                 $update_data['subsite_id'] = (int)$_SESSION['admin']['active_subsite']; 
-                 $update_data['page_id'] = (int)$page_id; 
-   
-                 if (!empty($enabled_extras['text'])) { 
-                     $update_data['text'] = $_POST['extras'][$page_id]['text']; 
-                 } 
-                 if (!empty($enabled_extras['image'])) { 
-                     if (empty($_POST['extras'][$page_id]['image'])) { 
-                         $_POST['extras'][$page_id]['image'] = null; 
-                     } 
-                     $update_data['image'] = $_POST['extras'][$page_id]['image']; 
-                 } 
-   
-                 try { 
-                     Pdb::insert('menu_extras', $update_data); 
-                 } catch (Exception $ex) { 
-                     if (strpos($ex, 'Duplicate entry') === false) throw $ex; 
-                     unset($update_data['page_id']); 
-                     Pdb ::update('menu_extras', $update_data, array('page_id' => $page_id));
-                 } 
-             } 
-         } 
-   
-         Notification::confirm('Your changes have been saved'); 
-         Url::redirect('admin/extra/page/menu_groups'); 
-     } 
-   
-   
-     /** 
-     * Adds a history item for a page 
-     **/ 
-     private function addHistoryItem($page_id, $changes_made, $editor = null) 
-     { 
-         if ($editor == null) { 
-             $operator = AdminAuth::getDetails(); 
-             if (! $operator) return false; 
-             $editor = $operator['name']; 
-         } 
-   
-         // Create a new revision 
-         $update_fields = array(); 
-         $update_fields['page_id'] = $page_id; 
-         $update_fields['modified_editor'] = $editor; 
-         $update_fields['changes_made'] = $changes_made; 
-         $update_fields['date_added'] = Pdb::now(); 
-   
-         $res = Pdb::insert('page_history_items', $update_fields); 
-   
-         return true; 
-     } 
-   
-     /** 
-     * Returns the edit form for editing the specified page 
-     * 
-     * @param int $id The record to show the edit form for 
-     * @return string The HTML code which represents the edit form 
-     **/ 
-     public function _getDeleteForm($id) 
-     { 
-         $id = (int) $id; 
-   
-         $view = new View('sprout/admin/page_delete'); 
-         $view->id = $id; 
-   
-         // Load page details 
-         $q = "SELECT * FROM ~pages WHERE id = ?"; 
-         try { 
-             $view->page = Pdb::q($q, [$id], 'row'); 
-         } catch (QueryException $ex) { 
-             return new AdminError("Invalid id specified - page does not exist"); 
-         } 
-   
-         // Check permissions 
-         $res = AdminPerms::checkPermissionsTree('pages', $id); 
-         if (! $res) return new AdminError("Access denied to delete this page"); 
-   
-         // Children pages 
-         $root = Navigation::getRootNode(); 
-         $node = $root->findNodeValue('id', $id); 
-         $child_pages = ($node ? $node->children : []); 
-         foreach ($child_pages as $child) { 
-             if (!$child->children) continue; 
-             foreach ($child->children as $descendent) { 
-                 $child_pages[] = $descendent; 
-             } 
-         } 
-         $view->child_pages = $child_pages; 
-   
-             'title' => 'Deleting page <strong>' . Enc::html($view->page['name']) . '</strong>', 
-             'content' => $view->render() 
-         ); 
-     } 
-   
-   
-     /** 
-      * Does custom actions before _deleteSave method is called, e.g. extra security checks 
-      * @param int $item_id The record to delete 
-      * @return void 
-      * @throws Exception if the deletion shouldn't proceed for some reason 
-      */ 
-     public function _deletePreSave($item_id) 
-     { 
-         if (!AdminPerms::checkPermissionsTree('pages', $item_id)) { 
-             throw new Exception('Permission denied'); 
-         } 
-     } 
-   
-   
-     /** 
-      * Does custom actions after the _deleteSave method is called, e.g. clearing cache data 
-      * @param int $item_id The record to delete 
-      * @return void 
-      */ 
-     public function _deletePostSave($item_id) 
-     { 
-         Navigation::clearCache(); 
-     } 
-   
-   
-     /** 
-     * Shows the links (incoming and outgoing) for a page 
-     **/ 
-     public function _extraLinks($id) 
-     { 
-         $id = (int) $id; 
-   
-         $res = AdminPerms::checkPermissionsTree('pages', $id); 
-         if (! $res) return "Access denied to view this page"; 
-   
-         $view = new View('sprout/admin/page_linklist'); 
-         $view->id = $id; 
-   
-         // Load page details 
-         $q = "SELECT pages.name, revs.text 
-             FROM ~pages AS pages 
-             INNER JOIN ~page_revisions AS revs 
-                 ON revs.page_id = pages.id AND revs.status = ? 
-             WHERE pages.id = ?"; 
-         $view->page = Pdb::q($q, ['live', $id], 'row'); 
-   
-         $root = Navigation::getRootNode(); 
-         $node = $root->findNodeValue('id', $id); 
-         $url = $node->getFriendlyUrl(); 
-   
-         // Incoming links 
-         $q = "SELECT pages.id, pages.name, revs.text 
-             FROM ~pages AS pages 
-             INNER JOIN ~page_revisions AS revs 
-                     ON revs.page_id = pages.id 
-                    AND revs.status = ? 
-             WHERE revs.text LIKE CONCAT('%', ?, '%')"; 
-         $res = Pdb::q($q, ['live', Pdb::likeEscape($url)], 'pdo'); 
-   
-         foreach ($res as $row) { 
-             $match = preg_match('/<a.*?href="' . preg_quote($url, '/') . '".*?>(.+?)<\/a>/', $row->text, $matches); 
-   
-             if ($match) { 
-                 $items[] = array('id' => $row['id'], 'name' => $row['name'], 'text' => $matches[1]); 
-             } 
-         } 
-         $res->closeCursor(); 
-   
-         $list = new Itemlist(); 
-         $list->items = $items; 
-         $list->main_columns = array( 
-             'Page' => 'name', 
-             'Link text' => 'text', 
-         ); 
-         $list->addAction('edit', "SITE/admin/edit/{$this->controller_name}/%%"); 
-         $view->incoming = $list->render(); 
-   
-   
-         // Outgoing links 
-         $res = preg_match_all('/<a.*?href="(.+?)".*?>(.+?)<\/a>/i', $view->page->text, $matches,-  PREG_SET_ORDER );
 
-   
-         foreach ($matches as $match) { 
-             $items[] = array('id' => $match[1], 'url' => $match[1], 'text' => $match[2]); 
-         } 
-   
-         $list = new Itemlist(); 
-         $list->items = $items; 
-         $list->main_columns = array( 
-             'URL' => 'url', 
-             'Link text' => 'text', 
-         ); 
-         $list->addAction('edit', '%ne%'); 
-         $view->outgoing = $list->render(); 
-   
-   
-             'title' => 'Links for page <strong>' . Enc::html($view->page->name) . '</strong>', 
-             'content' => $view->render() 
-         ); 
-     } 
-   
-   
-   
-     /** 
-     * Returns the intro HTML for this controller. 
-     * Looks for a view named "admin/<controller-name>_intro", and loads it if found. 
-     * Otherwise, loads the view, "admin/generic_intro". 
-     **/ 
-     public function _intro() 
-     { 
-         $intro = new View("sprout/admin/page_intro"); 
-         $intro->controller_name = $this->controller_name; 
-         $intro->friendly_name = $this->friendly_name; 
-   
-   
-         // Recently updated pages 
-         $q = "SELECT pages.id, pages.name, DATE_FORMAT(pages.date_modified, '%d/%m/%Y') AS date_modified, 
-                 pages.modified_editor 
-             FROM ~pages AS pages 
-             WHERE subsite_id = ? 
-             ORDER BY pages.date_modified DESC 
-             LIMIT 5"; 
-         $res = Pdb::q($q, [$_SESSION['admin']['active_subsite']], 'arr'); 
-   
-         // Create the itemlist 
-         $itemlist = new Itemlist(); 
-         $itemlist->main_columns = array('Name' => 'name', 'Date modified' => 'date_modified', 'Editor' => 'modified_editor'); 
-         $itemlist->items = $res; 
-         $itemlist->addAction('edit', "SITE/admin/edit/{$this->controller_name}/%%"); 
-   
-         $intro->recently_updated = $itemlist->render(); 
-   
-   
-         // Changes needing approval 
-         if (AdminPerms::canAccess('access_noapproval')) { 
-             $q = "SELECT pages.id, pages.name, DATE_FORMAT(page_revisions.date_modified, '%d/%m/%Y') AS date_modified, 
-                     page_revisions.modified_editor 
-                 FROM ~page_revisions AS page_revisions 
-                 INNER JOIN ~pages AS pages ON page_revisions.page_id = pages.id 
-                 WHERE page_revisions.status = ? 
-                     AND subsite_id = ? 
-                 ORDER BY page_revisions.date_modified DESC 
-                 LIMIT 5"; 
-             $res = Pdb::q($q, ['need_approval', $_SESSION['admin']['active_subsite']], 'arr'); 
-   
-             // Create the itemlist 
-             $itemlist = new Itemlist(); 
-             $itemlist->main_columns = [ 
-                 'Name' => 'name', 
-                 'Date modified' => 'date_modified', 
-                 'Editor' => 'modified_editor' 
-             ]; 
-             $itemlist->items = $res; 
-             $itemlist->addAction('edit', 'SITE/admin/edit/page/%%#main-tabs-revs'); 
-   
-             $intro->need_approval = $itemlist->render(); 
-         } 
-   
-   
-         return $intro->render(); 
-     } 
-   
-   
-     /** 
-     * Does a re-index for a page 
-     **/ 
-     private function reindexItem($item_id, $name, $text) 
-     { 
-         Search::selectIndex('page_keywords', $item_id); 
-   
-         $res = Search::clearIndex(); 
-         if (! $res) return false; 
-   
-         $res = Search::indexHtml($text, 1); 
-         if (! $res) return false; 
-   
-         $res = Search::indexText($name, 4); 
-         if (! $res) return false; 
-   
-         $res = Search::cleanup('pages'); 
-         if (! $res) return false; 
-   
-         return true; 
-     } 
-   
-     /** 
-     * Does a complete re-index of all pages 
-     **/ 
-     public function reindexAll() 
-     { 
-         AdminAuth::checkLogin(); 
-   
-         Pdb::transact(); 
-   
-         $q = "SELECT pages.id, pages.name, pages.active, widget.settings 
-             FROM ~pages AS pages 
-             INNER JOIN ~page_revisions AS rev 
-                 ON rev.page_id = pages.id AND rev.status = ? 
-             LEFT JOIN ~page_widgets AS widget ON rev.id = widget.page_revision_id 
-                 AND widget.area_id = 1 AND widget.active = 1 AND widget.type = 'RichText' 
-             ORDER BY widget.record_order"; 
-         $res = Pdb::q($q, ['live'], 'pdo'); 
-   
-         $pages = []; 
-         foreach ($res as $row) { 
-             if ($row['settings'] == null or $row['active'] == 0) { 
-                 $pages[$row['id']] = ['name' => $row['name'], 'text' => '']; 
-                 continue; 
-             } 
-             if (!isset($pages[$row['id']])) { 
-                 $pages[$row['id']] = ['name' => $row['name'], 'text' => $settings['text']]; 
-             } else { 
-                 $pages[$row['id']]['text'] .= "\n" . $settings['text']; 
-             } 
-         } 
-         $res->closeCursor(); 
-   
-         if (count($pages) == 0) { 
-             echo '<p>Nothing to index</p>'; 
-             Pdb::rollback(); 
-             return; 
-         } 
-   
-         foreach ($pages as $id => $page) { 
-             $this->reindexItem($id, $page['name'], $page['text']); 
-         } 
-   
-         Pdb::commit(); 
-   
-         echo '<p>Success</p>'; 
-     } 
-   
-   
-     /** 
-      * Validate given controller implements FrontEndEntrance 
-      * 
-      * @param string $controller Controller class 
-      * @param int $page_id Page record ID 
-      * @return bool True on success. False on failure 
-      */ 
-     private static function checkControllerEntrance($controller, $page_id) 
-     { 
-         $page_id = (int) $page_id; 
-   
-         $front_end_controllers = Register::getFrontEndControllers(); 
-         if (empty($front_end_controllers[$controller])) return false; 
-   
-         $inst = Sprout::instance($controller); 
-         if (!($inst instanceof FrontEndEntrance)) return false; 
-   
-         return true; 
-     } 
-   
-   
-     /** 
-     * Returns the children pages for a specific page, in a format required by jqueryFileTree. 
-     * Uses the POST param 'dir', and is usually run through an AJAX call. 
-     **/ 
-     public function filetreeOpen() 
-     { 
-         AdminAuth::checkLogin(); 
-   
-         $_POST['dir'] = trim($_POST['dir']); 
-         $_GET['record_id'] = (int) $_GET['record_id']; 
-   
-         Navigation::loadPageTree($_SESSION['admin']['active_subsite'], true); 
-   
-         $root = Navigation::getRootNode(); 
-         $top_node = $root->findNodeValue('id', basename($_POST['dir'])); 
-   
-         $nav_limit = Subsites::getConfigAdmin('nav_limit'); 
-         if (! $nav_limit) $nav_limit = 99999; 
-         if (Subsites::getConfigAdmin('nav_home')) $nav_limit--; 
-   
-         echo "<ul class=\"jqueryFileTree\" style=\"display: none;\">"; 
-   
-         // This item 
-         $dir_item_path = preg_replace('!^/(.+)/$!', '$1', $_POST['dir']); 
-         if ($dir_item_path != '/') { 
-             $dir_item_name = basename($_POST['dir']); 
-   
-             $name = $top_node['name']; 
-             if (strlen($name) > 25) $name = substr($name, 0, 25) . '...'; 
-             $name = Enc::html($name); 
-   
-             $rel = Enc::html('/' . $dir_item_path); 
-   
-             $admin_perms = AdminPerms::checkPermissionsTree('pages', $top_node['id']); 
-   
-             $class = ($admin_perms ? ' allow-access' : ' no-access'); 
-             if ($top_node['id'] == $_GET['record_id']) $class .= ' current-edit'; 
-             echo "<li class=\"file ext_txt{$class} directory-item\"><a href=\"#\" rel=\"{$rel}\">{$name}</a></li>"; 
-         } 
-   
-         // Children of this item 
-         foreach ($top_node->children as $child) { 
-             $name = $child['name']; 
-             if (strlen($name) > 25) $name = substr($name, 0, 25) . '...'; 
-             $name = Enc::html($name); 
-   
-             $rel = Enc::html($_POST['dir'] . $child['id']); 
-   
-             $admin_perms = AdminPerms::checkPermissionsTree('pages', $child['id']); 
-   
-             $class = ($admin_perms ? ' allow-access' : ' no-access'); 
-             if (count($child->children) > 0-  and  $admin_perms) {
 
-                 echo "<li class=\"directory collapsed{$class}\"><a href=\"#\" rel=\"{$rel}/\">{$name}</a></li>"; 
-             } else { 
-                 if ($child['id'] == $_GET['record_id']) $class .= ' current-edit'; 
-                 echo "<li class=\"file ext_txt{$class}\"><a href=\"#\" rel=\"{$rel}\">{$name}</a></li>"; 
-             } 
-   
-             if ($dir_item_path == '/') { 
-                 $nav_limit--; 
-                 if ($nav_limit == 0) { 
-                     echo "<li class=\"nav-limit\"> </li>"; 
-                 } 
-             } 
-         } 
-   
-         echo "</ul>"; 
-   
-         if ($dir_item_path != '/') { 
-             echo "<p class=\"tree-extras\">"; 
-             echo "+ <a href=\"SITE/admin/add/page?parent_id={$top_node['id']}\">Add Child</a>"; 
-             echo "   "; 
-             echo "↕ <a href=\"SITE/page/reorder/{$top_node['id']}\" onclick=\"$.facebox({'ajax':this.href}); return false;\">Re-order</a>"; 
-             echo "</p>"; 
-         } 
-   
-         if ($_SESSION['admin'][$this->controller_name . '_nav'] == null) $_SESSION['admin'][$this->controller_name . '_nav'] = array(); 
-         if ($_POST['dir'] != '/'-  and  !in_array ($_POST['dir'], $_SESSION['admin'][$this->controller_name . '_nav'])) {
 
-             $_SESSION['admin'][$this->controller_name . '_nav'][] = $_POST['dir']; 
-         } 
-     } 
-   
-     /** 
-     * Saves in the session data the currently open pages in the pages tree (navigation pane) 
-     * Uses the POST param 'pages', and is usually run through an AJAX call. 
-     **/ 
-     public function filetreeClose() 
-     { 
-         AdminAuth::checkLogin(); 
-   
-         if (empty($_SESSION['admin'][$this->controller_name . '_nav'])) return; 
-   
-         $index = array_search ($_POST['dir'], $_SESSION['admin'][$this->controller_name . '_nav']); 
-         unset ($_SESSION['admin'][$this->controller_name . '_nav'][$index]); 
-     } 
-   
-   
-     /** 
-     * Shows the reorder screen (which is shown in a popup box) for re-ordering the top-level stuff 
-     * This custom version adds subsite support 
-     **/ 
-     public function reorderTop() 
-     { 
-         AdminAuth::checkLogin(); 
-   
-         // Get children 
-         $q = "SELECT id, name 
-             FROM ~{$this->table_name} 
-             WHERE subsite_id = ? AND parent_id = 0 
-             ORDER BY record_order"; 
-         $children = Pdb::q($q, [$_SESSION['admin']['active_subsite']], 'arr'); 
-   
-         // If there is only one child, complain that it's impossible to re-order 
-         if (count($children) == 1) { 
-             echo "<p>This site does not have enough top-level items for ordering.</p>"; 
-             return; 
-         } 
-   
-         // View 
-         $view = new View('sprout/admin/categories_reorder'); 
-         $view->id = 0; 
-         $view->items = $children; 
-         $view->controller_name = $this->controller_name; 
-         $view->friendly_name = $this->friendly_name; 
-   
-         echo $view->render(); 
-     } 
-   
-     /** 
-      * If the specified item needs a record number to be set, 
-      * Puts this item at the end of the list. 
-      * 
-      * This custom version adds subsite support 
-      * 
-      * @param int $item_id Record-id to update 
-      */ 
-     protected function fixRecordOrder($item_id) 
-     { 
-         $q = "SELECT record_order, subsite_id, parent_id FROM ~{$this->table_name} WHERE id = ?"; 
-         $item = Pdb::q($q, [$item_id], 'row'); 
-   
-         if ($item['record_order'] != 0) return; 
-   
-         $q = "SELECT MAX(record_order) AS m 
-             FROM ~{$this->table_name} 
-             WHERE subsite_id = ? 
-             AND parent_id = ?"; 
-         try { 
-             $max = Pdb::q($q, [$item['subsite_id'], $item['parent_id']], 'val'); 
-         } catch (QueryException $ex) { 
-             return; 
-         } 
-   
-         $q = "UPDATE ~{$this->table_name} SET record_order = ? WHERE id = ?"; 
-         Pdb::q($q, [$max + 1, $item_id], 'count'); 
-     } 
-   
-   
-     /** 
-     * Activates AutoLaunch revisions 
-     **/ 
-     public function cronPageActivate() 
-     { 
-         Cron::start('Activate pages'); 
-   
-         try { 
-             Pdb::transact(); 
-   
-             // Find revisions needing launch 
-             $q = "SELECT id, page_id 
-                 FROM ~page_revisions 
-                 WHERE status = ? AND date_launch <= NOW()"; 
-             $res = Pdb::q($q, ['auto_launch'], 'arr'); 
-   
-             foreach ($res as $row) { 
-                 Cron::message("Launching revision {$row['id']} on page {$row['page_id']}"); 
-   
-                 // Launch revision 
-                 Pdb::update('page_revisions', ['status' => 'live'], ['id' => $row['id']]); 
-   
-                 $this->addHistoryItem($row['page_id'], "AutoLaunched revision {$row['id']}", 'n/a'); 
-   
-                 $where = [ 
-                     'page_id' => $row['page_id'], 
-                     ['id', '!=', $row['id']], 
-                     'status' => 'live', 
-                 ]; 
-                 Pdb::update('page_revisions', ['status' => 'old'], $where); 
-             } 
-   
-             Pdb::commit(); 
-         } catch (QueryException $ex) { 
-             return Cron::failure('Database error'); 
-         } 
-   
-         Navigation::clearCache(); 
-   
-         Cron::success(); 
-     } 
-   
-   
-     /** 
-     * Deactivates pages after set date 
-     **/ 
-     public function cronPageDeactivate() 
-     { 
-         Cron::start('De-activate pages'); 
-   
-         try { 
-             Pdb::transact(); 
-   
-             // Find revisions needing launch 
-             $q = "SELECT id 
-                 FROM ~pages 
-                 WHERE active = 1 
-                     AND date_expire != '0000-00-00' 
-                     AND date_expire IS NOT NULL 
-                     AND date_expire <= NOW()"; 
-             $res = Pdb::q($q, [], 'arr'); 
-   
-             foreach ($res as $row) { 
-                 Cron::message("De-activating page {$row['id']}"); 
-   
-                 // Deactivate page 
-                 Pdb::update('pages', ['active' => 0], ['id' => $row['id']]); 
-   
-                 $this->addHistoryItem($row['id'], "Deactivated page {$row['id']}", 'n/a'); 
-             } 
-   
-             Pdb::commit(); 
-         } catch (QueryException $ex) { 
-             return Cron::failure('Database error'); 
-         } 
-   
-         Navigation::clearCache(); 
-   
-         Cron::success(); 
-     } 
-   
-   
-     /** 
-     * Returns the tools to show in the left navigation 
-     **/ 
-     public function _getTools() 
-     { 
-   
-         if (count(- Register ::getDocImports()) > 0) {
 
-             $items[] = "<li class=\"import\"><a href=\"SITE/admin/import_upload/page\">Document import</a></li>"; 
-         } 
-   
-         $items[] = "<li class=\"action-log\"><a href=\"SITE/admin/search/{$this->controller_name}\">Search pages</a></li>"; 
-   
-         if (AdminPerms::canAccess('access_noapproval')) { 
-             $items[] = "<li class=\"action-log\"><a href=\"admin/extra/page/need_approval\">Pages needing approval</a></li>"; 
-         } 
-   
-         if (AdminAuth::isSuper() or Subsites::getConfigAdmin('nav_reorder')) { 
-   
-             $items[] = "<li class=\"reorder\"><a href=\"admin/call/{$this->controller_name}/reorderTop\" onclick=\"$.facebox({'ajax':this.href}); return false;\">Reorder top-level</a></li>"; 
-         } 
-   
-         if (AdminAuth::isSuper()) { 
-             $items[] = "<li class=\"config\"><a href=\"admin/extra/page/organise\">Sitemap manager</a></li>"; 
-         } 
-   
-         if (Subsites::getConfigAdmin('nav_groups') !== null) { 
-             $items[] = "<li class=\"config\"><a href=\"admin/extra/page/menu_groups\">Manage menu groups</a></li>"; 
-         } 
-   
-         $items[] = "<li class=\"config\"><a href=\"admin/extra/page/link_checker\">Link checker</a></li>"; 
-   
-         if (Kohana::config('cache.enabled')) { 
-             $items[] = "<li class=\"config\"><a href=\"page/clear_navigation_cache\">Clear navigation cache</a></li>"; 
-         } 
-   
-         if ($this->_actionLog()) { 
-             $tools[] = '<li class="action-log"><a href="SITE/admin/contents/action_log?record_table=' . $this->getTableName() . '">View action log</a></li>'; 
-         } 
-   
-         return $items; 
-     } 
-   
-   
-     /** 
-     * Starts the link checker 
-     **/ 
-     public function _extraLinkChecker() 
-     { 
-         $view = new View('sprout/admin/link_checker'); 
-         $view->ops = AdminPerms::getOperatorsWithAccess('access_reportemail'); 
-   
-         $details = AdminAuth::getDetails(); 
-         $view->email = $details['email']; 
-   
-             'title' => 'Link Checker', 
-             'content' => $view->render(), 
-         ); 
-     } 
-   
-   
-     /** 
-     * Starts the link checker 
-     **/ 
-     public function linkCheckerAction() 
-     { 
-         AdminAuth::checkLogin(); 
-         Csrf::checkOrDie(); 
-   
-         $_POST['send_to'] = trim($_POST['send_to']); 
-         $_POST['email'] = trim($_POST['email']); 
-   
-         if ($_POST['send_to'] != 'admins' and $_POST['send_to'] != 'specific') { 
-             Notification::error("Invalid 'send_to' argument"); 
-             Url::redirect('admin/extra/page/link_checker'); 
-         } 
-   
-         if ($_POST['send_to'] == 'specific' and $_POST['email'] == '') { 
-             Notification::error("You didn't enter an email address"); 
-             Url::redirect('admin/extra/page/link_checker'); 
-         } 
-   
-         try { 
-             if ($_POST['send_to'] == 'admins') { 
-                 $info = WorkerCtrl::start('Sprout\\Helpers\\WorkerLinkChecker'); 
-             } else if ($_POST['send_to'] == 'specific') { 
-                 $info = WorkerCtrl::start('Sprout\\Helpers\\WorkerLinkChecker', $_POST['email']); 
-             } 
-         } catch (WorkerJobException $ex) { 
-             Notification::error("Unable to start background process: {$ex->getMessage()}"); 
-             Url::redirect('admin/extra/page/link_checker'); 
-         } 
-   
-         Notification::confirm("Background process started"); 
-         Url::redirect('admin/extra/page/link_checker_info/' . $info['job_id']); 
-     } 
-   
-   
-     /** 
-     * Tells the user the link checker is running 
-     **/ 
-     public function _extraLinkCheckerInfo($id) 
-     { 
-         $id = (int) $id; 
-   
-         $out = ''; 
-         $out .= '<h3>Job started</h3>'; 
-         $out .= '<p>The link checker background process has been started.</p>'; 
-         $out .= '<p>An email will be sent once it is complete.</p>'; 
-   
-             'title' => 'Link Checker', 
-             'content' => $out, 
-         ); 
-     } 
-   
-   
-     /** 
-      * List of pages which need approval 
-      */ 
-     public function _extraNeedApproval() 
-     { 
-         if (!AdminPerms::canAccess('access_noapproval')) { 
-             return 'Access denied'; 
-         } 
-   
-         $q = "SELECT pages.id, pages.name, revs.date_modified, revs.modified_editor 
-             FROM ~page_revisions AS revs 
-             INNER JOIN ~pages AS pages ON revs.page_id = pages.id 
-             WHERE revs.status = 'need_approval' 
-                 AND pages.subsite_id = ? 
-             GROUP BY pages.id 
-             ORDER BY revs.date_modified DESC 
-             LIMIT 25"; 
-         $res = Pdb::query($q, [$_SESSION['admin']['active_subsite']], 'arr'); 
-   
-         $itemlist = new Itemlist(); 
-         $itemlist->main_columns = [ 
-             'Name' => 'name', 
-             'Date modified' => [new ColModifierDate(), 'date_modified'], 
-             'Editor' => 'modified_editor' 
-         ]; 
-         $itemlist->items = $res; 
-         $itemlist->addAction('edit', 'admin/edit/page/%%'); 
-   
-             'title' => 'Pages needing approval', 
-             'content' => $itemlist->render(), 
-         ); 
-     } 
-   
-   
-     /** 
-     * Cron version of the link checker 
-     **/ 
-     public function cronLinkChecker() 
-     { 
-         Cron::start('Link Checker'); 
-         WorkerCtrl::start('Sprout\\Helpers\\WorkerLinkChecker'); 
-         Cron::success(); 
-     } 
-   
-   
-     /** 
-      * Check for stale page content and send emails regarding stale pages; to be run via cron 
-      * 
-      * @return void 
-      */ 
-     public function cronCheckStale() 
-     { 
-         Cron::start('Stale page checker'); 
-   
-         $email = Kohana::config('sprout.stale_page_email'); 
-         $default_max_age = Kohana::config('sprout.stale_page_age'); 
-         $resend_interval = (int) Kohana::config('sprout.stale_page_resend_after'); 
-         if ($resend_interval <= 0) $resend_interval = 7; 
-   
-         $q = "SELECT page.id, page.subsite_id, page.name, 
-                 rev.modified_editor, DATEDIFF(NOW(), rev.date_modified) AS age, 
-                 op.id AS op_id, op.name AS operator, op.email 
-             FROM ~pages AS page 
-             INNER JOIN ~page_revisions AS rev 
-                 ON page.id = rev.page_id AND rev.status = 'live' AND rev.type = 'standard' 
-             LEFT JOIN ~operators AS op 
-                 ON rev.operator_id = op.id 
-             WHERE page.active = 1 
-                 AND DATE_SUB(CURDATE(), INTERVAL ? DAY) >= page.stale_reminder_sent 
-                 AND IFNULL(page.stale_age, ?) > 0 
-                 AND DATEDIFF(NOW(), rev.date_modified) >= IFNULL(page.stale_age, ?) 
-             ORDER BY age DESC, page.id"; 
-         $res = Pdb::q($q, [$resend_interval, $default_max_age, $default_max_age], 'map-arr'); 
-   
-             Cron::message('No stale pages found'); 
-             Cron::success(); 
-             return; 
-         } 
-   
-         $op_emails = []; 
-   
-         if ($email-  and  !preg_match('/example\.com$/', $email)) {
 
-             $op_emails[0] = ['email' => $email, 'pages' => []]; 
-         } 
-   
-         foreach ($res as $id => $row) { 
-             $url = Page::url($id); 
-             if (!$url) continue; 
-   
-             $url = Subsites::getAbsRoot($row['subsite_id']) . $url; 
-   
-             $op_emails[0]['pages'][] = [ 
-                 'id' => $row['id'], 
-                 'name' => $row['name'], 
-                 'age' => $row['age'], 
-                 'editor' => $row['modified_editor'], 
-                 'url' => $url, 
-             ]; 
-   
-             if (!$row['email']) continue; 
-   
-             $op = $row['op_id']; 
-             if (!isset($op_emails[$op])) { 
-                 $op_emails[$op] = [ 
-                     'email' => $row['email'], 
-                     'operator' => $row['operator'], 
-                     'pages' => [], 
-                 ]; 
-             } 
-   
-             $op_emails[$op]['pages'][] = [ 
-                 'id' => $row['id'], 
-                 'name' => $row['name'], 
-                 'age' => $row['age'], 
-                 'url' => $url, 
-             ]; 
-         } 
-   
-         foreach ($op_emails as $id => $details) { 
-             if (empty($details['email'])) continue; 
-             if (count($details['pages']) == 0) continue; 
-   
-             $msg = "Sending email to {$details['email']} about "; 
-             $msg .=-  Inflector ::numPlural(count($details['pages']), 'page');
 
-             Cron::message($msg); 
-   
-             $view = new View('sprout/email/pages_stale'); 
-             $view->show_op = ($id == 0); 
-             $view->pages = $details['pages']; 
-             $view->base = Sprout::absRoot(); 
-   
-             $mail = new Email(); 
-             $mail->Subject = 'Stale content warning'; 
-             if (!empty($details['operator'])) { 
-                 $mail->addAddress($details['email'], $details['operator']); 
-             } else { 
-                 $mail->addAddress($details['email']); 
-             } 
-             $mail->skinnedHTML($view); 
-             $mail->send(); 
-         } 
-   
-         Cron::message("Marking pages as sent"); 
-   
-         $params = [date('Y-m-d')]; 
-         $where = Pdb::buildClause($conds, $params); 
-   
-         $count = Pdb::q("UPDATE ~pages SET stale_reminder_sent = ? WHERE {$where}", $params, 'count'); 
-         Cron::message(Inflector::numPlural($count, 'page') . " marked as sent"); 
-   
-         Cron::success(); 
-     } 
-   
-   
-     /** 
-     * Forces a clear of the pagecache 
-     **/ 
-     public function clearNavigationCache() 
-     { 
-         AdminAuth::checkLogin(); 
-   
-         Navigation::clearCache(); 
-   
-         Notification::confirm('Page cache has been cleared'); 
-         Url::redirect('admin/intro/page'); 
-     } 
-   
-   
-     public function preview($item_id = 0) { 
-         $item_id = (int) $item_id; 
-   
-         $tables = [ 
-             'pages' => 1, 
-             'page_revisions' => ['id' => $_POST['rev_id']], 
-             'page_widgets' => 0, 
-             'page_history_items' => 0, 
-             'page_admin_permissions' => 1, 
-             'page_user_permissions' => 1, 
-             'page_attributes' => 0, 
-             'page_keywords' => 0, 
-             'search_keywords' => 0, 
-         ]; 
-   
-         // Make sure the resulting revision is live so it's the revision displayed in the preview, even though it might 
-         // be saved under a different status once the current administrator is happy with the preview 
-         $_POST['status'] = 'live'; 
-   
-         $this->in_preview = true; 
-         $item_id = Preview::load($this, $tables, $item_id); 
-   
-         $ctlr = new PageController(); 
-         Preview::run($ctlr, 'viewById', [$item_id]); 
-     } 
-   
-   
-     /** 
-      * Return JSON list of custom widget templates as defined by skin config 
-      * AJAX called 
-      * 
-      * @param string $_GET['template'] Template filename 
-      * @return void Echos HTML directly 
-      */ 
-     public function ajaxListWidgetTemplates() 
-     { 
-         $templates = Kohana::config('sprout.widget_templates'); 
-         Form::setData(['template' => @$_GET['template']]); 
-         $out = ''; 
-   
-         Form::nextFieldDetails('Template', false); 
-         $out .= Form::dropdown('template', [], $templates); 
-   
-         // Render Save button 
-         $out .= '<div class="-clearfix"><button class="save-changes-save-button button button-green icon-after icon-save" type="submit">Save changes</button></div>'; 
-   
-         echo $out; 
-     } 
- } 
-