Perforce Chronicle 2012.2/486814
API Documentation

P4_File Class Reference

Abstracts operations against Perforce files. More...

Inheritance diagram for P4_File:
P4_ModelAbstract P4_ResolvableInterface P4_ConnectedAbstract P4_ModelInterface P4_ConnectedInterface

List of all members.

Public Member Functions

 add ($change=null, $fileType=null)
 Open the file for add.
 clearAnnotateCache ()
 Clear the annotated content cache.
 clearAttribute ($attribute, $force=false)
 Clear the given attribute on the file.
 clearAttributes ($attributes, $force=false)
 Clear the specified attributes on this file.
 clearContentCache ()
 Clear the depot file cache.
 clearStatusCache ()
 Clear the file status cache.
 delete ($change=null, $force=true)
 Open this file for delete.
 deleteLocalFile ()
 Delete the local file from the workspace.
 edit ($change=null, $fileType=null, $force=true)
 Open the file for edit.
 flush ()
 Flush the file - tells the server we have the file.
 getAnnotateContent ()
 Get the annotated contents of the file in Perforce.
 getAttribute ($attribute)
 Get the named attribute from the set of submitted attributes on this file.
 getAttributes ($open=false)
 Get all submitted attributes of this file.
 getBasename ($suffix=null)
 Get the basename of the file.
 getChange ()
 Convenience function to return the change object associated with the file at its current revspec.
 getChanges (array $options=null)
 Convienence function to return all changes associated with this file.
 getDepotContents ()
 Get the contents of the file in Perforce.
 getDepotFilename ()
 Get the path to the file in depot file syntax.
 getDepotPath ()
 Get the depot path to the file.
 getFields ()
 Return array with all model fields.
 getFileSize ()
 Get the file's size in the depot.
 getFilespec ($stripRevspec=false)
 Get the filespec used to identify this file.
 getFilespecWithRevision ()
 Get the filespec used to identify this file including a revision specification if one is known.
 getLocalContents ()
 Get the contents of the local file in the client workspace.
 getLocalFilename ()
 Get the path to the file in local file syntax.
 getLocalFileSize ()
 Get the size of the local client file.
 getLocalPath ()
 Get the local path to the file.
 getOpenAttribute ($attribute)
 Get the named attribute from the set of pending attributes on this file.
 getOpenAttributes ()
 Get all pending attributes for this file.
 getStatus ($field=null)
 Get file status (run fstat on file).
 getValue ($field)
 Return value of given field of the model.
 hasAttribute ($attribute)
 Check if the file has the named attribute.
 hasField ($field)
 Check if given field is valid model field.
 hasOpenAttribute ($attribute)
 Check if the file has the named open attribute.
 hasStatusField ($field)
 Determine if this file has the named status field.
 isDeleted ()
 Test if a file is deleted in the depot.
 isHead ()
 Checks if this file is at the head revision or not.
 isOpened ()
 Check if the file is opened in Perforce by the current client.
 lock ()
 Lock this file in the depot.
 needsResolve ()
 Used to check if the file requires resolve or not.
 open ($change=null, $fileType=null, $force=true)
 Open file for add or edit as appropriate.
 reopen ($change=null, $type=null)
 Open the file in another change and/or as a different filetype.
 resolve ($options)
 Resolves the file based on the passed option(s).
 revert ($options=null)
 Revert the file.
 setAttribute ($key, $value, $propagate=true, $force=false)
 Set the given attribute/value on the file.
 setAttributes ($attributes, $propagate=true, $force=false)
 Set attributes on this file.
 setContentCache ($content)
 Prime the depot file cache with the given value.
 setFilespec ($filespec)
 Set the filespec identifier for the file/revision.
 setLocalContents ($content)
 Write contents to the local client file.
 setStatusCache ($status)
 Set the file status cache to the given array of fields/values.
 submit ($description, $options=null)
 Submit the file to perforce.
 sync ($force=false, $flush=false)
 Sync the file from the depot.
 touchLocalFile ()
 Touch the local client file.
 unlock ()
 Unlock this file in the depot.
 where ()
 Determine how this file maps through the client view.

Static Public Member Functions

static count ($query, P4_Connection_Interface $connection=null)
 Count files matching the given query.
static exists ($filespec, P4_Connection_Interface $connection=null, $excludeDeleted=false)
 Check if the given filespec is known to Perforce.
static fetch ($filespec, P4_Connection_Interface $connection=null)
 Fetch a model of the given filespec.
static fetchAll ($query, P4_Connection_Interface $connection=null)
 Fetch all files matching the given query.
static hasRevspec ($filespec)
 Check if the given filespec has a revision specifier.
static stripRevspec ($filespec)
 Strip the revision specifier from a file specification.

Public Attributes

const ALL_FILES = '//...'
const REVERT_UNCHANGED = 'unchanged'

Protected Member Functions

 _isOpenForAction ($action)
 Checks if the file is open for the given action.
 _openForAction ($action, $change=null, $fileType=null, $force=true)
 Open the file for the specified action.

Static Protected Member Functions

static _parsePrintOutput ($data)
 Parses print output for one or more files into the below format:

Protected Attributes

 $_cache = array()
 $_filespec = null

Detailed Description

Abstracts operations against Perforce files.

THEORY OF OPERATION

Unlike a typical database, all changes to Perforce files must be pended to the current client workspace before they can be commited.

The file model provides access to two copies of file data: the submitted depot copy and the client workspace copy. When you are accessing file data (be it file contents or file attributes), you must consider which of these sources you want to get the data from.

For example, if you call getDepotContents() you will get the submitted depot copy of the file; whereas, if you call getLocalContents() you will get the contents of the client workspace file.

The class attempts to faithfully represent the behavior of Perforce. There is, however, some simplification at work. In particular, the open() method will automatically add or edit a file as appropriate. It will also sync the file to the client if necessary.

Similarly, if a file is open for delete, the add, edit and open methods will revert the file and reopen it. Conversely, if delete() is called on a file that is opened (but not for delete), the file will be reverted and then deleted(). To suppress this behavior, pass false as the force option.

COMMON USAGE

To fetch a file from Perforce, call fetch() and pass the filespec of the file you wish to retrieve. For example:

$file = P4_File::fetch('//depot/file');

