Counter.php #1

  • //
  • guest/
  • perforce_software/
  • chronicle/
  • main/
  • library/
  • P4/
  • Counter.php
  • View
  • Commits
  • Open Download .zip Download (8 KB)
<?php
/**
 * Abstracts operations against Perforce counters.
 * 
 * As counters are quite volatile, this class performs no caching. Reading a counter
 * always queries perforce for the current value and setting a new value immediately 
 * stores to perforce.
 *  
 * @copyright   2011 Perforce Software. All rights reserved.
 * @license     Please see LICENSE.txt in top-level folder of this distribution.
 * @version     <release>/<patch>
 */
class P4_Counter extends P4_ConnectedAbstract
{
    const       FETCH_MAXIMUM   = 'maximum';
    
    protected   $_id            = null;
    
    /**
     * Get the id of this counter.
     *
     * @return  null|string     the id of this entry.
     */
    public function getId()
    {
        return $this->_id;
    }

    /**
     * Set the id of this counter. Id must be in a valid format or null.
     *
     * @param   null|string     $id     the id of this entry - pass null to clear.
     * @return  P4_Counter              provides a fluent interface
     * @throws  InvalidArgumentException    if id does not pass validation.
     */
    public function setId($id)
    {
        if ($id !== null && !static::_isValidId($id)) {
            throw new InvalidArgumentException("Cannot set id. Id is invalid.");
        }

        $this->_id = $id;
        
        return $this;
    }
    
    /**
     * Determine if the given counter id exists.
     *
     * @param   string                      $id             the id to check for.
     * @param   P4_Connection_Interface     $connection     optional - a specific connection to use.
     * @return  bool    true if the given id matches an existing counter.
     */
    public static function exists($id, P4_Connection_Interface $connection = null)
    {
        // check id for valid format
        if (!static::_isValidId($id)) {
            return false;
        }

        $counters = static::fetchAll(array(), $connection);

        return in_array($id, $counters->invoke('getId'));
    }
    
    /**
     * Get the requested counter from Perforce.
     *
     * @param   string                  $id         the id of the counter to fetch.
     * @param   P4_Connection_Interface $connection optional - a specific connection to use.
     * @return  P4_Counter              instace of the requested counter.
     * @throws  InvalidArgumentException    if invalid id is given.
     */
    public static function fetch($id, P4_Connection_Interface $connection = null)
    {
        // ensure a valid id is provided.
        if (!static::_isValidId($id)) {
            throw new InvalidArgumentException("Must supply a valid id to fetch.");
        }

        // if no connection given, use default.
        $connection = $connection ?: static::getDefaultConnection();

        // ensure id exists.
        if (!static::exists($id, $connection)) {
            throw new P4_Exception(
                "Cannot fetch counter. Counter does not exist."
            );
        }

        // construct counter instance.
        $counter = new static($connection);
        $counter->setId($id);

        return $counter;
    }
    
    /**
     * Get all Counters from Perforce.
     *
     * @param   array   $options    optional - array of options to augment fetch behavior.
     *                              supported options are:
     *                                   FETCH_MAXIMUM - set to integer value to limit to the first
     *                                                   'max' number of entries.
     *                                                   *Note: Limits imposed client side.
     *
     * @param   P4_Connection_Interface $connection  optional - a specific connection to use.
     * @return  P4_Iterator         all counters matching passed option(s).
     */
    public static function fetchAll($options = array(), P4_Connection_Interface $connection = null)
    {
        // if no connection given, use default.
        $connection = $connection ?: static::getDefaultConnection();

        // fetch all counters.
        $result = $connection->run('counters');

        // convert result data to counter objects.
        $counters = new P4_Iterator;
        $max      = array_key_exists(static::FETCH_MAXIMUM, $options) ? (int)$options[static::FETCH_MAXIMUM] : 0;
  
        foreach ($result->getData() as $data) {
            // populate a counter and add it to the iterator
            $counter = new static($connection);
            $counter->setId($data['counter']);

            $counters[] = $counter;

            // stop looping if we reach 'FETCH_MAXIMUM'
            if ($max > 0 && count($counters) == $max) {
                break;
            }
        }

        return $counters;
    }

    /**
     * Delete this counter entry.
     *
     * @param   bool    $force      optional - force delete the counter.
     * @return  P4_Counter          provides a fluent interface
     * @throws  P4_Exception        if no id has been set.
     */
    public function delete($force = false)
    {
        $id = $this->getId();
        if ($id === null) {
            throw new P4_Exception("Cannot delete. No id has been set.");
        }

        // ensure id exists.
        $connection = $this->getConnection();
        if (!static::exists($id, $connection)) {
            throw new P4_Exception(
                "Cannot delete counter. Counter does not exist."
            );
        }

        // setup counter command args.
        $params   = $force ? array('-f') : array();
        $params[] = "-d";
        $params[] = $id;

        $result = $connection->run('counter', $params);

        return $this;
    }

    /**
     * Get counter's value. There is no caching, the value is always read from
     * perforce.
     *
     * @return  mixed   the value of the counter.
     */
    public function getValue()
    {
        $id = $this->getId();
        $connection = $this->getConnection();

        // if the ID is not set or the ID doesn't exist in perforce, return null
        if ($id === null || !static::exists($id, $connection)) {
            return null;
        }
        
        $result = $connection->run('counter', $id);
        $data = $result->getData();

        return $data[0]['value'];
    }

    /**
     * Set counters value. The value will be immediately written to perforce.
     *
     * @param   mixed   $value  the value to set in the counter.
     * @param   bool    $force  optional - force set the counter.
     * @return  P4_Counter      provides a fluent interface
     * @throws  P4_Exception    if no Id has been set
     */
    public function setValue($value, $force = false)
    {
        $id = $this->getId();
        if ($id === null) {
            throw new P4_Exception("Cannot set value. No id has been set.");
        }
        
        // setup counter command args.
        $params   = $force ? array('-f') : array();
        $params[] = $id;
        $params[] = $value;

        $this->getConnection()->run('counter', $params);

        return $this;
    }
    
    /**
     * Increment counters value by 1. If the counter doesn't exist it will be
     * created and assigned the value 1.
     * The update is carried out atomically by the server.
     *
     * @return  string          The counters new value
     * @throws  P4_Exception    If the current value is non-numeric
     */
    public function increment()
    {
        $id = $this->getId();
        if ($id === null) {
            throw new P4_Exception("Cannot increment value. No id has been set.");
        }

        $result = $this->getConnection()->run('counter', array('-i', $id));
        $data   = $result->getData();

        return $data[0]['value'];
    }

    /**
     * Check if the given id is in a valid format.
     *
     * @param   string      $id     the id to check
     * @return  bool        true if id is valid, false otherwise
     */
    protected static function _isValidId($id)
    {
        $validator = new P4_Validate_CounterName;
        return $validator->isValid($id);
    }
}
# Change User Description Committed
#1 16170 perforce_software Move Chronicle files to follow new path scheme for branching.
//guest/perforce_software/chronicle/library/P4/Counter.php
#1 8972 Matt Attaway Initial add of the Chronicle source code