Perforce Chronicle 2012.2/486814
API Documentation

P4_Change Class Reference

Abstracts operations against Perforce changes. More...

Inheritance diagram for P4_Change:
P4_Spec_PluralAbstract P4_ResolvableInterface P4_SpecAbstract P4_ModelAbstract P4_ConnectedAbstract P4_ModelInterface P4_ConnectedInterface

List of all members.

Public Member Functions

 addFile ($file)
 Add a file to the list of files in this changelist.
 addJob ($job)
 Add a job to the list of jobs attached to this change.
 delete ($force=false)
 Delete this changelist.
 getClient ()
 Get the client on which this change was created.
 getDateTime ()
 Get the date this change was last modified on the server.
 getDescription ()
 Get the description for this change.
 getFileObject ($file)
 Get the requested file attached to this change in P4_File format.
 getFileObjects ()
 Get the files attached to this change in P4_File format.
 getFiles ()
 Get the files attached to this change.
 getFilesToResolve ()
 Get files that need to be resolved.
 getFilesToRevert ()
 Get files that must be reverted.
 getId ()
 Get the number of this change.
 getJobs ()
 Get the jobs attached to this change.
 getJobStatus ()
 Get the job status of this change (the status that associated jobs will have when the change is submitted).
 getStatus ()
 Get the status of this change (either 'pending' or 'submitted').
 getUser ()
 Get the user that created this change.
 isDefault ()
 Test if this is the default change.
 isPending ()
 Check if this is a pending change.
 isSubmitted ()
 Check if this is a submitted change.
 resolve ($options)
 Resolves the change based on the passed option(s).
 revert ()
 Revert all of the files in this changelist.
 save ($force=false)
 Extend parent to set id to 'new' if unset and to reopen files that are open in other pending changelists where necessary.
 setDescription ($description)
 Set the description for this change.
 setFiles ($files)
 Set the list of opened files attached to this change.
 setId ($id)
 Set the id of this spec entry.
 setJobs ($jobs)
 Set the list of jobs attached to this change.
 submit ($description=null, $options=null)
 Save and submit this changelist.

Static Public Member Functions

static exists ($id, P4_Connection_Interface $connection=null)
 Determine if the given change id exists.
static fetchAll ($options=array(), P4_Connection_Interface $connection=null)
 Get all changes from Perforce.

Public Attributes

const DEFAULT_CHANGE = 'default'
const FETCH_BY_CLIENT = 'client'
const FETCH_BY_FILESPEC = 'filespec'
const FETCH_BY_STATUS = 'status'
const FETCH_BY_USER = 'user'
const FETCH_INTEGRATED = 'integrated'
const MAX_SUBMIT_ATTEMPTS = 3
const PENDING_CHANGE = 'pending'
const RESOLVE_FILE = 'file'
const SUBMITTED_CHANGE = 'submitted'

Protected Member Functions

 _getSpecData ()
 Get raw spec data direct from Perforce.

Static Protected Member Functions

static _fromSpecListEntry ($listEntry, $flags, P4_Connection_Interface $connection)
 Given a spec entry from spec list output (p4 changes), 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 a change number.

Protected Attributes

 $_cache = array()

Static Protected Attributes

static $_accessors
static $_idField = 'Change'
static $_mutators
static $_specType = 'change'

Detailed Description

Abstracts operations against Perforce changes.

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_Change::_fromSpecListEntry ( listEntry,
flags,
P4_Connection_Interface connection 
) [static, protected]

Given a spec entry from spec list output (p4 changes), 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.

    {
        // time is in unixtime - unset to avoid figuring out timezone
        // for a proper conversion.
        unset($listEntry['time']);

        // rename 'desc' field to 'Description'.
        $listEntry['Description'] = $listEntry['desc'];
        unset($listEntry['desc']);

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

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

Extends parent to add support for additional options.

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);

        // always use -l (for full descriptions).
        $flags[] = "-l";

        if (isset($options[static::FETCH_INTEGRATED]) &&
            $options[static::FETCH_INTEGRATED] === true) {
            $flags[] = "-i";
        }

        if (isset($options[static::FETCH_BY_STATUS])) {
            $flags[] = "-s";
            $flags[] = $options[static::FETCH_BY_STATUS];
        }

        if (isset($options[static::FETCH_BY_CLIENT])) {
            $flags[] = "-c";
            $flags[] = $options[static::FETCH_BY_CLIENT];
        }

        if (isset($options[static::FETCH_BY_USER])) {
            $flags[] = "-u";
            $flags[] = $options[static::FETCH_BY_USER];
        }

        // filespec must come last.
        if (isset($options[static::FETCH_BY_FILESPEC])) {
            $flags[] = $options[static::FETCH_BY_FILESPEC];
        }

        return $flags;
    }