To fetch several files, call fetchAll() and pass a file query object representing the fstat options that you wish to use. For example:

$files = P4_File::fetchAll( new P4_File_Query(array('filespecs' => '//depot/path/...')) );

The query class also has options to filter, sort and limit files. See the P4_File_Query class for additional details.

To submit a file:

$file = new P4_File; $file->setFilespec('//depot/file'); $file->open(); $file->setLocalContents('new file content'); $file->submit('Description of change');

To delete a file:

$file->delete(); $file->submit('Description of change');

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

P4_File::_isOpenForAction ( action) [protected]

Checks if the file is open for the given action.

Applies a bit of fuzzy logic to consider move/add to be open for edit since a file must be opened for edit before it can be moved.

Parameters:
string$actionthe action to check for
Returns:
bool true if the file is open for the given action
    {
        // if not opened at all, nothing more to check
        if (!$this->isOpened()) {
            return false;
        }

        $openAction = $this->getStatus('action');
        if ($openAction == $action) {
            return true;
        }

        // consider move/add to also be open for edit - a file must be opened
        // for edit before it can be moved; therefore, a move/add file is open
        // for edit - without this, calling edit() on the target of a move
        // would incur a revert unless force is explicitly set to false.
        if ($openAction == 'move/add' && $action == 'edit') {
            return true;
        }

        return false;
    }
P4_File::_openForAction ( action,
change = null,
fileType = null,
force = true 
) [protected]

Open the file for the specified action.

Parameters:
string$actionthe action to open the file for ('add', 'edit' or 'delete').
int$changeoptional - a numbered pending change to open the file in.
string$fileTypeoptional - the file-type to open the file as.
bool$forceoptional - defaults to true - set to false to avoid reopening.
Returns:
P4_File provide fluent interface.
    {
        // verify we have a filespec set; throws if invalid/missing
        $this->_validateHasFilespec();

        // action must be one of: add, edit or delete.
        if (!in_array($action, array('add', 'edit', 'delete'))) {
            throw new P4_File_Exception("Cannot open file. Invalid open 'action' specified.");
        }

        // if already opened for specified action, verify change and type, then return.
        if ($this->_isOpenForAction($action)) {
            if (($change && $this->getStatus('change') !== $change)
                || ($fileType && $this->getStatus('type') !== $fileType)
            ) {
                $this->reopen($change, $fileType);
            }

            return $this;
        }

        $p4   = $this->getConnection();
        $file = $this->getFilespec(true);

        // if force is true, revert files opened for the wrong action
        // unless it's open for integrate and we are trying to edit
        // or it's open for branch and we are trying to add (to keep
        // the integration credit).
        if ($force
            && $this->isOpened()
            && !$this->_isOpenForAction($action)
            && !($action == 'edit' && $this->_isOpenForAction('integrate'))
            && !($action == 'add'  && $this->_isOpenForAction('branch'))
        ) {
            $result = $p4->run('revert', $file);
        }

        // setup command flags.
        $flags = array();
        if ($change) {
            $flags[] = '-c';
            $flags[] = $change;
        }
        if ($fileType) {
            $flags[] = '-t';
            $flags[] = $fileType;
        }

        // allows delete to work without having to sync file.
        if ($action === 'delete') {
            $flags[] = '-v';
        }
        $flags[] = $file;

        // throw for edit or delete of a deleted file (these are dead ends!)
        // use the -n flag to see what would happen without actually opening file.
        if (in_array($action, array('edit', 'delete'))) {
            $result   = $p4->run($action, array_merge(array('-n'), $flags));
            foreach ($result->getData() as $data) {
                if (is_string($data)
                    && preg_match("/warning: $action of deleted file/", $data)
                ) {
                    throw new P4_File_Exception(
                        "Failed to open file for $action: " . $data
                    );
                }
            }
        }

        // open file for specified action.
        $result = $p4->run($action, $flags);

        // check for warnings.
        if ($result->hasWarnings()) {
            throw new P4_File_Exception(
                "Failed to open file for $action: " . implode(", ", $result->getWarnings())
            );
        }

        // status has changed - clear the status cache.
        $this->clearStatusCache();

        // verify file was opened for specified action.
        if (!$this->hasStatusField('action') || $this->getStatus('action') !== $action) {
            throw new P4_File_Exception(
                "Failed to open file for $action: " . $result->getData(0)
            );
        }

        return $this;
    }
static P4_File::_parsePrintOutput ( data) [static, protected]

Parses print output for one or more files into the below format:

