2 /***************************************************************************
3 * Copyright (C) 2003-2010 Polytechnique.org *
4 * http://opensource.polytechnique.org/ *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
20 ***************************************************************************/
22 /** Class Address is meant to perform most of the access to the table profile_addresses.
24 * profile_addresses describes an Address, which can be related to either a
25 * Profile, a Job or a Company:
27 * - `type` is set to 'home'
28 * - `pid` is set to the related profile pid (in profiles)
29 * - `id` is the id of the address in the list of those related to that profile
30 * - `jobid` is set to 0
33 * - `type` is set to 'hq'
35 * - `jobid` is set to the id of the company (in profile_job_enum)
36 * - `id` is set to 0 (only one address per Company)
39 * - `type` is set to 'job'
40 * - `pid` is set to the pid of the Profile of the related Job (in both profiles and profile_job)
41 * - `id` is the id of the job to which we refer (in profile_job)
42 * - `jobid` is set to 0
44 * Thus an Address can be linked to a Company, a Profile, or a Job.
48 const LINK_JOB
= 'job';
49 const LINK_COMPANY
= 'hq';
50 const LINK_PROFILE
= 'home';
52 // Primary key fields: the quadruplet ($pid, $jobid, $type, $id) defines a unique address.
55 public $type = Address
::LINK_PROFILE
;
61 public $postalText = '';
62 public $postalCode = null
;
63 public $localityId = null
;
64 public $subAdministrativeAreaId = null
;
65 public $administrativeAreaId = null
;
66 public $localityName = null
;
67 public $subAdministrativeAreaName = null
;
68 public $administrativeAreaName = null
;
69 public $countryId = null
;
70 public $latitude = null
;
71 public $longitude = null
;
76 public $geocodedText = null
;
77 public $geocodedPostalText = null
;
78 public $geocodeChosen = null
;
80 // Database's field required for both 'home' and 'job' addresses.
81 public $pub = 'private';
83 // Database's fields required for 'home' addresses.
84 public $flags = null
; // 'current', 'temporary', 'secondary', 'mail', 'cedex'
85 public $comment = null
;
86 public $current = null
;
87 public $temporary = null
;
88 public $secondary = null
;
91 // Remaining fields that do not belong to profile_addresses.
92 public $phones = array();
93 public $error = false
;
97 public function __construct(array $data = array())
99 if (count($data) > 0) {
100 foreach ($data as $key => $val) {
105 if ($this->type
== self
::LINK_PROFILE
) {
106 if (!is_null($this->flags
)) {
107 $this->flags
= new PlFlagSet($this->flags
);
109 static $flags = array('current', 'temporary', 'secondary', 'mail');
111 $this->flags
= new PlFlagSet();
112 foreach ($flags as $flag) {
113 if (!is_null($this->$flag) && ($this->$flag == 1 ||
$this->$flag == 'on')) {
114 $this->flags
->addFlag($flag, 1);
117 $this->flags
->addFlag('cedex', (strpos(strtoupper(preg_replace(array("/[0-9,\"'#~:;_\- ]/", "/\r\n/"),
118 array('', "\n"), $this->text
)), 'CEDEX')) !== false
);
124 public function phones()
126 return $this->phones
;
129 public function addPhone(Phone
&$phone)
131 if ($phone->linkType() == Phone
::LINK_ADDRESS
&& $phone->pid() == $this->pid
) {
132 $this->phones
[$phone->uniqueId()] = $phone;
136 public function hasFlag($flag)
138 return ($this->flags
!= null
&& $this->flags
->hasFlag($flag));
141 public function format(array $format = array())
143 if (empty($format)) {
144 $format['requireGeocoding'] = false
;
145 $format['stripGeocoding'] = false
;
147 $this->text
= trim($this->text
);
148 if ($this->removed
== 1) {
153 if ($format['requireGeocoding'] ||
$this->changed
== 1) {
154 $gmapsGeocoder = new GMapsGeocoder();
155 $gmapsGeocoder->getGeocodedAddress($this);
157 $this->error
= !empty($this->geocodedText
);
159 if ($format['stripGeocoding'] ||
($this->type
== self
::LINK_COMPANY
&& $this->error
) ||
$this->geocodeChosen
=== '0') {
160 $gmapsGeocoder = new GMapsGeocoder();
161 $gmapsGeocoder->stripGeocodingFromAddress($this);
162 if ($this->geocodeChosen
=== '0') {
163 $mailer = new PlMailer('profile/geocoding.mail.tpl');
164 $mailer->assign('text', $this->text
);
165 $mailer->assign('geoloc', $this->geocodedText
);
169 if ($this->countryId
== '') {
170 $this->countryId
= null
;
172 $this->geocodeChosen
= null
;
173 $this->phones
= Phone
::formatFormArray($this->phones
, $this->error
);
174 return !$this->error
;
177 public function toFormArray()
180 'accuracy' => $this->accuracy
,
181 'text' => $this->text
,
182 'postalText' => $this->postalText
,
183 'postalCode' => $this->postalCode
,
184 'localityId' => $this->localityId
,
185 'subAdministrativeAreaId' => $this->subAdministrativeAreaId
,
186 'administrativeAreaId' => $this->administrativeAreaId
,
187 'countryId' => $this->countryId
,
188 'localityName' => $this->localityName
,
189 'subAdministrativeAreaName' => $this->subAdministrativeAreaName
,
190 'administrativeAreaName' => $this->administrativeAreaName
,
191 'latitude' => $this->latitude
,
192 'longitude' => $this->longitude
,
193 'north' => $this->north
,
194 'south' => $this->south
,
195 'east' => $this->east
,
196 'west' => $this->west
,
197 'error' => $this->error
,
198 'changed' => $this->changed
,
199 'removed' => $this->removed
,
201 if (!is_null($this->geocodedText
)) {
202 $address['geocodedText'] = $this->geocodedText
;
203 $address['geocodedPostalText'] = $this->geocodedPostalText
;
204 $address['geocodeChosen'] = $this->geocodeChosen
;
207 if ($this->type
== self
::LINK_PROFILE ||
$this->type
== self
::LINK_JOB
) {
208 $address['pub'] = $this->pub
;
210 if ($this->type
== self
::LINK_PROFILE
) {
211 static $flags = array('current', 'temporary', 'secondary', 'mail', 'cedex');
213 foreach ($flags as $flag) {
214 $address[$flag] = $this->flags
->hasFlag($flag);
216 $address['comment'] = $this->comment
;
217 $address['phones'] = Phone
::formatFormArray($this->phones
);
223 private function toString()
225 $address = 'Adresse : ' . $this->text
;
226 if ($this->type
== self
::LINK_PROFILE ||
$this->type
== self
::LINK_JOB
) {
227 $address .= ', affichage : ' . $this->pub
;
229 if ($this->type
== self
::LINK_PROFILE
) {
230 static $flags = array(
231 'current' => 'actuelle',
232 'temporary' => 'temporaire',
233 'secondary' => 'secondaire',
234 'mail' => 'conctactable par courier',
235 'cedex' => 'type cédex',
238 $address .= ', commentaire : ' . $this->comment
;
239 foreach ($flags as $flag => $flagName) {
240 if ($this->flags
->hasFlag($flag)) {
241 $address .= ', ' . $flagName;
244 if ($phones = Phone
::formArrayToString($this->phones
)) {
245 $address .= ', ' . $phones;
251 private function isEmpty()
253 return (!$this->text ||
$this->text
== '');
256 public function save()
258 static $areas = array('administrativeArea', 'subAdministrativeArea', 'locality');
261 if (!$this->isEmpty()) {
262 foreach ($areas as $area) {
263 Geocoder
::getAreaId($this, $area);
266 XDB
::execute('INSERT INTO profile_addresses (pid, jobid, type, id, flags, accuracy,
267 text, postalText, postalCode, localityId,
268 subAdministrativeAreaId, administrativeAreaId,
269 countryId, latitude, longitude, pub, comment,
270 north, south, east, west)
271 VALUES ({?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?},
272 {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?})',
273 $this->pid
, $this->jobid
, $this->type
, $this->id
, $this->flags
, $this->accuracy
,
274 $this->text
, $this->postalText
, $this->postalCode
, $this->localityId
,
275 $this->subAdministrativeAreaId
, $this->administrativeAreaId
,
276 $this->countryId
, $this->latitude
, $this->longitude
,
277 $this->pub
, $this->comment
,
278 $this->north
, $this->south
, $this->east
, $this->west
);
280 if ($this->type
== self
::LINK_PROFILE
) {
281 Phone
::savePhones($this->phones
, $this->pid
, Phone
::LINK_ADDRESS
, $this->id
);
286 static public function delete($pid, $type, $jobid = null
)
289 if (!is_null($pid)) {
290 $where = XDB
::format(' AND pid = {?}', $pid);
292 if (!is_null($jobid)) {
293 $where = XDB
::format(' AND jobid = {?}', $jobid);
295 XDB
::execute('DELETE FROM profile_addresses
296 WHERE type = {?}' . $where,
298 if ($type == self
::LINK_PROFILE
) {
299 Phone
::deletePhones($pid, Phone
::LINK_ADDRESS
);
303 /** Saves addresses into the database.
304 * @param $data: an array of form formatted addresses.
305 * @param $pid, $type, $linkid: pid, type and id concerned by the update.
307 static public function saveFromArray(array $data, $pid, $type = self
::LINK_PROFILE
, $linkid = null
)
309 foreach ($data as $id => $value) {
310 if (!is_null($linkid)) {
311 $value['id'] = $linkid;
315 if (!is_null($pid)) {
316 $value['pid'] = $pid;
318 if (!is_null($type)) {
319 $value['type'] = $type;
321 $address = new Address($value);
326 static private function formArrayWalk(array $data, $function, &$success = true
, $requiresEmptyAddress = false
)
328 $addresses = array();
329 foreach ($data as $item) {
330 $address = new Address($item);
331 $success = ($address->format() && $success);
332 if (!$address->isEmpty()) {
333 $addresses[] = call_user_func(array($address, $function));
336 if (count($address) == 0 && $requiresEmptyAddress) {
337 $address = new Address();
338 $addresses[] = call_user_func(array($address, $function));
343 // Formats an array of form addresses into an array of form formatted addresses.
344 static public function formatFormArray(array $data, &$success = true
)
346 // Only a single address can be the profile's current address and she must have one.
348 foreach ($data as $key => &$address) {
349 if (isset($address['current']) && $address['current']) {
351 $address['current'] = false
;
357 if (!$hasCurrent && count($value) > 0) {
358 foreach ($value as &$address) {
359 $address['current'] = true
;
364 return self
::formArrayWalk($data, 'toFormArray', $success, true
);
367 static public function formArrayToString(array $data)
369 return implode(' ; ', self
::formArrayWalk($data, 'toString'));
372 static public function iterate(array $pids = array(), array $types = array(),
373 array $jobids = array(), array $pubs = array())
375 return new AddressIterator($pids, $types, $jobids, $pubs);
379 /** Iterator over a set of Phones
381 * @param $pid, $type, $jobid, $pub
383 * The iterator contains the phones that correspond to the value stored in the
384 * parameters' arrays.
386 class AddressIterator
implements PlIterator
390 public function __construct(array $pids, array $types, array $jobids, array $pubs)
393 if (count($pids) != 0) {
394 $where[] = XDB
::format('(pa.pid IN {?})', $pids);
396 if (count($types) != 0) {
397 $where[] = XDB
::format('(pa.type IN {?})', $types);
399 if (count($jobids) != 0) {
400 $where[] = XDB
::format('(pa.jobid IN {?})', $jobids);
402 if (count($pubs) != 0) {
403 $where[] = XDB
::format('(pa.pub IN {?})', $pubs);
405 $sql = 'SELECT pa.pid, pa.jobid, pa.type, pa.id, pa.flags,
406 pa.accuracy, pa.text, pa.postalText, pa.postalCode,
407 pa.localityId, pa.subAdministrativeAreaId,
408 pa.administrativeAreaId, pa.countryId,
409 pa.latitude, pa.longitude, pa.north, pa.south, pa.east, pa.west,
411 gl.name AS locality, gs.name AS subAdministrativeArea,
412 ga.name AS administrativeArea, gc.countryFR AS country
413 FROM profile_addresses AS pa
414 LEFT JOIN geoloc_localities AS gl ON (gl.id = pa.localityId)
415 LEFT JOIN geoloc_administrativeareas AS ga ON (ga.id = pa.administrativeAreaId)
416 LEFT JOIN geoloc_subadministrativeareas AS gs ON (gs.id = pa.subAdministrativeAreaId)
417 LEFT JOIN geoloc_countries AS gc ON (gc.iso_3166_1_a2 = pa.countryId)
418 WHERE ' . implode(' AND ', $where) . '
419 ORDER BY pa.pid, pa.jobid, pa.id';
420 $this->dbiter
= XDB
::iterator($sql);
423 public function next()
425 if (is_null($this->dbiter
)) {
428 $data = $this->dbiter
->next();
429 if (is_null($data)) {
432 // Adds phones to addresses.
433 $it = Phone
::iterate(array($data['pid']), array(Phone
::LINK_ADDRESS
), array($data['id']));
434 while ($phone = $it->next()) {
435 $data['phones'][$phone->id()] = $phone->toFormArray();
437 return new Address($data);
440 public function total()
442 return $this->dbiter
->total();
445 public function first()
447 return $this->dbiter
->first();
450 public function last()
452 return $this->dbiter
->last();
455 public function value()
457 return $this->dbiter
;
461 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: