Add FtpPull job

This commit is contained in:
Romain Neutron
2013-09-05 17:13:20 +02:00
parent 5a3e444000
commit 14b3a39ca2
5 changed files with 375 additions and 0 deletions

View File

@@ -0,0 +1,74 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2013 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\TaskManager\Editor;
use Alchemy\Phrasea\Core\Configuration\ConfigurationInterface;
class FtpPullEditor extends AbstractEditor
{
/**
* {@inheritdoc}
*/
public function getTemplatePath()
{
return 'admin/task-manager/task-editor/ftp-pull.html.twig';
}
/**
* {@inheritdoc}
*/
public function getDefaultPeriod()
{
return 900;
}
/**
* {@inheritdoc}
*/
public function getDefaultSettings(ConfigurationInterface $config = null)
{
return <<<EOF
<?xml version="1.0" encoding="UTF-8"?>
<tasksettings>
<proxy></proxy>
<proxyport></proxyport>
<passive>0</passive>
<ssl>0</ssl>
<password></password>
<user></user>
<ftppath></ftppath>
<localpath></localpath>
<port>21</port>
<host></host>
</tasksettings>
EOF;
}
/**
* {@inheritdoc}
*/
protected function getFormProperties()
{
return array(
'proxy' => static::FORM_TYPE_STRING,
'proxyport' => static::FORM_TYPE_STRING,
'passive' => static::FORM_TYPE_BOOLEAN,
'ssl' => static::FORM_TYPE_BOOLEAN,
'password' => static::FORM_TYPE_STRING,
'user' => static::FORM_TYPE_STRING,
'ftppath' => static::FORM_TYPE_STRING,
'localpath' => static::FORM_TYPE_STRING,
'port' => static::FORM_TYPE_INTEGER,
'host' => static::FORM_TYPE_STRING,
);
}
}

View File

@@ -0,0 +1,135 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2013 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\TaskManager\Job;
use Alchemy\Phrasea\TaskManager\Editor\FtpPullEditor;
use Alchemy\Phrasea\Exception\RuntimeException;
class FtpPullJob extends AbstractJob
{
/**
* {@inheritdoc}
*/
public function getName()
{
return _("task::ftp:FTP Pull");
}
/**
* {@inheritdoc}
*/
public function getDescription()
{
return _('Periodically fetches an FTP repository content locally');
}
/**
* {@inheritdoc}
*/
public function getEditor()
{
return new FtpPullEditor();
}
/**
* {@inheritdoc}
*/
protected function doJob(JobData $data)
{
$app = $data->getApplication();
$settings = simplexml_load_string($data->getTask()->getSettings());
$proxy = (string) $settings->proxy;
$proxyport = (string) $settings->proxyport;
$localPath = (string) $settings->localpath;
$ftpPath = (string) $settings->ftppath;
$host = (string) $settings->host;
$port = (string) $settings->port;
$user = (string) $settings->user;
$password = (string) $settings->password;
$ssl = (Boolean) (string) $settings->ssl;
$passive = (Boolean) (string) $settings->passive;
foreach (array(
'localpath' => $localPath,
'host' => $host,
'port' => $host,
'user' => $user,
'password' => $password,
'ftppath' => $ftpPath,
) as $name => $value) {
if (trim($value) === '') {
// maybe throw an exception to consider the job as failing ?
$this->log('error', sprintf('setting `%s` must be set', $name));
throw new RuntimeException(sprintf('`%s` setting is empty', $name));
}
}
$app['filesystem']->mkdir($localPath, 0750);
if (!is_dir($localPath)) {
$this->log('error', sprintf('`%s` does not exists', $localPath));
throw new RuntimeException(sprintf('`%s` does not exists', $localPath));
}
if (!is_writeable($localPath)) {
$this->log('error', sprintf('`%s` is not writeable', $localPath));
throw new RuntimeException(sprintf('`%s` is not writeable', $localPath));
}
$ftp = $app['phraseanet.ftp.client']($host, $port, 90, $ssl, $proxy, $proxyport);
$ftp->passive($passive);
$ftp->login($user, $password);
$ftp->chdir($ftpPath);
$list_1 = $ftp->list_directory(true);
$done = 0;
$this->log('debug', "attente de 25sec pour avoir les fichiers froids...");
$this->pause(25);
if (!$this->isStarted()) {
$ftp->close();
$this->log('debug', "Stopping");
return;
}
$list_2 = $ftp->list_directory(true);
foreach ($list_1 as $filepath => $timestamp) {
$done++;
if (!isset($list_2[$filepath])) {
$this->log('debug', "le fichier $filepath a disparu...\n");
continue;
}
if ($list_2[$filepath] !== $timestamp) {
$this->log('debug', "le fichier $filepath a ete modifie depuis le dernier passage...");
continue;
}
$finalpath = \p4string::addEndSlash($localPath) . ($filepath[0] == '/' ? mb_substr($filepath, 1) : $filepath);
$this->log('debug', "Rappatriement de $filepath vers $finalpath\n");
if (file_exists($finalpath)) {
$this->log('debug', "Un fichier du meme nom ($finalpath) existe deja, skipping");
continue;
}
$this->log('debug', "Create ".dirname($finalpath)."");
$app['filesystem']->mkdir(dirname($finalpath), 0750);
$this->log('debug', "Get $filepath to $finalpath");
$ftp->get($finalpath, $filepath);
$this->log('debug', "Remove $filepath");
$ftp->delete($filepath);
}
$ftp->close();
}
}