Array ( [//depot/path/to/file.ext] => Array ( [depotFile] => //depot/path/to/file.ext [rev] => 6 [change] => 222450 [action] => edit [type] => text [time] => 1257743394 [content] => Full content of file ) )

Parameters:
array$dataData from p4 print result
Returns:
array File details and content keyed on depotFile; formated as above
    {
        $files = array();

        // print output consists of the following elements, repeated for each file:
        //  - file info
        //  - file content  (repeated for every 4k of file content, or when server feels like it)
        foreach ($data as $block) {
            // If we are at a meta-data block, store the file name and meta-data then continue
            if (is_array($block) && isset($block['depotFile'])) {
                $name           = $block['depotFile'];
                $files[$name]   = $block;

                // prime content entry as string
                $files[$name]['content']  = '';

                continue;
            }

            // Be defensive, clear file name if we hit an unrecognized block
            if (is_array($block)) {
                $name = null;
            }

            // If we made it this far, and we have a file name, it's a content block; append it
            if (isset($name)) {
                $files[$name]['content'] .= $block;
            }
        }

        return $files;
    }
P4_File::add ( change = null,
fileType = null 
)

Open the file for add.

Parameters:
int$changeoptional - a numbered pending change to open the file in.
string$fileTypeoptional - the file-type to open the file as.
Returns:
P4_File provides fluent interface.
    {
        return $this->_openForAction('add', $change, $fileType, false);
    }
P4_File::clearAnnotateCache ( )

Clear the annotated content cache.

Returns:
P4_File provide fluent interface.
    {
        $this->_cache['annotatedContent'] = null;

        return $this;
    }
P4_File::clearAttribute ( attribute,
force = false 
)

Clear the given attribute on the file.

By default the cleared attribute will be pended. To clear attributes in the depot directly, set the force flag to true.

Parameters:
string$attributethe name of the attribute to clear.
bool$forceoptional - defaults to false - clear the attribute in the depot directly.
Returns:
P4_File provide fluent interface.
    {
        return $this->clearAttributes(array($attribute), $force);
    }
P4_File::clearAttributes ( attributes,
force = false 
)

Clear the specified attributes on this file.

Parameters:
array$attributesthe set of attributes to clear.
bool$forceoptional - clear the attributes in the depot directly by default attributes are pended to the client workspace.
Returns:
P4_File provide fluent interface.
    {
        if (!is_array($attributes)) {
            throw new InvalidArgumentException(
                "Can't clear attributes. Attributes must be an array."
            );
        }

        // if no attributes given, nothing to clear.
        if (empty($attributes)) {
            return $this;
        }

        // verify we have a filespec set; throws if invalid/missing
        $this->_validateHasFilespec();
        $filespec = $force
            ? $this->getFilespecWithRevision()
            : $this->getFilespec(true);

        // make -n/attr-name argument pairs.
        $params = array();
        foreach ($attributes as $attribute) {
            $params[] = "-n";
            $params[] = $attribute;
        }

        // there is a potential to exceed the arg-max/option-limit;
        // run attribute command as few times as possible
        $connection   = $this->getConnection();
        $prefixParams = $force ? array('-f') : array();
        foreach ($connection->batchArgs($params, $prefixParams, array($filespec), 2) as $batch) {
            $connection->run('attribute', $batch);
        }

        // status has changed - clear the status cache.
        $this->clearStatusCache();

        return $this;
    }
P4_File::clearContentCache ( )

Clear the depot file cache.

Returns:
P4_File provide fluent interface.
    {
        unset($this->_cache['content']);

        return $this;
    }
P4_File::clearStatusCache ( )

Clear the file status cache.

Returns:
P4_File provide fluent interface.
    {
        $this->_cache['status'] = null;

        return $this;
    }
static P4_File::count ( query,
P4_Connection_Interface connection = null 
) [static]

Count files matching the given query.

This is a faster alternative to counting the result of fetchAll().

Parameters:
P4_File_Query | array$queryA query object or array expressing fstat options.
P4_Connection_Interface$connectionoptional - a specific connection to use.
Returns:
P4_Model_Iterator count of matching files.
    {
        if (!$query instanceof P4_File_Query && !is_array($query)) {
            throw new InvalidArgumentException(
                'Query must be a P4_File_Query or array.'
            );
        }

        // normalize array input to a query
        if (is_array($query)) {
            $query = new P4_File_Query($query);
        }

        // ensure caller provided a filespec.
        if (!count($query->getFilespecs())) {
            throw new InvalidArgumentException(
                'Cannot count files. No filespecs provided in query.'
            );
        }

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

        // remove options that cause unnecessary work for the server
        $query = clone $query;
        $query->setSortBy(null)->setReverseOrder(false);

        // only fetch a single field for performance.
        $query->setLimitFields('depotFile');

        // get fstat flags for given query and run fstat command.
        $flags  = array_merge($query->getFstatFlags(), $query->getFilespecs());
        $result = $connection->run('fstat', $flags);
        $count  = count($result->getData());

        // if fetching by change, the last block of data contains
        // the change description - remove it (unless we're fetching
        // from the default changelist)
        if ($query->getLimitToChangelist() !== null
            && $query->getLimitToChangelist() !== P4_Change::DEFAULT_CHANGE
        ) {
            $count--;
        }

        return $count;
    }
P4_File::delete ( change = null,
force = true 
)

Open this file for delete.

If the file is open, but not for delete, the file will be reverted and then deleted unless the force flag has been set to false.

Parameters:
int$changeoptional - a numbered pending change to open the file in.
bool$forceoptional - defaults to true - reverts files that are open then deletes them. if false, files that are open (not for delete) will result in an exception being thrown.
Returns:
P4_File provide fluent interface.
    {
        return $this->_openForAction('delete', $change, null, $force);
    }
P4_File::deleteLocalFile ( )

Delete the local file from the workspace.

Exceptions:
P4_File_Exceptionif the local file cannot be deleted.
Returns:
P4_File provide fluent interface.
    {
        $localFile = $this->getLocalFilename();
        if (!file_exists($localFile)) {
            throw new P4_File_Exception("Cannot delete local file. File does not exist.");
        }
        chmod($localFile, 0777);
        if (unlink($localFile) === false) {
            throw new P4_File_Exception("Failed to delete local file.");
        }

        return $this;
    }
P4_File::edit ( change = null,
fileType = null,
force = true 
)

Open the file for edit.

If the file is opened for delete, the file will be reverted and then edited unless the force flag has been set to false.

Parameters:
int$changeoptional - a numbered pending change to open the file in.
string$fileTypeoptional - the file-type to open the file as.
bool$forceoptional - defaults to true - set to false to avoid reopening.
Returns:
P4_File provide fluent interface.
    {
        // If our 'have' rev and our 'head' revision aren't the
        // same value throw an exception (caller needs to sync).
        if (!$this->hasStatusField('haveRev')
            || $this->getStatus('headRev') != $this->getStatus('haveRev')
        ) {
            throw new P4_File_Exception(
                'Workspace file is not at specified revision; unable to edit'
            );
        }

        return $this->_openForAction('edit', $change, $fileType, $force);
    }
static P4_File::exists ( filespec,
P4_Connection_Interface connection = null,
excludeDeleted = false 
) [static]

Check if the given filespec is known to Perforce.

Parameters:
string$filespeca filespec with no wildcards.
P4_Connection_Interface$connectionoptional - a specific connection to use.
bool$excludeDeletedoptional - exclude deleted files (defaults to false).
Returns:
bool|int head revision number or false if filespec doesn't exist
    {
        static::_validateFilespec($filespec);

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

        // run files to see if file exists.
        $result = $connection->run('files', $filespec);
        if ($result->hasWarnings()) {
            return false;
        } elseif ($excludeDeleted && strstr($result->getData(0, 'action'), 'delete') !== false) {
            return false;
        } else {
            $rev = $result->getData(0, 'rev');

            // this really shouldn't happen; just being defensive
            if ($rev === false) {
                throw new P4_File_Exception('Failed to capture revision during existance test');
            }

            return $rev;
        }
    }
static P4_File::fetch ( filespec,
P4_Connection_Interface connection = null 
) [static]

Fetch a model of the given filespec.

Parameters:
string$filespeca filespec with no wildcards - the filespec may be in any one of depot, client or local file syntax.
P4_Connection_Interface$connectionoptional - a specific connection to use.
    {
        // if no connection given, use default.
        $connection = $connection ?: static::getDefaultConnection();

        // determine whether the file exists.
        $rev = self::exists($filespec, $connection);
        if ($rev === false) {
            throw new P4_File_NotFoundException(
                "Cannot fetch file '$filespec'. File does not exist."
            );
        }

        // create new file instance and set the key.
        $file = new static($connection);
        $file->setFilespec($filespec);
        $file->_cache['revision'] = $rev;
        return $file;
    }
static P4_File::fetchAll ( query,
P4_Connection_Interface connection = null 
) [static]

Fetch all files matching the given query.

Parameters:
P4_File_Query | array$queryA query object or array expressing fstat options.
P4_Connection_Interface$connectionoptional - a specific connection to use.
Returns:
P4_Model_Iterator List of retrieved files.
Exceptions:
InvalidArgumentExceptionif no filespec is given.
    {
        if (!$query instanceof P4_File_Query && !is_array($query)) {
            throw new InvalidArgumentException(
                'Query must be a P4_File_Query or array.'
            );
        }

        // normalize array input to a query
        if (is_array($query)) {
            $query = new P4_File_Query($query);
        }

        // ensure caller provided a filespec.
        if (!count($query->getFilespecs())) {
            throw new InvalidArgumentException(
                'Cannot fetch files. No filespecs provided in query.'
            );
        }

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

        // get fstat flags for given query options and run fstat command.
        $flags  = array_merge($query->getFstatFlags(), $query->getFilespecs());

        // try/catch parent to deal with the exception we get on non-existend depots
        try {
            $result = $connection->run('fstat', $flags);
        } catch (P4_Connection_CommandException $e) {
            // if the 'depot' has been interpreted as an invalid client, just return no matches
            if (preg_match("/Command failed: .+ - must refer to client/", $e->getMessage())) {
                return new P4_Model_Iterator;
            }

            // unexpected error; rethrow it
            throw $e;
        }

        // if fetching by change, the last block of data contains
        // the change description - remove it (unless we're fetching
        // from the default changelist)
        $dataBlocks = $result->getData();
        if ($query->getLimitToChangelist() !== null
            && $query->getLimitToChangelist() !== P4_Change::DEFAULT_CHANGE) {
            array_pop($dataBlocks);
        }

        // generate file models from fstat output.
        $files = new P4_Model_Iterator;
        foreach ($dataBlocks as $data) {
            $file = new static($connection);
            $file->setFilespec($data['depotFile']);
            $file->setStatusCache($data);

            $files[] = $file;
        }

        return $files;
    }
P4_File::flush ( )

Flush the file - tells the server we have the file.

Returns:
P4_File provide fluent interface.
Exceptions:
P4_File_Exceptionif the flush fails.
    {
        return $this->sync(false, true);
    }
P4_File::getAnnotateContent ( )

Get the annotated contents of the file in Perforce.

Annotated file content is fetched once and then cached in the instance. The cache can be primed via setAnnotateCache(). It can be cleared via clearAnnotateCache().

Returns:
array an array of the file's lines, where each array entry looks like:

array( 'upper' => <upper version="" number>="">, 'lower' => <lower version="" number>="">, 'data' => <text data="" for="" the="" current="" line>="">, )

    {
        if (
            !array_key_exists('annotatedContent', $this->_cache)
            || !isset($this->_cache['annotatedContent'])
        ) {
            // verify we have a filespec set; throws if invalid/missing
            $this->_validateHasFilespec();

            $result = $this->getConnection()->run('annotate', $this->getFilespec(true));
            $annotate = $result->getData();
            // remove the command's metadata
            array_shift($annotate);
            $this->_cache['annotatedContent'] = $annotate;
        }
        return $this->_cache['annotatedContent'];
    }
P4_File::getAttribute ( attribute)

Get the named attribute from the set of submitted attributes on this file.

Submitted attributes are attributes that have been committed to the depot.

Parameters:
string$attributethe name of the attribute to get the value of.
Returns:
string the value of the attribute.
    {
        return $this->getStatus('attr-' . $attribute);
    }
P4_File::getAttributes ( open = false)

Get all submitted attributes of this file.

Submitted attributes are attributes that have been committed to the depot.

Parameters:
bool$openoptional - get open attributes - defaults to false.
Returns:
array all attributes of the file.
    {
        $attributes = array();
        foreach ($this->getStatus() as $field => $value) {
            if (!$open && substr($field, 0, 5) == 'attr-') {
                $attributes[substr($field, 5)] = $value;
            } else if ($open && substr($field, 0, 9) == 'openattr-') {
                $attributes[substr($field, 9)] = $value;
            }
        }
        return $attributes;
    }
P4_File::getBasename ( suffix = null)

Get the basename of the file.

Parameters:
string$suffixif filename ends in this suffix it will be cut off.
Returns:
string the basename of the file.
    {
        // verify we have a filespec set; throws if invalid/missing
        $this->_validateHasFilespec();

        return basename($this->getFilespec(true), $suffix);
    }
P4_File::getChange ( )

Convenience function to return the change object associated with the file at its current revspec.

Returns:
P4_Change The associated change object.
    {
        return P4_Change::fetch($this->getStatus('headChange'), $this->getConnection());
    }
P4_File::getChanges ( array $  options = null)

Convienence function to return all changes associated with this file.

Parameters:
array$optionsoptional - array of options to augment fetch behavior. supported options are the same as P4_Change, except for the use of FETCH_BY_FILESPEC which is not permitted here.
Returns:
P4_Iterator Iterator of P4_Changes
    {
        $this->_validateHasFilespec();

        $options = array_merge(
            (array) $options,
            array(P4_Change::FETCH_BY_FILESPEC => $this->getFilespec(true))
        );

        return P4_Change::fetchAll($options, $this->getConnection());
    }
P4_File::getDepotContents ( )

Get the contents of the file in Perforce.

File content is fetched once and then cached in the instance. The cache can be primed via setContentCache(). It can be cleared via clearContentCache().

Returns:
string the contents of the file in the depot.
Exceptions:
P4_File_Exceptionif the print command fails.
    {
        if (!array_key_exists('content', $this->_cache)) {
            // verify we have a filespec set; throws if invalid/missing
            $this->_validateHasFilespec();

            $result = $this->getConnection()->run('print', $this->getFilespecWithRevision());

            // check for warnings.
            if ($result->hasWarnings()) {
                throw new P4_File_Exception(
                    "Failed to get depot contents: " . implode(", ", $result->getWarnings())
                );
            }

            $print  = static::_parsePrintOutput($result->getData());

            // get first element
            $print  = reset($print);

            $this->_cache['content']  = $print['content'];
            $this->_cache['revision'] = $print['rev'];
        }
        return $this->_cache['content'];
    }
P4_File::getDepotFilename ( )

Get the path to the file in depot file syntax.

Returns:
string the path to the file in depot file syntax.
    {
        // verify we have a filespec set; throws if invalid/missing
        $this->_validateHasFilespec();

        $filespec = $this->getFilespec(true);

        // if filespec is in depot-file syntax, return it.
        // note, we must verify that it doesn't start with the client name.
        $clientPrefix = "//" . $this->getConnection()->getClient() . "/";
        if (strlen($filespec) >=2 && substr($filespec, 0, 2) == '//' &&
            substr($filespec, 0, strlen($clientPrefix)) != $clientPrefix) {
            return $filespec;
        }

        // otherwise, get depot file from p4 where.
        $where = $this->where();
        return $where[0];
    }
P4_File::getDepotPath ( )

Get the depot path to the file.

Returns:
string the depot path to the file.
    {
        return dirname($this->getDepotFilename());
    }
P4_File::getFields ( )

Return array with all model fields.

Returns:
array

Implements P4_ModelInterface.

    {
        return array_keys($this->getStatus());
    }
P4_File::getFileSize ( )

Get the file's size in the depot.

Returns:
int the depot file's size in bytes, or zero.
    {
        if (!$this->hasStatusField('fileSize')) {
            throw new P4_File_Exception('The file does not have a fileSize attribute.');
        }
        return (int) $this->getStatus('fileSize');
    }
P4_File::getFilespec ( stripRevspec = false)

Get the filespec used to identify this file.

If a revision specifier was passed to setFilespec or fetch, it will be returned here; otherwise, no revision specifier will be present.

Parameters:
bool$stripRevspecoptional - revspecs will be removed, if present, when true
Returns:
string the filespec of the file.
    {
        return $stripRevspec ? static::stripRevspec($this->_filespec) : $this->_filespec;
    }
P4_File::getFilespecWithRevision ( )

Get the filespec used to identify this file including a revision specification if one is known.

If getFilespec includes a revspec, this value is used. Otherwise, if we have fetched file contents or status the corresponding numeric revision is used.

Returns:
string the filespec with a revision specifier if one is known.
    {
        $filespec = $this->getFilespec();

        if ($filespec === null || static::hasRevspec($filespec)) {
            return $filespec;
        }

        $revision = '';
        if (isset($this->_cache['revision'])) {
            $revision = '#' . $this->_cache['revision'];
        }

        return $this->_filespec . $revision;
    }
P4_File::getLocalContents ( )

Get the contents of the local file in the client workspace.

Returns:
string the contents of the local client file.
    {
        if (!file_exists($this->getLocalFilename())) {
            throw new P4_File_Exception(
                'Cannot get local file contents. Local file does not exist.'
            );
        }
        return file_get_contents($this->getLocalFilename());
    }
P4_File::getLocalFilename ( )

Get the path to the file in local file syntax.

Returns:
string the path to the file in local file syntax.
    {
        // verify we have a filespec set; throws if invalid/missing
        $this->_validateHasFilespec();

        $filespec = $this->getFilespec(true);

        // if filespec is in local-file syntax return it.
        if (strlen($filespec) >=2 && substr($filespec, 0, 2) != '//') {
            return $filespec;
        }

        // otherwise, get local filename from p4 where.
        $where = $this->where();
        return $where[2];
    }
P4_File::getLocalFileSize ( )

Get the size of the local client file.

Returns:
int the local file's size in bytes, or zero.
    {
        if (!file_exists($this->getLocalFilename())) {
            throw new P4_File_Exception('The local file does not exist.');
        }
        return (int) filesize($this->getLocalFilename());
    }
P4_File::getLocalPath ( )

Get the local path to the file.

Returns:
string the local path to the file.
    {
        return dirname($this->getLocalFilename());
    }
P4_File::getOpenAttribute ( attribute)

Get the named attribute from the set of pending attributes on this file.

Pending attributes are attributes that have been written to the client but are not yet submitted to the depot.

Parameters:
string$attributethe name of the open attribute to get the value of.
Returns:
string the value of the attribute.
    {
        return $this->getStatus('openattr-' . $attribute);
    }
P4_File::getOpenAttributes ( )

Get all pending attributes for this file.

Pending attributes are attributes that have been written to the client but are not yet submitted to the depot.

Returns:
array all pending attributes of the file.
    {
        return $this->getAttributes(true);
    }
P4_File::getStatus ( field = null)

Get file status (run fstat on file).

File status is fetched once and then cached in the instance. The cache can be primed via setStatusCache(). It can be cleared via clearStatusCache().

Attributes are fetched along with the status.

Parameters:
string$fieldoptional - a specific status field to get. by default all fields are returned.
Exceptions:
P4_File_Exceptionif the requested status field does not exist.
    {
        // if cache is not primed, run fstat.
        if (!array_key_exists('status', $this->_cache) || !isset($this->_cache['status'])) {
            // verify we have a filespec set; throws if invalid/missing
            $this->_validateHasFilespec();

            $result = $this->getConnection()->run(
                'fstat',
                array('-Oal', $this->getFilespecWithRevision())
            );
            if ($result->hasWarnings()) {
                throw new P4_File_Exception(
                    "Cannot get status: " . implode(", ", $result->getWarnings())
                );
            }

            if (is_array($result->getData(0))) {
                $this->setStatusCache($result->getData(0));
            } else {
                $this->setStatusCache(array());
            }
        }

        // return a specific field or all fields as appropriate.
        if ($field) {
            if (!array_key_exists($field, $this->_cache['status'])) {
                throw new P4_File_Exception("Can't fetch status. The requested field ('"
                    . $field . "') does not exist.");
            } else {
                return $this->_cache['status'][$field];
            }
        } else {
            return $this->_cache['status'];
        }
    }
P4_File::getValue ( field)

Return value of given field of the model.

Parameters:
string$fieldmodel field to retrieve
Returns:
mixed

Implements P4_ModelInterface.

    {
        return $this->getStatus($field);
    }
P4_File::hasAttribute ( attribute)

Check if the file has the named attribute.

Parameters:
string$attributethe name of the attribute to check for.
Returns:
bool true if the file has an attribute with this name.
    {
        return array_key_exists($attribute, $this->getAttributes());
    }
P4_File::hasField ( field)

Check if given field is valid model field.

Parameters:
string$fieldmodel field to check
Returns:
boolean

Implements P4_ModelInterface.

    {
        return $this->hasStatusField($field);
    }
P4_File::hasOpenAttribute ( attribute)

Check if the file has the named open attribute.

Parameters:
string$attributethe name of the open attribute to check for.
Returns:
bool true if the file has an open attribute with this name.
    {
        return array_key_exists($attribute, $this->getOpenAttributes());
    }
static P4_File::hasRevspec ( filespec) [static]

Check if the given filespec has a revision specifier.

Parameters:
string$filespecthe filespec to check for a revspec.
Returns:
bool true if the filespec has a revspec component.
    {
        if (strpos($filespec, "#") !== false ||
            strpos($filespec, "@") !== false) {
            return true;
        }
        return false;
    }
P4_File::hasStatusField ( field)

Determine if this file has the named status field.

Parameters:
string$fieldthe name of the field to check for.
Returns:
bool true if the field exists.
    {
        try {
            $this->getStatus($field);
            return true;
        } catch (P4_File_Exception $e) {
            return false;
        }
    }
P4_File::isDeleted ( )

Test if a file is deleted in the depot.

Note: this method reports the deleted status based on the filespec, which could be a non-head revision.

Returns:
boolean indicated whether the file is deleted.
    {
        $headAction = $this->getStatus('headAction');
        if (preg_match('/delete/', $headAction)) {
            return true;
        }
        return false;
    }
P4_File::isHead ( )

Checks if this file is at the head revision or not.

Returns:
bool true if the file is at head, false otherwise
    {
        $head = static::exists($this->getFilespec(true), $this->getConnection());

        if ($head === $this->getStatus('headRev')) {
            return true;
        }

        return false;
    }
P4_File::isOpened ( )

Check if the file is opened in Perforce by the current client.

Returns:
bool true if the file is opened by the current client.
    {
        if ($this->hasStatusField('action')) {
            return true;
        } else {
            return false;
        }
    }
P4_File::lock ( )

Lock this file in the depot.

Returns:
P4_File provide fluent interface.
    {
        // verify we have a filespec set; throws if invalid/missing
        $this->_validateHasFilespec();

        $this->getConnection()->run('lock', $this->getFilespec(true));

        // status has changed - clear the status cache.
        $this->clearStatusCache();

        return $this;
    }
P4_File::needsResolve ( )

Used to check if the file requires resolve or not.

This function will return true only when a resolve is scheduled. It doesn't attempt to look at the current state and estimate if calling 'submit' would result in an unresolved exception.

Returns:
bool true if file is resolved, false otherwise
    {
        $this->_validateHasFilespec();

        $result = $this->getConnection()->run(
            'resolve',
            '-n',
            $this->getFilespecWithRevision()
        );

        return (bool) $result->hasData();
    }
P4_File::open ( change = null,
fileType = null,
force = true 
)

Open file for add or edit as appropriate.

If the file is open for delete, revert and edit unless force=false. Will sync the file before opening it for edit.

Parameters:
int$changeoptional - a numbered pending change to open the file in.
string$fileTypeoptional - the file-type to open the file as.
bool$forceoptional - defaults to true - reverts files that are open for delete then reopens them. if false, files that are open for delete will result in an exception being thrown.
Returns:
P4_File provide fluent interface.
    {
        // verify we have a filespec set; throws if invalid/missing
        $this->_validateHasFilespec();

        // add the file if it doesn't exist or is deleted at head - otherwise edit.
        if (!static::exists($this->getFilespecWithRevision(), $this->getConnection()) ||
            $this->getStatus('headAction') == 'delete') {
            $this->add($change, $fileType);
        } else {
            $this->sync(true);
            $this->edit($change, $fileType, $force);
        }

        return $this;
    }
P4_File::reopen ( change = null,
type = null 
)

Open the file in another change and/or as a different filetype.

Parameters:
string$changethe change list to open the file in.
string$typethe filetype to open the file as.
Exceptions:
InvalidArgumentExceptionif neither a change nor a type are given.
Returns:
P4_File provide fluent interface.
    {
        // verify we have a filespec set; throws if invalid/missing
        $this->_validateHasFilespec();

        // ensure user has specified a change and/or a type
        if (!$change && !$type) {
            throw new InvalidArgumentException(
                'Cannot reopen file. You must provide a change and/or a filetype.'
            );
        }

        $params = array();
        if ($change) {
            $params[] = '-c';
            $params[] = $change;
        }
        if ($type) {
            $params[] = '-t';
            $params[] = $type;
        }
        $params[] = $this->getFilespec(true);
        $this->getConnection()->run('reopen', $params);

        // status has changed - clear the status cache.
        $this->clearStatusCache();

        return $this;
    }
P4_File::resolve ( options)

Resolves the file 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

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

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

        // limit the resolve to just our file and let change do the work
        $options[P4_Change::RESOLVE_FILE] = $this->getFilespec(true);
        $this->getChange()->resolve($options);

        return $this;
    }
P4_File::revert ( options = null)

Revert the file.

Parameters:
string | array | null$optionsoptions to influence the operation: REVERT_UNCHANGED - only revert if unchanged
Returns:
P4_File provides fluent interface.
    {
        // verify we have a filespec set; throws if invalid/missing
        $this->_validateHasFilespec();

        // if the unchanged option is given, add -a flag.
        $params = array();
        $unchanged = in_array(static::REVERT_UNCHANGED, (array) $options);
        if ($unchanged) {
            $params[] = "-a";
        }

        $params[] = $this->getFilespec(true);

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

        // status has changed - clear the status cache.
        $this->clearStatusCache();

        return $this;
    }
P4_File::setAttribute ( key,
value,
propagate = true,
force = false 
)

Set the given attribute/value on the file.

By default attributes will propagate to new revisions of the file To disable this, set the propagate argument to false.

By default attributes will be pended. To write attributes to the depot directly, set the force flag to true.

Parameters:
string$keythe name of the attribute to write.
string | null$valuethe value to write.
bool$propagateoptional - defaults to true - propagate the attribute to new revisions.
bool$forceoptional - defaults to false - write the attribute to the depot directly.
Returns:
P4_File provide fluent interface.
    {
        // ensure attribute key name is valid.
        // we do this prior to forming the array as an
        // invalid key (e.g. an array) would cause an error.
        $validator = new P4_Validate_AttributeName;
        if (!$validator->isValid($key)) {
            throw new InvalidArgumentException("Cannot set attribute. Attribute name is invalid.");
        }

        return $this->setAttributes(array($key => $value), $propagate, $force);
    }
P4_File::setAttributes ( attributes,
propagate = true,
force = false 
)

Set attributes on this file.

Does not clear existing attributes.

Parameters:
array$attributesthe set of key/value pairs to set on the file.
bool$propagateoptional - defaults to true - automatically propagate the attributes to new revisions.
bool$forceoptional - write the attributes to the depot directly by default attributes are pended to the client workspace.
Returns:
P4_File provide fluent interface.
    {
        if (!is_array($attributes)) {
            throw new InvalidArgumentException(
                "Can't set attributes. Attributes must be an array."
            );
        }

        // if no attributes to set, nothing to do.
        if (empty($attributes)) {
            return $this;
        }

        // verify we have a filespec set; throws if invalid/missing
        $this->_validateHasFilespec();

        $params = array();
        foreach ($attributes as $key => $value) {
            $value = is_null($value) ? '' : $value;

            // ensure value is a string.
            if (!is_string($value)) {
                throw new InvalidArgumentException("Cannot set attribute. Value must be a string.");
            }

            // ensure attribute key name is valid.
            $validator = new P4_Validate_AttributeName;
            if (!$validator->isValid($key)) {
                throw new InvalidArgumentException("Cannot set attribute. Attribute name is invalid.");
            }

            // add params for attribute name/value.
            $params[] = '-n';
            $params[] = $key;
            $params[] = '-v';
            $params[] = bin2hex($value);
        }

        // setup shared inital parameters
        $prefixParams = array();
        if ($propagate) {
            $prefixParams[] = '-p';
        }
        if ($force) {
            $prefixParams[] = '-f';
        }

        // write value in binhex to avoid problems with binary data.
        $prefixParams[] = '-e';

        // permit revspec only if force writing attribute.
        $filespec = $force
            ? $this->getFilespecWithRevision()
            : $this->getFilespec(true);

        // see if we can set multiple attributes at once (for performance)
        // if we're unable (e.g. a value exceeds arg-max), set individually via input.
        $batches    = array();
        $connection = $this->getConnection();
        try {
            $batches = $connection->batchArgs($params, $prefixParams, array($filespec), 4);
        } catch (P4_Exception $e) {
            $prefixParams[] = '-i';
            foreach ($attributes as $key => $value) {
                $value  = is_null($value) ? '' : $value;
                $result = $this->getConnection()->run(
                    'attribute',
                    array_merge($prefixParams, array('-n', $key, $filespec)),
                    bin2hex($value)
                );

                // stop processing if we encounter warnings.
                if ($result->hasWarnings()) {
                    break;
                }
            }
        }

        // if we were able to batch the arguments, process them now.
        foreach ($batches as $batch) {
            $result = $this->getConnection()->run('attribute', $batch);

            // stop processing if we encounter warnings.
            if ($result->hasWarnings()) {
                break;
            }
        }

        if ($result->hasWarnings()) {
            throw new P4_File_Exception(
                "Failed to set attribute(s) on file: " . implode(", ", $result->getWarnings())
            );
        }

        // status has changed - clear the status cache.
        $this->clearStatusCache();

        return $this;
    }
P4_File::setContentCache ( content)

Prime the depot file cache with the given value.

Parameters:
string$contentthe contents of the file in the depot.
Returns:
P4_File provide fluent interface.
    {
        $this->_cache['content'] = $content;

        return $this;
    }
P4_File::setFilespec ( filespec)

Set the filespec identifier for the file/revision.

Filespec may be given in depot, client or local file-system syntax. The filename may be followed by a revision specifier. Wildcards are not permitted in the filespec.

For more information on filespecs visit: http://perforce.com/perforce/doc.current/manuals/cmdref/o.fspecs.html

Note: The instance cache is cleared when the filespec changes.

Parameters:
string$filespecthe filespec of the file.
Returns:
P4_File provide fluent interface.
    {
        static::_validateFilespec($filespec);
        $this->_filespec = $filespec;

        // identity has changed - clear all of the instance caches.
        $this->_cache = array();

        return $this;
    }
P4_File::setLocalContents ( content)

Write contents to the local client file.

If the file does not exist, it will be created.

Parameters:
string$contentthe content to write to the file
Exceptions:
P4_File_Exceptionif the file cannot be written.
Returns:
P4_File provide fluent interface.
    {
        $this->touchLocalFile();
        if (!is_writable($this->getLocalFilename())) {
            if (!chmod($this->getLocalFilename(), 0644)) {
                $message = "Failed to make local file writable.";
                throw new P4_File_Exception($message);
            }
        }
        if (file_put_contents($this->getLocalFilename(), $content) === false) {
            $message = "Failed to write local file.";
            throw new P4_File_Exception($message);
        }

        return $this;
    }
P4_File::setStatusCache ( status)

Set the file status cache to the given array of fields/values.

Parameters:
array$statusan array of field/value pairs.
Exceptions:
InvalidArgumentExceptionif the given value is not an array.
Returns:
P4_File provide fluent interface.
    {
        if (!is_array($status)) {
            throw new InvalidArgumentException('Cannot set status cache. Status must be an array.');
        }
        $this->_cache['status'] = $status;

        if (isset($status['headRev'])) {
            $this->_cache['revision'] = $status['headRev'];
        }

        return $this;
    }
static P4_File::stripRevspec ( filespec) [static]

Strip the revision specifier from a file specification.

This removes the #rev or @change component from a filespec.

Parameters:
string$filespecthe filespec to strip the revspec from.
Returns:
string the filespec without the revspec.
    {
        $revPos = strpos($filespec, "#");
        if ($revPos !== false) {
            $filespec = substr($filespec, 0, $revPos);
        }
        $revPos = strpos($filespec, "@");
        if ($revPos !== false) {
            $filespec = substr($filespec, 0, $revPos);
        }
        return $filespec;
    }
P4_File::submit ( description,
options = null 
)

Submit the file to perforce.

If the optional resolve flags are passed, an attempt will be made to automatically resolve/resubmit should a conflict occur.

Parameters:
string$descriptionthe change description.
null | string | array$optionsoptional resolve flags, to be used if conflict occurs. See resolve() for details.
Exceptions:
InvalidArgumentExceptionif no description is given.
Returns:
P4_File provide fluent interface.
    {
        // verify we have a filespec set; throws if invalid/missing
        $this->_validateHasFilespec();

        // ensure that we have a description.
        if (!is_string($description) || !strlen($description)) {
            throw new InvalidArgumentException(
                'Cannot submit. Description must be a non-empty string.'
            );
        }

        // ensure the file is in the default pending change.
        // this is required to avoid inadvertently affecting
        // a numbered pending change description and its files.
        if ($this->hasStatusField('change') && $this->getStatus('change') != 'default') {
            $this->reopen('default');
        }

        // setup the submit options
        $params   = array();
        $params[] = '-d';
        $params[] = $description;
        $params[] = $this->getFilespec(true);

        try {
            $this->getConnection()->run('submit', $params);
        } catch (P4_Connection_ConflictException $e) {
            // if there are no resolve options; re-throw the resolve exception
            if (empty($options)) {
                throw $e;
            }

            // re-do submit via our change as this will
            // attempt to do the resolve. note change presently
            // does a wasted try prior to resolve but hopefully
            // the use is seldom enough we don't take a notable
            // performance hit on it.
            $e->getChange()->submit(null, $options);
        }

        // file has changed - clear all of the instance caches.
        $this->_cache = array();

        // if we had a rev-spec previously, take it off
        $this->setFilespec($this->getFilespec(true));

        return $this;
    }
P4_File::sync ( force = false,
flush = false 
)

Sync the file from the depot.

Note when the P4_File is fetched, or if made via new the first time it is accessed and has a valid filespec, the revision is pinned at that point in time. Sync will always use the pinned revision which is not necessarily head.

Parameters:
bool$forceoptional - defaults to false - force sync the file.
bool$flushoptional - defaults to false - don't transfer the file.
Returns:
P4_File provide fluent interface.
Exceptions:
P4_File_Exceptionif sync fails.
    {
        // verify we have a filespec set; throws if invalid/missing
        $this->_validateHasFilespec();

        $params = array();
        if ($force) {
            $params[] = '-f';
        }
        if ($flush) {
            $params[] = '-k';
        }
        $params[] = $this->getFilespecWithRevision();
        $result = $this->getConnection()->run('sync', $params);

        // status has changed - clear the status cache.
        $this->clearStatusCache();

        // verify sync was successful.
        if ($result->hasWarnings()) {
            // if we had warnings throw if the haveRev doesn't equal the headRev
            // unless it is a deleted file in which case we expect a warning
            $haveRev = $this->hasStatusField('haveRev') ? $this->getStatus('haveRev') : -1;
            $headRev = $this->hasStatusField('headRev') ? $this->getStatus('headRev') : 0;
            if (!$this->isDeleted() && $headRev !== $haveRev) {
                throw new P4_File_Exception(
                    "Failed to sync file: " . implode(", ", $result->getWarnings())
                );
            }
        }

        return $this;
    }
P4_File::touchLocalFile ( )

Touch the local client file.

If the file does not exist, it will be created.

Exceptions:
P4_File_Exceptionif the file cannot be touched.
Returns:
P4_File provide fluent interface.
    {
        if (!is_dir($this->getLocalPath())) {
            $this->_createLocalPath();
        }
        if (!is_file($this->getLocalFilename())) {
            if (!touch($this->getLocalFilename())) {
                $message = "Failed to touch local file.";
                throw new P4_File_Exception($message);
            }
        }

        return $this;
    }
P4_File::unlock ( )

Unlock this file in the depot.

Returns:
P4_File provide fluent interface.
    {
        // verify we have a filespec set; throws if invalid/missing
        $this->_validateHasFilespec();

        $this->getConnection()->run('unlock', $this->getFilespec(true));

        // status has changed - clear the status cache.
        $this->clearStatusCache();

        return $this;
    }
P4_File::where ( )

Determine how this file maps through the client view.

Produces an array with three variations on the filespec. Depot-syntax, client-syntax and local file-system syntax (in that order).

Caches the result so that subsequent lookups do not incur the 'p4 where' command overhead.

Returns:
array three variations of the filespec: depot-syntax client-syntax and local-syntax (respectively).
Exceptions:
P4_File_Exceptionif the file is not mapped by the client.
    {
        if (!array_key_exists('where', $this->_cache) || !isset($this->_cache['where'])) {
            // verify we have a filespec set; throws if invalid/missing
            $this->_validateHasFilespec();

            $result = $this->getConnection()->run('where', $this->getFilespec(true));
            if ($result->hasWarnings()) {
                throw new P4_File_Exception("Where failed. File is not mapped.");
            }
            $this->_cache['where'] = array_values($result->getData(0));
        }
        return $this->_cache['where'];
    }

Member Data Documentation

P4_File::$_cache = array() [protected]
P4_File::$_filespec = null [protected]
const P4_File::ALL_FILES = '//...'
const P4_File::REVERT_UNCHANGED = 'unchanged'

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