Perforce Chronicle 2012.2/486814
API Documentation

P4_User Class Reference

Abstracts operations against Perforce users. More...

Inheritance diagram for P4_User:
P4_Spec_PluralAbstract P4_SpecAbstract P4_ModelAbstract P4_ConnectedAbstract P4_ModelInterface P4_ConnectedInterface

List of all members.

Public Member Functions

 addToGroup ($group)
 Add this user to the named group.
 delete ()
 Remove this user from Perforce.
 getAccessDateTime ()
 Get the last access time for this user spec.
 getClients ()
 Get an Iterator of all the Clients this user owns.
 getEmail ()
 Get the user's email address.
 getFullName ()
 Get the user's full name.
 getGroups ()
 Get the names of groups that this user belongs to.
 getJobView ()
 Get the user's job view (selects jobs for inclusion during changelist creation).
 getPassword ()
 Get the in-memory password (if one is set).
 getReviews ()
 Get the reviews for this client (depot paths to notify user of changes to).
 getUpdateDateTime ()
 Get the last update time for this user spec.
 isPassword ($password)
 Test if the given password is correct for this user.
 save ()
 Save this user to Perforce.
 setEmail ($email)
 Set the user's email address.
 setFullName ($name)
 Set the user's full name.
 setJobView ($jobView)
 Set the user's job view (selects jobs for inclusion during changelist creation).
 setPassword ($newPassword, $oldPassword=null)
 Set the user's password to the given password.
 setReviews ($reviews)
 Set the reviews for this user (depot paths to notify user of changes to).

Static Public Member Functions

static exists ($id, P4_Connection_Interface $connection=null)
 Determine if the given user id exists.
static fetchAll ($options=array(), P4_Connection_Interface $connection=null)
 Get all users from Perforce.
static isAutoUserCreationEnabled (P4_Connection_Interface $connection=null)
 Check if automatic user creation is enabled.

Public Attributes

const FETCH_BY_NAME = 'name'

Protected Member Functions

 _setPassword ($newPassword, $oldPassword=null, P4_Connection_Interface $connection=null)
 Immediately set the user's password to the given password.

Static Protected Member Functions

static _fromSpecListEntry ($listEntry, $flags, P4_Connection_Interface $connection)
 Given a spec entry from spec list output (p4 users), produce an instance of this spec with field values set where possible.
static _getFetchAllFlags ($options)
 Produce set of flags for the spec list command, given fetch all options array.
static _isValidId ($id)
 Check if the given id is in a valid format for user specs.

Static Protected Attributes

static $_accessors
static $_idField = 'User'
static $_mutators
static $_specType = 'user'

Detailed Description

Abstracts operations against Perforce users.

The P4 User class differs from the 'user' spec definition in that it does not have a password field. This is because the password does not behave like other fields. To change a user's password, use the setPassword() function. To test if a given string matches a user's password, use the isPassword() method. It is not possible to get a user's password.

Copyright:
2011-2012 Perforce Software. All rights reserved
License:
Please see LICENSE.txt in top-level folder of this distribution.
Version:
2012.2/486814

Member Function Documentation

static P4_User::_fromSpecListEntry ( listEntry,
flags,
P4_Connection_Interface connection 
) [static, protected]

Given a spec entry from spec list output (p4 users), produce an instance of this spec with field values set where possible.

Parameters:
array$listEntrya single spec entry from spec list output.
array$flagsthe flags that were used for this 'fetchAll' run.
P4_Connection_Interface$connectiona specific connection to use.
Returns:
P4_User a (partially) populated instance of this spec class.

Reimplemented from P4_Spec_PluralAbstract.

    {
        // update/access time are return as longs. Unset to avoid figuring out timezone
        // for a proper conversion.
        unset($listEntry['update']);
        unset($listEntry['access']);

        return parent::_fromSpecListEntry($listEntry, $flags, $connection);
    }
static P4_User::_getFetchAllFlags ( options) [static, protected]

Produce set of flags for the spec list command, given fetch all options array.

Extends parent to add support for filter option.

