diff --git a/src/module/Phpug/config/module.config.php b/src/module/Phpug/config/module.config.php
index 3d4526e..de699a4 100644
--- a/src/module/Phpug/config/module.config.php
+++ b/src/module/Phpug/config/module.config.php
@@ -444,6 +444,7 @@
'Phpug\Api\Rest\Twitter' => 'Phpug\Api\Rest\TwitterController',
'Phpug\Api\v1\Usergroup' => 'Phpug\Api\v1\UsergroupController',
'Phpug\Api\v1\Calendar' => 'Phpug\Api\v1\CalendarController',
+ 'Phpug\Api\v1\Location' => 'Phpug\Api\v1\LocationController',
'Phpug\Controller\MentoringController' => 'Phpug\Controller\MentoringController',
'Phpug\Controller\EventCacheController' => 'Phpug\Controller\EventCacheController',
'Phpug\Controller\TwitterController' => 'Phpug\Controller\TwitterController',
diff --git a/src/module/Phpug/src/Phpug/Api/v1/CalendarController.php b/src/module/Phpug/src/Phpug/Api/v1/CalendarController.php
index 03aab45..9478d0c 100644
--- a/src/module/Phpug/src/Phpug/Api/v1/CalendarController.php
+++ b/src/module/Phpug/src/Phpug/Api/v1/CalendarController.php
@@ -31,6 +31,7 @@
namespace Phpug\Api\v1;
+use Phpug\ORM\Query\AST\Functions\DistanceFrom;
use Zend\Mvc\Controller\AbstractActionController;
use Sabre\VObject;
use Zend\Json\Json;
@@ -64,10 +65,16 @@ public function listAction()
$em = $this->getServiceLocator()->get('doctrine.entitymanager.orm_default');
$result = $em->getRepository('Phpug\Entity\Cache')->findBy(array('type' => 'event'));
$calendar = new VObject\Component\VCalendar();
+ $affectedUGs = $this->findGroupsWithinRangeAndDistance();
foreach ($result as $cal) {
if (! $cal->getGRoup()) {
continue;
}
+
+ if ($affectedUGs && ! in_array($cal->getGroup()->getShortname(), $affectedUGs)) {
+ continue;
+ }
+
try {
$ical = VObject\Reader::read($cal->getCache());
foreach ($ical->children as $event) {
@@ -81,7 +88,7 @@ public function listAction()
} catch(\Exception $e){}
}
-
+
$viewModel = $this->getViewModel();
return $viewModel->setVariable('calendar', new \Phpug\Wrapper\SabreVCalendarWrapper($calendar));
@@ -114,4 +121,43 @@ protected function setAcceptHeaderAccordingToParameters()
return $this;
}
+
+ protected function findGroupsWithinRangeAndDistance()
+ {
+ $lat = $this->params()->fromQuery('latitude', null);
+ $lon = $this->params()->fromQuery('longitude', null);
+ $distance = $this->params()->fromQuery('distance', null);
+ $number = $this->params()->fromQuery('count', null);
+
+ if (! $lat || ! $lon) {
+ return array();
+ }
+ /** @var \Doctrine\ORM\EntityManager $em */
+ $em = $this->getServiceLocator()->get('doctrine.entitymanager.orm_default');
+ DistanceFrom::setLatitudeField('latitude');
+ DistanceFrom::setLongitudeField('longitude');
+ DistanceFrom::setRadius(6367);
+ $em->getConfiguration()->addCustomNumericFunction('DISTANCEFROM', 'Phpug\ORM\Query\AST\Functions\DistanceFrom');
+
+ $qs = 'SELECT p, DISTANCEFROM(' . (float) $lat . ',' . (float) $lon . ') AS distance FROM \Phpug\Entity\Usergroup p WHERE p.state = 1 ';
+
+
+ if ($distance) {
+ $qs .= ' AND DISTANCEFROM(' . (float) $lat . ',' . (float) $lon . ') <= ' . (float) $distance;
+ }
+
+ $qs .= ' ORDER BY distance';
+
+ $query = $em->createQuery($qs);
+ if ($number) {
+ $query->setMaxResults($number);
+ }
+
+ $res = array();
+ foreach ($query->getResult() as $result) {
+ $res[] = $result[0]->getShortname();
+ }
+
+ return $res;
+ }
}
\ No newline at end of file
diff --git a/src/module/Phpug/src/Phpug/Api/v1/LocationController.php b/src/module/Phpug/src/Phpug/Api/v1/LocationController.php
new file mode 100644
index 0000000..59b1b32
--- /dev/null
+++ b/src/module/Phpug/src/Phpug/Api/v1/LocationController.php
@@ -0,0 +1,168 @@
+
+ * @copyright ©2014-2014 Andreas Heigl
+ * @license http://www.opesource.org/licenses/mit-license.php MIT-License
+ * @version 0.0
+ * @since 04.02.14
+ * @link https://github.com/heiglandreas/
+ */
+
+namespace Phpug\Api\v1;
+
+use Phpug\ORM\Query\AST\Functions\DistanceFrom;
+use Zend\Mvc\Controller\AbstractActionController;
+use Sabre\VObject;
+use Zend\Json\Json;
+
+class LocationController extends AbstractActionController
+{
+ private $acceptCriteria = array(
+ 'Zend\View\Model\JsonModel' => array(
+ 'application/json',
+ 'text/html',
+ ),
+ 'Zend\View\Model\FeedModel' => array('application/rss+xml'),
+ );
+
+ /**
+ * Get a list of groups that are nearest to the given coordinates.
+ *
+ * Coordinates are given via the parameters latlon,
+ * the maximum distance from the current location is given via distance
+ * and the maximum number of entries is given via the parameter max
+ *
+ * This method will then return the maximum number of entries within the given
+ * range. If less than the maximum number of entries is found within the distance
+ * only that number of entries will be returned. When no distance is given or the
+ * distance is given as "0" the maximum number of entries will be retrieved.
+ *
+ * @return mixed|\Zend\View\Model\ModelInterface
+ * @throws \UnexpectedValueException
+ */
+ public function nextGroupsAction()
+ {
+ $adapter = $this->getAdapter();
+ $response = $this->getResponse();
+ $viewModel = $this->getViewModel();
+
+ Json::$useBuiltinEncoderDecoder = true;
+
+ // Get Latitude, Longitude, distance and/or number of groups to retrieve
+ $latitude = $this->params()->fromQuery('latitude');
+ $longitude = $this->params()->fromQuery('longitude');
+ $distance = $this->params()->fromQuery('distance', null);
+ $number = $this->params()->fromQuery('count', null);
+
+
+ //$this->sorter = $this->getServiceManager('Phpug\Sorter\Usergroup\Distance');
+ $groups = $this->findGroupsWithinRangeAndDistance($latitude, $longitude, $distance, $number);
+ $return = array(
+ 'currentLocation' => array(
+ 'latitude' => $latitude,
+ 'longitude' => $longitude,
+ ),
+ 'groups' => array(),
+ );
+ // $hydrator = $this->getServiceManager('Phpug\Hydrator\Usergroup');
+ foreach ($groups as $group) {
+ $grp = array(
+ 'name' => $group[0]->getName(),
+ 'latitude' => $group[0]->getLatitude(),
+ 'longitude' => $group[0]->getLongitude(),
+ 'shortname' => $group[0]->getShortname(),
+ 'distance' => $group['distance'],
+ 'icalendar_url' => $group[0]->getIcalendar_url(),
+ 'url' => $group[0]->getUrl(),
+ 'contacts' => array(),
+ 'uri' => '',
+ );
+
+ foreach ($group[0]->getContacts() as $contact) {
+ $grp['contacts'][] = array(
+ 'service' => $contact->getServiceName(),
+ 'name' => $contact->getName(),
+ 'uri' => $contact->getUrl(),
+ );
+ }
+
+ $return['groups'][] = $grp;
+ }
+ $viewModel->setVariable('groups', $return);
+
+ return $viewModel;
+ }
+
+ protected function getAdapter()
+ {
+ $format = $this->params()->fromQuery('format', null);
+ switch ($format) {
+ case 'sphp':
+ $contentType = 'text/plain';
+ $adapter = '\Zend\Serializer\Adapter\PhpSerialize';
+ break;
+ case 'json':
+ default:
+ $contentType = 'application/json';
+ $adapter = '\Zend\Serializer\Adapter\Json';
+ break;
+ }
+ $this->getResponse()->getHeaders()->addHeaderLine('Content-Type', $contentType);
+
+ return new $adapter;
+ }
+
+ protected function getViewModel()
+ {
+ return $this->acceptableViewModelSelector($this->acceptCriteria);
+ }
+
+ protected function findGroupsWithinRangeAndDistance($lat, $lon, $distance = null, $number = null)
+ {
+ /** @var \Doctrine\ORM\EntityManager $em */
+ $em = $this->getServiceLocator()->get('doctrine.entitymanager.orm_default');
+ DistanceFrom::setLatitudeField('latitude');
+ DistanceFrom::setLongitudeField('longitude');
+ DistanceFrom::setRadius(6367);
+ $em->getConfiguration()->addCustomNumericFunction('DISTANCEFROM', 'Phpug\ORM\Query\AST\Functions\DistanceFrom');
+
+ $qs = 'SELECT p, DISTANCEFROM(' . (float) $lat . ',' . (float) $lon . ') AS distance FROM \Phpug\Entity\Usergroup p WHERE p.state = 1 ';
+
+
+ if ($distance) {
+ $qs .= ' AND DISTANCEFROM(' . (float) $lat . ',' . (float) $lon . ') <= ' . (float) $distance;
+ }
+
+ $qs .= ' ORDER BY distance';
+
+ $query = $em->createQuery($qs);
+ if ($number) {
+ $query->setMaxResults($number);
+ }
+
+ return $query->getResult();
+
+
+ }
+}
\ No newline at end of file
diff --git a/src/module/Phpug/src/Phpug/ORM/Query/AST/Functions/DistanceFrom.php b/src/module/Phpug/src/Phpug/ORM/Query/AST/Functions/DistanceFrom.php
new file mode 100644
index 0000000..e9a1b5c
--- /dev/null
+++ b/src/module/Phpug/src/Phpug/ORM/Query/AST/Functions/DistanceFrom.php
@@ -0,0 +1,129 @@
+
+ * @copyright ©2015-2015 Andreas Heigl
+ * @license http://www.opesource.org/licenses/mit-license.php MIT-License
+ * @version 0.0
+ * @since 25.03.15
+ * @link https://github.com/heiglandreas/
+ */
+
+namespace Phpug\ORM\Query\AST\Functions;
+
+
+use Doctrine\ORM\Query\AST\Functions\FunctionNode;
+use Doctrine\ORM\Query\Lexer;
+
+/**
+ * DistanceFromFunction ::= "DISTANCEFROM" "(" ArithmeticPrimary "," ArithmeticPrimary ")"
+ *
+ * This distance is calculated acording to http://www.movable-type.co.uk/scripts/gis-faq-5.1.html
+ *
+ * @see http://www.movable-type.co.uk/scripts/gis-faq-5.1.html
+ */
+class DistanceFrom extends FunctionNode
+{
+ protected static $latitudeField = 'latitude';
+ protected static $longitudeField = 'longitude';
+
+ /**
+ * This is the radius of the sphere.
+ *
+ * For the earth use 6367 for distance results in kilometers or
+ * ?? for results in miles.
+ *
+ * @var float
+ */
+ protected static $radius = 6367;
+
+ protected $latitude = null;
+
+ protected $longitude = null;
+
+
+ /**
+ * @param \Doctrine\ORM\Query\SqlWalker $sqlWalker
+ *
+ * @return string
+ */
+ public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
+ {
+ return sprintf(
+ '(asin(sqrt(pow(sin((%2$s*0.017453293-%4$f*0.017453293)/2),2) + cos(%2$s*0.017453293) * cos(%4$f*0.017453293) * pow(sin((%3$s*0.017453293-%5$f*0.017453293)/2),2))) * %1$f)',
+ self::getRadius(),
+ self::getLatitudeField(),
+ self::getLongitudeField(),
+ $this->latitude->dispatch($sqlWalker),
+ $this->longitude->dispatch($sqlWalker)
+ );
+ }
+
+ /**
+ * @param \Doctrine\ORM\Query\Parser $parser
+ *
+ * @return void
+ */
+ public function parse(\Doctrine\ORM\Query\Parser $parser)
+ {
+ $parser->match(Lexer::T_IDENTIFIER);
+ $parser->match(Lexer::T_OPEN_PARENTHESIS);
+ $this->latitude = $parser->ArithmeticPrimary();
+ $parser->match(Lexer::T_COMMA);
+ $this->longitude = $parser->ArithmeticPrimary();
+ $parser->match(Lexer::T_CLOSE_PARENTHESIS);
+
+ }
+
+ public static function getRadius()
+ {
+ return self::$radius;
+ }
+
+ public static function getLatitudeField()
+ {
+ return self::$latitudeField;
+ }
+
+ public static function getLongitudeField()
+ {
+ return self::$longitudeField;
+ }
+
+ public static function setLongitudeField($longitude)
+ {
+ self::$longitudeField = (string) $longitude;
+ }
+
+ public static function setLatitudeField($latitude)
+ {
+ self::$latitudeField = (string) $latitude;
+ }
+
+ public static function setRadius($radius)
+ {
+ self::$radius = (float) $radius;
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/module/Phpug/src/Phpug/Wrapper/SabreVCalendarWrapper.php b/src/module/Phpug/src/Phpug/Wrapper/SabreVCalendarWrapper.php
index 8083a9b..b9c4e92 100644
--- a/src/module/Phpug/src/Phpug/Wrapper/SabreVCalendarWrapper.php
+++ b/src/module/Phpug/src/Phpug/Wrapper/SabreVCalendarWrapper.php
@@ -62,6 +62,7 @@ public function getEvents(\DateInterval $interval)
$now = new \DateTime();
$then = (new \DateTime())->add($interval);
$this->object->expand($now, $then);
+ $return = array();
foreach ($this->object->children as $item) {
if (! $item instanceof VEvent) {
continue;