Skip to content

Commit

Permalink
Implementing issue #10: the export engine
Browse files Browse the repository at this point in the history
  • Loading branch information
zyxist committed Feb 1, 2016
1 parent 1440eaf commit c8d35da
Show file tree
Hide file tree
Showing 8 changed files with 379 additions and 2 deletions.
1 change: 1 addition & 0 deletions db/schema/7.sql
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ CREATE TABLE IF NOT EXISTS `cantiga_data_export` (
`encryptionKey` VARCHAR(128) NOT NULL,
`active` tinyint(1) NOT NULL,
`notes` TEXT NULL,
`lastExportedAt` INT(11) NULL,
PRIMARY KEY (`id`),
KEY `projectId` (`projectId`),
KEY `areaStatusId` (`areaStatusId`)
Expand Down
33 changes: 31 additions & 2 deletions src/Cantiga/CoreBundle/Entity/Area.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class Area implements IdentifiableInterface, InsertableEntityInterface, Editable
private $reporter;
private $memberNum;
private $customData;
private $createdAt;
private $lastUpdatedAt;

private $oldGroup;
private $oldStatus;
Expand Down Expand Up @@ -314,6 +316,30 @@ public function setReporter($reporter)
$this->reporter = $reporter;
return $this;
}

public function getCreatedAt()
{
return $this->createdAt;
}

public function getLastUpdatedAt()
{
return $this->lastUpdatedAt;
}

public function setCreatedAt($createdAt)
{
DataMappers::noOverwritingField($this->createdAt);
$this->createdAt = $createdAt;
return $this;
}

public function setLastUpdatedAt($lastUpdatedAt)
{
DataMappers::noOverwritingField($this->lastUpdatedAt);
$this->lastUpdatedAt = $lastUpdatedAt;
return $this;
}

/**
* Fetches a value of a custom property. Null value is returned,
Expand Down Expand Up @@ -349,10 +375,12 @@ public function insert(Connection $conn)
$this->entity->setName($this->name);
$this->entity->insert($conn);

$this->createdAt = $this->lastUpdatedAt = time();

$this->slug = DataMappers::generateSlug($conn, CoreTables::GROUP_TBL);
$conn->insert(
CoreTables::AREA_TBL,
DataMappers::pick($this, ['name', 'slug', 'project', 'group', 'territory', 'status', 'reporter', 'entity'], ['customData' => json_encode($this->customData), 'groupName' => $groupName])
DataMappers::pick($this, ['name', 'slug', 'project', 'group', 'territory', 'status', 'reporter', 'entity', 'createdAt', 'lastUpdatedAt'], ['customData' => json_encode($this->customData), 'groupName' => $groupName])
);
return $this->id = $conn->lastInsertId();
}
Expand All @@ -376,10 +404,11 @@ public function update(Connection $conn)

$this->entity->setName($this->name);
$this->entity->update($conn);
$this->lastUpdatedAt = time();

return $conn->update(
CoreTables::AREA_TBL,
DataMappers::pick($this, ['name', 'group', 'territory', 'status'], ['customData' => json_encode($this->customData), 'groupName' => $groupName]),
DataMappers::pick($this, ['name', 'group', 'territory', 'status', 'lastUpdatedAt'], ['customData' => json_encode($this->customData), 'groupName' => $groupName]),
DataMappers::pick($this, ['id'])
);
}
Expand Down
90 changes: 90 additions & 0 deletions src/Cantiga/ExportBundle/Command/ExportCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php
/*
* This file is part of Cantiga Project. Copyright 2015 Tomasz Jedrzejewski.
*
* Cantiga Project is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Cantiga Project is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Foobar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
namespace Cantiga\ExportBundle\Command;

use Exception;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
* @author Tomasz Jędrzejewski
*/
class ExportCommand extends ContainerAwareCommand
{
protected function configure()
{
$this
->setName('cantiga:export-data')
->setDescription('Exports the data to the external services via REST.')
;
}

protected function execute(InputInterface $input, OutputInterface $output)
{
$exportEngine = $this->getContainer()->get('cantiga.export.repo.engine');
foreach ($exportEngine->findActiveExports() as $export) {
$output->writeln('<info>Exporting data to \''.$export['name'].'\' endpoint.</info>');
try {
$result = $exportEngine->exportData($export, function($text) use($output) {
$output->writeln($text, OutputInterface::VERBOSITY_NORMAL);
});
if ($this->send($export, $this->encrypt($export, $result), $output)) {
$output->writeln('<info>Export completed</info>');
} else {
$output->writeln('<info>Export failed</info>');
}
} catch(Exception $exception) {
$output->writeln('<error>Export failed: '.$exception->getMessage().'</error>');
}
}
}

private function encrypt($export, $output)
{
$key = base64_decode($export['encryptionKey']);

if (strlen($key) != 32) {
throw new \RuntimeException('The key must have the length of 32 bytes!');
}

$ivSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($ivSize, MCRYPT_RAND);
return base64_encode($iv.mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, json_encode($output), MCRYPT_MODE_CBC, $iv));
}

