*/ require_once BASEPATH.'include/common.php'; require_once 'User.php'; require_once 'GisPoint.php'; require_once 'AbstractGeocoder.php'; require_once 'Utils.php'; /** Abstract a Node. A Node is an actual physical transmitter. * @todo: Make all the setter functions no-op if the value is the same as what * was already stored Use setCustomPortalReduirectUrl as an example*/ class Node implements GenericObject { private $mRow; private $mdB; /**< An AbstractDb instance */ private $id; private static $current_node_id = null; /** Instantiate a node object * @param $id The id of the requested node * @return a Node object, or null if there was an error */ static function getObject($id) { $object = null; $object = new self($id); return $object; } /** Get the current node for which the portal is displayed or to which a user is physically connected. * @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. * @return a Node object, or null if it can't be found. */ static function getCurrentNode($real_node_only = false) { $object = null; if (self :: $current_node_id != null && $real_node_only == false) { $object = new self(self :: $current_node_id); } else { $object = self :: getCurrentRealNode(); } return $object; } /** Set the current node where the user is to be considered connected to. (For portal and content display purpuses, among other. * @param $node Node. The new current node. * @return true */ static function setCurrentNode(Node $node) { self :: $current_node_id = $node->GetId(); return true; } /** 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 * @param * @return a Node object, or null if it can't be found. */ public static function getCurrentRealNode() { global $db; $retval = null; $sql = "SELECT node_id, last_heartbeat_ip from nodes WHERE last_heartbeat_ip='$_SERVER[REMOTE_ADDR]' ORDER BY last_heartbeat_timestamp DESC"; $node_rows = null; $db->ExecSql($sql, $node_rows, false); $num_match = count($node_rows); if ($num_match == 0) { // User is not physically connected to a node $retval = null; } else if ($num_match = 1) { // Only a single node matches, the user is presumed to be there $retval = new self($node_rows[0]['node_id']); } else { /* We have more than one node matching the IP (the nodes are behind the same NAT). * We will try to discriminate by finding which node the user last authenticated against. * If the IP matches, we can be pretty certain the user is there. */ $retval = null; $current_user = User :: getCurrentUser(); if ($current_user != null) { $current_user_id = $current_user->getId(); $_SERVER['REMOTE_ADDR']; $sql = "SELECT node_id, last_heartbeat_ip from connections NATURAL JOIN nodes WHERE user_id='$current_user_id' ORDER BY last_updated DESC "; $db->ExecSql($sql, $node_rows, false); $node_row = $node_rows[0]; if ($node_row != null && $node_row['last_heartbeat_ip'] == $_SERVER['REMOTE_ADDR']) { $retval = new self($node_row['node_id']); } } } return $retval; } public function delete(& $errmsg) { $retval = false; $user = User :: getCurrentUser(); if ($this->isOwner($user) || $user->isSuperAdmin()) { global $db; $id = $db->EscapeString($this->getId()); if (!$db->ExecSqlUpdate("DELETE FROM nodes WHERE node_id='{$id}'", false)) { $errmsg = _('Could not delete node!'); } else { $retval = true; } } else { $errmsg = _('Access denied!'); } return $retval; } /** Create a new Node in the database * @param $node_id The id to be given to the new node. If not present, a * guid will be assigned. * @param $network Network object. The node's network. If not present, * the current Network will be assigned * * @return the newly created Node object, or null if there was an error */ static function createNewObject($node_id = null, $network = null) { global $db; if (empty ($node_id)) { $node_id = get_guid(); } $node_id = $db->EscapeString($node_id); if (empty ($network)) { $network = Network :: getCurrentNetwork(); } $network_id = $db->EscapeString($network->getId()); $node_deployment_status = $db->EscapeString("IN_PLANNING"); $node_name = _("New node"); if (Node :: nodeExists($node_id)) throw new Exception(_('This node already exists.')); $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')"; if (!$db->ExecSqlUpdate($sql, false)) { throw new Exception(_('Unable to insert new node into database!')); } $object = new self($node_id); return $object; } /** Get an interface to pick a node. * @param $user_prefix A identifier provided by the programmer to recognise it's generated html form * @param $sql_additional_where Addidional where conditions to restrict the candidate objects * @return html markup */ public static function getSelectNodeUI($user_prefix, $sql_additional_where = null) { global $db; $html = ''; $name = "{$user_prefix}"; $html .= _("Node: "); $sql = "SELECT node_id, name from nodes WHERE 1=1 $sql_additional_where ORDER BY node_id"; $node_rows = null; $db->ExecSql($sql, $node_rows, false); if ($node_rows != null) { $i = 0; foreach ($node_rows as $node_row) { $tab[$i][0] = $node_row['node_id']; $tab[$i][1] = $node_row['node_id'].": ".$node_row['name']; $i ++; } $html .= FormSelectGenerator :: generateFromArray($tab, null, $name, null, false); } return $html; } /** Get the selected Network object. * @param $user_prefix A identifier provided by the programmer to recognise it's generated form * @return the node object */ static function processSelectNodeUI($user_prefix) { $object = null; $name = "{$user_prefix}"; return new self($_REQUEST[$name]); } /** Get an interface to create a new node. * @param $network Optional: The network to which the new node will belong, * if absent, the user will be prompted. * @return html markup */ public static function getCreateNewObjectUI($network = null) { $html = ''; $html .= _("Create new node with id")." \n"; $name = "new_node_id"; $html .= "\n"; if ($network) { $name = "new_node_network_id"; $html .= "\n"; } else { $html .= " "._("in network:")." \n"; $html .= Network :: getSelectNetworkUI('new_node'); } return $html; } /** Process the new object interface. * Will return the new object if the user has the credentials and the form was fully filled. * @return the node object or null if no new node was created. */ static function processCreateNewObjectUI() { $retval = null; $name = "new_node_id"; if (!empty ($_REQUEST[$name])) { $node_id = $_REQUEST[$name]; $name = "new_node_network_id"; if (!empty ($_REQUEST[$name])) { $network = Network :: getObject($_REQUEST[$name]); } else { $network = Network :: processSelectNetworkUI('new_node'); } if ($node_id && $network) { if (!$network->hasAdminAccess(User :: getCurrentUser())) { throw new Exception(_("Access denied")); } $retval = self :: createNewObject($node_id, $network); } } return $retval; } /** Get an interface to select the deployment status * @param $user_prefix A identifier provided by the programmer to recognise it's generated html form * @return html markup */ public function getSelectDeploymentStatus($user_prefix) { global $db; $html = ''; $name = "{$user_prefix}"; $status_list = null; $db->ExecSql("SELECT node_deployment_status FROM node_deployment_status", $status_list, false); if ($status_list == null) throw new Exception(_("No deployment statues could be found in the database")); $tab = array (); foreach ($status_list as $status) $tab[] = array ($status['node_deployment_status'], $status['node_deployment_status']); $html .= FormSelectGenerator :: generateFromArray($tab, $this->getDeploymentStatus(), $name, null, false); return $html; } /** Get the selected deployment status * @param $user_prefix A identifier provided by the programmer to recognise it's generated form * @return the deployment status */ public function processSelectDeploymentStatus($user_prefix) { $object = null; $name = "{$user_prefix}"; return $_REQUEST[$name]; } /** @param $node_id The id of the node */ private function __construct($node_id) { global $db; $this->mDb = & $db; $node_id_str = $db->EscapeString($node_id); $sql = "SELECT * FROM nodes WHERE node_id='$node_id_str'"; $row = null; $db->ExecSqlUniqueRes($sql, $row, false); if ($row == null) { throw new Exception(_("The id $node_id_str could not be found in the database")); } $this->mRow = $row; $this->id = $row['node_id']; } function getId() { return $this->id; } /** Changing the id of a Node is supported. * Be carefull to anly call this when all other changes are processed, * or the id used to generate the form names may no longer match. * @param $id, string, the new node id. * @return true on success, false on failure. Check this, * as it's possible that someone will enter an existing id, especially * if the MAC address is used and hardware is recycled. */ function setId($id) { $id = $this->mDb->EscapeString($id); $retval = $this->mDb->ExecSqlUpdate("UPDATE nodes SET node_id = '{$id}' WHERE node_id = '{$this->getId()}'"); if($retval) { $this->id = $id; $this->refresh(); } return $retval; } /** Gets the Network to which the node belongs * @return Network object (never returns null) */ public function getNetwork() { return Network :: getObject($this->mRow['network_id']); } /** Get a GisPoint object ; altide is not supported yet */ function getGisLocation() { // Altitude is not supported yet return new GisPoint($this->mRow['latitude'], $this->mRow['longitude'], 0); } function setGisLocation($pt) { if (!empty ($pt)) { $lat = $this->mDb->EscapeString($pt->getLatitude()); $long = $this->mDb->EscapeString($pt->getLongitude()); if (!empty ($lat) && !empty ($long)) $this->mDb->ExecSqlUpdate("UPDATE nodes SET latitude = $lat, longitude = $long WHERE node_id = '{$this->getId()}'"); else $this->mDb->ExecSqlUpdate("UPDATE nodes SET latitude = NULL, longitude = NULL WHERE node_id = '{$this->getId()}'"); $this->refresh(); } } /** Return the name of the node */ function getName() { return $this->mRow['name']; } function setName($name) { $name = $this->mDb->EscapeString($name); $this->mDb->ExecSqlUpdate("UPDATE nodes SET name = '{$name}' WHERE node_id = '{$this->getId()}'"); $this->refresh(); } function getCreationDate() { return $this->mRow['creation_date']; } function getHomePageURL() { return $this->mRow['home_page_url']; } function setHomePageUrl($url) { $url = $this->mDb->EscapeString($url); $this->mDb->ExecSqlUpdate("UPDATE nodes SET home_page_url = '{$url}' WHERE node_id = '{$this->getId()}'"); $this->refresh(); } function getDescription() { return $this->mRow['description']; } function setDescription($description) { $description = $this->mDb->EscapeString($description); $this->mDb->ExecSqlUpdate("UPDATE nodes SET description = '{$description}' WHERE node_id = '{$this->getId()}'"); $this->refresh(); } function getMapURL() { return $this->mRow['map_url']; } function setMapURL($url) { $url = $this->mDb->EscapeString($url); $this->mDb->ExecSqlUpdate("UPDATE nodes SET map_url = '{$url}' WHERE node_id = '{$this->getId()}'"); $this->refresh(); } public function getCivicNumber() { return $this->mRow['civic_number']; } public function setCivicNumber($civic_number) { $civic_number = $this->mDb->EscapeString($civic_number); $this->mDb->ExecSqlUpdate("UPDATE nodes SET civic_number = '{$civic_number}' WHERE node_id = '{$this->getId()}'"); $this->refresh(); } public function getStreetName() { return $this->mRow['street_name']; } public function setStreetName($street_name) { $street_name = $this->mDb->EscapeString($street_name); $this->mDb->ExecSqlUpdate("UPDATE nodes SET street_name = '{$street_name}' WHERE node_id = '{$this->getId()}'"); $this->refresh(); } public function getCity() { return $this->mRow['city']; } public function setCity($city) { $city = $this->mDb->EscapeString($city); $this->mDb->ExecSqlUpdate("UPDATE nodes SET city = '{$city}' WHERE node_id = '{$this->getId()}'"); $this->refresh(); } public function getProvince() { return $this->mRow['province']; } public function setProvince($province) { $province = $this->mDb->EscapeString($province); $this->mDb->ExecSqlUpdate("UPDATE nodes SET province = '{$province}' WHERE node_id = '{$this->getId()}'"); $this->refresh(); } public function getCountry() { return $this->mRow['country']; } protected function setCountry($country) { $country = $this->mDb->EscapeString($country); $this->mDb->ExecSqlUpdate("UPDATE nodes SET country = '{$country}' WHERE node_id = '{$this->getId()}'"); $this->refresh(); } public function getPostalCode() { return $this->mRow['postal_code']; } public function setPostalCode($postal_code) { $postal_code = $this->mDb->EscapeString($postal_code); $this->mDb->ExecSqlUpdate("UPDATE nodes SET postal_code = '{$postal_code}' WHERE node_id = '{$this->getId()}'"); $this->refresh(); } function getTelephone() { return $this->mRow['public_phone_number']; } function setTelephone($phone) { $phone = $this->mDb->EscapeString($phone); $this->mDb->ExecSqlUpdate("UPDATE nodes SET public_phone_number = '{$phone}' WHERE node_id = '{$this->getId()}'"); $this->refresh(); } function getTransitInfo() { return $this->mRow['mass_transit_info']; } function setTransitInfo($transit_info) { $transit_info = $this->mDb->EscapeString($transit_info); $this->mDb->ExecSqlUpdate("UPDATE nodes SET mass_transit_info = '{$transit_info}' WHERE node_id = '{$this->getId()}'"); $this->refresh(); } function getEmail() { return $this->mRow['public_email']; } function setEmail($email) { $email = $this->mDb->EscapeString($email); $this->mDb->ExecSqlUpdate("UPDATE nodes SET public_email = '{$email}' WHERE node_id = '{$this->getId()}'"); $this->refresh(); } function getDeploymentStatus() { return $this->mRow['node_deployment_status']; } function setDeploymentStatus($status) { $status = $this->mDb->EscapeString($status); $this->mDb->ExecSqlUpdate("UPDATE nodes SET node_deployment_status = '{$status}' WHERE node_id = '{$this->getId()}'"); $this->refresh(); } function getLastPaged() { return $this->mRow['last_paged']; } function setLastPaged($last_paged) { $this->mDb->ExecSqlUpdate("UPDATE nodes SET last_paged = {$last_paged}::abstime WHERE node_id = '{$this->getId()}'"); $this->refresh(); } function getLastHeartbeatIP() { return $this->mRow['last_heartbeat_ip']; } function getLastHeartbeatUserAgent() { return $this->mRow['last_heartbeat_user_agent']; } function getLastHeartbeatTimestamp() { return $this->mRow['last_heartbeat_timestamp']; } function setLastHeartbeatTimestamp($timestamp) { $this->mDb->ExecSqlUpdate("UPDATE nodes SET last_heartbeat_timestamp = '{$timestamp}' WHERE node_id = '{$this->getId()}'"); $this->refresh(); } /** Is the node a Splash Only node? Will only return true if the Network configuration allows it. * @return true or false */ public function isSplashOnly() { return $this->getNetwork()->getSplashOnlyNodesAllowed() && $this->isConfiguredSplashOnly(); } /** Is the node configured as a Splash Only node? This is NOT the same as isSplashOnly(). * This is the getter for the configuration set in the database for this node. * For the node to actually be splash only, this AND the network * gonfiguration must match. * @return true or false */ public function isConfiguredSplashOnly() { return (($this->mRow['is_splash_only_node'] == 't') ? true : false); } /** Set if this node should be a splash-only (no login) node (if enabled in Network configuration) * @param $value The new value, true or false * @return true on success, false on failure */ function setIsConfiguredSplashOnly($value) { $retval = true; if ($value != $this->isConfiguredSplashOnly()) { global $db; $value ? $value = 'TRUE' : $value = 'FALSE'; $retval = $db->ExecSqlUpdate("UPDATE nodes SET is_splash_only_node = {$value} WHERE node_id = '{$this->getId()}'", false); $this->refresh(); } return $retval; } /** The url to show instead of the portal. If empty, the portal is shown Must be enabled in the Network configuration to have any effect @return a string */ function getCustomPortalRedirectUrl() { return $this->mRow['custom_portal_redirect_url']; } /** The url to show instead of the portal. If empty, the portal is shown Must be enabled in the Network configuration to have any effect @return true on success, false on failure */ function setCustomPortalRedirectUrl($value) { $retval = true; if ($value != $this->getCustomPortalRedirectUrl()) { global $db; $value = $db->EscapeString($value); $retval = $db->ExecSqlUpdate("UPDATE nodes SET custom_portal_redirect_url = '{$value}' WHERE node_id = '{$this->getId()}'", false); $this->refresh(); } return $retval; } /** Retrieves the admin interface of this object. * @return The HTML fragment for this interface */ public function getAdminUI() { //TODO: Most of this code will be moved to Hotspot class when the abtraction will be completed //pretty_print_r($_REQUEST); //pretty_print_r($this->mRow); $html = ''; $html .= "
\n"; $html .= "
Node (".get_class($this)." instance)
\n"; $html .= "

"._("Edit a node")."

\n"; // Display stats $html .= "
\n"; $html .= "
"._("Statistics:")."
\n"; $html .= "
\n"; $name = "node_".$this->id."_get_stats"; $html .= ""; $html .= "
\n"; $html .= "
\n"; // Information about the node $html .= "
\n"; $html .= "
"._("Information about the node:")."
\n"; // Hashed node_id (this is a workaround since PHP auto-converts HTTP vars var periods, spaces or underscores ) $hashed_node_id = md5($this->getId()); // Node ID $value = htmlspecialchars($this->getId(), ENT_QUOTES); $html .= "
\n"; $html .= "
"._("ID")." :
\n"; $html .= "
\n"; $name = "node_".$hashed_node_id."_id"; $html .= "\n"; $html .= "
\n"; $html .= "
\n"; // Name $html .= "
\n"; $html .= "
"._("Name")." :
\n"; $html .= "
\n"; $name = "node_".$hashed_node_id."_name"; $value = htmlspecialchars($this->getName(), ENT_QUOTES); $html .= "\n"; $html .= "
\n"; $html .= "
\n"; // Homepage URL $html .= "
\n"; $html .= "
"._("Homepage URL")." :
\n"; $html .= "
\n"; $name = "node_".$hashed_node_id."_homepage_url"; $value = htmlspecialchars($this->getHomePageURL(), ENT_QUOTES); $html .= "\n"; $html .= "
\n"; $html .= "
\n"; // Description $html .= "
\n"; $html .= "
"._("Description")." :
\n"; $html .= "
\n"; $name = "node_".$hashed_node_id."_description"; $value = htmlspecialchars($this->getDescription(), ENT_QUOTES); $html .= "\n"; $html .= "
\n"; $html .= "
\n"; // Map URL $html .= "
\n"; $html .= "
"._("Map URL")." :
\n"; $html .= "
\n"; $name = "node_".$hashed_node_id."_map_url"; $value = htmlspecialchars($this->getMapURL(), ENT_QUOTES); $html .= "\n"; $html .= "
\n"; $html .= "
\n"; // Civic number $html .= "
\n"; $html .= "
"._("Civic number")." :
\n"; $html .= "
\n"; $name = "node_".$hashed_node_id."_civic_number"; $value = htmlspecialchars($this->getCivicNumber(), ENT_QUOTES); $html .= "\n"; $html .= "
\n"; $html .= "
\n"; // Street name $html .= "
\n"; $html .= "
"._("Street name")." :
\n"; $html .= "
\n"; $name = "node_".$hashed_node_id."_street_name"; $value = htmlspecialchars($this->getStreetName(), ENT_QUOTES); $html .= "\n"; $html .= "
\n"; $html .= "
\n"; // City $html .= "
\n"; $html .= "
"._("City")." :
\n"; $html .= "
\n"; $name = "node_".$hashed_node_id."_city"; $value = htmlspecialchars($this->getCity(), ENT_QUOTES); $html .= "\n"; $html .= "
\n"; $html .= "
\n"; // Province $html .= "
\n"; $html .= "
"._("Province / State")." :
\n"; $html .= "
\n"; $name = "node_".$hashed_node_id."_province"; $value = htmlspecialchars($this->getProvince(), ENT_QUOTES); $html .= "\n"; $html .= "
\n"; $html .= "
\n"; // Postal Code $html .= "
\n"; $html .= "
"._("Postal code")." :
\n"; $html .= "
\n"; $name = "node_".$hashed_node_id."_postal_code"; $value = htmlspecialchars($this->getPostalCode(), ENT_QUOTES); $html .= "\n"; $html .= "
\n"; $html .= "
\n"; // Country $html .= "
\n"; $html .= "
"._("Country")." :
\n"; $html .= "
\n"; $name = "node_".$hashed_node_id."_country"; $value = htmlspecialchars($this->getCountry(), ENT_QUOTES); $html .= "\n"; $html .= "
\n"; $html .= "
\n"; // Public phone # $html .= "
\n"; $html .= "
"._("Public phone number")." :
\n"; $html .= "
\n"; $name = "node_".$hashed_node_id."_public_phone"; $value = htmlspecialchars($this->getTelephone(), ENT_QUOTES); $html .= "\n"; $html .= "
\n"; $html .= "
\n"; // Public mail $html .= "
\n"; $html .= "
"._("Public email")." :
\n"; $html .= "
\n"; $name = "node_".$hashed_node_id."_public_email"; $value = htmlspecialchars($this->getEmail(), ENT_QUOTES); $html .= "\n"; $html .= "
\n"; $html .= "
\n"; // Mass transit info $html .= "
\n"; $html .= "
"._("Mass transit info")." :
\n"; $html .= "
\n"; $name = "node_".$hashed_node_id."_mass_transit_info"; $value = htmlspecialchars($this->getTransitInfo(), ENT_QUOTES); $html .= "\n"; $html .= "
\n"; $html .= "
\n"; // End of information section $html .= "
\n"; // Node GIS data $html .= "
\n"; $html .= "
"._("GIS data")." :
\n"; // Build HTML form fields names & values $gis_point = $this->getGisLocation(); $gis_lat_name = "node_".$hashed_node_id."_gis_latitude"; $gis_lat_value = htmlspecialchars($gis_point->getLatitude(), ENT_QUOTES); $gis_long_name = "node_".$hashed_node_id."_gis_longitude"; $gis_long_value = htmlspecialchars($gis_point->getLongitude(), ENT_QUOTES); $html .= "
\n"; $html .= "
"._("Latitude")." :
\n"; $html .= "
\n"; $html .= "\n"; $html .= "
\n"; $html .= "
\n"; $html .= "
\n"; $html .= "
"._("Longitude")." :
\n"; $html .= "
\n"; $html .= "\n"; $html .= "
\n"; $html .= "
\n"; /* * If Google Maps is enabled, call the geocoding service, * then use Google Maps to let the user choose a more precise location * * otherwise * * Simply use a geocoding service. */ if (defined('GMAPS_HOTSPOTS_MAP_ENABLED') && GMAPS_HOTSPOTS_MAP_ENABLED === true) { $html .= "
\n"; $html .= "
\n"; $html .= "\n"; $html .= "\n"; $html .= " ("._("Use a geocoding service, then use Google Maps to pinpoint the exact location.").")"; $html .= "
\n"; $html .= "
\n"; } else { $html .= "
\n"; $html .= "
\n"; $html .= "\n"; $html .= " ("._("Use a geocoding service").")"; $html .= "
\n"; $html .= "
\n"; } // End of GIS data $html .= "
\n"; // Node configuration section $html .= "
\n"; $html .= "
"._("Node configuration:")."
\n"; $network = $this->getNetwork(); // Deployment status $html .= "
\n"; $html .= "
"._("Node deployment status")." :
\n"; $html .= "
\n"; $name = "node_".$hashed_node_id."_deployment_status"; $html .= self :: getSelectDeploymentStatus($name); $html .= "
\n"; $html .= "
\n"; // is_splash_only_node if ($network->getSplashOnlyNodesAllowed()) { $html .= "
\n"; $html .= "
"._("Is this node splash-only (no login)?")." :
\n"; $html .= "
\n"; $name = "node_".$hashed_node_id."_is_splash_only_node"; $this->isConfiguredSplashOnly() ? $checked = 'CHECKED' : $checked = ''; $html .= "\n"; $html .= "
\n"; $html .= "
\n"; } // custom_portal_redirect_url if ($network->getCustomPortalRedirectAllowed()) { $html .= "
\n"; $html .= "
"._("URL to show instead of the portal (if this is not empty, the portal will be disabled and this URL will be shown instead)")." :
\n"; $html .= "
\n"; $name = "node_".$hashed_node_id."_custom_portal_redirect_url"; $value = htmlspecialchars($this->getCustomPortalRedirectUrl(), ENT_QUOTES); $html .= "\n"; $html .= "
\n"; $html .= "
\n"; } // End Node configuration section $html .= "
\n"; // Owners management $html .= "
\n"; $html .= "
"._("Node owners")." :
\n"; $html .= "\n"; $html .= "
\n"; $html .= "
\n"; // Tech officers management $html .= "
\n"; $html .= "
"._("Technical officers")." :
\n"; $html .= "\n"; $html .= "
\n"; $html .= "\n"; /* Node content */ $html .= "
\n"; $html .= "
"._("Node content (login):")."
\n"; $name = "node_{$this->id}_content_login"; $html .= Content::getLinkedContentUI($name, 'node_has_content', 'node_id', $this->id, $display_location = 'login_page'); $html .= "
\n"; $html .= "
\n"; $html .= "
"._("Node content (portal):")."
\n"; $name = "node_{$this->id}_content_portal"; $html .= Content::getLinkedContentUI($name, 'node_has_content', 'node_id', $this->id, $display_location = 'portal_page'); $html .= "
\n"; return $html; } /** Process admin interface of this object. */ public function processAdminUI() { $user = User :: getCurrentUser(); if (!$this->isOwner($user) && !$user->isSuperAdmin()) { throw new Exception(_('Access denied!')); } // Information about the node // Hashed node_id (this is a workaround since PHP auto-converts HTTP vars var periods, spaces or underscores ) $hashed_node_id = md5($this->getId()); // Name $name = "node_".$hashed_node_id."_name"; $this->setName($_REQUEST[$name]); // Homepage URL $name = "node_".$hashed_node_id."_homepage_url"; $this->setHomePageUrl($_REQUEST[$name]); // Description $name = "node_".$hashed_node_id."_description"; $this->setDescription($_REQUEST[$name]); // Map URL $name = "node_".$hashed_node_id."_map_url"; $this->setMapUrl($_REQUEST[$name]); // Civic number $name = "node_".$hashed_node_id."_civic_number"; $this->setCivicNumber($_REQUEST[$name]); // Street name $name = "node_".$hashed_node_id."_street_name"; $this->setStreetName($_REQUEST[$name]); // City $name = "node_".$hashed_node_id."_city"; $this->setCity($_REQUEST[$name]); // Province $name = "node_".$hashed_node_id."_province"; $this->setProvince($_REQUEST[$name]); // Postal Code $name = "node_".$hashed_node_id."_postal_code"; $this->setPostalCode($_REQUEST[$name]); // Country $name = "node_".$hashed_node_id."_country"; $this->setCountry($_REQUEST[$name]); // Public phone # $name = "node_".$hashed_node_id."_public_phone"; $this->setTelephone($_REQUEST[$name]); // Public mail $name = "node_".$hashed_node_id."_public_email"; $this->setEmail($_REQUEST[$name]); // Mass transit info $name = "node_".$hashed_node_id."_mass_transit_info"; $this->setTransitInfo($_REQUEST[$name]); // GIS data // Get a geocoder for a given country if (!empty ($_REQUEST['geocode_only'])) { $geocoder = AbstractGeocoder :: getGeocoder($this->getCountry()); if ($geocoder != null) { $geocoder->setCivicNumber($this->getCivicNumber()); $geocoder->setStreetName($this->getStreetName()); $geocoder->setCity($this->getCity()); $geocoder->setProvince($this->getProvince()); $geocoder->setPostalCode($this->getPostalCode()); if ($geocoder->validateAddress() === true) { if (($point = $geocoder->getGisLocation()) !== null) $this->setGisLocation($point); else echo _("It appears that the Geocoder could not be reached or could not geocode the given address."); } else echo _("You must enter a valid address."); } } else { // Use what has been set by the user. $gis_lat_name = "node_".$hashed_node_id."_gis_latitude"; $gis_long_name = "node_".$hashed_node_id."_gis_longitude"; $this->setGisLocation(new GisPoint($_REQUEST[$gis_lat_name], $_REQUEST[$gis_long_name], .0)); } // Statistics $name = "node_{$this->id}_get_stats"; if (!empty ($_REQUEST[$name])) header("Location: stats.php?node_id=".urlencode($this->getId())); // Node configuration section $network = $this->getNetwork(); // Deployment status $name = "node_".$hashed_node_id."_deployment_status"; $this->setDeploymentStatus(self :: processSelectDeploymentStatus($name)); // is_splash_only_node if ($network->getSplashOnlyNodesAllowed()) { $name = "node_".$hashed_node_id."_is_splash_only_node"; $this->setIsConfiguredSplashOnly(empty ($_REQUEST[$name]) ? false : true); } // custom_portal_redirect_url if ($network->getCustomPortalRedirectAllowed()) { $name = "node_".$hashed_node_id."_custom_portal_redirect_url"; $this->setCustomPortalRedirectUrl($_REQUEST[$name]); } // End Node configuration section // Owners processing // Rebuild user id, and delete if it was selected foreach ($this->getOwners() as $owner) { $name = "node_{$this->getId()}_owner_{$owner->GetId()}_remove"; if (!empty ($_REQUEST[$name])) { if ($this->isOwner($owner)) $this->removeOwner($owner); else echo _("Invalid user!"); } } $name = "node_{$this->getId()}_new_owner_submit"; if (!empty ($_REQUEST[$name])) { $name = "node_{$this->getId()}_new_owner"; $owner = User :: processSelectUserUI($name); if ($owner) { if ($this->isOwner($owner)) echo _("The user is already an owner of this node."); else $this->addOwner($owner); } } // Technical officers processing // Rebuild user id, and delete if it was selected foreach ($this->getTechnicalOfficers() as $tech_officer) { $name = "node_{$this->getId()}_tech_officer_{$tech_officer->GetId()}_remove"; if (!empty ($_REQUEST[$name])) { if ($this->isTechnicalOfficer($tech_officer)) $this->removeTechnicalOfficer($tech_officer); else echo _("Invalid user!"); } } $name = "node_{$this->getId()}_new_tech_officer_submit"; if (!empty ($_REQUEST[$name])) { $name = "node_{$this->getId()}_new_tech_officer"; $tech_officer = User :: processSelectUserUI($name); if ($tech_officer) { if ($this->isTechnicalOfficer($tech_officer)) echo _("The user is already a technical officer of this node."); else $this->addTechnicalOfficer($tech_officer); } } // Content processing $name = "node_{$this->id}_content_login"; Content::processLinkedContentUI($name, 'node_has_content', 'node_id', $this->id); $name = "node_{$this->id}_content_portal"; Content::processLinkedContentUI($name, 'node_has_content', 'node_id', $this->id); // Name $name = "node_".$hashed_node_id."_id"; $this->setId($_REQUEST[$name]); } // Redirect to this node's portal page public function getUserUI() { header("Location: ".BASE_SSL_PATH."portal/?gw_id=".$this->getId()); } /** Add content to this node */ public function addContent(Content $content) { global $db; $content_id = $db->EscapeString($content->getId()); $sql = "INSERT INTO node_has_content (node_id, content_id) VALUES ('$this->id','$content_id')"; $db->ExecSqlUpdate($sql, false); } /** Remove content from this node */ public function removeContent(Content $content) { global $db; $content_id = $db->EscapeString($content->getId()); $sql = "DELETE FROM node_has_content WHERE node_id='$this->id' AND content_id='$content_id'"; $db->ExecSqlUpdate($sql, false); } /**Get an array of all Content linked to this node * @param boolean $exclude_subscribed_content * @param User $subscriber The User object used to discriminate the content * @param $display_location Only select the content to be displayed in thios * area. Defaults to 'portal_page' * @return an array of Content or an empty arrray */ function getAllContent($exclude_subscribed_content = false, $subscriber = null, $display_location='portal_page') { global $db; $retval = array (); $content_rows = null; // Get all network, but exclude user subscribed content if asked if ($exclude_subscribed_content == true && $subscriber) $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"; else $sql = "SELECT content_id FROM node_has_content WHERE node_id='{$this->id}' AND display_location='$display_location' ORDER BY subscribe_timestamp DESC"; $db->ExecSql($sql, $content_rows, false); if ($content_rows != null) { foreach ($content_rows as $content_row) { $retval[] = Content :: getObject($content_row['content_id']); } } return $retval; } /** Get an array of all artistic and locative Content for this hotspot * @return an array of Content or an empty arrray */ function getAllLocativeArtisticContent() { global $db; $retval = array (); $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"; $content_rows = null; $db->ExecSql($sql, $content_rows, false); if ($content_rows != null) { foreach ($content_rows as $content_row) { // Create a content group object and grab only those that have content for the current Node $content_group = Content :: getObject($content_row['content_group_id']); if ($content_group->getDisplayNumElements() >= 1) { if ($content_group->isDisplayableAt($this)) { // Disable logging and allow content to expand ( if possible ) $content_group->setExpandStatus(true); $content_group->setLoggingStatus(false); $retval[] = $content_group; } } } } return $retval; } /** The list of users online at this node * @return An array of User object, or en empty array */ function getOnlineUsers() { global $db; $retval = array (); $users = null; $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); if ($users != null) { foreach ($users as $user_row) { $retval[] = User :: getObject($user_row['user_id']); } } return $retval; } /** Find out how many users are online this specific Node * @return Number of online users */ function getNumOnlineUsers() { global $db; $retval = array (); $row = null; $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); return $row['count']; } /** The list of all real owners of this node * @return An array of User object, or en empty array */ function getOwners() { global $db; $retval = array (); $owners = null; $db->ExecSql("SELECT user_id FROM node_stakeholders WHERE is_owner = true AND node_id='{$this->id}'", $owners, false); if ($owners != null) { foreach ($owners as $owner_row) { $retval[] = User :: getObject($owner_row['user_id']); } } return $retval; } /** The list of all Technical officers of this node. * Technical officers are displayed highlited and in the online user's list, * and are contacted when the Node goes down. * @return An array of User object, or en empty array */ function getTechnicalOfficers() { global $db; $retval = array (); $officers = null; $db->ExecSql("SELECT user_id FROM node_stakeholders WHERE is_tech_officer = true AND node_id='{$this->id}'", $officers, false); if ($officers != null) { foreach ($officers as $officer_row) { $retval[] = User :: getObject($officer_row['user_id']); } } return $retval; } /** Associates an owner to this node * @param User */ function addOwner(User $user) { global $db; $rows = null; $db->ExecSql("SELECT * FROM node_stakeholders WHERE node_id = '{$this->getId()}' AND user_id = '{$user->getId()}'", $rows, false); if (!$rows) { if (!$db->ExecSqlUpdate("INSERT INTO node_stakeholders (node_id, user_id, is_owner) VALUES ('{$this->getId()}','{$user->getId()}', true)", false)) throw new Exception(_('Could not add owner')); } else if (!$db->ExecSqlUpdate("UPDATE node_stakeholders SET is_owner = true WHERE node_id = '{$this->getId()}' AND user_id = '{$user->getId()}';", false)) throw new Exception(_('Could not add owner')); } /** Associates a technical officer ( tech support ) to this node * @param User */ function addTechnicalOfficer(User $user) { global $db; $rows = null; $db->ExecSql("SELECT * FROM node_stakeholders WHERE node_id = '{$this->getId()}' AND user_id = '{$user->getId()}'", $rows, false); if (!$rows) { if (!$db->ExecSqlUpdate("INSERT INTO node_stakeholders (node_id, user_id, is_tech_officer) VALUES ('{$this->getId()}','{$user->getId()}', true)", false)) throw new Exception(_('Could not add tech officer')); } else if (!$db->ExecSqlUpdate("UPDATE node_stakeholders SET is_tech_officer = true WHERE node_id = '{$this->getId()}' AND user_id = '{$user->getId()}';", false)) throw new Exception(_('Could not set existing user as tech officer')); } /** Remove owner flag for a stakeholder of this node * @param User */ function removeOwner(User $user) { global $db; if (!$db->ExecSqlUpdate("UPDATE node_stakeholders SET is_owner = false WHERE node_id = '{$this->getId()}' AND user_id = '{$user->getId()}';", false)) throw new Exception(_('Could not remove owner')); } /** Remove technical officer flag for a stakeholder of this node * @param User */ function removeTechnicalOfficer(User $user) { global $db; if (!$db->ExecSqlUpdate("UPDATE node_stakeholders SET is_tech_officer = false WHERE node_id = '{$this->getId()}' AND user_id = '{$user->getId()}';", false)) throw new Exception(_('Could not remove tech officer')); } /** Is the user an owner of the Node? * @return true our false*/ function isOwner(User $user) { global $db; if ($user != null) { $user_id = $user->getId(); $retval = false; $row = null; $db->ExecSqlUniqueRes("SELECT * FROM node_stakeholders WHERE is_owner = true AND node_id='{$this->id}' AND user_id='{$user_id}'", $row, false); if ($row != null) { $retval = true; } } return $retval; } /** Is the user a technical officer of the Node? * @return true our false*/ function isTechnicalOfficer(User $user) { global $db; if ($user != null) { $user_id = $user->getId(); $retval = false; $row = null; $db->ExecSqlUniqueRes("SELECT * FROM node_stakeholders WHERE is_tech_officer = true AND node_id='{$this->id}' AND user_id='{$user_id}'", $row, false); if ($row != null) { $retval = true; } } return $retval; } /** Check if an node exists */ private function nodeExists($id) { global $db; $retval = false; $id_str = $db->EscapeString($id); $sql = "SELECT * FROM nodes WHERE node_id='{$id_str}'"; $row = null; $db->ExecSqlUniqueRes($sql, $row, false); if ($row != null) { $retval = true; } return $retval; } /** Reloads the object from the database. Should normally be called after a set operation */ protected function refresh() { $this->__construct($this->id); } } // End class ?>