P4_Change::_getSpecData ( ) [protected]

Get raw spec data direct from Perforce.

No caching involved. Overrides parent to suppress id when id is 'default' and to fetch files for submitted changes.

Returns:
array $data the raw spec output from Perforce.

Reimplemented from P4_Spec_PluralAbstract.

    {
        $flags = array('-o');
        if ($this->getId() !== static::DEFAULT_CHANGE) {
            $flags[] = $this->getId();
        }
        $data = $this->getConnection()
                     ->run(static::_getSpecType(), $flags)
                     ->expandSequences()
                     ->getData(0);

        // get files/jobs if this is a submitted change
        // note: can't use isSubmitted here - populate not complete yet.
        if ($data['Status'] == P4_Change::SUBMITTED_CHANGE) {
            $query = P4_File_Query::create()
                     ->addFilespec(P4_File::ALL_FILES)
                     ->setLimitToChangelist($this->getId());
            $files = P4_File::fetchAll($query, $this->getConnection());

            $this->_cache['fileObjects'] = $files;
            $data['Files'] = array();
            foreach ($files as $file) {
                $data['Files'][] = $file->getFilespec() . '#' . $file->getStatus('headRev');
            }
        }

        return $data;
    }
static P4_Change::_isValidId ( id) [static, protected]

Check if the given id is in a valid format for a change number.

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

Reimplemented from P4_Spec_PluralAbstract.

    {
        $validator = new P4_Validate_ChangeNumber;
        return $validator->isValid($id);
    }
P4_Change::addFile ( file)

Add a file to the list of files in this changelist.

Parameters:
string | P4_File$filethe file to attach to this change.
Returns:
P4_Change provides fluent interface.
    {
        // if file is a P4_File object, extract the filespecs.
        if ($file instanceof P4_File) {
            $file = $file->getFilespec();
        }

        $files = $this->getFiles();
        if (!in_array($file, $files)) {
            $files[] = $file;
        }
        $this->setFiles($files);

        return $this;
    }
P4_Change::addJob ( job)

Add a job to the list of jobs attached to this change.

Parameters:
string$jobthe id of the job to attach to this change.
Returns:
P4_Change provides fluent interface.
    {
        $jobs = $this->getJobs();
        if (!in_array($job, $jobs)) {
            $jobs[] = $job;
        }
        $this->setJobs($jobs);

        return $this;
    }
P4_Change::delete ( force = false)

Delete this changelist.

Parameters:
bool$forceoptional - defaults to false - set to true to force delete of another user/client's changelist or a submitted (empty) change.
Returns:
P4_Change provides fluent interface.
    {
        $id = $this->getId();
        if ($id === null) {
            throw new P4_Spec_Exception("Cannot delete change. No id has been set.");
        }

        // default change cannot be deleted.
        if ($id === P4_Change::DEFAULT_CHANGE) {
            throw new P4_Spec_Exception("Cannot delete the default change.");
        }

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

        // unknown or unhandled change status (e.g. 'shelved').
        if (!$this->isPending() && !$this->isSubmitted()) {
            throw new P4_Spec_Exception(
                "Unable to delete change with status '" . $this->getStatus() . "'."
            );
        }

        // handle submitted changes.
        $connection = $this->getConnection();
        if ($this->isSubmitted()) {

            // requires force option.
            if (!$force) {
                throw new P4_Spec_Exception(
                    "Cannot delete a submitted change without the force option."
                );
            }

            // check for files.
            if (count($this->getFiles())) {
                throw new P4_Spec_Exception(
                    "Cannot delete a submitted change that contains files."
                );
            }

            $result = $connection->run("change", array("-d", "-f", $id));
        }

        // handle pending changes (must remove files and fixes first).
        if ($this->isPending()) {
            if (!$force &&
                ($this->getUser()   !== $connection->getUser() ||
                 $this->getClient() !== $connection->getClient())) {
                throw new P4_Spec_Exception(
                    "Cannot delete a change from another user/client without the force option."
                );
            }

            // remove any associated files or jobs.
            $change = clone $this;
            $change->setFiles(null)->setJobs(null)->save();

            // delete the change.
            $flags = array("-d", $id);
            if ($force) {
                array_unshift($flags, "-f");
            }
            $connection->run("change", $flags);
        }

        // confirm delete successful (change -d does not surface errors).
        if (static::exists($id)) {
            throw new P4_Spec_Exception("Failed to delete change $id.");
        }

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

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

Determine if the given change 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 change.

Reimplemented from P4_Spec_PluralAbstract.

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

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

        // default change always exists.
        if ($id === static::DEFAULT_CHANGE) {
            return true;
        }

        // attempt to fetch change - assume id does not exist on failure.
        try {
            $connection->run('change', array('-o', $id));
            return true;
        } catch (P4_Exception $e) {
            return false;
        }
    }
