Overview

Namespaces

  • Cron
  • None

Classes

  • _HtmlGrid_TableOut
  • _TransactionModel_RawSaveOperation
  • AccessControlComponent
  • AccessControlHelper
  • ActionListHelper
  • ActiveDirectoryUtils
  • AddCurrentPidToSchedulingShellCallLogs
  • AnonymousFunctionOperation
  • ArrayUtil
  • AssociationIntegrityBehavior
  • AtomicOperation
  • AuthenticationComponent
  • AuthenticationController
  • AuthenticationUser
  • AutocompleteDatasourceComponent
  • BaseModelComponent
  • Basics
  • CakeLayersHelper
  • CheckAndRunShell
  • ClassSearcher
  • CommandLineUtil
  • CommonValidationBehavior
  • ConfigurableShellCallsSchedulingTask
  • ConfigurationKey
  • ConfigurationKeys
  • ConfigurationKeysController
  • Context
  • ContextComponent
  • ContextHelper
  • Contexts
  • ControllerInspector
  • ControllerMenuHelper
  • CreateJournalingTables
  • CreateTableConfigurationKeys
  • CreateTableSchedulingConfigurableShellCalls
  • CreateTableSchedulingShellCallLogs
  • CreateTableSettedConfigurationKeys
  • CreateTableUserResetPasswordRequests
  • CreateTableUsers
  • CronSchedulingInstaller
  • CronValidationBehavior
  • CssBox
  • CssController
  • CssProperties
  • CssShell
  • CsvUtil
  • CustomDataModel
  • DatasourceDumperManager
  • DateTimeInput
  • DependencyShell
  • DetailHelper
  • DumperShell
  • ExtendedFieldsAccessControl
  • ExtendedFieldSet
  • ExtendedFieldSetHelper
  • ExtendedFieldsParser
  • ExtendedFormHelper
  • ExtendedHasManyAppModel
  • ExtendedOperationsBehavior
  • FieldDefinition
  • FieldRowDefinition
  • FieldSetDefinition
  • FieldSetLayoutHelper
  • FileOperations
  • FileOperations_Rename
  • FileOperations_SymLink
  • FileOperations_Touch
  • FileOperations_Unlink
  • FileSystem
  • FixConfigurationKeysPrimaryKey
  • FixSettedConfigurationKeysPrimaryKey
  • HasManyUtilsBehavior
  • HtmlDocument
  • HtmlGrid
  • HtmlGrid_Cell
  • HttpClient
  • HttpResponse
  • ImapClient
  • ImapMailBox
  • ImapParserShell
  • IncludePath
  • InputMasked
  • InputSearchable
  • InputsOnSubmit
  • InstallShell
  • JenkinsBuildShell
  • Journal
  • JournalDetail
  • JournalizedBehavior
  • JsonResponseComponent
  • LayoutsHelper
  • Ldap
  • LdapUtils
  • ListFieldSet
  • ListFieldSetHelper
  • ListsHelper
  • MailParser
  • Make
  • MenuHelper
  • MigrationAllPluginsShell
  • ModelOperations
  • ModelOperations_Delete
  • ModelOperations_Save
  • ModelTraverser
  • MysqlDumper
  • OpenLdapUtils
  • PaginatorUtilComponent
  • PaginatorUtilComponentFilter
  • PaginatorUtilHelper
  • Plugin
  • PluginManager
  • Reflections
  • RenameEnabledToActiveFromUsersTable
  • RunShellCallShell
  • ScaffoldUtilComponent
  • ScaffoldUtilHelper
  • Scheduling
  • SchedulingConfigurableShellCall
  • SchedulingConfigurableShellCallsController
  • SchedulingShellCallLog
  • SchedulingShellCallLogsController
  • SettedConfigurationKey
  • StuffreposPluginsRename
  • TimeZoneBehavior
  • TransactionModel
  • TransactionOperation
  • Translator
  • TranslatorShell
  • User
  • UserAuthenticationComponent
  • UserChangePassword
  • UserResetPassword
  • UserResetPasswordRequest
  • UserResetPasswordRequestSubmission
  • UsersController
  • ViewUtilHelper

Interfaces

  • AccessControlFilter
  • CommitableOperation
  • DatasourceDumper
  • MakeListener
  • SchedulingInstaller
  • TasksObject
  • UndoableOperation