View File

@@ -0,0 +1,91 @@
{% extends 'admin/task-manager/task-editor/task.html.twig' %}
{% block form %}
<div class="control-group">
<label class="control-label">{% trans 'task::ftp:proxy' %}</label>
<div class="controls">
<input class="formElem" type="text" name="proxy" />
</div>
</div>
<div class="control-group">
<label class="control-label">{% trans 'task::ftp:proxy port' %}</label>
<div class="controls">
<input class="formElem" type="text" name="proxyport" />
</div>
</div>
<div class="control-group">
<label class="control-label">{% trans 'task::ftp:host' %}</label>
<div class="controls">
<input class="formElem" type="text" name="host" />
</div>
</div>
<div class="control-group">
<label class="control-label">{% trans 'task::ftp:port' %}</label>
<div class="controls">
<input class="formElem" type="text" name="port" />
</div>
</div>
<div class="control-group">
<label class="control-label">{% trans 'task::ftp:user' %}</label>
<div class="controls">
<input class="formElem" type="text" name="user" />
</div>
</div>
<div class="control-group">
<label class="control-label">{% trans 'task::ftp:password' %}</label>
<div class="controls">
<input class="formElem" type="password" name="password" />
</div>
</div>
<div class="control-group">
<label class="control-label">{% trans 'task::ftp:chemin distant' %}</label>
<div class="controls">
<input class="formElem" type="text" name="ftppath" />
</div>
</div>
<div class="control-group">
<label class="control-label">{% trans 'task::ftp:localpath' %}</label>
<div class="controls">
<input class="formElem" type="text" name="localpath" />
</div>
</div>
<div class="control-group">
<label class="control-label">{% trans 'task::ftp:mode passif' %}</label>
<div class="controls">
<input class="formElem" type="checkbox" name="passive" />
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input class="formElem" type="checkbox" name="ssl" />
{% trans 'task::ftp:utiliser SSL' %}
</label>
</div>
</div>
{% endblock %}
{% block javascript %}
function taskFillGraphic(xml)
{
if (xml) {
xml = $.parseXML(xml);
xml = $(xml);
with(document.forms['graphicForm'])
{
proxy.value = xml.find("proxy").text();
proxyport.value = xml.find("proxyport").text();
localpath.value = xml.find("localpath").text();
ftppath.value = xml.find("ftppath").text();
host.value = xml.find("host").text();
port.value = xml.find("port").text();
user.value = xml.find("user").text();
password.value = xml.find("password").text();
ssl.checked = Number(xml.find("ssl").text()) > 0;
passive.checked = Number(xml.find("passive").text()) > 0;
}
}
}
{% endblock %}

View File

@@ -0,0 +1,62 @@
<?php
namespace Alchemy\Tests\Phrasea\TaskManager\Editor;
use Alchemy\Phrasea\TaskManager\Editor\FtpPullEditor;
class FtpPullEditorTest extends EditorTestCase
{
public function provideDataForXMLUpdatesFromForm()
{
return array(
array('<?xml version="1.0" encoding="UTF-8"?>
<tasksettings>
<proxy></proxy><proxyport></proxyport><passive>0</passive><ssl>0</ssl><password></password><user></user><ftppath></ftppath><localpath></localpath><port></port><host></host></tasksettings>
', '<?xml version="1.0" encoding="UTF-8"?>
<tasksettings>
</tasksettings>', array()
),
array('<?xml version="1.0" encoding="UTF-8"?>
<tasksettings>
<proxy>1234</proxy>
<proxyport>5678</proxyport>
<passive>1</passive>
<ssl>1</ssl>
<password>a password</password>
<user>username</user>
<ftppath>nice path</ftppath>
<localpath>path to the future</localpath>
<port>22</port>
<host>example.com</host>
</tasksettings>
', '<?xml version="1.0" encoding="UTF-8"?>
<tasksettings><proxy>12</proxy><proxyport>8</proxyport><passive>0</passive><ssl>0</ssl><password></password><user></user><ftppath></ftppath><localpath></localpath><port>21</port><host></host>
</tasksettings>', array('proxy' => 1234, 'proxyport' => 5678, 'passive' => 1, 'ssl' => 1, 'password' => 'a password', 'user' => 'username', 'ftppath' => 'nice path', 'localpath' => 'path to the future', 'port' => 22, 'host' => 'example.com')
),
array('<?xml version="1.0" encoding="UTF-8"?>
<tasksettings>
<customtag>value</customtag>
<proxy></proxy>
<proxyport></proxyport>
<passive>0</passive>
<ssl>0</ssl>
<password></password>
<user></user>
<ftppath></ftppath>
<localpath></localpath>
<port></port>
<host></host>
</tasksettings>
', '<?xml version="1.0" encoding="UTF-8"?>
<tasksettings>
<customtag>value</customtag>
</tasksettings>', array()
),
);
}
protected function getEditor()
{
return new FtpPullEditor();
}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace Alchemy\Tests\Phrasea\TaskManager\Job;
use Alchemy\Phrasea\TaskManager\Job\FtpPullJob;
class FtpPullJobTest extends JobTestCase
{
protected function getJob()
{
return new FtpPullJob();
}
}