static P4_Change::fetchAll ( options = array(),
P4_Connection_Interface connection = null 
) [static]

Get all changes from Perforce.

Adds filtering options.

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_FILESPEC - set to a filespec to limit changes to those affecting the file(s) matching the filespec. FETCH_BY_STATUS - set to a valid change status to limit result to changes with that status (e.g. 'pending'). FETCH_INTEGRATED - set to true to include changes integrated into the specified files. FETCH_BY_CLIENT - set to a client to limit changes to those on the named client. FETCH_BY_USER - set to a user to limit changes to those owned by the named user.

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

Reimplemented from P4_Spec_PluralAbstract.

    {
        // simply return parent - method exists to document options.
        return parent::fetchAll($options, $connection);
    }
P4_Change::getClient ( )

Get the client on which this change was created.

Returns:
string the client on which this change was created.
    {
        $client = $this->_getValue('Client');
        if (!$client) {
            $client = $this->getConnection()->getClient();
        }
        return $client;
    }
P4_Change::getDateTime ( )

Get the date this change was last modified on the server.

Returns:
null|string the date this change was last modified on the server, or null if the change does not exist on the server.
    {
        return $this->_getValue('Date');
    }
P4_Change::getDescription ( )

Get the description for this change.

Returns:
string the description for this change.
    {
        return $this->_getValue('Description');
    }
P4_Change::getFileObject ( file)

Get the requested file attached to this change in P4_File format.

Parameters:
P4_File | string$fileFilespec in string or P4_File format; rev is ignored
Returns:
P4_File The requested file at the revision associated with this change
Exceptions:
InvalidArgumentExceptionIf the specified file doesn't exist.
    {
        // normalize to string
        if ($file instanceof P4_File) {
            $file = $file->getDepotFilename();
        }

        // validate input
        if (!is_string($file)) {
            throw new InvalidArgumentException('File must be a string or P4_File object.');
        }

        // ensure no rev-spec is present on our comparison entry
        $file = P4_File::stripRevspec($file);
        foreach ($this->getFileObjects() as $changeFile) {
            if (P4_File::stripRevspec($changeFile->getDepotfilename()) == $file) {
                return $changeFile;
            }
        }

        throw new InvalidArgumentException('The requested file was not found in this change');
    }
P4_Change::getFileObjects ( )

Get the files attached to this change in P4_File format.

Returns:
P4_Model_Iterator list of P4_File's associated with this change.
    {
        if (!isset($this->_cache['fileObjects'])
            || !$this->_cache['fileObjects'] instanceof P4_Model_Iterator
        ) {
            $this->_cache['fileObjects'] = P4_File::fetchAll(
                P4_File_Query::create()->addFilespecs(
                    $this->getFiles()
                )
            );
        }

        return clone $this->_cache['fileObjects'];
    }
P4_Change::getFiles ( )

Get the files attached to this change.

Revspecs are included for submitted changes but are not present on pending changes.

Returns:
array list of files associated with this change.
    {
        $files = $this->_getValue('Files');
        return is_array($files) ? $files : array();
    }
P4_Change::getFilesToResolve ( )

Get files that need to be resolved.