Parameters:
array$optionsarray of options to augment fetch behavior. see fetchAll for documented options.
Returns:
array set of flags suitable for passing to spec list command.

Reimplemented from P4_Spec_PluralAbstract.

    {
        $flags = parent::_getFetchAllFlags($options);

        if (isset($options[static::FETCH_BY_NAME])) {
            $name = $options[static::FETCH_BY_NAME];

            if ((!is_array($name) || !count($name)) && (!is_string($name) || trim($name) === "")) {
                throw new InvalidArgumentException(
                    'Filter by Name expects a non-empty string or an non-empty array as input'
                );
            }

            // if array is given, ensure values are non-empty strings
            if (is_array($name)) {
                $names    = $name;
                $filtered = array_filter($names,    'is_string');
                $filtered = array_filter($filtered, 'trim');

                if (count($names) !== count($filtered)) {
                    throw new InvalidArgumentException(
                        'Filter by Name expects all names in the input array to be non-empty strings'
                    );
                }
                $flags = array_merge($flags, $names);
            } else {
                $flags[] = $name;
            }
        }

        return $flags;
    }
static P4_User::_isValidId ( id) [static, protected]

Check if the given id is in a valid format for user specs.

Parameters:
string$idthe id to check
Returns:
bool true if id is valid, false otherwise

Reimplemented from P4_Spec_PluralAbstract.

    {
        $validator = new P4_Validate_UserName;
        return $validator->isValid($id);
    }
P4_User::_setPassword ( newPassword,
oldPassword = null,
P4_Connection_Interface connection = null 
) [protected]

Immediately set the user's password to the given password.

If the current password is given, it will be validated.

Parameters:
string$newPasswordthe new password.
string$oldPasswordoptional - existing password.
P4_Connection_Interface$connectionoptional - a specific connection to use.
Returns:
P4_User provides fluent interface.
Exceptions:
P4_Exceptionif the password can't be set.
    {
        $input = array();

        // if caller supplied an old password, prepend it to input array.
        if ($oldPassword) {
            $input[] = $oldPassword;
        }

        // always confirm old password
        $input[] = $newPassword;
        $input[] = $newPassword;

        // if no connection given, use default.
        $connection = $connection ?: $this->getConnection();

        // if not connected as this user, supply user id.
        $flags = array();
        if ($connection->getUser() !== $this->getId()) {
            $flags[] = $this->getId();
        }

        // attempt to set password.
        $result = $connection->run("password", $flags, $input);

        // change connection credentials if password for connected user has been changed
        // if we don't do this automatically, subsequent commands will fail when using
        // the command-line connection, but would succeed using the P4PHP extension.
        if ($connection->getUser() === $this->getId()) {
            $connection->setPassword($newPassword);
            if ($connection->getTicket()) {
                $connection->login();
            }
        }

        return $this;
    }
P4_User::addToGroup ( group)

Add this user to the named group.

Parameters:
string$groupthe name of the group to add the user to.
Returns:
P4_User provides fluent interface.
    {
        $group = P4_Group::fetch($group, $this->getConnection())
            ->addUser($this->getId())
            ->save();

        return $this;
    }
P4_User::delete ( )

Remove this user from Perforce.

Returns:
P4_SpecAbstract provides a fluent interface
Exceptions:
P4_Spec_Exceptionif no id has been set.
    {
        if ($this->getId() === null) {
            throw new P4_Spec_Exception("Cannot delete. No id has been set.");
        }

        // initialize command flags with first arg.
        $flags = array("-d");

        // if we are connected with super user privileges, add in the -f flag.
        // otherwise, if not connected as this user, connect as this user.
        $connection = $this->getConnection();
        if ($connection->isSuperUser()) {
            $flags[] = "-f";
        } else if ($connection->getUser() != $this->getId()) {
            $connection = P4_Connection::factory(
                $connection->getPort(),
                $this->getId()
            );
        }

        // issue delete user command.
        $flags[] = $this->getId();
        $result = $connection->run(static::_getSpecType(), $flags);

        // should re-populate.
        $this->_deferPopulate(true);

        return $this;
    }
