From 5f0399a97502cff0f56b489ae7254ce0dec13838 Mon Sep 17 00:00:00 2001 From: Gustavo Martin Morcuende Date: Wed, 23 May 2012 06:51:14 +0200 Subject: [PATCH] RESTFUL Web Service get ads by GPS --- .../modules/api/actions/actions.class.php | 32 +++++---- .../api/templates/getadsbygpsSuccess.json.php | 3 +- .../modules/category/actions/actions.class.php | 14 ++-- .../modules/category/templates/indexSuccess.php | 2 +- lib/model/doctrine/AdDescriptionTable.class.php | 78 ++++++++++++++++++++++ 5 files changed, 108 insertions(+), 21 deletions(-) diff --git a/apps/userfront/modules/api/actions/actions.class.php b/apps/userfront/modules/api/actions/actions.class.php index a41f588..d9fe629 100644 --- a/apps/userfront/modules/api/actions/actions.class.php +++ b/apps/userfront/modules/api/actions/actions.class.php @@ -5,8 +5,8 @@ * * @package mobileadvertising * @subpackage api - * @author Your name here - * @version SVN: $Id: actions.class.php 23810 2009-11-12 11:07:44Z Kris.Wallsmith $ + * @author Gustavo Martin Morcuende + * @version */ class apiActions extends sfActions { @@ -38,17 +38,23 @@ class apiActions extends sfActions */ public function executeGetadsbygps(sfWebRequest $request) { - //With RESTFUL is allowed to use cookies to get authentication (user / password) - $this->ads = AdTable::getInstance()->getAdsByGPSandUserId($this->getRoute()->getParameters(), $this->getUser()->getGuardUser()->getId()); - if (!$this->ads) - { - //If there are not results. - //In production replace this line by a die command (trying to stop wasting TCP bandwidth) - throw new sfError404Exception(sprintf(' - There are not offices with GPS coordinates: longitude "%s" and - latitude "%s".', $request->getParameter('longitude'), $request->getParameter('latitude'))); - //die; - } + //RESTFUL permits to use cookies to implement authentication (user / password) + $parameters = $this->getRoute()->getParameters(); + $userId = $this->getUser()->getGuardUser()->getId(); + + $this->ads = array(); + $this->ads = AdDescriptionTable::getInstance()->getAdsByGPSAndUserIdAndLanguageId($this->getRoute()->getParameters(), + $this->getUser()->getGuardUser()->getId(), + $this->getUser()->getGuardUser()->getLanguage()->getId()); + if (empty($this->ads)) + { + //If there are not results. + //In production replace this line by a die command (trying to stop wasting TCP bandwidth) + throw new sfError404Exception(sprintf(' + There are not offices with GPS coordinates: longitude "%s" and + latitude "%s".', $request->getParameter('longitude'), $request->getParameter('latitude'))); + //die; + } } /** diff --git a/apps/userfront/modules/api/templates/getadsbygpsSuccess.json.php b/apps/userfront/modules/api/templates/getadsbygpsSuccess.json.php index b951d93..ecbe959 100644 --- a/apps/userfront/modules/api/templates/getadsbygpsSuccess.json.php +++ b/apps/userfront/modules/api/templates/getadsbygpsSuccess.json.php @@ -1,5 +1,6 @@ [ - { "id" : "getId()?>", "domain" : "getDomain()?>", "link" : "getLinks()?>" }, + { "id" : "getAd()->getId()?>", "image" : "getAd()->getAdMobileImageLink() ?>", "link" : "getAdLink()?>", + "text" : "getAdMobileText()?>" }, ] diff --git a/apps/userfront/modules/category/actions/actions.class.php b/apps/userfront/modules/category/actions/actions.class.php index 3a2fecc..c59f661 100644 --- a/apps/userfront/modules/category/actions/actions.class.php +++ b/apps/userfront/modules/category/actions/actions.class.php @@ -86,6 +86,8 @@ class categoryActions extends sfActions //Get data from user $checked = $request->getParameter('checked'); + $uniqChecked = array_unique($checked, SORT_NUMERIC); + //We retrieve a Doctrine_Collection $userBaskets = UserBasketTable::getInstance()->findByUserId($userId); @@ -94,13 +96,13 @@ class categoryActions extends sfActions $iterator = $userBaskets->getIterator(); while ($userBasket = $iterator->current()) { - if (!empty($checked)) + if (!empty($uniqChecked)) { - foreach ($checked as $index => $value) + foreach ($uniqChecked as $index => $value) { if ($userBasket->getGeneralCategId() == $value) { - unset($checked[$index]); + unset($uniqChecked[$index]); $iterator->next(); continue 2; } @@ -110,9 +112,9 @@ class categoryActions extends sfActions $iterator->next(); } - if (!empty($checked)) + if (!empty($uniqChecked)) { - foreach ($checked as $index => $value) + foreach ($uniqChecked as $index => $value) { //Never trust in data coming from users... Performance vs security. $generalCategory = GeneralCategoryTable::getInstance()->findOneById($value); @@ -135,6 +137,6 @@ class categoryActions extends sfActions //Bypass completely the view layer and set the response code directly from this action. //In this way the user may know if the data were updated - return $this->renderText(json_encode($checked)); + return $this->renderText(json_encode($uniqChecked)); } } diff --git a/apps/userfront/modules/category/templates/indexSuccess.php b/apps/userfront/modules/category/templates/indexSuccess.php index 228997b..67c0f2e 100644 --- a/apps/userfront/modules/category/templates/indexSuccess.php +++ b/apps/userfront/modules/category/templates/indexSuccess.php @@ -14,7 +14,7 @@ }); $.post('', {'checked[]': checked}, function(data){ - alert("hola"); + alert("Updated successfully!"); }, "json"); }; diff --git a/lib/model/doctrine/AdDescriptionTable.class.php b/lib/model/doctrine/AdDescriptionTable.class.php index ba48ecc..a65c7f6 100644 --- a/lib/model/doctrine/AdDescriptionTable.class.php +++ b/lib/model/doctrine/AdDescriptionTable.class.php @@ -30,4 +30,82 @@ class AdDescriptionTable extends Doctrine_Table ->innerjoin('addescription.Ad ad') ->orderBy('ad.id'); } + + + public function getAdsByGPSAndUserIdAndLanguageId(array $parameters, $userId, $languageId) + { + $longitude = $parameters['longitude']; + $latitude = $parameters['latitude']; + $longitude = str_replace(',', '.', $longitude); + $latitude = str_replace(',', '.', $latitude); + + + // I will use this style to retrieve the radius because this is an Academic Project and I want to learn the ins and outs of using Symfony. + // I am wasting CPU cycles using this symfony helper. My Web Service will get worse cause this sentence. In production get the radius + // from a constant value or something like that. + $radius = sfConfig::get('app_radius', '100'); + + try{ + $adIds = Doctrine_Manager::getInstance()->getCurrentConnection()->fetchColumn( + "SELECT ad_id from office INNER JOIN office_ads ON (office_ads.office_id=office.id) + WHERE ST_DWithin(office_gps, ST_GeographyFromText('SRID=4326;POINT($longitude $latitude)'), $radius)" + ); + } + catch (Exception $e) + { + //In case of error return as soon as posible. + return null; + } + if (empty($adIds)) + { //There are not offices with those GPS coordinates. + //In many situations we will get this result, so a fast response. + return null; + } + + $uniqAdIds = array_unique($adIds, SORT_NUMERIC); + + //We can not waste time doing this query. What is the best way to achieve this goal? + //Is a direct query the best way? With big tables I think this is not going to work. + $adIds = array(); + foreach ($uniqAdIds as $uniqAdId) + { + try + { + $adIds[] = Doctrine_Manager::getInstance()->getCurrentConnection()->fetchOne( + "SELECT ad.id FROM ad INNER JOIN company_category ON (ad.company_categ_id=company_category.id) + INNER JOIN general_category ON (company_category.general_categ_id=general_category.id) + INNER JOIN user_basket ON (user_basket.general_categ_id=general_category.id) + WHERE user_id=$userId AND ad.id=$uniqAdId" + ); + } + catch (Exception $e) + { + //In case of error return as soon as posible. + return null; + } + } + if (empty($adIds)) + { + //There are not linked ads in those GPS coordinates with the specified user. + return null; + } + $ads = array(); + foreach($adIds as $adId) + { + //Array with Doctrine_Records Ads + $ad = $this->findOneByAdIdAndLanguageId($adId, $languageId); + if ($ad != null) + { + $ads[] = $ad; + } + else + { + //Return with the default language + $languageCode = sfConfig::get('app_default_language'); + $languageId = LanguageTable::getInstance()->findOneByCode($languageCode)->getId(); + $ads[] = $this->findOneByAdIdAndLanguageId($adId, $languageId); + } + } + return $ads; + } } -- 2.1.4