concrete5 Cookbook

3 (1 reviews total)
By David Strack
  • Instant online access to over 8,000+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Pages and Page Types

About this book

concrete5 is an increasingly popular open source content management system because of its incredible and easy-to-use interface. But, it also comes complete with a robust PHP framework, allowing web developers to create custom websites and applications with ease.

"concrete5 Cookbook" is a practical collection of solutions to tasks that both novice and experienced concrete5 developers face on a regular basis. Readers will learn multiple subjects, including full blueprints for developing an event calendar add-on and an image gallery block. Developers new to concrete5 will quickly learn how to customize concrete5 to their needs, and seasoned pros will find it an excellent quick reference for performing specific tasks.

"concrete5 Cookbook" will transform ordinary PHP developers into concrete5 experts capable of bending concrete5 to their will and unleashing the true power of this up-and-coming content management system. Throughout the course of over 140 recipes and 3 bonus project blueprint chapters, PHP developers will learn how to create custom blocks and dashboard interfaces as well as programmatically work with pages, files, users, permissions, and more. Discover the built-in Active Record support that makes working with databases simple and maintainable. Readers will also learn how to take advantage of the numerous helper classes included in concrete5, and will dive deep into the concrete5 MVC framework to create powerful custom websites and applications. Tie together all of the concepts learned in the recipes with 3 bonus chapters featuring complete blueprints to create a calendar add-on, an image gallery block type, and tips on how to sell your themes and add-ons for money!

"concrete5 Cookbook" is a complete collection of recipes to solve the most common (and some not-so-common) tasks that concrete5 developers will face on a regular basis.

Publication date:
July 2013
Publisher
Packt
Pages
296
ISBN
9781782164548

 

Chapter 1. Pages and Page Types

In this chapter we will cover the following topics:

  • Getting the current Page object

  • Getting a Page object by its ID

  • Getting a Page object by its path

  • Getting a Page type by its ID

  • Getting a Page type by its handle

  • Getting a page type's ID

  • Getting a page type's name

  • Getting a page type's handle

  • Getting the icon for a page type

  • Getting a list of pages that belong to a page type

  • Creating a page type

  • Updating a page type

  • Deleting a page type

  • Creating a page type

  • Updating an existing page

  • Setting page attributes

  • Getting a page attribute

  • Getting a page's ID

  • Getting a page's path

  • Getting a page's handle

  • Getting a page's name

  • Getting a page's description

  • Getting a page's page type ID

  • Getting a page's page type handle

  • Getting a page's theme object

  • Getting the children below a page

  • Moving a page

  • Deleting a page (and its children)

  • Getting a list of pages

  • Adding a page selector field to a form

 

Introduction


At the center of almost any content management system is the concept of pages. concrete5 pages contain reusable portions of content called blocks. Blocks can contain anything from formatted text content that you enter yourself, to photo slideshows, to videos, to custom forms that you have developed that contain special functionality. concrete5 pages are extensions of the internal Collection object, which gets its name from the fact that it contains a collection of blocks that make up the page.

Since pages on a website usually contain repeating areas of information (perhaps a sidebar with some persistent widgets), concrete5 includes the concept of page types. Page types allow you to define different templates for creating new pages in concrete5. They are used to specify a default set of blocks, content, and special attributes that are added to new pages of that type, as well as to create different visual layouts through the concrete5 website.

A common page type would be Left Sidebar, which contains a list of links in the sidebar with an area to add blocks of content on the right. A normal concrete5 installation comes with a few default page types out of the box, including Left Sidebar and Full Width. In code, page types are referred to either by their unique numerical ID in the database, or more commonly, a human readable identifier called a handle. The Left Sidebar page type, for example, would have a handle of left_sidebar.

When adding pages to a concrete5 website through the user interface, you will likely notice that the first step is choosing a page type. Page types are also used by the Composer feature of concrete5, which can assist in creating several pages of the same type (such as blog posts).

There are two types of pages in concrete5, the first being a standard page that gets added to the sitemap and gets assigned a page type, and the second a single page, which is handled a bit differently and does not get assigned a page type. This chapter will deal with pages of the first type.

A note about the code in this chapter

Typically, you will write code that interacts with pages and page types in a block, a controller, or a model in your concrete5 application. For the purpose of these demonstrations, you can place the code anywhere where concrete5 lets you execute arbitrary PHP code.

A great place for this is to add a site_process.php or site_post.php file to your site's root /config directory. concrete5 will execute all of the code in that file once all of the core classes and libraries have been loaded (site_post gets executed before the current page has been loaded, site_process gets executed after the current page has been set). We will use classic PHP debugging techniques to verify that our code is working. Typically, we will dump the contents of a variable using PHP's var_dump or print_r functions followed by an exit command.

Because the debugging techniques used in this book can interrupt the regular functionality of a concrete5 website, it is recommended that you perform these exercises on a development copy of concrete5.

Be sure to comment out or remove the debugging code once you are finished, to resume the normal functionality of your concrete5 website.

 

Create a custom debugging function


To aid in the dumping of variables, we can create a simple debugging function that will wrap our output in <pre> tags and automatically exit for us.

Place the following code at the top of /config/site_post.php (create the file if it does not exist):

function my_debug($var) {
  echo '<pre>';
  print_r($var);
  echo '</pre>';
  exit;
}

Tip

Downloading the example code

You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

Now, when we wish to inspect the contents of a variable or other object, we can simply call my_debug($variable), and get a nicely formatted, easy to read response.

Of course, you are more than welcome to use your own techniques for debugging variables.

 

Getting the current Page object


