Chamilo is a learning management system focused on ease of use and accessibility
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
chamilo-lms/main/inc/lib/hook/HookManagement.php

361 lines
12 KiB

<?php
/* For licensing terms, see /license.txt */
/**
* @TODO: Improve description
* @package chamilo.hookmanagement
*/
class HookManagement implements HookManagementInterface
{
/**
* Constructor
*/
protected function __construct()
{
$this->tables[TABLE_HOOK_OBSERVER] = Database::get_main_table(TABLE_HOOK_OBSERVER);
$this->tables[TABLE_HOOK_EVENT] = Database::get_main_table(TABLE_HOOK_EVENT);
$this->tables[TABLE_HOOK_CALL] = Database::get_main_table(TABLE_HOOK_CALL);
$this->hookCalls = $this->listAllHookCalls();
$this->hookEvents = $this->listAllHookEvents();
$this->hookObservers = $this->listAllHookObservers();
}
/**
* Instance the hook manager
* @staticvar null $result
* @return HookManagement
*/
public static function create()
{
static $result = null;
return $result ? $result : $result = new self();
}
/**
* Insert hook into Database. Return insert id
* @param string $eventName
* @param string $observerClassName
* @param int $type
*
* @return int
*/
public function insertHook($eventName, $observerClassName, $type)
{
if ($type === HOOK_EVENT_TYPE_ALL) {
$this->insertHook($eventName, $observerClassName, HOOK_EVENT_TYPE_PRE);
$this->insertHook($eventName, $observerClassName, HOOK_EVENT_TYPE_POST);
} else {
$this->insertHookIfNotExist($eventName, $observerClassName);
// Check if exists hook call
$row = Database::select('id, enabled',
$this->tables[TABLE_HOOK_CALL],
array(
'where' => array(
'hook_event_id = ? ' => $this->hookEvents[$eventName],
'AND hook_observer_id = ? ' => $this->hookObservers[$observerClassName],
'AND type = ? ' => $type,
),
),
'ASSOC');
if (!empty($row) && is_array($row)) {
// Check if is hook call is active
if ((int) $row['enabled'] === 0) {
Database::update(
$this->tables[TABLE_HOOK_CALL],
array(
'enabled' => 1,
),
array(
'id = ?' => $row['id'],
)
);
}
}
}
}
/**
* Delete hook from Database. Return deleted rows number
* @param string $eventName
* @param string $observerClassName
* @param int $type
*
* @return int
*/
public function deleteHook($eventName, $observerClassName, $type)
{
if ($type === HOOK_EVENT_TYPE_ALL) {
$this->deleteHook($eventName, $observerClassName, HOOK_EVENT_TYPE_PRE);
$this->deleteHook($eventName, $observerClassName, HOOK_EVENT_TYPE_POST);
} else {
$this->insertHookIfNotExist($eventName, $observerClassName);
Database::update(
$this->tables[TABLE_HOOK_CALL],
array(
'enabled' => 0,
),
array(
'id = ? ' => $this->hookCalls[$eventName][$observerClassName][$type],
)
);
}
}
/**
* Update hook observer order by hook event
* @param $eventName
* @param $type
* @param $hookOrders
*
* @return int
*/
public function orderHook($eventName, $type, $hookOrders)
{
foreach ($this->hookCalls[$eventName] as $observerClassName => $types) {
foreach ($hookOrders as $oldOrder => $newOrder)
{
$res = Database::update(
$this->tables[TABLE_HOOK_CALL],
array(
'hook_order ' => $newOrder,
),
array(
'id = ? ' => $types[$type],
'AND hook_order = ? ' => $oldOrder,
)
);
if ($res) {
break;
}
}
}
}
/**
* Return a list an associative array where keys are the active hook observer class name
* @param $eventName
*
* @return array
*/
public function listHookObservers($eventName)
{
$array = array();
$joinTable = $this->tables[TABLE_HOOK_CALL] . ' hc' .
' INNER JOIN ' . $this->tables[TABLE_HOOK_EVENT] . ' he' .
' ON hc.hook_event_id = he.id ' .
' INNER JOIN ' . $this->tables[TABLE_HOOK_OBSERVER] . ' ho ' .
' ON hc.hook_observer_id = ho.id ';
$columns = 'ho.class_name, ho.path, ho.plugin_name, hc.enabled';
$where = array('where' => array('he.class_name = ? ' => $eventName, 'AND hc.enabled = ? ' => 1));
$rows = Database::select($columns, $joinTable, $where);
foreach ($rows as $row) {
$array[$row['class_name']] = $row;
}
return $array;
}
/**
* Return a list an associative array where keys are the active hook observer class name
* @return array
*/
public function listAllHookObservers()
{
$array = array();
$columns = 'id, class_name';
$rows = Database::select($columns, $this->tables[TABLE_HOOK_OBSERVER]);
foreach ($rows as $row) {
$array[$row['class_name']] = $row['id'];
}
return $array;
}
/**
* Return a list an associative array where keys are the active hook observer class name
* @return array
*/
public function listAllHookEvents()
{
$array = array();
$columns = 'id, class_name';
$rows = Database::select($columns, $this->tables[TABLE_HOOK_EVENT]);
foreach ($rows as $row) {
$array[$row['class_name']] = $row['id'];
}
return $array;
}
/**
* Return a list an associative array where keys are the active hook observer class name
* @return array
*/
public function listAllHookCalls()
{
$array = array();
$joinTable = $this->tables[TABLE_HOOK_CALL] . ' hc' .
' INNER JOIN ' . $this->tables[TABLE_HOOK_EVENT] . ' he' .
' ON hc.hook_event_id = he.id ' .
' INNER JOIN ' . $this->tables[TABLE_HOOK_OBSERVER] . ' ho ' .
' ON hc.hook_observer_id = ho.id ';
$columns = 'he.class_name AS event_class_name, ho.class_name AS observer_class_name, hc.id AS id, hc.type AS type';
$rows = Database::select($columns, $joinTable);
foreach ($rows as $row) {
$array[$row['event_class_name']][$row['observer_class_name']][$row['type']] = $row['id'];
}
return $array;
}
/**
* Check if hooks (event, observer, call) exist in Database, if not,
* Will insert them into their respective table
* @param string $eventName
* @param string $observerClassName
*
* @return int
*/
public function insertHookIfNotExist($eventName = null, $observerClassName = null)
{
// Check if exists hook event
if (isset($eventName) && !isset($this->hookEvents[$eventName])) {
$attributes = array(
'class_name' => $eventName,
'description' => get_lang('HookDescription' . $eventName),
);
$id = Database::insert($this->tables[TABLE_HOOK_EVENT], $attributes);
$this->hookEvents[$eventName] = $id;
}
// Check if exists hook observer
if (isset($observerClassName) &&
!isset($this->hookObservers[$observerClassName])
){
$object = $observerClassName::create();
$attributes = array(
'class_name' => $observerClassName,
'path' => $object->getPath(),
'plugin_name' => $object->getPluginName(),
);
$id = Database::insert($this->tables[TABLE_HOOK_OBSERVER], $attributes);
$this->hookObservers[$observerClassName] = $id;
}
if (
isset($eventName) &&
isset($observerClassName) &&
!isset($this->hookCalls[$eventName][$observerClassName])
) {
// HOOK TYPE PRE
$row = Database::select(
'MAX(hook_order) as hook_order',
$this->tables[TABLE_HOOK_CALL],
array(
'where' => array(
'hook_event_id = ? ' =>$this->hookEvents[$eventName],
'AND type = ? ' => HOOK_EVENT_TYPE_PRE,
),
),
'ASSOC'
);
// Check if exists hook call
$id = Database::insert(
$this->tables[TABLE_HOOK_CALL],
array(
'hook_event_id' => $this->hookEvents[$eventName],
'hook_observer_id' => $this->hookObservers[$observerClassName],
'type' => HOOK_EVENT_TYPE_PRE,
'enabled' => 0,
'hook_order' => $row['hook_order'] + 1,
)
);
$this->hookCalls[$eventName][$observerClassName][HOOK_EVENT_TYPE_PRE] = $id;
// HOOK TYPE POST
$row = Database::select(
'MAX(hook_order) as hook_order',
$this->tables[TABLE_HOOK_CALL],
array(
'where' => array(
'hook_event_id = ? ' =>$this->hookEvents[$eventName],
'AND type = ? ' => HOOK_EVENT_TYPE_POST,
),
),
'ASSOC'
);
// Check if exists hook call
$id = Database::insert(
$this->tables[TABLE_HOOK_CALL],
array(
'hook_event_id' => $this->hookEvents[$eventName],
'hook_observer_id' => $this->hookObservers[$observerClassName],
'type' => HOOK_EVENT_TYPE_POST,
'enabled' => 0,
'hook_order' => $row['hook_order'] + 1,
)
);
$this->hookCalls[$eventName][$observerClassName][HOOK_EVENT_TYPE_POST] = $id;
} elseif (isset($eventName) && !isset($observerClassName)) {
foreach ($this->hookObservers as $observer => $id) {
$this->insertHookIfNotExist($eventName, $observer);
}
} elseif (!isset($eventName) && isset($observerClassName)) {
foreach ($this->hookEvents as $event => $id) {
$this->insertHookIfNotExist($event, $observerClassName);
}
}
return 1;
}
/**
* Return the hook call id identified by hook event, hook observer and type
* @param string $eventName
* @param string $observerClassName
* @param int $type
*
* @return mixed
*/
public function getHookCallId($eventName, $observerClassName, $type)
{
$eventName = Database::escape_string($eventName);
$observerClassName($observerClassName);
$type = Database::escape_string($type);
$joinTable = $this->tables[TABLE_HOOK_CALL] . ' hc' .
' INNER JOIN ' . $this->tables[TABLE_HOOK_EVENT] . ' he' .
' ON hc.hook_event_id = he.id ' .
' INNER JOIN ' . $this->tables[TABLE_HOOK_OBSERVER] . ' ho ' .
' ON hc.hook_observer_id = ho.id ';
$row = Database::select(
'id',
$joinTable,
array(
'where' => array(
'he.class_name = ? ' => $eventName,
'AND ho.class_name = ? ' => $observerClassName,
'AND hc.type = ? ' => $type,
),
),
'ASSOC'
);
return $row['id'];
}
}