117 lines
3.0 KiB
PHP
117 lines
3.0 KiB
PHP
<?php
|
|
|
|
/* --------------------------------------------------------------------
|
|
|
|
Chevereto
|
|
http://chevereto.com/
|
|
|
|
@author Rodolfo Berrios A. <http://rodolfoberrios.com/>
|
|
<inbox@rodolfoberrios.com>
|
|
|
|
Copyright (C) Rodolfo Berrios A. All rights reserved.
|
|
|
|
BY USING THIS SOFTWARE YOU DECLARE TO ACCEPT THE CHEVERETO EULA
|
|
http://chevereto.com/license
|
|
|
|
--------------------------------------------------------------------- */
|
|
|
|
namespace CHV;
|
|
use G, Exception;
|
|
|
|
class Lock {
|
|
|
|
static $expire_timeout = 15; // t=seconds
|
|
static $path;
|
|
|
|
function __construct($lock=NULL) {
|
|
self::$path = CHV_APP_PATH_CONTENT_LOCKS;
|
|
if(strlen($lock) > 0) {
|
|
$this->setLock($lock);
|
|
}
|
|
$this->expiration = self::$expire_timeout;
|
|
$this->id = $this->getId();
|
|
}
|
|
|
|
function getAPI() {
|
|
return 'default';
|
|
}
|
|
|
|
function getId() {
|
|
if(!isset($this->id)) {
|
|
$this->id = G\random_string(8) . md5(microtime(TRUE));
|
|
}
|
|
return $this->id;
|
|
}
|
|
|
|
function setID($id=NULL) {
|
|
$this->id = $id;
|
|
}
|
|
|
|
function setExpiration($time) {
|
|
$this->expiration = $time;
|
|
}
|
|
|
|
function setLock($lock) {
|
|
$this->lock = $lock;
|
|
}
|
|
|
|
// Magic wand here (binds ->check(), ->create() and ->destroy())
|
|
public function __call($name, $arguments) {
|
|
if(in_array($name, ['check', 'create', 'destroy'])) {
|
|
return $this->process($name, $arguments);
|
|
}
|
|
}
|
|
|
|
private function process($action) {
|
|
// Only accept things that look like a file name, not path or something else
|
|
$callee = debug_backtrace()[0];
|
|
$method = $callee['class'] . $callee['type'] . $callee['function'] . '()';
|
|
if(preg_replace('/[^\.\w\d-]/i', '', $this->lock) !== $this->lock) {
|
|
throw new LockException(sprintf('Invalid $lock argument \'%s\' passed in ' . $method, $this->lock));
|
|
}
|
|
$lock_folder = self::$path;
|
|
$lock_file = self::$path . $this->lock . '.lock';
|
|
clearstatcache(TRUE, $lock_file);
|
|
switch($action) {
|
|
case 'check':
|
|
if(!file_exists($lock_file)) {
|
|
return FALSE;
|
|
}
|
|
$contents = file_get_contents($lock_file);
|
|
if(strpos($contents, 'expires') !== FALSE) {
|
|
$contents = json_decode($contents);
|
|
}
|
|
if(isset($contents->expires)) {
|
|
$is_locked = $contents->expires > microtime(true);
|
|
if(!$is_locked) {
|
|
self::destroy();
|
|
}
|
|
return $is_locked;
|
|
}
|
|
break;
|
|
case 'create':
|
|
$contents = [
|
|
'id' => $this->id
|
|
];
|
|
$now = microtime(true);
|
|
if($this->expiration) {
|
|
$contents['expires'] = $now + (int)$this->expiration;
|
|
}
|
|
if(!is_dir(self::$path) && !@mkdir(self::$path)) {
|
|
throw new LockException('Unable to create lock folder in ' . $method);
|
|
}
|
|
if(file_put_contents($lock_file, json_encode($contents), LOCK_EX) === FALSE) {
|
|
throw new LockException('Unable to create ' . $this->lock . ' lock in ' . $method);
|
|
}
|
|
break;
|
|
case 'destroy':
|
|
if(file_exists($lock_file) && !@unlink($lock_file)) {
|
|
throw new LockException('Unable to destroy ' . $this->lock . ' lock in ' . $method);
|
|
}
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
}
|
|
class LockException extends Exception {} |