Returns:
P4_Model_Iterator files that need to be resolved.
    {
        $query = P4_File_Query::create()
                 ->addFilespec(P4_File::ALL_FILES)
                 ->setLimitToChangelist($this->getId())
                 ->setLimitToNeedsResolve(true)
                 ->setLimitToOpened(true);
        return P4_File::fetchAll($query, $this->getConnection());
    }
P4_Change::getFilesToRevert ( )

Get files that must be reverted.

Returns:
P4_Model_Iterator files that must be reverted.
    {
        // setup fstat filter to match files that must be reverted.
        // several conditions to catch:
        //  - files open for add, but already existing and not deleted, or
        //  - files that are not open for add, but are deleted in the depot.
        $filter = "(action=add & headAction=* & ^headAction=...deleted) | "
                . "(headAction=...delete & ^action=add)";

        $query = P4_File_Query::create()
                 ->addFilespec(P4_File::ALL_FILES)
                 ->setLimitToChangelist($this->getId())
                 ->setLimitToOpened(true)
                 ->setFilter($filter);
        return P4_File::fetchAll($query, $this->getConnection());
    }
P4_Change::getId ( )

Get the number of this change.

Extends parent to return an integer value for numbered changes.

Returns:
null|string|id the integer number of the change, the literal string 'default' or null if no id has been set.

Reimplemented from P4_Spec_PluralAbstract.

    {
        $id = parent::getId();
        if ($id !== null && $id !== static::DEFAULT_CHANGE) {
            $id = intval($id);
        }
        return $id;
    }
P4_Change::getJobs ( )

Get the jobs attached to this change.

Returns:
array the list of jobs attached to this change.
    {
        $jobs = $this->_getValue('Jobs');
        return is_array($jobs) ? $jobs : array();
    }
P4_Change::getJobStatus ( )

Get the job status of this change (the status that associated jobs will have when the change is submitted).

The value of the job status field is not preserved. You cannot get the job status of a saved or submitted change. Once a changelist is saved or submitted, the job status field is cleared. It can only be read after it has been explicitly set, and before the change is saved or submitted.

Returns:
null|string the job status of this change if not yet saved or submitted. null otherwise.
    {
        return $this->_getValue('JobStatus');
    }
P4_Change::getStatus ( )

Get the status of this change (either 'pending' or 'submitted').

Returns:
string the status of this change: 'pending', 'submitted'.
    {
        $status = $this->_getValue('Status');
        if (!$status) {
            $status = static::PENDING_CHANGE;
        }
        return $status;
    }
P4_Change::getUser ( )

Get the user that created this change.

Returns:
string the user that created this change.
    {
        $user = $this->_getValue('User');
        if (!$user) {
            $user = $this->getConnection()->getUser();
        }
        return $user;
    }
P4_Change::isDefault ( )

Test if this is the default change.

Returns:
bool true if this is the default change - false otherwise.
    {
        return ($this->getId() === static::DEFAULT_CHANGE);
    }
P4_Change::isPending ( )

Check if this is a pending change.

Returns:
bool true if this is a pending change - false otherwise.
    {
        return ($this->isDefault() || $this->getStatus() === static::PENDING_CHANGE);
    }
P4_Change::isSubmitted ( )

Check if this is a submitted change.

Returns:
bool true if this is a submitted change - false otherwise.
    {
        return ($this->getStatus() === static::SUBMITTED_CHANGE);
    }
P4_Change::resolve ( options)

Resolves the change based on the passed option(s).

You must specify one of the below: RESOLVE_ACCEPT_MERGED Automatically accept the Perforce-recom mended file revision: if theirs is identical to base, accept yours; if yours is identical to base, accept theirs; if yours and theirs are different from base, and there are no conflicts between yours and theirs; accept merge; other wise, there are conflicts between yours and theirs, so skip this file. RESOLVE_ACCEPT_YOURS Accept Yours, ignore theirs. RESOLVE_ACCEPT_THEIRS Accept Theirs. Use this flag with caution! RESOLVE_ACCEPT_SAFE Safe Accept. If either yours or theirs is different from base, (and the changes are in common) accept that revision. If both are different from base, skip this file. RESOLVE_ACCEPT_FORCE Force Accept. Accept the merge file no matter what. If the merge file has conflict markers, they will be left in, and you'll need to remove them by editing the file.