static P4_User::exists ( id,
P4_Connection_Interface connection = null 
) [static]

Determine if the given user id exists.

Parameters:
string$idthe id to check for.
P4_Connection_Interface$connectionoptional - a specific connection to use.
Returns:
bool true if the given id matches an existing user.

Reimplemented from P4_Spec_PluralAbstract.

    {
        // check id for valid format
        if (!static::_isValidId($id)) {
            return false;
        }

        $users = static::fetchAll(
            array(
                static::FETCH_BY_NAME => $id,
                static::FETCH_MAXIMUM => 1
            ),
            $connection
        );

        return (bool) count($users);
    }
static P4_User::fetchAll ( options = array(),
P4_Connection_Interface connection = null 
) [static]

Get all users from Perforce.

Adds filtering option.

Parameters:
array$optionsoptional - 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. FETCH_BY_NAME - set to user name pattern (e.g. 'jdo*'), can be a single string or array of strings.

Parameters:
P4_Connection_Interface$connectionoptional - a specific connection to use.
Returns:
P4_Model_Iterator all records of this type.

Reimplemented from P4_Spec_PluralAbstract.

    {
        $connection = $connection ?: static::getDefaultConnection();

        // if not fetching by name, defer to parent
        if (!isset($options[static::FETCH_BY_NAME])) {
            return parent::fetchAll($options, $connection);
        }

        // get fetch max option and uset it from the options as we handle it manually
        $max = isset($options[static::FETCH_MAXIMUM]) ? $options[static::FETCH_MAXIMUM] : 0;
        unset($options[static::FETCH_MAXIMUM]);

        // sort names before fetching users from the server, so if max is set
        // we get the first max users (according to case-sensitivity of server)
        $names = (array) $options[static::FETCH_BY_NAME];
        if ($connection->isCaseSensitive()) {
            sort($names);
        } else {
            usort($names, 'strcasecmp');
        }        

        // fetch users in several (as few as possible) runs as
        // there is a potential to exceed the arg-max on this command
        $users = new P4_Model_Iterator;
        foreach ($connection->batchArgs($names) as $batch) {
            $options[static::FETCH_BY_NAME] = $batch;
            foreach (parent::fetchAll($options, $connection) as $user) {
                $users[] = $user;

                // exit loop if we've reached the max limit
                if ($max && $users->count() == $max) {
                    break(2);
                }
            }
        }

        return $users;
    }
P4_User::getAccessDateTime ( )

Get the last access time for this user spec.

This value is read only, no setAccessTime function is provided.

If this is a brand new spec, null will be returned in lieu of a time.

Returns:
string|null Date/Time of last access, formatted "2009/11/23 12:57:06" or null
    {
        return $this->_getValue('Access');
    }
P4_User::getClients ( )

Get an Iterator of all the Clients this user owns.

Returns:
P4_Model_Iterator Iterator of P4_Clients owned by current user
Exceptions:
P4_Spec_ExceptionIf no ID is set for this user
    {
        if (!static::_isValidId($this->getId())) {
            throw new P4_Spec_Exception("Cannot get clients. No user id has been set.");
        }

        return P4_Client::fetchAll(
            array(P4_Client::FETCH_BY_OWNER => $this->getId()),
            $this->getConnection()
        );
    }
P4_User::getEmail ( )

Get the user's email address.

Returns:
string|null the user's email address.
    {
        return $this->_getValue('Email');
    }
P4_User::getFullName ( )

Get the user's full name.

Returns:
string|null the user's full name.
    {
        return $this->_getValue('FullName');
    }
P4_User::getGroups ( )

Get the names of groups that this user belongs to.

Returns:
P4_Model_Iterator Iterator of P4_Groups this user belongs to.
    {
        if (!static::_isValidId($this->getId())) {
            throw new P4_Spec_Exception("Cannot get groups. No user id has been set.");
        }

        return P4_Group::fetchAll(
            array(P4_Group::FETCH_BY_MEMBER => $this->getId(), P4_Group::FETCH_INDIRECT),
            $this->getConnection()
        );
    }
