Exercise 2. Task Scheduling and Dashboard Integration

In this exercise, you will create a simple RSS reader which displays the last feed item from the Plesk feed on the administrator's dashboard. While writing the extension, you will learn how to do the following:

  • Write installation and removal scripts.
  • Use the key-value storage.
  • Add scheduled tasks.
  • Create promotional blocks on the administrator's dashboard.

We assume that the extension ID is plesk-news, and that you start with the code inside the ex2 directory. This code is partly written by us to help you focus only on certain areas. Additionally, we have populated the directory with media content necessary for the exercise. To see the completed exercise, examine the ex2complete directory.

Step 1. Populate the storage with the last feed item.

The extension we are going to write will not have its own GUI. Instead, all its functions will be available from the promo block on the administrator's Home page. That is why we do not need to get the control flow as we did in Exercise 1, step 1. However, we need to populate the extension's storage with the last feed item. For this, we should write a script that fetches the item and saves it directly after the installation of our extension.

The extensions SDK provides the ability to run PHP scripts in this and some other situations. The following table summarizes which extension files are called in particular conditions.

File Condition

/plib/scripts/pre-install.php

Before installing an extension

/plib/scripts/post-install.php

After installing an extension

/plib/scripts/pre-uninstall.php

Before an extension removal

So the system scans each extension for these scripts and runs the scripts as needed.

In our exercise, we are interested in fetching the feed item after the installation, so you should change /plib/scripts/post-install.php by adding the following lines to the file:

pm_Context::init('plesk-news');

Modules_PanelNews_News::load();

The first line loads the extension's context. We will use it next to interact with the key-value storage. The next line calls the method which fetches the feed item. We are going to use this method more than in one place, so we isolated it into a separate class.

 

As you might have noticed that we didn't require Modules_PanelNews_News in post-install.php. This happened because it was loaded automatically. For auto-loading we rely on the Zend approach. Read more about it in http://framework.zend.com/manual/1.11/en/learning.autoloading.design.html.

Applied to our class, the system performs the following sequence of operations:

  1. The Modules_ prefix tells the system that a class should be inside an extension.
  2. The PanelNews_ part is transformed to the extension ID by adding dashes before capitals and moving capitals to the lower case. After the transformation, the resulting ID is plesk-news.
  3. Finally, News part tells the system to seek the class definition in News.php inside the /plib/library directory of our extension.

Knowing this strategy, you can write your own classes, put them in the /plib/library directory, and later use them in your code without requiring them first.

Returning to the load method implementation, open the /plib/library/News.php and change load to the following:

    public static function load()
    {
        $xml = simplexml_load_file('http://urn.swp.webapp.parallels.com/rss/?p=PLESK');

        $lastItem = $xml->channel->item;

        pm_Settings::set('news_text', (string) $lastItem->title);
        pm_Settings::set('news_link', (string) $lastItem->link);
    }

The code demonstrates how the feed item is saved to the storage using pm_Settings::set by assigning the news_text and news_link variables. Now you can get the variable values at any time with pm_Settings::get if the extension's context is initialized.

Step 2. Display the feed item in the promo block.

To create a promotional block in Plesk, add the following lines to /plib/library/Promo/Home.php:

class Modules_PanelNews_Promo_Home extends pm_Promo_Home
{

    public function getTitle()
    {
        return 'Plesk News';
    }

    public function getText()
    {
        pm_Context::init($this->_moduleId);
        return pm_Settings::get('news_text');
    }

    public function getButtonText()
    {
        return 'View Article';
    }

    public function getButtonUrl()
    {
        return pm_Settings::get('news_link');
    }

    public function getIconUrl()
    {
        pm_Context::init('plesk-news');
        return pm_Context::getBaseUrl() . '/images/feed.png';
    }

} 

As you can see, this class describes a promo block. It is not called from anywhere inside the extension itself. In fact, the system loads all classes which extend pm_Promo_Home automatically when the Plesk administrator loads the Home page. To be loaded, the class name should adhere to the naming convention we discussed at step 1. If you package the extension and add it to Plesk, you will see the following new block on the dashboard.

When the administrator clicks the link, they will be forwarded to the news_link variable from the key-value storage. We do two init calls in the Modules_PanelNews_Promo_Home code to be sure that the storage is initialized before it is used.

Step 3. Schedule the periodic update of the last feed item

The variable news_link is assigned only once, particularly, when the extension is installed. We need to update its value periodically to follow the Plesk feed. For this, we will run a scheduled script, but first let's create the script itself.

Note: It is mandatory to keep scheduled scripts under /plib/scripts.

Assume our script name periodic-task.php, so its path within the extension will be /plib/scripts/periodic-task.php. Open the file and add the following code to it:

pm_Context::init('plesk-news');

Modules_PanelNews_News::load();

 

Looks familiar? Yes, we used the same code in post-install.php. Now it's time to schedule the script run. The best place for this is the post-installation script to ensure that the task is safely scheduled just right after the installation of our extension. Open /plib/scripts/post-install.php and refine it to look as follows:

<?php

pm_Context::init('plesk-news');

$task = new pm_Scheduler_Task();
$task->setSchedule(pm_Scheduler::$EVERY_DAY);
$task->setCmd('periodic-task.php');

pm_Scheduler::getInstance()->putTask($task);
pm_Settings::set('periodic_task_id', $task->getId());

Modules_PanelNews_News::load();

 

The code demonstrates that to schedule a script run (so-called task), we need to create an instance of pm_Scheduler_Task, set its period by setSchedule, define a target script by setCmd. Finally, add the task the schedule interface by putTask.

We also need to securely remove the task when removing the extension, so we save the task ID to the periodic_task_id variable. For the same reason, you should add the following lines to /plib/scripts/post-uninstall.php:

pm_Context::init('plesk-news');

$taskId = pm_Settings::get('periodic_task_id');
$task = pm_Scheduler::getInstance()->getTaskById($taskId);
pm_Scheduler::getInstance()->removeTask($task);

This code will remove the task from the schedule interface.

Step 4. Install and test the extension.

Congratulations! You have completed the exercise. To install your extension to Plesk:

  1. Add the contents of the ex2 directory (not the directory itself) to a ZIP archive using your favorite software.

    Important: Ensure that meta.xml resides in the root of the unpacked archive. This is a very important requirement, otherwise Plesk will return an error on adding your extension to Plesk.

  2. Log in to Plesk as the administrator and add the extension on the Server Management > Extensions page.

You should see your extension in the list. It is dimmed because it does not have its own GUI, but you can see it on the Home page.