private function send($export, $encrypted, OutputInterface $output)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $export['url']);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $encrypted);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/plain'));

$result = curl_exec($ch);
$errno = curl_errno($ch);
if ($errno !== 0) {
$output->writeln('<error>The server responded with error: '.$errno.' ('.curl_error($ch).')</error>');
curl_close($ch);
return false;
}
curl_close($ch);
return true;
}
}
65 changes: 65 additions & 0 deletions src/Cantiga/ExportBundle/Entity/ExportBlock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php
/*
* This file is part of Cantiga Project. Copyright 2015 Tomasz Jedrzejewski.
*
* Cantiga Project is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Cantiga Project is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Foobar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
namespace Cantiga\ExportBundle\Entity;

/**
* Represents a single pack of data that shall be exported. It consists of the
* total list of all ID-s that shall be present in the external system, and the
* full records of those entities that need to be updated.
*
* @author Tomasz Jędrzejewski
*/
class ExportBlock
{
private $ids = [];
private $update = [];

public function addId($id)
{
$this->ids[] = $id;
}

public function addUpdate(array $update)
{
$this->update[] = $update;
}

public function countIds()
{
return sizeof($this->ids);
}

public function countUpdates()
{
return sizeof($this->update);
}

public function getIds()
{
return $this->ids;
}

public function output()
{
return [
'ids' => $this->ids,
'update' => $this->update
];
}
}
66 changes: 66 additions & 0 deletions src/Cantiga/ExportBundle/Event/ExportEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php
/*
* This file is part of Cantiga Project. Copyright 2015 Tomasz Jedrzejewski.
*
* Cantiga Project is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Cantiga Project is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Foobar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
namespace Cantiga\ExportBundle\Event;

use Cantiga\ExportBundle\Entity\ExportBlock;
use InvalidArgumentException;
use Symfony\Component\EventDispatcher\Event;

/**
* Description of ExportEvent
*
* @author Tomasz Jędrzejewski
*/
class ExportEvent extends Event
{
private $blocks = array();
private $reporter = null;

public function __construct($reporterCallback)
{
$this->reporter = $reporterCallback;
}

public function addBlock($name, ExportBlock $block)
{
if (isset($this->blocks[$name])) {
throw new InvalidArgumentException('Cannot overwrite export block: '.$name);
}
$this->blocks[$name] = $block;
$callback = $this->reporter;
$callback('Exporting block '.$name.': IDs '.$block->countIds().'; Updates '.$block->countUpdates());
}

public function getBlock($name)
{
if (!isset($this->blocks[$name])) {
throw new InvalidArgumentException('No such export block: '.$name);
}
return $this->blocks[$name];
}

public function output()
{
$output = [];
foreach ($this->blocks as $name => $block) {
$output[$name] = $block->output();
}
return $output;
}
}
30 changes: 30 additions & 0 deletions src/Cantiga/ExportBundle/ExportEvents.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php
/*
* This file is part of Cantiga Project. Copyright 2015 Tomasz Jedrzejewski.
*
* Cantiga Project is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Cantiga Project is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Foobar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
namespace Cantiga\ExportBundle;

/**
* @author Tomasz Jędrzejewski
*/
class ExportEvents
{
/**
* Call for adding the blocks to export to the external system.
*/
const EXPORT_ONGOING = 'export.ongoing';
}
Loading

0 comments on commit c8d35da

Please sign in to comment.