0011842: import full related record data
[tine20] / tests / tine20 / TestCase.php
1 <?php
2 /**
3  * Tine 2.0 - http://www.tine20.org
4  * 
5  * @package     Tests
6  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
7  * @copyright   Copyright (c) 2013-2015 Metaways Infosystems GmbH (http://www.metaways.de)
8  * @author      Philipp Schüle <p.schuele@metaways.de>
9  */
10
11 /**
12  * Test helper
13  */
14 require_once __DIR__ . DIRECTORY_SEPARATOR . 'TestHelper.php';
15
16 /**
17  * Abstract test class
18  * 
19  * @package     Tests
20  *
21  * TODO separation of concerns: split into multiple classes/traits with cleanup / fixture / ... functionality
22  */
23 abstract class TestCase extends PHPUnit_Framework_TestCase
24 {
25     /**
26      * transaction id if test is wrapped in an transaction
27      * 
28      * @var string
29      */
30     protected $_transactionId = null;
31     
32     /**
33      * usernames to be deleted (in sync backend)
34      * 
35      * @var array
36      */
37     protected $_usernamesToDelete = array();
38     
39     /**
40      * groups (ID) to be deleted (in sync backend)
41      * 
42      * @var array
43      */
44     protected $_groupIdsToDelete = array();
45     
46     /**
47      * remove group members, too when deleting groups
48      * 
49      * @var boolean
50      */
51     protected $_removeGroupMembers = true;
52     
53     /**
54      * invalidate roles cache
55      * 
56      * @var boolean
57      */
58     protected $_invalidateRolesCache = false;
59     
60     /**
61      * test personas
62      * 
63      * @var array
64      */
65     protected $_personas = array();
66     
67     /**
68      * unit in test
69      *
70      * @var Object
71      */
72     protected $_uit = null;
73     
74     /**
75      * the test user
76      *
77      * @var Tinebase_Model_FullUser
78      */
79     protected $_originalTestUser;
80     
81     /**
82      * the mailer
83      * 
84      * @var Zend_Mail_Transport_Abstract
85      */
86     protected static $_mailer = null;
87
88     /**
89      * db lock ids to be released
90      *
91      * @var array
92      */
93     protected $_releaseDBLockIds = array();
94
95     /**
96      * set up tests
97      */
98     protected function setUp()
99     {
100         $this->_transactionId = Tinebase_TransactionManager::getInstance()->startTransaction(Tinebase_Core::getDb());
101         
102         Addressbook_Controller_Contact::getInstance()->setGeoDataForContacts(false);
103         
104         $this->_personas = Zend_Registry::get('personas');
105         
106         $this->_originalTestUser = Tinebase_Core::getUser();
107     }
108     
109     /**
110      * tear down tests
111      */
112     protected function tearDown()
113     {
114         if (in_array(Tinebase_User::getConfiguredBackend(), array(Tinebase_User::LDAP, Tinebase_User::ACTIVEDIRECTORY))) {
115             $this->_deleteUsers();
116             $this->_deleteGroups();
117         }
118         if ($this->_transactionId) {
119             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG))
120                 Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Rolling back test transaction');
121             Tinebase_TransactionManager::getInstance()->rollBack();
122         }
123         
124         Addressbook_Controller_Contact::getInstance()->setGeoDataForContacts(true);
125
126         if ($this->_originalTestUser instanceof Tinebase_Model_User) {
127             Tinebase_Core::set(Tinebase_Core::USER, $this->_originalTestUser);
128         }
129         
130         if ($this->_invalidateRolesCache) {
131             Tinebase_Acl_Roles::getInstance()->resetClassCache();
132         }
133
134         Tinebase_Cache_PerRequest::getInstance()->reset();
135
136         $this->_releaseDBLocks();
137     }
138
139     /**
140      * release db locks
141      */
142     protected function _releaseDBLocks()
143     {
144         foreach ($this->_releaseDBLockIds as $lockId) {
145             Tinebase_Lock::releaseDBSessionLock($lockId);
146         }
147
148         $this->_releaseDBLockIds = array();
149     }
150
151     /**
152      * tear down after test class
153      */
154     public static function tearDownAfterClass()
155     {
156         Tinebase_Core::getDbProfiling();
157     }
158     
159     /**
160      * test needs transaction
161      */
162     protected function _testNeedsTransaction()
163     {
164         if ($this->_transactionId) {
165             Tinebase_TransactionManager::getInstance()->commitTransaction($this->_transactionId);
166             $this->_transactionId = null;
167         }
168     }
169     
170     /**
171      * get tag
172      *
173      * @param string $tagType
174      * @param string $tagName
175      * @param array $contexts
176      * @return Tinebase_Model_Tag
177      */
178     protected function _getTag($tagType = Tinebase_Model_Tag::TYPE_SHARED, $tagName = NULL, $contexts = NULL)
179     {
180         if ($tagName) {
181             try {
182                 $tag = Tinebase_Tags::getInstance()->getTagByName($tagName);
183                 return $tag;
184             } catch (Tinebase_Exception_NotFound $tenf) {
185             }
186         } else {
187             $tagName = Tinebase_Record_Abstract::generateUID();
188         }
189     
190         $targ = array(
191             'type'          => $tagType,
192             'name'          => $tagName,
193             'description'   => 'testTagDescription',
194             'color'         => '#009B31',
195         );
196     
197         if ($contexts) {
198             $targ['contexts'] = $contexts;
199         }
200     
201         return new Tinebase_Model_Tag($targ);
202     }
203     
204     /**
205      * delete groups and their members
206      * 
207      * - also deletes groups and users in sync backends
208      */
209     protected function _deleteGroups()
210     {
211         if (! is_array($this->_groupIdsToDelete)) {
212             return;
213         }
214
215         foreach ($this->_groupIdsToDelete as $groupId) {
216             if ($this->_removeGroupMembers) {
217                 foreach (Tinebase_Group::getInstance()->getGroupMembers($groupId) as $userId) {
218                     try {
219                         Tinebase_User::getInstance()->deleteUser($userId);
220                     } catch (Exception $e) {
221                         if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
222                             . ' error while deleting user: ' . $e->getMessage());
223                     }
224                 }
225             }
226             try {
227                 Tinebase_Group::getInstance()->deleteGroups($groupId);
228             } catch (Exception $e) {
229                 if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
230                     . ' error while deleting group: ' . $e->getMessage());
231             }
232         }
233     }
234     
235     /**
236      * delete users
237      */
238     protected function _deleteUsers()
239     {
240         foreach ($this->_usernamesToDelete as $username) {
241             try {
242                 if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
243                     . ' Trying to delete user: ' . $username);
244
245                 Tinebase_User::getInstance()->deleteUser(Tinebase_User::getInstance()->getUserByLoginName($username));
246             } catch (Exception $e) {
247                 if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
248                     . ' Error while deleting user: ' . $e->getMessage());
249             }
250         }
251     }
252
253     /**
254      * removes records and their relations
255      *
256      * @param Tinebase_Record_RecordSet $records
257      */
258     protected function _deleteRecordRelations($records, $modelsToDelete = array(), $typesToDelete = array())
259     {
260         $controller = Tinebase_Core::getApplicationInstance($records->getRecordClassName());
261
262         if (! method_exists($controller, 'deleteLinkedRelations')) {
263             return;
264         }
265
266         foreach ($records as $record) {
267             $controller->deleteLinkedRelations($record, $modelsToDelete, $typesToDelete);
268         }
269     }
270
271     /**
272      * get personal container
273      * 
274      * @param string $applicationName
275      * @param Tinebase_Model_User $user
276      * @return Tinebase_Model_Container
277      */
278     protected function _getPersonalContainer($applicationName, $user = null)
279     {
280         if ($user === null) {
281             $user = Tinebase_Core::getUser();
282         }
283         
284         $personalContainer = Tinebase_Container::getInstance()->getPersonalContainer(
285             $user,
286             $applicationName, 
287             $user,
288             Tinebase_Model_Grants::GRANT_EDIT
289         )->getFirstRecord();
290
291         if (! $personalContainer) {
292             throw new Tinebase_Exception_UnexpectedValue('no personal container found!');
293         }
294
295         return $personalContainer;
296     }
297     
298     /**
299      * get test container
300      * 
301      * @param string $applicationName
302      * @param string $model
303      */
304     protected function _getTestContainer($applicationName, $model = null)
305     {
306         return Tinebase_Container::getInstance()->addContainer(new Tinebase_Model_Container(array(
307             'name'           => 'PHPUnit ' . $model .' container',
308             'type'           => Tinebase_Model_Container::TYPE_PERSONAL,
309             'owner_id'       => Tinebase_Core::getUser(),
310             'backend'        => 'Sql',
311             'application_id' => Tinebase_Application::getInstance()->getApplicationByName($applicationName)->getId(),
312             'model'          => $model,
313         ), true));
314     }
315     
316     /**
317      * get test mail domain
318      * 
319      * @return string
320      */
321     protected function _getMailDomain()
322     {
323         return TestServer::getPrimaryMailDomain();
324     }
325     
326     /**
327      * get test user email address
328      * 
329      * @return test user email address
330      */
331     protected function _getEmailAddress()
332     {
333         $testConfig = Zend_Registry::get('testConfig');
334         return ($testConfig->email) ? $testConfig->email : Tinebase_Core::getUser()->accountEmailAddress;
335     }
336     
337     /**
338      * lazy init of uit
339      * 
340      * @return Object
341      * 
342      * @todo fix ide object class detection for completions
343      */
344     protected function _getUit()
345     {
346         if ($this->_uit === null) {
347             $uitClass = preg_replace('/Tests{0,1}$/', '', get_class($this));
348             if (@method_exists($uitClass, 'getInstance')) {
349                 $this->_uit = call_user_func($uitClass . '::getInstance');
350             } else if (@class_exists($uitClass)) {
351                 $this->_uit = new $uitClass();
352             } else {
353                 throw new Exception('could not find class ' . $uitClass);
354             }
355         }
356         
357         return $this->_uit;
358     }
359     
360     /**
361      * get messages
362      * 
363      * @return array
364      */
365     public static function getMessages()
366     {
367         // make sure messages are sent if queue is activated
368         if (isset(Tinebase_Core::getConfig()->actionqueue)) {
369             Tinebase_ActionQueue::getInstance()->processQueue(100);
370         }
371         
372         return self::getMailer()->getMessages();
373     }
374     
375     /**
376      * get mailer
377      * 
378      * @return Zend_Mail_Transport_Abstract
379      */
380     public static function getMailer()
381     {
382         if (! self::$_mailer) {
383             self::$_mailer = Tinebase_Smtp::getDefaultTransport();
384         }
385         
386         return self::$_mailer;
387     }
388     
389     /**
390      * flush mailer (send all remaining mails first)
391      */
392     public static function flushMailer()
393     {
394         // make sure all messages are sent if queue is activated
395         if (isset(Tinebase_Core::getConfig()->actionqueue)) {
396             Tinebase_ActionQueue::getInstance()->processQueue(10000);
397         }
398         
399         self::getMailer()->flush();
400     }
401     
402     /**
403      * returns the content.xml of an ods document
404      * 
405      * @param string $filename
406      * @return SimpleXMLElement
407      */
408     protected function _getContentXML($filename)
409     {
410         $zipHandler = zip_open($filename);
411         
412         do {
413             $entry = zip_read($zipHandler);
414         } while ($entry && zip_entry_name($entry) != "content.xml");
415         
416         // open entry
417         zip_entry_open($zipHandler, $entry, "r");
418         
419         // read entry
420         $entryContent = zip_entry_read($entry, zip_entry_filesize($entry));
421         
422         $xml = simplexml_load_string($entryContent);
423         zip_close($zipHandler);
424         
425         return $xml;
426     }
427     
428     /**
429      * get test temp file
430      * 
431      * @return Tinebase_TempFile
432      */
433     protected function _getTempFile()
434     {
435         $tempFileBackend = new Tinebase_TempFile();
436         $tempFile = $tempFileBackend->createTempFile(dirname(__FILE__) . '/Filemanager/files/test.txt');
437         return $tempFile;
438     }
439     
440     /**
441      * remove right in all users roles
442      * 
443      * @param string $applicationName
444      * @param string $right
445      * @param boolean $removeAdminRight
446      * @return array original role rights by role id
447      */
448     protected function _removeRoleRight($applicationName, $rightToRemove, $removeAdminRight = true)
449     {
450         $app = Tinebase_Application::getInstance()->getApplicationByName($applicationName);
451         $rolesOfUser = Tinebase_Acl_Roles::getInstance()->getRoleMemberships(Tinebase_Core::getUser()->getId());
452         $this->_invalidateRolesCache = true;
453
454         $roleRights = array();
455         foreach ($rolesOfUser as $roleId) {
456             $roleRights[$roleId] = $rights = Tinebase_Acl_Roles::getInstance()->getRoleRights($roleId);
457             foreach ($rights as $idx => $right) {
458                 if ($right['application_id'] === $app->getId() && ($right['right'] === $rightToRemove || $right['right'] === Tinebase_Acl_Rights_Abstract::ADMIN)) {
459                     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ 
460                         . ' Removing right ' . $right['right'] . ' from app ' . $applicationName . ' in role (id) ' . $roleId);
461                     unset($rights[$idx]);
462                 }
463             }
464             Tinebase_Acl_Roles::getInstance()->setRoleRights($roleId, $rights);
465         }
466         
467         return $roleRights;
468     }
469     
470     /**
471      * set grants for a persona and the current user
472      * 
473      * @param integer $containerId
474      * @param string $persona
475      * @param string $adminGrant
476      */
477     protected function _setPersonaGrantsForTestContainer($containerId, $persona, $personaAdminGrant = false, $userAdminGrant = true)
478     {
479         $grants = new Tinebase_Record_RecordSet('Tinebase_Model_Grants', array(array(
480             'account_id'    => $this->_personas[$persona]->getId(),
481             'account_type'  => 'user',
482             Tinebase_Model_Grants::GRANT_READ     => true,
483             Tinebase_Model_Grants::GRANT_ADD      => true,
484             Tinebase_Model_Grants::GRANT_EDIT     => true,
485             Tinebase_Model_Grants::GRANT_DELETE   => true,
486             Tinebase_Model_Grants::GRANT_ADMIN    => $personaAdminGrant,
487         ), array(
488             'account_id'    => Tinebase_Core::getUser()->getId(),
489             'account_type'  => 'user',
490             Tinebase_Model_Grants::GRANT_READ     => true,
491             Tinebase_Model_Grants::GRANT_ADD      => true,
492             Tinebase_Model_Grants::GRANT_EDIT     => true,
493             Tinebase_Model_Grants::GRANT_DELETE   => true,
494             Tinebase_Model_Grants::GRANT_ADMIN    => $userAdminGrant,
495         )));
496         
497         Tinebase_Container::getInstance()->setGrants($containerId, $grants, TRUE);
498     }
499
500     /**
501      * set current user
502      *
503      * @param $user
504      * @throws Tinebase_Exception_InvalidArgument
505      */
506     protected function _setUser($user)
507     {
508         Tinebase_Core::set(Tinebase_Core::USER, $user);
509     }
510
511     /**
512      * call handle cli function with params
513      *
514      * @param array $_params
515      */
516     protected function _cliHelper($command, $_params)
517     {
518         $opts = new Zend_Console_Getopt(array($command => $command));
519         $opts->setArguments($_params);
520         ob_start();
521         $this->_cli->handle($opts, false);
522         $out = ob_get_clean();
523         return $out;
524     }
525
526     /**
527      * returns true if main db adapter is postgresql
528      *
529      * @return bool
530      */
531     protected function _dbIsPgsql()
532     {
533         $db = Tinebase_Core::getDb();
534         return ($db instanceof Zend_Db_Adapter_Pdo_Pgsql);
535     }
536 }