A very common task for concrete5 developers is to retrieve information from the page that is currently displayed. You will encounter this situation quite often, whether you need to update some information about the current page (such as a page title), check the current user's permissions on this page, or just display the page title. Fortunately, this is quite simple.

How to do it...

The steps for getting the current Page objects are as follows:

  1. Create /config/site_process.php if it does not exist.

  2. Open /config/site_process.php in your preferred text editor.

  3. We can get the current Page object by calling the getCurrentPage static function of the Page class.

    $currentPage = Page::getCurrentPage();
  4. If we inspect the contents of the $currentPage variable, we can see that it is a Page object, and now we are ready to perform further operations on it. In this example we are using our custom debugging function that was created in the chapter introduction.

    my_debug($currentPage);

How it works...

Calling the static getCurrentPage function on the Page class will look in the concrete5 Request object to get the current page. If that is not set, concrete5 will use the global $c variable. Note the use of site_process.php to dump the current page variable. We used this file because it is read after concrete5 has set the current Page object. Using site_post.php would have resulted in a null object.

There's more...

You may have already noticed that sometimes developers will use the global variable, $c, within their code to get the current Collection or Page object. This typically works fine, but best practices would be to use the getCurrentPage function to handle this for you.

See also

  • The Getting a Page object by its ID recipe

  • The Getting a Page object by its path recipe

 

Getting a Page object by its ID


In many situations, you will need to load a Page object using its unique numerical ID from the database. As mentioned earlier, pages are actually extensions of the Collection object, so you will actually be loading the page by its collection ID.

Getting ready

We will need to know the numerical ID of the page that you are attempting to load. Often this will be stored in other objects, perhaps even a custom entity that you have stored in the database. For example, say you have a recipes table in the database, and each recipe has its own page in the concrete5 website. You store the page ID for each recipe, so you can load the relevant Page object whenever necessary.

How to do it...

First you will have to get the page ID for the Page object that you are trying to load. For this example, we will just hard-code the ID of the page that we are loading. The steps are as follows:

  1. Open /config/site_post.php in your favorite code editor.

  2. First, let's store the ID of the page we are loading into a variable. In real-world use, you will likely have this ID stored in a database table, or available from some other code that you have run. The ID of the home page in concrete5 defaults to 1, so we will use that for our page's ID:

    $pageId = 1; // load the home page
  3. Now that we have the ID of the page that we need to load, use the getByID function to get the Page object that we need:

    $page = Page::getByID($pageId);
  4. We can inspect the $page variable and verify that it contains a Page object.

    my_debug($page);

How it works...

The page ID (also known as collection ID) is unique in the database, so calling the getByID function will load the correct page data and return a Page object that you can interact with.

See also

  • The Getting the current Page object recipe

  • The Getting a Page object by its path recipe

 

Getting a Page object by its path


concrete5 also supports the loading of Page objects by the path that is displayed in the web browser. This is a convenient way to load pages without knowing their numerical ID. In this exercise, we will load an About Us page by its path.

Getting ready

We will be loading a page with the path of /about-us. If this page does not exist in your concrete5 site, please add it to the sitemap before attempting this exercise.

How to do it...

Using a static function called getByPath, we can easily get a Page object without knowing the ID. The steps are as follows:

  1. Open the /config/site-post.php file in your code editor.

  2. Declare the path of the page that you wish to load.

    $path = '/about-us';
  3. We can load the page located at http://example.com/about-us by passing the path string to the getByPath function.

    $aboutPage = Page::getByPath($path);
  4. To make sure we grabbed the correct page, dump the $aboutPage variable to verify that we have a fully loaded Page object. We will use the custom debug function that we created in the chapter introduction.

    my_debug($aboutPage);

How it works...

concrete5 will query the database for the page that has the specified path assigned to it. You will want to use good judgment when loading pages by their paths, as that data can change easily through the concrete5 interface. Imagine that you are working on a site with 15 editors, and any one of them has the ability to edit the path of a page. concrete5 by default will save old page paths whenever a new one is changed, but it is not required. Hard coding page paths in your custom applications should be used only when appropriate. It is a much better idea to load pages by their ID whenever possible, as that ID does not change.

There's more...

You can load any page on the site using this technique. To load a Careers page that exists below the About page that we just loaded, you would write the following:

$careersPage = Page::getByPath('/about-us/careers');

You should know that concrete5 will cache the page IDs related to each path, so if you are experiencing unexpected results while using this function, make sure to clear your site cache by visiting /dashboard/system/optimization/clear_cache/ on your concrete5 website.

See also

  • The Getting the current Page object recipe

  • The Getting a Page object by its ID recipe

 

Getting a page type by its ID


When creating and editing pages in concrete5 development, you will inevitably need to load the desired page type object that will be assigned to a page. Note that page types are actually instances of the CollectionType object in code. For consistency, we will continue to refer to them as page types outside of code.

Getting ready

We will continue performing these examples in the /config/site-post.php file, as that is a quick and easy place to run the arbitrary code. We will also continue making use of our custom my_debug function that was defined in the chapter introduction.

In this recipe, we will be loading a page type with the ID of 4. Please make sure that this page type exists in your instance of concrete5, otherwise change the ID to something appropriate to your environment.

How to do it...

Much like loading pages, you will need to call a static function on the CollectionType class. The steps are as follows:

  1. Open /config/site_post.php in your text editor.

  2. First, we will need to know the numerical ID of the page type. In this case, we are going to assume that a page type called "Left Sidebar" exists, and that it has the numerical ID of 4.

    $leftSidebarId = 4;
  3. Now that we have the ID of the page type that we wish to load, we can call the getByID function of the CollectionType class.

    $leftSidebarPageType = CollectionType::getByID($leftSidebarId);
  4. We can verify that we loaded the correct page type by inspecting the $leftSidebarPageType variable and verifying that it is an instance of the CollectionType class.

    my_debug($leftSidebarPageType);

