diff --git a/assets/documenter.admin.css b/assets/documenter.admin.css index aa0aab2..39b290a 100644 --- a/assets/documenter.admin.css +++ b/assets/documenter.admin.css @@ -1,6 +1,6 @@ /** - * A Symphony extension enabling addition of documentation - * to any page in the back end, including user-defined + * A Symphony extension enabling addition of documentation + * to any page in the back end, including user-defined * section indexes and entry editors. */ @@ -9,28 +9,29 @@ } #drawer-documenter { - background: #282828; + background: #fff; } #documenter-drawer .documenter-content { - color: rgba(255,255,255,.85); + color: #3B3D40; + padding: 0 3rem 3rem; } /* Headings */ #documenter-drawer h2 { - margin: 0 0 1em -0.39em; - padding: 0 0 0.39em 0.39em; - border-bottom: 1px solid #d1d1cc; - color: rgba(255,255,255,.85); + color: #2f77eb; + font-size: 2.4rem; + padding: 3rem; } #documenter-drawer .documenter-content + h2 { - padding-top: 3em; + padding-top: 3rem; + border-top: 1px solid #d3dce2; } -#documenter-drawer .documenter-content h1, -#documenter-drawer .documenter-content h2, +#documenter-drawer .documenter-content h1, +#documenter-drawer .documenter-content h2, #documenter-drawer .documenter-content h3 { border-bottom: 1px solid #e7e7e7; margin: 0 0 0 -0.5em; @@ -42,8 +43,8 @@ color: rgba(255,255,255,.85); } -#documenter-drawer .documenter-content h1:after, -#documenter-drawer .documenter-content h2:after, +#documenter-drawer .documenter-content h1:after, +#documenter-drawer .documenter-content h2:after, #documenter-drawer .documenter-content h3:after { content: attr(data-show); position: absolute; @@ -52,20 +53,20 @@ color: rgba(255,255,255,.85); } -#documenter-drawer .documenter-content h1.open, -#documenter-drawer .documenter-content h2.open, +#documenter-drawer .documenter-content h1.open, +#documenter-drawer .documenter-content h2.open, #documenter-drawer .documenter-content h3.open { background: rgba(255, 255, 255, 0.6); } -#documenter-drawer .documenter-content h1.open:after, -#documenter-drawer .documenter-content h2.open:after, +#documenter-drawer .documenter-content h1.open:after, +#documenter-drawer .documenter-content h2.open:after, #documenter-drawer .documenter-content h3.open:after { content: attr(data-hide); } -#documenter-drawer .documenter-content .block.open + h1, -#documenter-drawer .documenter-content .block.open + h2, +#documenter-drawer .documenter-content .block.open + h1, +#documenter-drawer .documenter-content .block.open + h2, #documenter-drawer .documenter-content .block.open + h3 { border-top: 1px solid #e7e7e7; } @@ -110,13 +111,13 @@ content: counters(section, ".") ". "; } -#documenter-drawer ul, +#documenter-drawer ul, #documenter-drawer ol { margin: 0 0 1.5em 0; list-style-position: inside; } -#documenter-drawer ul li li, +#documenter-drawer ul li li, #documenter-drawer ol li li { margin-left: 1.5em; } diff --git a/content/content.edit.php b/content/content.edit.php index b9ef02c..e26f70a 100644 --- a/content/content.edit.php +++ b/content/content.edit.php @@ -2,9 +2,9 @@ require_once(TOOLKIT . '/class.administrationpage.php'); require_once(EXTENSIONS . '/documenter/lib/class.form.php'); - + class contentExtensionDocumenterEdit extends AdministrationPage { - + private $form; public function __construct() { @@ -15,49 +15,67 @@ public function __construct() { public function view() { $this->form->render(); } - + public function action() { $doc_id = $this->_context[0]; - + // Delete action if (@array_key_exists('delete', $_POST['action'])) { - $page = Symphony::Database()->fetchRow(0, "SELECT * FROM tbl_documentation WHERE `id` = '$doc_id'"); - Symphony::Database()->delete('tbl_documentation', " `id` = '$doc_id'"); + $page = Symphony::Database() + ->select(['*']) + ->from('tbl_documentation') + ->where(['id' => $doc_id]) + ->execute() + ->next(); + + Symphony::Database() + ->delete('tbl_documentation') + ->where(['id' => $doc_id]) + ->execute() + ->success(); + redirect(URL . '/symphony/extension/documenter/'); } - + // Save action if(@array_key_exists('save', $_POST['action'])){ - + $this->_errors = array(); // Polish up some field content $fields = $_POST['fields']; - + if(isset($fields['pages'])) { $fields['pages'] = implode(',',$fields['pages']); } $fields['content_formatted'] = $this->form->applyFormatting($fields['content'], true, $this->_errors); - + if($fields['content_formatted'] === false){ - $fields['content_formatted'] = General::sanitize($this->form->applyFormatting($fields['content'])); + $fields['content_formatted'] = General::sanitize($this->form->applyFormatting($fields['content'])); } if(!isset($fields['content']) || trim($fields['content']) == '') $this->_errors['content'] = __('Content is a required field'); - - if(!isset($fields['pages']) || trim($fields['pages']) == '') $this->_errors['pages'] = __('Pages is a required field'); - if(empty($this->_errors)){ - if(!Symphony::Database()->update($fields, 'tbl_documentation', "`id` = '$doc_id'")) $this->pageAlert(__('Unknown errors occurred while attempting to save. Please check your activity log.', array(URL.'/symphony/system/log/')), Alert::ERROR); + if(!isset($fields['pages']) || trim($fields['pages']) == '') $this->_errors['pages'] = __('Pages is a required field'); - else{ + if(empty($this->_errors)){ + if (!Symphony::Database() + ->update('tbl_documentation') + ->set($fields) + ->where(['id' => $doc_id]) + ->execute() + ->success() + ) { + $this->pageAlert(__('Unknown errors occurred while attempting to save. Please check your activity log.', array(URL.'/symphony/system/log/')), Alert::ERROR); + } + else { redirect(URL . "/symphony/extension/documenter/edit/$doc_id/saved/"); } } } - - if(is_array($this->_errors) && !empty($this->_errors)) $this->pageAlert(__('An error occurred while processing this form. See below for details.'), Alert::ERROR); + + if(is_array($this->_errors) && !empty($this->_errors)) $this->pageAlert(__('An error occurred while processing this form. See below for details.'), Alert::ERROR); } - + } diff --git a/content/content.index.php b/content/content.index.php index 7d3c634..058b7c0 100644 --- a/content/content.index.php +++ b/content/content.index.php @@ -3,37 +3,37 @@ require_once(CONTENT . '/content.blueprintspages.php'); class contentExtensionDocumenterIndex extends contentBlueprintsPages { - + public function view() { - + // Start building the page $this->setPageType('table'); $this->setTitle(__('%1$s – %2$s', array(__('Symphony'), __('Documentation')))); - + $this->appendSubheading( __('Documentation'), Widget::Anchor( - __('Create New'), URL . '/symphony/extension/documenter/new/', - __('Create a new documentation item'), 'create button' + Widget::SVGIcon('add') . '' . __('Create New') . '', + URL . '/symphony/extension/documenter/new/', + __('Create a new documentation item'), + 'create button' ) ); - + // Grab all the documentation items - $docs = Symphony::Database()->fetch(" - SELECT - d.* - FROM - `tbl_documentation` AS d - ORDER BY - d.pages ASC - "); - + $docs = Symphony::Database() + ->select(['d.*']) + ->from('tbl_documentation', 'd') + ->orderBy('d.pages') + ->execute() + ->rows(); + // Build the table $thead = array( array(__('Title'), 'col'), array(__('Pages'), 'col') ); - + $tbody = array(); // If there are no records, display default message @@ -41,54 +41,57 @@ public function view() { $tbody = array(Widget::TableRow(array( Widget::TableData(__('None found.'), 'inactive', null, count($thead)) ), 'odd')); - + } - + // Otherwise, build table rows else{ $bOdd = true; - + foreach ($docs as $doc) { $doc_edit_url = URL . '/symphony/extension/documenter/edit/' . $doc['id'] . '/'; - + $col_title = Widget::TableData(Widget::Anchor( $doc['title'], $doc_edit_url )); $col_title->appendChild(Widget::Input("items[{$doc['id']}]", null, 'checkbox')); - + $col_title->setAttribute('data-title', __('Title')); + $pages = $doc['pages']; $pages = explode(',', $pages); $pages = join(', ', $pages); $col_pages = Widget::TableData($pages); - - $tbody[] = Widget::TableRow(array($col_title, $col_pages), ($bOdd ? 'odd' : NULL)); - + $col_pages->setAttribute('data-title', __('Pages')); + + $tbody[] = Widget::TableRow(array($col_title, $col_pages), ($bOdd ? 'odd' : null)); + $bOdd = !$bOdd; } } - + $table = Widget::Table( Widget::TableHead($thead), null, Widget::TableBody($tbody), null ); $table->setAttribute('class','selectable'); - + $table->setAttribute('data-interactive', 'data-interactive'); + $this->Form->appendChild($table); - + $actions = new XMLElement('div'); $actions->setAttribute('class', 'actions'); - + $options = array( array(null, false, __('With Selected...')), array('delete', false, __('Delete')), ); - + $actions->appendChild(Widget::Apply($options)); - + $this->Form->appendChild($actions); - + } - + function __actionIndex(){ $checked = @array_keys($_POST['items']); @@ -100,11 +103,16 @@ function __actionIndex(){ $doc_items = $checked; - Symphony::Database()->delete('tbl_documentation', " `id` IN('".implode("','",$checked)."')"); + Symphony::Database() + ->delete('tbl_documentation') + ->where(['id' => ['in' => $checked]]) + ->execute() + ->success(); + redirect(Administration::instance()->getCurrentPageURL()); break; } } - } - - } + } + + } diff --git a/content/content.new.php b/content/content.new.php index 9092108..71cce92 100644 --- a/content/content.new.php +++ b/content/content.new.php @@ -2,9 +2,9 @@ require_once(TOOLKIT . '/class.administrationpage.php'); require_once(EXTENSIONS . '/documenter/lib/class.form.php'); - + class contentExtensionDocumenterNew extends AdministrationPage { - + private $form; public function __construct() { @@ -18,40 +18,45 @@ public function view() { public function action() { if(@array_key_exists('save', $_POST['action'])){ - + $this->_errors = array(); // Polish up some field content $fields = $_POST['fields']; - + if(isset($fields['pages'])) { $fields['pages'] = implode(',',$fields['pages']); } - + $fields['content_formatted'] = $this->form->applyFormatting($fields['content'], true, $this->_errors); - + if($fields['content_formatted'] === false){ - $fields['content_formatted'] = General::sanitize($this->form->applyFormatting($fields['content'])); + $fields['content_formatted'] = General::sanitize($this->form->applyFormatting($fields['content'])); } - if(!isset($fields['title']) || trim($fields['title']) == '') $this->_errors['title'] = __('Title is a required field'); - + if(!isset($fields['title']) || trim($fields['title']) == '') $this->_errors['title'] = __('Title is a required field'); + if(!isset($fields['pages']) || trim($fields['pages']) == '') $this->_errors['pages'] = __('Page is a required field'); - + if(!isset($fields['content']) || trim($fields['content']) == '') $this->_errors['content'] = __('Content is a required field'); if(empty($this->_errors)){ - - if(!Symphony::Database()->insert($fields, 'tbl_documentation')) $this->pageAlert(__('Unknown errors occurred while attempting to save. Please check your activity log.', array(URL.'/symphony/system/log/')), Alert::ERROR); - - else{ + if (!Symphony::Database() + ->insert('tbl_documentation') + ->values($fields) + ->execute() + ->success() + ) { + $this->pageAlert(__('Unknown errors occurred while attempting to save. Please check your activity log.', array(URL.'/symphony/system/log/')), Alert::ERROR); + } + else { $doc_id = Symphony::Database()->getInsertID(); redirect(URL . "/symphony/extension/documenter/edit/$doc_id/created/"); - } + } } } - + if(is_array($this->_errors) && !empty($this->_errors)) $this->pageAlert(__('An error occurred while processing this form. See below for details.'), Alert::ERROR); } - + } diff --git a/extension.driver.php b/extension.driver.php index b389808..8c3c0bf 100644 --- a/extension.driver.php +++ b/extension.driver.php @@ -1,17 +1,8 @@ __('System'), - 'name' => __('Documentation'), - 'link' => '/', - 'limit' => 'manager', - ) - ); - } + if(!defined("__IN_SYMPHONY__")) die("
You cannot directly access this file
"); + + Class Extension_Documenter extends Extension { public function getSubscribedDelegates() { return array( @@ -34,6 +25,40 @@ public function getSubscribedDelegates() { 'page' => '/backend/', 'delegate' => 'InitaliseAdminPageHead', 'callback' => 'appendDocs' + ), + array( + 'page' => '/backend/', + 'delegate' => 'NavigationPreRender', + 'callback' => 'navigationPreRender' + ) + ); + } + + public function navigationPreRender($context) { + $c = Administration::instance()->getPageCallback(); + + if (strpos($c['classname'], 'contentExtensionDocumenter') !== false) { + foreach ($context['navigation'] as $key => $section) { + if ($section['name'] == __('System')) { + $context['navigation'][$key]['class'] = 'active opened'; + + foreach ($context['navigation'][$key]['children'] as $subkey => $subsection) { + if ($subsection['name'] == __('Documentation')) { + $context['navigation'][$key]['children'][$subkey]['class'] = 'active'; + } + } + } + } + } + } + + public function fetchNavigation() { + return array( + array( + 'location' => __('System'), + 'name' => __('Documentation'), + 'link' => '/', + 'limit' => 'manager', ) ); } @@ -50,14 +75,13 @@ public function appendDocs($context) { $pos = strripos($current_page_url, '/edit/'); $current_page_url = substr($current_page_url, 0, $pos + 6); } - $pages = Symphony::Database()->fetch(" - SELECT - d.pages, d.id - FROM - `tbl_documentation` AS d - ORDER BY - d.pages ASC - "); + + $pages = Symphony::Database() + ->select(['d.pages', 'd.id']) + ->from('tbl_documentation', 'd') + ->orderBy('d.pages') + ->execute() + ->rows(); foreach($pages as $key => $value) { if(strstr($value['pages'],',')) { @@ -78,21 +102,19 @@ public function appendDocs($context) { ) ); - // Fetch documentation items + // Fetch documentation items $items = array(); foreach($pages as $page) { if(in_array($current_page_url, $page)) { if(isset($page['id'])) { - $items[] = Symphony::Database()->fetchRow(0, " - SELECT - d.title, d.content_formatted - FROM - `tbl_documentation` AS d - WHERE - d.id = '{$page['id']}' - LIMIT 1 - "); - } + $items[] = Symphony::Database() + ->select(['d.title', 'd.content_formatted']) + ->from('tbl_documentation', 'd') + ->where(['d.id' => $page['id']]) + ->limit(1) + ->execute() + ->next(); + } else { ### # Delegate: appendDocsPost @@ -108,11 +130,11 @@ public function appendDocs($context) { // Allows a page to have more then one documentation source if(!empty($items)) { - + // Generate documentation panel - $docs = new XMLElement('div', NULL, array('id' => 'documenter-drawer')); + $docs = new XMLElement('div', null, array('id' => 'documenter-drawer')); foreach($items as $item) { - + // Add title if(isset($item['title'])) { $docs->appendChild( @@ -126,41 +148,76 @@ public function appendDocs($context) { ); } - - $button = General::sanitize(Symphony::Configuration()->get('button-text', 'Documentation')); + + $button = General::sanitize(Symphony::Configuration()->get('button-text', __('Documentation'))); $drawer = Widget::Drawer( 'documenter', ($button != '' ? $button : __('Documentation')), $docs, 'closed' ); - Administration::instance()->Page->insertDrawer($drawer, 'vertical-right'); - + + Widget::registerSVGIcon( + 'help', + '' + ); + Administration::instance()->Page->insertDrawer( + $drawer, + 'vertical-right', + 'append', + Widget::SVGIcon('help') + ); } } public function uninstall() { - Symphony::Database()->query("DROP TABLE `tbl_documentation`;"); + // Symphony::Database()->query("DROP TABLE `tbl_documentation`;"); Symphony::Configuration()->remove('text-formatter', 'documentation'); Symphony::Configuration()->remove('button-text', 'documentation'); Symphony::Configuration()->write(); + + return Symphony::Database() + ->drop('tbl_documentation') + ->ifExists() + ->execute() + ->success(); } public function install() { - Symphony::Database()->query( - "CREATE TABLE `tbl_documentation` ( - `id` int(11) unsigned NOT NULL auto_increment, - `title` varchar(255), - `pages` text, - `content` text, - `content_formatted` text, - PRIMARY KEY (`id`) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;" - ); Symphony::Configuration()->set('text-formatter', 'none', 'documentation'); Symphony::Configuration()->set('button-text', __('Documentation'), 'documentation'); Symphony::Configuration()->write(); - return; + + return Symphony::Database() + ->create('tbl_documentation') + ->ifNotExists() + ->fields([ + 'id' => [ + 'type' => 'int(11)', + 'auto' => true, + ], + 'title' => [ + 'type' => 'varchar(255)', + 'null' => true, + ], + 'pages' => [ + 'type' => 'text', + 'null' => true, + ], + 'content' => [ + 'type' => 'text', + 'null' => true, + ], + 'content_formatted' => [ + 'type' => 'text', + 'null' => true, + ], + ]) + ->keys([ + 'id' => 'primary', + ]) + ->execute() + ->success(); } public function savePreferences($context) { @@ -221,5 +278,5 @@ public function appendPreferences($context) { $group->appendChild($div); $context['wrapper']->appendChild($group); } - + } diff --git a/extension.meta.xml b/extension.meta.xml index 0d7d1f8..14a372e 100644 --- a/extension.meta.xml +++ b/extension.meta.xml @@ -22,6 +22,11 @@