Skip to content

Commit

Permalink
Post-installation Messages: A model method to insert post-installatio…
Browse files Browse the repository at this point in the history
…n messages
  • Loading branch information
Nicholas K. Dionysopoulos committed Aug 25, 2014
1 parent 424b8fe commit f666ff8
Showing 1 changed file with 263 additions and 5 deletions.
268 changes: 263 additions & 5 deletions administrator/components/com_postinstall/models/messages.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class PostinstallModelMessages extends FOFModel
/**
* Builds the SELECT query
*
* @param boolean $overrideLimits Are we requested to override the set limits?
* @param boolean $overrideLimits Are we requested to override the set limits?
*
* @return JDatabaseQuery
*
Expand All @@ -47,7 +47,7 @@ public function buildQuery($overrideLimits = false)
/**
* Returns the name of an extension, as registered in the #__extensions table
*
* @param integer $eid The extension ID
* @param integer $eid The extension ID
*
* @return string The extension name
*
Expand All @@ -61,7 +61,7 @@ public function getExtensionName($eid)
$query = $db->getQuery(true)
->select(array('name', 'element', 'client_id'))
->from($db->qn('#__extensions'))
->where($db->qn('extension_id') . ' = ' . $db->q((int) $eid));
->where($db->qn('extension_id') . ' = ' . $db->q((int)$eid));

$db->setQuery($query, 0, 1);

Expand Down Expand Up @@ -90,7 +90,7 @@ public function getExtensionName($eid)
/**
* Resets all messages for an extension
*
* @param integer $eid The extension ID whose messages we'll reset
* @param integer $eid The extension ID whose messages we'll reset
*
* @return mixed False if we fail, a db cursor otherwise
*
Expand All @@ -117,7 +117,7 @@ public function resetMessages($eid)
* Do note that this a core method of the RAD Layer which operates directly
* on the list it's being fed. A little touch of modern magic.
*
* @param array $resultArray A list of items to process
* @param array $resultArray A list of items to process
*
* @return void
*
Expand Down Expand Up @@ -206,4 +206,262 @@ public function getComponentOptions()

return $options;
}

/**
* Adds or updates a post-installation message (PIM) definition. You can use this in your post-installation script
* using this code:
*
* require_once JPATH_LIBRARIES . '/fof/include.php';
* FOFModel::getTmpInstance('Messages', 'PostinstallModel')->addPostInstallationMessage($options);
*
* The $options array contains the following mandatory keys:
*
* extension_id The numeric ID of the extension this message is for (see the #__extensions table)
*
* type One of message, link or action. Their meaning is:
* message Informative message. The user can dismiss it.
* link The action button links to a URL. The URL is defined in the action parameter.
* action A PHP action takes place when the action button is clicked. You need to specify the
* action_file (RAD path to the PHP file) and action (PHP function name) keys. See
* below for more information.
*
* title_key The JText language key for the title of this PIM
* Example: COM_FOOBAR_POSTINSTALL_MESSAGEONE_TITLE
*
* description_key The JText language key for the main body (description) of this PIM
* Example: COM_FOOBAR_POSTINSTALL_MESSAGEONE_DESCRIPTION
*
* action_key The JText language key for the action button. Ignored and not required when type=message
* Example: COM_FOOBAR_POSTINSTALL_MESSAGEONE_ACTION
*
* language_extension The extension name which holds the language keys used above. For example, com_foobar,
* mod_something, plg_system_whatever, tpl_mytemplate
*
* language_client_id Should we load the front-end (0) or back-end (1) language keys?
*
* version_introduced Which was the version of your extension where this message appeared for the first time?
* Example: 3.2.1
*
* enabled Must be 1 for this message to be enabled. If you omit it, it defaults to 1.
*
* condition_file The RAD path to a PHP file containing a PHP function which determines whether this message
* should be shown to the user. @see FOFTemplateUtils::parsePath() for RAD path format. Joomla!
* will include this file before calling the condition_method.
* Example: admin://components/com_foobar/helpers/postinstall.php
*
* condition_method The name of a PHP function which will be used to determine whether to show this message to
* the user. This must be a simple PHP user function (not a class method, static method etc)
* which returns true to show the message and false to hide it. This function is defined in the
* condition_file.
* Example: com_foobar_postinstall_messageone_condition
*
* When type=message no additional keys are required.
*
* When type=link the following additional keys are required:
*
* action The URL which will open when the user clicks on the PIM's action button
* Example: index.php?option=com_foobar&view=tools&task=installSampleData
*
* Then type=action the following additional keys are required:
*
* action_file The RAD path to a PHP file containing a PHP function which performs the action of this PIM.
* @see FOFTemplateUtils::parsePath() for RAD path format. Joomla! will include this file
* before calling the function defined in the action key below.
* Example: admin://components/com_foobar/helpers/postinstall.php
*
* action The name of a PHP function which will be used to run the action of this PIM. This must be a
* simple PHP user function (not a class method, static method etc) which returns no result.
* Example: com_foobar_postinstall_messageone_action
*
* @param array $options See description
*
* @return $this for chaining
*
* @throws Exception
*/
public function addPostInstallationMessage(array $options)
{
// Make sure there are options set
if (!is_array($options))
{
throw new Exception('Post-installation message definitions must be of type array', 500);
}

// Initialise array keys
$defaultOptions = array(
'extension_id' => '',
'type' => '',
'title_key' => '',
'description_key' => '',
'action_key' => '',
'language_extension' => '',
'language_client_id' => '',
'action_file' => '',
'action' => '',
'condition_file' => '',
'condition_method' => '',
'version_introduced' => '',
'enabled' => '1',
);

$options = array_merge($defaultOptions, $options);

// Array normalisation. Removes array keys not belonging to a definition.
$defaultKeys = array_keys($defaultOptions);
$allKeys = array_keys($options);
$extraKeys = array_diff($allKeys, $defaultKeys);

if (!empty($extraKeys))
{
foreach ($extraKeys as $key)
{
unset($options[$key]);
}
}

// Normalisation of integer values
$options['extension_id'] = (int)$options['extension_id'];
$options['language_client_id'] = (int)$options['language_client_id'];
$options['enabled'] = (int)$options['enabled'];

// Normalisation of 0/1 values
foreach (array('language_client_id', 'enabled') as $key)
{
$options[$key] = $options[$key] ? 1 : 0;
}

// Make sure there's an extension_id
if (!(int)$options['extension_id'])
{
throw new Exception('Post-installation message definitions need an extension_id', 500);
}

// Make sure there's a valid type
if (!in_array($options['type'], array('message', 'link', 'action')))
{
throw new Exception('Post-installation message definitions need to declare a type of message, link or action', 500);
}

// Make sure there's a title key
if (empty($options['title_key']))
{
throw new Exception('Post-installation message definitions need a title key', 500);
}

// Make sure there's a description key
if (empty($options['description_key']))
{
throw new Exception('Post-installation message definitions need a description key', 500);
}

// If the type is anything other than message you need an action key
if (($options['type'] != 'message') && empty($options['action_key']))
{
throw new Exception('Post-installation message definitions need an action key when they are of type "' . $options['type'] . '"', 500);
}

// You must specify the language extension
if (empty($options['language_extension']))
{
throw new Exception('Post-installation message definitions need to specify which extension contains their language keys', 500);
}

// The action file and method are only required for the "action" type
if ($options['type'] == 'action')
{
if (empty($options['action_file']))
{
throw new Exception('Post-installation message definitions need an action file when they are of type "action"', 500);
}

$file_path = FOFTemplateUtils::parsePath($options['action_file'], true);

if (!@is_file($file_path))
{
throw new Exception('The action file ' . $options['action_file'] . ' of your post-installation message definition does not exist', 500);
}

if (empty($options['action']))
{
throw new Exception('Post-installation message definitions need an action (function name) when they are of type "action"', 500);
}
}

if ($options['type'] == 'link')
{
if (empty($options['link']))
{
throw new Exception('Post-installation message definitions need an action (URL) when they are of type "link"', 500);
}
}

// The condition file and method are only required when the type is not "message"
if ($options['type'] != 'message')
{
if (empty($options['condition_file']))
{
throw new Exception('Post-installation message definitions need a condition file when they are of type "' . $options['type'] . '"', 500);
}

$file_path = FOFTemplateUtils::parsePath($options['condition_file'], true);

if (!@is_file($file_path))
{
throw new Exception('The condition file ' . $options['condition_file'] . ' of your post-installation message definition does not exist', 500);
}

if (empty($options['condition_method']))
{
throw new Exception('Post-installation message definitions need a condition method (function name) when they are of type "' . $options['type'] . '"', 500);
}
}

//Check if the definition exists
$table = $this->getTable();
$tableName = $table->getTableName();

$db = $this->getDbo();
$query = $db->getQuery(true)
->select('*')
->from($db->qn($tableName))
->where($db->q('extension_id') . ' = ' . $db->q($options['extension_id']))
->where($db->q('type') . ' = ' . $db->q($options['type']))
->where($db->q('title_key') . ' = ' . $db->q($options['title_key']));
$existingRow = $db->setQuery($query)->loadAssoc();

// Is the existing definition the same as the one we're trying to save?
if (!empty($existingRow))
{
$same = true;

foreach ($options as $k => $v)
{
if ($existingRow[$k] == $v)
{
$same = false;
break;
}
}

// Trying to add the same row as the existing one; quit
if ($same)
{
return $this;
}

// Otherwise it's not the same row. Remove the old row before insert a new one.
$query = $db->getQuery(true)
->delete($db->qn($tableName))
->where($db->q('extension_id') . ' = ' . $db->q($options['extension_id']))
->where($db->q('type') . ' = ' . $db->q($options['type']))
->where($db->q('title_key') . ' = ' . $db->q($options['title_key']));
$db->setQuery($query)->execute();
}

// Insert the new row
$options = (object)$options;
$db->insertObject($tableName, $options);

return $this;
}
}

0 comments on commit f666ff8

Please sign in to comment.