- <?php
- /*
- * Lokorin.com
- * Copyright 2004-2006
- * Licensed under the GNU LGPL. See COPYING for full terms.
- */
- /**
- * A library containing admin panel functionality. The library can create
- * simplified and customized panels which can be used to alter database
- * tables. The library is integrated with the administration log and update
- * libraries.
- * @author Andreas Launila
- * @version $Revision: 1.17 $
- * @package com.lokorin.lokorin.lib
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
- /**
- * For access to common constants and functions.
- */
- require_once('common.php');
- doInclude('admin_auth');
- doInclude('lib_forms');
- doInclude('lib_tables');
- doInclude('lib_displayer');
- CssHandler::getInstance()->includeCss('admin_panel');
-
- /**
- * Adds an entry to the admin log, storing the action for later examination.
- * @param string $table The name of the table that the action affects.
- * @param string $module The name of the module that performed the action, or
- * alternativly a description of the action.
- * @param string $comment An optional comment to add additional information to
- * the log message.
- * @access private
- */
- function logAdminAction($table, $module, $comment = '') {
- global $db;
-
- $vars = array(
- 'table' => $table,
- 'admin_module' => $module,
- 'url' => SELF,
- 'comment' => $comment,
- 'user' => $_SESSION['user'],
- 'timestamp' => time(),
- 'ip' => $_SERVER['REMOTE_ADDR']);
- $db->queryInsert(TABLE_ADMIN_LOGS, $vars);
- }
-
- /**
- * This function is notified whenever a module performs a table altering
- * action. Everything that should be notified of admin activity should
- * hook in here.
- * @param string $table The name of the table that the action affects.
- * @param string $module The name of the module class that performed the
- * action, or alternativly a description of the action.
- * @param string $sqlSelectThe sql selector (if there is any) that specifies
- * the row that was altered.
- * @access private
- */
- function logAdminActivity($table, $module, $sqlSelector = '') {
- $module = strtolower($module); //To avoid errors between PHP 4.3 and 5 .
- logAdminAction($table, $module, $sqlSelector);
-
- //Make sure the redirects and aliases reflect the change.
- doInclude('lib_redirects');
- buildUrlRedirects();
- buildUrlAliases();
-
- //Notify the sitemaps of the table changes.
- doInclude('lib_sitemap');
- notifyTableChanged($table);
-
- //Delete all directory cached contents to force it to be regenerated.
- doInclude('lib_cache');
- deleteAllCachedContents();
- }
-
- /*
- * Common callbacks start.
- */
- /**
- * Formats a timestamp to the number of elapsed days since the point in time
- * which the timestamp represents. This includes special cases like 'Never',
- * 'Today' and 'Yesterday'.
- * @param integer $timestamp The unix timestamp to be converted.
- * @return string A string indicating the number of elapsed days.
- * @access public
- */
- function formatTimestampDays($timestamp) {
- if($timestamp == 0) {
- return 'Never';
- } else {
- $days = round((time() - $timestamp) / (3600*24));
- if($days == 0) {
- return 'Today';
- } else if($days == 1) {
- return 'Yesterday';
- } else {
- return $days.' days ago';
- }
- }
- }
-
- /**
- * Formats a timestamp into a date representation. As a special case timestamp
- * equal to 0 get the representation 'Never'.
- * @param integer $timestamp The unix timestamp to be converted.
- * @return string A date representation.
- * @access public
- */
- function formatTimestampDate($timestamp) {
- if($timestamp == 0) {
- return 'Never';
- } else {
- return date(DATE_SHORTER, $timestamp);
- }
- }
-
- /**
- * Formats a timestamp into a date representation complete with hours and
- * minutes. As a special case timestamp equal to 0 get the representation
- * 'Never'.
- * @param integer $timestamp The unix timestamp to be converted.
- * @return string A date/time representation.
- * @access public
- */
- function formatTimestampTime($timestamp) {
- if($timestamp == 0) {
- return 'Never';
- } else {
- return date(DATE_TIME, $timestamp);
- }
- }
-
- /**
- * Converts a boolean value to either 'Yes' or 'No'. 'Yes' is used if the
- * value is a boolean true, 'No' is used in all other cases.
- * @param boolean $boolVal The boolean value that should be converted.
- * @return string 'Yes' or 'No'.
- * @access public
- */
- function convertBoolToYn($boolVal) {
- if($boolVal == 1) {
- return 'Yes';
- } else {
- return 'No';
- }
- }
- /*
- * Common callbacks end.
- */
-
-
- /**
- * Describes an module with admin functionality. The module defines actions
- * that it's able perform and performs the action when needed. This class
- * should be concidered abstract.
- * @author Andreas Launila
- * @package com.lokorin.lokorin.lib
- */
- abstract class AdminModule {
- /**
- * Contains all actions that the module handles. The key is the
- * action identifier and the value is the corresponding AdminAction
- * instance.
- * @var array
- */
- private $actions;
-
- /**
- * Constructor for AdminModule.
- * @param array $definedActions An array containing AdminAction describing
- * all actions handled by the module.
- */
- public function __construct($definedActions) {
- if(!is_array($definedActions)) {
- $definedActions = array();
- }
- //Build the actions array so that the correct keys are given.
- $actions = array();
- foreach($definedActions as $action) {
- $actions[$action->getAction()] = $action;
- }
- $this->actions = $actions;
-
- }
-
- /**
- * Gets the output that the module wants to diaply.
- * @param string $action The action that triggered the output.
- * @return string Output defined by the module.
- */
- abstract public function getOutput($action);
-
- /**
- * Checks if an action can be handled by the module.
- * @param string $action The action to be checked.
- * @return boolean True if the action can be handled by the module,
- * false otherwise.
- */
- public function handlesAction($action) {
- return in_array($action, array_keys($this->actions));
- }
-
- /**
- * Gets all admin actions handled by the module.
- * @return array An array containing all admin actions that the module
- * handles.
- */
- public function getAdminActions() {
- return $this->actions;
- }
-
- /**
- * Override this function if the module should be linked to once in the
- * panel.
- * @return string An expression that should be used with eval() or an
- * empty string if none is defined.
- */
- public function getGlobalLinkPattern() {
- return '';
- }
-
- /**
- * Override this function if the module should be linked to once for every
- * entry displayed in the panel's overview. The pattern can use fieldnames
- * as $row['foo'] (where foo is the fieldname).
- * @return string An expression that should be used with eval() or an empty
- * string if none is defined.
- */
- public function getEntryLinkPattern() {
- return '';
- }
-
- /**
- * Notifies everything that should be notified of admin activity. This
- * function should be called whenever a module alters a table.
- * @param string $table The name of the table that the action affects.
- * @param string $sqlSelector The sql selector (if there is any) that
- * specifies the row that was altered.
- */
- protected function logActivity($table, $sqlSelector = '') {
- logAdminActivity($table, get_class($this), $sqlSelector);
- }
- }
-
- /**
- * Describes a table field with a connected value in $_REQUEST. The table
- * field tries to capture it's connected value if possible.
- * @author Andreas Launila
- * @package com.lokorin.lokorin.lib
- */
- class TableField {
- /**
- * The name used to identify field in $_REQUEST.
- * @var string
- */
- private $requestName;
- /**
- * The name that should be displayed to the user.
- * @var string
- */
- private $displayName;
- /**
- * The name of the corresponding field in the table.
- * @var string
- */
- private $tableField;
- /**
- * The value of the field (used for different things, e.g. identification).
- * @var string
- */
- private $value;
-
- /**
- * Constructor for TableField.
- * @param string $requestName The name used to identify field in $_REQUEST.
- * @param string $displayName The name to display to the user.
- * @param string $tableField The corresponding field in the table.
- * @param string $value The value of the field.
- */
- public function __construct($requestName, $displayName, $tableField,
- $value = false) {
- $this->requestName = $requestName;
- $this->displayName = $displayName;
- $this->tableField = $tableField;
- if(($value !== false) || !isset($_REQUEST[$requestName])) {
- $this->value = $value;
- }
- }
-
- /**
- * Gets the request name of the field.
- * @return string An $_REQUEST name.
- */
- public function getRequestName() {
- return $this->requestName;
- }
-
- /**
- * Gets the display name of the field.
- * @return string A name.
- */
- public function getDisplayName() {
- return $this->displayName;
- }
-
- /**
- * Gets the name of the table field connected to this instance.
- * @return string A table field name.
- */
- public function getTableField() {
- return $this->tableField;
- }
-
- /**
- * Gets the value of the field.
- * @return string A value.
- */
- public function getValue() {
- if((strlen($this->value) == 0) &&
- isset($_REQUEST[$this->requestName])) {
- $this->value = $_REQUEST[$this->requestName];
- }
- return $this->value;
- }
-
- /**
- * Checks if the field has a value set or not.
- * @return boolean True if the field has a value, false otherwise.
- */
- public function hasValue() {
- return $this->value !== false;
- }
-
- /**
- * Sets a new value for the field.
- * @param $newVal The new value to assign.
- */
- public function setValue($newVal) {
- $this->value = $newVal;
- }
- }
-
- /**
- * Describes an admin action, an identifier for something that can be done by
- * the admin panel.
- * @author Andreas Launila
- * @package com.lokorin.lokorin.lib
- */
- class AdminAction {
- /**
- * The action value that triggers the action.
- * @var string
- */
- private $actionIdentifier;
- /**
- * The name that describes the action to the user.
- * @var string
- * @access private
- */
- private $displayName;
-
- /**
- * Constructor for AdminAction.
- * @param string $actionId The action value that identifies the action.
- * @param string $displayName The name that describes the action to the
- * user.
- */
- public function __construct($actionId, $displayName) {
- $this->actionIdentifier = $actionId;
- $this->displayName = $displayName;
- }
-
- /**
- * Gets the action value identifing the action.
- * @return string An action value.
- */
- public function getAction() {
- return $this->actionIdentifier;
- }
-
- /**
- * Gets the name that describes the action.
- * @return string An describing name.
- */
- public function getDisplayName() {
- return $this->displayName;
- }
- }
-
- /**
- * Describes a module that deletes rows from a table.
- * @author Andreas Launila
- * @package com.lokorin.lokorin.lib
- */
- class DeleteModule extends AdminModule {
- /**
- * The name of the table that the module should delete rows from.
- * @var string
- */
- private $table;
- /**
- * Contains the TableField instances that should be used to identify which
- * row that should be deleted.
- * @var array
- */
- private $fields;
- /**
- * If a confirmation should be asked for or not. True if a confirmation
- * should be asked for, false otherwise.
- * @var boolen
- */
- private $doConfirmation;
-
- /**
- * Constructor for DeleteModule.
- * @param string $table The table that should be worked against.
- * @param array $identifierFields The fields that identify which row that
- * should be deleted.
- * @param boolean $requestConfimation If a confimation should be asked
- * for or not.
- */
- public function __construct($table, $identifierFields, $requestConfirmation = true) {
- parent::__construct(array(
- new AdminAction('remove', 'Remove'),
- new AdminAction('do_remove', 'Remove')
- ));
- $this->table = $table;
- $this->fields = $identifierFields;
- $this->doConfirmation = $requestConfirmation;
- }
-
- /**
- * @see AdminModule.getOutput($action)
- */
- public function getOutput($action) {
- if($action == 'remove') {
- if($this->doConfirmation) {
- return $this->processConfirm();
- } else {
- return $this->processRemove();
- }
- } else if($action == 'do_remove') {
- return $this->processRemove();
- }
- }
-
- /**
- * Creates a confirmation dialog.
- * @return string A confirmation dialog.
- */
- private function processConfirm() {
- $queryString = '';
- $header = new Header();
- $body = array();
- foreach($this->fields as $field) {
- $header->add($field->getDisplayName());
- $body[] = $field->getValue();
- $queryString .= '&'.$field->getRequestName().'='.$field->getValue();
- }
- $table = new Table();
- $table->setHeader($header);
- $table->addRow($body);
- return 'Are you sure that you want to delete the following entry?'.$table->getTable().
- '<a href="'.SELF.'?action=do_remove'.$queryString.'" class="adminAction">Yes</a>' . "\n" .
- '<a href="'.SELF.'" class="adminAction">No</a>';
-
- }
-
- /**
- * Removes an entry and creates a confirmation message.
- * @return string An confirmation or error message.
- */
- private function processRemove() {
- //Make sure that all identifier fields have been set.
- $valid = true;
- foreach($this->fields as $field) {
- if(!$field->hasValue()) {
- $valid = false;
- break;
- }
- }
- if(!$valid) {
- return 'Invalid input, some identifier fields were not set.';
- }
-
- //Perform the deletion
- global $db;
- //Build the match parameters.
- $matchFields = array();
- foreach($this->fields as $field) {
- $matchFields[$field->getTableField()] = $field->getValue();
- }
- $sqlSel = $db->buildSqlSelector($matchFields);
- $result = $db->queryDelete($this->table, $sqlSel);
- $this->logActivity($this->table, $sqlSel);
- $idField = $this->fields[0];
- $output = 'The entry was successfully removed.';
-
- doInclude('lib_redirects');
- doDelayedRedirect(SELF, 2);
-
- return $output;
- }
-
- /**
- * @see AdminModule.getEntryLinkPattern()
- */
- public function getEntryLinkPattern() {
- $fields = '';
- foreach($this->fields as $field) {
- $fields .= "&".$field->getRequestName().
- "=\$row['".$field->getTableField()."']";
- }
- return '<a href="'.SELF.'?action=remove'.$fields.
- '" class="adminAction">Remove</a>';
- }
- }
-
- /**
- * Describes a module that edits a specified row in a table.
- * @author Andreas Launila
- * @package com.lokorin.lokorin.lib
- */
- class EditModule extends AdminModule {
- /**
- * The name of table that contains the row that should be edited.
- * @var string
- */
- private $table;
- /**
- * Contains the fields, represented by TableField instances, that should
- * be edited.
- * @var array
- */
- private $fields;
- /**
- * Contains the form fields, represented by Field instances, that should
- * be used to override the request name contained in the key.
- * @var array
- */
- private $formFields;
- /**
- * Contains the fields that identify the rows that should be edited. The
- * key is the name of the table field and the corresponding value is the
- * corresponding form field that should be used for the table field.
- * @var array
- */
- private $idFields;
-
- /**
- * Constructor for EditModule.
- * @param string $table The table that should be edited.
- * @param array $fieldsToEdit An array of TableField with the fields that
- * should be edited.
- * @param array $idFields An array of Tablefield that identifies which
- * entry that should be edited.
- * @param array $formFields An array of Field (from lib_form_generator.php)
- * with the connected request name as field name.
- */
- public function __construct($table, $fieldsToEdit, $idFields, $formFields = array()) {
- parent::__construct(array(
- new AdminAction('edit', 'Edit'),
- new AdminAction('do_edit', 'Perform edit')
- ));
- $this->table = $table;
- $this->fields = $fieldsToEdit;
-
- //Build the id fields.
- $this->idFields = array();
- foreach($idFields as $field) {
- $this->idFields[$field->getTableField()] =
- new Hidden('editid_'.$field->getRequestName());
- }
-
- //Build the form fields (making the key the request name).
- $fields = array();
- foreach($formFields as $field) {
- $fields[$field->getName()] = $field;
- }
- $this->formFields = $fields;
-
- }
-
- /**
- * @see AdminModule.getOutput($action)
- */
- public function getOutput($action) {
- if($action == 'edit') {
- return $this->getEditDialog();
- } else if($action == 'do_edit') {
- return $this->processEdit();
- }
- }
-
- /**
- * Gets the corresponding edit dialog.
- * @return string An edit dialog.
- */
- private function getEditDialog() {
- global $db;
-
- $sqlFields = array();
- foreach($this->idFields as $tableField => $formField) {
- $sqlFields[$tableField] = $formField->getValue();
- }
- $rows = $db->querySelectAll($this->table,
- $db->buildSqlSelector($sqlFields)." LIMIT 1");
- $row = $rows[0];
-
- //Make the form
- $form = new Form('Edit', 'post', SELF.'?action=do_edit');
- foreach($this->fields as $field) {
- if(isset($row[$field->getTableField()])) {
- $field->setValue($row[$field->getTableField()]);
- }
- if(isset($this->formFields[$field->getRequestName()])) {
- $formField = $this->formFields[$field->getRequestName()];
- } else {
- $formField = new TextField($field->getRequestName());
- }
- $formField->setValue($field->getValue());
- $form->addField($formField, $field->getDisplayName());
- }
- $form->addField(new SubmitButton('edit', 'Edit'));
- //Add the hidden identifiers.
- foreach($this->idFields as $field) {
- $form->addField($field);
- }
-
- return $form->getForm();
- }
-
- /**
- * Processes an edit request and returns the result or an error message.
- * @return An confirmation message or an error.
- */
- private function processEdit() {
- global $db;
-
- $vars = array();
- foreach($this->fields as $field) {
- $vars[$field->getTableField()] = $field->getValue();
- }
-
- $sqlFields = array();
- foreach($this->idFields as $tableField => $formField) {
- $sqlFields[$tableField] = $formField->getValue();
- }
- $sqlSelector = $db->buildSqlSelector($sqlFields);
- $db->queryUpdate($this->table, $vars, $sqlSelector);
- $this->logActivity($this->table, $sqlSelector);
- $output = 'The entry was successfully edited.';
-
- doInclude('lib_redirects');
- doDelayedRedirect(SELF, 2);
-
- return $output;
- }
-
- /**
- * @see AdminModule.getEntryLinkPattern()
- */
- public function getEntryLinkPattern() {
- $fields = '';
- foreach($this->idFields as $tableField => $formField) {
- $fields .= "&".$formField->getName()."=\$row['".$tableField."']";
- }
- return '<a href="'.SELF.'?action=edit'.$fields.'" class="adminAction">Edit</a>';
- }
- }
-
- /**
- * Describes a module for adding new rows to a table.
- * @author Andreas Launila
- * @package com.lokorin.lokorin.lib
- */
- class AddModule extends AdminModule {
- /**
- * The name of the table that the module should add rows to.
- * @var string
- */
- private $table;
- /**
- * Contains the fields (represented by TableFiled instances) that should
- * be set when adding a new module.
- * @var array
- */
- private $fields;
- /**
- * Contains the form fields, represented by Field instances, that should
- * be used to override the request name contained in the key.
- * @var array
- */
- private $formFields;
-
- /**
- * Constructor for AddModule.
- * @param string $table The table that entries should be added to.
- * @param array $fieldsToAdd An array of TableField with the fields that
- * should be added.
- * @param array $formFields An array of Field (from lib_form_generator.php)
- * with the connected request name as field name.
- */
- public function __construct($table, $fieldsToAdd, $formFields = array()) {
- parent::__construct(array(
- new AdminAction('add', 'New entry'),
- new AdminAction('do_add', 'Add')
- ));
- $this->table = $table;
- $this->fields = $fieldsToAdd;
- //Build the form fields (making the key the request name).
- $fields = array();
- foreach($formFields as $field) {
- $fields[$field->getName()] = $field;
- }
- $this->formFields = $fields;
- }
-
- /**
- * @see AdminModule.getOutput($action)
- */
- public function getOutput($action) {
- if($action == 'add') {
- return $this->getAddDialog();
- } else if($action == 'do_add') {
- return $this->processAdd();
- }
- }
-
- /**
- * Gets the corresponding add dialog.
- * @return string An add dialog.
- */
- private function getAddDialog() {
- $form = new Form('Add a new entry', 'post', SELF.'?action=do_add');
- foreach($this->fields as $field) {
- if(isset($this->formFields[$field->getRequestName()])) {
- $fieldToAdd = $this->formFields[$field->getRequestName()];
- } else {
- $fieldToAdd = new TextField($field->getRequestName());
- }
- if($field->hasValue()) {
- $fieldToAdd->setValue($field->getValue());
- }
- $form->addField($fieldToAdd, $field->getDisplayName());
- }
- $form->addField(new SubmitButton('add', 'Add'));
- return $form->getForm();
- }
-
- /**
- * Processes an add request and returns the result or an error message.
- * @return An confirmation message or an error.
- */
- private function processAdd() {
- global $db;
-
- $vars = array();
- foreach($this->fields as $field) {
- $vars[$field->getTableField()] = $field->getValue();
- }
-
- $db->queryInsert($this->table, $vars);
-
- $this->logActivity($this->table, $db->getLastInsertId());
- $output = 'The entry was successfully added.';
-
- doInclude('lib_redirects');
- doDelayedRedirect(SELF, 2);
-
- return $output;
- }
-
- /**
- * @see AdminModule.getGlobalLinkPattern()
- */
- public function getGlobalLinkPattern() {
- return '<a href="'.SELF.'?action=add" ' .
- 'class="adminAction">New Entry</a>';
- }
- }
-
- /**
- * Describes a module that uses callbacks to process events.
- * @author Andreas Launila
- * @package com.lokorin.lokorin.lib
- */
- class CallbackModule extends AdminModule {
- /**
- * Contains all the callbacks, action value as key, the callback as value.
- * @var array
- */
- private $callbacks;
- /**
- * The global link pattern to be used by the module.
- * @var string
- */
- private $globalLink;
- /**
- * The entry link pattern to be returned by the module.
- * @var string
- */
- private $entryLink;
-
- /**
- * Constructor for CallbackModule.
- * @param array $callbacks An array of the callbacks to be used,
- * corresponding action value as key, callback as value.
- * @param string $globalLink The global link pattern (see AdminModule.getGlobalLinkPattern()
- * that the module should use.
- * @param string $entryLink The entry link pattern (see AdminModule.getEntryLinkPattern()
- * that the module should use.
- */
- public function __construct($callbacks, $globalLink = '', $entryLink = '') {
- $actions = array();
- foreach($callbacks as $action => $callback) {
- $actions[] = new AdminAction($action, $action);
- }
- parent::__construct($actions);
-
- $this->callbacks = $callbacks;
- $this->globalLink = $globalLink;
- $this->entryLink = $entryLink;
- }
-
- /**
- * @see AdminModule.getOutput($action)
- */
- public function getOutput($action) {
- if(isset($this->callbacks[$action])) {
- return $this->callbacks[$action]();
- } else {
- return 'Unmapped action ('.$action.').';
- }
- }
-
- /**
- * @see AdminModule.getGlobalLinkPattern()
- */
- public function getGlobalLinkPattern() {
- return $this->globalLink;
- }
-
- /**
- * @see AdminModule.getEntryLinkPattern()
- */
- public function getEntryLinkPattern() {
- return $this->entryLink;
- }
- }
-
- /**
- * Describes a module that shows read only contents of a specified row.
- * @author Andreas Launila
- * @package com.lokorin.lokorin.lib
- */
- class DetailsModule extends AdminModule {
- /**
- * The table that should be read from.
- * @var string
- */
- private $table;
- /**
- * Contains TableField instances representing the fields that should be
- * viewed in the detailed overview.
- * @var array
- */
- private $fieldsToView;
- /**
- * Contains the fields (as TableField instances) that identify which row
- * that should be viewed.
- * @var array
- */
- private $idFields;
- /**
- * Contains all format callbacks with the corresponding table field as key
- * and the callback as value.
- * @var array
- */
- private $callbacks;
-
- /**
- * Constructor for DetailsModule.
- * @param string $table The table to read from.
- * @param array $fieldsToView The TableField instances that should be shown
- * in the detailed version.
- * @param array $idFields The Tablefield instances that identifies which
- * row that contains the specified entry.
- * @param array $formatCallbacks An optional set of callbacks that should
- * be used to format output (i.e. timestamps). The key should be the
- * corresponding table field.
- */
- public function __construct($table, $fieldsToView, $idFields,
- $formatCallbacks = array()) {
- parent::__construct(array(
- new AdminAction('details', 'Details')
- ));
-
- $this->table = $table;
- $this->fieldsToView = $fieldsToView;
- $this->idFields = $idFields;
- $this->callbacks = $formatCallbacks;
- }
-
- /**
- * @see AdminModule.getOutput($action)
- */
- public function getOutput($action) {
- if($action != 'details') {
- return '';
- }
-
- global $db;
-
- $sqlFields = array();
- foreach($this->idFields as $field) {
- $sqlFields[$field->getTableField()] = $field->getValue();
- }
- $rows = $db->querySelectAll($this->table,
- $db->buildSqlSelector($sqlFields));
- $row = $rows[0];
-
- $output = '<ul>';
- foreach($this->fieldsToView as $field) {
- $value = $row[$field->getTableField()];
- if(isset($this->callbacks[$field->getTableField()])) {
- $value = $this->callbacks[$field->getTableField()]($value);
- }
- $output .= '<li><i>'.$field->getDisplayName().'</i>: '.
- htmlspecialchars($value).'</li>';
- }
- $output .= '</ul>';
- return $output;
- }
-
- /**
- * @see AdminModule.getEntryLinkPattern()
- */
- public function getEntryLinkPattern() {
- $fields = '';
- foreach($this->idFields as $field) {
- $fields .= "&".$field->getRequestName()."=\$row['".$field->getTableField()."']";
- }
- return '<a href="'.SELF.'?action=details'.$fields.
- '" class="adminAction">Details</a>';
- }
- }
-
-
- /**
- * Describes a module that sets specified fields to specified values when
- * requested.
- * @author Andreas Launila
- * @package com.lokorin.lokorin.lib
- */
- class UpdateModule extends AdminModule {
- /**
- * The name of the table which rows should be updated.
- * @var string
- */
- private $table;
- /**
- * Contains the fields (represented by TableField instances) and the values
- * that they should be set to.
- * @var array
- */
- private $fieldsToSet;
- /**
- * Contains the fields (represented by TableFiled instances) that identify
- * which row that should be set.
- * @var array
- */
- private $idFields;
- /**
- * The name for the link that should represent the module.
- * @var string
- */
- private $linkName;
-
- /**
- * Constructor for UpdateModule.
- * @param string $table The table to read from.
- * @param array $fieldsToSet The TableField instances that should be set
- * (along with the value that should be used).
- * @param array $idFields The Tablefield instances that identifies which
- * row that should be set.
- * @param string $linkName An optional name for the link that will be
- * representing the action e.g. 'Mark as investigated'.
- */
- public function __construct($table, $fieldsToSet, $idFields, $linkName = 'Update') {
- parent::__construct(array(
- new AdminAction('update', 'Update')
- ));
-
- $this->table = $table;
- $this->fieldsToSet = $fieldsToSet;
- $this->idFields = $idFields;
- $this->linkName = $linkName;
- }
-
- /**
- * @see AdminModule.getOutput($action)
- */
- public function getOutput($action) {
- if($action != 'update') {
- return '';
- }
-
- global $db;
-
- $sqlFields = array();
- foreach($this->idFields as $field) {
- $sqlFields[$field->getTableField()] = $field->getValue();
- }
-
- $vars = array();
- foreach($this->fieldsToSet as $field) {
- $vars[$field->getTableField()] = $field->getValue();
- }
-
- $db->queryUpdate($this->table, $vars, $db->buildSqlSelector($sqlFields));
-
- return '';
- }
-
- /**
- * @see AdminModule.getEntryLinkPattern()
- */
- public function getEntryLinkPattern() {
- $fields = '';
- foreach($this->idFields as $field) {
- $fields .= "&".$field->getRequestName()."=\$row['".$field->getTableField()."']";
- }
- return '<a href="'.SELF.'?action=update'.$fields.
- '" class="adminAction">'.$this->linkName.'</a>';
- }
- }
-
-
- /**
- * Describes a panel itself. The panel itself is an module that shows an
- * overview of a table and the available modules.
- * @author Andreas Launila
- * @package com.lokorin.lokorin.lib
- */
- class AdminPanel extends AdminModule {
- /**
- * Contains all the modules (AdminModule instances) that belong to the
- * panel.
- * @var array
- */
- private $modules;
- /**
- * The action that should be used if no other action is declared (in
- * $_REQUEST).
- * @var string
- */
- private $defaultAction;
- /**
- * The name of the table that the panel should view.
- * @var string
- */
- private $tabel;
- /**
- * Contains the fields (represented by TableField instances) that should
- * be displayed.
- * @var array
- */
- private $fields;
- /**
- * Contains callbacks that should be used to properly format fields. Key
- * is the tables fieldname, value is the callback. If no callback for a
- * field is found then the field is directly outputted without any
- * preprocessing.
- * @var array
- */
- private $formatCallbacks;
- /**
- * The appendage to the view query. This could for instance be a match
- * statement or a order apppendage.
- * @var string
- */
- private $queryAppendage;
- /**
- * The number of items that should be displayed in each page when viewing
- * the table overview.
- * @var integer
- */
- private $itemsPerPage;
- /**
- * The table displayer that should be used to view the the contents of the
- * viewe database.
- * @var AbstractTableDisplayer
- */
- private $displayer;
-
- /**
- * Constructor for AdminPanel.
- * @param string $table The table that should be overviewed to.
- * @param array $fieldsToView An array of TableField with the fields that
- * should be viewed.
- * @param string $queryAppendage An optional condition on what and how to
- * show the sql result. The condition is appended to the end of the
- * query.
- * @param string $defaultAction The action value that should be used if no
- * other action is declared. If no value is specified then the first
- * module added to the panel will be used.
- * @param array $formatCallbacks An array of Field (from lib_form_generator.php)
- * with the connected table field as name.
- */
- public function __construct($table, $fieldsToView, $queryAppendage = '',
- $defaultAction = '', $formatCallbacks = array()) {
- parent::__construct(array(
- new AdminAction('view', 'Overview')
- ));
- $this->table = $table;
- $this->fields = $fieldsToView;
- $this->queryAppendage = $queryAppendage;
- $this->formatCallbacks = $formatCallbacks;
- $this->defaultAction = $defaultAction;
- $this->itemsPerPage = 20;
-
- $this->displayer = new TableDisplayer(
- $this->table, $this->itemsPerPage, $this->queryAppendage);
-
- $this->addModule($this);
- }
-
- /**
- * Sets the number of items that should be displayed in each page when
- * viewing the table overview.
- * @param integer $newValue The number of items that should be displayed
- * per page.
- */
- public function setItemsPerPage($newValue) {
- $this->displayer->setRowsPerPage($newValue);
- }
-
- /**
- * Sets a new table displayer that should be used by the panel to view
- * databses with.
- * @param AbstractTableDisplayer $newTableDisplayerToUse the new table
- * displayer that should be used.
- */
- public function setTableDisplayer(AbstractTableDisplayer $newTableDisplayerToUse) {
- $this->displayer = $newTableDisplayerToUse;
- }
-
- /**
- * Adds an additional module to the panel.
- * @param AdminModule $module The module that should be added.
- */
- public function addModule(AdminModule $module) {
- $this->modules[] = $module;
- //Update the default action if none is set.
- if($this->defaultAction == '') {
- $actions = $module->getAdminActions();
- if(sizeof($actions) > 0) {
- $action = current($actions);
- $this->defaultAction = $action->getAction();
- }
- }
- }
-
- /**
- * Gets the panel in its HTML form.
- * @return string An admin panel.
- */
- public function getPanel() {
- if(isset($_REQUEST['action'])) {
- $action = $_REQUEST['action'];
- } else {
- $action = $this->defaultAction;
- }
-
- /*
- * This is a necessary because of how PHP handles function calls. It
- * does not accept calling the same class through a pointer for some
- * strange reason.
- */
- if($action == 'view') {
- return $this->getOutput($action);
- }
-
- //Go through all modules.
- foreach($this->modules as $module) {
- if($module->handlesAction($action)) {
- $output = $module->getOutput($action);
- //If the module produced output then show it, otherwise display
- //the default action.
- if($output != '') {
- return $output;
- } else {
- $_REQUEST['action'] = $this->defaultAction;
- return $this->getPanel();
- }
- }
- }
-
- return 'No module was found for the specified action.';
- }
-
- /**
- * @see AdminModule.getOutput($action)
- */
- public function getOutput($action) {
- if($action != 'view') {
- return '';
- }
-
- global $db;
-
- $displayer = $this->displayer;
- $menuBar = $displayer->getPageMenuBar();
-
- $output = $menuBar;
- $fieldNames = array();
- foreach($this->fields as $field) {
- $fieldNames[] = $field->getTableField();
- }
-
- //Check what modules that want to be added where.
- $entryLinkPatterns = array();
- foreach($this->modules as $module) {
- if($module->getEntryLinkPattern() != '') {
- //Add to the per entry list.
- $entryLinkPatterns[] = $module->getEntryLinkPattern();
- }
- if($module->getGlobalLinkPattern() != '') {
- //Add the link directly.
- $output .= ' '.$module->getGlobalLinkPattern();
- }
- }
-
- $rows = $displayer->getPageRows();
- if(sizeof($rows) > 0) {
- //Construct the table header.
- $header = new Header();
- foreach($this->fields as $field) {
- $header->add($field->getDisplayName());
- }
- if(sizeof($entryLinkPatterns) > 0) {
- $header->add('Admin operations');
- }
-
- //Construct the table.
- $table = new Table();
- $table->setHeader($header);
- foreach($rows as $row) {
- //Output the designated fields.
- $tableRow = array();
- foreach($this->fields as $field) {
- $name = $field->getTableField();
- $value = $row[$name];
- if(isset($this->formatCallbacks[$name])) {
- $value = $this->formatCallbacks[$name]($value);
- }
- $tableRow[] = htmlspecialchars($value);
- }
-
- if(sizeof($entryLinkPatterns) > 0) {
- //Add the modules that want to be added for each entry.
- $cell = '';
- foreach($entryLinkPatterns as $pattern) {
- foreach($row as $name => $value) {
- //Horribly inefficent method, couldn't get any other method to work though.
- $pattern = str_replace("\$row['".$name."']", $row[$name], $pattern);
- }
- $cell .= ' '.$pattern;
- }
- $tableRow[] = $cell;
- }
- $table->addRow($tableRow);
- }
-
- return $output.$table->getTable().$menuBar;
- } else {
- return $output.'No entries found.';
- }
- }
- }
-
- ?>