66 var $_runtime_event_listeners = Array();
72 var $_runtime_listener_objects = Array();
80 parent::MySource_Object();
100 if (empty($events))
return false;
102 foreach ($events as $event_name) {
103 $event_name = trim($event_name);
104 if (empty($event_name))
continue;
106 if (!array_key_exists($event_name, $this->_runtime_event_listeners)) {
107 $this->_runtime_event_listeners[$event_name] = Array();
109 $index = count($this->_runtime_listener_objects);
110 $this->_runtime_listener_objects[] = $listener;
111 $this->_runtime_event_listeners[$event_name][$index] =
true;
130 if (!isset($this->_runtime_event_listeners[$event_name])) {
134 $event_name = trim($event_name);
135 $function_name =
'on'.$event_name;
137 foreach (array_keys($this->_runtime_event_listeners[$event_name]) as $index) {
138 if (!isset($this->_runtime_listener_objects[$index])) {
141 $listener = $this->_runtime_listener_objects[$index];
142 if (is_null($listener))
continue;
143 if (!method_exists($listener, $function_name)) {
146 $listener->$function_name($broadcaster, $vars);
182 if (!isset($this->_tmp[
'event_listeners'])) {
187 if (!isset($this->_tmp[
'event_listeners'][
'global'][$event_name]) && !isset($this->_tmp[
'event_listeners'][strtolower(get_class($broadcaster))][$event_name])) {
191 $listeners = Array();
192 $listener_codes = Array();
194 if (isset($this->_tmp[
'event_listeners'][
'global'][$event_name])) {
195 $listener_codes += $this->_tmp[
'event_listeners'][
'global'][$event_name];
197 if (isset($this->_tmp[
'event_listeners'][get_class_lower($broadcaster)][$event_name])) {
198 $listener_codes += $this->_tmp[
'event_listeners'][get_class_lower($broadcaster)][$event_name];
207 $possible_listeners_parents = array();
208 $possible_listeners_children = array();
210 foreach ($listener_codes as $listener_type_code => $options) {
212 if (empty($options[
'type_code'])) {
213 $options[
'type_code'] =
'';
215 if (empty($options[
'strict_type_code'])) {
216 $options[
'strict_type_code'] =
false;
218 if (empty($options[
'global'])) {
219 $options[
'global'] =
false;
222 $side_of_link = (isset($options[
'side_of_link']) && ($options[
'side_of_link'] ==
'minor')) ?
'major' :
'minor';
224 if ($options[
'global']) {
226 $assetids = $GLOBALS[
'SQ_SYSTEM']->am->getTypeAssetids($listener_type_code,
true);
227 }
else if ($options[
'indirect']) {
230 if (!($broadcaster instanceof asset))
return true;
231 if (!$broadcaster->id)
return;
234 if ($options[
'is_dependant'] && !$options[
'is_exclusive']) {
235 if (isset($found_listener)) {
240 if ($side_of_link ===
'minor') {
241 if (empty($possible_listeners_parents)) {
242 $possible_listeners_parents = $GLOBALS[
'SQ_SYSTEM']->am->getDependantParents($broadcaster->id);
244 $possible_listeners = $possible_listeners_parents;
246 if (empty($possible_listeners_children)) {
247 $possible_listeners_children = $GLOBALS[
'SQ_SYSTEM']->am->getDependantChildren($broadcaster->id);
249 $possible_listeners = $possible_listeners_children;
253 if (!isset($types)) {
254 for ($i=0; $i<count($possible_listeners); $i++) {
255 $asset = $GLOBALS[
'SQ_SYSTEM']->am->getAsset($possible_listeners[$i]);
256 $types[$possible_listeners[$i]] = $asset->type();
260 }
else if ($options[
'is_dependant'] || $options[
'is_exclusive'] || $options[
'type_code']) {
261 $assetids = $this->
_getDiscreteAssets($broadcaster->id, $listener_type_code, $side_of_link, $options);
269 $function =
'get'.(($options[
'side_of_link'] ==
'minor') ?
'Parents' :
'Children');
270 $assetids = $GLOBALS[
'SQ_SYSTEM']->am->$function($broadcaster->id, $listener_type_code, $options[
'strict_type_code']);
271 if (empty($assetids))
continue;
276 $links = $GLOBALS[
'SQ_SYSTEM']->am->getLinks($broadcaster->id, $options[
'link_type'], $listener_type_code,
true, $options[
'side_of_link'], $options[
'value'], $options[
'is_dependant'], $options[
'is_exclusive']);
277 if (empty($links))
continue;
280 foreach ($links as $link) {
281 $assetids[] = $link[$side_of_link.
'id'];
289 if (in_array($listener_type_code, $types)) {
290 foreach ($types as $assetid => $type_code) {
291 if ($type_code === $listener_type_code) {
292 $found_listener = TRUE;
293 $asset = $GLOBALS[
'SQ_SYSTEM']->am->getAsset($assetid);
294 if (is_null($asset))
continue;
295 $listeners[] = $asset;
300 foreach ($assetids as $assetid) {
301 $asset = $GLOBALS[
'SQ_SYSTEM']->am->getAsset($assetid);
302 if (is_null($asset))
continue;
303 $listeners[] = $asset;
309 if (empty($listeners))
return false;
311 $function =
'on'.$event_name;
312 for (reset($listeners); null !== ($key = key($listeners)); next($listeners)) {
313 $listener = $listeners[$key];
314 if (!method_exists($listener, $function)) {
315 trigger_localised_error(
'SYS0127', E_USER_WARNING, $function, $listener->type(), $asset->id);
318 $listener->$function($broadcaster, $vars);
319 $GLOBALS[
'SQ_SYSTEM']->am->forgetAsset($listener);
342 if (empty($assetid) || empty($type_code)) {
346 $sql =
'SELECT (t2.treeid || \'%\')
348 INNER JOIN sq_ast_lnk_tree t1 ON l1.linkid = t1.linkid,
350 INNER JOIN sq_ast_lnk_tree t2 ON l2.linkid = t2.linkid,
352 WHERE l1.'.$side_of_link.
'id = :assetid
353 AND SUBSTR(t1.treeid, 1, LENGTH(t2.treeid)) = t2.treeid
354 AND a.assetid=l2.'.$side_of_link.
'id
355 AND a.type_code= :type_code
356 ORDER BY t2.treeid DESC';
364 }
catch (Exception $e) {
365 throw new Exception(
'Unable to get Discrete Assets due to database error: '.$e->getMessage());
368 if (empty($result))
return Array();
371 foreach ($result as $treeid) {
372 $treeid_string .=
't2.treeid LIKE \''.$treeid.
'\' OR
';
374 $treeid_string = substr($treeid_string, 0, -4);
377 $sql = 'SELECT a.assetid, t2.treeid, a.type_code, l2.link_type, l2.is_dependant, l2.is_exclusive
379 INNER JOIN sq_ast_lnk_tree t1 ON l1.linkid = t1.linkid,
381 INNER JOIN sq_ast_lnk_tree t2 ON l2.linkid = t2.linkid,
383 WHERE l1.
'.$side_of_link.'id = :assetid
384 AND SUBSTR(t1.treeid, 1, LENGTH(t2.treeid)) = t2.treeid
385 AND a.assetid = l2.
'.$side_of_link.'id
386 AND (
'.$treeid_string.')
392 $query = MatrixDAL::preparePdoQuery($sql);
393 MatrixDAL::bindValueToPdo($query, 'assetid
', $assetid);
394 $result = MatrixDAL::executePdoAll($query);
395 } catch (Exception $e) {
396 throw new Exception('Unable to
get Discrete Assets due to database error:
'.$e->getMessage());
400 $start_treeid = true;
401 $popped_treeid = false;
403 for ($i = 0; $i < count($result); $i++) {
405 if (isset($result[$i+1]) && strpos($result[$i+1]['treeid
'], $result[$i]['treeid
']) === false) {
407 // the next treeid is not based on our treeid, so we will be starting a new branch
408 $start_treeid = true;
409 $popped_treeid = false;
413 if (!$popped_treeid) {
415 if (in_array($result[$i]['assetid
'], $assetids)) {
416 // we have already approved this asset to get notified
417 // so lets skip the rest of the branch
418 $popped_treeid = true;
422 if ($side_of_link == 'minor
') {
423 if (!isset($result[$i +1])) continue;
424 $test_info = $result[$i +1];
426 $test_info = $result[$i];
429 $valid_assetid = true;
430 if ($valid_assetid && $info['value
'] && $info['value
'] != $test_info['value
']) {
431 $valid_assetid = false;
433 if ($valid_assetid && !$test_info['is_dependant
'] && $info['is_dependant
']) {
434 $valid_assetid = false;
436 if ($valid_assetid && !$test_info['is_exclusive
'] && $info['is_exclusive
']) {
437 $valid_assetid = false;
439 if ($valid_assetid && $test_info['link_type
'] & $info['link_type
'] <= 0) {
440 $valid_assetid = false;
443 if ($start_treeid && $valid_assetid) {
444 $assetids[] = $result[$i]['assetid
'];
445 $start_treeid = false;
446 } else if (!$start_treeid && !$valid_assetid) {
447 // the last assetid we added failed the test, so get rid of it
448 array_pop($assetids);
449 $popped_treeid = true;
452 }//end if !$popped_treeid
454 }//end if not starting again next time around
460 }//end _getDiscreteAssets()
471 function writeStaticEventsCacheFile()
473 if (!isset($this->_tmp['event_listeners
']) || empty($this->_tmp['event_listeners
'])) {
477 $output = '<
'.'?php
'."\n".' $cached_event_listeners_array =
';
478 $output .= var_export($this->_tmp['event_listeners
'], true);
479 $output .= "\n?".'>
';
481 if (!string_to_file($output, SQ_DATA_PATH.'/
private/events/event_listeners.inc
')) {
484 unset($this->_tmp['event_listeners
']);
488 }//end writeStaticEventsCacheFile()
504 function installStaticEvents($listeners=Array(), $listener_type_code='', $recursive_call=false)
506 if (!is_array($listeners)|| empty($listeners)) {
509 if (!isset($this->_tmp['event_listeners
'])) {
510 $this->_loadCachedEventListeners();
513 $listener_name = Array();
514 foreach ($listeners as $index => $info) {
515 if (!isset($this->_tmp['event_listeners
'][$info['broadcast_type_code
']])) {
516 $this->_tmp['event_listeners
'][$info['broadcast_type_code
']] = Array();
518 if (!isset($this->_tmp['event_listeners
'][$info['broadcast_type_code
']][$info['event_name
']])) {
519 $this->_tmp['event_listeners
'][$info['broadcast_type_code
']][$info['event_name
']] = Array();
522 // if they have been lazy, do some cleanup
523 if (!isset($info['options
']['value
'])) {
524 $info['options
']['value
'] = '';
527 if (!is_array($info['options
'])) {
528 trigger_localised_error('SYS0143
', E_USER_WARNING, $listener_type_code, gettype($info['options
']));
532 $this->_tmp['event_listeners
'][$info['broadcast_type_code
']][$info['event_name
']][$listener_type_code] = $info['options
'];
534 // if the broadcast type code can be of multiple types, then we have to add some more
535 // entries for these in the array
536 if (!$info['broadcast_strict_type_code
'] && !$recursive_call) {
537 // only broadcast if the listener is installed, fail silently
538 if ($GLOBALS['SQ_SYSTEM
']->am->installed($info['broadcast_type_code
'])) {
539 $type_codes = $GLOBALS['SQ_SYSTEM
']->am->getTypeDescendants($info['broadcast_type_code
']);
540 if (empty($type_codes)) continue;
541 foreach ($type_codes as $type_code) {
542 $info['broadcast_type_code
'] = $type_code;
543 $this->installStaticEvents(Array($info), $listener_type_code, true);
547 $listener_name[] = $info['event_name
'];
550 // done with everything ?
551 // remove any of the listeners that might have been deleted from our asset
552 foreach ($this->_tmp['event_listeners
'] as $broadcast_type_code => $listener_info) {
553 foreach ($listener_info as $name => $asset_array) {
554 foreach ($asset_array as $asset_type => $info) {
555 if ($asset_type == $listener_type_code && !in_array($name, $listener_name)) {
556 unset($this->_tmp['event_listeners
'][$broadcast_type_code][$name][$asset_type]);
564 }//end installStaticEvents()
573 function _loadCachedEventListeners()
575 if (!file_exists(SQ_DATA_PATH.'/
private/events/event_listeners.inc
')) {
576 $this->_tmp['event_listeners
'] = Array();
579 require SQ_DATA_PATH.'/
private/events/event_listeners.inc
';
580 if (!isset($cached_event_listeners_array)) {
581 trigger_error('Failed loading
event listeners from SQ_DATA_PATH/
private/events/event_listeners.inc; Event listeners file may be corrupt
', E_USER_ERROR);
584 $this->_tmp['event_listeners
'] = $cached_event_listeners_array;
586 }//end _loadCachedEventListeners()