e79d6296b078dd1199219d13b71847514ba16ecd
[tine20] / tine20 / Tinebase / Model / Tree / Node.php
1 <?php
2 /**
3  * Tine 2.0
4  *
5  * @package     Tinebase
6  * @subpackage  Model
7  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
8  * @author      Lars Kneschke <l.kneschke@metaways.de>
9  * @copyright   Copyright (c) 2010-2017 Metaways Infosystems GmbH (http://www.metaways.de)
10  */
11
12 /**
13  * class to hold data representing one node in the tree
14  *
15  * @package     Tinebase
16  * @subpackage  Model
17  * @property    string             contenttype
18  * @property    Tinebase_DateTime  creation_time
19  * @property    string             hash
20  * @property    string             indexed_hash
21  * @property    string             name
22  * @property    Tinebase_DateTime  last_modified_time
23  * @property    string             object_id
24  * @property    string             parent_id
25  * @property    string             size
26  * @property    string             revision_size
27  * @property    string             type
28  * @property    string             revision
29  * @property    string             available_revisions
30  * @property    string             description
31  * @property    string             acl_node
32  * @property    string             revisionProps
33  * @property    string             preview_count
34  * @property    Tinebase_Record_RecordSet grants
35  */
36 class Tinebase_Model_Tree_Node extends Tinebase_Record_Abstract
37 {
38     const XPROPS_REVISION = 'revisionProps';
39     const XPROPS_REVISION_NODE_ID = 'nodeId';
40     const XPROPS_REVISION_ON = 'keep';
41     const XPROPS_REVISION_NUM = 'keepNum';
42     const XPROPS_REVISION_MONTH = 'keepMonth';
43
44     /**
45      * {"notificationProps":[{"active":true,....},{"active":true....},{....}]}
46      */
47     const XPROPS_NOTIFICATION = 'notificationProps';
48     const XPROPS_NOTIFICATION_ACTIVE = 'active';
49     const XPROPS_NOTIFICATION_SUMMARY = 'summary';
50     const XPROPS_NOTIFICATION_ACCOUNT_ID = 'accountId';
51     const XPROPS_NOTIFICATION_ACCOUNT_TYPE = 'accountType';
52     
53     /**
54      * key in $_validators/$_properties array for the filed which
55      * represents the identifier
56      *
57      * @var string
58      */
59     protected $_identifier = 'id';
60     
61     /**
62      * application the record belongs to
63      *
64      * @var string
65      */
66     protected $_application = 'Tinebase';
67
68     /**
69      * name of fields that should be omitted from modlog
70      *
71      * @var array list of modlog omit fields
72      */
73     protected $_modlogOmitFields = array('hash', 'available_revisions', 'revision_size', 'path', 'indexed_hash');
74
75     /**
76      * if foreign Id fields should be resolved on search and get from json
77      * should have this format:
78      *     array('Calendar_Model_Contact' => 'contact_id', ...)
79      * or for more fields:
80      *     array('Calendar_Model_Contact' => array('contact_id', 'customer_id), ...)
81      * (e.g. resolves contact_id with the corresponding Model)
82      *
83      * @var array
84      */
85     protected static $_resolveForeignIdFields = array(
86         'Tinebase_Model_User' => array('created_by', 'last_modified_by')
87     );
88
89     /**
90      * list of zend validator
91      *
92      * these validators get used when validating user generated content with Zend_Input_Filter
93      *
94      * @var array
95      */
96     protected $_validators = array(
97         // tine 2.0 generic fields
98         'id'                 => array(Zend_Filter_Input::ALLOW_EMPTY => true, Zend_Filter_Input::DEFAULT_VALUE => null),
99         'created_by'         => array(Zend_Filter_Input::ALLOW_EMPTY => true),
100         'creation_time'      => array(Zend_Filter_Input::ALLOW_EMPTY => true),
101         'last_modified_by'   => array(Zend_Filter_Input::ALLOW_EMPTY => true),
102         'last_modified_time' => array(Zend_Filter_Input::ALLOW_EMPTY => true),
103         'is_deleted'         => array(Zend_Filter_Input::ALLOW_EMPTY => true),
104         'deleted_time'       => array(Zend_Filter_Input::ALLOW_EMPTY => true),
105         'deleted_by'         => array(Zend_Filter_Input::ALLOW_EMPTY => true),
106         'seq'                => array(Zend_Filter_Input::ALLOW_EMPTY => true),
107         // model specific fields
108         'parent_id'         => array(Zend_Filter_Input::ALLOW_EMPTY => true, Zend_Filter_Input::DEFAULT_VALUE => null),
109         'object_id'         => array('presence' => 'required'),
110         'revisionProps'     => array(Zend_Filter_Input::ALLOW_EMPTY => true),
111         'notificationProps' => array(Zend_Filter_Input::ALLOW_EMPTY => true),
112         // contains id of node with acl info
113         'acl_node'          => array(Zend_Filter_Input::ALLOW_EMPTY => true),
114         'name'              => array('presence' => 'required'),
115         'islink'            => array(
116             Zend_Filter_Input::DEFAULT_VALUE => '0',
117             array('InArray', array(true, false))
118         ),
119
120         'relations' => array(Zend_Filter_Input::ALLOW_EMPTY => true),
121         'notes' => array(Zend_Filter_Input::ALLOW_EMPTY => true),
122         'tags' => array(Zend_Filter_Input::ALLOW_EMPTY => true),
123         'customfields' => array(Zend_Filter_Input::ALLOW_EMPTY => true),
124
125         // fields from filemanager_objects table (ro)
126         'type'           => array(
127             Zend_Filter_Input::ALLOW_EMPTY => true,
128             array('InArray', array(Tinebase_Model_Tree_FileObject::TYPE_FILE,
129                 Tinebase_Model_Tree_FileObject::TYPE_FOLDER, Tinebase_Model_Tree_FileObject::TYPE_PREVIEW)),
130         ),
131         'description'           => array(Zend_Filter_Input::ALLOW_EMPTY => true),
132         'contenttype'           => array(Zend_Filter_Input::ALLOW_EMPTY => true),
133         'revision'              => array(Zend_Filter_Input::ALLOW_EMPTY => true),
134         'available_revisions'   => array(Zend_Filter_Input::ALLOW_EMPTY => true),
135         'hash'                  => array(Zend_Filter_Input::ALLOW_EMPTY => true),
136         'indexed_hash'          => array(Zend_Filter_Input::ALLOW_EMPTY => true),
137         'size'                  => array(Zend_Filter_Input::ALLOW_EMPTY => true),
138         'revision_size'         => array(Zend_Filter_Input::ALLOW_EMPTY => true),
139         'preview_count'         => array(Zend_Filter_Input::ALLOW_EMPTY => true, 'Digits',
140             Zend_Filter_Input::DEFAULT_VALUE => 0),
141
142         // not persistent
143         'container_name' => array(Zend_Filter_Input::ALLOW_EMPTY => true),
144
145         // this is needed should be sent by / delivered to client (not persistent in db atm)
146         'path'           => array(Zend_Filter_Input::ALLOW_EMPTY => true),
147         'account_grants' => array(Zend_Filter_Input::ALLOW_EMPTY => true),
148         'tempFile'       => array(Zend_Filter_Input::ALLOW_EMPTY => true),
149         'stream'         => array(Zend_Filter_Input::ALLOW_EMPTY => true),
150         // acl grants
151         'grants'                => array(Zend_Filter_Input::ALLOW_EMPTY => true),
152     );
153
154     /**
155      * name of fields containing datetime or or an array of datetime information
156      *
157      * @var array list of datetime fields
158      */
159     protected $_datetimeFields = array(
160         'creation_time',
161         'last_modified_time',
162         'deleted_time'
163     );
164     
165     /**
166     * overwrite constructor to add more filters
167     *
168     * @param mixed $_data
169     * @param bool $_bypassFilters
170     * @param mixed $_convertDates
171     */
172     public function __construct($_data = null, $_bypassFilters = false, $_convertDates = true)
173     {
174         $this->_filters['size'] = new Zend_Filter_Empty(0);
175         parent::__construct($_data, $_bypassFilters, $_convertDates);
176     }
177
178     public function runConvertToRecord()
179     {
180         if (isset($this->_properties['available_revisions'])) {
181             $this->_properties['available_revisions'] = explode(',', ltrim(
182                 rtrim($this->_properties['available_revisions'], '}'), '{'));
183         }
184
185         parent::runConvertToRecord();
186     }
187
188     public function runConvertToData()
189     {
190         if (isset($this->_properties[self::XPROPS_REVISION]) && is_array($this->_properties[self::XPROPS_REVISION])) {
191             if (count($this->_properties[self::XPROPS_REVISION]) > 0) {
192                 $this->_properties[self::XPROPS_REVISION] = json_encode($this->_properties[self::XPROPS_REVISION]);
193             } else {
194                 $this->_properties[self::XPROPS_REVISION] = null;
195             }
196         }
197
198         if (isset($this->_properties[self::XPROPS_NOTIFICATION]) &&
199                 is_array($this->_properties[self::XPROPS_NOTIFICATION])) {
200             if (count($this->_properties[self::XPROPS_NOTIFICATION]) > 0) {
201                 $this->_properties[self::XPROPS_NOTIFICATION] =
202                     json_encode($this->_properties[self::XPROPS_NOTIFICATION]);
203             } else {
204                 $this->_properties[self::XPROPS_NOTIFICATION] = null;
205             }
206         }
207
208         parent::runConvertToData();
209     }
210
211     /**
212      * returns real filesystem path
213      *
214      * @param string $baseDir
215      * @throws Tinebase_Exception_NotFound
216      * @return string
217      */
218     public function getFilesystemPath($baseDir = null)
219     {
220         if (empty($this->hash)) {
221             throw new Tinebase_Exception_NotFound('file object hash is missing');
222         }
223
224         if ($baseDir === null) {
225             $baseDir = Tinebase_Core::getConfig()->filesdir;
226         }
227
228         return $baseDir . DIRECTORY_SEPARATOR . substr($this->hash, 0, 3) . DIRECTORY_SEPARATOR .
229             substr($this->hash, 3);
230     }
231 }