How it works...

The getByID function performs a simple database query to find the page type that belongs to that ID. A CollectionType object is returned when a successful lookup is made.

See also

  • The Getting a page type by its handle recipe

 

Getting a page type by its handle


As mentioned in the chapter introduction, page types also have human readable handles, which offer a convenient way of loading page types without knowing their numerical IDs. Handles are always alphanumerical strings with underscores between words, and do not contain any file extensions such as .php. For example, the handle for a page type called "Left Sidebar" would most likely be left_sidebar, but concrete5 lets users specify any alphanumeric string for a handle, so it's possible that the handle for Left Sidebar would also just be left.

You can find the handles of page types by visiting the Page Types area of the concrete5 dashboard, located at /dashboard/pages/types/ on your concrete5 website.

Getting ready

In this recipe, we will be loading a page type with the handle of left_sidebar. Please make sure that page type exists in your concrete5 installation, otherwise you can add a new page type with that handle, or adapt the recipe to work for your situation.

How to do it...

Here's how we would load the page type with a handle of left_sidebar. This is similar to loading a page by its path. The steps are as follows:

  1. Open /config/site_post.php in your preferred code editor.

  2. Declare the handle of the page type that you wish to load.

    $handle = 'left_sidebar';
  3. Load the page type using the handle that we just defined.

    $pageType = CollectionType::getByHandle($handle);
  4. You can verify that you have loaded the page type by dumping the $pageType variable.

    my_debug($pageType);

How it works...

A simple database query is performed, which will return a CollectionType object if it is successful.

There's more...

Just like the warning for loading pages by their paths, you will want to exercise the same good judgment when loading page types by their handles. Since these handles are just strings that can be edited through the concrete5 interface, you will need to make sure that you aren't writing code that could break if one of the site editors changes the handle of a page type.

See also

  • The Getting a page type by its ID recipe

 

Getting a page type's ID


Once a page type has been loaded, we can get different information from it. Sometimes, if a page type is loaded by its handle, or if it was provided from another function call, developers will need to get the page type's ID from an existing page type object. In this exercise, we will load a page type by its handle, and then find out the ID of the page type.

Getting ready

We will be loading a page type with a handle of right_sidebar in this example. If that page type does not exist in your concrete5 system, feel free to adapt this recipe to suit your specific situation.

How to do it...

