diff --git a/lib/Alchemy/Phrasea/TaskManager/Job/WriteMetadataJob.php b/lib/Alchemy/Phrasea/TaskManager/Job/WriteMetadataJob.php index 4d4b04b76c..f80bac1616 100644 --- a/lib/Alchemy/Phrasea/TaskManager/Job/WriteMetadataJob.php +++ b/lib/Alchemy/Phrasea/TaskManager/Job/WriteMetadataJob.php @@ -145,7 +145,7 @@ class WriteMetadataJob extends AbstractJob } foreach ($tsub as $name => $file) { - $app['exiftool.writer']->erase($name != 'document' || $clearDoc); + $app['exiftool.writer']->erase($name != 'document' || $clearDoc, true); try { $app['exiftool.writer']->write($file, $metadatas); diff --git a/lib/classes/task/Scheduler.php b/lib/classes/task/Scheduler.php deleted file mode 100644 index 1b0cb6b667..0000000000 --- a/lib/classes/task/Scheduler.php +++ /dev/null @@ -1,630 +0,0 @@ -dependencyContainer = $application; - $this->logger = $logger; - $this->schedstatus = ''; - } - - protected function log($message) - { - $this->logger->addInfo($message); - - return $this; - } - - protected function sleep($nsec) - { - $nsec = (integer) $nsec; - if ($nsec < 0) { - throw new \InvalidArgumentException(sprintf("(%s) is not > 0")); - } - - $end = microtime(true) + $nsec; - while (microtime(true) < $end) { - usleep(10000); - } - } - - /** - * @throws Exception if scheduler is already running - * @todo doc all possible exception - */ - public function sigHandler($signal) - { - switch ($signal) { - case SIGCHLD: - $status = null; - $pid = pcntl_wait($status); - $exitstatus = pcntl_wexitstatus($status); - $this->log(sprintf("SIGCHLD (%s) received from pid=%s, status=%s, exitstatus=%s", $signal, $pid, var_export($status, true), $exitstatus)); - break; - case SIGINT: // ctrl C - $this->log(sprintf("SIGINT (%s) Ctrl-C received, schedstatus='tostop'", $signal)); - $this->schedstatus = 'tostop'; - break; - case SIGTERM: - $this->log(sprintf("SIGTERM (%s) received but ignored, http timeout ?", $signal)); - break; - } - } - - public function run() - { - //prevent scheduler to fail if GV_cli is not provided - if (isset($this->dependencyContainer['phraseanet.configuration']['binaries']['php_binary'])) { - $php = $this->dependencyContainer['phraseanet.configuration']['binaries']['php_binary']; - } else { - $finder = new PhpExecutableFinder(); - $php = $finder->find(); - } - - if ( ! is_executable($php)) { - throw new \RuntimeException('PHP cli is not provided in binary configuration'); - } - - $this->method = self::METHOD_PROC_OPEN; - - $nullfile = '/dev/null'; - - if (defined('PHP_WINDOWS_VERSION_BUILD')) { - $nullfile = 'NUL'; - } - - if (\task_manager::isPosixPcntlSupported()) { - // avoid php when a task ends - // pcntl_signal(SIGCHLD, SIG_IGN); // no zombies but no returnValue - // pcntl_signal(SIGCHLD, SIG_DFL); // with "declare(ticks=1)" returnValue ok but zombies - pcntl_signal(SIGCHLD, array($this, 'sigHandler')); // ok - pcntl_signal(SIGINT, array($this, 'sigHandler')); - pcntl_signal(SIGTERM, array($this, 'sigHandler')); - - $this->method = self::METHOD_FORK; - } - - $lockdir = $this->dependencyContainer['root.path'] . '/tmp/locks/'; - - for ($try = 1; true; $try ++) { - $lockfile = ($lockdir . 'scheduler.lock'); - if (($schedlock = fopen($lockfile, 'a+')) != FALSE) { - if (flock($schedlock, LOCK_EX | LOCK_NB) === FALSE) { - $this->log(sprintf("failed to lock '%s' (try=%s/4)", $lockfile, $try)); - if ($try == 4) { - $this->log("scheduler already running."); - fclose($schedlock); - - throw new Exception('scheduler already running.', self::ERR_ALREADY_RUNNING); - - return; - } else { - $this->sleep(2); - } - } else { - // locked - ftruncate($schedlock, 0); - fwrite($schedlock, '' . getmypid()); - fflush($schedlock); - - // for windows : unlock then lock shared to allow OTHER processes to read the file - // too bad : no critical section nor atomicity - flock($schedlock, LOCK_UN); - flock($schedlock, LOCK_SH); - break; - } - } - } - - $this->log(sprintf("running scheduler with method %s", $this->method)); - - $conn = $this->dependencyContainer['phraseanet.appbox']->get_connection(); - - $taskPoll = array(); // the poll of tasks - - $sleeptime = 3; - - $sql = "UPDATE sitepreff SET schedstatus='started'"; - $conn->exec($sql); - - $task_manager = $this->dependencyContainer['task-manager']; - - // set every 'auto-start' task to start - foreach ($task_manager->getTasks() as $task) { - if ($task->isActive()) { - if ( ! $task->getPID()) { - /* @var $task task_abstract */ - $task->resetCrashCounter(); - $task->setState(task_abstract::STATE_TOSTART); - } - } - } - - $this->schedstatus = 'started'; - $runningtask = 0; - $connwaslost = false; - - while ($this->schedstatus == 'started' || $runningtask > 0) { - while (1) { - try { - assert(is_object($conn)); - $ping = @$conn->ping(); - } catch (ErrorException $e) { - $ping = false; - } - if ($ping) { - break; - } - - unset($conn); - if (! $connwaslost) { - $this->log(sprintf("Warning : abox connection lost, restarting in 10 min.")); - } - $this->sleep(60 * 10); - try { - $conn = $this->dependencyContainer['phraseanet.appbox']->get_connection(); - } catch (ErrorException $e) { - $ping = false; - } - - $connwaslost = true; - } - if ($connwaslost) { - $this->log("abox connection restored"); - - $sql = 'UPDATE task SET crashed=0'; - $stmt = $conn->prepare($sql); - $stmt->execute(); - $stmt->closeCursor(); - - $connwaslost = false; - } - - if ($this->schedstatus == "started") { - $this->schedstatus = ''; - $row = NULL; - try { - $sql = "SELECT schedstatus FROM sitepreff"; - $stmt = $conn->prepare($sql); - $stmt->execute(); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - } catch (ErrorException $e) { - continue; - } - - if ($row) { - $this->schedstatus = $row["schedstatus"]; - } - } - - if ($this->schedstatus == 'tostop') { - $sql = 'UPDATE sitepreff SET schedstatus = "stopping"'; - $stmt = $conn->prepare($sql); - $stmt->execute(); - $stmt->closeCursor(); - - // if scheduler is stopped, stop the tasks - $sql = 'UPDATE task2 SET status="tostop" WHERE status != "stopped" and status != "manual"'; - $stmt = $conn->prepare($sql); - $stmt->execute(); - $stmt->closeCursor(); - $this->log("schedstatus == 'stopping', waiting tasks to end"); - } - - // initialy, all tasks are supposed to be removed from the poll - foreach ($taskPoll as $tkey => $task) { - $taskPoll[$tkey]["todel"] = true; - } - - foreach ($task_manager->getTasks(true) as $task) { - $tkey = "t_" . $task->getID(); - $status = $task->getState(); - - if ( ! isset($taskPoll[$tkey])) { - // the task is not in the poll, add it - - $arguments = array(); - if ($this->dependencyContainer['phraseanet.registry']->get('GV_PHP_INI')) { - $arguments[] = '-c'; - $arguments[] = $this->dependencyContainer['phraseanet.registry']->get('GV_PHP_INI'); - } - - $arguments = array_merge($arguments, array( - '-f', - $this->dependencyContainer['root.path'] . '/bin/console', - '--', - '-q', - 'task:run', - $task->getID(), '--runner=scheduler' - )); - - $taskPoll[$tkey] = array( - "task" => $task, - "current_status" => $status, - "cmd" => $php, - "args" => $arguments, - "killat" => null, - "sigterm_sent" => false, - "pid" => false - ); - if ($this->method == self::METHOD_PROC_OPEN) { - $taskPoll[$tkey]['process'] = NULL; - $taskPoll[$tkey]['pipes'] = NULL; - } - - $this->log( - sprintf( - "new Task %s, status=%s" - , $taskPoll[$tkey]["task"]->getID() - , $status - ) - ); - } else { - // the task is already in the poll, update its status - if ($taskPoll[$tkey]["current_status"] != $status) { - $this->log( - sprintf( - "Task %s, oldstatus=%s, newstatus=%s" - , $taskPoll[$tkey]["task"]->getID() - , $taskPoll[$tkey]["current_status"] - , $status - ) - ); - $taskPoll[$tkey]["current_status"] = $status; - } - // update the whole task object - unset($taskPoll[$tkey]["task"]); - $taskPoll[$tkey]["task"] = $task; - } - - unset($task); - - $taskPoll[$tkey]["todel"] = false; // this task exists, do not remove from poll - } - - // remove not-existing task from poll - foreach ($taskPoll as $tkey => $task) { - if ($task["todel"]) { - $this->log(sprintf("Task %s deleted", $taskPoll[$tkey]["task"]->getID())); - unset($taskPoll[$tkey]); - } - } - - // Launch task that are not yet launched - $runningtask = 0; - - foreach ($taskPoll as $tkey => $tv) { - $status = $tv['task']->getState(); - switch ($status) { - default: - $this->log(sprintf('Unknow status `%s`', $status)); - break; - - case task_abstract::STATE_TORESTART: - if ( ! $taskPoll[$tkey]['task']->getPID()) { - if ($this->method == self::METHOD_PROC_OPEN) { - @fclose($taskPoll[$tkey]["pipes"][1]); - @fclose($taskPoll[$tkey]["pipes"][2]); - @proc_close($taskPoll[$tkey]["process"]); - - $taskPoll[$tkey]["process"] = null; - } elseif ($this->method == self::METHOD_FORK) { - $pid = $taskPoll[$tkey]['pid']; - if ($pid) { - $status = NULL; - if (pcntl_waitpid($pid, $status, WNOHANG) === $pid) { - // pid has quit - $taskPoll[$tkey]['pid'] = false; - } - } - } - - if ($this->schedstatus == 'started') { - $taskPoll[$tkey]["task"]->setState(task_abstract::STATE_TOSTART); - } - // trick to start the task immediatly : DON'T break if ending with 'tostart' - // so it will continue with 'tostart' case ! - } else { - break; - } - - case task_abstract::STATE_TOSTART: - // if scheduler is 'tostop', don't launch a new task ! - if ($this->schedstatus != 'started') { - break; - } - - $taskPoll[$tkey]["killat"] = NULL; - - if ($this->method == self::METHOD_PROC_OPEN) { - if (! $taskPoll[$tkey]["process"]) { - - $nullfile = defined('PHP_WINDOWS_VERSION_BUILD') ? 'NUL' : '/dev/null'; - - $descriptors[1] = array('file', $nullfile, 'a+'); - $descriptors[2] = array('file', $nullfile, 'a+'); - - $taskPoll[$tkey]["process"] = proc_open( - escapeshellarg($taskPoll[$tkey]["cmd"]) . ' ' . implode(' ', array_map('escapeshellarg', $taskPoll[$tkey]["args"])) - , $descriptors - , $taskPoll[$tkey]["pipes"] - , $this->dependencyContainer['root.path'] . "/bin/" - , null - , array('bypass_shell' => true) - ); - - if (is_resource($taskPoll[$tkey]["process"])) { - // let the process lock and write it's pid - $sleepTimeout = microtime(true) + 10; - do { - usleep(500000); - if (null !== $taskPoll[$tkey]['task']->getPID()) { - break; - } - } while (microtime(true) < $sleepTimeout); - } - - if (is_resource($taskPoll[$tkey]["process"]) && ($pid = $taskPoll[$tkey]['task']->getPID()) !== null) { - $taskPoll[$tkey]['pid'] = $pid; - $this->log( - sprintf( - "Task %s '%s' started (pid=%s)" - , $taskPoll[$tkey]['task']->getID() - , $taskPoll[$tkey]["cmd"] . ' ' . implode(' ', $taskPoll[$tkey]["args"]) - , $pid - ) - ); - $runningtask ++; - } else { - $taskPoll[$tkey]["task"]->incrementCrashCounter(); - - @fclose($taskPoll[$tkey]["pipes"][1]); - @fclose($taskPoll[$tkey]["pipes"][2]); - @proc_close($taskPoll[$tkey]["process"]); - $taskPoll[$tkey]["process"] = null; - - $this->log( - sprintf( - "Task %s '%s' failed to start %d times" - , $taskPoll[$tkey]["task"]->getID() - , $taskPoll[$tkey]["cmd"] - , $taskPoll[$tkey]["task"]->getCrashCounter() - ) - ); - - if ($taskPoll[$tkey]["task"]->getCrashCounter() > 5) { - $taskPoll[$tkey]["task"]->setState(task_abstract::STATE_STOPPED); - } else { - $taskPoll[$tkey]["task"]->setState(task_abstract::STATE_TOSTART); - } - } - } - } elseif ($this->method == self::METHOD_FORK) { - $pid = pcntl_fork(); - if ($pid == -1) { - die("failed to fork"); - } elseif ($pid == 0) { - umask(0); - if (posix_setsid() < 0) { - die("Forked process could not detach from terminal\n"); - } - - // todo (if possible) : redirecting stdin, stdout to log files ? - - $this->log(sprintf("exec('%s %s')", $taskPoll[$tkey]["cmd"], implode(' ', $taskPoll[$tkey]["args"]))); - pcntl_exec($taskPoll[$tkey]["cmd"], $taskPoll[$tkey]["args"]); - } else { - // parent (scheduler) - $taskPoll[$tkey]['pid'] = $pid; - } - } - break; - - case task_abstract::STATE_STARTED: - $crashed = false; - // If no process, the task is probably manually ran - - if ($this->method == self::METHOD_PROC_OPEN) { - if ($taskPoll[$tkey]["process"]) { - $taskPoll[$tkey]["killat"] = NULL; - - if (is_resource($taskPoll[$tkey]["process"])) { - $proc_status = proc_get_status($taskPoll[$tkey]["process"]); - if ($proc_status['running']) { - $runningtask ++; - } else { - $crashed = true; - } - } else { - $crashed = true; - } - } - } - - if ( ! $crashed && ! $taskPoll[$tkey]['task']->getPID()) { - $crashed = true; - } - - if (! $crashed) { - $taskPoll[$tkey]["killat"] = NULL; - $runningtask ++; - } else { - // crashed ! - $taskPoll[$tkey]["task"]->incrementCrashCounter(); - - if ($this->method == self::METHOD_PROC_OPEN) { - @fclose($taskPoll[$tkey]["pipes"][1]); - @fclose($taskPoll[$tkey]["pipes"][2]); - @proc_close($taskPoll[$tkey]["process"]); - $taskPoll[$tkey]["process"] = null; - } - $this->log( - sprintf( - "Task %s crashed %d times" - , $taskPoll[$tkey]["task"]->getID() - , $taskPoll[$tkey]["task"]->getCrashCounter() - ) - ); - - if ($taskPoll[$tkey]["task"]->getCrashCounter() > 5) { - $taskPoll[$tkey]["task"]->setState(task_abstract::STATE_STOPPED); - } else { - $taskPoll[$tkey]["task"]->setState(task_abstract::STATE_TOSTART); - } - } - break; - - case task_abstract::STATE_TOSTOP: - - if ($taskPoll[$tkey]["killat"] === NULL) { - $taskPoll[$tkey]["killat"] = time() + self::TASKDELAYTOQUIT; - } - - $pid = $taskPoll[$tkey]['task']->getPID(); - if ($pid) { - // send ctrl-c to tell the task to CLEAN quit - // (just in case the task doesn't pool his status 'tostop' fast enough) - if (function_exists('posix_kill')) { - if (! $taskPoll[$tkey]['sigterm_sent']) { - posix_kill($pid, SIGTERM); - $this->log( - sprintf( - "SIGTERM sent to task %s (pid=%s)" - , $taskPoll[$tkey]["task"]->getID() - , $pid - ) - ); - } - } - - if (($dt = $taskPoll[$tkey]["killat"] - time()) < 0) { - // task still alive, time to kill - if ($this->method == self::METHOD_PROC_OPEN) { - proc_terminate($taskPoll[$tkey]["process"], 9); - @fclose($taskPoll[$tkey]["pipes"][1]); - @fclose($taskPoll[$tkey]["pipes"][2]); - proc_close($taskPoll[$tkey]["process"]); - $this->log( - sprintf( - "proc_terminate(...) done on task %s (pid=%s)" - , $taskPoll[$tkey]["task"]->getID() - , $pid - ) - ); - } else { // METHOD_FORK, I guess we have posix - posix_kill($pid, 9); - $this->log( - sprintf( - "SIGKILL sent to task %s (pid=%s)" - , $taskPoll[$tkey]["task"]->getID() - , $pid - ) - ); - } - } else { - $this->log( - sprintf( - "waiting task %s to quit (kill in %d seconds)" - , $taskPoll[$tkey]["task"]->getID() - , $dt - ) - ); - $runningtask ++; - } - } else { - $this->log( - sprintf( - "task %s has quit" - , $taskPoll[$tkey]["task"]->getID() - ) - ); - $taskPoll[$tkey]["task"]->setState(task_abstract::STATE_STOPPED); - } - - break; - - case task_abstract::STATE_STOPPED: - case task_abstract::STATE_TODELETE: - if ($this->method == self::METHOD_PROC_OPEN) { - if ($taskPoll[$tkey]["process"]) { - @fclose($taskPoll[$tkey]["pipes"][1]); - @fclose($taskPoll[$tkey]["pipes"][2]); - @proc_close($taskPoll[$tkey]["process"]); - - $taskPoll[$tkey]["process"] = null; - } - } elseif ($this->method == self::METHOD_FORK) { - $pid = $taskPoll[$tkey]['pid']; - if ($pid) { - $status = NULL; - if (pcntl_waitpid($pid, $status, WNOHANG) === $pid) { - // pid has quit - $taskPoll[$tkey]['pid'] = false; - } - } - } - break; - } - } - if(function_exists('pcntl_sigprocmask')) { - @pcntl_sigprocmask(SIG_BLOCK, array(SIGCHLD)); - } - $this->sleep(1); - for ($i = 0; $this->schedstatus=='started' && $i < $sleeptime; $i++) { - $this->sleep(1); - } - if(function_exists('pcntl_sigprocmask')) { - @pcntl_sigprocmask(SIG_UNBLOCK, array(SIGCHLD)); - } - } - - $sql = "UPDATE sitepreff SET schedstatus='stopped', schedpid='0'"; - $stmt = $conn->prepare($sql); - $stmt->execute(); - $stmt->closeCursor(); - - $this->log("Scheduler2 is quitting."); - - ftruncate($schedlock, 0); - fclose($schedlock); - - $this->log("Scheduler2 has quit.\n"); - } -} diff --git a/lib/classes/task/abstract.php b/lib/classes/task/abstract.php deleted file mode 100644 index 8ff35c1e59..0000000000 --- a/lib/classes/task/abstract.php +++ /dev/null @@ -1,909 +0,0 @@ - - */ - protected $records_done = 0; - - /** - * Maximum number of records before we restart the task - * - * @var - */ - protected $maxrecs; - - /** - * Boolean switch to stop the task - * - * @var - */ - protected $running = false; - - /** - * current number of loops done - * - * @var - */ - protected $loop = 0; - - /** - * max number of loops before the task is restarted - * - * @var - */ - protected $maxloops = 5; - - /** - * task state, either ok, maxmemory or maxrecords reached - * - * @var - */ - protected $current_state; - - /** - * maximum memory allowed - * - * @var - */ - protected $maxmegs; - protected $runner; - - /** - * delay between two loops - * - * @var - */ - protected $title; - protected $settings; - protected $crash_counter; - protected $status; - protected $active; - protected $debug = false; - protected $completed_percentage; - protected $period = 60; - protected $taskid = NULL; - protected $system = ''; - protected $dependencyContainer; - - public function __construct($taskid, Pimple $dependencyContainer, Logger $logger) - { - $this->dependencyContainer = $dependencyContainer; - - $this->logger = $logger; - - $this->taskid = (integer) $taskid; - - phrasea::use_i18n($this->dependencyContainer['locale']); - - $this->launched_by = array_key_exists("REQUEST_URI", $_SERVER) ? self::LAUCHED_BY_BROWSER : self::LAUCHED_BY_COMMANDLINE; - - try { - $conn = connection::getPDOConnection($this->dependencyContainer); - } catch (Exception $e) { - $this->log($e->getMessage()); - $this->log(("Warning : abox connection lost, restarting in 10 min.")); - - $this->sleep(60 * 10); - - $this->running = false; - - return ''; - } - $sql = 'SELECT crashed, pid, status, active, settings, name, completed, runner - FROM task2 WHERE task_id = :taskid'; - $stmt = $conn->prepare($sql); - $stmt->execute(array(':taskid' => $this->getID())); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - if (! $row) { - throw new Exception('Unknown task id'); - } - $this->title = $row['name']; - $this->crash_counter = (integer) $row['crashed']; - $this->active = ! ! $row['active']; - $this->settings = $row['settings']; - $this->runner = $row['runner']; - $this->completed_percentage = (int) $row['completed']; - $this->settings = $row['settings']; - - if (false !== $sx = @simplexml_load_string($this->settings)) { - $this->loadSettings($sx); - } - } - - /** - * - * @return string - */ - public function getClass() - { - return get_class($this); - } - - /** - * get the state of the task (task_abstract::STATE_*) - * - * @return String - */ - public function getState() - { - static $stmt = NULL; - $conn = connection::getPDOConnection($this->dependencyContainer); - if (! $stmt) { - $sql = 'SELECT status FROM task2 WHERE task_id = :taskid'; - $stmt = $conn->prepare($sql); - } - $stmt->execute(array(':taskid' => $this->taskid)); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - if (! $row) { - throw new Exception('Unknown task id'); - } - unset($conn); - - return $row['status']; - } - - /** - * to be overwritten by tasks : ECHO text to be included in in task interface - */ - public function printInterfaceHEAD() - { - - } - - /** - * to be overwritten by tasks : ECHO javascript to be included in in task interface - */ - public function printInterfaceJS() - { - - } - - /** - * - * @return boolean - */ - public function hasInterfaceHTML() - { - return method_exists($this, "getInterfaceHTML"); - } - - /** - * set the state of the task (task_abstract::STATE_*) - * - * @param String $status - * @throws Exception_InvalidArgument - */ - public function setState($status) - { - $av_status = array( - self::STATE_STARTED, - self::STATE_TOSTOP, - self::STATE_STOPPED, - self::STATE_TORESTART, - self::STATE_TOSTART, - self::STATE_TODELETE - ); - - if ( ! in_array($status, $av_status)) { - throw new Exception_InvalidArgument(sprintf('unknown status `%s`', $status)); - } - - $conn = connection::getPDOConnection($this->dependencyContainer); - - $sql = 'UPDATE task2 SET status = :status WHERE task_id = :taskid'; - $stmt = $conn->prepare($sql); - $stmt->execute(array(':status' => $status, ':taskid' => $this->getID())); - $stmt->closeCursor(); - $this->log(sprintf("task %d <- %s", $this->getID(), $status)); - } - - /** - * - * @param boolean $active 'active' means 'auto-start when scheduler starts' - * @return \task_abstract - */ - public function setActive($active) - { - $conn = connection::getPDOConnection($this->dependencyContainer); - - $sql = 'UPDATE task2 SET active = :active WHERE task_id = :taskid'; - $stmt = $conn->prepare($sql); - $stmt->execute(array(':active' => ($active ? '1' : '0'), ':taskid' => $this->getID())); - $stmt->closeCursor(); - - $this->active = ! ! $active; - - return $this; - } - - /** - * - * @param string $title - * @return \task_abstract - */ - public function setTitle($title) - { - $title = strip_tags($title); - $conn = connection::getPDOConnection($this->dependencyContainer); - - $sql = 'UPDATE task2 SET name = :title WHERE task_id = :taskid'; - $stmt = $conn->prepare($sql); - $stmt->execute(array(':title' => $title, ':taskid' => $this->getID())); - $stmt->closeCursor(); - - $this->title = $title; - - return $this; - } - - /** - * - * @param string $settings xml settings as STRING - * @throws Exception_InvalidArgument if not proper xml - * @return \task_abstract - */ - public function setSettings($settings) - { - $dom = new DOMDocument('1.0', 'UTF-8'); - $dom->preserveWhiteSpace = false; - $dom->formatOutput = true; - if (!@$dom->loadXML($settings)) { - throw new Exception_InvalidArgument('Bad XML'); - } - - $conn = connection::getPDOConnection($this->dependencyContainer); - - $sql = 'UPDATE task2 SET settings = :settings WHERE task_id = :taskid'; - $stmt = $conn->prepare($sql); - $stmt->execute(array(':settings' => $dom->saveXML(), ':taskid' => $this->getID())); - $stmt->closeCursor(); - - $this->settings = $settings; - - $this->loadSettings(simplexml_load_string($dom->saveXML())); - - return $this; - } - - /** - * - * @return \task_abstract - */ - public function resetCrashCounter() - { - $conn = connection::getPDOConnection($this->dependencyContainer); - - $sql = 'UPDATE task2 SET crashed = 0 WHERE task_id = :taskid'; - $stmt = $conn->prepare($sql); - $stmt->execute(array(':taskid' => $this->getID())); - $stmt->closeCursor(); - - $this->crash_counter = 0; - - return $this; - } - - /** - * - * @return int - */ - public function getCrashCounter() - { - return $this->crash_counter; - } - - /** - * - * @return int - */ - public function incrementCrashCounter() - { - $conn = connection::getPDOConnection($this->dependencyContainer); - - $sql = 'UPDATE task2 SET crashed = crashed + 1 WHERE task_id = :taskid'; - $stmt = $conn->prepare($sql); - $stmt->execute(array(':taskid' => $this->getID())); - $stmt->closeCursor(); - - return ++ $this->crash_counter; - } - - /** - * - * @return string - */ - public function getSettings() - { - return $this->settings; - } - - /** - * 'active' means 'auto-start when scheduler starts' - * - * @return boolean - * - */ - public function isActive() - { - return $this->active; - } - - /** - * - * @return int - */ - public function getCompletedPercentage() - { - return $this->completed_percentage; - } - - public static function getName() - { - throw new \LogicException('This method must be implemented'); - } - - public static function help() - { - throw new \LogicException('This method must be implemented'); - } - - /** - * - * @return enum (self::RUNNER_MANUAL or self::RUNNER_SCHEDULER) - */ - public function getRunner() - { - return $this->runner; - } - - /** - * - * @param enum $runner (self::RUNNER_MANUAL or self::RUNNER_SCHEDULER) - * @throws Exception_InvalidArgument - * @return \task_abstract - */ - public function setRunner($runner) - { - if ($runner != self::RUNNER_MANUAL && $runner != self::RUNNER_SCHEDULER) { - throw new Exception_InvalidArgument(sprintf('unknown runner `%s`', $runner)); - } - - $this->runner = $runner; - - $conn = connection::getPDOConnection($this->dependencyContainer); - $sql = 'UPDATE task2 SET runner = :runner WHERE task_id = :taskid'; - - $params = array( - ':taskid' => $this->getID() - , ':runner' => $this->runner - ); - - $stmt = $conn->prepare($sql); - $stmt->execute($params); - $stmt->closeCursor(); - - return $this; - } - - /** - * - * @return string - */ - public function getTitle() - { - return $this->title; - } - - /** - * - */ - public function delete() - { - if ( ! $this->getPID()) { // do not delete a running task - $conn = connection::getPDOConnection($this->dependencyContainer); - $sql = "DELETE FROM task2 WHERE task_id = :task_id"; - $stmt = $conn->prepare($sql); - $stmt->execute(array(':task_id' => $this->getID())); - $stmt->closeCursor(); - - $lock_file = $this->dependencyContainer['root.path'] . '/tmp/locks/task_' . $this->getID() . '.lock'; - @unlink($lock_file); - } - } - - /** - * set last execution time to now() - */ - public function setLastExecTime() - { - $conn = connection::getPDOConnection($this->dependencyContainer); - $sql = 'UPDATE task2 SET last_exec_time=NOW() WHERE task_id = :taskid'; - $stmt = $conn->prepare($sql); - $stmt->execute(array(':taskid' => $this->getID())); - $stmt->closeCursor(); - } - - /** - * Return the last time the task was executed - * - * @return null|\DateTime - */ - public function getLastExecTime() - { - $conn = connection::getPDOConnection($this->dependencyContainer); - - $sql = 'SELECT last_exec_time FROM task2 WHERE task_id = :taskid'; - $stmt = $conn->prepare($sql); - $stmt->execute(array(':taskid' => $this->getID())); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - $time = null; - if ($row['last_exec_time'] != '0000-00-00 00:00:00') { - $time = new \DateTime($row['last_exec_time']); - } - - return $time; - } - - /** - * - * @return null|integer - * pid (int) of the task - * NULL : the pid file is not locked (task no running) - */ - public function getPID() - { - $pid = NULL; - - $lockfile = $this->getLockfilePath(); - - if (($fd = fopen($lockfile, 'a+')) != FALSE) { - if (flock($fd, LOCK_EX | LOCK_NB) === FALSE) { - // already locked ? : task running - $pid = (integer) fgets($fd); - } else { - // can lock : not running - flock($fd, LOCK_UN); - } - fclose($fd); - } - - return $pid; - } - - /** - * set to false to ask the task to quit its loop - * @param boolean $stat - * - */ - public function setRunning($stat) - { - $this->running = $stat; - } - - protected function pause($when_started = 0) - { - $this->log($this->records_done . ' records done'); - if ($this->running) { // && $this->records_done == 0) - $when_started = time() - $when_started; - if ($when_started < $this->period) { - for ($t = $this->period - $when_started; $this->running && $t > 0; $t --) { - // DON'T do sleep($this->period - $when_started) because it prevents ticks ! - $s = $this->getState(); - if ($s == self::STATE_TOSTOP) { - $this->setState(self::STATE_STOPPED); - $this->running = FALSE; - } else { - $this->sleep(1); - } - } - } - } - } - - /** - * sleep n seconds - * - * @param int $nsec - * @throws \InvalidArgumentException - */ - protected function sleep($nsec) - { - $nsec = (integer) $nsec; - if ($nsec < 0) { - throw new \InvalidArgumentException(sprintf("(%s) is not > 0")); - } - - $end = microtime(true) + $nsec; - while ($this->running && microtime(true) < $end) { - usleep(10000); - } - } - - /** - * - * @return string fullpath to the pid file for the task - */ - private function getLockfilePath() - { - $lockdir = $this->dependencyContainer['root.path'] . '/tmp/locks/'; - $lockfilePath = ($lockdir . 'task_' . $this->getID() . '.lock'); - - return $lockfilePath; - } - - /** - * - * @return resource file descriptor of the OPENED pid file - * @throws Exception if file is already locked (task running) - */ - private function lockTask() - { - $lockfile = $this->getLockfilePath(); - - $lockFD = fopen($lockfile, 'a+'); - - $locker = true; - if (flock($lockFD, LOCK_EX | LOCK_NB, $locker) === FALSE) { - $this->log("runtask::ERROR : task already running."); - fclose($lockFD); - - throw new Exception('task already running.', self::ERR_ALREADY_RUNNING); - } - - // here we run the task - ftruncate($lockFD, 0); - fwrite($lockFD, '' . getmypid()); - fflush($lockFD); - - // for windows : unlock then lock shared to allow OTHER processes to read the file - // too bad : no critical section nor atomicity - flock($lockFD, LOCK_UN); - flock($lockFD, LOCK_SH); - - return $lockFD; - } - - final public function run($runner) - { - $lockFD = $this->lockTask(); - - $this->setRunner($runner); - $this->setState(self::STATE_STARTED); - - // run the real code of the task -into the task's class- (may throw an exception) - $exception = NULL; - try { - $this->run2(); - } catch (\Exception $exception) { - - } - - if ($this->getState() === self::STATE_STARTED && $this->runner === self::RUNNER_MANUAL) { - $this->setState(self::STATE_STOPPED); - } - - // in any case, exception or not, the task is ending so unlock the pid file - $this->unlockTask($lockFD); - - // if something went wrong, report - if ($exception) { - throw $exception; - } - } - - /** - * - * @param resource $lockFD file descriptor of the OPENED lock file - */ - private function unlockTask($lockFD) - { - flock($lockFD, LOCK_UN | LOCK_NB); - ftruncate($lockFD, 0); - fclose($lockFD); - - $lockfile = $this->getLockfilePath(); - @unlink($lockfile); - - switch ($this->getState()) { - case self::STATE_TODELETE: - $this->delete(); - break; - case self::STATE_TOSTOP: - $this->setState(self::STATE_STOPPED); - break; - } - } - - abstract protected function run2(); - - protected function processLoop(&$box, &$rs) - { - $ret = self::STATE_OK; - - $rowstodo = count($rs); - $rowsdone = 0; - - if ($rowstodo > 0) { - $this->setProgress(0, $rowstodo); - } - - foreach ($rs as $row) { - - try { - // process one record - $this->processOneContent($box, $row); - } catch (Exception $e) { - $this->log("Exception : " . $e->getMessage() . " " . basename($e->getFile()) . " " . $e->getLine()); - } - - $this->records_done ++; - $this->setProgress($rowsdone, $rowstodo); - - // post-process - $this->postProcessOneContent($box, $row); - - $rowsdone ++; - - $current_memory = memory_get_usage(); - if ($current_memory >> 20 >= $this->maxmegs) { - $this->log(sprintf("Max memory (%s M) reached (actual is %.02f M)", $this->maxmegs, ($current_memory >> 10) / 1024), self::LOG_ERROR); - $this->running = FALSE; - $ret = self::STATE_MAXMEGSREACHED; - } - - if ($this->records_done >= (integer) ($this->maxrecs)) { - $this->log(sprintf("Max records done (%s) reached (actual is %s)", $this->maxrecs, $this->records_done)); - $this->running = FALSE; - $ret = self::STATE_MAXRECSDONE; - } - - try { - if ($this->getState() == self::STATE_TOSTOP) { - $this->running = FALSE; - $ret = self::STATE_TOSTOP; - } - } catch (Exception $e) { - $this->running = FALSE; - } - - if (! $this->running) { - break; - } - } - // - // if nothing was done, at least check the status - if ($rowsdone == 0 && $this->running) { - - $current_memory = memory_get_usage(); - if ($current_memory >> 20 >= $this->maxmegs) { - $this->log(sprintf("Max memory (%s M) reached (current is %.02f M)", $this->maxmegs, ($current_memory >> 10) / 1024), self::LOG_ERROR); - $this->running = FALSE; - $ret = self::STATE_MAXMEGSREACHED; - } - - if ($this->records_done >= (integer) ($this->maxrecs)) { - $this->log(sprintf("Max records done (%s) reached (actual is %s)", $this->maxrecs, $this->records_done)); - $this->running = FALSE; - $ret = self::STATE_MAXRECSDONE; - } - - try { - $status = $this->getState(); - if ($status == self::STATE_TOSTOP) { - $this->running = FALSE; - $ret = self::STATE_TOSTOP; - } - } catch (Exception $e) { - $this->running = FALSE; - } - } - - if ($rowstodo > 0) { - $this->setProgress(0, 0); - } - - return $ret; - } - - protected function loadSettings(SimpleXMLElement $sx_task_settings) - { - $this->period = (integer) $sx_task_settings->period; - if ($this->period < self::MINPERIOD || $this->period > self::MAXPERIOD) { - $this->period = self::MINPERIOD; - } - - $this->maxrecs = (integer) $sx_task_settings->maxrecs; - if ($sx_task_settings->maxrecs < self::MINRECS || $sx_task_settings->maxrecs > self::MAXRECS) { - $this->maxrecs = self::MINRECS; - } - - $this->maxmegs = (integer) $sx_task_settings->maxmegs; - if ($sx_task_settings->maxmegs < self::MINMEGS || $sx_task_settings->maxmegs > self::MAXMEGS) { - $this->maxmegs = self::DEFMEGS; - } - - $this->record_buffer_size = (integer) $sx_task_settings->flush; - if ($sx_task_settings->flush < self::MINFLUSH || $sx_task_settings->flush > self::MAXFLUSH) { - $this->record_buffer_size = self::MINFLUSH; - } - } - - protected function incrementLoops() - { - if ($this->getRunner() == self::RUNNER_SCHEDULER && ++ $this->loop >= $this->maxloops) { - $this->log(sprintf(('%d loops done, restarting'), $this->loop)); - $this->setState(self::STATE_TORESTART); - - $this->running = false; - } - } - - public function log($message, $level=self::LOG_INFO) - { - // nb : self::log_levels ARE standard log levels, ok with monolog - $this->logger->addRecord($level, $message); - - return $this; - } - - public static function interfaceAvailable() - { - return true; - } - - public function getInterfaceHTML() - { - return ''; - } - - public function graphic2xml($oldxml) - { - return $oldxml; - } - - /** - * - * @param \Pimple $dependencyContainer - * @param string $class_name - * @param string $settings - * @return task_abstract - */ - public static function create(\Pimple $dependencyContainer, $settings = null) - { - $sql = 'INSERT INTO task2 - (task_id, usr_id_owner, status, crashed, active, - name, last_exec_time, class, settings) - VALUES - (null, 0, "stopped", 0, :active, - :name, "0000/00/00 00:00:00", :class, :settings)'; - - $domdoc = new DOMDocument(); - if ($settings && ! $domdoc->loadXML($settings)) { - throw new Exception('Invalid settings'); - } elseif (! $settings) { - $settings = static::getDefaultSettings($dependencyContainer['phraseanet.configuration']); - } - - $params = array( - ':active' => 1 - , ':name' => '' - , ':class' => get_called_class() - , ':settings' => $settings - ); - - $stmt = $dependencyContainer['phraseanet.appbox']->get_connection()->prepare($sql); - $stmt->execute($params); - $stmt->closeCursor(); - - $tid = $dependencyContainer['phraseanet.appbox']->get_connection()->lastInsertId(); - - $task = new static($tid, $dependencyContainer, $dependencyContainer['task-manager.logger']); - $task->setTitle($task->getName()); - - return $task; - } - - /** - * - * @return int id of the task - */ - public function getID() - { - return $this->taskid; - } - - /** - * - * @param int $done - * @param int $todo - * @return \task_abstract - */ - public function setProgress($done, $todo) - { - $p = ($todo > 0) ? ((100 * $done) / $todo) : -1; - - try { - $conn = connection::getPDOConnection($this->dependencyContainer); - $sql = 'UPDATE task2 SET completed = :p WHERE task_id = :taskid'; - $stmt = $conn->prepare($sql); - $stmt->execute(array( - ':p' => $p, - ':taskid' => $this->getID() - )); - $stmt->closeCursor(); - $this->completed_percentage = $p; - } catch (Exception $e) { - - } - - return $this; - } - - /** - * @param Configuration $config - * @param array $params - * @return string - */ - public static function getDefaultSettings(Configuration $config, array $params = array()) - { - return "\n\n"; - } -} diff --git a/lib/classes/task/appboxAbstract.php b/lib/classes/task/appboxAbstract.php deleted file mode 100644 index fc79b69b15..0000000000 --- a/lib/classes/task/appboxAbstract.php +++ /dev/null @@ -1,131 +0,0 @@ -running = TRUE; - while ($this->running) { - try { - $conn = connection::getPDOConnection($this->dependencyContainer); - } catch (Exception $e) { - $this->log($e->getMessage()); - if ($this->getRunner() == self::RUNNER_SCHEDULER) { - $this->log(("Warning : abox connection lost, restarting in 10 min.")); - - $this->sleep(60 * 10); - // because connection is lost we cannot change status to 'torestart' - // anyway the current status 'running' with no pid - // will enforce the scheduler to restart the task - } else { - // runner = manual : can't restart so simply quit - } - $this->running = FALSE; - - return; - } - - $this->setLastExecTime(); - - try { - $sql = 'SELECT settings FROM task2 WHERE task_id = :taskid'; - $stmt = $conn->prepare($sql); - $stmt->execute(array(':taskid' => $this->getID())); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - $this->records_done = 0; - $duration = time(); - } catch (Exception $e) { - // failed sql, simply return - $this->running = FALSE; - - return; - } - - if ($row) { - if (! $this->running) { - break; - } - - try { - $this->loadSettings(simplexml_load_string($row['settings'])); - } catch (Exception $e) { - $this->log($e->getMessage()); - continue; - } - - $process_ret = $this->process($this->dependencyContainer['phraseanet.appbox']); - - switch ($process_ret) { - case self::STATE_MAXMEGSREACHED: - case self::STATE_MAXRECSDONE: - if ($this->getRunner() == self::RUNNER_SCHEDULER) { - $this->setState(self::STATE_TORESTART); - $this->running = FALSE; - } - break; - - case self::STATE_TOSTOP: - $this->setState(self::STATE_TOSTOP); - $this->running = FALSE; - break; - - case self::STATE_TODELETE: // formal 'suicidable' - $this->setState(self::STATE_TODELETE); - $this->running = FALSE; - break; - } - } // if(row) - - $this->incrementLoops(); - - if ($this->running) { - $this->pause($duration); - } - } // while running - - return; - } - - /** - * - * @return - */ - protected function process(appbox $appbox) - { - $ret = self::STATE_OK; - - try { - // get the records to process - $rs = $this->retrieveContent($appbox); - - // process the records - $ret = $this->processLoop($appbox, $rs); - } catch (Exception $e) { - $this->log('Error : ' . $e->getMessage()); - } - - return $ret; - } -} diff --git a/lib/classes/task/databoxAbstract.php b/lib/classes/task/databoxAbstract.php deleted file mode 100644 index c8eb02befd..0000000000 --- a/lib/classes/task/databoxAbstract.php +++ /dev/null @@ -1,173 +0,0 @@ -running = TRUE; - while ($this->running) { - try { - $conn = connection::getPDOConnection($this->dependencyContainer); - } catch (PDOException $e) { - $this->log($e->getMessage(), self::LOG_ERROR ); - if ($this->getRunner() == self::RUNNER_SCHEDULER) { - $this->log("appbox connection lost, restarting in 10 min.", self::LOG_ERROR); - - $this->sleep(60 * 10); - // because connection is lost we cannot change status to 'torestart' - // anyway the current status 'running' with no pid - // will enforce the scheduler to restart the task - } else { - // runner = manual : can't restart so simply quit - $this->log("appbox connection lost, quit.", self::LOG_ERROR); - } - $this->running = FALSE; - - return; - } - - $this->setLastExecTime(); - try { - if ($this->mono_sbas_id) { - $sql = 'SELECT sbas_id, task2.* FROM sbas, task2 WHERE task_id=:taskid AND sbas_id=:sbas_id'; - $stmt = $conn->prepare($sql); - $stmt->execute(array(':taskid' => $this->getID(), ':sbas_id' => $this->mono_sbas_id)); - } else { - $sql = 'SELECT sbas_id, task2.* FROM sbas, task2 WHERE task_id = :taskid'; - $stmt = $conn->prepare($sql); - $stmt->execute(array(':taskid' => $this->getID())); - } - $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - $this->records_done = 0; - $duration = time(); - } catch (Exception $e) { - // failed sql, simply return - $this->running = FALSE; - - return; - } - - foreach ($rs as $row) { // every sbas - if (! $this->running) { - break; - } - - $this->sbas_id = (int) $row['sbas_id']; - $this->log(sprintf('This task works now on sbasid=%s ', $this->sbas_id), self::LOG_INFO); - - try { - // get the records to process - $databox = $this->dependencyContainer['phraseanet.appbox']->get_databox((int) $row['sbas_id']); - } catch (Exception $e) { - $this->log(sprintf('can\'t connect to sbas(%s) because "%s"', - $row['sbas_id'], - $e->getMessage()), - self::LOG_WARNING - ); - continue; - } - - try { - $this->loadSettings(simplexml_load_string($row['settings'])); - } catch (Exception $e) { - $this->log(sprintf('can\'t get get settings of task because "%s"', - $e->getMessage()), - self::LOG_WARNING - ); - continue; - } - - $process_ret = $this->processSbas($databox); - - // close the cnx to the dbox - $connbas = $databox->get_connection(); - if ($connbas instanceof PDO) { - $connbas->close(); - unset($connbas); - } - - switch ($process_ret) { - case self::STATE_MAXMEGSREACHED: - case self::STATE_MAXRECSDONE: - if ($this->getRunner() == self::RUNNER_SCHEDULER) { - $this->setState(self::STATE_TORESTART); - $this->running = FALSE; - } - break; - - case self::STATE_TOSTOP: - $this->setState(self::STATE_TOSTOP); - $this->running = FALSE; - break; - - case self::STATE_TODELETE: // formal 'suicidable' - // DO NOT SUICIDE IN THE LOOP, may have to work on other sbas !!! - $task_must_delete = TRUE; - break; - } - - $this->flushRecordsSbas(); - } - - $this->incrementLoops(); - - if ($this->running) { - $this->pause($duration); - } - } - - if ($task_must_delete) { - $this->setState(self::STATE_TODELETE); - $this->log('task will self delete', self::LOG_INFO); - } - - return; - } - - /** - * - * @return - */ - protected function processSbas(databox $databox) - { - $ret = self::STATE_OK; - - try { - // get the records to process - $rs = $this->retrieveSbasContent($databox); - - // process the records - $ret = $this->processLoop($databox, $rs); - } catch (Exception $e) { - $this->log($e->getMessage(), self::LOG_ERROR); - } - - return $ret; - } -} diff --git a/lib/classes/task/manager.php b/lib/classes/task/manager.php deleted file mode 100644 index 5f04f06132..0000000000 --- a/lib/classes/task/manager.php +++ /dev/null @@ -1,267 +0,0 @@ -app = $app; - $this->logger = $logger; - - return $this; - } - - public function getLogger() - { - return $this->logger; - } - - /** - * status of scheduler and tasks - * used do refresh the taskmanager page - * - * @return array - */ - public function toArray() - { - $ret = array( - 'time' => date("H:i:s"), - 'scheduler' => $this->getSchedulerState(), - 'tasks' => array() - ); - - foreach ($this->getTasks(true) as $task) { - if ($task->getState() == self::STATE_TOSTOP && $task->getPID() === NULL) { - // fix - $task->setState(self::STATE_STOPPED); - } - $id = $task->getID(); - $ret['tasks'][$id] = array( - 'id' => $id, - 'pid' => $task->getPID(), - 'crashed' => $task->getCrashCounter(), - 'completed' => $task->getCompletedPercentage(), - 'status' => $task->getState() - ); - } - - return $ret; - } - - public function getTasks($refresh = false) - { - if ($this->tasks && !$refresh) { - return $this->tasks; - } - - $sql = "SELECT task2.* FROM task2 ORDER BY task_id ASC"; - $stmt = $this->app['phraseanet.appbox']->get_connection()->prepare($sql); - $stmt->execute(); - $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - $tasks = array(); - - foreach ($rs as $row) { - $row['pid'] = NULL; - - $classname = $row['class']; - if (!class_exists($classname)) { - if(substr($classname, 0, 12) == "task_period_") { - $classfile = substr($classname, 12) . ".php"; - @require_once(__DIR__ . "/../../../config/classes/task/period/" . $classfile); - } - } - if (!class_exists($classname)) { - continue; - } - try { - $tasks[$row['task_id']] = new $classname($row['task_id'], $this->app, $this->logger); - } catch (Exception $e) { - - } - } - - $this->tasks = $tasks; - - return $this->tasks; - } - - /** - * - * @param int $task_id - * @return task_abstract - */ - public function getTask($task_id) - { - $tasks = $this->getTasks(false); - - if (!isset($tasks[$task_id])) { - throw new NotFoundHttpException('Unknown task_id ' . $task_id); - } - - return $tasks[$task_id]; - } - - public function getSchedulerProcess() - { - //prevent scheduler to fail if GV_cli is not provided - if (isset($this->app['phraseanet.configuration']['binaries']['php_binary'])) { - $php = $this->app['phraseanet.configuration']['binaries']['php_binary']; - } else { - $finder = new PhpExecutableFinder(); - $php = $finder->find(); - } - - $builder = ProcessBuilder::create(array($php)); - - if ($this->app['phraseanet.registry']->get('GV_PHP_INI')) { - $builder->add('-c')->add($this->app['phraseanet.registry']->get('GV_PHP_INI')); - } - - return $builder - ->add('-f') - ->add($this->app['root.path'] . "/bin/console") - ->add('scheduler:start') - ->getProcess(); - } - - public function setSchedulerState($status) - { - $av_status = array( - self::STATE_STARTED, - self::STATE_STOPPED, - self::STATE_STOPPING, - self::STATE_TOSTOP - ); - - if (!in_array($status, $av_status)) - throw new Exception(sprintf('unknown status `%s` ', $status)); - - if ($status == self::STATE_TOSTOP && function_exists('posix_kill')) { - $gs = $this->getSchedulerState(); - if ($gs['pid'] !== NULL) { - @posix_kill($gs['pid'], 2); // 2 = SIGINT - } - } - - $sql = "UPDATE sitepreff SET schedstatus = :schedstatus, schedqtime=NOW()"; - $stmt = $this->app['phraseanet.appbox']->get_connection()->prepare($sql); - $stmt->execute(array(':schedstatus' => $status)); - $stmt->closeCursor(); - - return $this; - } - - public function getSchedulerState() - { - $sql = "SELECT UNIX_TIMESTAMP()-UNIX_TIMESTAMP(schedqtime) AS qdelay - , schedqtime AS updated_on - , schedstatus AS status FROM sitepreff"; - $stmt = $this->app['phraseanet.appbox']->get_connection()->prepare($sql); - $stmt->execute(); - $ret = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - $pid = NULL; - - $lockdir = $this->app['root.path'] . '/tmp/locks/'; - if (($schedlock = fopen($lockdir . 'scheduler.lock', 'a+')) != FALSE) { - if (flock($schedlock, LOCK_EX | LOCK_NB) === FALSE) { - // already locked : running ! - $pid = trim(fgets($schedlock, 512)); - } else { - // can lock : not running - flock($schedlock, LOCK_UN); - } - fclose($schedlock); - } - - if ($ret['updated_on'] == '0000-00-00 00:00:00') { - $ret['updated_on'] = null; - } else { - $ret['updated_on'] = new \DateTime($ret['updated_on']); - } - - if ($pid === NULL && $ret['status'] !== 'stopped') { - // auto fix - $this->app['phraseanet.appbox']->get_connection()->exec('UPDATE sitepreff SET schedstatus=\'stopped\''); - $ret['status'] = 'stopped'; - } - $ret['pid'] = $pid; - - return $ret; - } - - /** - * Returns true if Pcntl posix supported is enabled, false otherwise - * - * @return Boolean - */ - public static function isPosixPcntlSupported() - { - return extension_loaded('pcntl') && extension_loaded('posix'); - } - - public static function getAvailableTasks() - { - $dirs = array(__DIR__ . "/period"); - - if (is_dir($configDir = __DIR__ . "/../../../config/classes/task/period")) { - $dirs[] = $configDir; - } - - $tasks = array(); - $finder = new Finder(); - - foreach ($finder->files()->in($dirs)->name("*.php") as $file) { - $classname = 'task_period_' . $file->getBasename('.php'); - - try { - if (!class_exists($classname)) { - @require_once($file->getRealPath()); - } - if (class_exists($classname) && $classname::interfaceAvailable()) { - $tasks[] = array( - "class" => $classname, - "name" => $classname::getName(), - "err" => null - ); - } - } catch (Exception $e) { - - } - } - - return $tasks; - } -} diff --git a/lib/classes/task/period/RecordMover.php b/lib/classes/task/period/RecordMover.php deleted file mode 100644 index e0e07ba11f..0000000000 --- a/lib/classes/task/period/RecordMover.php +++ /dev/null @@ -1,878 +0,0 @@ -get_parms('period', 'logsql'); - $dom = new DOMDocument(); - $dom->preserveWhiteSpace = false; - $dom->formatOutput = true; - - if ($dom->loadXML($oldxml)) { - foreach (array( - 'str:period' - , 'boo:logsql' - ) as $pname) { - $ptype = substr($pname, 0, 3); - $pname = substr($pname, 4); - $pvalue = $parm2[$pname]; - if (($ns = $dom->getElementsByTagName($pname)->item(0))) { - // field did exists, remove thevalue - while (($n = $ns->firstChild)) - $ns->removeChild($n); - } else { - // field did not exists, create it - $ns = $dom->documentElement->appendChild($dom->createElement($pname)); - } - // set the value - switch ($ptype) { - case "str": - case "pop": - $ns->appendChild($dom->createTextNode($pvalue)); - break; - case "boo": - $ns->appendChild($dom->createTextNode($pvalue ? '1' : '0')); - break; - } - } - } - - return $dom->saveXML(); - } - - /** - * PRINT head for the gui - */ - public function printInterfaceHEAD() - { - ?> - - - - -
-
- -
- - -
-
-
-
- -
-
-
-
-
-
- maxrecs = 1000; - $this->sxTaskSettings = simplexml_load_string($this->getSettings()); - if (false === $this->sxTaskSettings || !$this->sxTaskSettings->tasks) { - return array(); - } - - $ret = array(); - - $logsql = (int) ($this->sxTaskSettings->logsql) > 0; - - foreach ($this->sxTaskSettings->tasks->task as $sxtask) { - - if (!$this->running) { - break; - } - - $task = $this->calcSQL($sxtask); - - if (!$task['active']) { - continue; - } - - if ($logsql) { - $this->log(sprintf("playing task '%s' on base '%s'" - , $task['name'] - , $task['basename'] ? $task['basename'] : ''), self::LOG_INFO); - } - - try { - $connbas = connection::getPDOConnection($this->dependencyContainer, $task['sbas_id']); - } catch (Exception $e) { - $this->log(sprintf("can't connect sbas %s", $task['sbas_id']), self::LOG_ERROR); - continue; - } - - $stmt = $connbas->prepare($task['sql']['real']['sql']); - if ($stmt->execute(array())) { - while ($this->running && ($row = $stmt->fetch(PDO::FETCH_ASSOC)) !== FALSE) { - - $tmp = array('sbas_id' => $task['sbas_id'], 'record_id' => $row['record_id'], 'action' => $task['action']); - - $rec = new record_adapter($this->dependencyContainer, $task['sbas_id'], $row['record_id']); - switch ($task['action']) { - - case 'UPDATE': - - // change collection ? - if (($x = (int) ($sxtask->to->coll['id'])) > 0) { - $tmp['coll'] = $x; - } - - // change sb ? - if (($x = $sxtask->to->status['mask'])) { - $tmp['sb'] = $x; - } - $ret[] = $tmp; - break; - - case 'DELETE': - $tmp['deletechildren'] = false; - if ($sxtask['deletechildren'] && $rec->is_grouping()) { - $tmp['deletechildren'] = true; - } - $ret[] = $tmp; - break; - } - } - $stmt->closeCursor(); - } - } - - return $ret; - } - - /** - * work on ONE record - * - * @param appbox $appbox - * @param array $row - * @return \task_period_RecordMover - */ - protected function processOneContent(appbox $appbox, $row) - { - $logsql = (int) ($this->sxTaskSettings->logsql) > 0; - $databox = $this->dependencyContainer['phraseanet.appbox']->get_databox($row['sbas_id']); - $rec = new record_adapter($this->dependencyContainer, $row['sbas_id'], $row['record_id']); - switch ($row['action']) { - - case 'UPDATE': - - // change collection ? - if (array_key_exists('coll', $row)) { - $coll = collection::get_from_coll_id($this->dependencyContainer, $databox, $row['coll']); - $rec->move_to_collection($coll, $this->dependencyContainer['phraseanet.appbox']); - $this['phraseanet.SE']->updateRecord($rec); - if ($logsql) { - $this->log(sprintf("on sbas %s move rid %s to coll %s \n", $row['sbas_id'], $row['record_id'], $coll->get_coll_id())); - } - } - - // change sb ? - if (array_key_exists('sb', $row)) { - $status = str_split($rec->get_status()); - foreach (str_split(strrev($row['sb'])) as $bit => $val) { - if ($val == '0' || $val == '1') { - $status[31 - $bit] = $val; - } - } - $status = implode('', $status); - $rec->set_binary_status($status); - $this->dependencyContainer['phraseanet.SE']->updateRecord($rec); - if ($logsql) { - $this->log(sprintf("on sbas %s set rid %s status to %s \n", $row['sbas_id'], $row['record_id'], $status)); - } - } - break; - - case 'DELETE': - if ($row['deletechildren'] && $rec->is_grouping()) { - foreach ($rec->get_children() as $child) { - $child->delete(); - $this->dependencyContainer['phraseanet.SE']->removeRecord($child); - if ($logsql) { - $this->log(sprintf("on sbas %s delete (grp child) rid %s \n", $row['sbas_id'], $child->get_record_id())); - } - } - } - $rec->delete(); - $this->dependencyContainer['phraseanet.SE']->removeRecord($rec); - if ($logsql) { - $this->log(sprintf("on sbas %s delete rid %s \n", $row['sbas_id'], $rec->get_record_id())); - } - break; - } - - return $this; - } - - /** - * all work done on processOneContent, so nothing to do here - * - * @param appbox $appbox - * @param array $row - * @return \task_period_RecordMover - */ - protected function postProcessOneContent(appbox $appbox, $row) - { - return $this; - } - - /** - * compute sql for a task ( entry in settings) - * - * @param simplexml $sxtask - * @param boolean $playTest - * @return array - */ - private function calcSQL($sxtask, $playTest = false) - { - $sbas_id = (int) ($sxtask['sbas_id']); - - $ret = array( - 'name' => $sxtask['name'] ? (string) $sxtask['name'] : 'sans nom', - 'name_htmlencoded' => \p4string::MakeString(($sxtask['name'] ? $sxtask['name'] : 'sans nom'), 'html'), - 'active' => trim($sxtask['active']) === '1', - 'sbas_id' => $sbas_id, - 'basename' => '', - 'basename_htmlencoded' => '', - 'action' => strtoupper($sxtask['action']), - 'sql' => NULL, - 'err' => '', - 'err_htmlencoded' => '', - ); - - try { - $dbox = $this->dependencyContainer['phraseanet.appbox']->get_databox($sbas_id); - - $ret['basename'] = $dbox->get_label($this->dependencyContainer['locale.I18n']); - $ret['basename_htmlencoded'] = htmlentities($ret['basename']); - switch ($ret['action']) { - case 'UPDATE': - $ret['sql'] = $this->calcUPDATE($sbas_id, $sxtask, $playTest); - break; - case 'DELETE': - $ret['sql'] = $this->calcDELETE($sbas_id, $sxtask, $playTest); - $ret['deletechildren'] = (int) ($sxtask['deletechildren']); - break; - default: - $ret['err'] = "bad action '" . $ret['action'] . "'"; - $ret['err_htmlencoded'] = htmlentities($ret['err']); - break; - } - } catch (Exception $e) { - $ret['err'] = "bad sbas '" . $sbas_id . "'"; - $ret['err_htmlencoded'] = htmlentities($ret['err']); - } - - return $ret; - } - - /** - * compute entry for a UPDATE query - * - * @param integer $sbas_id - * @param simplexml $sxtask - * @param boolean $playTest - * @return array - */ - private function calcUPDATE($sbas_id, &$sxtask, $playTest) - { - $tws = array(); // NEGATION of updates, used to build the 'test' sql - // - // set coll_id ? - if (($x = (int) ($sxtask->to->coll['id'])) > 0) { - $tws[] = 'coll_id!=' . $x; - } - - // set status ? - $x = $sxtask->to->status['mask']; - $mx = str_replace(' ', '0', ltrim(str_replace(array('0', 'x'), array(' ', ' '), $x))); - $ma = str_replace(' ', '0', ltrim(str_replace(array('x', '0'), array(' ', '1'), $x))); - if ($mx && $ma) - $tws[] = '((status ^ 0b' . $mx . ') & 0b' . $ma . ')!=0'; - elseif ($mx) - $tws[] = '(status ^ 0b' . $mx . ')!=0'; - elseif ($ma) - $tws[] = '(status & 0b' . $ma . ')!=0'; - - // compute the 'where' clause - list($tw, $join) = $this->calcWhere($sbas_id, $sxtask); - - // ... complete the where to buid the TEST - if (count($tws) == 1) - $tw[] = $tws[0]; - elseif (count($tws) > 1) - $tw[] = '(' . implode(') OR (', $tws) . ')'; - if (count($tw) == 1) - $where = $tw[0]; - if (count($tw) > 1) - $where = '(' . implode(') AND (', $tw) . ')'; - - // build the TEST sql (select) - $sql_test = 'SELECT record_id FROM record' . $join; - if (count($tw) > 0) - $sql_test .= ' WHERE ' . ((count($tw) == 1) ? $tw[0] : '(' . implode(') AND (', $tw) . ')'); - - // build the real sql (select) - $sql = 'SELECT record_id FROM record' . $join; - if (count($tw) > 0) - $sql .= ' WHERE ' . ((count($tw) == 1) ? $tw[0] : '(' . implode(') AND (', $tw) . ')'); - - $ret = array( - 'real' => array( - 'sql' => $sql, - 'sql_htmlencoded' => htmlentities($sql), - ), - 'test' => array( - 'sql' => $sql_test, - 'sql_htmlencoded' => htmlentities($sql_test), - 'result' => NULL, - 'err' => NULL - ) - ); - - if ($playTest) { - $ret['test']['result'] = $this->playTest($sbas_id, $sql_test); - } - - return $ret; - } - - /** - * compute entry for a DELETE task - * - * @param integer $sbas_id - * @param simplexml $sxtask - * @param boolean $playTest - * @return array - */ - private function calcDELETE($sbas_id, &$sxtask, $playTest) - { - // compute the 'where' clause - list($tw, $join) = $this->calcWhere($sbas_id, $sxtask); - - // build the TEST sql (select) - $sql_test = 'SELECT SQL_CALC_FOUND_ROWS record_id FROM record' . $join; - if (count($tw) > 0) - $sql_test .= ' WHERE ' . ((count($tw) == 1) ? $tw[0] : '(' . implode(') AND (', $tw) . ')'); - $sql_test .= ' LIMIT 10'; - - // build the real sql (select) - $sql = 'SELECT record_id FROM record' . $join; - if (count($tw) > 0) - $sql .= ' WHERE ' . ((count($tw) == 1) ? $tw[0] : '(' . implode(') AND (', $tw) . ')'); - - $ret = array( - 'real' => array( - 'sql' => $sql, - 'sql_htmlencoded' => htmlentities($sql), - ), - 'test' => array( - 'sql' => $sql_test, - 'sql_htmlencoded' => htmlentities($sql_test), - 'result' => NULL, - 'err' => NULL - ) - ); - - if ($playTest) { - $ret['test']['result'] = $this->playTest($sbas_id, $sql_test); - } - - return $ret; - } - - /** - * compute the 'where' clause - * returns an array of clauses to be joined by 'and' - * and a 'join' to needed tables - * - * @param integer $sbas_id - * @param simplecms $sxtask - * @return array - */ - private function calcWhere($sbas_id, &$sxtask) - { - $connbas = connection::getPDOConnection($this->dependencyContainer, $sbas_id); - - $tw = array(); - $join = ''; - - $ijoin = 0; - - // criteria - if (($x = $sxtask->from->type['type']) !== NULL) { - switch (strtoupper($x)) { - case 'RECORD': - $tw[] = 'parent_record_id!=record_id'; - break; - case 'STORY': - $tw[] = 'parent_record_id=record_id'; - break; - } - } - - // criteria - foreach ($sxtask->from->text as $x) { - $ijoin++; - $comp = strtoupper($x['compare']); - if (in_array($comp, array('<', '>', '<=', '>=', '=', '!='))) { - $s = 'p' . $ijoin . '.name=\'' . $x['field'] . '\' AND p' . $ijoin . '.value' . $comp; - $s .= '' . $connbas->quote($x['value']) . ''; - - $tw[] = $s; - $join .= ' INNER JOIN prop AS p' . $ijoin . ' USING(record_id)'; - } else { - // bad comparison operator - } - } - - // criteria - foreach ($sxtask->from->date as $x) { - $ijoin++; - $s = 'p' . $ijoin . '.name=\'' . $x['field'] . '\' AND NOW()'; - $s .= strtoupper($x['direction']) == 'BEFORE' ? '<' : '>='; - $delta = (int) ($x['delta']); - if ($delta > 0) - $s .= '(p' . $ijoin . '.value+INTERVAL ' . $delta . ' DAY)'; - elseif ($delta < 0) - $s .= '(p' . $ijoin . '.value-INTERVAL ' . -$delta . ' DAY)'; - else - $s .= 'p' . $ijoin . '.value'; - - $tw[] = $s; - $join .= ' INNER JOIN prop AS p' . $ijoin . ' USING(record_id)'; - } - - // criteria - if (($x = $sxtask->from->coll) !== NULL) { - $tcoll = explode(',', $x['id']); - foreach ($tcoll as $i => $c) - $tcoll[$i] = (int) $c; - if ($x['compare'] == '=') { - if (count($tcoll) == 1) { - $tw[] = 'coll_id = ' . $tcoll[0]; - } else { - $tw[] = 'coll_id IN(' . implode(',', $tcoll) . ')'; - } - } elseif ($x['compare'] == '!=') { - if (count($tcoll) == 1) { - $tw[] = 'coll_id != ' . $tcoll[0]; - } else { - $tw[] = 'coll_id NOT IN(' . implode(',', $tcoll) . ')'; - } - } else { - // bad operator - } - } - - // criteria - $x = $sxtask->from->status['mask']; - $mx = str_replace(' ', '0', ltrim(str_replace(array('0', 'x'), array(' ', ' '), $x))); - $ma = str_replace(' ', '0', ltrim(str_replace(array('x', '0'), array(' ', '1'), $x))); - if ($mx && $ma) { - $tw[] = '((status^0b' . $mx . ')&0b' . $ma . ')=0'; - } elseif ($mx) { - $tw[] = '(status^0b' . $mx . ')=0'; - } elseif ($ma) { - $tw[] = '(status&0b' . $ma . ")=0"; - } - - if (count($tw) == 1) { - $where = $tw[0]; - } - if (count($tw) > 1) { - $where = '(' . implode(') AND (', $tw) . ')'; - } - - return array($tw, $join); - } - - /** - * play a 'test' sql on sbas, return the number of records and the 10 first rids - * - * @param integer $sbas_id - * @param string $sql - * @return array - */ - private function playTest($sbas_id, $sql) - { - $connbas = connection::getPDOConnection($this->dependencyContainer, $sbas_id); - $result = array('rids' => array(), 'err' => '', 'n' => null); - - $result['n'] = $connbas->query('SELECT COUNT(*) AS n FROM (' . $sql . ') AS x')->fetchColumn(); - - $stmt = $connbas->prepare('SELECT record_id FROM (' . $sql . ') AS x LIMIT 10'); - if ($stmt->execute(array())) { - while (($row = $stmt->fetch(PDO::FETCH_ASSOC))) { - $result['rids'][] = $row['record_id']; - } - $stmt->closeCursor(); - } else { - $result['err'] = $connbas->last_error(); - } - - return $result; - } - - /** - * facility called by xhttp/jquery from interface for ex. when switching interface from gui<->xml - */ - public function facility() - { - $request = http_request::getInstance(); - - $parm2 = $request->get_parms( - 'ACT', 'xml' - ); - - $ret = array('tasks' => array()); - switch ($parm2['ACT']) { - case 'CALCTEST': - $sxml = simplexml_load_string($parm2['xml']); - if (isset($sxml->tasks->task)) { - foreach ($sxml->tasks->task as $sxtask) { - $ret['tasks'][] = $this->calcSQL($sxtask, false); - } - } - break; - case 'PLAYTEST': - $sxml = simplexml_load_string($parm2['xml']); - if (isset($sxml->tasks->task)) { - foreach ($sxml->tasks->task as $sxtask) { - $ret['tasks'][] = $this->calcSQL($sxtask, true); - } - } - break; - case 'CALCSQL': - $xml = $this->graphic2xml(''); - $sxml = simplexml_load_string($xml); - if (isset($sxml->tasks->task)) { - foreach ($sxml->tasks->task as $sxtask) { - $ret['tasks'][] = $this->calcSQL($sxtask, false); - } - } - break; - } - - return json_encode($ret); - } - - /** - * @param array $params - */ - public static function getDefaultSettings(Configuration $config, array $params = array()) - { - $period = isset($params['period']) ? $params['period'] : self::MINPERIOD; - - return " - - ". min(max($period, self::MINPERIOD), self::MAXPERIOD) ." - 0 - - "; - } -} diff --git a/lib/classes/task/period/apibridge.php b/lib/classes/task/period/apibridge.php deleted file mode 100644 index dcd359f8c6..0000000000 --- a/lib/classes/task/period/apibridge.php +++ /dev/null @@ -1,178 +0,0 @@ -get_connection()->prepare($sql); - $stmt->execute($params); - $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - return $rs; - } - - /** - * - * @param appbox $appbox - * @param array $row - * @return task_period_apibridge - */ - protected function processOneContent(appbox $appbox, $row) - { - try { - $account = Bridge_Account::load_account($this->dependencyContainer, $row['account_id']); - $element = new Bridge_Element($this->dependencyContainer, $account, $row['id']); - - $this->log("process " . $element->get_id() . " with status " . $element->get_status()); - - if ($element->get_status() == Bridge_Element::STATUS_PENDING) { - $this->upload_element($element); - } else { - $this->update_element($element); - } - } catch (Exception $e) { - $sql = 'UPDATE bridge_elements SET status = :status WHERE id = :id'; - - $params = array( - ':status' => Bridge_Element::STATUS_ERROR - , ':id' => $row['id'] - ); - - $stmt = $appbox->get_connection()->prepare($sql); - $stmt->execute($params); - $stmt->closeCursor(); - } - - return $this; - } - - /** - * - * @param appbox $appbox - * @param array $row - * @return task_period_apibridge - */ - protected function postProcessOneContent(appbox $appbox, $row) - { - return $this; - } - - /** - * - * @param Bridge_Element $element - * @return task_period_apibridge - */ - private function upload_element(Bridge_Element $element) - { - $account = $element->get_account(); - $element->set_status(Bridge_Element::STATUS_PROCESSING); - $dist_id = null; - try { - $dist_id = $account->get_api()->upload($element->get_record(), $element->get_datas()); - $element->set_uploaded_on(new DateTime()); - } catch (Exception $e) { - $this->log('Error while uploading : ' . $e->getMessage()); - $element->set_status(Bridge_Element::STATUS_ERROR); - } - $element->set_dist_id($dist_id); - - return $this; - } - - /** - * - * @param Bridge_Element $element - * @return task_period_apibridge - */ - protected function update_element(Bridge_Element $element) - { - $account = $element->get_account(); - $connector_status = $account->get_api()->get_element_status($element); - - $status = $element->get_account()->get_api()->map_connector_to_element_status($connector_status); - $error_message = $element->get_account()->get_api()->get_error_message_from_status($connector_status); - - $previous_status = $element->get_status(); - - if ($status) { - $element->set_status($status); - $this->log('updating status for : ' . $element->get_id() . " to " . $status); - } - $element->set_connector_status($connector_status); - - if ($status === $previous_status) { - return; - } - - switch ($status) { - case Bridge_Element::STATUS_ERROR: - - $params = array( - 'usr_id' => $account->get_user()->get_id() - , 'reason' => $error_message - , 'account_id' => $account->get_id() - , 'sbas_id' => $element->get_record()->get_sbas_id() - , 'record_id' => $element->get_record()->get_record_id() - ); - $this->dependencyContainer['events-manager']->trigger('__BRIDGE_UPLOAD_FAIL__', $params); - - break; - default: - case Bridge_Element::STATUS_DONE: - case Bridge_Element::STATUS_PENDING: - case Bridge_Element::STATUS_PROCESSING_SERVER: - case Bridge_Element::STATUS_PROCESSING: - - break; - } - - return $this; - } -} diff --git a/lib/classes/task/period/archive.php b/lib/classes/task/period/archive.php deleted file mode 100644 index 226d88b94d..0000000000 --- a/lib/classes/task/period/archive.php +++ /dev/null @@ -1,2216 +0,0 @@ - - */ - protected $sxTaskSettings = null; - - /** - * - * @var string - */ - protected $msg = ""; - - /** - * - * @var boolean - */ - protected $move_archived = true; - - /** - * - * @var boolean - */ - protected $move_error = true; - - /** - * - * @var LazaretSession - */ - protected $lazaretSession; - - /** - * - * @return string - */ - public static function getName() - { - return _('task::archive:Archivage'); - } - - /** - * - * @param string $oldxml - * @return string - */ - public function graphic2xml($oldxml) - { - $request = http_request::getInstance(); - - $parm2 = $request->get_parms( - 'base_id' - , 'hotfolder' - , 'period' - , 'move_archived' - , 'move_error' - , 'copy_spe' - , 'delfolder' - , 'cold' - ); - $dom = new DOMDocument(); - $dom->formatOutput = true; - $dom->preserveWhiteSpace = false; - if ($dom->loadXML($oldxml)) { - foreach (array( - 'str:base_id' - , 'str:hotfolder' - , 'str:period' - , 'boo:move_archived' - , 'boo:move_error' - , 'boo:delfolder' - , 'boo:copy_spe' - , 'str:cold' - ) as $pname) { - $ptype = substr($pname, 0, 3); - $pname = substr($pname, 4); - $pvalue = $parm2[$pname]; - if (($ns = $dom->getElementsByTagName($pname)->item(0)) != null) { - // le champ existait dans le xml, on supprime son ancienne valeur (tout le contenu) - while (($n = $ns->firstChild)) { - $ns->removeChild($n); - } - } else { - // le champ n'existait pas dans le xml, on le cree - $ns = $dom->documentElement->appendChild($dom->createElement($pname)); - } - // on fixe sa valeur - switch ($ptype) { - case "str": - case "pop": - $ns->appendChild($dom->createTextNode($pvalue)); - break; - case "boo": - $ns->appendChild($dom->createTextNode($pvalue ? '1' : '0')); - break; - } - } - } - - return $dom->saveXML(); - } - - - /** - * Return some javascript code for the graphic view - */ - public function printInterfaceJS() - { - ?> - - - -
-
- -
- -
-
-
- -
- -
-
-
- -
- - -
-
-
- -
- - -
-
-
-
- -
-
-
-
- -
-
-
-
- -
-
-
-
- -
-
-
- debug = false; - - // test if connection is available - $this->dependencyContainer['phraseanet.appbox']->get_connection(); - - $this->sxTaskSettings = simplexml_load_string($this->settings); - - $base_id = (int) ($this->sxTaskSettings->base_id); - $this->sbas_id = \phrasea::sbasFromBas($this->dependencyContainer, $base_id); - - if (!$this->sbas_id) { - $this->log('base_id unknown'); - - return 'tostop'; - } - - $databox = $this->dependencyContainer['phraseanet.appbox']->get_databox($this->sbas_id); - - $this->TColls = array(); - $collection = null; - foreach ($databox->get_collections() as $coll) { - $this->TColls['c' . $coll->get_coll_id()] = $coll->get_coll_id(); - if ($base_id == $coll->get_base_id()) { - $collection = $coll; - } - } - $server_coll_id = $collection->get_coll_id(); - - // mask(s) of accepted files - $this->tmask = array(); - $this->tmaskgrp = array(); - $this->cold = 30; - - if (false !== $this->sxBasePrefs = @simplexml_load_string($collection->get_prefs())) { - $this->sxBasePrefs["id"] = $base_id; - - $this->cold = (int) ($this->sxTaskSettings->cold); - if ($this->cold < self::MINCOLD || $this->cold > self::MAXCOLD) { - $this->cold = self::MINCOLD; - } - - // check the data-repository exists - $pathhd = (string) ($this->sxBasePrefs->path); - - if ($pathhd) { - try { - $this->dependencyContainer['filesystem']->mkdir($pathhd, 0750); - } catch (IOException $e) { - $this->log($e->getMessage()); - $this->running = false; - - return; - } - } - - // load masks - if ($this->sxTaskSettings->files && $this->sxTaskSettings->files->file) { - foreach ($this->sxTaskSettings->files->file as $ft) { - $this->tmask[] = array( - "mask" => (string) $ft["mask"] - , "caption" => (string) $ft["caption"] - , "accept" => (string) $ft["accept"] - ); - } - } - if ($this->sxTaskSettings->files && $this->sxTaskSettings->files->grouping) { - foreach ($this->sxTaskSettings->files->grouping as $ft) { - $this->tmaskgrp[] = array( - "mask" => (string) $ft["mask"] - , "caption" => (string) $ft["caption"] - , "representation" => (string) $ft["representation"] - , "accept" => (string) $ft["accept"] - ); - } - } - if (count($this->tmask) == 0) { - // no mask defined : accept all kind of files - $this->tmask[] = array("mask" => ".*", "caption" => "", "accept" => ""); - } - - // main loop - $this->running = true; - $loop = 0; - while ($this->running) { - try { - connection::getPDOConnection($this->dependencyContainer); - } catch (Exception $e) { - $this->log($e->getMessage()); - if ($this->getRunner() == self::RUNNER_SCHEDULER) { - $this->log(("Warning : abox connection lost, restarting in 10 min.")); - - $this->sleep(60 * 10); - /** - * because connection is lost we cannot change status to 'torestart' - * anyway the current status 'running' with no pid - * will enforce the scheduler to restart the task - */ - } else { - $this->log(("Error : abox connection lost, quitting.")); - } - $this->running = false; - - return; - } - - $path_in = (string) ($this->sxTaskSettings->hotfolder); - if (!@is_dir($path_in)) { - if ($this->getRunner() == self::RUNNER_SCHEDULER) { - $this->log(sprintf(('Warning : missing hotfolder \'%s\', restarting in 10 min.'), $path_in)); - - $this->sleep(60 * 10); - - if ($this->getState() === self::STATE_STARTED) { - $this->setState(self::STATE_TORESTART); - } - } else { - $this->log(sprintf(('Error : missing hotfolder \'%s\', stopping.'), $path_in)); - // runner = manual : can't restart so simply quit - $this->setState(self::STATE_STOPPED); - } - $this->running = false; - - return; - } - - $this->setLastExecTime(); - try { - if (false === $this->sxTaskSettings = simplexml_load_string($this->getSettings())) { - throw new Exception(sprintf('Error fetching or reading settings of the task \'%d\'', $this->getID())); - } else { - // copy settings to task, so it's easier to get later - $this->move_archived = p4field::isyes($this->sxTaskSettings->move_archived); - $this->move_error = p4field::isyes($this->sxTaskSettings->move_error); - - $period = (int) ($this->sxTaskSettings->period); - if ($period <= 0 || $period >= 3600) { - $period = 60; - } - $cold = (int) ($this->sxTaskSettings->cold); - if ($cold <= 0 || $cold >= 300) { - $cold = 30; - } - } - } catch (Exception $e) { - if ($this->getRunner() == self::RUNNER_SCHEDULER) { - $this->log(sprintf(('Warning : error fetching or reading settings of the task \'%d\', restarting in 10 min.'), $this->getID())); - - $this->sleep(60 * 10); - - if ($this->getState() === self::STATE_STARTED) { - $this->setState(self::STATE_TORESTART); - } - } else { - $this->log(sprintf(('Error : error fetching task \'%d\', stopping.'), $this->getID())); - // runner = manual : can't restart so simply quit - $this->setState(self::STATE_STOPPED); - } - $this->running = false; - - return; - } - - $status = $this->getState(); - - if ($status == self::STATE_TOSTOP) { - $this->running = false; - - return; - } - - $duration = time(); - $r = $this->archiveHotFolder($server_coll_id); - - if ($loop > 10) { - $r = 'MAXLOOP'; - } - - switch ($r) { - case 'TOSTOP': - $this->setState(self::STATE_STOPPED); - $this->running = false; - break; - case 'WAIT': - $this->setState(self::STATE_STOPPED); - $this->running = false; - break; - case 'BAD': - $this->setState(self::STATE_STOPPED); - $this->running = false; - break; - case 'NORECSTODO': - $duration = time() - $duration; - if ($duration < ($period + $cold)) { - for ($i = 0; $i < (($period + $cold) - $duration) && $this->running; $i++) { - $s = $this->getState(); - if ($s == self::STATE_TOSTOP) { - $this->setState(self::STATE_STOPPED); - $this->running = false; - } else { - $this->sleep(1); - } - } - } - break; - case 'MAXRECSDONE': - case 'MAXMEMORY': - case 'MAXLOOP': - if ($status == self::STATE_STARTED && $this->getRunner() !== self::RUNNER_MANUAL) { - $this->setState(self::STATE_TORESTART); - $this->running = false; - } - break; - default: - if ($status == self::STATE_STARTED) { - $this->setState(self::STATE_STOPPED); - $this->running = false; - } - break; - } - $loop++; - } - } - } - - /** - * - * @param integer $server_coll_id - * @return string - */ - protected function archiveHotFolder($server_coll_id) - { - clearstatcache(); - - connection::getPDOConnection($this->dependencyContainer); - $this->dependencyContainer['phraseanet.appbox']->get_databox($this->sbas_id)->get_connection(); - - $path_in = p4string::delEndSlash(trim((string) ($this->sxTaskSettings->hotfolder))); - if (false === $this->dependencyContainer['filesystem']->exists($path_in . "/.phrasea.xml")) { - $this->log(sprintf(('NO .phrasea.xml AT ROOT v2 \'%s\' !'), $path_in)); - - return 'WAIT'; - } - - $path_archived = $path_error = null; - if ($this->move_archived) { - $path_archived = $path_in . '_archived'; - - try { - $this->dependencyContainer['filesystem']->mkdir($path_archived, 0755); - } catch (IOException $e) { - $this->log($e->getMessage()); - - return 'BAD'; - } - } - if ($this->move_error) { - $path_error = $path_in . '_error'; - - try { - $this->dependencyContainer['filesystem']->mkdir($path_error, 0755); - } catch (IOException $e) { - $this->log($e->getMessage()); - - return 'BAD'; - } - } - - $dom = new DOMDocument(); - $dom->formatOutput = true; - $root = $dom->appendChild($dom->createElement('root')); - - $this->movedFiles = 0; - $this->archivedFiles = 0; - $this->path_in = $path_in; - - $nnew = $this->listFilesPhase1($dom, $root, $path_in, $server_coll_id); - if ($this->debug) { - $this->log("=========== listFilesPhase1 ========== (returned " . $nnew . ")\n" . $dom->saveXML()); - } - - // special case : status has changed to TOSTOP while listing files - if ($nnew === 'TOSTOP') { - return 'TOSTOP'; - } - - // wait for files to be cold - $cold = (int) ($this->sxTaskSettings->cold); - if ($cold <= 0 || $cold >= 300) { - $cold = 30; - } - - while ($this->running && $cold > 0) { - $s = $this->getState(); - if ($s == self::STATE_TOSTOP) { - return 'TOSTOP'; - } - $this->sleep(2); - $cold -= 2; - } - - $nnew = $this->listFilesPhase2($dom, $root, $path_in); - if ($this->debug) { - $this->log("=========== listFilesPhase2 ========== : \n" . $dom->saveXML()); - } - - // special case : status has changed to TOSTOP while listing files - if ($nnew === 'TOSTOP') { - return 'TOSTOP'; - } - - $this->makePairs($dom, $root, $path_in, $path_archived, $path_error); - if ($this->debug) { - $this->log("=========== makePairs ========== : \n" . $dom->saveXML()); - } - - $r = $this->removeBadGroups($dom, $root, $path_in, $path_archived, $path_error); - if ($this->debug) { - $this->log("=========== removeBadGroups ========== (returned " . ($r ? 'true' : 'false') . ") : \n" . $dom->saveXML()); - } - - $this->archive($dom, $root, $path_in, $path_archived, $path_error); - if ($this->debug) { - $this->log("=========== archive ========== : \n" . $dom->saveXML()); - } - - if ($this->running) { - $this->bubbleResults($dom, $root, $path_in); - if ($this->debug) { - $this->log("=========== bubbleResults ========== : \n" . $dom->saveXML()); - } - - $r = $this->moveFiles($dom, $root, $path_in, $path_archived, $path_error); - if ($this->debug) { - $this->log("=========== moveFiles ========== (returned " . ($r ? 'true' : 'false') . ") : \n" . $dom->saveXML()); - } - } - if ($this->movedFiles) { - - // something happened : a least one file has moved - return 'MAXRECSDONE'; - } elseif (memory_get_usage() >> 20 > 25) { - return 'MAXMEGSREACHED'; - } else { - return 'NORECSTODO'; - } - } - - /** - * - * @param string $f - * @return boolean - */ - protected function isIgnoredFile($f) - { - $f = strtolower($f); - - return ($f[0] == '.' && $f != '.phrasea.xml' && $f != '.grouping.xml') || $f == 'thumbs.db' || $f == 'par-system'; - } - - /** - * check if the file matches any mask, and flag the 'caption' file if found - * - * @param \DOMDocument $dom - * @param \DOMElement $node - */ - protected function checkMatch(\DOMDocument $dom, \DOMElement $node) - { - $file = $node->getAttribute('name'); - - foreach ($this->tmask as $mask) { - $preg_mask = '/' . $mask['mask'] . '/'; - if (preg_match($preg_mask, $file)) { - if ($mask['caption']) { - // caption in a linked file ? - $captionFileName = @preg_replace($preg_mask, $mask['caption'], $file); - $xpath = new DOMXPath($dom); - $dnl = $xpath->query('./file[@name="' . $captionFileName . '"]', $node->parentNode); - if ($dnl->length == 1) { - // the caption file exists - $node->setAttribute('match', $captionFileName); - $dnl->item(0)->setAttribute('match', '*'); - } else { - // the caption file is missing - $node->setAttribute('match', '?'); - } - } else { - // self-described - $node->setAttribute('match', '.'); - } - - // first match is ok - break; - } - } - - return; - } - - /** - * Phase 1 : - * list every file, all 'hot' - * read .phrasea.xml files - * - * @param \DOMDocument $dom - * @param \DomElement $node - * @param string $path - * @param integer $server_coll_id - * @return integer|string the number on found files or "TOSTOP" if task is to stop - */ - private function listFilesPhase1(\DOMDocument $dom, \DomElement $node, $path, $server_coll_id, $depth = 0) - { - static $time0 = null; - if ($depth == 0) { - $time0 = time(); - } - - $nnew = 0; - - try { - $listFolder = new CListFolder($path); - - if (false !== $sxDotPhrasea = @simplexml_load_file($path . '/.phrasea.xml')) { - - // test for magic file - if (($magicfile = trim((string) ($sxDotPhrasea->magicfile))) != '') { - $magicmethod = strtoupper($sxDotPhrasea->magicfile['method']); - if ($magicmethod == 'LOCK' && true === $this->dependencyContainer['filesystem']->exists($path . '/' . $magicfile)) { - return; - } elseif ($magicmethod == 'UNLOCK' && false === $this->dependencyContainer['filesystem']->exists($path . '/' . $magicfile)) { - return; - } - } - - // change collection ? - if (($new_cid = $sxDotPhrasea['collection']) != '') { - if (isset($this->TColls['c' . $new_cid])) { - $server_coll_id = $new_cid; - } else { - $this->log(sprintf(('Unknown coll_id (%1$d) in "%2$s"'), (int) $new_cid, $path . '/.phrasea.xml')); - $server_coll_id = -1; - } - } - $node->setAttribute('pxml', '1'); - } - - $iloop = 0; - $time0 = time(); - while (($file = $listFolder->read()) !== null) { - // each 2 secs, check the status of the task - if (time() - $time0 >= 2) { - if ($this->getState() == self::STATE_TOSTOP) { - // since we will return a string... - $nnew = 'TOSTOP'; - // ...we can check it against numerical result - break; - } - $time0 = time(); - } - - if (($iloop++ % 100) == 0) { - usleep(1000); - } - - if ($this->isIgnoredFile($file)) { - continue; - } - - if (is_dir($path . '/' . $file)) { - $n = $node->appendChild($dom->createElement('file')); - $n->setAttribute('isdir', '1'); - $n->setAttribute('name', $file); - - $_nnew_ = $this->listFilesPhase1($dom, $n, $path . '/' . $file, $server_coll_id, $depth + 1); - if ($_nnew_ === 'TOSTOP') { - // special case to quit recursion - $nnew = 'TOSTOP'; - break; - } else { - // normal case, _nnew_ is a number - $nnew += $_nnew_; - } - } else { - $n = $node->appendChild($dom->createElement('file')); - $n->setAttribute('name', $file); - $stat = stat($path . '/' . $file); - foreach (array("size", "ctime", "mtime") as $k) { - $n->setAttribute($k, $stat[$k]); - } - $nnew++; - } - $n->setAttribute('cid', $server_coll_id); - - $n->setAttribute('temperature', 'hot'); - } - } catch (Exception $e) { - - } - - return $nnew; - } - - /** - * Phase 2 : - * list again and flag dead files as 'cold' - * - * @staticvar int $iloop - * @param \DOMDocument $dom - * @param \DOMElement $node - * @param string $path - * @param integer $depth - * @return integer|string the number of NEW files or "TOSTOP" if task is to stop - */ - private function listFilesPhase2(\DOMDocument $dom, \DOMElement $node, $path, $depth = 0) - { - static $iloop = 0; - static $time0 = null; - if ($depth == 0) { - $iloop = 0; - $time0 = time(); - } - - $nnew = 0; - - try { - $listFolder = new CListFolder($path); - - $xp = new DOMXPath($dom); - - if (false !== $sxDotPhrasea = @simplexml_load_file($path . '/.phrasea.xml')) { - - // test magicfile - if (($magicfile = trim((string) ($sxDotPhrasea->magicfile))) != '') { - $magicmethod = strtoupper($sxDotPhrasea->magicfile['method']); - if ($magicmethod == 'LOCK' && true === $this->dependencyContainer['filesystem']->exists($path . '/' . $magicfile)) { - return 0; - } elseif ($magicmethod == 'UNLOCK' && false === $this->dependencyContainer['filesystem']->exists($path . '/' . $magicfile)) { - return 0; - } - } - } - - while (($file = $listFolder->read()) !== null) { - // each 2 secs, check the status of the task - if (time() - $time0 >= 2) { - if ($this->getState() == self::STATE_TOSTOP) { - // since we will return a string... - $nnew = 'TOSTOP'; - // ...we can check it against numerical result - break; - } - $time0 = time(); - } - - if ($this->isIgnoredFile($file)) { - continue; - } - - if (($iloop++ % 100) == 0) { - usleep(500); - } - - $dnl = @$xp->query('./file[@name="' . $file . '"]', $node); - if ($dnl && $dnl->length == 0) { - if (is_dir($path . '/' . $file)) { - $n = $node->appendChild($dom->createElement('file')); - $n->setAttribute('isdir', '1'); - $n->setAttribute('name', $file); - - $_nnew_ = $this->listFilesPhase2($dom, $n, $path . '/' . $file, $depth + 1); - if ($_nnew_ === 'TOSTOP') { - // special case to quit recursion - $nnew = 'TOSTOP'; - break; - } else { - // normal case, _nnew_ is a number - $nnew += $_nnew_; - } - } else { - $n = $node->appendChild($dom->createElement('file')); - $n->setAttribute('name', $file); - $nnew++; - } - $this->setBranchHot($dom, $n); - } elseif ($dnl && $dnl->length == 1) { - - $dnl->item(0)->setAttribute('temperature', 'cold'); - - if (is_dir($path . '/' . $file)) { - $this->listFilesPhase2($dom, $dnl->item(0), $path . '/' . $file, $depth + 1); - } else { - $stat = stat($path . '/' . $file); - foreach (array("size", "ctime", "mtime") as $k) { - if ($dnl->item(0)->getAttribute($k) != $stat[$k]) { - $this->setBranchHot($dom, $dnl->item(0)); - break; - } - } - } - } - } - } catch (Exception $e) { - - } - - return $nnew; - } - - /** - * makePairs : - * flag files to be archived (make pairs with linked caption when needed) - * flag grp folders and their linked files (caption, representation) - * declare uncomplete grp as error - * - * @staticvar int $iloop - * @param \DOMDocument $dom - * @param \DOMElement $node - * @param string $path - * @param string $path_archived - * @param string $path_error - * @param boolean $inGrp - * @param integer $depth - */ - private function makePairs(\DOMDocument $dom, \DOMElement $node, $path, $path_archived, $path_error, $inGrp = false, $depth = 0) - { - static $iloop = 0; - if ($depth == 0) { - $iloop = 0; - } - - if ($depth == 0 && ($node->getAttribute('temperature') == 'hot' || $node->getAttribute('cid') == '-1')) { - return; - } - - $xpath = new DOMXPath($dom); - - for ($n = $node->firstChild; $this->running && $n; $n = $n->nextSibling) { - if (($iloop++ % 100) == 0) { - usleep(1000); - } - - // make xml lighter (free ram) - foreach (array("size", "ctime", "mtime") as $k) { - $n->removeAttribute($k); - } - - if ($n->getAttribute('temperature') == 'hot' || $n->getAttribute('cid') == '-1') { - continue; - } - - $name = $n->getAttribute('name'); - if ($n->getAttribute('isdir') == '1') { - // get 'caption', 'representation' - if (($grpSettings = $this->getGrpSettings($name)) !== false) { - // this is a grp folder, we check it - $dnl = $xpath->query('./file[@name=".grouping.xml"]', $n); - if ($dnl->length == 1) { - // this group is old (don't care about any linked files), just flag it - $n->setAttribute('grp', 'tocomplete'); - $dnl->item(0)->setAttribute('match', '*'); - // recurse only if group is ok - $this->makePairs($dom, $n, $path . '/' . $name, true, $depth + 1); - } else { - // this group in new (to be created) - // do we need one (or both) linked file ? (caption or representation) - $err = false; - $flink = array('caption' => null, 'representation' => null); - - foreach ($flink as $linkName => $v) { - if (isset($grpSettings[$linkName]) && $grpSettings[$linkName] != '') { - // we need this linked file, calc his real name - $f = preg_replace('/' . $grpSettings['mask'] . '/i', $grpSettings[$linkName], $name); - - $dnl = $xpath->query('./file[@name="' . $f . '"]', $node); - if ($dnl->length == 1) { - // it's here - $flink[$linkName] = $dnl->item(0); - } else { - $this->log(sprintf(('missing linked file \'%1$s\' to group \'%2$s\''), $f, $name)); - // missing -> error - $err = true; - } - } - } - - if (!$err) { - // the group is ok, flag it ... - $n->setAttribute('grp', 'tocreate'); - - // ... as the existing linked file(s) ... - foreach ($flink as $linkName => $v) { - // this linked file exists - if ($v) { - $v->setAttribute('match', '*'); - $n->setAttribute('grp_' . $linkName, $v->getAttribute('name')); - } - } - // recurse only if group is ok - $this->makePairs($dom, $n, $path . '/' . $name - , $path_archived . '/' . $name - , $path_error . '/' . $name - , true, $depth + 1); - } else { - // something is missing, the whole group goes error, ... - $n->setAttribute('grp', 'todelete'); - - $this->setAllChildren($dom, $n, array('error' => '1')); - - // bubble to the top - for ($nn = $n; $nn && $nn->nodeType == XML_ELEMENT_NODE; $nn = $nn->parentNode) { - $nn->setAttribute('error', '1'); - } - - // ... as the existing linked file(s) ... - foreach ($flink as $linkName => $v) { - // this linked file exists, it goes error also - if ($v) { - $v->setAttribute('error', '1'); - } - } - } - } - } else { - // not a grp folder, recurse - $this->makePairs($dom, $n, $path . '/' . $name - , $path_archived . '/' . $name - , $path_error . '/' . $name - , $inGrp, $depth + 1); - } - } else { - // this is a file - if (!$n->getAttribute('match')) { - // because match can be set before - if ($name == '.phrasea.xml') { - // special file(s) always ok - $n->setAttribute('match', '*'); - } else { - $this->checkMatch($dom, $n); - } - } - } - } - - // scan again for unmatched files - for ($n = $node->firstChild; $this->running && $n; $n = $n->nextSibling) { - if (!$n->getAttribute('isdir') == '1' && !$n->getAttribute('match')) { - // still no match, now it's an error (bubble to the top) - for ($nn = $n; $nn && $nn->nodeType == XML_ELEMENT_NODE; $nn = $nn->parentNode) { - $nn->setAttribute('error', '1'); - } - } - } - - return; - } - - /** - * removeBadGroups : - * move files to archived or error dir - * - * @staticvar int $iloop - * @param \DOMDocument $dom - * @param \DOMElement $node - * @param string $path - * @param string $path_archived - * @param string $path_error - * @param integer $depth - */ - private function removeBadGroups(\DOMDocument $dom, \DOMElement $node, $path, $path_archived, $path_error, $depth = 0) - { - static $iloop = 0; - if ($depth == 0) { - $iloop = 0; - } - - $ret = false; - - // if root of hotfolder if hot, die... - if ($depth == 0 && $node->getAttribute('temperature') == 'hot') { - return $ret; - } - - $nodesToDel = array(); - for ($n = $node->firstChild; $this->running && $n; $n = $n->nextSibling) { - if (($iloop++ % 20) == 0) { - usleep(1000); - } - - if ($n->getAttribute('temperature') == 'hot') { - // do not move hotfiles - continue; - } - - $name = $n->getAttribute('name'); - - if ($n->getAttribute('isdir')) { - $ret |= $this->removeBadGroups($dom, $n, $path . '/' . $name - , $path_archived . '/' . $name - , $path_error . '/' . $name - , $depth + 1); - if ($n->getAttribute('grp') == 'todelete') { - $nodesToDel[] = $n; - - try { - $this->dependencyContainer['filesystem']->remove($path . '/' . $name); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - } - } else { - if ($n->getAttribute('error')) { - if ($this->move_error) { - $rootpath = p4string::delEndSlash(trim((string) ($this->sxTaskSettings->hotfolder))); - $subpath = substr($path, strlen($rootpath)); - $this->log(sprintf(('copy \'%s\' to \'error\''), $subpath . '/' . $name)); - - try { - $this->dependencyContainer['filesystem']->mkdir($path_error, 0755); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - - try { - $this->dependencyContainer['filesystem']->copy($path . '/' . $name, $path_error . '/' . $name, true); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - } - - $nodesToDel[] = $n; - - try { - $this->dependencyContainer['filesystem']->remove($path . '/' . $name); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - - $this->movedFiles++; - } - } - } - - foreach ($nodesToDel as $n) { - $n->parentNode->removeChild($n); - } - - return; - } - - /** - * archive : - * archive files - * do special work on grp folders - * - * @staticvar int $iloop - * @param \DOMDOcument $dom - * @param \DOMElement $node - * @param string $path - * @param string $path_archived - * @param string $path_error - * @param integer $depth - */ - private function archive(\DOMDOcument $dom, \DOMElement $node, $path, $path_archived, $path_error, $depth = 0) - { - static $iloop = 0; - - if ($depth == 0) { - $iloop = 0; - } - - if ($node->getAttribute('temperature') == 'hot') { - return; - } - - $nodesToDel = array(); - for ($n = $node->firstChild; $this->running && $n; $n = $n->nextSibling) { - if (($iloop++ % 20) == 0) { - usleep(1000); - } - - if ($n->getAttribute('temperature') == 'hot') { - continue; - } - - if ($n->getAttribute('cid') == '-1') { - $n->setAttribute('error', '1'); - continue; - } - - if ($n->getAttribute('isdir') == '1') { - if ($n->getAttribute('grp')) { - // a grp folder : special work - $this->archiveGrp($dom, $n, $path, $path_archived, $path_error, $nodesToDel); - } else { - // ...normal subfolder : recurse - $name = $n->getAttribute('name'); - $this->archive($dom, $n, $path . '/' . $name - , $path_archived . '/' . $name - , $path_error . '/' . $name - , $depth + 1); - } - } else { - // a file, 0 = no grp - $this->archiveFile($dom, $n, $path, $path_archived, $path_error, $nodesToDel, 0); - } - } - foreach ($nodesToDel as $n) { - $n->parentNode->removeChild($n); - } - - // at the end of recursion, restore the magic file (create or delete it) - if (($magicfile = $node->getAttribute('magicfile')) != '') { - $magicmethod = $node->getAttribute('magicmethod'); - if ($magicmethod == 'LOCK') { - file_put_contents($path . '/' . $magicfile, ''); - } elseif ($magicmethod == 'UNLOCK') { - - try { - $this->dependencyContainer['filesystem']->remove($path . '/' . $magicfile); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - } - } - - return; - } - - /** - * bubbleResults : - * bubble result attributes ('keep', 'archived', 'error') up to top, - * to help creation of result folders and cleaning of the hotfolder - * - * @staticvar int $iloop - * @param \DOMDocument $dom - * @param \DOMElement $node - * @param string $path - * @param integer $depth - * @return integer flags used only inside recursion - */ - private function bubbleResults(\DOMDocument $dom, \DOMElement $node, $path, $depth = 0) - { - static $iloop = 0; - if ($depth == 0) { - $iloop = 0; - } - - if ($node->getAttribute('temperature') == 'hot') { - return; - } - - $ret = 0; - for ($n = $node->firstChild; $n; $n = $n->nextSibling) { - if (($iloop++ % 20) == 0) { - usleep(1000); - } - - if ($n->getAttribute('name') == '.phrasea.xml' || $n->getAttribute('name') == '.grouping.xml') { - // special files stay in place AND are copied into 'archived' - $n->setAttribute('keep', '1'); - if (p4field::isyes($this->sxTaskSettings->copy_spe)) { - $n->setAttribute('archived', '1'); - } - } - if ($n->getAttribute('keep') == '1') { - $ret |= 1; - } - if ($n->getAttribute('archived') == '1') { - $ret |= 2; - } - if ($n->getAttribute('error') == '1') { - $ret |= 4; - } - if ($n->getAttribute('isdir') == '1') { - $ret |= $this->bubbleResults($dom, $n, $path . '/' . $n->getAttribute('name'), $depth + 1); - } - } - if ($ret & 1) { - $node->setAttribute('keep', '1'); - } - if ($ret & 2) { - $node->setAttribute('archived', '1'); - } - if ($ret & 4) { - $node->setAttribute('error', '1'); - } - - return $ret; - } - - /** - * Phase 5 : move files to archived or error dir - * - * @staticvar int $iloop - * @param \DOMDocument $dom - * @param \DOMElement $node - * @param string $path - * @param string $path_archived - * @param string $path_error - * @param integer $depth - * @return boolean at least one file was moved - */ - private function moveFiles(\DOMDocument $dom, \DOMElement $node, $path, $path_archived, $path_error, $depth = 0) - { - - static $iloop = 0; - if ($depth == 0) { - $iloop = 0; - } - - $ret = false; - - // if root of hotfolder if hot, die... - if ($depth == 0 && $node->getAttribute('temperature') == 'hot') { - return $ret; - } - - $nodesToDel = array(); - for ($n = $node->firstChild; $n; $n = $n->nextSibling) { - if (($iloop++ % 20) == 0) { - usleep(1000); - } - - if ($n->getAttribute('temperature') == 'hot') { // do not move hotfiles - continue; - } - - $name = $n->getAttribute('name'); - - if ($n->getAttribute('isdir')) { - $ret |= $this->moveFiles($dom, $n, $path . '/' . $name - , $path_archived . '/' . $name - , $path_error . '/' . $name - , $depth + 1); - - if (!$n->firstChild) { - $nodesToDel[] = $n; - } - /** - * Do not remove empty folders yet - */ - } else { - $rootpath = p4string::delEndSlash(trim((string) ($this->sxTaskSettings->hotfolder))); - $subpath = substr($path, strlen($rootpath)); - - if ($n->getAttribute('archived') && $this->move_archived) { - $this->log(sprintf(('copy \'%s\' to \'archived\''), $subpath . '/' . $name)); - - try { - $this->dependencyContainer['filesystem']->mkdir($path_archived); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - - try { - $this->dependencyContainer['filesystem']->copy($path . '/' . $name, $path_archived . '/' . $name, true); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - - if (!$n->getAttribute('keep')) { // do not count copy of special files as a real event - $nodesToDel[] = $n; - $ret = true; - } - } - - if ($n->getAttribute('error') && $this->move_error) { - $this->log(sprintf(('copy \'%s\' to \'error\''), $subpath . '/' . $name)); - - try { - $this->dependencyContainer['filesystem']->mkdir($path_error); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - - try { - $this->dependencyContainer['filesystem']->copy($path . '/' . $name, $path_error . '/' . $name, true); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - - if (!$n->getAttribute('keep')) { // do not count copy of special files as a real event - $nodesToDel[] = $n; - $ret = true; - } - } - - if (!$n->getAttribute('keep')) { - $this->log(sprintf(('delete \'%s\''), $subpath . '/' . $name)); - - try { - $this->dependencyContainer['filesystem']->remove($path . '/' . $name); - $this->movedFiles ++; - } catch (IOException $e) { - $this->log($e->getMessage()); - } - } - } - } - - foreach ($nodesToDel as $n) { - $n->parentNode->removeChild($n); - } - - return $ret; - } - - /** - * - * @param \DOMDocument $dom - * @param \DOMElement $node - */ - private function setBranchHot(\DOMDocument $dom, \DOMElement $node) - { - for ($n = $node; $n; $n = $n->parentNode) { - if ($n->nodeType == XML_ELEMENT_NODE) { - $n->setAttribute('temperature', 'hot'); - if ($n->hasAttribute('pxml')) { - break; - } - } - } - - return; - } - - /** - * - * special work for a grp folder : - * create the grp if needed - * archive files - * - * @param \DOMDocument $dom - * @param \DOMElement $node - * @param string $path - * @param string $path_archived - * @param string $path_error - * @param array $nodesToDel out, filled with deleted files - */ - private function archiveGrp(\DOMDocument $dom, \DOMElement $node, $path, $path_archived, $path_error, array &$nodesToDel) - { - $xpath = new DOMXPath($dom); - - // grp folders stay in place - $node->setAttribute('keep', '1'); - $grpFolder = $node->getAttribute('name'); - - $groupingFile = $path . '/' . $grpFolder . '/.grouping.xml'; - - if ($node->getAttribute('grp') == 'tocreate') { - $representationFileName = null; - $representationFileNode = null; - $captionFileName = null; - $captionFileNode = null; - $cid = $node->getAttribute('cid'); - $genericdoc = null; - - $rootpath = p4string::delEndSlash(trim((string) ($this->sxTaskSettings->hotfolder))); - $subpath = substr($path, strlen($rootpath)); - - $this->log(sprintf(('created story \'%s\''), $subpath . '/' . $grpFolder)); - - // if the .grp does not have a representative doc, let's use a generic file - if (!($rep = $node->getAttribute('grp_representation'))) { - - try { - $this->dependencyContainer['filesystem']->copy($this->dependencyContainer['root.path'] . '/www/skins/icons/substitution/regroup_doc.png', $genericdoc = ($path . '/group.jpg'), true); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - - $representationFileName = 'group.jpg'; - $this->log((' (no representation file)')); - } else { - $dnl = $xpath->query('./file[@name="' . $rep . '"]', $node->parentNode); - $representationFileNode = $dnl->item(0); - $representationFileName = $rep; - $node->removeAttribute('grp_representation'); - $this->log(sprintf(('representation from \'%s\''), $representationFileName)); - } - - if (($cap = $node->getAttribute('grp_caption')) != '') { - $dnl = $xpath->query('./file[@name="' . $cap . '"]', $node->parentNode); - $captionFileNode = $dnl->item(0); - $captionFileName = $cap; - $node->removeAttribute('grp_caption'); - $this->log(sprintf(('caption from \'%s\''), $captionFileName)); - } - - try { - - $databox = $this->dependencyContainer['phraseanet.appbox']->get_databox($this->sbas_id); - $collection = collection::get_from_coll_id($this->dependencyContainer, $databox, (int) $cid); - if ($captionFileName === null) { - $story = $this->createStory($collection, $path . '/' . $representationFileName, null); - } else { - $story = $this->createStory($collection, $path . '/' . $representationFileName, $path . '/' . $captionFileName); - } - - $rid = $story->get_record_id(); - - $this->log(sprintf('story %s created', $rid)); - $this->archivedFiles++; - - if ($genericdoc) { - try { - $this->dependencyContainer['filesystem']->remove($genericdoc); - $this->movedFiles ++; - } catch (IOException $e) { - $this->log($e->getMessage()); - } - } - - file_put_contents($groupingFile, ''); - $n = $node->appendChild($dom->createElement('file')); - $n->setAttribute('name', '.grouping.xml'); - $n->setAttribute('temperature', 'cold'); - $n->setAttribute('grp', '1'); - $n->setAttribute('match', '*'); - if ($this->move_archived) { - $this->log(sprintf(('copy \'%s\' to \'archived\''), $subpath . '/' . $grpFolder . '/.grouping.xml')); - - try { - $this->dependencyContainer['filesystem']->mkdir($path_archived . '/' . $grpFolder, 0755); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - - try { - $this->dependencyContainer['filesystem']->copy($path . '/' . $grpFolder . '/.grouping.xml', $path_archived . '/' . $grpFolder . '/.grouping.xml', true); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - } - - if ($captionFileNode) { - $captionFileNode->setAttribute('archived', '1'); - if ($this->move_archived) { - $this->log(sprintf(('copy \'%s\' to \'archived\''), $subpath . '/' . $captionFileName)); - - try { - $this->dependencyContainer['filesystem']->mkdir($path_archived, 0755); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - - try { - $this->dependencyContainer['filesystem']->copy($path . '/' . $captionFileName, $path_archived . '/' . $captionFileName, true); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - } - - try { - $this->dependencyContainer['filesystem']->remove($path . '/' . $captionFileName); - $this->movedFiles ++; - } catch (IOException $e) { - $this->log($e->getMessage()); - } - - $nodesToDel[] = $captionFileNode; - - $this->movedFiles++; - } - if ($representationFileNode) { - $representationFileNode->setAttribute('archived', '1'); - if ($this->move_archived) { - $this->log(sprintf(('copy \'%s\' to \'archived\''), $subpath . '/' . $representationFileName)); - - try { - $this->dependencyContainer['filesystem']->mkdir($path_archived, 0755); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - - try { - $this->dependencyContainer['filesystem']->copy($path . '/' . $representationFileName, $path_archived . '/' . $representationFileName, true); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - } - - try { - $this->dependencyContainer['filesystem']->remove($path . '/' . $representationFileName); - $this->movedFiles ++; - } catch (IOException $e) { - $this->log($e->getMessage()); - } - $nodesToDel[] = $representationFileNode; - - $this->movedFiles++; - } - $node->setAttribute('grp', 'tocomplete'); - } catch (Exception $e) { - $this->logger->addDebug($e->getMessage()); - } - } - - // here the .grouping.xml should exists - if ($this->dependencyContainer['filesystem']->exists($groupingFile)) { - // a .grouping.xml must stay in place - // -- don't do, done in phase4 - - $sxGrouping = @simplexml_load_file($groupingFile); - $grp_rid = $sxGrouping['grouping']; - - $this->archiveFilesToGrp($dom, $node, $path . '/' . $grpFolder - , $path_archived . '/' . $grpFolder - , $path_error . '/' . $grpFolder - , $grp_rid); - } - - return; - } - - /** - * Create a story - * - * @todo pathfile should be optionnal - * - * @param \collection $collection The destination collection - * @param sring $pathfile The base file - * @param string $captionFile The optionnal Phrasea XML caption file - * @return \record_adapter - */ - public function createStory(\collection $collection, $pathfile, $captionFile = null) - { - $stat0 = $stat1 = "0"; - - if (isset($this->sxBasePrefs)) { - if ($this->sxBasePrefs->status) { - $stat0 = (string) ($this->sxBasePrefs->status); - } - if ($this->sxTaskSettings->status) { - $stat1 = (string) ($this->sxTaskSettings->status); - } - } - - if (!$stat0) { - $stat0 = '0'; - } - if (!$stat1) { - $stat1 = '0'; - } - - $media = $this->dependencyContainer['mediavorus']->guess($pathfile); - - $databox = $collection->get_databox(); - $metadatasStructure = $databox->get_meta_structure(); - - $metadatas = $this->getIndexByFieldName($metadatasStructure, $media->getMetadatas()); - $metaFields = null; - - if ($captionFile !== null && true === $this->dependencyContainer['filesystem']->exists($captionFile)) { - $metaFields = $this->readXMLForDatabox($metadatasStructure, $captionFile); - $captionStatus = $this->parseStatusBit(@simplexml_load_file($captionFile)); - - if ($captionStatus) { - $status = databox_status::operation_or($this->dependencyContainer, $status, $captionStatus); - } - } - - $story = record_adapter::createStory($this->dependencyContainer, $collection); - $story->substitute_subdef('document', $media, $this->dependencyContainer); - - $story->set_metadatas($metadatas->toMetadataArray($metadatasStructure), true); - - if ($metaFields) { - $story->set_metadatas($metaFields->toMetadataArray($metadatasStructure), true); - } - - $story->set_binary_status(databox_status::operation_or($this->dependencyContainer, $stat0, $stat1)); - $story->rebuild_subdefs(); - - $this->dependencyContainer['phraseanet.SE']->addStory($story); - - $media = $databox = null; - - return $story; - } - - /** - * Creates a record - * - * @param \collection $collection The destination collection - * @param string $pathfile The file to archive - * @param string|null $captionFile The Phrasea XML caption file or null if no caption file - * @param integer $grp_rid Add the record to a story - * @param integer $force Force lazaret or record ; use \Alchemy\Phrasea\Border\Manager::FORCE_* constants - * @return \record_adapter - */ - public function createRecord(\collection $collection, $pathfile, $captionFile, $grp_rid, $force = null) - { - $stat0 = $stat1 = "0"; - - if (isset($this->sxBasePrefs)) { - if ($this->sxBasePrefs->status) { - $stat0 = (string) ($this->sxBasePrefs->status); - } - if ($this->sxTaskSettings->status) { - $stat1 = (string) ($this->sxTaskSettings->status); - } - } - - if (!$stat0) { - $stat0 = '0'; - } - if (!$stat1) { - $stat1 = '0'; - } - - $status = databox_status::operation_or($this->dependencyContainer, $stat0, $stat1); - - $media = $this->dependencyContainer['mediavorus']->guess($pathfile); - - $databox = $collection->get_databox(); - $metadatasStructure = $databox->get_meta_structure(); - - $metadatas = $this->getIndexByFieldName($metadatasStructure, $media->getMetadatas()); - - $metaFields = array(); - if ($captionFile !== null && true === $this->dependencyContainer['filesystem']->exists($captionFile)) { - $metaFields = $this->readXMLForDatabox($metadatasStructure, $captionFile); - $captionStatus = $this->parseStatusBit(@simplexml_load_file($captionFile)); - - if ($captionStatus) { - $status = databox_status::operation_or($this->dependencyContainer, $status, $captionStatus); - } - } - $file = new File($this->dependencyContainer, $media, $collection); - - $file->addAttribute(new BorderAttribute\Status($this->dependencyContainer, $status)); - - $file->addAttribute(new BorderAttribute\Metadata(new Metadata(new PhraseaTag\TfFilepath(), new \PHPExiftool\Driver\Value\Mono($media->getFile()->getRealPath())))); - $file->addAttribute(new BorderAttribute\Metadata(new Metadata(new PhraseaTag\TfDirname(), new \PHPExiftool\Driver\Value\Mono(dirname($media->getFile()->getRealPath()))))); - - $file->addAttribute(new BorderAttribute\Metadata(new Metadata(new PhraseaTag\TfAtime(), new \PHPExiftool\Driver\Value\Mono($media->getFile()->getATime())))); - $file->addAttribute(new BorderAttribute\Metadata(new Metadata(new PhraseaTag\TfMtime(), new \PHPExiftool\Driver\Value\Mono($media->getFile()->getMTime())))); - $file->addAttribute(new BorderAttribute\Metadata(new Metadata(new PhraseaTag\TfCtime(), new \PHPExiftool\Driver\Value\Mono($media->getFile()->getCTime())))); - - foreach ($metadatas as $meta) { - $file->addAttribute(new BorderAttribute\Metadata($meta)); - } - - foreach ($metaFields as $metaField) { - $file->addAttribute($metaField); - } - - if ($grp_rid) { - $file->addAttribute(new BorderAttribute\Story(new record_adapter($this->dependencyContainer, $databox->get_sbas_id(), $grp_rid))); - } - - $record = null; - - $postProcess = function($element, $visa, $code) use (&$record) { - $record = $element; - }; - - $this->dependencyContainer['border-manager']->process($this->getLazaretSession(), $file, $postProcess, $force); - - return $record; - } - - /** - * - * @param \DOMDocument $dom - * @param \DOMElement $node - * @param string $path - * @param string $path_archived - * @param string $path_error - * @param integer $grp_rid - */ - private function archiveFilesToGrp(\DOMDocument $dom, \DOMElement $node, $path, $path_archived, $path_error, $grp_rid) - { - $nodesToDel = array(); - for ($n = $node->firstChild; $this->running && $n; $n = $n->nextSibling) { - if ($n->getAttribute('isdir') == '1') { - // in a grp, all levels goes in the same grp - $node->setAttribute('archived', '1'); // the main grp folder is 'keep'ed, but not subfolders - $this->archiveFilesToGrp($dom, $n, $path . '/' . $n->getAttribute('name') - , $path_archived . '/' . $n->getAttribute('name') - , $path_error . '/' . $n->getAttribute('name') - , $grp_rid); - } else { - // a file - $this->archiveFile($dom, $n, $path, $path_archived, $path_error, $nodesToDel, $grp_rid); - } - } - foreach ($nodesToDel as $n) { - $n->parentNode->removeChild($n); - } - - return; - } - - /** - * Archive File - * - * @param \DOMDocument $dom - * @param \DOMElement $node - * @param string $path - * @param string $path_archived - * @param string $path_error - * @param array $nodesToDel out, filled with files to delete - * @param integer $grp_rid - */ - private function archiveFile(\DOMDocument $dom, \DOMElement $node, $path, $path_archived, $path_error, array &$nodesToDel, $grp_rid = 0) - { - $match = $node->getAttribute('match'); - - if ($match == '*') { - return; - } - - $file = $node->getAttribute('name'); - $captionFileNode = null; - - $rootpath = p4string::delEndSlash(trim((string) ($this->sxTaskSettings->hotfolder))); - $subpath = substr($path, strlen($rootpath)); - - - if (!$match) { - // the file does not match on any mask - $this->log(sprintf(("File '%s' does not match any mask"), $subpath . '/' . $file)); - $node->setAttribute('error', '1'); - - return; - } elseif ($match == '?') { - // the caption file is missing - $this->log(sprintf(("Caption of file '%s' is missing"), $subpath . '/' . $file)); - $node->setAttribute('error', '1'); - - return; - } elseif ($match != '.') { // match='.' : the file does not have a separate caption - $xpath = new DOMXPath($dom); - $dnl = $xpath->query('./file[@name="' . $match . '"]', $node->parentNode); - // in fact, xquery has been done in checkMatch, setting match='?' if caption does not exists... - if ($dnl->length == 1) { - // ...so we ALWAYS come here - $captionFileNode = $dnl->item(0); - } else { - // ...so we should NEVER come here - $node->setAttribute('error', '1'); - - return; - } - } - - $this->archiveFileAndCaption($dom, $node, $captionFileNode, $path, $path_archived, $path_error, $grp_rid, $nodesToDel); - } - - /** - * - * @param \DOMDOcument $dom - * @param \DOMElement $node - * @param \DOMElement $captionFileNode - * @param string $path - * @param string $path_archived - * @param string $path_error - * @param integer $grp_rid - * @param array $nodesToDel out, filled with files to delete - */ - private function archiveFileAndCaption(\DOMDocument $dom, \DOMElement $node, \DOMElement $captionFileNode = null, $path, $path_archived, $path_error, $grp_rid, array &$nodesToDel) - { - $file = $node->getAttribute('name'); - $cid = $node->getAttribute('cid'); - $captionFileName = $captionFileNode ? $captionFileNode->getAttribute('name') : null; - - $rootpath = p4string::delEndSlash(trim((string) ($this->sxTaskSettings->hotfolder))); - $subpath = substr($path, strlen($rootpath)); - - $this->log(sprintf(("Archiving file '%s'"), $subpath . '/' . $file)); - if ($captionFileName !== null) { - $this->log(sprintf(' ' . (" (caption in '%s')"), $captionFileName)); - } - if ($grp_rid !== 0) { - $this->log(sprintf(' ' . (" into GRP rid=%s"), $grp_rid)); - } - - $stat0 = $stat1 = "0"; - if ($this->sxBasePrefs->status) { - $stat0 = (string) ($this->sxBasePrefs->status); - } - if ($this->sxTaskSettings->status) { - $stat1 = (string) ($this->sxTaskSettings->status); - } - if (!$stat0) { - $stat0 = '0'; - } - if (!$stat1) { - $stat1 = '0'; - } - - try { - $databox = $this->dependencyContainer['phraseanet.appbox']->get_databox($this->sbas_id); - $collection = collection::get_from_coll_id($this->dependencyContainer, $databox, (int) $cid); - - if ($captionFileName === null) { - $this->createRecord($collection, $path . '/' . $file, null, $grp_rid); - } else { - $this->createRecord($collection, $path . '/' . $file, $path . '/' . $captionFileName, $grp_rid); - } - - $node->setAttribute('archived', '1'); - - if ($captionFileNode) { - $captionFileNode->setAttribute('archived', '1'); - } - - $this->archivedFiles++; - } catch (\Exception $e) { - - $this->log(("Error : can't insert record : " . $e->getMessage())); - - $node->setAttribute('error', '1'); - - if ($captionFileNode) { - $captionFileNode->setAttribute('error', '1'); - } - } - - if ($node->getAttribute('archived') && $this->move_archived) { - $this->log(sprintf(('copy \'%s\' to \'archived\''), $subpath . '/' . $file)); - - try { - $this->dependencyContainer['filesystem']->mkdir($path_archived); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - - try { - $this->dependencyContainer['filesystem']->copy($path . '/' . $file, $path_archived . '/' . $file, true); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - - if ($captionFileName != $file && $captionFileName) { - $this->log(sprintf(('copy \'%s\' to \'archived\''), $subpath . '/' . $captionFileName)); - - try { - $this->dependencyContainer['filesystem']->copy($path . '/' . $captionFileName, $path_archived . '/' . $captionFileName, true); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - } - } - - if ($node->getAttribute('error') && $this->move_error) { - $this->log(sprintf(('copy \'%s\' to \'error\''), $subpath . '/' . $file)); - - try { - $this->dependencyContainer['filesystem']->mkdir($path_error); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - - try { - $this->dependencyContainer['filesystem']->copy($path . '/' . $file, $path_error . '/' . $file, true); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - - if ($captionFileName != $file && $captionFileName) { - $this->log(sprintf(('copy \'%s\' to \'error\''), $subpath . '/' . $captionFileName)); - - try { - $this->dependencyContainer['filesystem']->copy($path . '/' . $captionFileName, $path_error . '/' . $captionFileName, true); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - } - } - - if (!$node->getAttribute('keep')) { - $file = $node->getAttribute('name'); - - try { - $this->dependencyContainer['filesystem']->remove($path . '/' . $file); - } catch (IOException $e) { - $this->log($e->getMessage()); - } - - $nodesToDel[] = $node; - - $this->movedFiles++; - } - - if ($captionFileNode && !$captionFileNode->getAttribute('keep')) { - $file = $captionFileNode->getAttribute('name'); - - try { - $this->dependencyContainer['filesystem']->remove($path . '/' . $file); - $this->movedFiles ++; - } catch (IOException $e) { - $this->log($e->getMessage()); - } - - $nodesToDel[] = $captionFileNode; - - $this->movedFiles++; - } - - return; - } - - /** - * xml facility : set attributes to a node and all children - * - * @staticvar integer $iloop - * @param \DOMDocument $dom - * @param \DOMElement $node - * @param array $attributes An associative array of attributes - * @param integer $depth - */ - private function setAllChildren(\DOMDocument $dom, \DOMElement $node, array $attributes, $depth = 0) - { - static $iloop = 0; - if ($depth == 0) { - $iloop = 0; - } - - foreach ($attributes as $a => $v) { - $node->setAttribute($a, $v); - } - - if (($iloop++ % 100) == 0) { - usleep(1000); - } - - for ($n = $node->firstChild; $n; $n = $n->nextSibling) { - $this->setAllChildren($dom, $n, $attributes, $depth + 1); - } - } - - /** - * Return the story settings - * - * @param string $file - * @return array - */ - private function getGrpSettings($file) - { - $matched = false; - - foreach ($this->tmaskgrp as $maskgrp) { - $preg_maskgrp = "/" . $maskgrp["mask"] . "/"; - if (preg_match($preg_maskgrp, $file)) { - $matched = $maskgrp; - } - if ($matched) { - break; - } - } - - return $matched; - } - - /** - * Return a LazaretSession - * - * @return LazaretSession - */ - protected function getLazaretSession() - { - if ($this->lazaretSession) { - return $this->lazaretSession; - } - - $lazaretSession = new LazaretSession(); - - $this->dependencyContainer['EM']->persist($lazaretSession); - $this->dependencyContainer['EM']->flush(); - - $this->lazaretSession = $lazaretSession; - - return $this->lazaretSession; - } - - /** - * Map a Bag of metadatas indexed by **Tagnames** to a bag of metadatas - * indexed by **FieldNames** - * - * @param \databox_descriptionStructure $metadatasStructure The databox structure related - * @param ExiftoolMetadataBag $bag The metadata bag - * @return MetadataBag - */ - protected function getIndexByFieldName(\databox_descriptionStructure $metadatasStructure, ExiftoolMetadataBag $bag) - { - $ret = new MetadataBag(); - - foreach ($metadatasStructure as $databox_field) { - if ($bag->containsKey($databox_field->get_tag()->getTagname())) { - $ret->set($databox_field->get_name(), $bag->get($databox_field->get_tag()->getTagname())); - } - } - - return $ret; - } - - protected function readXMLForDatabox(\databox_descriptionStructure $metadatasStructure, $pathfile) - { - if (false === $this->dependencyContainer['filesystem']->exists($pathfile)) { - throw new \InvalidArgumentException(sprintf('file %s does not exists', $pathfile)); - } - - if (false === $sxcaption = @simplexml_load_file($pathfile)) { - throw new \InvalidArgumentException(sprintf('Invalid XML file %s', $pathfile)); - } - - $metadataBag = new MetaFieldsBag(); - - foreach ($sxcaption->description->children() as $tagname => $field) { - $field = trim($field); - - $meta = $metadatasStructure->get_element_by_name(trim($tagname)); - if (!$meta) { - continue; - } - - if ($meta->is_multi()) { - $fields = caption_field::get_multi_values($field, $meta->get_separator()); - - if (!$metadataBag->containsKey($meta->get_name())) { - $values = $fields; - } else { - $values = array_merge($metadataBag->get($meta->get_name())->getValue(), $fields); - } - - $metadataBag->set($meta->get_name(), new BorderAttribute\MetaField($meta, $values)); - } else { - $metadataBag->set($meta->get_name(), new BorderAttribute\MetaField($meta, array($field))); - } - } - - return $metadataBag; - } - - /** - * Parse a Phrasea XML to find status tag - * - * @param \SimpleXMLElement $sxcaption The SimpleXML related to the XML - * @return string - */ - protected function parseStatusBit($sxcaption) - { - if (!$sxcaption instanceof SimpleXMLElement) { - return null; - } - - if ('' !== $inStatus = (string) $sxcaption->status) { - return $inStatus; - } - - return null; - } - - /** - * @param array $params - */ - public static function getDefaultSettings(Configuration $config, array $params = array()) - { - $period = isset($params['period']) ? $params['period'] : self::MINPERIOD; - - return sprintf(" - - - - %s - 0 - 0 - 0 - 0 - - ", min(max($period, self::MINPERIOD), self::MAXPERIOD)); - } -} - -class CListFolder -{ - /** - * - * @var Array - */ - protected $list; - - /** - * - * @param string $path - * @param boolean $sorted - */ - public function __construct($path, $sorted = true) - { - $this->list = array(); - if ($hdir = opendir($path)) { - while (false !== $file = readdir($hdir)) { - $this->list[] = $file; - } - closedir($hdir); - if ($sorted) { - natcasesort($this->list); - } - } - } - - /** - * Destructor - * - */ - public function __destruct() - { - unset($this->list); - } - - /** - * - * @return string - */ - public function read() - { - return array_shift($this->list); - } -} diff --git a/lib/classes/task/period/cindexer.php b/lib/classes/task/period/cindexer.php deleted file mode 100644 index acdb447f92..0000000000 --- a/lib/classes/task/period/cindexer.php +++ /dev/null @@ -1,656 +0,0 @@ -get_parms( - 'host', 'port', 'base', 'user', 'password', 'socket', 'nolog', 'clng', 'winsvc_run', 'charset', 'debugmask', 'stem', 'sortempty' - ); - $dom = new DOMDocument(); - $dom->formatOutput = true; - if ($dom->loadXML($oldxml)) { - foreach (array("str:host", "str:port", "str:base", "str:user", "str:password", "str:socket", "boo:nolog", "str:clng", "boo:winsvc_run", "str:charset", 'str:debugmask', 'str:stem', 'str:sortempty') as $pname) { - $ptype = substr($pname, 0, 3); - $pname = substr($pname, 4); - $pvalue = $parm2[$pname]; - if (($ns = $dom->getElementsByTagName($pname)->item(0)) != NULL) { - // le champ existait dans le xml, on supprime son ancienne valeur (tout le contenu) - while (($n = $ns->firstChild)) { - $ns->removeChild($n); - } - } else { - // le champ n'existait pas dans le xml, on le cree - $ns = $dom->documentElement->appendChild($dom->createElement($pname)); - } - // on fixe sa valeur - switch ($ptype) { - case "str": - $ns->appendChild($dom->createTextNode($pvalue)); - break; - case "boo": - $ns->appendChild($dom->createTextNode($pvalue ? '1' : '0')); - break; - } - } - } - - return($dom->saveXML()); - } - - - /** - * - * @return void - */ - public function printInterfaceJS() - { - ?> - - -
-
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- - -
-
-
- -
- -
-
-
-
- -
-
-
-
- -
-
-
- -
-
cmd
-
- host = trim($sx_task_settings->host); - $this->port = trim($sx_task_settings->port); - $this->base = trim($sx_task_settings->base); - $this->user = trim($sx_task_settings->user); - $this->password = trim($sx_task_settings->password); - $this->socket = trim($sx_task_settings->socket); - $this->charset = trim($sx_task_settings->charset); - $this->stem = trim($sx_task_settings->stem); - $this->sortempty = trim($sx_task_settings->sortempty); - $this->debugmask = (int) (trim($sx_task_settings->debugmask)); - $this->nolog = p4field::isyes(trim($sx_task_settings->nolog)); - $this->winsvc_run = p4field::isyes(trim($sx_task_settings->winsvc_run)); - - parent::loadSettings($sx_task_settings); - } - - private function getIndexer() - { - $binaries = $this->dependencyContainer['phraseanet.configuration']['binaries']; - - if (isset($binaries['phraseanet_indexer'])) { - $cmd = $binaries['phraseanet_indexer']; - } else { - $finder = new ExecutableFinder(); - $cmd = $finder->find('phraseanet_indexer'); - } - - return $cmd; - } - - /** - * - * @return void - */ - protected function run2() - { - $cmd = $this->getIndexer(); - - $this->method = self::METHOD_PROC_OPEN; - - if ( ! file_exists($cmd) || ! is_executable($cmd)) { - $this->setState(self::STATE_STOPPED); - $this->log(sprintf('File \'%s\' does not exists', $cmd)); - throw new Exception('cindexer executable not found', self::ERR_EXECUTABLE_NOT_FOUND); - - return; - } - - $args = array(); - $args_nopwd = array(); - if ($this->host) { - $args[] = '-h=' . $this->host; - $args_nopwd[] = '-h=' . $this->host; - } - if ($this->port) { - $args[] = '-P=' . $this->port; - $args_nopwd[] = '-P=' . $this->port; - } - if ($this->base) { - $args[] = '-b=' . $this->base; - $args_nopwd[] = '-b=' . $this->base; - } - if ($this->user) { - $args[] = '-u=' . $this->user; - $args_nopwd[] = '-u=' . $this->user; - } - if ($this->password) { - $args[] = '-p=' . $this->password; - $args_nopwd[] = '-p=xxxxxxx'; - } - if ($this->socket) { - $args[] = '--socket=' . $this->socket; - $args_nopwd[] = '--socket=' . $this->socket; - } - - $args[] = '-o'; - $args_nopwd[] = '-o'; - - if ($this->charset) { - $args[] = '--default-character-set=' . $this->charset; - $args_nopwd[] = '--default-character-set=' . $this->charset; - } - if ($this->stem) { - $args[] = '--stem=' . $this->stem; - $args_nopwd[] = '--stem=' . $this->stem; - } - if ($this->sortempty) { - $args[] = '--sort-empty=' . $this->sortempty; - $args_nopwd[] = '--sort-empty=' . $this->sortempty; - } - if ($this->debugmask > 0) { - $args[] = '-d=' . $this->debugmask; - $args_nopwd[] = '-d=' . $this->debugmask; - } - if ($this->nolog) { - $args[] = '-n'; - $args_nopwd[] = '-n'; - } - if ($this->winsvc_run) { - $args[] = '--run'; - $args_nopwd[] = '--run'; - } - - $this->new_status = NULL; // new status to set at the end - $this->exception = NULL; // exception to throw at the end - - $this->log(sprintf("running cindexer with method %s", $this->method)); - switch ($this->method) { - case self::METHOD_PROC_OPEN: - $this->run_with_proc_open($cmd, $args, $args_nopwd); - break; - case self::METHOD_FORK: - $this->run_with_fork($cmd, $args, $args_nopwd); - break; - case self::METHOD_EXEC: - $this->run_with_exec($cmd, $args, $args_nopwd); - break; - } - - if ($this->new_status !== NULL) { - $this->setState($this->new_status); - } - - if ($this->exception) { - throw $this->exception; - } - } - - private function run_with_proc_open($cmd, $args, $args_nopwd) - { - $nullfile = defined('PHP_WINDOWS_VERSION_BUILD') ? 'NUL' : '/dev/null'; - - $descriptors = array(); - $descriptors[1] = array("file", $nullfile, "a+"); - $descriptors[2] = array("file", $nullfile, "a+"); - - $pipes = array(); - - $logcmd = escapeshellarg($cmd).' '.implode(' ', array_map('escapeshellarg', $args_nopwd)); - $execmd = escapeshellarg($cmd).' '.implode(' ', array_map('escapeshellarg', $args)); - - $this->log(sprintf('cmd=\'%s\'', $logcmd)); - - $process = proc_open($execmd, $descriptors, $pipes, dirname($cmd), null, array('bypass_shell' => true)); - - $qsent = ''; - $timetokill = NULL; - $sock = NULL; - - $this->running = true; - - while ($this->running) { - if ($this->getState() == self::STATE_TOSTOP && $this->socket > 0) { - // must quit task, so send 'Q' to port 127.0.0.1:XXXX to cindexer - if ( ! $qsent && (($sock = socket_create(AF_INET, SOCK_STREAM, 0)) !== false)) { - if (socket_connect($sock, '127.0.0.1', $this->socket) === true) { - socket_write($sock, 'Q', 1); - socket_write($sock, "\r\n", strlen("\r\n")); - for ($i = 0; $this->running && $i < 5; $i ++) { - $this->sleep(1); - } - $qsent = 'Q'; - $timetokill = time() + 10; - } else { - socket_close($sock); - $sock = NULL; - } - } - } - - $proc_status = proc_get_status($process); - if (! $proc_status['running']) { - // the cindexer died - if ($qsent == 'Q') { - $this->log('Phrasea indexer stopped'); - $this->new_status = self::STATE_STOPPED; - } elseif ($qsent == 'K') { - $this->log('Phrasea indexer has been killed'); - $this->new_status = self::STATE_STOPPED; - } else { - $this->log('Phrasea indexer crashed'); - $this->exception = new Exception('cindexer crashed', self::ERR_CRASHED); - // do not change the status so scheduler may restart it - } - $this->running = false; - } else { - // the cindexer is still alive - if ($qsent == 'Q') { - if (time() > $timetokill) { - // must kill cindexer - $this->log('Sending kill signal to Phrasea indexer'); - $qsent = 'K'; - proc_terminate($process); // sigint - } - } - } - for ($i = 0; $this->running && $i < 5; $i ++) { - $this->sleep(1); - } - } - - if ($sock) { - socket_close($sock); - $sock = NULL; - } - - foreach (array_keys($pipes) as $offset) { - if (is_resource($pipes[$offset])) { - fclose($pipes[$offset]); - } - } - - proc_terminate($process); // sigint - proc_close($process); - } - - private function run_with_fork($cmd, $args, $args_nopwd) - { - $pid = pcntl_fork(); - if ($pid == -1) { - $this->exception = new Exception('cindexer can\'t fork', self::ERR_CANT_FORK); - } elseif ($pid == 0) { - // child - umask(0); - if (($err = posix_setsid()) < 0) { - $this->exception = new Exception('cindexer can\'t detach from terminal', $err); - } else { - chdir(dirname(__FILE__)); - pcntl_exec($cmd, $args); - $this->sleep(2); - } - } else { - // parent - $this->running = true; - - $sigsent = NULL; - while ($this->running) { - // is the cindexer alive ? - if ( ! posix_kill($pid, 0)) { - // dead... - if ($sigsent === NULL) { - // but it's not my fault - $this->log('Phrasea indexer crashed'); - $this->exception = new Exception('cindexer crashed', self::ERR_CRASHED); - // do not change the status so scheduler may restart it - break; - } - } - - if ($this->getState() == self::STATE_TOSTOP) { - posix_kill($pid, ($sigsent = SIGINT)); - $timetokill = time() + 10; - $this->sleep(2); - } - - $status = NULL; - if (pcntl_wait($status, WNOHANG) == $pid) { - // child (indexer) has exited - if ($sigsent == SIGINT) { - $this->log('Phrasea indexer stopped'); - $this->new_status = self::STATE_STOPPED; - } elseif ($sigsent == SIGKILL) { - $this->log('Phrasea indexer has been killed'); - $this->new_status = self::STATE_STOPPED; - } else { - $this->log('Phrasea indexer crashed'); - $this->exception = new Exception('cindexer crashed', self::ERR_CRASHED); - // do not change the status so scheduler may restart it - } - $this->running = false; - } else { - if ($sigsent == SIGINT && time() > $timetokill) { - // must kill cindexer - $this->log('Kill signal sent to Phrasea indexer'); - posix_kill($pid, ($sigsent = SIGKILL)); - } - $this->sleep(2); - } - } // while running - } - } - - private function run_with_exec($cmd, $args, $args_nopwd) - { - pcntl_exec($cmd, $args); - $this->sleep(2); - } - - /** - * @param array $params - */ - public static function getDefaultSettings(Configuration $config, array $params = array()) - { - $database = $config['main']['database']; - - return "\n\n" - ."" . $database['host'] . "" - . $database['port'] . "" - . $database['dbname'] . "" - . $database['user'] . "" - . $database['password'] . "25200" - . "10" - . "0utf8"; - } -} diff --git a/lib/classes/task/period/emptyColl.php b/lib/classes/task/period/emptyColl.php deleted file mode 100644 index 236a4fddc8..0000000000 --- a/lib/classes/task/period/emptyColl.php +++ /dev/null @@ -1,80 +0,0 @@ -' . (isset($params['bas_id']) ? $params['bas_id'] : '' ) . ''; - } - - protected function loadSettings(SimpleXMLElement $sx_task_settings) - { - $this->base_id = (int) $sx_task_settings->base_id; - parent::loadSettings($sx_task_settings); - } - - protected function retrieveContent(appbox $appbox) - { - if (! $this->base_id) { - $this->setState(self::STATE_STOPPED); - - return array(); - } - $collection = collection::get_from_base_id($this->dependencyContainer, $this->base_id); - $this->total_records = $collection->get_record_amount(); - $collection->empty_collection(200); - $this->records_done += $this->total_records; - $this->setProgress($this->records_done, $this->total_records); - - if ($this->total_records == 0) { - $this->setState(self::STATE_STOPPED); - $this->log('Job finished'); - } - - return array(); - } - - protected function processOneContent(appbox $appbox, $row) - { - return $this; - } - - protected function postProcessOneContent(appbox $appbox, $row) - { - return $this; - } -} diff --git a/lib/classes/task/period/ftp.php b/lib/classes/task/period/ftp.php deleted file mode 100644 index 903303ab97..0000000000 --- a/lib/classes/task/period/ftp.php +++ /dev/null @@ -1,618 +0,0 @@ -get_parms('proxy', 'proxyport', 'period', 'syslog'); - $dom = new DOMDocument(); - $dom->preserveWhiteSpace = false; - $dom->formatOutput = true; - if ((@$dom->loadXML($oldxml)) != FALSE) { - foreach (array('str:proxy', 'str:proxyport', 'str:period', 'pop:syslog') as $pname) { - $ptype = substr($pname, 0, 3); - $pname = substr($pname, 4); - $pvalue = $parm2[$pname]; - if (($ns = $dom->getElementsByTagName($pname)->item(0)) != NULL) { - // le champ existait dans le xml, on supprime son ancienne valeur (tout le contenu) - while (($n = $ns->firstChild)) { - $ns->removeChild($n); - } - } else { - // le champ n'existait pas dans le xml, on le cree - $ns = $dom->documentElement->appendChild($dom->createElement($pname)); - } - // on fixe sa valeur - switch ($ptype) { - case "str": - case "pop": - $ns->appendChild($dom->createTextNode($pvalue)); - break; - case "boo": - $ns->appendChild($dom->createTextNode($pvalue ? '1' : '0')); - break; - } - } - } - - return($dom->saveXML()); - } - - - /** - * - * @return void - */ - public function printInterfaceJS() - { - ?> - - -
-
- -
- -
-
-
- -
- -
-
-
- -
- - -
-
-
- get_parms( - 'xml' - , 'name' - , 'active' - , 'proxy' - , 'proxyport' - , 'period' - ); - - if ($parm["xml"] === null) { - // pas de xml 'raw' : on accepte les champs 'graphic view' - $domTaskSettings = new DOMDocument(); - if ((@$domTaskSettings->loadXML($taskrow["settings"])) != FALSE) { - $xmlchanged = false; - foreach (array( - 'proxy' - , 'proxyport' - , 'period' - ) as $f) { - if ($parm[$f] !== NULL) { - if (($ns = $domTaskSettings->getElementsByTagName($f)->item(0)) != NULL) { - // le champ existait dans le xml, on supprime son ancienne valeur (tout le contenu) - while (($n = $ns->firstChild)) { - $ns->removeChild($n); - } - } else { - // le champ n'existait pas dans le xml, on le cree - $ns = $domTaskSettings->documentElement->appendChild($domTaskSettings->createElement($f)); - } - // on fixe sa valeur - $ns->appendChild($domTaskSettings->createTextNode($parm[$f])); - $xmlchanged = true; - } - } - if ($xmlchanged) { - $parm["xml"] = $domTaskSettings->saveXML(); - } - } - } - - // si on doit changer le xml, on verifie qu'il est valide - $domdoc = new DOMDocument(); - if ($parm["xml"] && ! @$domdoc->loadXML($parm["xml"])) { - return(false); - } - - $sql = ""; - $params = array(':task_id' => $taskid); - if ($parm["xml"] !== NULL) { - $sql .= ( $sql ? " ," : "") . "settings = :settings"; - $params[':settings'] = $parm['xml']; - } - if ($parm["name"] !== NULL) { - $sql .= ( $sql ? " ," : "") . "name = :name"; - $params[':name'] = $parm['name']; - } - if ($parm["active"] !== NULL) { - $sql .= ( $sql ? " ," : "") . "active = :active"; - $params[':active'] = $parm['active']; - } - - if ($sql) { - try { - $sql = "UPDATE task2 SET $sql WHERE task_id = :task_id"; - $stmt = $conn->prepare($sql); - $stmt->execute($params); - $stmt->closeCursor(); - - return true; - } catch (Exception $e) { - return false; - } - } else { - return true; - } - } - - protected function loadSettings(SimpleXMLElement $sx_task_settings) - { - $this->proxy = (string) $sx_task_settings->proxy; - $this->proxyport = (string) $sx_task_settings->proxyport; - - parent::loadSettings($sx_task_settings); - } - - protected function retrieveContent(appbox $appbox) - { - foreach ($this->dependencyContainer['EM'] - ->getRepository('Alchemy\Phrasea\Model\Entities\FtpExport') - ->findCrashedExports(new \DateTime('-1 month')) as $export) { - $this->dependencyContainer['EM']->remove($export); - } - $this->dependencyContainer['EM']->flush(); - - return $this->dependencyContainer['EM'] - ->getRepository('Alchemy\Phrasea\Model\Entities\FtpExport') - ->findDoableExports(); - } - - protected function processOneContent(appbox $appbox, $export) - { - $state = ""; - $ftp_server = $export->getAddr(); - $ftp_user_name = $export->getLogin(); - $ftp_user_pass = $export->getPwd(); - - $ftpLog = $ftp_user_name . "@" . p4string::addEndSlash($ftp_server) . $export->getDestfolder(); - - if ($export->getCrash() == 0) { - $line = sprintf( - _('task::ftp:Etat d\'envoi FTP vers le serveur' . - ' "%1$s" avec le compte "%2$s" et pour destination le dossier : "%3$s"') . PHP_EOL - , $ftp_server - , $ftp_user_name - , $export->getDestfolder() - ); - $state .= $line; - $this->logger->addDebug($line); - } - - $state .= $line = sprintf( - _("task::ftp:TENTATIVE no %s, %s") - , $export->getCrash() + 1 - , " (" . date('r') . ")" - ) . PHP_EOL; - - $this->logger->addDebug($line); - - try { - $ssl = $export->isSsl(); - $ftp_client = $this->dependencyContainer['phraseanet.ftp.client']($ftp_server, 21, 300, $ssl, $this->proxy, $this->proxyport); - $ftp_client->login($ftp_user_name, $ftp_user_pass); - - if ($export->isPassif()) { - try { - $ftp_client->passive(true); - } catch (Exception $e) { - $this->logger->addDebug($e->getMessage()); - } - } - - if (trim($export->getDestfolder()) != '') { - try { - $ftp_client->chdir($export->getDestFolder()); - $export->setDestfolder('/' . $export->getDestfolder()); - } catch (Exception $e) { - $this->logger->addDebug($e->getMessage()); - } - } else { - $export->setDestfolder('/'); - } - - if (trim($export->getFoldertocreate()) != '') { - try { - $ftp_client->mkdir($export->getFoldertocreate()); - } catch (Exception $e) { - $this->logger->addDebug($e->getMessage()); - } - try { - $new_dir = $ftp_client->add_end_slash($export->getDestfolder()) - . $export->getFoldertocreate(); - $ftp_client->chdir($new_dir); - } catch (Exception $e) { - $this->logger->addDebug($e->getMessage()); - } - } - - $obj = array(); - - $basefolder = ''; - if (!in_array(trim($export->getDestfolder()), array('.', './', ''))) { - $basefolder = p4string::addEndSlash($export->getDestfolder()); - } - - $basefolder .= $export->getFoldertocreate(); - - if (in_array(trim($basefolder), array('.', './', ''))) { - $basefolder = '/'; - } - - foreach ($export->getElements() as $exportElement) { - if ($exportElement->isDone()) { - continue; - } - - $base_id = $exportElement->getBaseId(); - $record_id = $exportElement->getRecordId(); - $subdef = $exportElement->getSubdef(); - $localfile = null; - - try { - $sbas_id = phrasea::sbasFromBas($this->dependencyContainer, $base_id); - $record = new record_adapter($this->dependencyContainer, $sbas_id, $record_id); - - $sdcaption = $record->get_caption()->serialize(caption_record::SERIALIZE_XML, $exportElement->isBusinessfields()); - - $remotefile = $exportElement->getFilename(); - - if ($subdef == 'caption') { - $desc = $record->get_caption()->serialize(\caption_record::SERIALIZE_XML, $exportElement->isBusinessfields()); - - $localfile = $this->dependencyContainer['root.path'] . '/tmp/' . md5($desc . time() . mt_rand()); - if (file_put_contents($localfile, $desc) === false) { - throw new Exception('Impossible de creer un fichier temporaire'); - } - } elseif ($subdef == 'caption-yaml') { - $desc = $record->get_caption()->serialize(\caption_record::SERIALIZE_YAML, $exportElement->isBusinessfields()); - - $localfile = $this->dependencyContainer['root.path'] . '/tmp/' . md5($desc . time() . mt_rand()); - if (file_put_contents($localfile, $desc) === false) { - throw new Exception('Impossible de creer un fichier temporaire'); - } - } else { - $sd = $record->get_subdefs(); - - if (!$sd || !isset($sd[$subdef])) { - continue; - } - - $localfile = $sd[$subdef]->get_pathfile(); - if (!file_exists($localfile)) { - throw new Exception('Le fichier local n\'existe pas'); - } - } - - $current_folder = p4string::delEndSlash(str_replace('//', '/', $basefolder . $exportElement->getFolder())); - - if ($ftp_client->pwd() != $current_folder) { - try { - $ftp_client->chdir($current_folder); - } catch (Exception $e) { - $this->logger->addDebug($e->getMessage()); - } - } - - $ftp_client->put($remotefile, $localfile); - - $obj[] = array( - "name" => $subdef, "size" => filesize($localfile), - "shortXml" => ($sdcaption ? $sdcaption : '') - ); - - if ($subdef == 'caption') { - unlink($localfile); - } - - $exportElement - ->setDone(true) - ->setError(false); - $this->dependencyContainer['EM']->persist($exportElement); - $this->dependencyContainer['EM']->flush(); - $this->logexport($record, $obj, $ftpLog); - } catch (Exception $e) { - $state .= $line = sprintf(_('task::ftp:File "%1$s" (record %2$s) de la base "%3$s"' . - ' (Export du Document) : Transfert cancelled (le document n\'existe plus)') - , basename($localfile), $record_id - , phrasea::sbas_labels(phrasea::sbasFromBas($this->dependencyContainer, $base_id), $this->dependencyContainer)) . "\n
"; - - $this->logger->addDebug($line); - - // One failure max - $exportElement - ->setDone($exportElement->isError()) - ->setError(true); - $this->dependencyContainer['EM']->persist($exportElement); - $this->dependencyContainer['EM']->flush(); - } - } - - if ($export->isLogfile()) { - $this->logger->addDebug("logfile "); - - $date = new DateTime(); - $buffer = '#transfert finished ' . $date->format(DATE_ATOM) . "\n\n"; - - foreach ($export->getElements() as $exportElement) { - if (!$exportElement->isDone() || $exportElement->isError()) { - continue; - } - $filename = $exportElement->getFilename(); - $folder = $exportElement->getFilename(); - $root = $export->getFoldertocreate(); - - $buffer .= $root . '/' . $folder . $filename . "\n"; - } - - $tmpfile = $this->dependencyContainer['root.path'] . '/tmp/tmpftpbuffer' . $date->format('U') . '.txt'; - - file_put_contents($tmpfile, $buffer); - - $remotefile = $date->format('U') . '-transfert.log'; - $ftp_client->chdir($export->getDestFolder()); - $ftp_client->put($remotefile, $tmpfile); - unlink($tmpfile); - } - - $ftp_client->close(); - unset($ftp_client); - } catch (Exception $e) { - $state .= $line = $e . "\n"; - - $this->logger->addDebug($line); - - $export->incrementCrash(); - $this->dependencyContainer['EM']->persist($export); - $this->dependencyContainer['EM']->flush(); - - unset($ftp_client); - } - - $this->finalize($appbox, $export); - } - - protected function postProcessOneContent(appbox $appbox, $row) - { - return $this; - } - - public function finalize(appbox $appbox, FtpExport $export) - { - if ($export->getCrash() >= $export->getNbretry()) { - $this->send_mails($appbox, $export); - - return $this; - } - - $total = count($export->getElements()); - $done = count($export->getElements()->filter(function (FtpExportElement $element) { - return $element->isDone(); - })); - $error = count($export->getElements()->filter(function (FtpExportElement $element) { - return $element->isError(); - })); - - if ($done === $total) { - $this->send_mails($appbox, $export); - - if ((int) $error === 0) { - $this->dependencyContainer['EM']->remove($export); - $this->dependencyContainer['EM']->flush(); - } else { - $export->setCrash($export->getNbretry()); - foreach ($export->getElements() as $element) { - if (!$element->isError()) { - $this->dependencyContainer['EM']->remove($export); - } - } - $this->dependencyContainer['EM']->flush(); - } - - return $this; - } - } - - public function send_mails(appbox $appbox, FtpExport $export) - { - $transferts = array(); - $transfert_status = _('task::ftp:Tous les documents ont ete transferes avec succes'); - - foreach ($export->getElements() as $element) { - if (!$element->isError() && $element->isDone()) { - $transferts[] = - '
  • ' . sprintf(_('task::ftp:Record %1$s - %2$s de la base (%3$s - %4$s) - %5$s') - , $element->getRecordId(), $element->getFilename() - , phrasea::sbas_labels(phrasea::sbasFromBas($this->dependencyContainer, $element->getBaseId()), $this->dependencyContainer) - , phrasea::bas_labels($element->getBaseId(), $this->dependencyContainer), $element->getSubdef()) . ' : ' . _('Transfert OK') . '
  • '; - } else { - $transferts[] = - '
  • ' . sprintf(_('task::ftp:Record %1$s - %2$s de la base (%3$s - %4$s) - %5$s') - , $element->getRecordId(), $element->getFilename() - , phrasea::sbas_labels(phrasea::sbasFromBas($this->dependencyContainer, $element->getBaseId()), $this->dependencyContainer), phrasea::bas_labels($element->getBaseId(), $this->dependencyContainer) - , $element->getSubdef()) . ' : ' . _('Transfert Annule') . '
  • '; - $transfert_status = _('task::ftp:Certains documents n\'ont pas pu etre tranferes'); - } - } - - if ($export->getCrash() >= $export->getNbretry()) { - $connection_status = _('Des difficultes ont ete rencontres a la connection au serveur distant'); - } else { - $connection_status = _('La connection vers le serveur distant est OK'); - } - - $text_mail_sender = $export->getTextMailSender(); - $text_mail_receiver = $export->getTextMailReceiver(); - $mail = $export->getMail(); - $sendermail = $export->getSendermail(); - $ftp_server = $export->getAddr(); - - $message = "\n\n----------------------------------------\n\n"; - $message = $connection_status . "\n"; - $message .= $transfert_status . "\n"; - $message .= _("task::ftp:Details des fichiers") . "\n\n"; - - $message .= implode("\n", $transferts); - - $sender_message = $text_mail_sender . $message; - $receiver_message = $text_mail_receiver . $message; - - try { - $receiver = new Receiver(null, $sendermail); - } catch (InvalidArgumentException $e) { - $receiver = null; - } - - if ($receiver) { - $mail = MailSuccessFTPSender::create($this->dependencyContainer, $receiver, null, $sender_message); - $mail->setServer($ftp_server); - $this->dependencyContainer['notification.deliverer']->deliver($mail); - } - - try { - $receiver = new Receiver(null, $mail); - $mail = MailSuccessFTPSender::create($this->dependencyContainer, $receiver, null, $receiver_message); - $mail->setServer($ftp_server); - $this->dependencyContainer['notification.deliverer']->deliver($mail); - } catch (\Exception $e) { - $this->log('Unable to deliver success message'); - } - } - - public function logexport(record_adapter $record, $obj, $ftpLog) - { - foreach ($obj as $oneObj) { - $this->dependencyContainer['phraseanet.logger']($record->get_databox()) - ->log($record, Session_Logger::EVENT_EXPORTFTP, $ftpLog, ''); - } - - return $this; - } - - /** - * @param array $params - */ - public static function getDefaultSettings(Configuration $config, array $params = array()) - { - $period = isset($params['period']) ? $params['period'] : self::MINPERIOD; - - return sprintf(" - - - - %s - - ", min(max($period, self::MINPERIOD), self::MAXPERIOD)); - } -} diff --git a/lib/classes/task/period/ftpPull.php b/lib/classes/task/period/ftpPull.php deleted file mode 100644 index 58fff2af3a..0000000000 --- a/lib/classes/task/period/ftpPull.php +++ /dev/null @@ -1,473 +0,0 @@ -get_parms( - 'proxy' - , 'proxyport' - , 'host' - , 'port' - , 'user' - , 'password' - , 'ssl' - , 'ftppath' - , 'localpath' - , 'passive' - , 'period' - ); - $dom = new DOMDocument(); - $dom->preserveWhiteSpace = false; - $dom->formatOutput = true; - if (@$dom->loadXML($oldxml)) { - $xmlchanged = false; - foreach (array( - 'str:proxy' - , 'str:proxyport' - , 'str:period' - , 'boo:passive' - , 'boo:ssl' - , 'str:password' - , 'str:user' - , 'str:ftppath' - , 'str:localpath' - , 'str:port' - , 'str:host' - ) as $pname) { - $ptype = substr($pname, 0, 3); - $pname = substr($pname, 4); - $pvalue = $parm2[$pname]; - if ($ns = $dom->getElementsByTagName($pname)->item(0)) { - // le champ existait dans le xml, on supprime son ancienne valeur (tout le contenu) - while (($n = $ns->firstChild)) { - $ns->removeChild($n); - } - } else { - // le champ n'existait pas dans le xml, on le cree - $ns = $dom->documentElement->appendChild($dom->createElement($pname)); - } - // on fixe sa valeur - switch ($ptype) { - case "str": - case "pop": - $ns->appendChild($dom->createTextNode($pvalue)); - break; - case "boo": - $ns->appendChild($dom->createTextNode($pvalue ? '1' : '0')); - break; - } - $xmlchanged = true; - } - } - - return($dom->saveXML()); - } - - - public function printInterfaceJS() - { - ?> - - - -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    -
    - -
    -
    -
    - -
    - - -
    -
    -
    - get_parms( - 'xml' - , 'name' - , 'active' - , 'proxy' - , 'proxyport' - , 'period' - , 'localpath' - , 'ftppath' - , 'port' - , 'host' - , 'user' - , 'password' - , 'passive' - , 'ssl' - ); - - if ($parm["xml"] === null) { - // pas de xml 'raw' : on accepte les champs 'graphic view' - $domdoc = new DOMDocument(); - if (($domTaskSettings = $domdoc->loadXML($taskrow["settings"])) != FALSE) { - $xmlchanged = false; - foreach (array( - 'proxy' - , 'proxyport' - , 'period' - , 'localpath' - , 'ftppath' - , 'host' - , 'port' - , 'user' - , 'password' - , 'passive' - , 'ssl' - ) as $f) { - if ($parm[$f] !== NULL) { - if (($ns = $domTaskSettings->getElementsByTagName($f)->item(0)) != NULL) { - // le champ existait dans le xml, on supprime son ancienne valeur (tout le contenu) - while (($n = $ns->firstChild)) { - $ns->removeChild($n); - } - } else { - // le champ n'existait pas dans le xml, on le cree - $ns = $domTaskSettings->documentElement->appendChild($domTaskSettings->createElement($f)); - } - // on fixe sa valeur - $ns->appendChild($domTaskSettings->createTextNode($parm[$f])); - $xmlchanged = true; - } - } - if ($xmlchanged) { - $parm["xml"] = $domTaskSettings->saveXML(); - } - } - } - - // si on doit changer le xml, on verifie qu'il est valide - $domdoc = new DOMDocument(); - if ($parm["xml"] && ! $domdoc->loadXML($parm["xml"])) { - return(false); - } - - $sql = ""; - $params = array(':task_id' => $taskid); - if ($parm["xml"] !== NULL) { - $sql .= ( $sql ? " ," : "") . "settings = :settings"; - $params[':settings'] = $parm['xml']; - } - if ($parm["name"] !== NULL) { - $sql .= ( $sql ? " ," : "") . "name = :name"; - $params[':name'] = $parm['name']; - } - if ($parm["active"] !== NULL) { - $sql .= ( $sql ? " ," : "") . "active = :active"; - $params[':active'] = $parm['active']; - } - - if ($sql) { - try { - $sql = "UPDATE task2 SET $sql WHERE task_id = :task_id"; - $stmt = $conn->prepare($sql); - $stmt->execute($params); - $stmt->closeCursor(); - - return true; - } catch (Exception $e) { - return false; - } - } else { - return true; - } - } - - protected function loadSettings(SimpleXMLElement $sx_task_settings) - { - $this->proxy = (string) $sx_task_settings->proxy; - $this->proxyport = (string) $sx_task_settings->proxyport; - $this->host = (string) ($sx_task_settings->host); - $this->port = (string) ($sx_task_settings->port); - $this->user = (string) ($sx_task_settings->user); - $this->password = (string) ($sx_task_settings->password); - $this->ssl = !!((string) ($sx_task_settings->ssl)); - $this->passive = !!((string) ($sx_task_settings->passive)); - $this->ftppath = (string) ($sx_task_settings->ftppath); - $this->localpath = (string) ($sx_task_settings->localpath); - - parent::loadSettings($sx_task_settings); - } - - protected function retrieveContent(appbox $appbox) - { - foreach (array('localpath', 'host', 'port', 'user', 'password', 'ftppath') as $f) { - if (trim((string) ($this->{$f})) === '') { - $this->log(sprintf('setting \'%s\' must be set', $f), self::LOG_ERROR); - $this->running = FALSE; - } - } - - $this->dependencyContainer['filesystem']->mkdir($this->localpath, 0750); - - if (!is_dir($this->localpath)) { - $this->log(sprintf('\'%s\' does not exists', $this->localpath), self::LOG_ERROR); - $this->running = FALSE; - } - if (!is_writeable($this->localpath)) { - $this->log(sprintf('\'%s\' is not writeable', $this->localpath), self::LOG_ERROR); - $this->running = FALSE; - } - - if (!$this->running) { - $this->set_status(self::STATE_STOPPED); - - return array(); - } - - try { - $ftp = $this->dependencyContainer['phraseanet.ftp.client']($this->host, $this->port, 90, $this->ssl, $this->proxy, $this->proxyport); - $ftp->login($this->user, $this->password); - $ftp->chdir($this->ftppath); - $list_1 = $ftp->list_directory(true); - - $done = 0; - $todo = count($list_1); - $this->setProgress($done, $todo); - - $this->logger->addDebug("attente de 25sec pour avoir les fichiers froids..."); - - $this->sleep(25); - if (!$this->running) { - if (isset($ftp) && $ftp instanceof ftpclient) { - $ftp->close(); - } - - return array(); - } - - $list_2 = $ftp->list_directory(true); - - foreach ($list_1 as $filepath => $timestamp) { - $done++; - $this->setProgress($done, $todo); - - if (!isset($list_2[$filepath])) { - $this->logger->addDebug("le fichier $filepath a disparu...\n"); - continue; - } - if ($list_2[$filepath] !== $timestamp) { - $this->logger->addDebug("le fichier $filepath a ete modifie depuis le dernier passage..."); - continue; - } - - $finalpath = p4string::addEndSlash($this->localpath) . ($filepath[0] == '/' ? mb_substr($filepath, 1) : $filepath); - $this->logger->addDebug("Ok pour rappatriement de $filepath vers $finalpath\n"); - - try { - if (file_exists($finalpath)) { - throw new Exception("Un fichier du meme nom ($finalpath) existe deja..."); - } - - $this->dependencyContainer['filesystem']->mkdir(dirname($finalpath), 0750); - - $ftp->get($finalpath, $filepath); - $ftp->delete($filepath); - } catch (Exception $e) { - $this->logger->addDebug("Erreur lors du rappatriement de $filepath : " . $e->getMessage()); - } - } - - $ftp->close(); - - $this->setProgress(0, 0); - } catch (Exception $e) { - if (isset($ftp) && $ftp instanceof ftpclient) { - $ftp->close(); - } - $this->log($e->getMessage(), self::LOG_ERROR); - - return array(); - } - } - - protected function processOneContent(appbox $appbox, $row) - { - - } - - protected function postProcessOneContent(appbox $appbox, $row) - { - - } - - /** - * @param array $params - */ - public static function getDefaultSettings(Configuration $config, array $params = array()) - { - $period = isset($params['period']) ? $params['period'] : self::MINPERIOD; - - return sprintf(" - - - - %s - 0 - 0 - - - - - 21 - - ", min(max($period, self::MINPERIOD), self::MAXPERIOD)); - } -} diff --git a/lib/classes/task/period/subdef.php b/lib/classes/task/period/subdef.php deleted file mode 100644 index 0a325a78a8..0000000000 --- a/lib/classes/task/period/subdef.php +++ /dev/null @@ -1,372 +0,0 @@ - - */ - protected $record_buffer_size; - - protected $thumbnailExtraction; - - /** - * Return about text - * - * @return - */ - public static function help() - { - return( - _("task::subdef:creation des sous definitions des documents d'origine") - ); - } - - /** - * Returns task name - * - * @return string - */ - public static function getName() - { - return(_('task::subdef:creation des sous definitions')); - } - - protected function loadSettings(SimpleXMLElement $sx_task_settings) - { - $this->thumbnailExtraction = (Boolean) trim($sx_task_settings->embedded); - - parent::loadSettings($sx_task_settings); - } - - /** - * must return the xml (text) version of the form - * - * @param string $oldxml - * @return string - */ - public function graphic2xml($oldxml) - { - $request = http_request::getInstance(); - - $parm2 = $request->get_parms('period', 'flush', 'maxrecs', 'maxmegs', 'embedded'); - $dom = new DOMDocument(); - $dom->preserveWhiteSpace = false; - $dom->formatOutput = true; - if (@$dom->loadXML($oldxml)) { - foreach (array('str:period', 'str:flush', 'str:maxrecs', 'str:maxmegs', 'boo:embedded') as $pname) { - $ptype = substr($pname, 0, 3); - $pname = substr($pname, 4); - $pvalue = $parm2[$pname]; - if (($ns = $dom->getElementsByTagName($pname)->item(0)) != NULL) { - while (($n = $ns->firstChild)) { - $ns->removeChild($n); - } - } else { - $ns = $dom->documentElement->appendChild($dom->createElement($pname)); - } - switch ($ptype) { - case "str": - case "pop": - $ns->appendChild($dom->createTextNode($pvalue)); - break; - case "boo": - $ns->appendChild($dom->createTextNode($pvalue ? '1' : '0')); - break; - } - } - } - - return($dom->saveXML()); - } - - /** - * must fill the graphic form (using js) from xml - * - * @param string $xml - * @param string $form - * @return string - */ - public function xml2graphic($xml, $form) - { - if (false !== $sxml = simplexml_load_string($xml)) { - if ((int) ($sxml->period) < self::MINPERIOD) { - $sxml->period = self::MINPERIOD; - } elseif ((int) ($sxml->period) > self::MAXPERIOD) { - $sxml->period = self::MAXPERIOD; - } - - if ((int) ($sxml->flush) < self::MINFLUSH) { - $sxml->flush = self::MINFLUSH; - } elseif ((int) ($sxml->flush) > self::MAXFLUSH) { - $sxml->flush = self::MAXFLUSH; - } - - if ((int) ($sxml->maxrecs) < self::MINRECS) { - $sxml->maxrecs = self::MINRECS; - } elseif (self::MAXRECS != -1 && (int) ($sxml->maxrecs) > self::MAXRECS) { - $sxml->maxrecs = self::MAXRECS; - } - - if ((int) ($sxml->maxmegs) < self::MINMEGS) { - $sxml->maxmegs = self::MINMEGS; - } elseif (self::MAXMEGS != -1 && (int) ($sxml->maxmegs) > self::MAXMEGS) { - $sxml->maxmegs = self::MAXMEGS; - } - ?> - - - - - -
    -
    - -
    - - -
    -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - - Mo -
    -
    -
    - -
    - -
    -
    -
    - thumbnailExtraction; - - $connbas = $databox->get_connection(); - - $sql = 'SELECT coll_id, record_id - FROM record - WHERE jeton & ' . JETON_MAKE_SUBDEF . ' > 0 - ORDER BY record_id DESC LIMIT 0, '.$this->maxrecs; - $stmt = $connbas->prepare($sql); - $stmt->execute(); - $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - return $rs; - } - - public function processOneContent(databox $databox, $row) - { - $record_id = $row['record_id']; - $this->log(sprintf( - "Generate subdefs for : sbasid=%s / databox=%s / recordid=%s " - , $databox->get_sbas_id(), $databox->get_dbname() , $record_id) - , self::LOG_INFO - ); - - try { - $record = new record_adapter($this->dependencyContainer, $this->sbas_id, $record_id); - - $record->generate_subdefs($databox, $this->dependencyContainer); - } catch (\Exception $e) { - $this->log( - sprintf( - "Generate subdefs failed for : sbasid=%s / databox=%s / recordid=%s : %s" - , $databox->get_sbas_id(), $databox->get_dbname() , $record_id, $e->getMessage()) - , self::LOG_WARNING - ); - } - - $this->recs_to_write[] = $record->get_record_id(); - - if (count($this->recs_to_write) >= $this->record_buffer_size) { - $this->flushRecordsSbas(); - } - unset($record); - - return $this; - } - - protected function postProcessOneContent(databox $databox, $row) - { - $connbas = $databox->get_connection(); - $sql = 'UPDATE record - SET jeton=(jeton & ~' . JETON_MAKE_SUBDEF . '), moddate=NOW() - WHERE record_id=:record_id'; - - $stmt = $connbas->prepare($sql); - $stmt->execute(array(':record_id' => $row['record_id'])); - $stmt->closeCursor(); - - return $this; - } - - protected function flushRecordsSbas() - { - $sql = implode(', ', $this->recs_to_write); - - if ($sql != '') { - $this->log(sprintf( - 'setting %d record(s) to subdef meta writing' - , count($this->recs_to_write) - ), self::LOG_INFO); - - try { - $connbas = connection::getPDOConnection($this->dependencyContainer, $this->sbas_id); - $sql = 'UPDATE record - SET status=(status & ~0x03), - jeton=(jeton | ' . JETON_WRITE_META_SUBDEF . ') - WHERE record_id IN (' . $sql . ')'; - $stmt = $connbas->prepare($sql); - $stmt->execute(); - $stmt->closeCursor(); - } catch (\Exception $e) { - $this->log($e->getMessage(), self::LOG_CRITICAL); - } - } - $this->recs_to_write = array(); - - return $this; - } - - /** - * @param array $params - */ - public static function getDefaultSettings(Configuration $config, array $params = array()) - { - $period = isset($params['period']) ? $params['period'] : self::MINPERIOD; - $flush = isset($params['flush']) ? $params['flush'] : self::MINFLUSH; - $maxrecs = isset($params['maxrecs']) ? $params['maxrecs'] : self::MINRECS; - $maxmegs = isset($params['maxmegs']) ? $params['maxmegs'] : self::DEFMEGS; - - return sprintf(' - - %s - %s - %s - %s - 0 - ', - min(max($period, self::MINPERIOD), self::MAXPERIOD), - min(max($flush, self::MINFLUSH), self::MAXFLUSH), - min(max($maxrecs, self::MINRECS), self::MAXRECS), - min(max($maxmegs, self::MINMEGS), self::MAXMEGS) - ); - } -} diff --git a/lib/classes/task/period/test.php b/lib/classes/task/period/test.php deleted file mode 100644 index 16f3720c39..0000000000 --- a/lib/classes/task/period/test.php +++ /dev/null @@ -1,45 +0,0 @@ -log('test class, retrieve content'); - - return array(array('hello'), array('world')); - } - - protected function processOneContent(appbox $appbox, $row) - { - $this->log(sprintf("test class, process content : `%s`", implode(' ', $row))); - - return $this; - } - - protected function postProcessOneContent(appbox $appbox, $row) - { - $this->log(sprintf("test class, post process content, they were %s", count($row))); - - return $this; - } -} diff --git a/lib/classes/task/period/writemeta.php b/lib/classes/task/period/writemeta.php deleted file mode 100644 index eaac5e33d9..0000000000 --- a/lib/classes/task/period/writemeta.php +++ /dev/null @@ -1,360 +0,0 @@ -clear_doc = p4field::isyes($sx_task_settings->cleardoc); - parent::loadSettings($sx_task_settings); - } - - public static function getName() - { - return(_('task::writemeta:ecriture des metadatas')); - } - - public function graphic2xml($oldxml) - { - $request = http_request::getInstance(); - - $parm2 = $request->get_parms('period', 'cleardoc', 'maxrecs', 'maxmegs'); - $dom = new DOMDocument(); - $dom->preserveWhiteSpace = false; - $dom->formatOutput = true; - if ($dom->loadXML($oldxml)) { - foreach (array('str:period', 'str:maxrecs', 'str:maxmegs', 'boo:cleardoc') as $pname) { - $ptype = substr($pname, 0, 3); - $pname = substr($pname, 4); - $pvalue = $parm2[$pname]; - if (($ns = $dom->getElementsByTagName($pname)->item(0)) != NULL) { - // le champ existait dans le xml, on supprime son ancienne valeur (tout le contenu) - while (($n = $ns->firstChild)) { - $ns->removeChild($n); - } - } else { - // le champ n'existait pas dans le xml, on le cree - $ns = $dom->documentElement->appendChild($dom->createElement($pname)); - } - // on fixe sa valeur - switch ($ptype) { - case "str": - case "pop": - $ns->appendChild($dom->createTextNode($pvalue)); - break; - case "boo": - $ns->appendChild($dom->createTextNode($pvalue ? '1' : '0')); - break; - } - } - } - - return($dom->saveXML()); - } - - public function xml2graphic($xml, $form) - { - if (false !== $sxml = simplexml_load_string($xml)) { - - if ((int) ($sxml->period) < self::MINPERIOD) { - $sxml->period = self::MINPERIOD; - } elseif ((int) ($sxml->period) > self::MAXPERIOD) { - $sxml->period = self::MAXPERIOD; - } - - if ((int) ($sxml->maxrecs) < self::MINRECS) { - $sxml->maxrecs = self::MINRECS; - } elseif (self::MAXRECS != -1 && (int) ($sxml->maxrecs) > self::MAXRECS) { - $sxml->maxrecs = self::MAXRECS; - } - - if ((int) ($sxml->maxmegs) < self::MINMEGS) { - $sxml->maxmegs = self::MINMEGS; - } elseif (self::MAXMEGS != -1 && (int) ($sxml->maxmegs) > self::MAXMEGS) { - $sxml->maxmegs = self::MAXMEGS; - } - - ?> - - - - dependencyContainer['authentication']->getUser()->ACL()->get_granted_sbas(array('bas_manage')); - - ob_start(); - if (count($sbas_ids) > 0) { - ?> -
    -
    - -
    - - -
    -
    -
    -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - - Mo -
    -
    -
    - dependencyContainer['exiftool.writer']->setModule(Writer::MODULE_MWG, true); - - $connbas = $databox->get_connection(); - $subdefgroups = $databox->get_subdef_structure(); - $metasubdefs = array(); - - foreach ($subdefgroups as $type => $subdefs) { - foreach ($subdefs as $sub) { - $name = $sub->get_name(); - if ($sub->meta_writeable()) { - $metasubdefs[$name . '_' . $type] = true; - } - } - } - - $this->metasubdefs = $metasubdefs; - - $sql = 'SELECT record_id, coll_id, jeton - FROM record WHERE (jeton & ' . JETON_WRITE_META . ' > 0)'; - - $stmt = $connbas->prepare($sql); - $stmt->execute(); - $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - return $rs; - } - - protected function processOneContent(databox $databox, $row) - { - $record_id = $row['record_id']; - $jeton = $row['jeton']; - - $record = new record_adapter($this->dependencyContainer, $this->sbas_id, $record_id); - - $type = $record->get_type(); - $subdefs = $record->get_subdefs(); - - $tsub = array(); - - foreach ($subdefs as $name => $subdef) { - $write_document = (($jeton & JETON_WRITE_META_DOC) && $name == 'document'); - $write_subdef = (($jeton & JETON_WRITE_META_SUBDEF) && isset($this->metasubdefs[$name . '_' . $type])); - - if (($write_document || $write_subdef) && $subdef->is_physically_present()) { - $tsub[$name] = $subdef->get_pathfile(); - } - } - - $metadatas = new Metadata\MetadataBag(); - - if ($record->get_uuid()) { - $metadatas->add( - new Metadata\Metadata( - new Tag\XMPExif\ImageUniqueID(), - new Value\Mono($record->get_uuid()) - ) - ); - $metadatas->add( - new Metadata\Metadata( - new Tag\ExifIFD\ImageUniqueID(), - new Value\Mono($record->get_uuid()) - ) - ); - $metadatas->add( - new Metadata\Metadata( - new Tag\IPTC\UniqueDocumentID(), - new Value\Mono($record->get_uuid()) - ) - ); - } - - foreach ($record->get_caption()->get_fields() as $field) { - - $meta = $field->get_databox_field(); - /* @var $meta \databox_field */ - - $datas = $field->get_values(); - - if ($meta->is_multi()) { - $values = array(); - foreach ($datas as $data) { - $values[] = $data->getValue(); - } - - $value = new Value\Multi($values); - } else { - $data = array_pop($datas); - $value = $data->getValue(); - - $value = new Value\Mono($value); - } - - $metadatas->add( - new Metadata\Metadata($meta->get_tag(), $value) - ); - } - - $this->dependencyContainer['exiftool.writer']->reset(); - foreach ($tsub as $name => $file) { - - $this->dependencyContainer['exiftool.writer']->erase($name != 'document' || $this->clear_doc, true); - - try { - $this->dependencyContainer['exiftool.writer']->write($file, $metadatas); - - $this->log(sprintf('meta written for sbasid=%1$d - recordid=%2$d (%3$s)', $this->sbas_id, $record_id, $name), self::LOG_INFO); - } catch (\PHPExiftool\Exception\Exception $e) { - $this->log(sprintf('meta NOT written for sbasid=%1$d - recordid=%2$d (%3$s) because "%s"', $this->sbas_id, $record_id, $name, $e->getMessage()), self::LOG_ERROR); - } - } - - return $this; - } - - protected function flushRecordsSbas() - { - return $this; - } - - protected function postProcessOneContent(databox $databox, $row) - { - $connbas = $databox->get_connection(); - - $sql = 'UPDATE record SET jeton=jeton & ~' . JETON_WRITE_META . ' - WHERE record_id = :record_id'; - $stmt = $connbas->prepare($sql); - $stmt->execute(array(':record_id' => $row['record_id'])); - $stmt->closeCursor(); - - return $this; - } - - /** - * @param array $params - */ - public static function getDefaultSettings(Configuration $config, array $params = array()) - { - $period = isset($params['period']) ? $params['period'] : self::MINPERIOD; - $maxrecs = isset($params['maxrecs']) ? $params['maxrecs'] : self::MINRECS; - $maxmegs = isset($params['maxmegs']) ? $params['maxmegs'] : self::DEFMEGS; - - return sprintf(' - - %s - %s - %s - 0 - ', - min(max($period, self::MINPERIOD), self::MAXPERIOD), - min(max($maxrecs, self::MINRECS), self::MAXRECS), - min(max($maxmegs, self::MINMEGS), self::MAXMEGS) - ); - } -} diff --git a/tests/classes/task/period/task_period_archiveTest.php b/tests/classes/task/period/task_period_archiveTest.php deleted file mode 100644 index 4191220a2b..0000000000 --- a/tests/classes/task/period/task_period_archiveTest.php +++ /dev/null @@ -1,538 +0,0 @@ -pushHandler(new \Monolog\Handler\NullHandler()); - - self::$object = new archiveTester($task->getID(), $app, $logger); - } - - public static function tearDownAfterClass() - { - self::$object->delete(); - parent::tearDownAfterClass(); - } - - /** - * @covers task_period_archive::getName - * @todo Implement testGetName(). - */ - public function testGetName() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::graphic2xml - * @todo Implement testGraphic2xml(). - */ - public function testGraphic2xml() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::xml2graphic - * @todo Implement testXml2graphic(). - */ - public function testXml2graphic() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::printInterfaceJS - * @todo Implement testPrintInterfaceJS(). - */ - public function testPrintInterfaceJS() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::getInterfaceHTML - * @todo Implement testGetInterfaceHTML(). - */ - public function testGetInterfaceHTML() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::help - * @todo Implement testHelp(). - */ - public function testHelp() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::archiveHotFolder - * @todo Implement testArchiveHotFolder(). - */ - public function testArchiveHotFolder() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::isIgnoredFile - * @todo Implement testIsIgnoredFile(). - */ - public function testIsIgnoredFile() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::checkMatch - * @todo Implement testCheckMatch(). - */ - public function testCheckMatch() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::listFilesPhase1 - * @todo Implement testListFilesPhase1(). - */ - public function testListFilesPhase1() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::listFilesPhase2 - * @todo Implement testListFilesPhase2(). - */ - public function testListFilesPhase2() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::makePairs - * @todo Implement testMakePairs(). - */ - public function testMakePairs() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::removeBadGroups - * @todo Implement testRemoveBadGroups(). - */ - public function testRemoveBadGroups() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::archive - * @todo Implement testArchive(). - */ - public function testArchive() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::bubbleResults - * @todo Implement testBubbleResults(). - */ - public function testBubbleResults() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::moveFiles - * @todo Implement testMoveFiles(). - */ - public function testMoveFiles() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::setBranchHot - * @todo Implement testSetBranchHot(). - */ - public function testSetBranchHot() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::archiveGrp - * @todo Implement testArchiveGrp(). - */ - public function testArchiveGrp() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - public function getXml() - { - $meta_struct = self::$DI['collection']->get_databox()->get_meta_structure(); - - $xml = ' - - ' . "\n"; - - $tofetch = array(); - - foreach ($meta_struct as $databox_field) { - if ($databox_field->is_multi()) { - - $tofetch[$databox_field->get_name()] = array(); - - $values = array('a-value-' . $databox_field->get_id(), 'b-value-' . $databox_field->get_id()); - - $tofetch[$databox_field->get_name()] = array_merge($tofetch[$databox_field->get_name()], $values); - - $xml .= '<' . $databox_field->get_name() . '>'; - $xml .= implode(' ; ', $values); - $xml .= 'get_name() . '>' . "\n"; - - $values = array('c-value-' . $databox_field->get_id(), 'd-value-' . $databox_field->get_id()); - - $tofetch[$databox_field->get_name()] = array_merge($tofetch[$databox_field->get_name()], $values); - - foreach ($values as $value) { - $xml .= '<' . $databox_field->get_name() . '>'; - $xml .= $value; - $xml .= 'get_name() . '>' . "\n"; - } - } else { - - $value = 'c-value-' . $databox_field->get_id(); - - $xml .= '<' . $databox_field->get_name() . '>'; - $xml .= $value; - $xml .= 'get_name() . '>' . "\n"; - - $tofetch[$databox_field->get_name()] = array($value); - } - } - - $xml .= ' - - '; - - return array($xml, $tofetch, $meta_struct); - } - - /** - * @covers task_period_archive::createStory - * @todo Implement testCreateStory(). - */ - public function testCreateStory() - { - list($xml, $tofetch, $meta_struct) = $this->getXml(); - - $tmp = sys_get_temp_dir() . '/tmp' . time() . mt_rand(1000, 9999) . '.xml'; - $tmpFile = sys_get_temp_dir() . '/tmp' . time() . mt_rand(1000, 9999) . '.jpg'; - copy(__DIR__ . '/../../../files/cestlafete.jpg', $tmpFile); - - file_put_contents($tmp, $xml); - - $story = self::$object->createStory(self::$DI['collection'], $tmpFile, $tmp); - - unlink($tmpFile); - - $this->assertTrue($story->is_grouping()); - } - - /** - * @covers task_period_archive::createRecord - * @todo Implement testCreateRecord(). - */ - public function testCreateRecord() - { - list($xml, $tofetch, $meta_struct) = $this->getXml(); - - $tmp = sys_get_temp_dir() . '/tmp' . time() . mt_rand(1000, 9999) . '.xml'; - $tmpFile = sys_get_temp_dir() . '/tmp' . time() . mt_rand(1000, 9999) . '.jpg'; - copy(__DIR__ . '/../../../files/cestlafete.jpg', $tmpFile); - - file_put_contents($tmp, $xml); - - $story = self::$object->createRecord(self::$DI['collection'], $tmpFile, $tmp, null, Manager::FORCE_RECORD); - - unlink($tmpFile); - - $this->assertFalse($story->is_grouping()); - } - - /** - * @covers task_period_archive::archiveFilesToGrp - * @todo Implement testArchiveFilesToGrp(). - */ - public function testArchiveFilesToGrp() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::archiveFile - * @todo Implement testArchiveFile(). - */ - public function testArchiveFile() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::archiveFileAndCaption - * @todo Implement testArchiveFileAndCaption(). - */ - public function testArchiveFileAndCaption() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::setAllChildren - * @todo Implement testSetAllChildren(). - */ - public function testSetAllChildren() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::getGrpSettings - * @todo Implement testGetGrpSettings(). - */ - public function testGetGrpSettings() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers task_period_archive::getLazaretSession - */ - public function testGetLazaretSession() - { - $session = self::$object->getLazaretSessionTester(); - $this->assertInstanceOf('\\Alchemy\Phrasea\Model\Entities\\LazaretSession', $session); - - $session_id = self::$object->getLazaretSessionTester()->getId(); - - $session = self::$object->getLazaretSessionTester(); - - $this->assertEquals($session_id, $session->getId()); - } - - /** - * @covers task_period_archive::getIndexByFieldName - */ - public function testGetIndexByFieldName() - { - $meta_struct = self::$DI['collection']->get_databox()->get_meta_structure(); - $media = self::$DI['app']['mediavorus']->guess(__DIR__ . '/../../../files/test001.jpg'); - - $bagByName = self::$object->getIndexByFieldNameTester($meta_struct, $media->getMetadatas()); - - $this->assertInstanceOf('\\Alchemy\\Phrasea\\Border\\MetadataBag', $bagByName); - - if (count($bagByName) == 0) { - $this->markTestSkipped('No enough data to tests'); - } - - foreach ($bagByName as $fieldname => $value) { - $this->assertNotNull($meta_struct->get_element_by_name($fieldname)); - $this->assertInstanceOf('\\databox_field', $meta_struct->get_element_by_name($fieldname)); - $this->assertInstanceof('\\PHPExiftool\\Driver\\Metadata\\Metadata', $value); - } - } - - /** - * @covers task_period_archive::readXMLForDatabox - * @expectedException \InvalidArgumentException - */ - public function testReadXMLForDataboxFail() - { - $meta_struct = self::$DI['collection']->get_databox()->get_meta_structure(); - self::$object->readXMLForDataboxTester($meta_struct, 'non existant file'); - } - - /** - * @covers task_period_archive::readXMLForDatabox - * @expectedException \InvalidArgumentException - */ - public function testReadXMLForDataboxWrongXML() - { - $meta_struct = self::$DI['collection']->get_databox()->get_meta_structure(); - self::$object->readXMLForDataboxTester($meta_struct, __FILE__); - } - - /** - * @covers task_period_archive::readXMLForDatabox - */ - public function testReadXMLForDatabox() - { - list($xml, $tofetch, $meta_struct) = $this->getXml(); - - $tmp = sys_get_temp_dir() . '/tmp' . time() . mt_rand(1000, 9999) . '.xml'; - file_put_contents($tmp, $xml); - - $bag = self::$object->readXMLForDataboxTester($meta_struct, $tmp); - - unlink($tmp); - - $found = array(); - - foreach ($bag as $fieldname => $metadata) { - $found[$fieldname] = $metadata->getValue(); - } - - foreach ($tofetch as $fieldname => $values) { - $this->assertEquals($values, $found[$fieldname]); - } - } - - /** - * @covers task_period_archive::parseStatusBit - */ - public function testParseStatusBit() - { - $xml = ' - - 10000 - - - '; - $sxcaption = simplexml_load_string($xml); - $this->assertEquals('10000', self::$object->parseStatusBitTester($sxcaption)); - - $xml = ' - - - - - '; - $sxcaption = simplexml_load_string($xml); - - $this->assertNull(self::$object->parseStatusBitTester($sxcaption)); - $xml = ' - - '; - $sxcaption = simplexml_load_string($xml); - $this->assertNull(self::$object->parseStatusBitTester($sxcaption)); - } -} - -class archiveTester extends task_period_archive -{ - - public function getLazaretSessionTester() - { - return parent::getLazaretSession(); - } - - public function getIndexByFieldNameTester($meta_struct, $bag) - { - return parent::getIndexByFieldName($meta_struct, $bag); - } - - public function readXMLForDataboxTester($meta_struct, $pathfile) - { - return parent::readXMLForDatabox($meta_struct, $pathfile); - } - - public function parseStatusBitTester($sxcaption) - { - return parent::parseStatusBit($sxcaption); - } -} diff --git a/tests/classes/task/task_abstractTest.php b/tests/classes/task/task_abstractTest.php deleted file mode 100644 index 937d31fca4..0000000000 --- a/tests/classes/task/task_abstractTest.php +++ /dev/null @@ -1,173 +0,0 @@ -getID(); - } - - public static function tearDownAfterClass() - { - self::$task->delete(); - parent::tearDownAfterClass(); - } - - /** - * @covers \task_abstract::setActive - * @covers \task_abstract::isActive - */ - public function testActive() - { - self::$task->setActive(true); - $this->assertTrue(self::$task->isActive()); - - self::$task->setActive(false); - $this->assertFalse(self::$task->isActive()); - } - - /** - * @covers \task_abstract::setState - * @covers \task_abstract::getState - */ - public function testState() - { - self::$task->setState(\task_abstract::STATE_STOPPED); - $this->assertEquals(\task_abstract::STATE_STOPPED, self::$task->getState()); - - self::$task->setState(\task_abstract::STATE_TOSTOP); - $this->assertEquals(\task_abstract::STATE_TOSTOP, self::$task->getState()); - } - - /** - * @covers \task_abstract::setTitle - * @covers \task_abstract::getTitle - */ - public function testTitle() - { - self::$task->setTitle('a_test_title'); - $this->assertEquals('a_test_title', self::$task->getTitle()); - } - - /** - * @covers \task_abstract::resetCrashCounter - * @covers \task_abstract::incrementCrashCounter - * @covers \task_abstract::getCrashCounter - */ - public function testCrashCounter() - { - self::$task->resetCrashCounter(); - self::$task->incrementCrashCounter(); - $this->assertEquals(1, self::$task->getCrashCounter()); - - self::$task->incrementCrashCounter(); - $this->assertEquals(2, self::$task->getCrashCounter()); - - self::$task->resetCrashCounter(); - $this->assertEquals(0, self::$task->getCrashCounter()); - } - - /** - * @covers \task_abstract::setSettings - * @covers \task_abstract::getSettings - */ - public function testSettings() - { - $goodSettings = ""; - $sxGoodSettings = simplexml_load_string($goodSettings); - - self::$task->setSettings($goodSettings); - $settings = self::$task->getSettings(); - $sxSettings = @simplexml_load_string($settings); - - $this->assertTrue($sxSettings !== FALSE); - $this->assertEquals($sxGoodSettings->saveXML(), $sxSettings->saveXML()); - } - - /** - * @covers \task_abstract::setSettings - * @expectedException Exception_InvalidArgument - */ - public function testSettingsException() - { - self::$task->setSettings('this_is_bad_xml'); - } - - /** - * @covers \task_abstract::setRunner - * @covers \task_abstract::getRunner - */ - public function testRunner() - { - self::$task->setRunner(\task_abstract::RUNNER_MANUAL); - $this->assertTrue(\task_abstract::RUNNER_MANUAL === self::$task->getRunner()); - - self::$task->setRunner(\task_abstract::RUNNER_SCHEDULER); - $this->assertTrue(\task_abstract::RUNNER_SCHEDULER === self::$task->getRunner()); - } - - /** - * @covers \task_abstract::setRunner - * @expectedException Exception_InvalidArgument - */ - public function testRunnerException() - { - self::$task->setRunner('this_is_bad_runner'); - } - - /** - * @covers \task_abstract::lockTask - * @covers \task_abstract::unlockTask - */ - public function testLockTask() - { - $methodL = new ReflectionMethod(self::$task, 'lockTask'); - $methodL->setAccessible(TRUE); - - $methodU = new ReflectionMethod(self::$task, 'unlockTask'); - $methodU->setAccessible(TRUE); - - // test that task should not be locked - try { - $fd = $methodL->invoke(self::$task); - } catch (Exception $e) { - $this->fail('file should not be locked'); - } - $this->assertInternalType('resource', $fd); - - // now task should be locked - try { - $fd = $methodL->invoke(self::$task); - $this->fail('file should be locked'); - } catch (Exception $e) { - - } - - // so we can unlock - $methodU->invokeArgs(self::$task, array($fd)); - - // task should not be locked - try { - $fd = $methodL->invoke(self::$task); - } catch (Exception $e) { - $this->fail('file should not be locked'); - } - $this->assertInternalType('resource', $fd); - - // leave the file unlocked - $methodU->invokeArgs(self::$task, array($fd)); - - } -}