Additionally, one of the following whitespace options can, optionally, be passed: IGNORE_WHITESPACE_CHANGES Ignore whitespace-only changes (for instance, a tab replaced by eight spaces) IGNORE_WHITESPACE Ignore whitespace altogether (for instance, deletion of tabs or other whitespace) IGNORE_LINE_ENDINGS Ignore differences in line-ending convention

Lastly, the resolve can be limited to a particular file in the change by passing: RESOLVE_FILE => filespec with no wildcards

Parameters:
array | string$optionsResolve option(s); must include a RESOLVE_* preference.
Returns:
P4_Change provide fluent interface.
    {
        if (is_string($options)) {
            $options = array($options);
        }

        if (!is_array($options)) {
            throw new InvalidArgumentException('Expected a string or array of options.');
        }

        $mode       = '';
        $whitespace = '';
        $arguments  = array();

        // loop options so we accept the last mode
        // and whitespace setting we encounter.
        foreach ($options as $option) {
            switch ($option)
            {
                case static::RESOLVE_ACCEPT_MERGED:
                    $mode = '-am';
                    break;
                case static::RESOLVE_ACCEPT_YOURS:
                    $mode = '-ay';
                    break;
                case static::RESOLVE_ACCEPT_THEIRS:
                    $mode = '-at';
                    break;
                case static::RESOLVE_ACCEPT_SAFE:
                    $mode = '-as';
                    break;
                case static::RESOLVE_ACCEPT_FORCE:
                    $mode = '-af';
                    break;
            }

            switch ($option)
            {
                case static::IGNORE_WHITESPACE_CHANGES:
                    $whitespace = '-db';
                    break;
                case static::IGNORE_WHITESPACE:
                    $whitespace = '-dw';
                    break;
                case static::IGNORE_LINE_ENDINGS:
                    $whitespace = '-dl';
                    break;
            }
        }

        // we can't do anything without a mode; throw
        if (empty($mode)) {
            throw new InvalidArgumentException(
                'No action specified. Expected Resolve Accept Merged|Yours|Theirs|Safe|Force'
            );
        }

        // compile our various flags into our arguments array
        $arguments[] = $mode;
        if ($whitespace) {
            $arguments[] = $whitespace;
        }

        $files = $this->getFiles();
        if (isset($options[static::RESOLVE_FILE])) {
            $file = $options[static::RESOLVE_FILE];
            if (!in_array($file, $files)) {
                throw new InvalidArgumentException(
                    "The RESOLVE_FILE specified is not in this change."
                );
            }

            $files = array($file);
        }

        // resolve files in several (as few as possible) runs as
        // there is a potential to exceed the arg-max on this command
        $connection = $this->getConnection();
        $batches    = $connection->batchArgs($files, $arguments);
        foreach ($batches as $batch) {
            $connection->run('resolve', $batch);
        }

        return $this;
    }
P4_Change::revert ( )

Revert all of the files in this changelist.

Returns:
P4_Change provides fluent interface.
Exceptions:
P4_Spec_Exceptionif the change is not a pending change.
    {
        // ensure change is a pending change.
        if (!$this->isPending()) {
            throw new P4_Spec_Exception("Can only revert pending changes.");
        }

        // save the change before revert (updates files in change).
        $this->save();

        // perform revert.
        $result = $this->getConnection()->run(
            "revert",
            array("-c", $this->getId(), '//...')
        );

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

        return $this;
    }
P4_Change::save ( force = false)

Extend parent to set id to 'new' if unset and to reopen files that are open in other pending changelists where necessary.