P4_User::getJobView ( )

Get the user's job view (selects jobs for inclusion during changelist creation).

Returns:
string|null the user's job view.
    {
        return $this->_getValue('JobView');
    }
P4_User::getPassword ( )

Get the in-memory password (if one is set).

Returns:
string|null the in-memory password.
    {
        $password = $this->_getValue('Password');
        return is_array($password) ? $password[0] : null;
    }
P4_User::getReviews ( )

Get the reviews for this client (depot paths to notify user of changes to).

Returns:
array list of filespec strings.
    {
        return $this->_getValue('Reviews') ?: array();
    }
P4_User::getUpdateDateTime ( )

Get the last update time for this user spec.

This value is read only, no setUpdateTime function is provided.

If this is a brand new spec, null will be returned in lieu of a time.

Returns:
string|null Date/Time of last update, formatted "2009/11/23 12:57:06" or null
    {
        return $this->_getValue('Update');
    }
static P4_User::isAutoUserCreationEnabled ( P4_Connection_Interface connection = null) [static]

Check if automatic user creation is enabled.

Parameters:
P4_Connection_Interface$connectionoptional - a specific connection to use.
Returns:
bool true if auto user creation is enabled, false otherwise.
Exceptions:
P4_Exceptionif we exceed the maximum number of unlikely usernames
    {
        // if no connection given, use default.
        $connection = $connection ?: static::getDefaultConnection();

        $port = $connection->getPort();

        // limit the number of 'unlikely' username lookups to 3.
        $maxLookups = 3;
        for ($i = 0; $i < $maxLookups; $i++) {
            // generate an unlikely user name.
            $username = md5(mt_rand());

            // try to run p4 users as the unlikely user
            // (perforce won't create an account for this lookup).
            try {
                $connection = P4_Connection::factory($port, $username);
                $result = $connection->run('users', $username);
            } catch (P4_Connection_CommandException $e) {
                return false;
            }

            // ensure unlikely user doesn't exist.
            if (!$result->getData()) {
                return true;
            }
        }

        throw new P4_Exception(
            "Failed to determine if auto user creation is enabled."
          . "Exceeded the maximum of $maxLookups 'unlikely' username lookups."
        );
    }
P4_User::isPassword ( password)

Test if the given password is correct for this user.

Parameters:
string$passwordthe password to test.
Returns:
bool true if the password is correct, false otherwise.
    {
        $p4 = P4_Connection::factory(
            $this->getConnection()->getPort(),
            $this->getId(),
            null,
            $password
        );

        try {
            $p4->login();
            return true;
        } catch (P4_Connection_LoginException $e) {
            return false;
        }
    }
P4_User::save ( )

Save this user to Perforce.

This will not save changes to the password field. Passwords must be set via setPassword().

Returns:
P4_SpecAbstract provides a fluent interface
Exceptions:
P4_Spec_Exceptionif no id has been set.

Reimplemented from P4_SpecAbstract.

    {
        // ensure all required fields have values.
        $this->_validateRequiredFields();

        // set 'password' field to '******' otherwise password
        // will be deleted under certain security levels.
        $values = $this->_getValues();
        $values['Password'] = '******';

        // initialize command flags with first arg.
        $flags = array("-i");

        // if we are connected with super user privileges, add in the -f flag.
        // otherwise, if not connected as this user, connect as this user.
        $connection = $this->getConnection();
        if ($connection->isSuperUser()) {
            $flags[] = "-f";
        } else if ($connection->getUser() != $this->getId()) {
            $connection = P4_Connection::factory(
                $connection->getPort(),
                $this->getId()
            );
        }

        // send user spec to server.
        $password = $this->_getValue('Password');
        try {
            $connection->run(static::_getSpecType(), $flags, $values);
        } catch (P4_Connection_CommandException $e) {
            
            // if saving user failed because password has not been
            // set, and the caller supplied a password, try setting
            // the password first, then saving user again.
            //
            // @todo This workaround relies on the fact, that user has been created although previous
            // command had failed. At the moment it seems, that when adding a new user (with non-superuser
            // connection) this error cannot be avoided.
            $errors = $e->getResult()->getErrors();
            if (stristr($errors[0], "password must be set") && is_array($password) && isset($password[0])) {
                $this->_setPassword($password[0], null, $connection);
                $connection->run(static::_getSpecType(), $flags, $values);
                // avoid redundant password change
                $password[0] = null;
            } else {
                throw $e;
            }
        }

        // change the users password if they have set a new one.
        if (is_array($password) && $password[0] !== null) {
            $this->_setPassword($password[0], $password[1], $connection);
        }

        // should re-populate (server may change values).
        $this->_deferPopulate(true);

        return $this;
    }