The steps for getting a page type's ID are as follows:

  1. Open /config/site_post.php in your code editor.

  2. Load the page type by its path:

    $pageType = CollectionType::getByHandle('right_sidebar');
  3. Get the ID from the page type.

    $id = $pageType->getCollectionTypeId();
  4. Dump the page type ID (we are using the custom debugger explained in this chapter's introduction).

    my_debug($id);

How it works...

Once the page type object is loaded, developers can call a number of functions to retrieve data from it, including the numeric ID.

See also

  • The Getting a page type by its handle recipe

 

Getting a page type's name


Page type objects also contain methods to retrieve the name of the page type. In this exercise, we will load a page type by its handle, and then retrieve the name of the page type.

Getting ready

We will be loading a page type with the handle of right_sidebar, so if that page type does not exist in your instance of concrete5, please adapt this recipe to suit your needs.

How to do it...

The steps for getting a page type's name are as follows:

  1. Open /config/site_post.php in your preferred code editor.

  2. Load the page type by its handle:

    $pageType = CollectionType::getByHandle('right_sidebar');
  3. Get the name of the page type.

    $name = $pageType->getCollectionTypeName();
  4. Dump the name using our custom debugger.

    my_debug($name);

How it works...

The getCollectionTypeName function simply returns the string value of the page type's name.

See also

  • The Getting a page type by its handle recipe

 

Getting a page type's handle


If a page type has been loaded by its ID or has been provided in a different manner, developers may want to retrieve the handle of the page type. In this example, we will load a page type with an ID of 4 and use the concrete5 API to get its handle.

Getting ready

We will be loading a page type with an ID of 4, so please ensure that this exists in your concrete5 website. Feel free to change the ID in this recipe to something appropriate for your instance of concrete5.

How to do it...

The steps for getting a page type's handle are as follows:

  1. Open /config/site_post.php in your preferred code editor.

  2. Load the page type by its ID.

    $pageType = CollectionType::getByID(4);
  3. Get the handle of the page type.

    $handle = $pageType->getCollectionTypeHandle();
  4. Dump the handle using our custom debugger function.

    my_debug($handle);

How it works...

The function getCollectionTypeHandle of the page type object returns the handle string of the page type.

See also

  • The Getting a page type by its ID recipe

 

Getting the icon for a page type


In the concrete5 dashboard interface, page types have icons associated with them. In some advanced applications, you may want to retrieve the icon for the page type. In this recipe, we will load a page type by its handle and get its icon.

Getting ready

We will be loading a page type with a handle of right_sidebar. Feel free to change this handle to something appropriate for your concrete5 instance if right_sidebar does not exist.

How to do it...

The steps for getting the icon for a page are as follows:

  1. Open /config/site_post.php in your favorite code editor, as this is a good place to try out random code.

  2. Load the page type by its path.

    $pageType = CollectionType::getByHandle('right_sidebar');
  3. Get the icon image.

    $icon = $pageType->getCollectionTypeIconImage();
  4. Output the image. You should see the icon's image appear.

    echo $icon;
    exit;

How it works...

concrete5 returns a string containing the actual HTML image tag with the collection type's icon.

There's more...

If you would like to get the numeric ID of the file containing the page type icon, you can simply call this function:

$iconId = $pageType->getCollectionTypeIcon();

The numeric ID is useful when working with the file manager in concrete5, which is discussed in detail in Chapter 3, Files and File Sets of this book.

See also

  • The Getting a page type by its ID recipe

 

Getting a list of pages that belong to a page type


In many advanced concrete5 applications, developers may need to find a list of all of the pages that belong to a given page type. In this example, we will get an array of pages that have a page type with the handle of right_sidebar.

Getting ready

If your instance of concrete5 does not have a page type with the handle of right_sidebar, feel free to adapt the recipe to suit your needs. We will continue using /config/site_post.php as our sandbox to run random code snippets, as well as our custom debugging function that we created in this chapter's introduction.

How to do it...

The steps for getting a list of pages belonging to a page type are as follows:

  1. Open /config/site_post.php in your code editor to try out the following code.

  2. Load the page type by its handle.

    $pageType = CollectionType::getByHandle('right_sidebar');
  3. Get the array of Page objects.

    $pages = $pageType->getPages();
  4. Dump the array to see its contents.

    foreach ($pages as $page) {
      echo $page->getCollectionTitle().'<br />';
    }
    exit;

How it works...

concrete5 simply uses the relational MySQL database to find all of the pages that are related to the page type. Be aware that concrete5 ignores permissions settings when this function is called, so this should really only be used for internal purposes.

See also

  • The Getting a page type by its handle recipe

 

Creating a page type


You can easily add new page types through the concrete5 user interface, but there are some situations that can require you to create page types dynamically using PHP code.

Getting ready

First, you will need to create an associative array that contains the data of the page type that you are creating.

The array can contain the following fields:

Attribute

Required?

Description

ctHandle

Yes

The collection type handle: an alphanumeric string with underscores between words.

ctName

Yes

The collection type name: a string that will appear in the concrete5 interface.

ctIcon

No

If you'd like to specify an icon for this page type, pass in the numerical ID of the icon from the File Manager.

ctIsInternal

No

A Boolean indicating if this page type is an internal page type. Internal page types do not appear in the page creation dialog in the concrete5 interface.

akID

No

An array of attribute key IDs to be added to the new page type.

How to do it...

We will create a page type using only the required fields: ctHandle and ctName. The steps are as follows:

  1. Open /config/site_post.php in your preferred code editor.

  2. Declare the handle of the new page type to be created.

    $handle = 'page_type_handle';
  3. Declare the array that contains the data for the ctHandle and ctName fields.

    $data = array(
      'ctHandle' => $handle,
      'ctName' => 'Page Type Name'
    );
  4. Check to see if the page type already exists by loading it by the new handle.

    $pageType = CollectionType::getByHandle($handle);
  5. If the page type does not exist, create it.

    if (!$pageType) {
      $newPageType = CollectionType::add($data);
    }
  6. If it does exist, assign the existing page type to the new page type variable.

    else {
      $newPageType = $pageType;
    }
  7. Dump the new page type variable to ensure that it worked.

    my_debug($newPageType);

How it works...

concrete5 will take the data array that you pass in and use it to create a new CollectionType record in the database. concrete5 will also automatically generate a Master Collection page in the database. The Master Collection is a template page that concrete5 will use as base for all pages of that type. Any blocks, attributes, or other data assigned to the Master Collection will automatically be added to any new pages created with that page type.

There's more...

If you are creating this page type in a custom package, you will need to pass in your package object to the add() function, so concrete5 knows that this page type belongs to your package. That way, when users uninstall your package, they will have the option of removing all of the page types that it created.

Assuming that you know the handle of your package, use the following code to create a page type with it:

$data = array(
  'ctHandle' => $handle,
  'ctName' => 'Page Type Name'
);
$pkg = Package::getByHandle('my_package');
$newPageType = CollectionType::add($data, $pkg);

See also

  • The Creating custom add-on package recipe

  • The Updating a page type recipe

 

Updating a page type


Updating page types is very similar to creating a page type as discussed in the previous recipe.

How to do it...

First you will need to load an existing page type. You will need to pass in the same data array when updating page types as you would when creating them. The steps are as follows:

  1. Open /config/site_post.php in your code editor.

  2. Declare the old handle and the new handle variables.

    $handle = 'page_type_handle';
    $newHandle = 'new_handle';
  3. Define the new $data array with the new handle and new name.

    $data = array(
      'ctHandle' => $newHandle,
      'ctName' => 'New Name'
    );
  4. If the page type exists, update it.

    $pageType = CollectionType::getByHandle($handle);
    if ($pageType) {
      $pageType->update($data);
    }
  5. Verify that the page type was updated by visiting /dashboard/pages/types in your concrete5 website.

How it works...

concrete5 will update the record in the database for the loaded page type. The Master Collection page is not updated when this function is called. You also cannot pass a packaged object to the update function, as that is only necessary when first creating a page type.

See also

  • The Creating a page type recipe

  • The Deleting a page type recipe

 

Deleting a page type


In addition to adding and editing page types, you can also delete them.

Getting ready

Since deleting page types is a destructive action that is irreversible, it's a good idea to create a dummy page type with the handle of delete_me for this exercise. We will also continue using site_post.php to execute arbitrary code.

How to do it...

The steps for deleting a page type are as follows:

  1. Open /config/site_post.php in your preferred code editor.

  2. Define the handle of the page to be deleted.

    $handle = 'delete_me';
  3. Load the page type by its handle.

    $pageType = CollectionType::getByHandle($handle);
  4. Now, delete the page type.

    $pageType->delete();

How it works...

The delete() function deletes the page type, the Master Collection, and all of the pages that use it. Use this function very cautiously, as once the data has been deleted, it cannot be recovered (unless you have a backup copy of the site's database).

See also

  • The Getting a page type by its ID recipe

 

Creating a page type


Creating pages dynamically is a central concept of concrete5 development and can unlock a lot of powerful features in custom applications. Imagine a concrete5 website that has a recipes database. You could make it so, that every time a recipe is added to the database, a new page for that recipe is added to the sitemap, immediately improving the depth of content on your website, its usability, and even search engine performance.

In this example, we will create an "About Us" page and add it to the sitemap.

Getting ready

We are continuing the practice of putting our code in /config/site_post.php for the purposes of demonstration and testing. In real-world use, your dynamic page creation would happen in controller files or in add-on packages.

We will be assigning the new page a page type with the handle of right_sidebar. If this doesn't exist in your own concrete5 installation, please adapt the recipe to suit your needs.

How to do it...

The steps for creating a page are as follows:

  1. Open /config/site_post.php in your code editor.

  2. Load the page type that the new page will use. We will load the page type using its handle (right_sidebar, in this case).

    $pageType = CollectionType::getByHandle('right_sidebar');
  3. Create an associative array that contains the fields that you wish to specify for the new page. In this example, we will only specify the page's name and handle.

    $data = array(
      'cName' => 'About Us',
      'cHandle' => 'about'
    );
  4. Load the parent page that the new page will be placed under. In this case, we are loading the home page, since the new page will be available at the top level.

    $parent = Page::getByID(1);
  5. Add the page by passing the $pageType object and $data array to the add function of the parent Page class.

    $newPage = $parent->add($pageType, $data);
  6. Output a message and exit the process.

    echo 'done!';
    exit;
  7. Visit your site's homepage to execute the code in site_post.php.

  8. If you see the success message, comment out the code in site_post.php so you can visit the newly created page. Otherwise, concrete5 will create a new page every time the site is loaded into a browser.

  9. Visit the newly created page at http://example.com/about.

How it works...

The add() function is a wrapper for the Collection class's add() function. Calling it will create a new Collection record in the database, and a new pending CollectionVersion record (which will be approved if the cvIsApproved variable is set to true or left blank). Then the new page will inherit the necessary permissions and get all of the blocks and other attributes from the Master Collection of the related page type.

There's more...

You will need to provide two parameters to the add() function, a CollectionType object (which we worked with earlier in this chapter), and an associative array containing all of the data needed to create the page. The associative array can contain the following fields.

Attribute

Required?

Description

cName

Yes

This is the name of the page. This will be how the page is referred to throughout the site, and will be automatically used in the page's <title> tag (unless overridden by a meta title attribute, which you can specify after the page has been created.)

cHandle

No

This is the handle of the page, that is, how the page title will appear in the page URL. If you omit this field, concrete5 will generate a handle based off of the cName field. This is a little confusing, because concrete5 allows dash characters ("-") in page handles, but does not seem to support them anywhere else. This is good, though, because the typical convention for page paths on the web is to use dashes rather than underscores.

cDescription

No

This is the internal description of the page. It is just a string that describes the purpose of a page. Some themes might use this data somewhere in the theme, but it is not required. Older versions of concrete5 displayed the description of the page in the dashboard, but that has gone away since the update to version 5.5.

uID

No

This is an integer ID to indicate the page's author. Pass in the ID of any user in the concrete5 Users table to set that user as the page author. If omitted, the currently logged in user will be registered as the page author.

pkgID

No

This is an integer ID of the package that created this page. Make sure to include this field if you are creating pages from a package. If you omit this field, but the attached page type belongs to a package, the page type's package ID will be attached to this page. This will help users optionally remove any pages that were created by your package if they choose to uninstall your package.

cDatePublic

No

This is a MySQL-formatted date string (YYYY-MM-DD) of when this page should be publicly visible on the website. If omitted, the current date and time from the web server is used.

cvIsApproved

No

This is a Boolean that indicates if the initial page version should be approved. Defaults to true if nothing is specified. When pages are approved, they are made immediately visible to all users that have permission to access that page on the website. Any subsequent edits to a page will require the new versions of the page to be approved before users can see the changes.

See also

  • The Updating an existing page recipe

  • The Getting a page type by its ID recipe

  • The Getting a page type by its handle recipe

 

Updating an existing page


Updating pages is similar to creating them in that you must first pass in an associative array containing all of the data that you wish to update on the page.

Getting ready

In this recipe, we will be modifying a page with the path of /about. We created that page in the previous recipe, but if it does not exist on your system, please adapt the code to your needs.

How to do it...

In this example, we will update the name of the About page. The steps are as follows:

  1. First, we need to load the Page object by its path.

    $page = Page::getByPath('/about');
  2. Create an associative array with the data that you wish to update.

    $data = array(
      'cName' => 'About Our Company'
    );
  3. Pass the data array into the $page object's update function.

    $page->update($data);
  4. Output a success message and exit the process.

    echo 'done!';
    exit;

How it works...

The update function updates the necessary tables in the database with the newly specified information. concrete5 will also rescan all permissions for this page and all of the related page paths. When the function is complete, the on_page_update event is fired, which you can write custom code to listen to and perform custom actions when a page is updated. Listening to system events is covered in a later chapter.

There's more...

Just like creating a page, you will need to pass an associative array to the update() function in order to update an existing page. You can use all of the fields specified in the previous recipe for adding a page, in addition to these other optional fields.

Attribute

Description

ctID

This is the numerical ID of a page type to change the page to. Supply this field to change the page type of a given page.

cCacheFullPageContent

A Boolean that specifies if the page should support full page caching (some block types do not support full page caching, so only use this when the blocks on that page offer full caching support).

cCacheFullPageContentOverrideLifetime

A string to tell concrete5 how the cache lifetime should perform. Possible values are default, custom, or forever.

cCacheFullPageContentLifetimeCustom

A setting in minutes as to how long the cache should last when the override mode is set to custom.

See also

  • The Creating a page type recipe

 

Setting page attributes


Pages, like most objects in concrete5, can have any type of custom attribute attached to them. This allows for immense flexibility, but it can be difficult to read and write these attributes using raw SQL. The concrete5 API makes setting and reading page attributes easy.

Getting ready

You will need to know at least the handle of the attribute key that you wish to assign to the page. A common attribute to set is the Meta Title attribute, which updates the text that appears in the HTML <title> tag.

How to do it...

We will set the Meta Title attribute to the About Us page in this example. The steps are as follows:

  1. Open /config/site_post.php in your preferred code editor.

  2. Load the Page object that you wish to set the attribute on.

    $page = Page::getByPath('/about');
  3. Call the setAttribute function on the $page object, passing in two parameters: the attribute handle (key), and the value.

    $page->setAttribute('meta_title', 'New Page Meta Title');
  4. Output a success message and exit the process.

    echo 'done!';
    exit;

How it works...

The setAttribute function is a member of the Collection class, which the Page class extends. It requires that you provide two parameters, an attribute key (which can either be a string representing the attribute key handle (which we provided here), or an actual AttributeKey object), and the value.

There's more...

The setAttribute function is very handy for setting the data of any kind of page attribute. One can update a page's meta information (such as description, keywords, and title) and also give the page various options, such as, excluding it from the navigation (as seen previously) or from the sitemap.xml file that search engines look for.

You can update any attribute that has been installed in the concrete5 system. To see all available page attributes, or to create new ones, visit the Page Attributes area of your site's dashboard (located at /dashboard/pages/attributes/).

See also

  • The Getting a page by its path recipe

  • The Getting a page attribute recipe

 

Getting a page attribute


In addition to being able to set page attributes, developers can also retrieve attributes just as easily. In this exercise, we will get the Meta Title attribute for the About page.

Getting ready

We are assuming the presence of a page with the path of /about in this recipe. If that page does not exist, you can create it, or adapt the code in this recipe to fit your circumstances.

How to do it...

The steps for getting a page attribute are as follows:

  1. Open /config/site_post.php in your preferred editor. This is a good place to run some arbitrary code.

  2. Load the Page object.

    $page = Page::getByPath('/about');
  3. Get the meta_title attribute.

    $title = $page->getAttribute('meta_title');
  4. Dump the variable using the custom debugging function that we created in the chapter's introduction.

    my_debug($title);

How it works...

concrete5 uses the attribute handle string to find the appropriate record in the database and return its value. concrete5 stores attributes in the EAV format (entity, attribute, value), and this makes it difficult to read these values directly with SQL queries. The concrete5 API simplifies this for developers.

See also

  • The Getting a page by its path recipe

  • The Setting a page attribute recipe

 

Getting a page's ID


Developers will often need to know a page's ID, especially when relating pages to other database objects (such as a blog post or calendar event). In this example, we will load the /about page that we've been working with and get its ID.

Getting ready

Please make sure the /about page exists in your instance of concrete5. Feel free to modify the code in this recipe if that page does not exist.

How to do it...

The steps for getting a page's ID are as follows:

  1. Open /config/site_post.php in your code editor.

  2. Load the Page object by its path.

    $page = Page::getByPath('/about');
  3. Get the page's ID.

    $id = $page->getCollectionId();
  4. Dump the contents of the $id variable to see what the ID is.

    my_debug($id);

See also

  • The Getting a page by its path recipe

 

Getting a page's path


In addition to being able to get a page's ID, developers can also retrieve the path for a page. In this recipe, we will load a page by its ID and then retrieve its path.

How to do it...

The steps for getting a page's path are as follows:

  1. Open /config/site_post.php in your preferred code editor.

  2. Load the page by its ID. We will use the ID of 4 here, which should belong to a page on the dashboard.

    $page = Page::getByID(4);
  3. Get the page's path.

    $path = $page->getCollectionPath();
  4. Use the custom debugging function to output the path.

    my_debug($path);

See also

  • The Getting a page by its ID recipe

 

Getting a page's handle


Pages, like page types and other objects in concrete5, have handles in addition to paths. The handle is similar to a slug in other content management systems. In this exercise, we will load a page by its ID and then retrieve its handle.

How to do it...

The steps for getting a page's handle are as follows:

  1. Open /config/site_post.php in your code editor.

  2. Load the page by its ID.

    $page = Page::getByID(4);
  3. Get the page's handle.

    $handle = $page->getCollectionHandle();
  4. Dump the handle variable to see its contents.

    my_debug($handle);

See also

  • The Getting a page by its ID recipe

 

Getting a page's name


Page names are often used as the de facto titles in concrete5. In this exercise, we will load a page by its path, and then get its name.

How to do it...

The steps for getting a page's name are as follows:

  1. Open /config/site_post.php in your editor.

  2. Load the page by its path.

    $page = Page::getByPath('/about');
  3. Get the page's title.

    $name = $page->getCollectionName();
  4. Dump the contents of the title variable.

    my_debug($name);

See also

  • The Getting a page by its path recipe

 

Getting a page's description


Page descriptions are not used very widely used in concrete5. Some themes will treat them as content excerpts, while other add-ons will use descriptions as a generic attribute storage area. Regardless, they are still built into concrete5, and in this recipe we will load a page by its path and retrieve its description.

Getting ready

Many pages in concrete5 do not have descriptions. If you wish, you can edit a page to add a description as shown in the following screenshot:

How to do it...

The steps for getting a page's description are as follows:

  1. Open the /config/site_post.php file in your code editor.

  2. Load the page by its path.

    $page = Page::getByPath('/about');
  3. Get the page's description.

    $description = $page->getCollectionDescription();
  4. Dump the contents of the description variable.

    my_debug($description);

See also

  • The Getting a page by its path recipe

 

Getting a page's page type ID


As we discussed earlier in the chapter, pages are assigned a page type. In this recipe, we will get the page type ID from a Page object.

How to do it...

The steps for getting a page's page type ID are as follows:

  1. Open /config/site_post.php in your code editor, so we can run some arbitrary code.

  2. Load the page by its path.

    $page = Page::getByPath('/about');
  3. Get the page type ID for this page.

    $pageTypeId = $page->getCollectionTypeID();
  4. Dump the page type ID using our custom debugging function.

    my_debug($pageTypeId);

See also

  • The Getting a page by its path recipe

 

Getting a page's page type handle


In addition to being able to retrieve the ID of a page's page type, developers can also get the handle.

How to do it...

The steps for getting a page's page type handle are as follows:

  1. Open /config/site_post.php in your code editor, since we will just be running some arbitrary code.

  2. Load the page by its path.

    $page = Page::getByPath('/about');
  3. Get the page type handle.

    $handle = $page->getCollectionTypeHandle();
  4. Dump the handle variable to see its contents.

    my_debug($handle);

See also

  • The Getting a page by its path recipe

 

Getting a page's theme object


Every page can have its own individual theme in concrete5. While it's typical for most sites to only use one global theme, concrete5 does allow developers to set individual themes for each page. In this recipe, we will get the page's theme object, which can be used to see what theme is active on a given page.

How to do it...

The steps for getting a page's theme object are as follows:

  1. Open /config/site_post.php in your preferred code editor.

  2. Load the page by its path.

    $page = Page::getByPath('/about');
  3. Get the theme object.

    $theme = $page->getCollectionThemeObject();
  4. Dump the theme object to inspect the class.

    my_debug($theme);

See also

  • The Getting a page by its path recipe

 

Getting the children below a page


If you need to access the children of a page, you can have concrete5 return an array of numerical IDs. These IDs can then be used to load each of the Page objects individually.

How to do it...

The steps for getting the children below a page are as follows:

  1. Open /config/site_post.php in your preferred code editor.

  2. Load the parent page by its ID.

    $page = Page::getByID(1);
  3. Get the array of child IDs.

    $children = $page->getCollectionChildrenArray();
  4. Loop through the child ID array and output the name of each page.

    foreach ($children as $childId) {
      $child = Page::getByID($childId);
      echo $child->getCollectionName().'<br />';
    }
  5. Exit the process.

    exit;

How it works...

concrete5 will return an array of numeric IDs for each of the pages beneath the parent page. In this example, we loaded the home page, so the result should be a list of every page on the website. This function ignores permissions, and can be taxing on the database if there are a lot of pages to load. It is a better idea to use the PageList class to loop through pages, and that class is described later on in this chapter.

 

Moving a page


The concrete5 sitemap is a great tool for managing the page hierarchy of your website. It lets you arrange the order of pages, and even drag-and-drop pages to different areas of the site. Thankfully, you aren't limited to using the graphical interface to move pages around the site. You can also rearrange pages dynamically in your custom concrete5 applications.

Getting ready

In this example, we are going to move a Careers page underneath the About Us page. Before we can move a page, we need to have the Page object of the new parent page that we are moving the current page to.

This exercise assumes that pages exist at both /about and /careers in your concrete5 site. You can create those pages through the concrete5 interface, or adapt the code in this recipe to work with pages that exist on your own site.

How to do it...

The steps for moving a page are as follows:

  1. Open /config/site_post.php, as that is a safe place to play with some random code.

  2. First, load the About Us page, which is where the Careers page will be moved to.

    $newParent = Page::getByPath('/about');
  3. Now, we need to load the careers page that we are moving.

    $careersPage = Page::getByPath('/careers');
  4. Finally, call the move function on the careers page, passing it the new parent page and an optional Boolean which tells concrete5 if we want to save the old page path as well as the new one.

    $careersPage->move($newParent, true);

How it works...

The move function is very easy to use. You only need to provide one parameter, which is a Page object of the new parent that you are moving the page under. There is an optional second parameter to indicate if you wish to retain the old page path in addition to the current one. That parameter defaults to false.

Once the page is moved, it will inherit the permissions of the new parent page (if the page does not have its own permissions set explicitly).

Once the page is moved, the event on_page_move is fired.

See also

  • Listening to system events in Chapter 9, System Events and Advanced Configuration

  • The Getting a Page object by its path recipe

 

Deleting a page (and its children)


concrete5 also makes it easy to delete pages from the sitemap.

Getting ready

Deleting pages is a permanent destructive action. When experimenting with this code, it would be a good idea to create a dummy page with a path of /delete-me.

How to do it...

We will permanently delete the about us page and all of its child pages. The steps are as follows:

  1. First, load the page that you wish to delete. We will delete a dummy page.

    $page = Page::getByPath('/delete-me');
  2. Call the delete() function on the Page object.

    $page->delete();

How it works...

concrete5 will fire the on_page_delete event before any actual deleting occurs. After the event fires, the page (and all of its children) are deleted from the database. This operation is permanent, so it is important to make sure that you only delete pages when you are certain that they are no longer needed.

There's more...

If you don't want to permanently delete a page, you can move it to the Trash. As of concrete5 version 5.5, pages can be "temporarily" deleted and moved under a special internal page called the Trash.

$page->moveToTrash();

See also

  • The Getting a page by its path recipe

 

Getting a list of pages


Many applications will have a need to get a list of pages and perform various filter and sorting functions on the list. For this, there is the PageList class, which exposes many convenient helper functions to assist in working with large lists of pages.

Getting ready

In this example, we are going to find all of the pages under the /blog page. This is a common use of the page list model. The PageList class is not automatically loaded by concrete5, so we will need to use the Loader class to have it available to us.

If your site does not have a page located at /blog, it would be helpful to create that page, as well as a few child pages below it. Otherwise, feel free to adapt the code in this recipe to suit your needs.

How to do it...

In this recipe, we will get a list of 20 pages that exist under /blog in the sitemap. The steps are as follows:

  1. First, we must make the PageList class available for us to use.

    Loader::model('page_list');
  2. Create a new instance of the PageList class. We will assign it to a variable called $list.

    $list = new PageList();
  3. Filter the list to only include pages underneath the /blog page.

    $list->filterByPath('/blog');
  4. Limit the list of pages to only include the first 20 results.

    $list->setItemsPerPage(20);
  5. Run the database query and get the first "page" of results, which will return an array of 20 Page objects.

    $pages = $list->getPage();
  6. Dump the contents of the pages variable to see the array.

    foreach ($pages as $page) {
      echo $page->getCollectionTitle().'<br />';
    }
    exit;

How it works...

The PageList class extends the core DatabaseItemList class, which has a number of useful functions itself. The get() function accepts two parameters, the number of records to retrieve, and the offset.

There's more...

The page list class implements "magic methods," which allow allow us to filter the list by any page attribute. We simply need to create a function name based off of the camel cased version of the attribute handle, preceded by "filterBy". So to filter all pages that have the exclude_nav attribute, we would write the following function:

$list->filterByExcludeNav(true);

Alternatively, if you want to just get an array of the first 99 Page objects and ignore pagination, use the get() function.

$pages = $list->get(99);

Since version 5.5, concrete5 uses Twitter's open source Bootstrap CSS framework for many of their internal styles. You can get the pagination controls in nicely formatted HTML (with relevant Bootstrap CSS classes) by printing/echoing the results of the following function (preferably you'd use this function in a view or template file of a block or single page):

echo $list->displayPagingV2();

The DatabaseItemList class and PageList class have several functions that make working with a collection of pages easier. You can filter by keywords, by collection type, parent page, and by any attribute using magic methods. We will cover the DatabaseItemList class further in Chapter 5, Working with Databases and Models.

 

Adding a page selector field to a form


It is easy to add a page selector field to a form. When clicked on, the sitemap will appear in a modal window, allowing for easy browsing and selecting of a page. This allows for user friendly custom applications that can allow users to attach pages to any type of custom object, like a blog post or cooking recipe, for example.

Getting ready

We will need to use the FormPageSelectorHelper class, which we will need to load using the Loader library.

This recipe will need to be written inside of an HTML form somewhere in your site. We have created a basic single page for this purpose, which can be downloaded with the code from the website for this book. To install the single page, copy the code for this recipe to your concrete5 site directory and visit /dashboard/pages/single. Add a new single page with a path of /example.

How to do it...

concrete5 includes a helper to generate the necessary JavaScript and HTML text needed to show the sitemap selector widget. We will use the Loader class to include and return the PageSelectorHelper class, which will then return the entire HTML that we need. The steps are as follows:

  1. Make the pageSelector helper class available for us to use. The Loader class will automatically instantiate and return the instantiated helper object when the helper gets loaded.

    $pageSelector = Loader::helper('form/page_selector');
  2. Output the HTML and JavaScript required allowing users to select a page.

    echo $pageSelector->selectPage('page_id');

How it works...

The selectPage function returns the HTML and JavaScript necessary to produce a page selector field. There is only one parameter required, and that is a string indicating the name of the field. concrete5 will add a hidden <input> element to the form, which will allow the selected page ID to be read from a POST request.

In this example, once the form is submitted, you could retrieve the selected page ID by looking in the $_POST super variable.

$pageId = $_POST['page_id'];

There's more...

You can specify a page ID in the optional second parameter, which will populate the page selector with an existing page.

$page = Page::getByCollectionPath('/about-us');
echo $pageSelector->selectPage('page_id', $page->getCollectionID());

The pageSelector helper also has a function to display a sitemap in a modal window.

$args = array(
'display_mode' => 'full'
);
$pageSelector->sitemap($args);

Note that the sitemap() function loads an element, which is automatically printed to the screen, so there is no need to echo or print the result.

About the Author

  • David Strack

    David Strack has been a software engineer for over 10 years. With a strong background in HTML, PHP, and JavaScript, he has developed websites for dozens of companies, large and small. David currently works for a small startup in California creating energy analytics software. He lives in Milwaukee, Wisconsin, with his wife, Sarah, and their crazy dog, Brewski. David can usually be found hacking away with JavaScript, designing mobile apps, watching pro football, and drinking craft beer.

    Browse publications by this author

Latest Reviews

(1 reviews total)
The book is for an older version of Concrete5. there's nothing available for the latest version of C5
Book Title
Access this book and the full library for just $5/m.
Access now