4bcb4fb6313002e55a4ebc7693dd69326a7bb0b8
[tine20] / scripts / syncuuids / lib / Sync.php
1 <?php
2 /**
3  * Tine 2.0
4  *
5  * @package     Sync
6  * @author      Philipp Schüle <p.schuele@metaways.de>
7  */
8
9 /**
10  * class documentation
11  *
12  * @package     Sync
13  */
14 class Sync 
15 {
16     /**
17      * configuration
18      * 
19      * @var Zend_Config
20      */
21     protected $_config = NULL;
22     
23     /**
24      * logger
25      * 
26      * @var Zend_Log
27      */
28     protected $_logger = NULL;
29     
30     /**
31      * ldap connector
32      * 
33      * @var Zend_Ldap
34      */
35     protected $_ldap = NULL;
36     
37     /**
38     * the basic group ldap filter (for example the objectclass)
39      *
40     * @var string
41     */
42     protected $_groupBaseFilter = 'objectclass=posixgroup';
43     
44     /**
45      * the basic user ldap filter (for example the objectclass)
46     *
47     * @var string
48     */
49     protected $_userBaseFilter = 'objectclass=posixaccount';
50     
51     /**
52      * the tine user backend
53     *
54     * @var Tinebase_User_Sql
55     */
56     protected $_tineUserBackend = NULL;
57     
58     /**
59      * the tine group backend
60     *
61     * @var Tinebase_Group_Sql
62     */
63     protected $_tineGroupBackend = NULL;
64     
65     /**
66     * the basic user search scope
67     *
68     * @var integer
69     */
70     protected $_userSearchScope = Zend_Ldap::SEARCH_SCOPE_SUB;
71     
72     /**
73     * the basic group search scope
74     *
75     * @var integer
76     */
77     protected $_groupSearchScope     = Zend_Ldap::SEARCH_SCOPE_SUB;
78     
79     /**
80      * the constructor
81      */
82     public function __construct()
83     {
84         $this->_initSettings();
85         $this->_initConfig();
86         $this->_initLogger();
87         $this->_initLdap();
88         $this->_initTineBackends();
89         
90         $this->_logger->info(__METHOD__ . '::' . __LINE__ . ' init complete');
91     }
92     
93     /**
94      * init php settings
95      */
96     protected function _initSettings()
97     {
98         error_reporting(E_COMPILE_ERROR | E_CORE_ERROR | E_ERROR | E_PARSE);
99         ini_set('display_errors', 1);
100         ini_set('log_errors', 1);
101         set_error_handler('Tinebase_Core::errorHandler', E_ALL);
102         
103         ini_set('iconv.internal_encoding', 'utf-8');
104     }
105     
106     /**
107      * init config
108      */
109     protected function _initConfig()
110     {
111         $configData = include('conf.php');
112         if ($configData === false) {
113             die ('central configuration file config.inc.php not found in includepath: ' . get_include_path());
114         }
115         $this->_config = new Zend_Config($configData);
116         
117         if (! $this->_config->inputfile) {
118             die('need inputfile in config');
119         }
120     }
121
122     /**
123      * init config
124      */
125     protected function _initLogger()
126     {
127         $this->_logger = new Zend_Log();
128         if ($this->_config->logfile) {
129             $writer = new Zend_Log_Writer_Stream($this->_config->logfile);
130         } else {
131             $writer = new Zend_Log_Writer_Null;
132         }
133         $this->_logger->addWriter($writer);
134         
135         if ($this->_config->loglevel) {
136             $filter = new Zend_Log_Filter_Priority($this->_config->loglevel);
137             $this->_logger->addFilter($filter);
138         }
139     }
140     
141     /**
142      * returns config
143      * 
144      * @return Zend_Config
145      */
146     public function getConfig()
147     {
148         return $this->_config;
149     }
150     
151     /**
152      * init ldap
153      */
154     protected function _initLdap()
155     {
156         if (! $this->_config->ldap || ! $this->_config->ldap->baseDn) {
157             throw new Exception('ldap config section or basedn missing');
158         }
159         
160         $this->_ldap = new Zend_Ldap($this->_config->ldap->toArray());
161         $this->_ldap->bind();
162         $this->_logger->info(__METHOD__ . '::' . __LINE__ . ' LDAP initialized');
163     }
164
165     /**
166     * init tine backends
167     */
168     protected function _initTineBackends()
169     {
170         Tinebase_Core::setupConfig();
171         Tinebase_Core::setupDatabaseConnection();
172         
173         $this->_tineUserBackend = new Tinebase_User_Sql();
174         $this->_tineGroupBackend = new Tinebase_Group_Sql();
175     }
176     
177     /**
178      * sync user/group ids in db dump
179      */
180     public function doSync()
181     {
182         $userMapping = $this->_getUserMapping();
183         $groupMapping = $this->_getGroupMapping();
184         
185         if ($this->_config->dryrun) {
186             echo "user mapping:\n" . print_r($userMapping, TRUE);
187             echo "group mapping:\n" . print_r($groupMapping, TRUE);
188         } else {
189             $this->_syncIdsInDump(array_merge($userMapping, $groupMapping));
190             $this->_logger->info(__METHOD__ . '::' . __LINE__ . ' Sync finished.');
191         }
192     }
193     
194     /**
195      * read ldap / get users from tine an create mapping
196      * 
197      * @return array
198      */
199     protected function _getUserMapping()
200     {
201         $this->_logger->info(__METHOD__ . '::' . __LINE__ . ' Fetching user mapping ...');
202         
203         $filter = Zend_Ldap_Filter::andFilter(
204             Zend_Ldap_Filter::string($this->_userBaseFilter)
205         );
206         $mapping = array();
207         $ldapUsers = $this->_ldap->search($filter, $this->_config->ldap->baseDn, $this->_userSearchScope, array('*', '+'));
208         foreach ($ldapUsers as $user) {
209             $username = $user['uid'][0];
210             $ldapUuid = $user['entryuuid'][0];
211             try {
212                 $tineUser = $this->_tineUserBackend->getFullUserByLoginName($username);
213                 $this->_logger->debug(__METHOD__ . '::' . __LINE__ . ' User ' . $username . ': ' . $tineUser->getId() . ' -> ' . $ldapUuid);
214                 $mapping[$tineUser->getId()] = $ldapUuid;
215             } catch (Tinebase_Exception_NotFound $tenf) {
216                 $this->_logger->debug(__METHOD__ . '::' . __LINE__ . ' User ' . $username . ' not found.');
217             }
218         }
219         
220         $this->_logger->info(__METHOD__ . '::' . __LINE__ . ' Found ' . count($mapping) . ' users for the mapping.');
221         $this->_logger->debug(__METHOD__ . '::' . __LINE__ . ' ' . print_r($mapping, TRUE));
222         
223         return $mapping;
224     }
225
226     /**
227      * read ldap / get users and groups from tine an create mapping
228      * 
229      * @return array
230      */
231     protected function _getGroupMapping()
232     {
233         $this->_logger->info(__METHOD__ . '::' . __LINE__ . ' Fetching user mapping ...');
234         
235         $filter = Zend_Ldap_Filter::andFilter(
236             Zend_Ldap_Filter::string($this->_groupBaseFilter)
237         );
238         $mapping = array();
239         $groupNameMapping = ($this->_config->groupNameMapping) ? $this->_config->groupNameMapping->toArray() : array();
240         $this->_logger->debug(__METHOD__ . '::' . __LINE__ . ' Group name mapping: ' . print_r($groupNameMapping, TRUE));
241         $ldapGroups = $this->_ldap->search($filter, $this->_config->ldap->baseDn, $this->_groupSearchScope, array('*', '+'));
242         foreach ($ldapGroups as $group) {
243             $groupname = (isset($groupNameMapping[$group['cn'][0]])) ? $groupNameMapping[$group['cn'][0]] : $group['cn'][0];
244             $ldapUuid = $group['entryuuid'][0];
245             try {
246                 $tineGroup = $this->_tineGroupBackend->getGroupByName($groupname);
247                 $this->_logger->debug(__METHOD__ . '::' . __LINE__ . ' Group ' . $groupname . ' (' .$group['cn'][0] . '): ' . $tineGroup->getId() . ' -> ' . $ldapUuid);
248                 $mapping[$tineGroup->getId()] = $ldapUuid;
249             } catch (Tinebase_Exception_Record_NotDefined $tenf) {
250                 // @todo should be: Tinebase_Exception_NotFound 
251                 $this->_logger->debug(__METHOD__ . '::' . __LINE__ . ' Group ' . $groupname . ' (' .$group['cn'][0] . '): ' . $tenf->getMessage());
252             }
253         }
254         
255         $this->_logger->info(__METHOD__ . '::' . __LINE__ . ' Found ' . count($mapping) . ' groups for the mapping.');
256         $this->_logger->debug(__METHOD__ . '::' . __LINE__ . ' ' . print_r($mapping, TRUE));
257         
258         return $mapping;
259     }
260     
261     /**
262      * syncs the ids in a sql dump file
263      * 
264      * @param array $mapping
265      */
266     protected function _syncIdsInDump($mapping)
267     {
268         // use mapping for str_replace
269         if (! file_exists($this->_config->inputfile)) {
270             die('file does not exist');
271         }
272         $this->_logger->info(__METHOD__ . '::' . __LINE__ . ' Reading input file: ' . $this->_config->inputfile);
273         $input = file_get_contents($this->_config->inputfile);
274         $this->_logger->info(__METHOD__ . '::' . __LINE__ . ' Replacing ids ...');
275         $output = str_replace(array_keys($mapping), array_values($mapping), $input);
276         
277         $filename = ($this->_config->outputfile) ? $this->_config->outputfile : 'synced.sql';
278         $this->_logger->info(__METHOD__ . '::' . __LINE__ . ' Writing to file: ' . $filename);
279         file_put_contents($filename, $output);
280     }
281 }