0004934: Ensure that container does exists
[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      * @return null|array
63      */
64     public function runNextScheduledImport()
65     {
66         if ($record = $this->_getNextScheduledImport()) {
67             return $this->_doScheduledImport($record)->toArray();
68         }
69         
70         return NULL;
71     }
72     
73     /**
74      * Get the next scheduled import
75      * 
76      * @param interval
77      * @param recursive
78      * @return Object
79      */
80     protected function _getNextScheduledImport()
81     {
82         $timestampBefore = null;
83         
84         $now = new Tinebase_DateTime();
85         
86         $anHourAgo = clone $now;
87         $anHourAgo->subHour(1);
88         
89         $aDayAgo = clone $now;
90         $aDayAgo->subDay(1);
91         
92         $aWeekAgo = clone $now;
93         $aWeekAgo->subWeek(1);
94         
95         $filter = new Tinebase_Model_ImportFilter(array(), 'OR');
96         
97         $filter0 = new Tinebase_Model_ImportFilter(array(
98                 array('field' => 'interval', 'operator' => 'equals', 'value' => Tinebase_Model_Import::INTERVAL_ONCE),
99                 array('field' => 'timestamp', 'operator' => 'isnull', 'value' => null),
100         ), 'AND');
101         
102         $filter1 = new Tinebase_Model_ImportFilter(array(
103             array('field' => 'interval', 'operator' => 'equals', 'value' => Tinebase_Model_Import::INTERVAL_HOURLY),
104             array('field' => 'timestamp', 'operator' => 'before', 'value' => $anHourAgo),
105         ), 'AND');
106         
107         $filter2 = new Tinebase_Model_ImportFilter(array(
108                 array('field' => 'interval', 'operator' => 'equals', 'value' => Tinebase_Model_Import::INTERVAL_DAILY),
109                 array('field' => 'timestamp', 'operator' => 'before', 'value' => $aDayAgo),
110         ), 'AND');
111         
112         $filter3 = new Tinebase_Model_ImportFilter(array(
113                 array('field' => 'interval', 'operator' => 'equals', 'value' => Tinebase_Model_Import::INTERVAL_WEEKLY),
114                 array('field' => 'timestamp', 'operator' => 'before', 'value' => $aWeekAgo),
115         ), 'AND');
116         
117         $filter->addFilterGroup($filter0);
118         $filter->addFilterGroup($filter1);
119         $filter->addFilterGroup($filter2);
120         $filter->addFilterGroup($filter3);
121         
122         // Always sort by creation timestamp to ensure first in first out
123         $pagination = new Tinebase_Model_Pagination(array(
124             'limit'     => 1,
125             'sort'      => 'timestamp',
126             'dir'       => 'DESC'
127         ));
128         
129         $record = $this->search($filter, $pagination)->getFirstRecord();
130         
131         if (! $record) {
132             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
133                 Tinebase_Core::getLogger()->debug(__METHOD__ . ' ' . __LINE__ . ' No ScheduledImport could be found.');
134             }
135             
136             return NULL;
137         }
138         return $record;
139     }
140     
141     /**
142      * Execute scheduled import
143      * @param Tinebase_Model_Import $record
144      * @return Tinebase_Model_Import
145      */
146     protected function _doScheduledImport(Tinebase_Model_Import $record)
147     {
148         $currentUser = Tinebase_Core::getUser();
149         // set user who created the import job
150         $importUser = Tinebase_User::getInstance()->getUserByPropertyFromSqlBackend('accountId', $record->user_id, 'Tinebase_Model_FullUser');
151         Tinebase_Core::set(Tinebase_Core::USER, $importUser);
152         
153         $importer = $record->getOption('plugin');
154         
155         $options = array(
156             'container_id' => $record->container_id,
157             // legacy
158             'importContainerId' => $record->container_id,
159         );
160         
161         try {
162             if (strpos($record->source, 'http') === 0) {
163                 $client = new Zend_Http_Client($record->source);
164                 $toImport = $client->request()->getBody();
165             } else {
166                 $toImport = file_get_contents($record->source);
167             }
168         } catch (Exception $e) {
169             throw new Tinebase_Exception_NotFound('Could not load file to import: ' . $record->source);
170         }
171         
172         $importer = new $importer($options);
173         
174         if ($toImport) {
175             // do import
176             $importer->import($toImport);
177             
178             if ($record->interval === Tinebase_Model_Import::INTERVAL_ONCE || ! $record->timestamp instanceof Tinebase_DateTime) {
179                 $record->timestamp = Tinebase_DateTime::now();
180             }
181             
182             switch ($record->interval) {
183                 case Tinebase_Model_Import::INTERVAL_DAILY:
184                     $record->timestamp->addDay(1);
185                     break;
186                 case Tinebase_Model_Import::INTERVAL_WEEKLY:
187                     $record->timestamp->addWeek(1);
188                     break;
189                 case Tinebase_Model_Import::INTERVAL_HOURLY:
190                     $record->timestamp->addHour(1);
191                     break;
192             }
193             
194             // update record
195             $record = $this->update($record);
196             
197         } else {
198             if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
199                 Tinebase_Core::getLogger()->info(__METHOD__ . ' ' . __LINE__ . ' The source could not be loaded: "' . $record->source . '"');
200             }
201         }
202         
203         Tinebase_Core::set(Tinebase_Core::USER, $currentUser);
204         
205         return $record;
206     }
207     
208     /**
209      * Creates a remote import for events
210      * 
211      * @param string $remoteUrl
212      * @param string $interval
213      * @param array $importOptions
214      * @throws Calendar_Exception_InvalidUrl
215      * @return Tinebase_Record_Interface
216      */
217     public function createRemoteImportEvent($data)
218     {
219         $possibleIntervals = array(
220             Tinebase_Model_Import::INTERVAL_DAILY,
221             Tinebase_Model_Import::INTERVAL_HOURLY,
222             Tinebase_Model_Import::INTERVAL_ONCE,
223             Tinebase_Model_Import::INTERVAL_WEEKLY
224         );
225         
226         if (! in_array($data['interval'], $possibleIntervals)) {
227             $data['interval'] = Tinebase_Model_Import::INTERVAL_ONCE;
228         }
229         
230         $url = filter_var($data['source'], FILTER_VALIDATE_URL);
231         if ($url) {
232             if (strpos($data['source'], 'http') === 0) {
233                 $client = new Zend_Http_Client($data['source']);
234                 $toImport = $client->request()->getBody();
235             } else {
236                 $toImport = file_get_contents($data['source']);
237             }
238         } else {
239             throw new Calendar_Exception_InvalidUrl();
240         }
241         
242         // find container or create a new one
243         $containerId = $data['options']['container_id'];
244         
245         try {
246             $container = Tinebase_Container::getInstance()->getContainerById($containerId);
247         } catch (Tinebase_Exception_InvalidArgument $e) {
248             $container = new Tinebase_Model_Container(array(
249                 'name'              => $data['options']['container_id'],
250                 'type'              => Tinebase_Model_Container::TYPE_PERSONAL,
251                 'backend'           => Tinebase_User::SQL,
252                 'color'             => '#ffffff',
253                 'application_id'    => $data['application_id'],
254                 'owner_id'          => $data['user_id'],
255                 'model'             => $data['model'],
256             ));
257
258             $container = Tinebase_Container::getInstance()->addContainer($container);
259         }
260         
261         $data['options'] = json_encode(array_replace(array(
262             'forceUpdateExisting' => TRUE,
263             'import_defintion' => NULL,
264         ), $data['options']));
265         
266         $record = new Tinebase_Model_Import(array_replace(array(
267             'id'                => Tinebase_Record_Abstract::generateUID(),
268             'user_id'           => Tinebase_Core::getUser()->getId(),
269             'sourcetype'        => Tinebase_Model_Import::SOURCETYPE_REMOTE,
270             'container_id'      => $container->getId(),
271         ), $data));
272         
273         return $this->create($record);
274     }
275 }