Parameters:
bool$forceoptional - default false - true to save submitted change.
Returns:
P4_Change provides a fluent interface
Exceptions:
P4_UnopenedExceptionif change contains unopened files.
P4_Connection_CommandExceptionif save command fails for some reason.
    {
        $values = $this->_getValues();
        if (!isset($values[static::_getIdField()]) || $this->isDefault()) {
            $values[static::_getIdField()] = "new";
        }

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

        // can't update a submitted change without the force option.
        if (!$force && $this->isSubmitted()) {
            throw new P4_Spec_Exception(
                "Cannot update a submitted change without the force option."
            );
        }

        // perform save.
        $connection = $this->getConnection();
        try {

            $flags = array("-i");
            if ($force) {
                $flags[] = "-u";
            }
            $result = $connection->run(static::_getSpecType(), $flags, $values);

            // extract change number from command result.
            $data = $result->getData(0);

            if (!preg_match('/^Change ([^ ]+) (created|updated)/', $data, $matches)) {
                throw new P4_Spec_Exception('Cannot determine number of saved change.');
            }

            $id = $matches[1];

        } catch (P4_Connection_CommandException $e) {

            // if the exception was caused by non-existant jobs, the change should
            // have been created.
            if (preg_match(
                "/Change ([^ ]+) (created|updated).*Job '([^']+)' doesn't exist\./s",
                $e->getMessage(), $matches
            )) {
                $this->setId($matches[1]);
                throw $e;
            }

            // if exception not caused by un-opened files, re-throw.
            if (strpos($e->getMessage(), "Can't include file(s) not already opened.") === false) {
                throw $e;
            }

            // if any files are truly un-opened throw a special un-opened files exception.
            // (save will complain of un-opened files if files are not in default change)
            $flags  = array("-Ro", "-T", "depotFile");
            $flags  = array_merge($flags, $values['Files']);
            $result = $connection->run("fstat", $flags);
            if ($result->hasWarnings()) {
                throw new P4_UnopenedException(
                    "Cannot save change. One or more files are not open."
                );
            }

            // all files are actually open, save w.out files first, then reopen.
            $change = clone $this;
            $id     = $change->setFiles(null)->save()->getId();
            $flags  = $values['Files'];
            array_unshift($flags, "-c", $id);
            $connection->run("reopen", $flags);

        }

        // Store the retrieved id.
        $this->setId($id);

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

        return $this;
    }
P4_Change::setDescription ( description)

Set the description for this change.

Parameters:
string | null$descriptiondescription for this change.
Returns:
P4_Change provides a fluent interface.
Exceptions:
InvalidArgumentExceptionif description is incorrect type.
    {
        if ($description !== null && !is_string($description)) {
            throw new InvalidArgumentException("Cannot set description. Invalid type given.");
        }

        return $this->_setValue('Description', $description);
    }
P4_Change::setFiles ( files)

Set the list of opened files attached to this change.

Parameters:
null | array | P4_Model_Iterator$filesthe files to attach to this change.
Returns:
P4_Change provides a fluent interface.
Exceptions:
InvalidArgumentExceptionif files is incorrect type.
P4_Spec_Exceptionif change is submitted.
    {
        if ($files === null) {
            $files = array();
        }

        if ($files instanceof P4_Model_Iterator) {
            $files = iterator_to_array($files);
        }

        // ensure files is an array.
        if (!is_array($files)) {
            throw new InvalidArgumentException('Cannot set files. Invalid type given.');
        }

        // normalize the array entries to a string, stripping revspecs
        foreach ($files as &$file) {
            if ($file instanceof P4_File) {
                $file = $file->getFilespec();
            }

            if (!is_string($file)) {
                throw new InvalidArgumentException('All files must be a string or P4_File');
            }

            $file = P4_File::stripRevspec($file);
        }

        // don't permit set files on submitted changes.
        if ($this->isSubmitted()) {
            throw new P4_Spec_Exception('Cannot set files on a submitted change.');
        }

        // we cache file objects; clear that out
        $this->_cache = array();

        $this->_setValue('Files', $files);

        return $this;
    }
P4_Change::setId ( id)

Set the id of this spec entry.

Id must be in a valid format or null. Extended from parent to clear cache.

Parameters:
null | string$idthe id of this entry - pass null to clear.
Returns:
P4_Spec_PluralAbstract provides a fluent interface
Exceptions:
InvalidArgumentExceptionif id does not pass validation.

Reimplemented from P4_Spec_PluralAbstract.

    {
        if ($this->getId() !== $id) {
            $this->_cache = array();
        }

        return parent::setId($id);
    }
P4_Change::setJobs ( jobs)

Set the list of jobs attached to this change.

