public function getFormSettings() { $pages = PageModel::Find(['baseurl LIKE /blog/view/%'], null, 'title'); $opts = array('' => 'All Blogs'); foreach ($pages as $page) { $id = substr($page->get('baseurl'), 11); $opts[$id] = $page->get('title'); } $settings = [['type' => 'text', 'name' => 'title', 'title' => 'Displayed Title', 'description' => 'Displayed title on the page where this widget is added to.'], ['type' => 'select', 'name' => 'blog', 'title' => 'Blog', 'options' => $opts, 'description' => 'Choose a specific blog if you wish to retrieve posts from a specific blog.'], ['type' => 'select', 'name' => 'count', 'title' => 'Number of results', 'options' => array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)], ['type' => 'select', 'name' => 'sort', 'title' => 'Sort By', 'options' => array('newest' => 'Newest', 'popular' => 'Most Popular', 'random' => 'Random')]]; return $settings; }
/** * Widget to quickly create a new Content page as a draft. */ public function quickdraft() { $view = $this->getView(); if (!\Core\user()->checkAccess('p:/content/manage_all')) { // Users who do not have access to manage page content do not get this. return ''; } $form = new Form(); $form->set('orientation', 'vertical'); $form->set('callsmethod', 'ContentAdminWidget::QuickDraftSave'); $form->addElement('text', ['name' => 'title', 'placeholder' => 'Page or Post Title']); $form->addElement('textarea', ['name' => 'content', 'placeholder' => "What's up?", 'cols' => 50]); $form->addElement('submit', ['value' => 'Save Draft']); // Load in all the pages on the site that are currently set as draft too, why not? ;) $drafts = PageModel::Find(['published_status = draft'], 10, 'updated DESC'); $view->assign('form', $form); $view->assign('drafts', $drafts); }
public function testBug(){ $selectablepage = PageModel::Find(['selectable' => 1], null); $notselectablepage = PageModel::Find(['selectable' => 0], null); // Both of these should return an array! $this->assertNotEmpty($selectablepage); $this->assertNotEmpty($notselectablepage); // And this needs to be an array too. $pagearray = PageModel::GetPagesAsOptions(); $this->assertNotEmpty($pagearray); // Run through each selectable page and make sure that it displays in the list. foreach($selectablepage as $page){ $this->assertInstanceOf('PageModel', $page); $this->assertArrayHasKey($page->get('baseurl'), $pagearray); } foreach($notselectablepage as $page){ $this->assertInstanceOf('PageModel', $page); $this->assertArrayNotHasKey($page->get('baseurl'), $pagearray); } }
/** * Display the admin dashboard. * * This page is primarily made up of widgets added by other systems. * * @return int */ public function index() { $view = $this->getView(); $pages = PageModel::Find(array('admin' => '1')); $viewable = array(); foreach ($pages as $p) { if (!\Core\user()->checkAccess($p->get('access'))) continue; $viewable[] = $p; } // If there are no viewable pages... don't display any admin dashboard. if(!sizeof($viewable)){ return View::ERROR_ACCESSDENIED; } $view->title = 't:STRING_ADMIN'; $view->assign('links', $viewable); // Dispatch the hook that other systems can hook into and perform checks or operations on the admin dashboard page. HookHandler::DispatchHook('/core/admin/view'); }
/** * See the details of a given search criteria, be it IP address, session, or user. */ public function details(){ $view = $this->getView(); $request = $this->getPageRequest(); $listing = new Core\ListingTable\Table(); $listing->setName('useractivity-details'); $listing->setLimit(100); $listing->addFilter( 'text', ['name' => 'user_id', 'title' => 'User ID', 'link' => FilterForm::LINK_TYPE_STANDARD] ); $listing->addFilter( 'text', ['name' => 'ip_addr', 'title' => 'IP Address', 'link' => FilterForm::LINK_TYPE_STANDARD] ); $listing->addFilter( 'text', ['name' => 'session_id', 'title' => 'Session ID', 'link' => FilterForm::LINK_TYPE_STANDARD] ); $pages = PageModel::Find(null, null, 'baseurl'); $allPages = ['' => '-- ' . t('STRING_ALL_PAGES') . ' --']; foreach($pages as $p){ /** @var PageModel $p */ $allPages[$p->get('baseurl')] = $p->get('baseurl'); } $listing->addFilter( 'select', [ 'name' => 'baseurl', 'title' => 'Page', 'options' => $allPages, 'link' => FilterForm::LINK_TYPE_STANDARD, ] ); $listing->addColumn('Time', 'datetime'); $listing->addColumn('User & Browser'); $listing->addColumn('Type', 'type'); $listing->addColumn('URL & Referrer', 'request'); $listing->addColumn('Referrer', 'referrer', false); $listing->addColumn('Session', 'session_id', false); $listing->addColumn('IP Address', 'ip_addr', false); $listing->addColumn('User Agent', 'useragent', false); $listing->addColumn('Generation', 'processing_time', false); $listing->addColumn('DB Reads', 'db_reads', false); $listing->addColumn('DB Writes', 'db_writes', false); $listing->setModelName('UserActivityModel'); $listing->setDefaultSort('datetime', 'DESC'); $listing->loadFiltersFromRequest($request); $view->title = 'User Activity Details'; $view->assign('listings', $listing); }
public function view(){ $v = $this->getView(); $pages = PageModel::Find(array('admin' => '1')); $groups = array(); $flatlist = array(); if(isset($_SESSION['user_sudo'])){ $p = new PageModel('/user/sudo'); $p->set('title', 'Exit SUDO Mode'); $groups['SUDO'] = [ 'title' => 'SUDO', 'href' => '', 'children' => [ 'Exit SUDO Mode' => $p, ], ]; $flatlist[ 'Exit SUDO Mode' ] = $p; } if(\Core\user()){ foreach($pages as $p){ /** @var PageModel $p */ if(!\Core\user()->checkAccess($p->get('access'))) continue; // Pages can define which sub-menu they get grouped under. // The 'Admin' submenu is the default. $group = $p->get('admin_group') ? $p->get('admin_group') : 't:STRING_ADMIN'; // Support i18n here! if(strpos($group, 't:') === 0){ $group = t(substr($group, 2)); } if(!isset($groups[$group])){ $groups[$group] = [ 'title' => $group, 'href' => '', 'children' => [], ]; } if($p->get('baseurl') == '/admin'){ // Admin gets special treatment. $groups[t('STRING_ADMIN')]['href'] = '/admin'; continue; } switch($p->get('title')){ case 'System Configuration': $p->set('title', "System Config"); break; case 'Navigation Listings': $p->set('title', "Navigation"); break; case 'Content Page Listings': $p->set('title', "Content Pages"); break; default: $p->set( 'title', trim( str_replace(['Administration', 'Admin'],'', $p->get('title')) ) ); } $title = $p->get('title'); // Support i18n here! if(strpos($title, 't:') === 0){ $title = t(substr($title, 2)); } if(isset($groups[$title])){ // Link the main group to this page instead of an empty link. // This removes duplicate links such as the group "User" and page "User". $groups[$title]['href'] = $p->get('rewriteurl'); } else{ // The new grouped pages $groups[$group]['children'][ $title ] = $p; // And the flattened list to support legacy templates. $flatlist[ $title ] = $p; } } // This is a hack to make sure that users can view the /admin link if they can view other admin pages. /*if(sizeof($flatlist) && !isset($groups['Admin']['Dashboard'])){ $p = new PageModel('/admin'); $p->set('title', 'Dashboard'); $groups['Admin']['Dashboard'] = $p; }*/ } ksort($flatlist); ksort($groups); foreach($groups as $gname => $dat){ ksort($groups[$gname]['children']); } // Build a list of languages that can be set by the user. $locales = \Core\i18n\I18NLoader::GetLocalesEnabled(); $selected = \Core\i18n\I18NLoader::GetUsersLanguage(); $languages = []; if(sizeof($locales) > 1){ // There is at least 1 language available on the system, YAY! foreach($locales as $localeKey => $localeDat){ if(($pos = strpos($localeKey, '_')) !== false){ // This locale contains an underscore, that means it has a corresponding country! // These are what we want to display to the end user. $country = substr($localeKey, $pos+1); // Here I am retrieving the language and dialect in the native dialect if at all possible. // This is because if you as a user only can read your native language and your browser renders something different, // then you want to be able to read what you're switching it to. $str1 = new \Core\i18n\I18NString($localeDat['lang']); $str1->setLanguage($localeKey); $localeTitle = $str1->getTranslation(); if($localeDat['dialect']){ $str2 = new \Core\i18n\I18NString($localeDat['dialect']); $str2->setLanguage($localeKey); $localeTitle .= ' (' . $str2->getTranslation() . ')'; } $languages[] = [ 'key' => $localeKey, 'title' => $localeTitle, 'country' => $country, 'image' => 'assets/images/iso-country-flags/' . strtolower($country) . '.png', 'selected' => $localeKey == $selected, ]; } } } $v->templatename = 'widgets/adminmenu/view.tpl'; $v->assign('pages', $flatlist); $v->assign('groups', $groups); $v->assign('languages', $languages); return $v; }
/** * Execute the controller and method this page request points to. */ public function execute() { \Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->record('Starting PageRequest->execute()'); if($this->isCacheable()){ $uakey = \Core\UserAgent::Construct()->getPseudoIdentifier(); $urlkey = $this->host . $this->uri; $expires = $this->getPageModel()->get('expires'); $key = 'page-cache-' . md5($urlkey . '-' . $uakey); $cached = \Core\Cache::Get($key, $expires); if($cached && $cached instanceof View){ $this->_pageview = $cached; $this->_cached = true; return; } } // Anything that needs to fire off *before* the page is rendered. // This includes widgets, script addons, and anything else that needs a CurrentPage. HookHandler::DispatchHook('/core/page/preexecute'); // Load the underlying controller. $pagedat = $this->splitParts(); /** @var View $view The valid view object for this page */ $view = $this->getView(); // The controller must exist first! // (note, the SplitParts logic already takes care of the "Is this a valid controller" logic) if (!(isset($pagedat['controller']) && $pagedat['controller'])) { $view->error = View::ERROR_NOTFOUND; return; } $component = Core::GetComponentByController($pagedat['controller']); ////////////////////////////////////////////////////////////////////////////// /// In this block of logic, either the page is executed and a view returned, /// or a view is generated with an error. ////////////////////////////////////////////////////////////////////////////// if (!$component) { // Not found $view->error = View::ERROR_NOTFOUND; return; } elseif(!is_a($component, 'Component_2_1')) { $view->error = View::ERROR_NOTFOUND; return; } // Any method that starts with a "_" is an internal-only method! if ($pagedat['method']{0} == '_') { $view->error = View::ERROR_NOTFOUND; return; } // It also must be a part of the class... obviously if (!method_exists($pagedat['controller'], $pagedat['method'])) { $view->error = View::ERROR_NOTFOUND; return; } /** @var $controller Controller_2_1 This will be a Controller object. */ $controller = Controller_2_1::Factory($pagedat['controller']); $view->baseurl = $this->getBaseURL(); $controller->setView($view); // Make sure that the controller can access this object. $controller->setPageRequest($this); // The main page object. $page = $this->getPageModel(); // Check the access string first, (if there is one) if ($controller->accessstring !== null) { // Update the page's access string, (just in case it's saved at the end of execution) $page->set('access', $controller->accessstring); // And if the user doesn't have access to it... if (!\Core\user()->checkAccess($controller->accessstring)) { $view->error = View::ERROR_ACCESSDENIED; return; } } if($page->get('password_protected')) { if(\Core\Session::Get('page-password-protected/' . $page->get('baseurl')) !== $page->get('password_protected')){ $view->templatename = '/pages/page/passwordprotected.tpl'; $form = new Form(); $form->set('callsmethod', 'PageRequest::PasswordProtectHandler'); $form->addElement( 'system', [ 'name' => 'page', 'value' => $page ] ); $form->addElement( 'password', [ 'name' => 'passinput', 'title' => 'Password', 'required' => 'required', 'maxlength' => 128 ] ); $form->addElement( 'submit', [ 'value' => 'Submit' ] ); $view->assign('form', $form); return; } } // If the parent Controller object has a method named $pagedat['method'], assume it's a security error! // This is because if the parent Controller object has a method, it's most likely a utility method // that shouldn't be called from the public web! foreach(get_class_methods('Controller_2_1') as $parentmethod){ $parentmethod = strtolower($parentmethod); if($parentmethod == $pagedat['method']){ $view->error = View::ERROR_BADREQUEST; return; } } // Additional security logic for existing pages in multi-site mode. // If this exact URL is registered to another site, then // don't allow this site to display it. if(!$page->exists() && Core::IsComponentAvailable('multisite') && MultiSiteHelper::IsEnabled()){ $site = MultiSiteHelper::GetCurrentSiteID(); $anypage = PageModel::Find(['baseurl = ' . $page->get('baseurl')], 1); if($anypage){ if($anypage->get('site') == -1){ // If this is a global page.... that's ok. // Just remap the page variable to this one! $page = $anypage; } elseif($anypage->get('site') == $site){ // Strange... it should have located this page... // Anyway, it's allowed, the site matches up. $page = $anypage; } else{ \Core\redirect($anypage->getResolvedURL()); } } } $return = call_user_func(array($controller, $pagedat['method'])); if (is_int($return)) { // A generic error code was returned. Create a View with that code and return that instead. $view->error = $return; //return; } elseif(is_a($return, 'View') && $return != $view){ // The controller method changed the view, (which is allowed), // but this needs to be remapped to this object so render knows about it. $this->_pageview = $view = $return; } elseif ($return === null) { // Hopefully it's setup! $return = $controller->getView(); if($return != $view){ $this->_pageview = $view = $return; } } elseif(!is_a($return, 'View')){ if(DEVELOPMENT_MODE){ var_dump('Controller method returned', $return); die('Sorry, but this controller did not return a valid object. Please ensure that your method returns either an integer, null, or a View object!'); } else{ $view->error = View::ERROR_SERVERERROR; return; } } // No else needed, else it's a valid object. // You may be asking why $view is one object, but $return is the return from page execution. // GREAT QUESTION, The $view is the original view object created from the page request. That is passed into // the controller and exposed via $this->getView(). The return can be a view, int, or other status indicator. // However since the controller can return a different view, that view should be used instead! ///** @var $return View */ // Allow the controller to assign controls via a shortcut function. if($view->error == View::ERROR_NOERROR){ $controls = $controller->getControls(); // This method may do absolutely nothing, add the controls to the view itself, or return an array of them. if(is_array($controls)){ foreach($controls as $control){ $view->addControl($control); } } } // For some of the options, there may be some that can be used for a fuzzy page, ie: a page's non-fuzzy template, // title, or meta information. if($view->error == View::ERROR_NOERROR){ if ($page->exists()) { $defaultpage = $page; } else { $defaultpage = null; $url = $view->baseurl; while ($url != '') { $url = substr($url, 0, strrpos($url, '/')); $p = PageModel::Find(array('baseurl' => $url, 'fuzzy' => 1), 1); if ($p === null) continue; if ($p->exists()) { $defaultpage = $p; break; } } if ($defaultpage === null) { // Fine.... $defaultpage = $page; } } $defaultmetas = $defaultpage->getLink('PageMeta'); // Make a list of the existing ones so I know which ones not to overwrite! // Just the key will suffice quite nicely. $currentmetas = array(); foreach($view->meta as $k => $meta){ $currentmetas[] = $k; } // Load some of the page information into the view now! foreach($defaultmetas as $meta){ /** @var $meta PageMetaModel */ $key = $meta->get('meta_key'); $viewmeta = $meta->getViewMetaObject(); // again, allow the executed controller have the final say on meta information. if ($meta->get('meta_value_title') && !in_array($key, $currentmetas)) { $view->meta[$key] = $viewmeta; } } // Since the controller already ran, do not overwrite the title. if ($view->title === null){ $view->title = $defaultpage->get('title'); } // Tracker to see if this page, (or a parent's page), is an admin-level page. // This is required because "admin" pages may have a different skin and should always have the dashboard as the top-level breadcrumb. /** @var boolean $isadmin */ $isadmin = ($page->get('admin') == '1'); $parents = array(); $parenttree = $page->getParentTree(); foreach ($parenttree as $parent) { /** @var PageModel $parent */ $parents[] = array( 'title' => $parent->get('title'), 'link' => $parent->getResolvedURL() ); // Since I'm here, check if this page is an admin page. if($parent->get('admin')){ $isadmin = true; } } $view->breadcrumbs = array_merge($parents, $view->breadcrumbs); if($isadmin && $view->baseurl != '/admin'){ // Make sure that admin is the top breadcrumb. // This block doesn't need to apply for the actual admin page itself, as that doesn't need its own breadcrumb :/ $adminlink = \Core\resolve_link('/admin'); if(!isset($view->breadcrumbs[0])){ // Nothing is even set! $view->breadcrumbs[] = ['title' => 'Administration', 'link' => $adminlink]; } elseif($view->breadcrumbs[0]['link'] != $adminlink){ // It's set, but not to admin. $view->breadcrumbs = array_merge([['title' => 'Administration', 'link' => $adminlink]], $view->breadcrumbs); } } } else{ $defaultpage = null; $isadmin = false; } if( $view->mode == View::MODE_PAGEORAJAX && $this->isAjax() && $view->jsondata !== null && $view->templatename === null ){ // Allow the content type to be overridden for ajax pages that have JSON data embedded in them. $view->contenttype = View::CTYPE_JSON; } if($view->mode == View::MODE_NOOUTPUT){ $view->mastertemplate = false; $view->templatename = null; } elseif( $view->error == View::ERROR_NOERROR && $view->contenttype == View::CTYPE_HTML && $view->templatename === null ){ // Try to guess the templatename if it wasn't set. // This $cnameshort = (strpos($pagedat['controller'], 'Controller') == strlen($pagedat['controller']) - 10) ? substr($pagedat['controller'], 0, -10) : $pagedat['controller']; $view->templatename = strtolower('/pages/' . $cnameshort . '/' . $pagedat['method'] . '.tpl'); } elseif( $view->error == View::ERROR_NOERROR && $view->contenttype == View::CTYPE_XML && $view->templatename === null ){ $cnameshort = (strpos($pagedat['controller'], 'Controller') == strlen($pagedat['controller']) - 10) ? substr($pagedat['controller'], 0, -10) : $pagedat['controller']; $view->templatename = Template::ResolveFile(strtolower('pages/' . $cnameshort . '/' . $pagedat['method'] . '.xml.tpl')); } // In addition to the autogeneration, also support the page_template from the datastore. if($defaultpage && $defaultpage->get('page_template')){ // Switch the template over to that custom one. // Some legacy data will have the fully resolved path for this template. // This has been switched to just the basename of the custom template, // but legacy data be legacy, 'yo. 0.o $base = substr($view->templatename, 0, -4); $override = $defaultpage->get('page_template'); if($base && strpos($override, $base) === 0){ $view->templatename = $override; } elseif($base){ $view->templatename = $base . '/' . $override; } } // Guess which theme skin (mastertemplate) should be used if one wasn't specified. if($view->mastertemplate == 'admin'){ // If the master template is set explictly to be the admin skin, then transpose that to the set admin skin. // This is useful for the pages that may not be under the "/admin" umbrella, but still rendered with the admin UI. $view->mastertemplate = ConfigHandler::Get('/theme/default_admin_template'); } elseif($view->mastertemplate){ // No change needed, just skip the below cases. } elseif($view->mastertemplate === false){ // If the master template is explictly set to false, the page wanted no master template! } elseif($isadmin){ // This page doesn't have a master template set, but it or a parent is set as an admin-level page. $view->mastertemplate = ConfigHandler::Get('/theme/default_admin_template'); } elseif ($defaultpage && $defaultpage->get('theme_template')) { // Master template set in the database? $view->mastertemplate = $defaultpage->get('theme_template'); } elseif($defaultpage && $defaultpage->exists() && $defaultpage->get('admin')){ // Or an admin level page? $view->mastertemplate = ConfigHandler::Get('/theme/default_admin_template'); } elseif(sizeof($view->breadcrumbs) && $view->breadcrumbs[0]['title'] == 'Administration'){ // Whatever, close e-damn-nough! // This happens for pages that don't actually exist, like "edit".... $view->mastertemplate = ConfigHandler::Get('/theme/default_admin_template'); } else{ $view->mastertemplate = ConfigHandler::Get('/theme/default_template'); } // First of all, if the current theme is not available, reset back to the first theme available! if(!($theme = ThemeHandler::GetTheme())){ /** @var \Theme\Theme $theme */ $theme = ThemeHandler::GetTheme('base-v2'); $view->mastertemplate = 'basic.tpl'; \Core\set_message('t:MESSAGE_ERROR_INVALID_THEME_SELECTED'); } // Make sure the selected mastertemplate actually exists! if($view->mastertemplate !== false){ $themeskins = $theme->getSkins(); $mastertplgood = false; foreach($themeskins as $skin){ if($skin['file'] == $view->mastertemplate){ // It's located! $mastertplgood =true; break; } } // A few special cases. if($view->mastertemplate == 'blank.tpl'){ // This is acceptable as a default one. $mastertplgood =true; } if(!$mastertplgood){ // Just use the first one instead! trigger_error('Invalid skin [' . $view->mastertemplate . '] selected for this page, skin is not located within the selected theme! Using first available instead.', E_USER_NOTICE); $view->mastertemplate = $themeskins[0]['file']; } } // Handle some of the new automatic meta data associated with Pages and the resulting View. if(\ConfigHandler::Get('/core/page/indexable') == 'deny'){ // Administratively set to noindex on all pages. $view->addMetaName('robots', 'noindex'); } elseif(!$page->get('indexable')){ // Bots have no business indexing user-action pages. $view->addMetaName('robots', 'noindex'); } if(!isset($view->meta['title'])){ $view->meta['title'] = $page->getSEOTitle(); } HookHandler::DispatchHook('/core/page/postexecute'); \Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->record('Completed PageRequest->execute()'); }
/** * This is a widget to display children of the current page * * The page is dynamic based on the currently viewed page. * * @return int */ public function children() { $view = $this->getView(); $current = PageRequest::GetSystemRequest(); $model = $current->getPageModel(); if (!$model) { return ''; } $baseurl = $model->get('baseurl'); // Give me all the siblings of that baseurl. $pages = PageModel::Find(['parenturl' => $baseurl, 'selectable' => 1], null, 'title'); $entries = []; foreach ($pages as $page) { $subpages = PageModel::Find(['parenturl' => $page->get('baseurl'), 'selectable' => 1], null, 'title'); $subentries = []; foreach ($subpages as $subpage) { $subentries[] = ['obj' => $subpage, 'children' => [], 'class' => '']; } $entries[] = ['obj' => $page, 'children' => $subentries, 'class' => 'active']; } $view->assign('entries', $entries); }
<?php /** * Created by JetBrains PhpStorm. * User: powellc * Date: 1/17/13 * Time: 10:20 PM * This is the upgrade file from 1.3.0 to 1.4.0 * * Now that core supports selectable and non-selectable pages, I need to update all the existing blog articles to make them not selectable. */ $pages = PageModel::Find(array('baseurl LIKE /blog/article/view/%')); foreach ($pages as $page) { $page->set('selectable', 0); $page->save(); } // return
/** * Hook to check for any new files in the system and register pages (or deregister them as necessary). * * Only runs if the config option is enabled to do so. */ public static function _AutoRegisterFiles() { if (!\ConfigHandler::Get('/markdownbrowser/autoregister')) { echo 'Skipping autoregistration of markdown files, configuration option for this feature is disabled.' . "\n"; return true; } $dir = \ConfigHandler::Get('/markdownbrowser/basedir'); $markdownFiles = []; if (!$dir) { echo 'Skipping autoregistration of markdown files, no markdown directory configured.' . "\n"; return true; } // Make sure it's readable! $dir = \Core\Filestore\Factory::Directory($dir); $dirbase = $dir->getPath(); $dirlen = strlen($dirbase); if (!$dir->exists()) { echo 'Skipping autoregistration of markdown files, ' . $dir->getPath() . ' does not exist.' . "\n"; return true; } $all = []; $files = $dir->ls('md', true); foreach ($files as $file) { /** @var \Core\Filestore\File $file */ $fileBase = substr($file->getFilename(), $dirlen); if (strpos($fileBase, 'index.md') !== false) { $fileRel = substr($fileBase, 0, -8); } else { $fileRel = substr($fileBase, 0, -3); } if (preg_match('/[A-Z]/', $fileRel) !== 0) { $warning = t('STRING_MARKDOWNBROWSER_WARNING_FILE_HAS_CAPITALS'); } elseif (strpos($fileRel, ' ')) { $warning = t('STRING_MARKDOWNBROWSER_WARNING_FILE_HAS_SPACES'); } else { $warning = ''; } if ($warning == '') { $url = '/markdownbrowser/view/' . $fileRel; $all[$url] = ['file' => $file, 'page' => null]; } else { echo $warning . ' - ' . $fileRel . "\n"; } } // Now that the files are loaded into memory, load any page that may already exist. // This will be used to ignore entries that already have a page, to create ones without, // and to remove pages that no longer have a corresponding file. $pages = PageModel::Find(['baseurl LIKE /markdownbrowser/view%']); foreach ($pages as $p) { $url = $p->get('baseurl'); if (!isset($all[$url])) { $all[$url] = ['file' => null, 'page' => null]; } $all[$url]['page'] = $p; } // Now $all contains everything I need to process on! :) foreach ($all as $url => &$dat) { /** @var PageModel|null $page */ $page = $dat['page']; /** @var \Core\Filestore\File|null $file */ $file = $dat['file']; if ($page && !$file) { // There is a page but no file, DELETE! $page->delete(); echo 'Deleted page for non-existent file: ' . $url . "\n"; } elseif (!$page && $file) { // There is a file but no page, create. $contents = $file->getContents(); // Convert these contents from markdown to HTML. $processor = new \Core\MarkdownProcessor(); $html = $processor->transform($contents); // Pre-populate this page with information from the rendered markdown document. // If this page exists, then it'll be updated and kept in sync. // Else, it'll still be set with what's in the document and kept in sync. $page = PageModel::Construct($url); $page->set('title', $processor->getMeta('title')); $page->set('body', $html); $page->set('baseurl', $url); $page->set('rewriteurl', $url); $page->set('editurl', str_replace('/markdownbrowser/view', '/markdownbrowser/update', $url)); $page->set('component', 'markdown-browser'); $page->set('selectable', 1); $page->set('published', $file->getMTime()); $page->set('updated', $file->getMTime()); $page->set('created', $file->getMTime()); $page->save(); echo 'Created page for new file: ' . $url . "\n"; } } return true; }