Working with Pages Programmatically
Programmatically Modifying Pages with Concrete
With Concrete, you can programmatically modify pages. Here's how you can set attributes, update properties, or manage pages.
Adjusting Page Attributes
To set the "Exclude from Nav" attribute to true:
$page = \Page::getCurrentPage();
$page->setAttribute('exclude_nav', true);
For complex attributes, such as an address:
$page = \Page::getCurrentPage();
$addressValues = array(
'address1' => '123 SW Test',
'address2' => 'Suite 100',
'city' => 'Portland',
'state_province' => 'OR',
'postal_code' => '99999'
);
$page->setAttribute('address', $addressValues);
Editing Page Properties
Utilize the update
method to change page properties:
$page = \Page::getCurrentPage();
$page->update(array(
'cName' => 'My new page name' // changes the name
));
There are multiple properties you can adjust, such as Name (cName), Description (cDescription), Posting Date (cDatePublic), and more.
Creating a New Page
Choose a parent page, page type, and template to add a new page:
$parentPage = \Page::getByPath('/my/articles');
$pageType = \PageType::getByHandle('blog_post');
$template = \PageTemplate::getByHandle('three_column');
$data = array('cName' => 'Hello World!', 'cDescription' => 'Just a quick blog post.');
$newPage = $parentPage->add($pageType, $data, $template);
Move or Copy a Page
To move:
$entry = \Page::getByPath('/my/articles/hello-all');
$archives = \Page::getByPath('/archives');
$entry->move($archives);
To copy:
$starter = \Page::getByPath("/starters/profile-page");
$parent = \Page::getByPath('/profiles');
$copiedPage = $starter->duplicate($parent);
$copiedPage->update(array('cName' => 'Jane Doe'));
Deleting a Page
Directly deleting:
$pageToDelete = \Page::getByPath('/profiles/jane-doe');
$pageToDelete->delete();
Moving to trash:
$pageToTrash = \Page::getByID(200);
$pageToTrash->moveToTrash();
Note: Direct delete doesn't send the page to trash.
PageList: Searching, Sorting & Filtering Pages
With Concrete CMS, the Concrete\Core\Page\PageList
object lets developers obtain lists of pages based on set criteria. This object is preferred for sorting, searching, or filtering pages over direct database querying. It considers permissions, page versions, aliases, and more.
Get all Pages
$list = new \Concrete\Core\Page\PageList();
$pages = $list->getResults();
This fetches all pages, excluding: - Aliases - Inactive pages - Pages inaccessible due to permissions - System/dashboard pages
Basic Filters:
Specific Page Type
$list = new \Concrete\Core\Page\PageList();
$list->filterByPageTypeHandle('blog_entry');
$pages = $list->getResults();
Multiple Page Types
$list->filterByPageTypeHandle(['blog_entry', 'press_release']);
Keywords
$list->filterByKeywords('foobar');
This searches name, description, text content, and searchable page attributes.
For advanced keyword searching:
$list->filterByFulltextKeywords('foobar');
Attribute Filtering
Use 'magic methods' for easy attribute-based filtering. For instance:
$list->filterByExcludeNav(true);
For topic attributes
$topicNode = \Concrete\Core\Tree\Node::getByID(10);
$list->filterByBlogEntryTopic($topicNode);
Sorting
By Public Date
$list->sortByPublicDate();
Reverse Order
$list->sortByPublicDateDescending();
Alphabetically by Name
$list->sortByName();
Sitemap Order
$list->sortByDisplayOrder();
By Page Attribute
$list->sortByAttributeName();
Inclusions and Permissions
Ignore Permissions
$list->ignorePermissions();
Include Special Pages
$list->includeInactivePages();
$list->includeAliases();
$list->includeSystemPages();
For Multilingual Sites
$list->setSiteTreeToAll();
Advanced Usage
You can directly use the underlying QueryBuilder from Doctrine DBAL:
$list = new \Concrete\Core\Page\PageList();
$qb = $list->getQueryObject();
$qb->where('p.clsActive', 1)
->andWhere('p.clsTemplate', 0)
->orderBy('p.cDisplayOrder', 'ASC');
$pages = $list->getResults();
For repetitive custom queries, extend the PageList
class to create a custom class.
Pagination
For paginating results:
$list = new \Concrete\Core\Page\PageList();
$pagination = $list->getPagination();
$pagination->setMaxPerPage(10)->setCurrentPage(2);
$results = $pagination->getCurrentPageResults();
Rendering Pagination
echo $pagination->renderDefaultView();
For more, refer to the Pagerfanta
documentation.
Custom Page Type Validator
Page types in Concrete define attributes and blocks for specific type of page you expect editors to create frequently. For instance, a Job Posting type might have attributes like "Department" and "Location". To add custom validation, like ensuring a job isn't posted for a date more than 30 days ahead, we use a custom page type validator.
Set Up Custom Validator for Job Posting
- Inform Concrete about the custom validator for the Job Posting page type:
$manager = \Core::make('manager/page_type/validator');
$manager->extend('job_posting', function($app) {
return new \Application\Src\Page\Type\Validator\JobPostingValidator();
});
This code registers our custom validator for the job_posting
page type.
- Create the custom validator:
- Make a directory:
application/src/Page/Type/Validator/
- Add a file:
JobPostingValidator.php
with the following code:
- Make a directory:
<?php
namespace Application\Src\Page\Type\Validator;
use Concrete\Core\Page\Page;
use Concrete\Core\Page\Type\Composer\Control\Control;
use Concrete\Core\Page\Type\Composer\Control\CorePageProperty\DateTimeCorePageProperty;
use \Concrete\Core\Page\Type\Validator\StandardValidator;
class JobPostingValidator extends StandardValidator {
public function validatePublishDraftRequest(Page $page = null) {
$e = parent::validatePublishDraftRequest($page);
foreach(Control::getList($this->type) as $control) {
if ($control instanceof DateTimeCorePageProperty) {
$property = $control;
break;
}
}
$property->setPageObject($page);
$date = $property->getRequestValue() ?: $property->getPageTypeComposerControlDraftValue();
$datetime = is_array($date) ? strtotime(\Core::make("helper/form/date_time")->translate('date_time', $date)) : strtotime($date);
if ($datetime - time() > 2592000) {
$e->add(t('A job cannot be posted more than 30 days in the future.'));
}
return $e;
}
}
This validator ensures a job's date isn't more than 30 days in the future. It keeps standard validation and adds custom logic.
Programmatically Adding Page Types
Example: News Item Page
We'll add a "News Item" page type that can only use the "left side template" and can only be added beneath a "News" page type.
- Import Required Namespaces
use PageType;
use PageTemplate;
use \Concrete\Core\Page\Type\PublishTarget\Type\Type as PublishTargetType;
- Define the Page Template
Only the "left sidebar" template is used:
$left_side = PageTemplate::getByHandle('left_sidebar');
- Add the Page Type
Ensure it doesn't exist, then add:
$newsItem = PageType::getByHandle('news_item');
if (!is_object($newsItem)) {
$newsItem = PageType::add(
array(
'handle' => 'news_item',
'name' => 'News Item',
'defaultTemplate' => $left_side,
'allowedTemplates' => 'C',
'templates' => array($left_side),
'ptLaunchInComposer' => false,
'ptIsFrequentlyAdded' => true
),
$pkg
);
}
- Set Publish Restrictions
Ensure news items are only published under a "News" page type:
$newsTarget = PublishTargetType::getByHandle('page_type');
$newsId = PageType::getByHandle('news')->getPageTypeID();
$configuredNews = $newsTarget->configurePageTypePublishTarget($newsItem, array('ptID' => $newsId, 'selectorFormFactorPageType' => null));
$newsItem->setConfiguredPageTypePublishTargetObject($configuredNews);
Appendix: Publish Target Configuration
All Type
$allTarget = PublishTargetType::getByHandle('all');
$configuredAllTarget = $allTarget->configurePageTypePublishTarget($pageTypeObject, array('selectorFormFactorAll' => null, 'startingPointPageIDall' => (cID)));
$pageType->setConfiguredPageTypePublishTargetObject($configuredAllTarget);
Page Type Type
$typeTarget = PublishTargetType::getByHandle('page_type');
$configuredTypeTarget = $typeTarget->configurePageTypePublishTarget($pageTypeObject, array('ptID' => (ptID), 'startingPointPageIDPageType' => (cID), 'selectorFormFactorPageType' => null));
$pageType->setConfiguredPageTypePublishTargetObject($configuredTypeTarget);
Parent Page Type
$parentTarget = PublishTargetType::getByHandle('parent_page');
$configuredPageTarget = $parentTarget->configurePageTypePublishTarget($pageTypeObject, array('cParentID' => (cID)));
$pageType->setConfiguredPageTypePublishTargetObject($configuredPageTarget);