Parameters:
null | array$jobsthe jobs to attach to this change.
Returns:
P4_Change provides a fluent interface.
Exceptions:
InvalidArgumentExceptionif jobs is incorrect type.
P4_Spec_Exceptionif change is submitted.
    {
        if ($jobs === null) {
            $jobs = array();
        }

        // if jobs is an iterator, extract the job numbers.
        if ($jobs instanceof P4_Model_Iterator) {
            $newJobs = array();
            foreach ($jobs as $job) {
                if ($job instanceof P4_Job) {
                    $newJobs[] = $job->getId();
                } else {
                    throw new InvalidArgumentException('Each iterator job must be a P4_Job object.');
                }
            }
            $jobs = $newJobs;
        }

        // ensure jobs is an array.
        if (!is_array($jobs)) {
            throw new InvalidArgumentException('Cannot set jobs. Invalid type given.');
        }

        // ensure job elements are strings.
        foreach ($jobs as $job) {
            if (!is_string($job)) {
                throw new InvalidArgumentException('Each job must be a string.');
            }
        }

        // don't permit set jobs on submitted changes.
        if ($this->isSubmitted()) {
            throw new P4_Spec_Exception('Cannot set jobs on a submitted change.');
        }

        return $this->_setValue('Jobs', $jobs);
    }
P4_Change::submit ( description = null,
options = null 
)

Save and submit this changelist.

Parameters:
string$descriptionoptional - a description of this change.
null | string | array$optionsoptional resolve flags, to be used if conflict occurs. See resolve() for details.
Returns:
P4_Change provides fluent interface.
Exceptions:
P4_Spec_Exceptionif the change is not a pending change.
P4_Change_ResolveConflictExceptionif change contains files requiring resolve.
P4_Change_DeleteConflictExceptionif change contains files that have been deleted.
    {
        // ensure change is a pending change.
        if (!$this->isPending()) {
            throw new P4_Spec_Exception("Can only submit pending changes.");
        }

        // if description is given, use it.
        if (strlen($description)) {
            $this->setDescription($description);
        }

        // save the change before submit.
        $this->save();

        // try repeatedly to submit (with resolves in-between attempts)
        // note: no need to explicitly sync as submit schedules resolve
        for ($i = static::MAX_SUBMIT_ATTEMPTS; $i > 0; $i--) {
            try {
                $result = $this->getConnection()->run("submit", array("-c", $this->getId()));

                // everything went ok no need to retry.
                break;
            } catch (P4_Connection_ConflictException $e) {
                // if there are no resolve options or we have exceeded
                // max resolve attempts; re-throw the resolve exception
                if ($i <= 1 || empty($options)) {
                    throw $e;
                }

                // our changelist id has possibly been updated
                // update our id field to match.
                $this->setId($e->getChange()->getId());

                $this->resolve($options);
            }
        }

        // extract change number from last data block of command result
        // because the change number may have changed during submit.
        $last = end($result->expandSequences()->getData());
        $this->setId($last['submittedChange']);

        return $this;
    }

Member Data Documentation

P4_Change::$_accessors [static, protected]
Initial value:
 array(
        'Date'          => 'getDateTime',
        'User'          => 'getUser',
        'Client'        => 'getClient',
        'Status'        => 'getStatus',
        'Description'   => 'getDescription',
        'JobStatus'     => 'getJobStatus',
        'Jobs'          => 'getJobs',
        'Files'         => 'getFiles'
    )

Reimplemented from P4_SpecAbstract.

P4_Change::$_cache = array() [protected]
P4_Change::$_idField = 'Change' [static, protected]

Reimplemented from P4_Spec_PluralAbstract.

P4_Change::$_mutators [static, protected]
Initial value:
 array(
        'Description'   => 'setDescription',
        'JobStatus'     => 'setJobStatus',
        'Jobs'          => 'setJobs',
        'Files'         => 'setFiles'
    )

Reimplemented from P4_SpecAbstract.

P4_Change::$_specType = 'change' [static, protected]

Reimplemented from P4_SpecAbstract.

const P4_Change::DEFAULT_CHANGE = 'default'
const P4_Change::FETCH_BY_CLIENT = 'client'
const P4_Change::FETCH_BY_FILESPEC = 'filespec'
const P4_Change::FETCH_BY_STATUS = 'status'
const P4_Change::FETCH_BY_USER = 'user'
const P4_Change::FETCH_INTEGRATED = 'integrated'
const P4_Change::PENDING_CHANGE = 'pending'
const P4_Change::RESOLVE_FILE = 'file'
const P4_Change::SUBMITTED_CHANGE = 'submitted'

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