blob: 8f65318fb01794fb37f315dc5d8fbee7604b73bf [file] [log] [blame]
<?php
/**
* File containing the ezcWebdavLockPurger class.
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package Webdav
* @version //autogen//
* @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
*
* @access private
*/
/**
* Instances of this class are used to purge outdated locks.
*
* An instance of this class is used in {@link ezcWebdavLockAdministrator} to
* purge locks.
*
* @package Webdav
* @version //autogen//
*
* @access private
*/
class ezcWebdavLockPurger
{
/**
* The backend to operate on.
*
* @var ezcWebdavBackend
*/
protected $backend;
/**
* All collected lock properties under $path.
*
* @var array(ezcWebdavLockDiscoveryProperty)
*/
protected $lockProperties = array();
/**
* Lock tokens that need to be purged.
*
* @var array(string=>true)
*/
protected $locksToPurge = array();
/**
* Creates a new lock purger.
*
* After creation, the instance can be used to purge locks under a given
* path with {@link purgeLocks()}.
*
* @param ezcWebdavBackend $backend
*/
public function __construct( ezcWebdavBackend $backend )
{
$this->backend = $backend;
}
/**
* Purges locks under $path.
*
* Checks all active locks on any resource under $path. Purges every lock
* that has not been accessed for its $timeout value.
*
* @param string $path
*
* @throws ezcWebdavLockAdministrationException
* if searching for locks or purging an outdated lock failed.
*/
public function purgeLocks( $path )
{
$this->locksToPurge = array();
$this->lockProperties = array();
$propFindReq = new ezcWebdavPropFindRequest( $path );
$propFindReq->prop = new ezcWebdavBasicPropertyStorage();
$propFindReq->prop->attach( new ezcWebdavLockDiscoveryProperty() );
$propFindReq->setHeader( 'Depth', ezcWebdavRequest::DEPTH_INFINITY );
$propFindReq->validateHeaders();
$propFindMultistatusRes = $this->backend->propFind( $propFindReq );
if ( !( $propFindMultistatusRes instanceof ezcWebdavMultistatusResponse ) )
{
throw new ezcWebdavLockAdministrationException(
'Finding locks failed.',
$propFindMultistatusRes
);
}
$this->collectPurgeProperties( $propFindMultistatusRes );
if ( $this->locksToPurge !== array() )
{
$this->performPurge();
}
}
/**
* Collects lock properties and locks to purge.
*
* Iterates of the request response $res and stores all found {@link
* ezcWebdavLockDiscoveryProperty} elements in {@link $lockProperties}. In
* addition, records all lock tokens that are outdated for later purge in
* {@link $locksToPurge}.
*
* @param ezcWebdavMultistatusResponse $res
*/
protected function collectPurgeProperties( ezcWebdavMultistatusResponse $res )
{
$now = time();
foreach ( $res->responses as $propFindRes )
{
if ( !( $propFindRes instanceof ezcWebdavPropFindResponse ) )
{
continue;
}
foreach ( $propFindRes->responses as $propStatRes )
{
if ( $propStatRes->status === ezcWebdavResponse::STATUS_200
&& $propStatRes->storage->contains( 'lockdiscovery' )
)
{
$lockDiscoveryProp = clone $propStatRes->storage->get( 'lockdiscovery' );
$this->lockProperties[$propFindRes->node->path] = $lockDiscoveryProp;
foreach ( $lockDiscoveryProp->activeLock as $activeLock )
{
if ( $activeLock->lastAccess !== null )
{
$timeDiff = $now - $activeLock->lastAccess->format( 'U' );
if ( $timeDiff > $activeLock->timeout )
{
// Lock is outdated, record for purging
$this->locksToPurge[(string) $activeLock->token] = true;
}
}
}
}
}
}
}
/**
* Performs actual purging of locks.
*
* Iterates over {@link $lockProperties} and purges all locks of which the
* tokens have been collected in {$locksToPurge}.
*
* @return void
*
* @throws ezcWebdavLockAdministrationException
* in case purging of a lock failed.
*/
protected function performPurge()
{
foreach ( $this->lockProperties as $path => $lockDiscoveryProp )
{
$removeIds = array();
foreach ( $lockDiscoveryProp->activeLock as $id => $activeLock )
{
if ( isset( $this->locksToPurge[(string) $activeLock->token] ) )
{
$removeIds[] = $id;
}
}
if ( $removeIds !== array() )
{
foreach ( $removeIds as $id )
{
$lockDiscoveryProp->activeLock->offsetUnset( $id );
}
$propPatchReq = new ezcWebdavPropPatchRequest( $path );
$propPatchReq->updates = new ezcWebdavFlaggedPropertyStorage();
$propPatchReq->updates->attach(
$lockDiscoveryProp,
ezcWebdavPropPatchRequest::SET
);
$propPatchReq->validateHeaders();
$propPatchRes = $this->backend->propPatch( $propPatchReq );
if ( !( $propPatchRes instanceof ezcWebdavPropPatchResponse ) )
{
throw new ezcWebdavLockAdministrationException(
"PROPPATCH to remove timedout lock failed for '$path'.",
$propPatchRes
);
}
}
}
}
}
?>