Apache Zeta Components Manual :: File Source for signal_collection.php

Source for file signal_collection.php

Documentation is available at signal_collection.php

  1. <?php
  2. /**
  3.  *
  4.  * Licensed to the Apache Software Foundation (ASF) under one
  5.  * or more contributor license agreements.  See the NOTICE file
  6.  * distributed with this work for additional information
  7.  * regarding copyright ownership.  The ASF licenses this file
  8.  * to you under the Apache License, Version 2.0 (the
  9.  * "License"); you may not use this file except in compliance
  10.  * with the License.  You may obtain a copy of the License at
  11.  * 
  12.  *   http://www.apache.org/licenses/LICENSE-2.0
  13.  * 
  14.  * Unless required by applicable law or agreed to in writing,
  15.  * software distributed under the License is distributed on an
  16.  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  17.  * KIND, either express or implied.  See the License for the
  18.  * specific language governing permissions and limitations
  19.  * under the License.
  20.  *
  21.  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
  22.  * @version //autogentag//
  23.  * @filesource
  24.  * @package SignalSlot
  25.  */
  26.  
  27. /**
  28.  * ezcSignalCollection implements a mechanism for inter and intra object communication.
  29.  *
  30.  * See the tutorial for extensive examples on how to use this class.
  31.  *
  32.  * @property bool $signalsBlocked     If set to true emits will not cause any slots to be called.
  33.  *
  34.  * @property-read string $identifier  The identifier of this signal collection.
  35.  *                                     Usually the class name of the object containing the collection.
  36.  *
  37.  * @version //autogen//
  38.  * @mainclass
  39.  * @package SignalSlot
  40.  */
  41. {
  42.     /**
  43.      * Holds the properties of this class.
  44.      *
  45.      * @var array(string=>mixed) 
  46.      */
  47.     private $properties array();
  48.  
  49.     /**
  50.      * Holds the connections for this object with the default priority.
  51.      *
  52.      * @var array(string=>array(callback)) 
  53.      */
  54.     private $defaultConnections array();
  55.  
  56.     /**
  57.      * Holds the priority connections for this object.
  58.      *
  59.      * @var array(string=>array(int=>array(callback))) 
  60.      */
  61.     private $priorityConnections array();
  62.  
  63.     /**
  64.      * If set this object will be used to fetch static connections instead of ezcSignalStaticConnections.
  65.      *
  66.      * @var ezcSignalStaticConnectionsBase 
  67.      */
  68.     private static $staticConnectionsHolder null;
  69.  
  70.     /**
  71.      * Holds the options for this signal collection
  72.      *
  73.      * @var ezcSignalCollectionOptions 
  74.      */
  75.     private $options;
  76.  
  77.     /**
  78.      * Constructs a new signal collection with the identifier $identifier.
  79.      *
  80.      * The identifier can be used to connect to signals statically using
  81.      * ezcSignalStaticConnections.
  82.      *
  83.      * Through the associative array options you can specify the options for this class in the
  84.      * format array( 'optionName' => value ). See the documentation of ezcSignalCollectionOptions
  85.      * for information on the available options.
  86.      *
  87.      * @param string $identifier 
  88.      * @param array $options 
  89.      */
  90.     public function __construct$identifier "default"array $options array() )
  91.     {
  92.         $this->options new ezcSignalCollectionOptions$options );
  93.         $this->properties['identifier'$identifier;
  94.         $this->signalsBlocked false;
  95.     }
  96.  
  97.     /**
  98.      * If set, $holder will be used to fetch static connections instead of ezcSignalStaticConnections.
  99.      *
  100.      * @param ezcSignalStaticConnectionsBase $holder 
  101.      */
  102.     public static function setStaticConnectionsHolderezcSignalStaticConnectionsBase $holder )
  103.     {
  104.         self::$staticConnectionsHolder $holder;
  105.     }
  106.  
  107.     /**
  108.      * Returns the current provider of static connections or null if there is none.
  109.      *
  110.      * @return ezcSignalStaticConnectionsBase 
  111.      */
  112.     public static function getStaticConnectionsHolder()
  113.     {
  114.         return self::$staticConnectionsHolder;
  115.     }
  116.  
  117.    /**
  118.      * Sets the property $name to $value.
  119.      *
  120.      * @throws ezcBasePropertyNotFoundException if the property does not exist.
  121.      * @param string $name 
  122.      * @param mixed $value 
  123.      * @return void 
  124.      */
  125.     public function __set$name$value )
  126.     {
  127.         switch $name )
  128.         {
  129.             case 'signalsBlocked':
  130.                 $this->properties[$name$value;
  131.                 break;
  132.             case 'identifier':
  133.                 throw new ezcBasePropertyPermissionException$nameezcBasePropertyPermissionException::READ );
  134.                 break;
  135.             case 'options':
  136.                 if !$value instanceof ezcSignalCollectionOptions ) )
  137.                 {
  138.                     throw new ezcBaseValueException'options'$value'instanceof ezcSignalCollectionOptions' );
  139.                 }
  140.                 $this->options $value;
  141.                 break;
  142.             default:
  143.                 throw new ezcBasePropertyNotFoundException$name );
  144.                 break;
  145.         }
  146.  
  147.     }
  148.  
  149.     /**
  150.      * Returns the property $name.
  151.      *
  152.      * @throws ezcBasePropertyNotFoundException if the property does not exist.
  153.      * @param string $name 
  154.      * @return mixed 
  155.      */
  156.     public function __get$name )
  157.     {
  158.         switch $name )
  159.         {
  160.             case 'signalsBlocked':
  161.             case 'identifier':
  162.                 return $this->properties[$name];
  163.                 break;
  164.             case 'options':
  165.                 return $this->options;
  166.                 break;
  167.             default:
  168.                 throw new ezcBasePropertyNotFoundException$name );
  169.                 break;
  170.         }
  171.     }
  172.  
  173.     /**
  174.      * Sets the options of this class.
  175.      *
  176.      * @param ezcSignalCollectionOptions|array(string=>value)$options The options to set
  177.      *         either as an associative array in the form array(optionName=>value) or a
  178.      *         ezcSignalCollectionOptions object.
  179.      *
  180.      * @throws ezcBaseSettingNotFoundException
  181.      *          If you tried to set a non-existent option value.
  182.      * @throws ezcBaseSettingValueException
  183.      *          If the value is not valid for the desired option.
  184.      * @throws ezcBaseValueException
  185.      *          If you submit neither an array nor an instance of
  186.      *          ezcSignalCollectionOptions.
  187.      */
  188.     public function setOptions$options )
  189.     {
  190.         if $options instanceof ezcSignalCollectionOptions )
  191.         {
  192.             $this->options $options;
  193.         }
  194.         else if is_array$options ) )
  195.         {
  196.             $this->options new ezcSignalCollectionOptions$options );
  197.         }
  198.         else
  199.         {
  200.             throw new ezcBaseValueException"options"$options'array or instance of ezcSignalCollectionOptions' );
  201.         }
  202.     }
  203.  
  204.     /**
  205.      * Returns the options for this class.
  206.      *
  207.      * @return ezcSignalCollectionOptions 
  208.      */
  209.     public function getOptions()
  210.     {
  211.         return $this->options;
  212.     }
  213.  
  214.     /**
  215.      * Returns true if any slots have been connected to the signal $signal.
  216.      * False is returned if no slots have been connected to the $signal.
  217.      *
  218.      * Note: Emitting the signal $signal may still not call any slots if
  219.      * the property signalsBlocked has been set.
  220.      *
  221.      * @throws ezcSignalSlotException if the signals options has been set and $signal is not in the list of signals.
  222.      * @param string $signal 
  223.      * @return bool 
  224.      */
  225.     public function isConnected$signal )
  226.     {
  227.         // if the the signals option is set we must check if the signal exists
  228.         if $this->options->signals != null && !in_array$signal$this->options->signals ) )
  229.         {
  230.             throw new ezcSignalSlotException"No such signal {$signal});
  231.         }
  232.  
  233.         // static connections
  234.         if self::$staticConnectionsHolder == null // custom static connections class
  235.         {
  236.             if countezcSignalStaticConnections::getInstance()->getConnections$this->identifier$signal ) ) )
  237.             {
  238.                 return true;
  239.             }
  240.         }
  241.         else if countself::$staticConnectionsHolder->getConnections$this->identifier$signal ) ) )
  242.         {
  243.             return true;
  244.         }
  245.         // default connections
  246.         if isset$this->defaultConnections[$signal&& count$this->defaultConnections[$signal)
  247.         {
  248.             return true;
  249.         }
  250.  
  251.         // priority connections
  252.         if isset$this->priorityConnections[$signal&& count$this->priorityConnections[$signal)
  253.         {
  254.             return true;
  255.         }
  256.  
  257.         return false;
  258.     }
  259.  
  260.     /**
  261.      * Emits the signal with the name $signal
  262.      *
  263.      * Any additional parameters are sent as parameters to the slot.
  264.      *
  265.      * @throws ezcSignalSlotException if the signals options has been set and $signal is not in the list of signals.
  266.      * @param string $signal 
  267.      * @param ... $signal_parameters 
  268.      * @return void 
  269.      */
  270.     public function emit$signal )
  271.     {
  272.         // if the the signals option is set we must check if the signal exists
  273.         if $this->options->signals != null && !in_array$signal$this->options->signals ) )
  274.         {
  275.             throw new ezcSignalSlotException"No such signal {$signal});
  276.         }
  277.  
  278.         if $this->signalsBlocked )
  279.         {
  280.             return;
  281.         }
  282.  
  283.         // prepare the parameters
  284.         $parameters array_slicefunc_get_args());
  285.  
  286.         // check if there are any static connections
  287.         $priStaticConnections array();
  288.         if self::$staticConnectionsHolder == null )
  289.         {
  290.             $priStaticConnections ezcSignalStaticConnections::getInstance()->getConnections$this->identifier$signal );
  291.         }
  292.         else
  293.         {
  294.             $priStaticConnections self::$staticConnectionsHolder->getConnections$this->identifier$signal );
  295.         }
  296.  
  297.         $hasPriStaticConnections false;
  298.         if count$priStaticConnections isset$priStaticConnections[10000) )
  299.         {
  300.             $hasPriStaticConnections true;
  301.         }
  302.  
  303.         // fast algorithm if there are no prioritized slots
  304.         if isset$this->priorityConnections[$signal=== false && !$hasPriStaticConnections )
  305.         {
  306.             if isset$this->defaultConnections[$signal) )
  307.             {
  308.                 foreach $this->defaultConnections[$signalas $callback )
  309.                 {
  310.                     call_user_func_array$callback$parameters );
  311.                 }
  312.             }
  313.             if isset$priStaticConnections[1000) )
  314.             {
  315.                 foreach $priStaticConnections[1000as $callback )
  316.                 {
  317.                     call_user_func_array$callback$parameters );
  318.                 }
  319.             }
  320.         }
  321.         else // default algorithm
  322.         {
  323.             // order slots
  324.             $defaultKeys array();
  325.             if isset$this->priorityConnections[$signal) )
  326.             {
  327.                 $defaultKeys array_keys$this->priorityConnections[$signal);
  328.             }
  329.             $staticKeys array_keys$priStaticConnections );
  330.  
  331.             $allKeys array_uniquearray_merge$defaultKeys$staticKeysarray1000 /*default*/ ) );
  332.             sort$allKeysSORT_NUMERIC );
  333.  
  334.             foreach $allKeys as $key // call all slots in the correct order
  335.             {
  336.                 if $key == 1000 && isset$this->defaultConnections[$signal) )
  337.                 {
  338.                     foreach $this->defaultConnections[$signalas $callback )
  339.                     {
  340.                         call_user_func_array$callback$parameters );
  341.                     }
  342.                 }
  343.                 if isset$this->priorityConnections[$signal][$key) )
  344.                 {
  345.                     foreach $this->priorityConnections[$signal][$keyas $callback )
  346.                     {
  347.                         call_user_func_array$callback$parameters );
  348.                     }
  349.                 }
  350.                 if isset$priStaticConnections[$key) )
  351.                 {
  352.                     foreach $priStaticConnections[$keyas $callback )
  353.                     {
  354.                         call_user_func_array$callback$parameters );
  355.                     }
  356.                 }
  357.             }
  358.         }
  359.     }
  360.  
  361.     /**
  362.      * Connects the signal $signal to the slot $slot.
  363.      *
  364.      * To control the order in which slots are called you can set a priority
  365.      * from 1 - 65 536. The lower the number the higher the priority. The default
  366.      * priority is 1000.
  367.      * Slots with the same priority may be called with in any order.
  368.      *
  369.      * A slot will be called once for every time it is connected. It is possible
  370.      * to connect a slot more than once.
  371.      *
  372.      * See the PHP documentation for examples on the callback type.
  373.      * http://php.net/callback.
  374.      *
  375.      * We recommend avoiding excessive usage of the $priority parameter
  376.      * since it makes it much harder to track how your program works.
  377.      *
  378.      * @throws ezcSignalSlotException if the signals options has been set and $signal is not in the list of signals.
  379.      * @param string $signal 
  380.      * @param callback $slot 
  381.      * @param int $priority 
  382.      * @return void 
  383.      */
  384.     public function connect$signal$slot$priority 1000 )
  385.     {
  386.         // if the the signals option is set we must check if the signal exists
  387.         if $this->options->signals != null && !in_array$signal$this->options->signals ) )
  388.         {
  389.             throw new ezcSignalSlotException"No such signal {$signal});
  390.         }
  391.  
  392.         if $priority === 1000 // default
  393.         {
  394.             $this->defaultConnections[$signal][$slot;
  395.         }
  396.         else
  397.         {
  398.             $this->priorityConnections[$signal][$priority][$slot;
  399.             sort$this->priorityConnections[$signal][$priority]SORT_NUMERIC );
  400.         }
  401.     }
  402.  
  403.     /**
  404.      * Disconnects the $slot from the $signal.
  405.      *
  406.      * If the priority is given it will try to disconnect a slot with that priority.
  407.      * If no such slot is found no slot will be disconnected.
  408.      *
  409.      * If no priority is given it will disconnect the matching slot with the lowest priority.
  410.      *
  411.      * @throws ezcSignalSlotException if the signals options has been set and $signal is not in the list of signals.
  412.      * @param string $signal 
  413.      * @param callback $slot 
  414.      * @param int $priority 
  415.      * @return void 
  416.      */
  417.     public function disconnect$signal$slot$priority null )
  418.     {
  419.         // if the the signals option is set we must check if the signal exists
  420.         if $this->options->signals != null && !in_array$signal$this->options->signals ) )
  421.         {
  422.             throw new ezcSignalSlotException"No such signal {$signal});
  423.         }
  424.  
  425.         if $priority === null // delete first found, searched from back
  426.         {
  427.             $priorityKeys array();
  428.             if isset$this->priorityConnections[$signal) )
  429.             {
  430.                 $priorityKeys array_keys$this->priorityConnections[$signal);
  431.             }
  432.  
  433.             $allPriorities array_uniquearray_merge$priorityKeysarray1000 /*default*/ ) );
  434.             rsort$allPrioritiesSORT_NUMERIC );
  435.             foreach $allPriorities as $priority )
  436.             {
  437.                 if $priority === 1000 )
  438.                 {
  439.                     if isset$this->defaultConnections[$signal) )
  440.                     {
  441.                         foreach $this->defaultConnections[$signalas $key => $callback )
  442.                         {
  443.                             if ezcSignalCallbackComparer::compareCallbacks$slot$callback ) )
  444.                             {
  445.                                 unset$this->defaultConnections[$signal][$key);
  446.                                 return;
  447.                             }
  448.                         }
  449.                     }
  450.                 }
  451.                 else
  452.                 {
  453.                     if isset$this->priorityConnections[$signal&&
  454.                         isset$this->priorityConnections[$signal][$priority) )
  455.                     {
  456.                         foreach $this->priorityConnections[$signal][$priorityas $key => $callback)
  457.                         {
  458.                             if ezcSignalCallbackComparer::compareCallbacks$slot$callback ) )
  459.                             {
  460.                                 unset$this->priorityConnections[$signal][$priority][$key);
  461.                                 // if the priority is empty now it should be unset
  462.                                 if count$this->priorityConnections[$signal][$priority== )
  463.                                 {
  464.                                     unset$this->priorityConnections[$signal][$priority);
  465.                                 }
  466.                                 return;
  467.                             }
  468.                         }
  469.                     }
  470.                 }
  471.             }
  472.  
  473.         }
  474.         else if $priority === 1000 // only delete from default
  475.         {
  476.             if isset$this->defaultConnections[$signal) )
  477.             {
  478.                 foreach $this->defaultConnections[$signalas $key => $callback )
  479.                 {
  480.                     if ezcSignalCallbackComparer::compareCallbacks$slot$callback ) )
  481.                     {
  482.                         unset$this->defaultConnections[$signal][$key);
  483.                         return;
  484.                     }
  485.                 }
  486.             }
  487.         }
  488.         else // delete from priority connectinos
  489.         {
  490.             if isset$this->priorityConnections[$signal&&
  491.                 isset$this->priorityConnections[$signal][$priority) )
  492.             {
  493.                 foreach $this->priorityConnections[$signal][$priorityas $key => $callback )
  494.                 {
  495.                     if ezcSignalCallbackComparer::compareCallbacks$slot$callback ) )
  496.                     {
  497.                         unset$this->priorityConnections[$signal][$priority][$key);
  498.                         // if the priority is empty now it should be unset
  499.                         if count$this->priorityConnections[$signal][$priority== )
  500.                         {
  501.                             unset$this->priorityConnections[$signal][$priority);
  502.                         }
  503.                         return;
  504.                     }
  505.                 }
  506.             }
  507.         }
  508.     }
  509. }
  510. ?>
Documentation generated by phpDocumentor 1.4.3