release 0.6.1
[bdrem.git] / src / bdrem / Source / Ldap.php
1 <?php
2 /**
3  * Part of bdrem
4  *
5  * PHP version 5
6  *
7  * @category  Tools
8  * @package   Bdrem
9  * @author    Christian Weiske <cweiske@cweiske.de>
10  * @copyright 2014 Christian Weiske
11  * @license   http://www.gnu.org/licenses/agpl.html GNU AGPL v3
12  * @link      http://cweiske.de/bdrem.htm
13  */
14 namespace bdrem;
15
16 /**
17  * Fetch data from an LDAP server.
18  * Works fine with evolutionPerson schema.
19  *
20  * @category  Tools
21  * @package   Bdrem
22  * @author    Christian Weiske <cweiske@cweiske.de>
23  * @copyright 2014 Christian Weiske
24  * @license   http://www.gnu.org/licenses/agpl.html GNU AGPL v3
25  * @link      http://cweiske.de/bdrem.htm
26  */
27 class Source_Ldap
28 {
29     /**
30      * LDAP server configuration
31      *
32      * Keys:
33      * - host   - LDAP server host name
34      * - basedn - root DN that gets searched
35      * - binddn - Username to authenticate with
36      * - bindpw - Password for username
37      *
38      * @var array
39      */
40     protected $config;
41
42     /**
43      * Create new ldap source
44      *
45      * @param array $config Array of Net_LDAP2 configuration parameters.
46      *                      Some of those you might want to use:
47      *                      - host   - LDAP server host name
48      *                      - basedn - root DN that gets searched
49      *                      - binddn - Username to authenticate with
50      *                      - bindpw - Password for username
51      */
52     public function __construct($config)
53     {
54         $this->config = $config;
55     }
56
57     /**
58      * Return all events for the given date range
59      *
60      * @param string  $strDate       Date the events shall be found for,
61      *                               YYYY-MM-DD
62      * @param integer $nDaysPrevious Include number of days before $strDate
63      * @param integer $nDaysNext     Include number of days after $strDate
64      *
65      * @return Event[] Array of matching event objects
66      */
67     public function getEvents($strDate, $nDaysPrevious, $nDaysNext)
68     {
69         //Net_LDAP2 is not E_STRICT compatible
70         error_reporting(error_reporting() & ~E_STRICT);
71
72         $ldap = \Net_LDAP2::connect($this->config);
73         if (\PEAR::isError($ldap)) {
74             throw new \Exception(
75                 'Could not connect to LDAP-server: ' . $ldap->getMessage()
76             );
77         }
78
79         $dateAttributes = array(
80             'birthDate'   => 'Birthday',
81             'anniversary' => 'Anniversary',
82         );
83
84         $arDays   = $this->getDates($strDate, $nDaysPrevious, $nDaysNext);
85         $arEvents = array();
86
87         foreach ($dateAttributes as $dateAttribute => $attributeTitle) {
88             $filters = array();
89             foreach ($arDays as $day) {
90                 $filters[] = \Net_LDAP2_Filter::create($dateAttribute, 'ends', $day);
91             }
92
93             if (count($filters) < 2) {
94                 $filter = $filters[0];
95             } else {
96                 $filter = \Net_LDAP2_Filter::combine('or', $filters);
97             }
98             $options = array(
99                 'scope'      => 'sub',
100                 'attributes' => array(
101                     'displayName', 'givenName', 'sn', 'cn', $dateAttribute
102                 )
103             );
104
105             $search = $ldap->search(null, $filter, $options);
106             if (!$search instanceof \Net_LDAP2_Search) {
107                 throw new \Exception(
108                     'Error searching LDAP: ' . $search->getMessage()
109                 );
110             } else if ($search->count() == 0) {
111                 continue;
112             }
113
114             while ($entry = $search->shiftEntry()) {
115                 $event = new Event(
116                     $this->getNameFromEntry($entry),
117                     $attributeTitle,
118                     $entry->getValue($dateAttribute, 'single')
119                 );
120                 if ($event->isWithin($strDate, $nDaysPrevious, $nDaysNext)) {
121                     $arEvents[] = $event;
122                 }
123             }
124         }
125
126         return $arEvents;
127     }
128
129     /**
130      * Extract the name from the given LDAP entry object.
131      * Uses displayName or givenName + sn
132      *
133      * @param object $entry LDAP entry
134      *
135      * @return string Name or NULL
136      */
137     protected function getNameFromEntry(\Net_LDAP2_Entry $entry)
138     {
139         $arEntry = $entry->getValues();
140         if (isset($arEntry['displayName'])) {
141             return $arEntry['displayName'];
142         } else if (isset($arEntry['sn']) && isset($arEntry['givenName'])) {
143             return $arEntry['givenName'] . ' ' . $arEntry['sn'];
144         } else if (isset($arEntry['cn'])) {
145             return $arEntry['cn'];
146         }
147         return null;
148     }
149
150     /**
151      * Create an array of dates that are included in the given range.
152      *
153      * @param string  $strDate       Date the events shall be found for,
154      *                               YYYY-MM-DD
155      * @param integer $nDaysPrevious Include number of days before $strDate
156      * @param integer $nDaysNext     Include number of days after $strDate
157      *
158      * @return array Values like "-01-24" ("-$month-$day")
159      */
160     protected function getDates($strDate, $nDaysPrevious, $nDaysNext)
161     {
162         $ts = strtotime($strDate) - 86400 * $nDaysPrevious;
163         $numDays = $nDaysPrevious + $nDaysNext;
164
165         $arDays = array();
166         do {
167             $arDays[] = date('-m-d', $ts);
168             $ts += 86400;
169         } while (--$numDays >= 0);
170         return $arDays;
171     }
172 }
173 ?>