Merge branch 'pu/2013.10-groupimport'
[tine20] / tine20 / Tinebase / Controller / ScheduledImport.php
1 <?php
2 /**
3  * Tine 2.0
4  * 
5  * @package     Tinebase
6  * @subpackage  Controller
7  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
8  * @author      Michael Spahn <m.spahn@metaways.de>
9  * @copyright   Copyright (c) 2014 Metaways Infosystems GmbH (http://www.metaways.de)
10  */
11
12 /**
13  * Tinebase Import Controller
14  * 
15  * @package Tinebase
16  * @subpackage  Controller
17  */
18 class Tinebase_Controller_ScheduledImport extends Tinebase_Controller_Record_Abstract
19 {
20     /**
21      * holds the instance of the singleton
22      *
23      * @var Tinebase_Controller_ScheduledImport
24      */
25     private static $instance = null;
26     
27     /**
28      * the constructor
29      *
30      * don't use the constructor. use the singleton 
31      */
32     private function __construct()
33     {
34         $this->_applicationName = 'Tinebase';
35         $this->_modelName = 'Tinebase_Model_Import';
36         $this->_backend = new Tinebase_Backend_Sql(array(
37             'modelName' => $this->_modelName, 
38             'tableName' => 'import',
39         ));
40         $this->_purgeRecords = false;
41         // activate this if you want to use containers
42         $this->_doContainerACLChecks = false;
43         $this->_resolveCustomFields = false;
44     }
45     
46     /**
47      * the singleton pattern
48      *
49      * @return Tinebase_Controller_ScheduledImport
50      */
51     public static function getInstance() 
52     {
53         if (self::$instance === null) {
54             self::$instance = new self();
55         }
56         return self::$instance;
57     }
58     
59     /**
60      * Search and executed the next scheduled import
61      */
62     public function runNextScheduledImport()
63     {
64         if ($record = $this->_getNextScheduledImport()) {
65             return $this->_doScheduledImport($record);
66         }
67         
68         return NULL;
69     }
70     
71     /**
72      * Get the next scheduled import
73      * 
74      * @param interval
75      * @param recursive
76      * @return Object
77      */
78     protected function _getNextScheduledImport()
79     {
80         $timestampBefore = null;
81         
82         $now = new Tinebase_DateTime();
83         
84         $anHourAgo = clone $now;
85         $anHourAgo->subHour(1);
86         
87         $aDayAgo = clone $now;
88         $aDayAgo->subDay(1);
89         
90         $aWeekAgo = clone $now;
91         $aWeekAgo->subWeek(1);
92         
93         $filter = new Tinebase_Model_ImportFilter(array(), 'OR');
94         
95         $filter0 = new Tinebase_Model_ImportFilter(array(
96                 array('field' => 'interval', 'operator' => 'equals', 'value' => Tinebase_Model_Import::INTERVAL_ONCE),
97                 array('field' => 'timestamp', 'operator' => 'before', 'value' => $now),
98         ), 'AND');
99         
100         $filter1 = new Tinebase_Model_ImportFilter(array(
101             array('field' => 'interval', 'operator' => 'equals', 'value' => Tinebase_Model_Import::INTERVAL_HOURLY),
102             array('field' => 'timestamp', 'operator' => 'before', 'value' => $anHourAgo),
103         ), 'AND');
104         
105         $filter2 = new Tinebase_Model_ImportFilter(array(
106                 array('field' => 'interval', 'operator' => 'equals', 'value' => Tinebase_Model_Import::INTERVAL_DAILY),
107                 array('field' => 'timestamp', 'operator' => 'before', 'value' => $aDayAgo),
108         ), 'AND');
109         
110         $filter3 = new Tinebase_Model_ImportFilter(array(
111                 array('field' => 'interval', 'operator' => 'equals', 'value' => Tinebase_Model_Import::INTERVAL_WEEKLY),
112                 array('field' => 'timestamp', 'operator' => 'before', 'value' => $aWeekAgo),
113         ), 'AND');
114         
115         $filter->addFilterGroup($filter0);
116         $filter->addFilterGroup($filter1);
117         $filter->addFilterGroup($filter2);
118         $filter->addFilterGroup($filter3);
119         
120         // Always sort by creation timestamp to ensure first in first out
121         $pagination = new Tinebase_Model_Pagination(array(
122             'limit'     => 1,
123             'sort'      => 'timestamp',
124             'dir'       => 'DESC'
125         ));
126         
127         $record = $this->search($filter, $pagination)->getFirstRecord();
128         
129         if (! $record) {
130             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
131                 Tinebase_Core::getLogger()->debug(__METHOD__ . ' ' . __LINE__ . ' No ScheduledImport could be found.');
132             }
133             
134             return NULL;
135         }
136         return $record;
137     }
138     
139     /**
140      * Execute scheduled import
141      * @param Tinebase_Model_Import $record
142      * @return Tinebase_Model_Import
143      */
144     protected function _doScheduledImport(Tinebase_Model_Import $record = NULL)
145     {
146         $importer = $record->getOption('plugin');
147         
148         $options = array(
149             'container_id' => $record->container_id,
150             // legacy
151             'importContainerId' => $record->container_id,
152         );
153         
154         if (strpos($record->source, 'http') === 0) {
155             $client = new Zend_Http_Client($record->source);
156             $toImport = $client->request()->getBody();
157         } else {
158             $toImport = file_get_contents($record->source);
159         }
160
161         
162         $importer = new $importer($options);
163         
164         if ($toImport) {
165             // do import
166             $importer->import($toImport);
167             
168             if ($record->interval === Tinebase_Model_Import::INTERVAL_ONCE || ! $record->timestamp instanceof Tinebase_DateTime) {
169                 $record->timestamp = Tinebase_DateTime::now();
170             }
171             
172             switch ($record->interval) {
173                 case Tinebase_Model_Import::INTERVAL_DAILY:
174                     $record->timestamp->addDay(1);
175                     break;
176                 case Tinebase_Model_Import::INTERVAL_WEEKLY:
177                     $record->timestamp->addWeek(1);
178                     break;
179                 case Tinebase_Model_Import::INTERVAL_HOURLY:
180                     $record->timestamp->addHour(1);
181                     break;
182             }
183             
184             // update record
185             $record = $this->update($record);
186             
187         } else {
188             if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
189                 Tinebase_Core::getLogger()->info(__METHOD__ . ' ' . __LINE__ . ' The source could not be loaded: "' . $record->source . '"');
190             }
191         }
192         
193         return $record;
194     }
195     
196     /**
197      * Creates a remote import for events
198      * 
199      * @param string $remoteUrl
200      * @param string $interval
201      * @param array $importOptions
202      * @throws Calendar_Exception_InvalidUrl
203      * @return Tinebase_Record_Interface
204      */
205     public function createRemoteImportEvent($data)
206     {
207         $possibleIntervals = array(
208             Tinebase_Model_Import::INTERVAL_DAILY,
209             Tinebase_Model_Import::INTERVAL_HOURLY,
210             Tinebase_Model_Import::INTERVAL_ONCE,
211             Tinebase_Model_Import::INTERVAL_WEEKLY
212         );
213         
214         if (! in_array($data['interval'], $possibleIntervals)) {
215             $data['interval'] = Tinebase_Model_Import::INTERVAL_ONCE;
216         }
217         
218         $url = filter_var($data['source'], FILTER_VALIDATE_URL);
219         if ($url) {
220             if (strpos($data['source'], 'http') === 0) {
221                 $client = new Zend_Http_Client($data['source']);
222                 $toImport = $client->request()->getBody();
223             } else {
224                 $toImport = file_get_contents($data['source']);
225             }
226         } else {
227             throw new Calendar_Exception_InvalidUrl();
228         }
229         
230         // find container or create a new one
231         $containerId = $data['options']['container_id'];
232         
233         try {
234             $container = Tinebase_Container::getInstance()->getContainerById($containerId);
235         } catch (Tinebase_Exception_InvalidArgument $e) {
236             $container = new Tinebase_Model_Container(array(
237                 'name'              => $data['options']['container_id'],
238                 'type'              => Tinebase_Model_Container::TYPE_PERSONAL,
239                 'backend'           => Tinebase_User::SQL,
240                 'color'             => '#ffffff',
241                 'application_id'    => $data['application_id'],
242                 'owner_id'          => $data['user_id'],
243                 'model'             => $data['model'],
244             ));
245
246             $container = Tinebase_Container::getInstance()->addContainer($container);
247         }
248         
249         $data['options'] = json_encode(array_replace(array(
250             'forceUpdateExisting' => TRUE,
251             'import_defintion' => NULL,
252         ), $data['options']));
253         
254         $record = new Tinebase_Model_Import(array_replace(array(
255             'id'                => Tinebase_Record_Abstract::generateUID(),
256             'user_id'           => Tinebase_Core::getUser()->getId(),
257             'sourcetype'        => Tinebase_Model_Import::SOURCETYPE_REMOTE,
258             'container_id'      => $container->getId(),
259         ), $data));
260         
261         return $this->create($record);
262     }
263 }