Working with Dashboard Single Pages

I've built a couple of Add-Ons that have dashboard single pages. I really don't want to have multiple sections for each Add-On, so I have come up with this solution:

In the install() and upgrade() methods of the package controller:

Then the installDashboard() method in the package controller I add the single pages. Note that the package for the single page '/dashboard/sollos' is set to 'NULL'. I update the cFilename for these pages in the 'Pages' table and copy them from the package to the 'single_pages' directory at the root level.
function installDashboard($pkg) {
   $db = Loader::db();
   $dashPages = array(
      array('pkg'=>null,'path'=>'/dashboard/sollos','name'=>'Sollos Web Development','description'=>'Make your site a better place.')
   foreach ($dashPages as $dashPage) {
      $dp = Page::getByPath($dashPage['path']);
      if($dp->cID==0) {
         $sp = SinglePage::add($dashPage['path'],$dashPage['pkg']);
         $sp->update(array('cName'=>t($dashPage['name']), 'cDescription'=>t($dashPage['description'])));
         $db->query("UPDATE Pages SET cFilename=? WHERE cID = ?", array($dashPage['path'].'.php',$sp->cID));

Then in the uninstall() method of the controller I go through all the single pages installed on the site and search for pages that start with 'dashboard/sollos'. If only one exists, then it is the base single page and we remove it from the site.
function uninstall() {
   $ssps = array();
   $sps = SinglePage::getList();
   foreach ($sps as $sp) {
      if (strpos($sp->cPath,'/dashboard/sollos')!==false) {
         $ssps[] = $sp;
   if (count($ssps)<2) {
      foreach($ssps as $ssp) {
         if (is_file(DIR_FILES_CONTENT.'/dashboard/sollos.php')) {

This seems to work in my development environment, but I don't know how well it would work in the wild; if there is an upgrade to the main single page in one Add-On, it would be necessary to update it in all Add-Ons.

Has anyone ever done this, or something similar, before? Any suggestions on making this approach better?

View Replies:
jgarcia replied on at Permalink Reply
It's generally a better idea to create your single pages like this (this is within the install function of the package class):

$pkg = parent::install();
$mySinglePage = SinglePage::add('/dashboard/mysinglepage', $pkg);
$mySinglePage->update(array('cName' => 'My Single Page', 'cDescription' => 'My single page description'));

Essentially, it sounds like you would want to keep you top level dashboard page (/dashboard/sollos), so what you could do is just not pass the $pkg object when calling SinglePage::add on that one. What that will do is make it so that the page does not automatically uninstall when the package is removed. Then just do a check in your uninstall function to see if the package they are removing is the only one to be found under /dashboard/sollos, and if so just do

$sollosPage = Page::getByPath('/dashboard/sollos');
SkyBlueSofa replied on at Permalink Reply
Thanks for the response.

In my first attempt, I tried the approach you outlined, but then I noticed that when I navigated to 'dashboard/sollos', the page content was empty; the links to any sub-pages ('dashboard/sollos/add-on', etc) were available. But just having an empty page when you click the link in the left navigation is a bit disconcerting.

As I looked into the Pages table, the cFilename for this record was set to '0'. If I changed the cFilename to 'dashboard/sollos.php' C5 still could not find it, since it didn't know which package (if any) to find it in. On a whim, I added the 'single_pages/dashboard/sollos.php' file and the dashboard page started showing with the content I wanted.

I just wanted to give some of the reasoning behind the process that I've described.

Do you see any issues for this code breaking the site as new c5 releases are made?

On a similar note, I'm trying to find a way to add a new sub-page to an existing dashboard section, such as a new Page related dashboard sub-page under 'Pages and Themes'. Would the process be similar to what I've described here? Is there already a specified way to do this?
jgarcia replied on at Permalink Reply
You can add some code in the view function of the controller of dashboard/sollos to redirect to one of the subpages to prevent the blank page problem. Just do $this->redirect('/dashboard/sollos/subpagename').

The problem with doing it the way you are (direct DB interaction, rather than API calls) is that who knows...the core codebase may not change and you might be okay doing it that way...or it might and if so you could potentially have problems.

It might be okay, but I'm probably not to the person to make that call...the C5 core team are the only ones with the power to actually approve what might go into the marketplace.
SkyBlueSofa replied on at Permalink Reply
Yeah you nailed my concern: what if the core functionality changes?

The 'dashboard/sollos' page was just going to show some basic info, anyway. I think the redirect might be a good fix.

Thanks for the info and help.