P4_User::setEmail ( email)

Set the user's email address.

We don't require a valid email address here because Perforce doesn't enforce one. If we did then users with invalid emails would be innaccessible.

Parameters:
string | null$emailthe email of the user.
Returns:
P4_User provides fluent interface.
Exceptions:
InvalidArgumentExceptionif given email is not a string.
    {
        if ($email !== null && !is_string($email)) {
            throw new InvalidArgumentException("Cannot set email. Invalid type given.");
        }
        return $this->_setValue("Email", $email);
    }
P4_User::setFullName ( name)

Set the user's full name.

Parameters:
string | null$namethe full name to give the user.
Returns:
P4_User provides fluent interface.
Exceptions:
InvalidArgumentExceptionif given name is not a string.
    {
        if ($name !== null && !is_string($name)) {
            throw new InvalidArgumentException("Cannot set full name. Invalid type given.");
        }
        return $this->_setValue('FullName', $name);
    }
P4_User::setJobView ( jobView)

Set the user's job view (selects jobs for inclusion during changelist creation).

Parameters:
string | null$jobViewthe user's job view.
Returns:
P4_User provides fluent interface.
Exceptions:
InvalidArgumentExceptionif given job view is not a string.
    {
        if ($jobView !== null && !is_string($jobView)) {
            throw new InvalidArgumentException("Cannot set job view. Invalid type given.");
        }
        return $this->_setValue("JobView", $jobView);
    }
P4_User::setPassword ( newPassword,
oldPassword = null 
)

Set the user's password to the given password.

Does not take effect until save() is called.

Parameters:
string | null$newPasswordthe new password string or null to clear in-memory password.
string$oldPasswordoptional - existing password.
Returns:
P4_User provides fluent interface.
    {
        $this->_setValue('Password', array($newPassword, $oldPassword));

        return $this;
    }
P4_User::setReviews ( reviews)

Set the reviews for this user (depot paths to notify user of changes to).

Reviews is passed as an array of filespec strings.

Parameters:
array$reviewsReview entries - an array of filespec strings.
Returns:
P4_User provides a fluent interface.
Exceptions:
InvalidArgumentExceptionif reviews is not an array.
    {
        if (!is_array($reviews)) {
            throw new InvalidArgumentException('Reviews must be passed as array.');
        }

        return $this->_setValue('Reviews', $reviews);
    }

Member Data Documentation

P4_User::$_accessors [static, protected]
Initial value:
 array(
        'Email'     => 'getEmail',
        'Update'    => 'getUpdateDateTime',
        'Access'    => 'getAccessDateTime',
        'FullName'  => 'getFullName',
        'JobView'   => 'getJobView',
        'Reviews'   => 'getReviews',
        'Password'  => 'getPassword',
    )

Reimplemented from P4_SpecAbstract.

P4_User::$_idField = 'User' [static, protected]

Reimplemented from P4_Spec_PluralAbstract.

P4_User::$_mutators [static, protected]
Initial value:
 array(
        'Email'     => 'setEmail',
        'FullName'  => 'setFullName',
        'JobView'   => 'setJobView',
        'Reviews'   => 'setReviews',
        'Password'  => 'setPassword',
    )

Reimplemented from P4_SpecAbstract.

P4_User::$_specType = 'user' [static, protected]

Reimplemented from P4_SpecAbstract.

const P4_User::FETCH_BY_NAME = 'name'

The documentation for this class was generated from the following file: