root/trunk/wifidog-auth/wifidog/classes/Node.php @ 788

Revision 788, 47.2 KB (checked in by benoitg, 8 years ago)

it Gr�goire <bock@…>

  • Remove a bunch of deprecated methods from the Node object, document undocumented methods.
  • Make the node id editable. This allows the gateway "MAC address as node ID" patch by London wireless to be usable with the standard auth server, and to transition to using MAC address as node ID.
  • Fix a saving problem with all the content types with some versions of PHP
  • Add a new Content type: IFrameRest. This allows the result of a REST style query returning HTML to be displayed in a HTML iframeset. Currently supported are substitution of the node_id, the user_id and the last display date in the get query.
  • CVS version of the auth server should now be "reasonnably" safe to use in production, so the 2005-09-01 notice is no longuer in effect.
  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1<?php
2
3/********************************************************************\
4 * This program is free software; you can redistribute it and/or    *
5 * modify it under the terms of the GNU General Public License as   *
6 * published by the Free Software Foundation; either version 2 of   *
7 * the License, or (at your option) any later version.              *
8 *                                                                  *
9 * This program is distributed in the hope that it will be useful,  *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
12 * GNU General Public License for more details.                     *
13 *                                                                  *
14 * You should have received a copy of the GNU General Public License*
15 * along with this program; if not, contact:                        *
16 *                                                                  *
17 * Free Software Foundation           Voice:  +1-617-542-5942       *
18 * 59 Temple Place - Suite 330        Fax:    +1-617-542-2652       *
19 * Boston, MA  02111-1307,  USA       gnu@gnu.org                   *
20 *                                                                  *
21 \********************************************************************/
22/**@file Node.php
23 * @author Copyright (C) 2005 Benoit Grégoire <bock@step.polymtl.ca>
24 */
25
26require_once BASEPATH.'include/common.php';
27require_once 'User.php';
28require_once 'GisPoint.php';
29require_once 'AbstractGeocoder.php';
30require_once 'Utils.php';
31
32/** Abstract a Node.  A Node is an actual physical transmitter.
33 * @todo:  Make all the setter functions no-op if the value is the same as what
34 * was already stored Use setCustomPortalReduirectUrl as an example*/
35class Node implements GenericObject
36{
37        private $mRow;
38        private $mdB; /**< An AbstractDb instance */
39        private $id;
40        private static $current_node_id = null;
41
42        /** Instantiate a node object
43         * @param $id The id of the requested node
44         * @return a Node object, or null if there was an error
45         */
46        static function getObject($id)
47        {
48                $object = null;
49                $object = new self($id);
50                return $object;
51        }
52
53        /** Get the current node for which the portal is displayed or to which a user is physically connected.
54         * @param $real_node_only true or false.  If true, the real physical node where the user is connected is returned, and the node set by setCurrentNode is ignored.
55         * @return a Node object, or null if it can't be found.
56         */
57        static function getCurrentNode($real_node_only = false)
58        {
59                $object = null;
60                if (self :: $current_node_id != null && $real_node_only == false)
61                {
62                        $object = new self(self :: $current_node_id);
63                }
64                else
65                {
66                        $object = self :: getCurrentRealNode();
67                }
68                return $object;
69        }
70
71        /** Set the current node where the user is to be considered connected to.  (For portal and content display purpuses, among other.
72         * @param $node Node.  The new current node.
73         * @return true  */
74        static function setCurrentNode(Node $node)
75        {
76                self :: $current_node_id = $node->GetId();
77                return true;
78        }
79
80        /** Get the current node to which a user is physically connected, if any.  This is done by an IP adress lookup against the last reported IP adress of the node
81         * @param        * @return a Node object, or null if it can't be found.
82         */
83        public static function getCurrentRealNode()
84        {
85                global $db;
86                $retval = null;
87                $sql = "SELECT node_id, last_heartbeat_ip from nodes WHERE last_heartbeat_ip='$_SERVER[REMOTE_ADDR]' ORDER BY last_heartbeat_timestamp DESC";
88                $node_rows = null;
89                $db->ExecSql($sql, $node_rows, false);
90                $num_match = count($node_rows);
91                if ($num_match == 0)
92                {
93
94                        // User is not physically connected to a node
95                        $retval = null;
96                }
97                else
98                        if ($num_match = 1)
99                        {
100                                // Only a single node matches, the user is presumed to be there
101                                $retval = new self($node_rows[0]['node_id']);
102                        }
103                        else
104                        {
105                                /* We have more than one node matching the IP (the nodes are behind the same NAT).
106                                 * We will try to discriminate by finding which node the user last authenticated against.
107                                 * If the IP matches, we can be pretty certain the user is there.
108                                 */
109                                $retval = null;
110                                $current_user = User :: getCurrentUser();
111                                if ($current_user != null)
112                                {
113                                        $current_user_id = $current_user->getId();
114                                        $_SERVER['REMOTE_ADDR'];
115                                        $sql = "SELECT node_id, last_heartbeat_ip from connections NATURAL JOIN nodes WHERE user_id='$current_user_id' ORDER BY last_updated DESC ";
116                                        $db->ExecSql($sql, $node_rows, false);
117                                        $node_row = $node_rows[0];
118                                        if ($node_row != null && $node_row['last_heartbeat_ip'] == $_SERVER['REMOTE_ADDR'])
119                                        {
120                                                $retval = new self($node_row['node_id']);
121                                        }
122                                }
123                        }
124                return $retval;
125        }
126
127        public function delete(& $errmsg)
128        {
129                $retval = false;
130                $user = User :: getCurrentUser();
131                if ($this->isOwner($user) || $user->isSuperAdmin())
132                {
133                        global $db;
134                        $id = $db->EscapeString($this->getId());
135                        if (!$db->ExecSqlUpdate("DELETE FROM nodes WHERE node_id='{$id}'", false))
136                        {
137                                $errmsg = _('Could not delete node!');
138                        }
139                        else
140                        {
141                                $retval = true;
142                        }
143                }
144                else
145                {
146                        $errmsg = _('Access denied!');
147                }
148
149                return $retval;
150        }
151
152        /** Create a new Node in the database
153         * @param $node_id The id to be given to the new node.  If not present, a
154         * guid will be assigned.
155         * @param $network Network object.  The node's network.  If not present,
156         * the current Network will be assigned
157         *
158         * @return the newly created Node object, or null if there was an error
159         */
160        static function createNewObject($node_id = null, $network = null)
161        {
162                global $db;
163                if (empty ($node_id))
164                {
165                        $node_id = get_guid();
166                }
167                $node_id = $db->EscapeString($node_id);
168
169                if (empty ($network))
170                {
171                        $network = Network :: getCurrentNetwork();
172                }
173                $network_id = $db->EscapeString($network->getId());
174
175                $node_deployment_status = $db->EscapeString("IN_PLANNING");
176                $node_name = _("New node");
177                if (Node :: nodeExists($node_id))
178                        throw new Exception(_('This node already exists.'));
179
180                $sql = "INSERT INTO nodes (node_id, network_id, creation_date, node_deployment_status, name) VALUES ('$node_id', '$network_id', NOW(),'$node_deployment_status', '$node_name')";
181
182                if (!$db->ExecSqlUpdate($sql, false))
183                {
184                        throw new Exception(_('Unable to insert new node into database!'));
185                }
186                $object = new self($node_id);
187                return $object;
188        }
189
190        /** Get an interface to pick a node.
191        * @param $user_prefix A identifier provided by the programmer to recognise it's generated html form
192        * @param $sql_additional_where Addidional where conditions to restrict the candidate objects
193        * @return html markup
194        */
195        public static function getSelectNodeUI($user_prefix, $sql_additional_where = null)
196        {
197                global $db;
198                $html = '';
199                $name = "{$user_prefix}";
200                $html .= _("Node: ");
201                $sql = "SELECT node_id, name from nodes WHERE 1=1 $sql_additional_where ORDER BY node_id";
202                $node_rows = null;
203                $db->ExecSql($sql, $node_rows, false);
204                if ($node_rows != null)
205                {
206                        $i = 0;
207                        foreach ($node_rows as $node_row)
208                        {
209                                $tab[$i][0] = $node_row['node_id'];
210                                $tab[$i][1] = $node_row['node_id'].": ".$node_row['name'];
211                                $i ++;
212                        }
213                        $html .= FormSelectGenerator :: generateFromArray($tab, null, $name, null, false);
214                }
215                return $html;
216        }
217
218        /** Get the selected Network object.
219         * @param $user_prefix A identifier provided by the programmer to recognise it's generated form
220         * @return the node object
221         */
222        static function processSelectNodeUI($user_prefix)
223        {
224                $object = null;
225                $name = "{$user_prefix}";
226                return new self($_REQUEST[$name]);
227        }
228
229        /** Get an interface to create a new node.
230        * @param $network Optional:  The network to which the new node will belong,
231        * if absent, the user will be prompted.
232        * @return html markup
233        */
234        public static function getCreateNewObjectUI($network = null)
235        {
236                $html = '';
237                $html .= _("Create new node with id")." \n";
238                $name = "new_node_id";
239                $html .= "<input type='text' size='10' name='{$name}'>\n";
240                if ($network)
241                {
242                        $name = "new_node_network_id";
243                        $html .= "<input type='hidden' name='{$name}' value='{$network->getId()}'>\n";
244                }
245                else
246                {
247                        $html .= " "._("in network:")." \n";
248                        $html .= Network :: getSelectNetworkUI('new_node');
249                }
250                return $html;
251
252        }
253
254        /** Process the new object interface.
255         *  Will return the new object if the user has the credentials and the form was fully filled.
256         * @return the node object or null if no new node was created.
257         */
258        static function processCreateNewObjectUI()
259        {
260                $retval = null;
261                $name = "new_node_id";
262                if (!empty ($_REQUEST[$name]))
263                {
264                        $node_id = $_REQUEST[$name];
265                        $name = "new_node_network_id";
266                        if (!empty ($_REQUEST[$name]))
267                        {
268                                $network = Network :: getObject($_REQUEST[$name]);
269                        }
270                        else
271                        {
272                                $network = Network :: processSelectNetworkUI('new_node');
273                        }
274                        if ($node_id && $network)
275                        {
276                                if (!$network->hasAdminAccess(User :: getCurrentUser()))
277                                {
278                                        throw new Exception(_("Access denied"));
279                                }
280                                $retval = self :: createNewObject($node_id, $network);
281                        }
282                }
283                return $retval;
284        }
285
286        /** Get an interface to select the deployment status
287        * @param $user_prefix A identifier provided by the programmer to recognise it's generated html form
288        * @return html markup
289        */
290        public function getSelectDeploymentStatus($user_prefix)
291        {
292                global $db;
293                $html = '';
294                $name = "{$user_prefix}";
295                $status_list = null;
296                $db->ExecSql("SELECT node_deployment_status FROM node_deployment_status", $status_list, false);
297                if ($status_list == null)
298                        throw new Exception(_("No deployment statues  could be found in the database"));
299
300                        $tab = array ();
301                        foreach ($status_list as $status)
302                                $tab[] = array ($status['node_deployment_status'], $status['node_deployment_status']);
303                        $html .= FormSelectGenerator :: generateFromArray($tab, $this->getDeploymentStatus(), $name, null, false);
304                return $html;
305        }
306
307        /** Get the selected deployment status
308         * @param $user_prefix A identifier provided by the programmer to recognise it's generated form
309         * @return the deployment status
310         */
311        public function processSelectDeploymentStatus($user_prefix)
312        {
313                $object = null;
314                $name = "{$user_prefix}";
315                return $_REQUEST[$name];
316        }
317
318        /** @param $node_id The id of the node */
319        private function __construct($node_id)
320        {
321                global $db;
322                $this->mDb = & $db;
323
324                $node_id_str = $db->EscapeString($node_id);
325                $sql = "SELECT * FROM nodes WHERE node_id='$node_id_str'";
326                $row = null;
327                $db->ExecSqlUniqueRes($sql, $row, false);
328                if ($row == null)
329                {
330                        throw new Exception(_("The id $node_id_str could not be found in the database"));
331                }
332                $this->mRow = $row;
333                $this->id = $row['node_id'];
334        }
335
336        function getId()
337        {
338                return $this->id;
339        }
340
341/** Changing the id of a Node is supported.
342 *  Be carefull to anly call this when all other changes are processed,
343 * or the id used to generate the form names may no longer match.
344 * @param $id, string, the new node id.
345 * @return true on success, false on failure. Check this,
346 * as it's possible that someone will enter an existing id, especially
347 * if the MAC address is used and hardware is recycled.
348 */
349        function setId($id)
350        {
351                $id = $this->mDb->EscapeString($id);
352                $retval = $this->mDb->ExecSqlUpdate("UPDATE nodes SET node_id = '{$id}' WHERE node_id = '{$this->getId()}'");
353                if($retval)
354                {
355                $this->id = $id;
356                $this->refresh();
357                }
358                return $retval;
359        }
360       
361        /** Gets the Network to which the node belongs
362         * @return Network object (never returns null)
363         */
364        public function getNetwork()
365        {
366                return Network :: getObject($this->mRow['network_id']);
367        }
368
369        /** Get a GisPoint object ; altide is not supported yet
370         */
371        function getGisLocation()
372        {
373                // Altitude is not supported yet
374                return new GisPoint($this->mRow['latitude'], $this->mRow['longitude'], 0);
375        }
376
377        function setGisLocation($pt)
378        {
379                if (!empty ($pt))
380                {
381                        $lat = $this->mDb->EscapeString($pt->getLatitude());
382                        $long = $this->mDb->EscapeString($pt->getLongitude());
383
384                        if (!empty ($lat) && !empty ($long))
385                                $this->mDb->ExecSqlUpdate("UPDATE nodes SET latitude = $lat, longitude = $long WHERE node_id = '{$this->getId()}'");
386                        else
387                                $this->mDb->ExecSqlUpdate("UPDATE nodes SET latitude = NULL, longitude = NULL WHERE node_id = '{$this->getId()}'");
388                        $this->refresh();
389                }
390        }
391
392        /** Return the name of the node
393         */
394        function getName()
395        {
396                return $this->mRow['name'];
397        }
398
399        function setName($name)
400        {
401                $name = $this->mDb->EscapeString($name);
402                $this->mDb->ExecSqlUpdate("UPDATE nodes SET name = '{$name}' WHERE node_id = '{$this->getId()}'");
403                $this->refresh();
404        }
405
406        function getCreationDate()
407        {
408                return $this->mRow['creation_date'];
409        }
410
411        function getHomePageURL()
412        {
413                return $this->mRow['home_page_url'];
414        }
415
416        function setHomePageUrl($url)
417        {
418                $url = $this->mDb->EscapeString($url);
419                $this->mDb->ExecSqlUpdate("UPDATE nodes SET home_page_url = '{$url}' WHERE node_id = '{$this->getId()}'");
420                $this->refresh();
421        }
422
423        function getDescription()
424        {
425                return $this->mRow['description'];
426        }
427
428        function setDescription($description)
429        {
430                $description = $this->mDb->EscapeString($description);
431                $this->mDb->ExecSqlUpdate("UPDATE nodes SET description = '{$description}' WHERE node_id = '{$this->getId()}'");
432                $this->refresh();
433        }
434
435        function getMapURL()
436        {
437                return $this->mRow['map_url'];
438        }
439
440        function setMapURL($url)
441        {
442                $url = $this->mDb->EscapeString($url);
443                $this->mDb->ExecSqlUpdate("UPDATE nodes SET map_url = '{$url}' WHERE node_id = '{$this->getId()}'");
444                $this->refresh();
445        }
446
447        public function getCivicNumber()
448        {
449                return $this->mRow['civic_number'];
450        }
451
452        public function setCivicNumber($civic_number)
453        {
454                $civic_number = $this->mDb->EscapeString($civic_number);
455                $this->mDb->ExecSqlUpdate("UPDATE nodes SET civic_number = '{$civic_number}' WHERE node_id = '{$this->getId()}'");
456                $this->refresh();
457        }
458
459        public function getStreetName()
460        {
461                return $this->mRow['street_name'];
462        }
463
464        public function setStreetName($street_name)
465        {
466                $street_name = $this->mDb->EscapeString($street_name);
467                $this->mDb->ExecSqlUpdate("UPDATE nodes SET street_name = '{$street_name}' WHERE node_id = '{$this->getId()}'");
468                $this->refresh();
469        }
470
471        public function getCity()
472        {
473                return $this->mRow['city'];
474        }
475
476        public function setCity($city)
477        {
478                $city = $this->mDb->EscapeString($city);
479                $this->mDb->ExecSqlUpdate("UPDATE nodes SET city = '{$city}' WHERE node_id = '{$this->getId()}'");
480                $this->refresh();
481        }
482
483        public function getProvince()
484        {
485                return $this->mRow['province'];
486        }
487
488        public function setProvince($province)
489        {
490                $province = $this->mDb->EscapeString($province);
491                $this->mDb->ExecSqlUpdate("UPDATE nodes SET province = '{$province}' WHERE node_id = '{$this->getId()}'");
492                $this->refresh();
493        }
494
495        public function getCountry()
496        {
497                return $this->mRow['country'];
498        }
499
500        protected function setCountry($country)
501        {
502                $country = $this->mDb->EscapeString($country);
503                $this->mDb->ExecSqlUpdate("UPDATE nodes SET country = '{$country}' WHERE node_id = '{$this->getId()}'");
504                $this->refresh();
505        }
506
507        public function getPostalCode()
508        {
509                return $this->mRow['postal_code'];
510        }
511
512        public function setPostalCode($postal_code)
513        {
514                $postal_code = $this->mDb->EscapeString($postal_code);
515                $this->mDb->ExecSqlUpdate("UPDATE nodes SET postal_code = '{$postal_code}' WHERE node_id = '{$this->getId()}'");
516                $this->refresh();
517        }
518
519        function getTelephone()
520        {
521                return $this->mRow['public_phone_number'];
522        }
523
524        function setTelephone($phone)
525        {
526                $phone = $this->mDb->EscapeString($phone);
527                $this->mDb->ExecSqlUpdate("UPDATE nodes SET public_phone_number = '{$phone}' WHERE node_id = '{$this->getId()}'");
528                $this->refresh();
529        }
530
531        function getTransitInfo()
532        {
533                return $this->mRow['mass_transit_info'];
534        }
535
536        function setTransitInfo($transit_info)
537        {
538                $transit_info = $this->mDb->EscapeString($transit_info);
539                $this->mDb->ExecSqlUpdate("UPDATE nodes SET mass_transit_info = '{$transit_info}' WHERE node_id = '{$this->getId()}'");
540                $this->refresh();
541        }
542
543        function getEmail()
544        {
545                return $this->mRow['public_email'];
546        }
547
548        function setEmail($email)
549        {
550                $email = $this->mDb->EscapeString($email);
551                $this->mDb->ExecSqlUpdate("UPDATE nodes SET public_email = '{$email}' WHERE node_id = '{$this->getId()}'");
552                $this->refresh();
553        }
554
555        function getDeploymentStatus()
556        {
557                return $this->mRow['node_deployment_status'];
558        }
559
560        function setDeploymentStatus($status)
561        {
562                $status = $this->mDb->EscapeString($status);
563                $this->mDb->ExecSqlUpdate("UPDATE nodes SET node_deployment_status = '{$status}' WHERE node_id = '{$this->getId()}'");
564                $this->refresh();
565        }
566
567        function getLastPaged()
568        {
569                return $this->mRow['last_paged'];
570        }
571
572        function setLastPaged($last_paged)
573        {
574                $this->mDb->ExecSqlUpdate("UPDATE nodes SET last_paged = {$last_paged}::abstime WHERE node_id = '{$this->getId()}'");
575                $this->refresh();
576        }
577
578        function getLastHeartbeatIP()
579        {
580                return $this->mRow['last_heartbeat_ip'];
581        }
582
583        function getLastHeartbeatUserAgent()
584        {
585                return $this->mRow['last_heartbeat_user_agent'];
586        }
587
588        function getLastHeartbeatTimestamp()
589        {
590                return $this->mRow['last_heartbeat_timestamp'];
591        }
592
593        function setLastHeartbeatTimestamp($timestamp)
594        {
595                $this->mDb->ExecSqlUpdate("UPDATE nodes SET last_heartbeat_timestamp = '{$timestamp}' WHERE node_id = '{$this->getId()}'");
596                $this->refresh();
597        }
598
599        /** Is the node a Splash Only node?  Will only return true if the Network configuration allows it.
600         * @return true or false */
601        public function isSplashOnly()
602        {
603                return $this->getNetwork()->getSplashOnlyNodesAllowed() && $this->isConfiguredSplashOnly();
604        }
605
606        /** Is the node configured as a Splash Only node?  This is NOT the same as isSplashOnly(). 
607         * This is the getter for the configuration set in the database for this node. 
608         * For the node to actually be splash only, this AND the network
609         * gonfiguration must match.
610         * @return true or false */
611        public function isConfiguredSplashOnly()
612        {
613                return (($this->mRow['is_splash_only_node'] == 't') ? true : false);
614        }
615
616        /** Set if this node should be a splash-only (no login) node (if enabled in Network configuration)
617         * @param $value The new value, true or false
618         * @return true on success, false on failure */
619        function setIsConfiguredSplashOnly($value)
620        {
621                $retval = true;
622                if ($value != $this->isConfiguredSplashOnly())
623                {
624                        global $db;
625                        $value ? $value = 'TRUE' : $value = 'FALSE';
626                        $retval = $db->ExecSqlUpdate("UPDATE nodes SET is_splash_only_node = {$value} WHERE node_id = '{$this->getId()}'", false);
627                        $this->refresh();
628                }
629                return $retval;
630        }
631
632        /** The url to show instead of the portal.  If empty, the portal is shown
633         Must be enabled in the Network configuration to have any effect
634         @return a string */
635        function getCustomPortalRedirectUrl()
636        {
637                return $this->mRow['custom_portal_redirect_url'];
638        }
639
640        /** The url to show instead of the portal.  If empty, the portal is shown
641         Must be enabled in the Network configuration to have any effect
642         @return true on success, false on failure */
643        function setCustomPortalRedirectUrl($value)
644        {
645                $retval = true;
646                if ($value != $this->getCustomPortalRedirectUrl())
647                {
648                        global $db;
649                        $value = $db->EscapeString($value);
650                        $retval = $db->ExecSqlUpdate("UPDATE nodes SET custom_portal_redirect_url = '{$value}' WHERE node_id = '{$this->getId()}'", false);
651                        $this->refresh();
652                }
653                return $retval;
654        }
655
656        /** Retrieves the admin interface of this object.
657         * @return The HTML fragment for this interface */
658        public function getAdminUI()
659        {
660                //TODO: Most of this code will be moved to Hotspot class when the abtraction will be completed
661
662                //pretty_print_r($_REQUEST);
663                //pretty_print_r($this->mRow);
664                $html = '';
665                $html .= "<div class='admin_container'>\n";
666                $html .= "<div class='admin_class'>Node (".get_class($this)." instance)</div>\n";
667                $html .= "<h3>"._("Edit a node")."</h3>\n";
668
669                // Display stats
670                $html .= "<div class='admin_section_container'>\n";
671                $html .= "<div class='admin_section_title'>"._("Statistics:")."</div>\n";
672                $html .= "<div class='admin_section_data'>\n";
673                $name = "node_".$this->id."_get_stats";
674                $html .= "<input type='submit' name='$name' value='"._("Get access statistics")."'>";
675                $html .= "</div>\n";
676                $html .= "</div>\n";
677
678                // Information about the node
679                $html .= "<div class='admin_section_container'>\n";
680                $html .= "<div class='admin_section_title'>"._("Information about the node:")."</div>\n";
681
682
683                // Hashed node_id (this is a workaround since PHP auto-converts HTTP vars var periods, spaces or underscores )
684                $hashed_node_id = md5($this->getId());
685
686                // Node ID
687                $value = htmlspecialchars($this->getId(), ENT_QUOTES);
688                $html .= "<div class='admin_section_container'>\n";
689                $html .= "<div class='admin_section_title'>"._("ID")." : </div>\n";
690                $html .= "<div class='admin_section_data'>\n";
691                $name = "node_".$hashed_node_id."_id";
692                $html .= "<input type='text' size='20' value='$value' name='$name'>\n";
693                $html .= "</div>\n";
694                $html .= "</div>\n";
695
696                // Name
697                $html .= "<div class='admin_section_container'>\n";
698                $html .= "<div class='admin_section_title'>"._("Name")." : </div>\n";
699                $html .= "<div class='admin_section_data'>\n";
700                $name = "node_".$hashed_node_id."_name";
701                $value = htmlspecialchars($this->getName(), ENT_QUOTES);
702                $html .= "<input type='text' size ='50' value='$value' name='$name'>\n";
703                $html .= "</div>\n";
704                $html .= "</div>\n";
705
706                // Homepage URL
707                $html .= "<div class='admin_section_container'>\n";
708                $html .= "<div class='admin_section_title'>"._("Homepage URL")." : </div>\n";
709                $html .= "<div class='admin_section_data'>\n";
710                $name = "node_".$hashed_node_id."_homepage_url";
711                $value = htmlspecialchars($this->getHomePageURL(), ENT_QUOTES);
712                $html .= "<input type='text' size ='50' value='$value' name='$name'>\n";
713                $html .= "</div>\n";
714                $html .= "</div>\n";
715
716                // Description
717                $html .= "<div class='admin_section_container'>\n";
718                $html .= "<div class='admin_section_title'>"._("Description")." : </div>\n";
719                $html .= "<div class='admin_section_data'>\n";
720                $name = "node_".$hashed_node_id."_description";
721                $value = htmlspecialchars($this->getDescription(), ENT_QUOTES);
722                $html .= "<textarea cols='50' rows='5' name='$name'>$value</textarea>\n";
723                $html .= "</div>\n";
724                $html .= "</div>\n";
725
726                // Map URL
727                $html .= "<div class='admin_section_container'>\n";
728                $html .= "<div class='admin_section_title'>"._("Map URL")." : </div>\n";
729                $html .= "<div class='admin_section_data'>\n";
730                $name = "node_".$hashed_node_id."_map_url";
731                $value = htmlspecialchars($this->getMapURL(), ENT_QUOTES);
732                $html .= "<input type='text' size ='50' value='$value' name='$name'>\n";
733                $html .= "</div>\n";
734                $html .= "</div>\n";
735
736                // Civic number
737                $html .= "<div class='admin_section_container'>\n";
738                $html .= "<div class='admin_section_title'>"._("Civic number")." : </div>\n";
739                $html .= "<div class='admin_section_data'>\n";
740                $name = "node_".$hashed_node_id."_civic_number";
741                $value = htmlspecialchars($this->getCivicNumber(), ENT_QUOTES);
742                $html .= "<input type='text' size ='10' value='$value' name='$name'>\n";
743                $html .= "</div>\n";
744                $html .= "</div>\n";
745
746                // Street name
747                $html .= "<div class='admin_section_container'>\n";
748                $html .= "<div class='admin_section_title'>"._("Street name")." : </div>\n";
749                $html .= "<div class='admin_section_data'>\n";
750                $name = "node_".$hashed_node_id."_street_name";
751                $value = htmlspecialchars($this->getStreetName(), ENT_QUOTES);
752                $html .= "<input type='text' size ='25' value='$value' name='$name'>\n";
753                $html .= "</div>\n";
754                $html .= "</div>\n";
755
756                // City
757                $html .= "<div class='admin_section_container'>\n";
758                $html .= "<div class='admin_section_title'>"._("City")." : </div>\n";
759                $html .= "<div class='admin_section_data'>\n";
760                $name = "node_".$hashed_node_id."_city";
761                $value = htmlspecialchars($this->getCity(), ENT_QUOTES);
762                $html .= "<input type='text' size ='25' value='$value' name='$name'>\n";
763                $html .= "</div>\n";
764                $html .= "</div>\n";
765
766                // Province
767                $html .= "<div class='admin_section_container'>\n";
768                $html .= "<div class='admin_section_title'>"._("Province / State")." : </div>\n";
769                $html .= "<div class='admin_section_data'>\n";
770                $name = "node_".$hashed_node_id."_province";
771                $value = htmlspecialchars($this->getProvince(), ENT_QUOTES);
772                $html .= "<input type='text' size ='15' value='$value' name='$name'>\n";
773                $html .= "</div>\n";
774                $html .= "</div>\n";
775
776                // Postal Code
777                $html .= "<div class='admin_section_container'>\n";
778                $html .= "<div class='admin_section_title'>"._("Postal code")." : </div>\n";
779                $html .= "<div class='admin_section_data'>\n";
780                $name = "node_".$hashed_node_id."_postal_code";
781                $value = htmlspecialchars($this->getPostalCode(), ENT_QUOTES);
782                $html .= "<input type='text' size ='10' value='$value' name='$name'>\n";
783                $html .= "</div>\n";
784                $html .= "</div>\n";
785
786                // Country
787                $html .= "<div class='admin_section_container'>\n";
788                $html .= "<div class='admin_section_title'>"._("Country")." : </div>\n";
789                $html .= "<div class='admin_section_data'>\n";
790                $name = "node_".$hashed_node_id."_country";
791                $value = htmlspecialchars($this->getCountry(), ENT_QUOTES);
792                $html .= "<input type='text' size ='15' value='$value' name='$name'>\n";
793                $html .= "</div>\n";
794                $html .= "</div>\n";
795
796                // Public phone #
797                $html .= "<div class='admin_section_container'>\n";
798                $html .= "<div class='admin_section_title'>"._("Public phone number")." : </div>\n";
799                $html .= "<div class='admin_section_data'>\n";
800                $name = "node_".$hashed_node_id."_public_phone";
801                $value = htmlspecialchars($this->getTelephone(), ENT_QUOTES);
802                $html .= "<input type='text' size ='20' value='$value' name='$name'>\n";
803                $html .= "</div>\n";
804                $html .= "</div>\n";
805
806                // Public mail
807                $html .= "<div class='admin_section_container'>\n";
808                $html .= "<div class='admin_section_title'>"._("Public email")." : </div>\n";
809                $html .= "<div class='admin_section_data'>\n";
810                $name = "node_".$hashed_node_id."_public_email";
811                $value = htmlspecialchars($this->getEmail(), ENT_QUOTES);
812                $html .= "<input type='text' size ='50' value='$value' name='$name'>\n";
813                $html .= "</div>\n";
814                $html .= "</div>\n";
815
816                // Mass transit info
817                $html .= "<div class='admin_section_container'>\n";
818                $html .= "<div class='admin_section_title'>"._("Mass transit info")." : </div>\n";
819                $html .= "<div class='admin_section_data'>\n";
820                $name = "node_".$hashed_node_id."_mass_transit_info";
821                $value = htmlspecialchars($this->getTransitInfo(), ENT_QUOTES);
822                $html .= "<input type='text' size ='50' value='$value' name='$name'>\n";
823                $html .= "</div>\n";
824                $html .= "</div>\n";
825
826                // End of information section
827                $html .= "</div>\n";
828
829                // Node GIS data
830                $html .= "<div class='admin_section_container'>\n";
831                $html .= "<div class='admin_section_title'>"._("GIS data")." : </div>\n";
832
833                // Build HTML form fields names & values
834                $gis_point = $this->getGisLocation();
835                $gis_lat_name = "node_".$hashed_node_id."_gis_latitude";
836                $gis_lat_value = htmlspecialchars($gis_point->getLatitude(), ENT_QUOTES);
837                $gis_long_name = "node_".$hashed_node_id."_gis_longitude";
838                $gis_long_value = htmlspecialchars($gis_point->getLongitude(), ENT_QUOTES);
839
840                $html .= "<div class='admin_section_container'>\n";
841                $html .= "<div class='admin_section_title'>"._("Latitude")." : </div>\n";
842                $html .= "<div class='admin_section_data'>\n";
843                $html .= "<input type='text' size ='15' value='$gis_lat_value' id='$gis_lat_name' name='$gis_lat_name'>\n";
844                $html .= "</div>\n";
845                $html .= "</div>\n";
846
847                $html .= "<div class='admin_section_container'>\n";
848                $html .= "<div class='admin_section_title'>"._("Longitude")." : </div>\n";
849                $html .= "<div class='admin_section_data'>\n";
850                $html .= "<input type='text' size ='15' value='$gis_long_value' id='$gis_long_name' name='$gis_long_name'>\n";
851                $html .= "</div>\n";
852                $html .= "</div>\n";
853
854                /*
855                 * If Google Maps is enabled, call the geocoding service,
856                 * then use Google Maps to let the user choose a more precise location
857                 *
858                 * otherwise
859                 *
860                 * Simply use a geocoding service.
861                 */
862
863                if (defined('GMAPS_HOTSPOTS_MAP_ENABLED') && GMAPS_HOTSPOTS_MAP_ENABLED === true)
864                {
865                        $html .= "<div class='admin_section_container'>\n";
866                        $html .= "<div class='admin_section_data'>\n";
867                        $html .= "<input type='submit' name='geocode_only' value='"._("Geocode only")."'>\n";
868                        $html .= "<input type='button' name='google_maps_geocode' value='"._("Check using Google Maps")."' onClick='window.open(\"hotspot_location_map.php?node_id={$this->getId()}\", \"hotspot_location\", \"toolbar=0,scrollbars=1,resizable=1,location=0,statusbar=0,menubar=0,width=600,height=600\");'>\n";
869                        $html .= " ("._("Use a geocoding service, then use Google Maps to pinpoint the exact location.").")";
870                        $html .= "</div>\n";
871                        $html .= "</div>\n";
872                }
873                else
874                {
875                        $html .= "<div class='admin_section_container'>\n";
876                        $html .= "<div class='admin_section_data'>\n";
877                        $html .= "<input type='submit' name='geocode_only' value='"._("Geocode location")."'>\n";
878                        $html .= " ("._("Use a geocoding service").")";
879                        $html .= "</div>\n";
880                        $html .= "</div>\n";
881                }
882
883                // End of GIS data
884                $html .= "</div>\n";
885
886                // Node configuration section
887                $html .= "<div class='admin_section_container'>\n";
888                $html .= "<div class='admin_section_title'>"._("Node configuration:")."</div>\n";
889
890                $network = $this->getNetwork();
891
892                // Deployment status
893                $html .= "<div class='admin_section_container'>\n";
894                $html .= "<div class='admin_section_title'>"._("Node deployment status")." : </div>\n";
895                $html .= "<div class='admin_section_data'>\n";
896                $name = "node_".$hashed_node_id."_deployment_status";
897                $html .= self :: getSelectDeploymentStatus($name);
898                $html .= "</div>\n";
899                $html .= "</div>\n";
900
901                //  is_splash_only_node
902                if ($network->getSplashOnlyNodesAllowed())
903                {
904                        $html .= "<div class='admin_section_container'>\n";
905                        $html .= "<div class='admin_section_title'>"._("Is this node splash-only (no login)?")." : </div>\n";
906                        $html .= "<div class='admin_section_data'>\n";
907                        $name = "node_".$hashed_node_id."_is_splash_only_node";
908                        $this->isConfiguredSplashOnly() ? $checked = 'CHECKED' : $checked = '';
909                        $html .= "<input type='checkbox' name='$name' $checked>\n";
910                        $html .= "</div>\n";
911                        $html .= "</div>\n";
912                }
913
914                // custom_portal_redirect_url
915                if ($network->getCustomPortalRedirectAllowed())
916                {
917                        $html .= "<div class='admin_section_container'>\n";
918                        $html .= "<div class='admin_section_title'>"._("URL to show instead of the portal (if this is not empty, the portal will be disabled and this URL will be shown instead)")." : </div>\n";
919                        $html .= "<div class='admin_section_data'>\n";
920                        $name = "node_".$hashed_node_id."_custom_portal_redirect_url";
921                        $value = htmlspecialchars($this->getCustomPortalRedirectUrl(), ENT_QUOTES);
922                        $html .= "<input type='text' size ='50' value='$value' name='$name'>\n";
923                        $html .= "</div>\n";
924                        $html .= "</div>\n";
925                }
926                // End Node configuration section
927                $html .= "</div>\n";
928
929                // Owners management
930                $html .= "<div class='admin_section_container'>\n";
931                $html .= "<div class='admin_section_title'>"._("Node owners")." : </div>\n";
932                $html .= "<ul class='admin_section_list'>\n";
933                foreach ($this->getOwners() as $owner)
934                {
935                        $html .= "<li class='admin_section_list_item'>\n";
936                        $html .= "<div class='admin_section_data'>\n";
937                        $html .= "{$owner->getUsername()}";
938                        $html .= "</div>\n";
939                        $html .= "<div class='admin_section_tools'>\n";
940                        $name = "node_{$this->getId()}_owner_{$owner->GetId()}_remove";
941                        $html .= "<input type='submit' name='$name' value='"._("Remove owner")."'>";
942                        $html .= "</div>\n";
943                        $html .= "</li>\n";
944                }
945                $html .= "<li class='admin_section_list_item'>\n";
946                $name = "node_{$this->getId()}_new_owner";
947                $html .= User :: getSelectUserUI($name);
948                $name = "node_{$this->getId()}_new_owner_submit";
949                $html .= "<input type='submit' name='$name' value='"._("Add owner")."'>";
950                $html .= "</li>\n";
951                $html .= "</ul>\n";
952                $html .= "</div>\n";
953                $html .= "</div>\n";
954
955                // Tech officers management
956                $html .= "<div class='admin_section_container'>\n";
957                $html .= "<div class='admin_section_title'>"._("Technical officers")." : </div>\n";
958                $html .= "<ul class='admin_section_list'>\n";
959                foreach ($this->getTechnicalOfficers() as $tech_officer)
960                {
961                        $html .= "<li class='admin_section_list_item'>\n";
962                        $html .= "<div class='admin_section_data'>\n";
963                        $html .= "{$tech_officer->getUsername()}";
964                        $html .= "</div>\n";
965                        $html .= "<div class='admin_section_tools'>\n";
966                        $name = "node_{$this->getId()}_tech_officer_{$tech_officer->GetId()}_remove";
967                        $html .= "<input type='submit' name='$name' value='"._("Remove technical officer")."'>";
968                        $html .= "</div>\n";
969                        $html .= "</li>\n";
970                }
971                $html .= "<li class='admin_section_list_item'>\n";
972                $name = "node_{$this->getId()}_new_tech_officer";
973                $html .= User :: getSelectUserUI($name);
974                $name = "node_{$this->getId()}_new_tech_officer_submit";
975                $html .= "<input type='submit' name='$name' value='"._("Add technical officer")."'>";
976                $html .= "</li>\n";
977                $html .= "</ul>\n";
978                $html .= "</div>\n";
979                $html .= "</div>\n";
980
981/* Node content */
982                $html .= "<div class='admin_section_container'>\n";
983                $html .= "<div class='admin_section_title'>"._("Node content (login):")."</div>\n";
984                $name = "node_{$this->id}_content_login";
985$html .= Content::getLinkedContentUI($name, 'node_has_content', 'node_id', $this->id, $display_location = 'login_page');
986                $html .= "</div>\n";
987               
988                $html .= "<div class='admin_section_container'>\n";
989                $html .= "<div class='admin_section_title'>"._("Node content (portal):")."</div>\n";
990                $name = "node_{$this->id}_content_portal";
991$html .= Content::getLinkedContentUI($name, 'node_has_content', 'node_id', $this->id, $display_location = 'portal_page');
992                $html .= "</div>\n";
993
994                return $html;
995        }
996
997        /** Process admin interface of this object.
998        */
999        public function processAdminUI()
1000        {
1001                $user = User :: getCurrentUser();
1002                if (!$this->isOwner($user) && !$user->isSuperAdmin())
1003                {
1004                        throw new Exception(_('Access denied!'));
1005                }
1006
1007                // Information about the node
1008
1009                // Hashed node_id (this is a workaround since PHP auto-converts HTTP vars var periods, spaces or underscores )
1010                $hashed_node_id = md5($this->getId());
1011
1012                // Name
1013                $name = "node_".$hashed_node_id."_name";
1014                $this->setName($_REQUEST[$name]);
1015
1016                // Homepage URL
1017                $name = "node_".$hashed_node_id."_homepage_url";
1018                $this->setHomePageUrl($_REQUEST[$name]);
1019
1020                // Description
1021                $name = "node_".$hashed_node_id."_description";
1022                $this->setDescription($_REQUEST[$name]);
1023
1024                // Map URL
1025                $name = "node_".$hashed_node_id."_map_url";
1026                $this->setMapUrl($_REQUEST[$name]);
1027
1028                // Civic number
1029                $name = "node_".$hashed_node_id."_civic_number";
1030                $this->setCivicNumber($_REQUEST[$name]);
1031
1032                // Street name
1033                $name = "node_".$hashed_node_id."_street_name";
1034                $this->setStreetName($_REQUEST[$name]);
1035
1036                // City
1037                $name = "node_".$hashed_node_id."_city";
1038                $this->setCity($_REQUEST[$name]);
1039
1040                // Province
1041                $name = "node_".$hashed_node_id."_province";
1042                $this->setProvince($_REQUEST[$name]);
1043
1044                // Postal Code
1045                $name = "node_".$hashed_node_id."_postal_code";
1046                $this->setPostalCode($_REQUEST[$name]);
1047
1048                // Country
1049                $name = "node_".$hashed_node_id."_country";
1050                $this->setCountry($_REQUEST[$name]);
1051
1052                // Public phone #
1053                $name = "node_".$hashed_node_id."_public_phone";
1054                $this->setTelephone($_REQUEST[$name]);
1055
1056                // Public mail
1057                $name = "node_".$hashed_node_id."_public_email";
1058                $this->setEmail($_REQUEST[$name]);
1059
1060                // Mass transit info
1061                $name = "node_".$hashed_node_id."_mass_transit_info";
1062                $this->setTransitInfo($_REQUEST[$name]);
1063
1064                // GIS data
1065                // Get a geocoder for a given country
1066                if (!empty ($_REQUEST['geocode_only']))
1067                {
1068                        $geocoder = AbstractGeocoder :: getGeocoder($this->getCountry());
1069                        if ($geocoder != null)
1070                        {
1071                                $geocoder->setCivicNumber($this->getCivicNumber());
1072                                $geocoder->setStreetName($this->getStreetName());
1073                                $geocoder->setCity($this->getCity());
1074                                $geocoder->setProvince($this->getProvince());
1075                                $geocoder->setPostalCode($this->getPostalCode());
1076                                if ($geocoder->validateAddress() === true)
1077                                {
1078                                        if (($point = $geocoder->getGisLocation()) !== null)
1079                                                $this->setGisLocation($point);
1080                                        else
1081                                                echo _("It appears that the Geocoder could not be reached or could not geocode the given address.");
1082                                }
1083                                else
1084                                        echo _("You must enter a valid address.");
1085                        }
1086                }
1087                else
1088                {
1089                        // Use what has been set by the user.   
1090                        $gis_lat_name = "node_".$hashed_node_id."_gis_latitude";
1091                        $gis_long_name = "node_".$hashed_node_id."_gis_longitude";
1092                        $this->setGisLocation(new GisPoint($_REQUEST[$gis_lat_name], $_REQUEST[$gis_long_name], .0));
1093                }
1094
1095                // Statistics
1096                $name = "node_{$this->id}_get_stats";
1097                if (!empty ($_REQUEST[$name]))
1098                        header("Location: stats.php?node_id=".urlencode($this->getId()));
1099
1100                // Node configuration section
1101
1102                $network = $this->getNetwork();
1103
1104                // Deployment status
1105                $name = "node_".$hashed_node_id."_deployment_status";
1106                $this->setDeploymentStatus(self :: processSelectDeploymentStatus($name));
1107
1108                //  is_splash_only_node
1109                if ($network->getSplashOnlyNodesAllowed())
1110                {
1111                        $name = "node_".$hashed_node_id."_is_splash_only_node";
1112                        $this->setIsConfiguredSplashOnly(empty ($_REQUEST[$name]) ? false : true);
1113                }
1114
1115                // custom_portal_redirect_url
1116                if ($network->getCustomPortalRedirectAllowed())
1117                {
1118                        $name = "node_".$hashed_node_id."_custom_portal_redirect_url";
1119                        $this->setCustomPortalRedirectUrl($_REQUEST[$name]);
1120                }
1121
1122                // End Node configuration section
1123
1124                // Owners processing
1125                // Rebuild user id, and delete if it was selected
1126                foreach ($this->getOwners() as $owner)
1127                {
1128                        $name = "node_{$this->getId()}_owner_{$owner->GetId()}_remove";
1129                        if (!empty ($_REQUEST[$name]))
1130                        {
1131                                if ($this->isOwner($owner))
1132                                        $this->removeOwner($owner);
1133                                else
1134                                        echo _("Invalid user!");
1135                        }
1136                }
1137
1138                $name = "node_{$this->getId()}_new_owner_submit";
1139                if (!empty ($_REQUEST[$name]))
1140                {
1141                        $name = "node_{$this->getId()}_new_owner";
1142                        $owner = User :: processSelectUserUI($name);
1143                        if ($owner)
1144                        {
1145                                if ($this->isOwner($owner))
1146                                        echo _("The user is already an owner of this node.");
1147                                else
1148                                        $this->addOwner($owner);
1149                        }
1150                }
1151
1152                // Technical officers processing
1153                // Rebuild user id, and delete if it was selected
1154                foreach ($this->getTechnicalOfficers() as $tech_officer)
1155                {
1156                        $name = "node_{$this->getId()}_tech_officer_{$tech_officer->GetId()}_remove";
1157                        if (!empty ($_REQUEST[$name]))
1158                        {
1159                                if ($this->isTechnicalOfficer($tech_officer))
1160                                        $this->removeTechnicalOfficer($tech_officer);
1161                                else
1162                                        echo _("Invalid user!");
1163                        }
1164                }
1165
1166                $name = "node_{$this->getId()}_new_tech_officer_submit";
1167                if (!empty ($_REQUEST[$name]))
1168                {
1169                        $name = "node_{$this->getId()}_new_tech_officer";
1170                        $tech_officer = User :: processSelectUserUI($name);
1171                        if ($tech_officer)
1172                        {
1173                                if ($this->isTechnicalOfficer($tech_officer))
1174                                        echo _("The user is already a technical officer of this node.");
1175                                else
1176                                        $this->addTechnicalOfficer($tech_officer);
1177                        }
1178                }
1179
1180                // Content processing
1181                $name = "node_{$this->id}_content_login";
1182                Content::processLinkedContentUI($name, 'node_has_content', 'node_id', $this->id);
1183                                $name = "node_{$this->id}_content_portal";
1184Content::processLinkedContentUI($name, 'node_has_content', 'node_id', $this->id);
1185
1186                // Name
1187                $name = "node_".$hashed_node_id."_id";
1188                $this->setId($_REQUEST[$name]);
1189                                        }
1190
1191        // Redirect to this node's portal page
1192        public function getUserUI()
1193        {
1194                header("Location: ".BASE_SSL_PATH."portal/?gw_id=".$this->getId());
1195        }
1196
1197        /** Add content to this node */
1198        public function addContent(Content $content)
1199        {
1200                global $db;
1201                $content_id = $db->EscapeString($content->getId());
1202                $sql = "INSERT INTO node_has_content (node_id, content_id) VALUES ('$this->id','$content_id')";
1203                $db->ExecSqlUpdate($sql, false);
1204        }
1205
1206        /** Remove content from this node */
1207        public function removeContent(Content $content)
1208        {
1209                global $db;
1210                $content_id = $db->EscapeString($content->getId());
1211                $sql = "DELETE FROM node_has_content WHERE node_id='$this->id' AND content_id='$content_id'";
1212                $db->ExecSqlUpdate($sql, false);
1213        }
1214
1215        /**Get an array of all Content linked to this node
1216         * @param boolean $exclude_subscribed_content
1217        * @param User $subscriber The User object used to discriminate the content
1218        * @param $display_location Only select the content to be displayed in thios
1219        * area.  Defaults to 'portal_page'
1220        * @return an array of Content or an empty arrray */
1221        function getAllContent($exclude_subscribed_content = false, $subscriber = null, $display_location='portal_page')
1222        {
1223                global $db;
1224                $retval = array ();
1225                $content_rows = null;
1226                // Get all network, but exclude user subscribed content if asked
1227                if ($exclude_subscribed_content == true && $subscriber)
1228                        $sql = "SELECT content_id FROM node_has_content WHERE node_id='{$this->id}' AND display_location='$display_location' AND content_id NOT IN (SELECT content_id FROM user_has_content WHERE user_id = '{$subscriber->getId()}') ORDER BY subscribe_timestamp DESC";
1229                else
1230                        $sql = "SELECT content_id FROM node_has_content WHERE node_id='{$this->id}' AND display_location='$display_location' ORDER BY subscribe_timestamp DESC";
1231                $db->ExecSql($sql, $content_rows, false);
1232
1233                if ($content_rows != null)
1234                {
1235                        foreach ($content_rows as $content_row)
1236                        {
1237                                $retval[] = Content :: getObject($content_row['content_id']);
1238                        }
1239                }
1240                return $retval;
1241        }
1242
1243        /** Get an array of all artistic and locative Content for this hotspot
1244        * @return an array of Content or an empty arrray */
1245        function getAllLocativeArtisticContent()
1246        {
1247                global $db;
1248                $retval = array ();
1249                $sql = "SELECT * FROM content_group JOIN content ON (content.content_id = content_group.content_group_id) JOIN node_has_content ON (node_has_content.content_id = content_group.content_group_id AND node_has_content.node_id = '{$this->getId()}') WHERE is_persistent = true AND is_artistic_content = true AND is_locative_content = true ORDER BY subscribe_timestamp DESC";
1250                $content_rows = null;
1251                $db->ExecSql($sql, $content_rows, false);
1252                if ($content_rows != null)
1253                {
1254                        foreach ($content_rows as $content_row)
1255                        {
1256                                // Create a content group object and grab only those that have content for the current Node
1257                                $content_group = Content :: getObject($content_row['content_group_id']);
1258                                if ($content_group->getDisplayNumElements() >= 1)
1259                                {
1260                                        if ($content_group->isDisplayableAt($this))
1261                                        {
1262                                                // Disable logging and allow content to expand ( if possible )
1263                                                $content_group->setExpandStatus(true);
1264                                                $content_group->setLoggingStatus(false);
1265                                                $retval[] = $content_group;
1266                                        }
1267                                }
1268                        }
1269                }
1270                return $retval;
1271        }
1272
1273        /** The list of users online at this node
1274         * @return An array of User object, or en empty array */
1275        function getOnlineUsers()
1276        {
1277                global $db;
1278                $retval = array ();
1279                $users = null;
1280                $db->ExecSql("SELECT users.user_id FROM users,connections WHERE connections.token_status='".TOKEN_INUSE."' AND users.user_id=connections.user_id AND connections.node_id='{$this->id}'", $users, false);
1281                if ($users != null)
1282                {
1283                        foreach ($users as $user_row)
1284                        {
1285                                $retval[] = User :: getObject($user_row['user_id']);
1286                        }
1287                }
1288                return $retval;
1289        }
1290
1291        /** Find out how many users are online this specific Node
1292         * @return Number of online users
1293         */
1294        function getNumOnlineUsers()
1295        {
1296                global $db;
1297                $retval = array ();
1298                $row = null;
1299                $db->ExecSqlUniqueRes("SELECT COUNT(DISTINCT users.user_id) as count FROM users,connections WHERE connections.token_status='".TOKEN_INUSE."' AND users.user_id=connections.user_id AND connections.node_id='{$this->id}'", $row, false);
1300                return $row['count'];
1301        }
1302
1303        /** The list of all real owners of this node
1304         * @return An array of User object, or en empty array */
1305        function getOwners()
1306        {
1307                global $db;
1308                $retval = array ();
1309                $owners = null;
1310                $db->ExecSql("SELECT user_id FROM node_stakeholders WHERE is_owner = true AND node_id='{$this->id}'", $owners, false);
1311                if ($owners != null)
1312                {
1313                        foreach ($owners as $owner_row)
1314                        {
1315                                $retval[] = User :: getObject($owner_row['user_id']);
1316                        }
1317                }
1318                return $retval;
1319        }
1320
1321        /** The list of all Technical officers of this node. 
1322         * Technical officers are displayed highlited and in the online user's list,
1323         * and are contacted when the Node goes down.
1324         * @return An array of User object, or en empty array */
1325        function getTechnicalOfficers()
1326        {
1327                global $db;
1328                $retval = array ();
1329                $officers = null;
1330                $db->ExecSql("SELECT user_id FROM node_stakeholders WHERE is_tech_officer = true AND node_id='{$this->id}'", $officers, false);
1331                if ($officers != null)
1332                {
1333                        foreach ($officers as $officer_row)
1334                        {
1335                                $retval[] = User :: getObject($officer_row['user_id']);
1336                        }
1337                }
1338                return $retval;
1339        }
1340
1341        /** Associates an owner to this node
1342         * @param User
1343         */
1344        function addOwner(User $user)
1345        {
1346                global $db;
1347                $rows = null;
1348                $db->ExecSql("SELECT * FROM node_stakeholders WHERE node_id = '{$this->getId()}' AND user_id = '{$user->getId()}'", $rows, false);
1349                if (!$rows)
1350                {
1351                        if (!$db->ExecSqlUpdate("INSERT INTO node_stakeholders (node_id, user_id, is_owner) VALUES ('{$this->getId()}','{$user->getId()}', true)", false))
1352                                throw new Exception(_('Could not add owner'));
1353                }
1354                else
1355                        if (!$db->ExecSqlUpdate("UPDATE node_stakeholders SET is_owner = true WHERE node_id = '{$this->getId()}' AND user_id = '{$user->getId()}';", false))
1356                                throw new Exception(_('Could not add owner'));
1357        }
1358
1359        /** Associates a technical officer ( tech support ) to this node
1360         * @param User
1361         */
1362        function addTechnicalOfficer(User $user)
1363        {
1364                global $db;
1365                $rows = null;
1366                $db->ExecSql("SELECT * FROM node_stakeholders WHERE node_id = '{$this->getId()}' AND user_id = '{$user->getId()}'", $rows, false);
1367                if (!$rows)
1368                {
1369                        if (!$db->ExecSqlUpdate("INSERT INTO node_stakeholders (node_id, user_id, is_tech_officer) VALUES ('{$this->getId()}','{$user->getId()}', true)", false))
1370                                throw new Exception(_('Could not add tech officer'));
1371                }
1372                else
1373                        if (!$db->ExecSqlUpdate("UPDATE node_stakeholders SET is_tech_officer = true WHERE node_id = '{$this->getId()}' AND user_id = '{$user->getId()}';", false))
1374                                throw new Exception(_('Could not set existing user as tech officer'));
1375        }
1376
1377        /** Remove owner flag for a stakeholder of this node
1378         * @param User
1379         */
1380        function removeOwner(User $user)
1381        {
1382                global $db;
1383                if (!$db->ExecSqlUpdate("UPDATE node_stakeholders SET is_owner = false WHERE node_id = '{$this->getId()}' AND user_id = '{$user->getId()}';", false))
1384                        throw new Exception(_('Could not remove owner'));
1385        }
1386
1387        /** Remove technical officer flag for a stakeholder of this node
1388         * @param User
1389         */
1390        function removeTechnicalOfficer(User $user)
1391        {
1392                global $db;
1393                if (!$db->ExecSqlUpdate("UPDATE node_stakeholders SET is_tech_officer = false WHERE node_id = '{$this->getId()}' AND user_id = '{$user->getId()}';", false))
1394                        throw new Exception(_('Could not remove tech officer'));
1395        }
1396
1397        /** Is the user an owner of the Node?
1398         * @return true our false*/
1399        function isOwner(User $user)
1400        {
1401                global $db;
1402                if ($user != null)
1403                {
1404                        $user_id = $user->getId();
1405                        $retval = false;
1406                        $row = null;
1407                        $db->ExecSqlUniqueRes("SELECT * FROM node_stakeholders WHERE is_owner = true AND node_id='{$this->id}' AND user_id='{$user_id}'", $row, false);
1408                        if ($row != null)
1409                        {
1410                                $retval = true;
1411                        }
1412                }
1413                return $retval;
1414        }
1415
1416        /** Is the user a technical officer of the Node?
1417         * @return true our false*/
1418        function isTechnicalOfficer(User $user)
1419        {
1420                global $db;
1421                if ($user != null)
1422                {
1423                        $user_id = $user->getId();
1424                        $retval = false;
1425                        $row = null;
1426                        $db->ExecSqlUniqueRes("SELECT * FROM node_stakeholders WHERE is_tech_officer = true AND node_id='{$this->id}' AND user_id='{$user_id}'", $row, false);
1427                        if ($row != null)
1428                        {
1429                                $retval = true;
1430                        }
1431                }
1432                return $retval;
1433        }
1434
1435        /** Check if an node exists */
1436        private function nodeExists($id)
1437        {
1438                global $db;
1439                $retval = false;
1440                $id_str = $db->EscapeString($id);
1441                $sql = "SELECT * FROM nodes WHERE node_id='{$id_str}'";
1442                $row = null;
1443                $db->ExecSqlUniqueRes($sql, $row, false);
1444                if ($row != null)
1445                {
1446                        $retval = true;
1447                }
1448                return $retval;
1449        }
1450
1451        /** Reloads the object from the database.  Should normally be called after a set operation */
1452        protected function refresh()
1453        {
1454                $this->__construct($this->id);
1455        }
1456
1457} // End class
1458?>
Note: See TracBrowser for help on using the browser.