Exceptions

  • LdapObjectNotWritableException
  • ModelTraverserException
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: 
  3: App::uses('Basics', 'Base.Lib');
  4: App::uses('LdapUtils', 'Ldap.Lib');
  5: App::uses('LdapObjectNotWritableException', 'Ldap.Lib');
  6: 
  7: class Ldap extends DataSource {
  8: 
  9:     const LDAP_ERROR_NO_SUCH_OBJECT = 32;
 10: 
 11:     public $connection = null;
 12: 
 13:     protected $_baseConfig = array(
 14:         'host' => 'localhost',
 15:         'version' => 3,
 16:         'ssl' => false,
 17:     );
 18:     
 19:     private $_modelBaseConfig = array(
 20:         'relativeBaseDn' => '',
 21:     );
 22: 
 23:     public function __construct($config = null) {
 24:         parent::__construct($config);
 25:         $this->connection = $this->_buildConnection();                
 26:         if (!@ldap_bind($this->connection, $this->config['login'], $this->config['password'])) {
 27:             $this->_throwPhysicalConnectionException("Datasource not connected");            
 28:         }
 29:     }
 30:     
 31:     private function _buildConnection() {
 32:         $url = ($this->config['ssl'] ? 'ldaps' : 'ldap') . '://' . $this->config['host'];
 33:         
 34:         if (!empty($this->config['port'])) {           
 35:             $url .= ':' . $this->config['port'];
 36:         }
 37: 
 38:         $connection = ldap_connect($url);
 39: 
 40:         if (!$connection) {
 41:             throw new Exception("Not connected");
 42:         }
 43:         
 44:         ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION, $this->config['version']);
 45:         
 46:         return $connection;
 47:     }
 48: 
 49:     public function column($real) {
 50:         return $real;
 51:     }
 52: 
 53:     public function create(\Model $model, $fields = null, $values = null) {
 54:         if ($fields == null) {
 55:             unset($fields, $values);
 56:             $fields = array_keys($model->data);
 57:             $values = array_values($model->data);
 58:         }
 59: 
 60:         $modelData = array();
 61:         for ($i = 0; $i < count($fields); $i++) {
 62:             $modelData[$fields[$i]] = $values[$i];
 63:         }
 64: 
 65:         $ldapData = array(
 66:             'objectClass' => $this->_getModelConfig($model, 'objectClass')
 67:             ) + $this->_toLdapData($model, $modelData);
 68:         $dn = $this->buildDnByData($model, $modelData);        
 69:         $this->_throwExceptionIfIsNotWritable($model, $dn);
 70:         
 71:         unset($ldapData['dn']);
 72: 
 73:         if (@ldap_add($this->connection, $dn, $ldapData)) {
 74:             $model->id = $dn;
 75:             return true;
 76:         } else {
 77:             //$model->onError();
 78:             //return false;
 79:             $this->_throwPhysicalConnectionException(print_r(compact('dn', 'ldapData'), true));
 80:         }
 81:     }
 82:     
 83:     /**
 84:      * Used to read records from the Datasource. The "R" in CRUD
 85:      *     
 86:      *
 87:      * @param Model $model The model being read.
 88:      * @param array $queryData An array of query data used to find the data you want
 89:      * @param integer $recursive Number of levels of association
 90:      * @return mixed
 91:      */
 92:     function read(\Model $model, $queryData = array(), $recursive = null) {                
 93:         $queryData = $this->__scrubQueryData($queryData);
 94:         $search = $this->_searchParameters($model, $queryData);
 95:         
 96:         $searchResult = @ldap_search(
 97:                         $this->connection
 98:                         , $search['baseDn']
 99:                         , $search['filter']                
100:                         , $search['attributes']
101:                         , $search['attributesOnly']
102:                         , $search['sizeLimit']
103:                         , $search['timeLimit']
104:                         , $search['deref']
105:         );
106:         
107:         if ($searchResult === false) {
108:             if (ldap_errno($this->connection) == self::LDAP_ERROR_NO_SUCH_OBJECT) {
109:                 return array();
110:             }
111:             
112:             $this->_throwPhysicalConnectionException(print_r($search,true));            
113:             $model->onError();
114:             return false;
115:         }
116:                 
117:         $info = ldap_get_entries($this->connection, $searchResult);
118:         if ($search['excludeBase']) {
119:             $infoBefore = $info;
120:             $info = $this->_excludeDn($info, $search['baseDn']);
121:         }
122:         
123:         if ($this->_isQueryCount($queryData)) {      
124:             $result[0][$model->alias]['count'] =  $info['count'];
125:             return $result;            
126:         }
127:         
128:         unset($info['count']);        
129:         
130:         $modelInstances = array();                
131:         
132:         foreach($info as $ldapInstance) {
133:             $modelInstances[][$model->alias] = $this->_fromLdapData(
134:                 $model
135:                 , $ldapInstance);
136:         }                
137:         
138:         return $modelInstances;
139:     }
140:     
141:     private function _searchParameters(Model $model, $queryData) {        
142:         $conditions = $this->_parseConditions($model, $queryData['conditions']);
143:         
144:         if (array_key_exists("{$model->alias}.{$model->primaryKey}", $conditions)) {
145:             $baseDn = $queryData['conditions']["{$model->alias}.{$model->primaryKey}"];
146:             $filter = '(objectclass=*)';
147:             $excludeBase = false;
148:         } else {
149:             $baseDn = $this->_getModelBaseDn($model);
150:             $filter = $this->_conditions($model, $conditions);
151:             $excludeBase = true;
152:         }
153: 
154:         $attributes = array();
155:         $attributesOnly = null;
156:         $sizeLimit = null;
157:         $timeLimit = null;
158:         $deref = null;
159: 
160:         return compact(
161:                         'baseDn'
162:                         , 'filter'
163:                         , 'attributes'
164:                         , 'attributesOnly'
165:                         , 'sizeLimit'
166:                         , 'timeLimit'
167:                         , 'deref'
168:                         , 'excludeBase'
169:         );
170:     }
171:     
172:     private function _parseConditions($model, $conditions) {
173:         if (is_string($conditions)) {
174:             if (preg_match('/^([^=])+=(.+)$/', $conditions, $matches)) {
175:                 return $this->_parseConditions($model, array(
176:                     $matches[1] => $matches[2]
177:                 ));
178:             }
179:             else {
180:                 throw new Exception("Condition pattern not recognized: $conditions");
181:             }
182:         }
183:         if (is_array ($conditions)) {
184:             $parsedConditions = array();
185:             foreach($conditions as $key => $value) {
186:                 if (!is_string($value)) {
187:                     throw new Exception("Condition value is not a string");
188:                 }
189:                                 
190:                 $parsedConditions[Basics::fieldFullName($key, $model->alias)] = $value;
191:             }
192:             return $parsedConditions;
193:         }
194:         else {
195:             throw new Exception('$conditions is not string neither array');
196:         }
197:     }
198:     
199:     private function _isQueryCount($queryData) {
200:         return is_string($queryData['fields']) &&
201:                 $queryData['fields'] == 'COUNT(*) AS ' . $this->column('count');
202:     }        
203:     
204:     public function update(\Model $model, $fields = null, $values = null, $conditions = null) {        
205:         if ($conditions !== null) {
206:             throw new NotImplementedException("Unsuported update() call with \"conditions\" parameter");
207:         }
208:         
209:         if ($fields == null) {
210:             unset($fields, $values);
211:             $fields = array_keys($model->data);
212:             $values = array_values($model->data);
213:         }
214: 
215:         $modelData = array();
216:         for ($i = 0; $i < count($fields); $i++) {
217:             $modelData[$fields[$i]] = $values[$i];
218:         }                
219:         
220:         if (empty($modelData[$model->primaryKey])) {
221:             $modelData[$model->primaryKey] = $model->id;
222:         }
223: 
224:         $ldapData = $this->_toLdapData($model, $modelData);
225:                 
226:         if (!empty($modelData[$model->primaryKey]))  {
227:             $dn = $modelData[$model->primaryKey];
228:         }
229:         else if (!empty($model->id)) {
230:             $dn = $model->id;
231:         }                
232:         else {
233:             throw new Exception("No primary key value was defined");
234:         }                
235:         
236:         $this->_throwExceptionIfIsNotWritable($model, $dn);
237:         unset($ldapData['dn']);
238:                 
239:         $rdnAttribute = $this->_rdnAttribute($dn);        
240:         if (isset($ldapData[$rdnAttribute])) {            
241:             if ($ldapData[$rdnAttribute] != LdapUtils::firstRdn($dn, 'value')) {
242:                 $dn = $this->_renameRdn($dn, $ldapData[$rdnAttribute]);
243:             }
244:             unset($ldapData[$rdnAttribute]);
245:             if (empty($ldapData)) {
246:                 $model->id = $dn;
247:                 return true;
248:             }
249:         }
250: 
251:         if (@ldap_modify($this->connection, $dn, $ldapData)) {
252:             $model->id = $dn;
253:             return true;
254:         } else {
255:             //$model->onError();
256:             //return false;
257:             $this->_throwPhysicalConnectionException(print_r(compact('dn', 'ldapData'), true));
258:         }
259:     }
260:     
261:     public   function calculate(&$model, $func, $params = array()) {
262:         $params = (array)$params;
263: 
264:         switch (strtolower($func)) {
265:             case 'count':
266:                 if (!isset($params[0])) {
267:                     $params[0] = '*';
268:                 }
269:                 if (!isset($params[1])) {
270:                     $params[1] = 'count';
271:                 }
272:                 return 'COUNT(' . $this->column($params[0]) . ') AS ' . $this->column($params[1]);
273:             case 'max':
274:             case 'min':
275:                 if (!isset($params[1])) {
276:                     $params[1] = $params[0];
277:                 }
278:                 return strtoupper($func) . '(' . $this->column($params[0]) . ') AS ' . $this->column($params[1]);
279:             break;
280:         }
281:     }
282:     
283:     public function delete(\Model $model, $id = null) {
284:         if (!$id) {
285:             $id = array(
286:                 "{$model->alias}.{$model->primaryKey}"=> $this->id
287:             );            
288:         }        
289:         
290:         $instances = $model->find(
291:                 'all', array(
292:             'conditions' => $id
293:                 )
294:         );
295:                
296:         if (empty($instances)) {
297:             return false;
298:         }                
299:         
300:         foreach($instances as $instance) {            
301:             if (!@ldap_delete($this->connection, $instance[$model->alias][$model->primaryKey])) {
302:                 return false;
303:             }
304:         }
305:         
306:         return true;
307:     }
308: 
309:     public function query() {
310:         $args = func_get_args();
311:         $fields = null;
312:         $order = null;
313:         $limit = null;
314:         $page = null;
315:         $recursive = null;
316: 
317:         if (count($args) === 1) {
318:             throw new Exception('count($args) === 1');
319:         } elseif (count($args) > 1 && (strpos($args[0], 'findBy') === 0 || strpos($args[0], 'findAllBy') === 0)) {
320:             $params = $args[1];
321: 
322:             if (substr($args[0], 0, 6) === 'findBy') {
323:                 $all = false;
324:                 $field = Inflector::underscore(substr($args[0], 6));
325:             } else {
326:                 $all = true;
327:                 $field = Inflector::underscore(substr($args[0], 9));
328:             }
329: 
330:             $or = (strpos($field, '_or_') !== false);
331:             if ($or) {
332:                 $field = explode('_or_', $field);
333:             } else {
334:                 $field = explode('_and_', $field);
335:             }
336:             $off = count($field) - 1;
337: 
338:             if (isset($params[1 + $off])) {
339:                 $fields = $params[1 + $off];
340:             }
341: 
342:             if (isset($params[2 + $off])) {
343:                 $order = $params[2 + $off];
344:             }
345: 
346:             if (!array_key_exists(0, $params)) {
347:                 return false;
348:             }
349: 
350:             $c = 0;
351:             $conditions = array();
352: 
353:             foreach ($field as $f) {
354:                 $conditions[$args[2]->alias . '.' . $f] = $params[$c++];
355:             }
356: 
357:             if ($or) {
358:                 $conditions = array('OR' => $conditions);
359:             }
360: 
361:             if ($all) {
362:                 if (isset($params[3 + $off])) {
363:                     $limit = $params[3 + $off];
364:                 }
365: 
366:                 if (isset($params[4 + $off])) {
367:                     $page = $params[4 + $off];
368:                 }
369: 
370:                 if (isset($params[5 + $off])) {
371:                     $recursive = $params[5 + $off];
372:                 }
373:                 return $args[2]->find('all', compact('conditions', 'fields', 'order', 'limit', 'page', 'recursive'));
374:             } else {
375:                 if (isset($params[3 + $off])) {
376:                     $recursive = $params[3 + $off];
377:                 }
378:                 return $args[2]->find('first', compact('conditions', 'fields', 'order', 'recursive'));
379:             }
380:         } else {
381:             throw new Exception("Method not found: {$args[0]}");
382:         }
383:     }
384:     
385:     public function bind($dn, $password) {        
386:         return @ldap_bind(
387:                         $this->_buildConnection()
388:                         , $dn
389:                         , $password
390:         );
391:     }
392:     
393:     public function describe($model) {
394:         if (empty($model->schema)) {
395:             throw new Exception("{$model->name} has no attribute '\$schema' defined");
396:         }
397:         
398:         $schema = array($model->primaryKey => array('type' => 'string')) + $model->schema;
399:         
400:         foreach(array_keys($schema) as $field) {
401:             $schema[$field] += array(
402:                 'type' => 'string',
403:                 'length' => null,
404:                 'null' => false
405:             );
406:         }
407: 
408:         return $schema;
409:     }
410: 
411:     /**
412:      * 
413:      * @param Model $model
414:      * @param array $modelConditions
415:      * @return string
416:      * @throws NotImplementedException
417:      */
418:     public function _conditions(Model $model, $modelConditions) {
419:         $modelData = array();
420:         
421:         foreach($modelConditions as $modelField => $value) {
422:             list($alias,$field) = Basics::fieldNameToArray($modelField);
423:             if ($alias != $model->alias) {
424:                 throw new NotImplementedException("Conditions with alias then self model: {$modelField} in {$model->alias}");
425:             }
426:             $modelData[$field] = $value;                        
427:         }
428:         
429:         $ldapData = array();
430:         foreach($this->_toLdapData($model, $modelData) as $attribute => $value) {
431:             $ldapData[] = array($attribute, $this->_quote($value));
432:         }
433: 
434:         $ldapData[] = array('objectClass', $this->_getModelConfig($model, 'objectClass'));
435:         return $this->_conditionsArrayToString($ldapData);        
436:     }        
437:     /**
438:      * Convert an array into a ldap condition string
439:      *
440:      * @param array $conditions condition
441:      * @return string
442:      */
443:     function _conditionsArrayToString($conditions, $join = '&') {
444:         if (empty($conditions)) {
445:             return null;
446:         }
447:         else {
448:             reset($conditions);
449:             list($attribute, $value) = $conditions[key($conditions)];            
450:             unset($conditions[key($conditions)]);
451:             
452:             $currentCondition = $this->_conditionAttributeValue($attribute, $value);
453:             $leftConditions = $this->_conditionsArrayToString($conditions);
454:             return $leftConditions ? '(' . $join . $currentCondition . $leftConditions . ')' : "$currentCondition";
455:         }
456:     }
457: 
458:     private function _conditionAttributeValue($attribute, $value) {
459:         if (is_array($value)) {
460:             $conditions = array();
461:             foreach ($value as $subValue) {
462:                 $conditions = array(array($attribute, $subValue));
463:             }
464:             return $this->_conditionsArrayToString($conditions, '|');
465:         } else {
466:             return "($attribute=$value)";
467:         }
468:     }
469: 
470:     private function _quote($str) {
471:         return str_replace(
472:                 array('\\', ' ', '*', '(', ')')
473:                 , array('\\5c', '\\20', '\\2a', '\\28', '\\29'), $str
474:         );
475:     }
476: 
477:     /**
478:      * Private helper method to remove query metadata in given data array.
479:      *
480:      * @param array $queryData
481:      */
482:     function __scrubQueryData($queryData) { 
483:     if (!isset ($queryData['type']))
484:         $queryData['type'] = 'default';
485: 
486:     if (!isset ($queryData['conditions']))
487:         $queryData['conditions'] = array();
488: 
489:     if (!isset ($queryData['fields']) && empty($queryData['fields']))
490:         $queryData['fields'] = array ();
491: 
492:     if (!isset ($queryData['order']) && empty($queryData['order']))
493:         $queryData['order'] = array ();
494: 
495:     if (!isset ($queryData['limit']))
496:         $queryData['limit'] = null;
497:         
498:         return $queryData;
499:     }
500:     
501:     private function _toLdapData(Model $model, $modelData) {
502:         $method = $this->_getDatabaseMethod($model, 'ToLdap');
503:         if ($method->getNumberOfParameters() > 1) {
504:             $ldapData = $method->invoke(
505:                 ConnectionManager::$config
506:                 , $modelData
507:                 , $this->_previousLdapData($model, $modelData)
508:             );
509:         } else {
510:             $ldapData = $method->invoke(
511:                 ConnectionManager::$config
512:                 , $modelData);
513:         }
514: 
515:         unset($ldapData['dn']);
516:         if (!empty($modelData[$model->primaryKey])) {
517:             $ldapData['dn'] = $modelData[$model->primaryKey];
518:         }
519: 
520:         return $ldapData;
521:     }
522:     
523:     private function _fromLdapData(Model $model, $ldapData) {
524:         unset($ldapData['objectclass']);
525:         unset($ldapData['count']);
526:         
527:         foreach ($ldapData as $key => $value) {
528:             if (is_numeric($key)) {
529:                 unset($ldapData[$key]);
530:             } else if (is_array($value)) {
531:                 $ldapData[$key] = array_key_exists(0, $value) ?
532:                     $value[0] :
533:                     null;
534:             }
535:         }
536: 
537:         $modelData = $this->_getDatabaseMethod($model, 'FromLdap')->invoke(
538:             ConnectionManager::$config
539:             , $ldapData);
540: 
541:         if (!empty($ldapData['dn'])) {
542:             $modelData[$model->primaryKey] = LdapUtils::normalizeDn($ldapData['dn']);
543:         }        
544: 
545: 
546:         return $modelData;
547:     }
548: 
549:     /**
550:      * 
551:      * @param type $model
552:      * @param type $suffix
553:      * @return \ReflectionMethod
554:      * @throws Exception
555:      */
556:     private function _getDatabaseMethod($model, $suffix) {
557:         $class = new ReflectionClass($model);
558: 
559:         $methods = array();
560: 
561:         while ($class) {
562:             $databaseToLdapMethod = '__' . $model->useDbConfig . $class->getName() . $suffix;
563: 
564:             if (method_exists(ConnectionManager::$config, $databaseToLdapMethod)) {
565:                 return new ReflectionMethod(ConnectionManager::$config, $databaseToLdapMethod);
566:             }
567: 
568:             $class = $class->getParentClass();
569:             $methods[] = $databaseToLdapMethod;
570:         }
571: 
572:         throw new Exception("Class \"" . get_class(ConnectionManager::$config) . "\" has no method " . print_r($methods, true));
573:     }
574: 
575:     public function buildDnByData(Model $model, $modelData) {
576:         $ldapData = $this->_toLdapData($model, $modelData);
577:         $dnAttribute = $this->_getModelConfig($model, 'dnAttribute');
578: 
579:         if (empty($ldapData[$dnAttribute])) {
580:             throw new Exception("Ldap data has no DN attribute \"$dnAttribute\"");
581:         }
582: 
583:         $modelDn = $this->_getModelWritableBaseDn($model);
584:         return LdapUtils::normalizeDn("$dnAttribute={$ldapData[$dnAttribute]}" . ($modelDn ? ',' . $modelDn : ''));
585:     }
586: 
587:     private function _getModelBaseDn(Model $model) {
588:         $modelDn = $this->_getModelConfig($model, 'relativeBaseDn');
589:         $dataSourceDn = $this->config['database'] ? $this->config['database'] : '';
590: 
591:         if ($modelDn && $dataSourceDn) {
592:             return LdapUtils::normalizeDn($modelDn . ',' . $dataSourceDn);
593:         } else {
594:             return LdapUtils::normalizeDn($modelDn . $dataSourceDn);
595:         }
596:     }
597:         
598:     private function _getModelWritableBaseDn(\Model $model) {
599:         return LdapUtils::joinDns(
600:                         $this->_getModelConfig($model, 'writableRelativeBaseDn', false, '')
601:                         , $this->_getModelBaseDn($model)
602:                 );
603:     }
604: 
605:     private function _getModelConfig(Model $model, $key, $required = true, $defaultValue = null) {
606:         $class = new ReflectionClass($model);
607: 
608:         while ($class) {
609:             if (isset($this->config['models'][$class->getName()][$key])) {
610:                 return $this->config['models'][$class->getName()][$key];
611:             }
612: 
613:             $class = $class->getParentClass();
614:         }
615: 
616:         if (!empty($this->_modelBaseConfig[$key])) {
617:             return $this->_modelBaseConfig[$key];
618:         }
619:         if ($required) {
620:             throw new Exception("No config '$key' defined for model \"{$model->name}\"");
621:         }
622:         else {
623:             return $defaultValue;
624:         }
625:     }
626: 
627:     private function _throwPhysicalConnectionException($message) {
628:         $errorCode = ldap_errno($this->connection);
629:         throw new Exception(
630:             ldap_err2str($errorCode) . " (Code: $errorCode)" .
631:             ($message ? "\n$message" : '')
632:         );
633:     }
634:     
635:     private function _rdnAttribute($dn) {
636:         if (($firstEqualsPosition = strpos($dn, '=')) === false) {
637:             throw new Exception("DN bad formatted: $dn");
638:         } else {
639:             return substr($dn, 0, $firstEqualsPosition);
640:         }
641:     }
642:     
643:     /**
644:      * 
645:      * @param type $dn
646:      * @param type $rdnValue
647:      * @return O novo valor do DN
648:      */
649:     private function _renameRdn($dn, $rdnValue) {
650:         $rdn = $this->_rdnAttribute($dn) . '=' . $rdnValue;   
651:         $parentDn = $this->_parentDn($dn);
652:         //$newDn = $this->_getRenamedDn($dn, $rdn)
653:         //$this->_throwPhysicalConnectionException(print_r(compact('dn','rdnValue','rdn', 'newDn'),true));
654:         if (ldap_rename(
655:                 $this->connection
656:                 , $dn
657:                 , $rdn
658:                 , $parentDn
659:                 , true
660:         )) {
661:             return $this->_getRenamedDn($dn, $rdn);
662:         } else {
663:             $this->_throwPhysicalConnectionException(print_r(compact('dn','rdnValue','rdn'),true));
664:         }
665:     }    
666:     
667:     private function _getRenamedDn($dn,$rdn) {
668:         return $rdn . ',' . $this->_parentDn($dn);
669:     }
670:     
671:     private function _parentDn($dn) {
672:         $parts = ldap_explode_dn($dn, 0);
673:         unset($parts['count']);
674:         array_shift($parts);        
675:         return implode(',', $parts);
676:     }
677: 
678:     private function _excludeDn($entries, $dn) {
679:         $dn = LdapUtils::normalizeDn($dn);
680:         $newEntries = array();
681:         for ($i = 0; $i < $entries['count']; $i++) {
682:             if ($this->_entryDn($entries[$i]) != $dn) {
683:                 $newEntries[] = $entries[$i];
684:             }
685:         }
686: 
687:         $newEntries['count'] = count($newEntries);
688:         return $newEntries;
689:     }
690: 
691:     private function _entryDn($entry) {
692:         foreach (array('dn', 'DN', 'Dn', 'dN') as $key) {
693:             if (isset($entry[$key])) {
694:                 return LdapUtils::normalizeDn($entry[$key]);
695:             }
696:         }
697: 
698:         throw new Exception("Entry has no DN attribute");
699:     }
700: 
701:     private function _previousLdapData($model, $modelData) {
702:         if (!empty($modelData[$model->primaryKey])) {
703:             $id = $modelData[$model->primaryKey];
704:         } /*else if (!empty($model->id)) {
705:             $id = $model->id;
706:         }*/
707: 
708:         if (!empty($id)) {
709:             $previousData = $model->find(
710:                 'first', array(
711:                 'conditions' => array(
712:                     "{$model->alias}.{$model->primaryKey}" => $id
713:                 )
714:                 ));
715: 
716:             $previousData = empty($previousData) ?
717:                 false :
718:                 $previousData[$model->alias];
719:         } else {
720:             $previousData = false;
721:         }
722: 
723:         return $previousData;
724:     }
725:     
726:     private function _throwExceptionIfIsNotWritable(\Model $model, $dn) {
727:         if (!$this->isWritable($model, $dn)) {
728:             throw new LdapObjectNotWritableException(
729:                     $model
730:                     , $dn
731:                     , $this->_getModelWritableBaseDn($model));
732:         }
733:     }
734:     
735:     public function isWritable(\Model $model, $dn) {
736:         return LdapUtils::isDnParent(
737:                         $this->_getModelWritableBaseDn($model)
738:                         , $dn
739:         );
740:     }
741: 
742: } // LdapSource
743: ?>
API documentation generated by ApiGen 2.8.0