Notifications API

added get all notification by summit endpoint
allows ordering, paging and filtering.

Change-Id: I45cd3d059695e7e86395b93d94f566efaf738767
This commit is contained in:
Sebastian Marcet 2016-09-09 19:12:54 -03:00
parent d483119a20
commit 42a7e3607c
29 changed files with 1090 additions and 61 deletions

View File

@ -29,6 +29,7 @@ use models\summit\ISummitRepository;
use ModelSerializers\SerializerRegistry;
use services\model\ISummitService;
use utils\FilterParser;
use utils\FilterParserException;
use utils\OrderParser;
use utils\PagingInfo;
@ -590,7 +591,12 @@ final class OAuth2SummitEventsApiController extends OAuth2ProtectedController
return $this->ok($response->toArray(Request::input('expand', '')));
} catch (Exception $ex) {
}
catch(FilterParserException $ex1){
Log::warning($ex1);
return $this->error412($ex1->getMessages());
}
catch (Exception $ex) {
Log::error($ex);
return $this->error500($ex);
}

View File

@ -28,6 +28,7 @@ use ModelSerializers\SerializerRegistry;
use services\model\ISummitService;
use utils\Filter;
use utils\FilterParser;
use utils\FilterParserException;
use utils\PagingInfo;
use utils\PagingResponse;
@ -206,6 +207,10 @@ final class OAuth2SummitLocationsApiController extends OAuth2ProtectedController
Log::warning($ex2);
return $this->error412($ex2->getMessages());
}
catch(FilterParserException $ex3){
Log::warning($ex3);
return $this->error412($ex3->getMessages());
}
catch (Exception $ex) {
Log::error($ex);
return $this->error500($ex);
@ -231,6 +236,10 @@ final class OAuth2SummitLocationsApiController extends OAuth2ProtectedController
Log::warning($ex2);
return $this->error412($ex2->getMessages());
}
catch(FilterParserException $ex3){
Log::warning($ex3);
return $this->error412($ex3->getMessages());
}
catch (Exception $ex) {
Log::error($ex);
return $this->error500($ex);

View File

@ -0,0 +1,146 @@
<?php namespace App\Http\Controllers;
/**
* Copyright 2016 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use models\exceptions\EntityNotFoundException;
use models\exceptions\ValidationException;
use models\oauth2\IResourceServerContext;
use models\summit\ISummitNotificationRepository;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Input;
use models\summit\ISummitRepository;
use models\summit\SummitPushNotificationChannel;
use utils\FilterParser;
use utils\FilterParserException;
use utils\OrderParser;
use utils\PagingInfo;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Request;
/**
* Class OAuth2SummitNotificationsApiController
* @package App\Http\Controllers
*/
class OAuth2SummitNotificationsApiController extends OAuth2ProtectedController
{
/**
* @var ISummitRepository
*/
private $summit_repository;
public function __construct
(
ISummitRepository $summit_repository,
ISummitNotificationRepository $notification_repository,
IResourceServerContext $resource_server_context
) {
parent::__construct($resource_server_context);
$this->repository = $notification_repository;
$this->summit_repository = $summit_repository;
}
/**
* @param $summit_id
* @return mixed
*/
public function getAll($summit_id)
{
try
{
$summit = SummitFinderStrategyFactory::build($this->summit_repository)->find($summit_id);
if (is_null($summit)) return $this->error404();
$values = Input::all();
$rules = array
(
'page' => 'integer|min:1',
'per_page' => 'required_with:page|integer|min:5|max:100',
);
$validation = Validator::make($values, $rules);
if ($validation->fails()) {
$ex = new ValidationException();
throw $ex->setMessages($validation->messages()->toArray());
}
// default values
$page = 1;
$per_page = 5;
if (Input::has('page')) {
$page = intval(Input::get('page'));
$per_page = intval(Input::get('per_page'));
}
$filter = null;
if (Input::has('filter')) {
$filter = FilterParser::parse(Input::get('filter'), [
'channel' => ['=='],
'sent_date' => ['>', '<', '<=', '>=', '=='],
'created' => ['>', '<', '<=', '>=', '=='],
'is_sent' => ['=='],
'event_id' => ['=='],
]);
$channels = $filter->getFlatFilter("channel");
// validate that channel filter, if present if for a public one
if(!is_null($channels) && is_array($channels)){
foreach ($channels as $element){
if(!SummitPushNotificationChannel::isPublicChannel($element->getValue()))
throw new ValidationException(sprintf("%s channel is not public!", $element->getValue()));
}
}
}
$order = null;
if (Input::has('order'))
{
$order = OrderParser::parse(Input::get('order'), array
(
'sent_date',
'created',
'id',
));
}
$result = $this->repository->getAllByPage($summit, new PagingInfo($page, $per_page), $filter, $order);
return $this->ok
(
$result->toArray(Request::input('expand', ''),[],[],['summit_id' => $summit_id])
);
}
catch (EntityNotFoundException $ex1)
{
Log::warning($ex1);
return $this->error404();
}
catch (ValidationException $ex2)
{
Log::warning($ex2);
return $this->error412($ex2->getMessages());
}
catch(FilterParserException $ex3){
Log::warning($ex3);
return $this->error412($ex3->getMessages());
}
catch (\Exception $ex)
{
Log::error($ex);
return $this->error500($ex);
}
}
}

View File

@ -25,6 +25,7 @@ use models\summit\ISummitRepository;
use ModelSerializers\SerializerRegistry;
use services\model\ISummitService;
use utils\FilterParser;
use utils\FilterParserException;
use utils\OrderParser;
use utils\PagingInfo;
@ -143,6 +144,10 @@ final class OAuth2SummitSpeakersApiController extends OAuth2ProtectedController
$result->toArray(Request::input('expand', ''),[],[],['summit_id' => $summit_id, 'published' => true])
);
}
catch(FilterParserException $ex1){
Log::warning($ex1);
return $this->error412($ex1->getMessages());
}
catch (Exception $ex)
{
Log::error($ex);

View File

@ -55,7 +55,9 @@ class DoctrineJoinFilterMapping extends FilterMapping
public function apply(QueryBuilder $query, FilterElement $filter){
$where = str_replace(":value", $filter->getValue(), $this->where);
$where = str_replace(":operator", $filter->getOperator(), $where);
return $query->innerJoin($this->table, $this->alias, Join::WITH, $where);
if(!in_array($this->alias, $query->getAllAliases()))
$query->innerJoin($this->table, $this->alias, Join::WITH);
return $query->andWhere($where);
}
/**
@ -66,6 +68,8 @@ class DoctrineJoinFilterMapping extends FilterMapping
public function applyOr(QueryBuilder $query, FilterElement $filter){
$where = str_replace(":value", $filter->getValue(), $this->where);
$where = str_replace(":operator", $filter->getOperator(), $where);
return $query->innerJoin($this->table, $this->alias, Join::WITH)->orWhere($where);
if(!in_array($this->alias, $query->getAllAliases()))
$query->innerJoin($this->table, $this->alias, Join::WITH);
return $query->orWhere($where);
}
}

View File

@ -48,6 +48,7 @@ final class Filter
}
/**
* will return an array of filter elements, OR filters are returned on a sub array
* @param string $field
* @return null|FilterElement[]
*/
@ -55,17 +56,44 @@ final class Filter
{
$res = array();
foreach ($this->filters as $filter) {
if ($filter instanceof FilterElement && $filter->getField() === $field) {
$res[] = $filter;
} else if (is_array($filter)) {
}
else if (is_array($filter)) {
// OR
$or_res = array();
foreach ($filter as $e) {
if ($e instanceof FilterElement && $e->getField() === $field) {
array_push($or_res, $e);
$or_res[] = $e;
}
}
if (count($or_res)) array_push($res, $or_res);
if (count($or_res)) $res[] = $or_res;
}
}
return $res;
}
/**
* @param string $field
* @return null|FilterElement[]
*/
public function getFlatFilter($field)
{
$res = array();
foreach ($this->filters as $filter) {
if ($filter instanceof FilterElement && $filter->getField() === $field) {
$res[] = $filter;
}
else if (is_array($filter)) {
// OR
foreach ($filter as $e) {
if ($e instanceof FilterElement && $e->getField() === $field) {
$res[] = $e;
}
}
}
}
return $res;
@ -88,7 +116,8 @@ final class Filter
}
$mapping = explode(':', $mapping);
$value = $filter->getValue();
$value = $filter->getValue();
if (count($mapping) > 1) {
$value = $this->convertValue($value, $mapping[1]);
}
@ -134,11 +163,13 @@ final class Filter
}
$mapping = explode(':', $mapping);
$value = $filter->getValue();
$value = $filter->getValue();
if (count($mapping) > 1) {
$value = $this->convertValue($value, $mapping[1]);
}
$query = $query->where($mapping[0] . ' ' . $filter->getOperator() . ' ' . $value);
$query = $query->andWhere(sprintf("%s %s %s",$mapping[0], $filter->getOperator(), $value));
}
else if (is_array($filter)) {
// OR
@ -151,12 +182,14 @@ final class Filter
continue;
}
$mapping = explode(':', $mapping);
$value = $filter->getValue();
$mapping = explode(':', $mapping);
$value = $e->getValue();
if (count($mapping) > 1) {
$value = $this->convertValue($value, $mapping[1]);
}
$query->orWhere($mapping[0], $e->getOperator(), $value);
$query->orWhere(sprintf("%s %s %s",$mapping[0], $e->getOperator(), $value));
}
}
}
@ -179,6 +212,9 @@ final class Filter
case 'json_int':
return intval($value);
break;
case 'json_string':
return sprintf("'%s'",$value);
break;
default:
return $value;
break;

View File

@ -17,63 +17,65 @@ final class FilterParser
/**
* @param mixed $filters
* @param array $allowed_fields
* @throws FilterParserException
* @return Filter
*/
public static function parse($filters, $allowed_fields = array())
{
$res = array();
$res = array();
$matches = array();
if(!is_array($filters))
if (!is_array($filters))
$filters = array($filters);
foreach($filters as $filter) // parse AND filters
foreach ($filters as $filter) // parse AND filters
{
$f = null;
// parse OR filters
$or_filters = explode(',', $filter);
if(count($or_filters) > 1)
{
if (count($or_filters) > 1) {
$f = array();
foreach ($or_filters as $of) {
//single filter
preg_match('/[=<>][=>@]{0,1}/', $of, $matches);
if(count($matches) === 1)
{
$op = $matches[0];
$operands = explode($op, $of);
$field = $operands[0];
$value = $operands[1];
if(!isset($allowed_fields[$field])) continue;
if(!in_array($op, $allowed_fields[$field])) continue;
$f_or = self::buildFilter($field, $op, $value);
if(!is_null($f_or))
array_push($f, $f_or);
}
}
}
else
{
//single filter
preg_match('/[=<>][=>@]{0,1}/', $filter, $matches);
if(count($matches) === 1)
{
if (count($matches) != 1)
throw new FilterParserException(sprintf("invalid OR filter format %s (should be [:FIELD_NAME:OPERAND:VALUE])", $of));
$op = $matches[0];
$operands = explode($op, $filter);
$operands = explode($op, $of);
$field = $operands[0];
$value = $operands[1];
if(!isset($allowed_fields[$field])) continue;
if(!in_array($op, $allowed_fields[$field])) continue;
$f = self::buildFilter($field, $op, $value);
if (!isset($allowed_fields[$field])) continue;
if (!in_array($op, $allowed_fields[$field])) continue;
$f_or = self::buildFilter($field, $op, $value);
if (!is_null($f_or))
array_push($f, $f_or);
}
} else {
//single filter
preg_match('/[=<>][=>@]{0,1}/', $filter, $matches);
if (count($matches) != 1)
throw new FilterParserException(sprintf("invalid filter format %s (should be [:FIELD_NAME:OPERAND:VALUE])", $filter));
$op = $matches[0];
$operands = explode($op, $filter);
$field = $operands[0];
$value = $operands[1];
if (!isset($allowed_fields[$field])) continue;
if (!in_array($op, $allowed_fields[$field])) continue;
$f = self::buildFilter($field, $op, $value);
}
if(!is_null($f))
if (!is_null($f))
array_push($res, $f);
}
return new Filter($res);
return new Filter($res);
}
/**
@ -86,8 +88,7 @@ final class FilterParser
*/
public static function buildFilter($field, $op, $value)
{
switch($op)
{
switch ($op) {
case '==':
return FilterElement::makeEqual($field, $value);
break;

View File

@ -0,0 +1,26 @@
<?php namespace utils;
/**
* Copyright 2016 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use models\exceptions\ValidationException;
/**
* Class FilterParserException
* @package utils
*/
final class FilterParserException extends ValidationException
{
public function __construct($message = "") {
parent::__construct($message, 0, null);
}
}

View File

@ -46,10 +46,6 @@ Route::group(array(
Route::group(array('prefix' => 'summits'), function () {
Route::get('', 'OAuth2SummitApiController@getSummits');
Route::group(array('prefix' => 'events'), function () {
Route::get('', 'OAuth2SummitApiController@getAllEvents');
Route::get('published', 'OAuth2SummitApiController@getAllEvents');
});
Route::group(array('prefix' => '{id}'), function () {
@ -79,6 +75,11 @@ Route::group(array(
});
});
// notifications
Route::group(array('prefix' => 'notifications'), function () {
Route::get('', 'OAuth2SummitNotificationsApiController@getAll');
});
// speakers
Route::group(array('prefix' => 'speakers'), function () {

View File

@ -0,0 +1,48 @@
<?php namespace ModelSerializers;
/**
* Copyright 2016 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use models\main\Group;
/**
* Class GroupSerializer
* @package ModelSerializers
*/
final class GroupSerializer extends SilverStripeSerializer
{
protected static $array_mappings = array
(
'Title' => 'title:json_string',
'Description' => 'description:json_string',
);
/**
* @param null $expand
* @param array $fields
* @param array $relations
* @param array $params
* @return array
*/
public function serialize($expand = null, array $fields = array(), array $relations = array(), array $params = array() )
{
$group = $this->object;
if(! $group instanceof Group) return [];
$values = parent::serialize($expand, $fields, $relations, $params);
$members = [];
foreach($group->getMembers() as $member){
$members[] = SerializerRegistry::getInstance()->getSerializer($member)->serialize();
}
$values['members'] = $members;
return $values;
}
}

View File

@ -77,10 +77,13 @@ final class SerializerRegistry
$this->registry['SummitAirport'] = SummitAirportSerializer::class;
$this->registry['SummitLocationImage'] = SummitLocationImageSerializer::class;
// member
$this->registry['Member'] = MemberSerializer::class;
$this->registry['Group'] = GroupSerializer::class;
// push notification
$this->registry['SummitPushNotification'] = SummitPushNotificationSerializer::class;
}
/**

View File

@ -0,0 +1,55 @@
<?php namespace ModelSerializers;
/**
* Copyright 2016 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use models\summit\SummitPushNotification;
use models\summit\SummitPushNotificationChannel;
/**
* Class SummitPushNotificationSerializer
* @package ModelSerializers
*/
final class SummitPushNotificationSerializer extends SilverStripeSerializer
{
protected static $array_mappings = array
(
'Channel' => 'channel:json_string',
'Message' => 'message:json_string',
'SentDate' => 'sent_date:datetime_epoch',
'Created' => 'created:datetime_epoch',
'IsSent' => 'is_sent:json_boolean',
);
/**
* @param null $expand
* @param array $fields
* @param array $relations
* @param array $params
* @return array
*/
public function serialize($expand = null, array $fields = array(), array $relations = array(), array $params = array() )
{
$notification = $this->object;
if(! $notification instanceof SummitPushNotification) return [];
$values = parent::serialize($expand, $fields, $relations, $params);
if($notification->getChannel() == SummitPushNotificationChannel::Event){
$values['event'] = SerializerRegistry::getInstance()->getSerializer($notification->getSummitEvent())->serialize();
}
if($notification->getChannel() == SummitPushNotificationChannel::Group){
$values['group'] = SerializerRegistry::getInstance()->getSerializer($notification->getGroup())->serialize();
}
return $values;
}
}

View File

@ -22,7 +22,7 @@ class ValidationException extends Exception
{
private $messages;
public function __construct($message= '', $code = 0, Exception $previous = null)
public function __construct($message = '', $code = 0, Exception $previous = null)
{
parent::__construct($message, $code, $previous);
}

View File

@ -0,0 +1,30 @@
<?php namespace models\main;
/**
* Copyright 2016 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use Doctrine\ORM\Mapping as ORM;
use models\utils\SilverstripeBaseModel;
/**
* @ORM\Entity
* @ORM\Table(name="CustomDataObject")
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="ClassName", type="string")
* @ORM\DiscriminatorMap({"CustomDataObject" = "CustomDataObject", "SummitPushNotification" = "models\summit\SummitPushNotification"})
* Class CustomDataObject
* @package models\main
*/
abstract class CustomDataObject extends SilverstripeBaseModel
{
}

View File

@ -0,0 +1,162 @@
<?php namespace models\main;
/**
* Copyright 2016 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use Doctrine\ORM\Mapping AS ORM;
use models\utils\SilverstripeBaseModel;
/**
* @ORM\Entity
* @ORM\Table(name="`Group`")
* Class Group
* @package models\main
*/
class Group extends SilverstripeBaseModel
{
public function __construct(){
parent::__construct();
$this->members = new ArrayCollection();
$this->groups = new ArrayCollection();
}
/**
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* @param string $title
*/
public function setTitle($title)
{
$this->title = $title;
}
/**
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* @param string $description
*/
public function setDescription($description)
{
$this->description = $description;
}
/**
* @return string
*/
public function getCode()
{
return $this->code;
}
/**
* @param string $code
*/
public function setCode($code)
{
$this->code = $code;
}
/**
* @return mixed
*/
public function getMembers()
{
return $this->members;
}
/**
* @param mixed $members
*/
public function setMembers($members)
{
$this->members = $members;
}
/**
* @return mixed
*/
public function getParent()
{
return $this->parent;
}
/**
* @param mixed $parent
*/
public function setParent($parent)
{
$this->parent = $parent;
}
/**
* @return mixed
*/
public function getGroups()
{
return $this->groups;
}
/**
* @param mixed $groups
*/
public function setGroups($groups)
{
$this->groups = $groups;
}
/**
* @ORM\Column(name="Title", type="string")
* @var string
*/
private $title;
/**
* @ORM\Column(name="Description", type="string")
* @var string
*/
private $description;
/**
* @ORM\Column(name="Code", type="string")
* @var string
*/
private $code;
/**
* @ORM\ManyToMany(targetEntity="models\main\Member", mappedBy="groups")
*/
private $members;
/**
* @ORM\ManyToOne(targetEntity="Group", inversedBy="groups")
* @ORM\JoinColumn(name="ParentID", referencedColumnName="ID")
*/
private $parent;
/**
* @ORM\OneToMany(targetEntity="Group", mappedBy="parent")
*/
private $groups;
}

View File

@ -27,6 +27,37 @@ use Doctrine\ORM\Mapping AS ORM;
*/
class Member extends SilverstripeBaseModel
{
/**
* @return mixed
*/
public function getGroups()
{
return $this->groups;
}
/**
* @param mixed $groups
*/
public function setGroups($groups)
{
$this->groups = $groups;
}
public function __construct(){
parent::__construct();
$this->feedback = new ArrayCollection();
$this->groups = new ArrayCollection();
}
/**
* @ORM\ManyToMany(targetEntity="models\main\Group", inversedBy="members")
* @ORM\JoinTable(name="Group_Members",
* joinColumns={@ORM\JoinColumn(name="MemberID", referencedColumnName="ID")},
* inverseJoinColumns={@ORM\JoinColumn(name="GroupID", referencedColumnName="ID")}
* )
*/
private $groups;
/**
* @return string
*/
@ -137,12 +168,6 @@ class Member extends SilverstripeBaseModel
*/
private $feedback;
public function __construct()
{
parent::__construct();
$this->feedback = new ArrayCollection();
}
/**
* @return File
*/

View File

@ -0,0 +1,35 @@
<?php namespace models\summit;
/**
* Copyright 2016 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use models\utils\IBaseRepository;
use utils\Filter;
use utils\Order;
use utils\PagingInfo;
use utils\PagingResponse;
/**
* Interface ISummitNotificationRepository
* @package models\summit
*/
interface ISummitNotificationRepository extends IBaseRepository
{
/**
* @param Summit $summit
* @param PagingInfo $paging_info
* @param Filter|null $filter
* @param Order|null $order
* @return PagingResponse
*/
public function getAllByPage(Summit $summit, PagingInfo $paging_info, Filter $filter = null, Order $order = null);
}

View File

@ -0,0 +1,259 @@
<?php namespace models\summit;
/**
* Copyright 2016 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use models\main\CustomDataObject;
use models\main\Group;
use models\main\Member;
/**
* Class SummitPushNotificationChannel
* @package models\summit
*/
final class SummitPushNotificationChannel {
const Everyone = 'EVERYONE';
const Speakers = 'SPEAKERS';
const Attendees = 'ATTENDEES';
const Members = 'MEMBERS';
const Summit = 'SUMMIT';
const Event = 'EVENT';
const Group = 'GROUP';
/**
* @return array
*/
public static function getPublicChannels(){
return [self::Everyone, self::Speakers, self::Attendees, self::Summit, self::Event, self::Group];
}
/**
* @param string $channel
* @return bool
*/
public static function isPublicChannel($channel){
return in_array($channel, self::getPublicChannels());
}
}
/**
* @ORM\Entity
* @ORM\Table(name="SummitPushNotification")
* @ORM\Entity(repositoryClass="repositories\summit\DoctrineSummitNotificationRepository")
* Class SummitPushNotification
* @package models\summit
*/
class SummitPushNotification extends CustomDataObject
{
use SummitOwned;
/**
* @ORM\Column(name="Channel", type="string")
* @var string
*/
private $channel;
/**
* @return string
*/
public function getChannel()
{
return $this->channel;
}
/**
* @param string $channel
*/
public function setChannel($channel)
{
$this->channel = $channel;
}
/**
* @return string
*/
public function getMessage()
{
return $this->message;
}
/**
* @param string $message
*/
public function setMessage($message)
{
$this->message = $message;
}
/**
* @return \DateTime
*/
public function getSentDate()
{
return $this->sent_date;
}
/**
* @param \DateTime $sent_date
*/
public function setSentDate($sent_date)
{
$this->sent_date = $sent_date;
}
/**
* @return boolean
*/
public function isSent()
{
return $this->is_sent;
}
/**
* @return boolean
*/
public function getIsSent()
{
return $this->isSent();
}
/**
* @param boolean $is_sent
*/
public function setIsSent($is_sent)
{
$this->is_sent = $is_sent;
}
/**
* @return Member
*/
public function getOwner()
{
return $this->owner;
}
/**
* @param Member $owner
*/
public function setOwner($owner)
{
$this->owner = $owner;
}
/**
* @return SummitEvent
*/
public function getSummitEvent()
{
return $this->summit_event;
}
/**
* @param SummitEvent $summit_event
*/
public function setSummitEvent($summit_event)
{
$this->summit_event = $summit_event;
}
/**
* @return Group
*/
public function getGroup()
{
return $this->group;
}
/**
* @param Group $group
*/
public function setGroup($group)
{
$this->group = $group;
}
/**
* @return ArrayCollection
*/
public function getRecipients()
{
return $this->recipients;
}
/**
* @param ArrayCollection $recipients
*/
public function setRecipients($recipients)
{
$this->recipients = $recipients;
}
/**
* @ORM\Column(name="Message", type="string")
* @var string
*/
private $message;
/**
* @ORM\Column(name="SentDate", type="datetime")
* @var \DateTime
*/
private $sent_date;
/**
* @ORM\Column(name="IsSent", type="boolean")
* @var bool
*/
private $is_sent;
/**
* @ORM\ManyToOne(targetEntity="models\main\Member")
* @ORM\JoinColumn(name="OwnerID", referencedColumnName="ID")
* @var Member
*/
private $owner;
/**
* @ORM\ManyToOne(targetEntity="models\summit\SummitEvent")
* @ORM\JoinColumn(name="EventID", referencedColumnName="ID")
* @var SummitEvent
*/
private $summit_event;
/**
* @ORM\ManyToOne(targetEntity="models\main\Group")
* @ORM\JoinColumn(name="GroupID", referencedColumnName="ID")
* @var Group
*/
private $group;
/**
* @ORM\ManyToMany(targetEntity="models\main\Member")
* @ORM\JoinTable(name="SummitPushNotification_Recipients",
* joinColumns={@ORM\JoinColumn(name="SummitPushNotificationID", referencedColumnName="ID")},
* inverseJoinColumns={@ORM\JoinColumn(name="MemberID", referencedColumnName="ID")}
* )
*/
private $recipients;
/**
* SummitPushNotification constructor.
*/
public function __construct()
{
parent::__construct();
$this->recipients = new ArrayCollection();
}
}

View File

@ -98,5 +98,11 @@ class RepositoriesProvider extends ServiceProvider
function(){
return EntityManager::getRepository(\models\summit\SummitAttendeeTicket::class);
});
App::singleton(
'models\summit\ISummitNotificationRepository',
function(){
return EntityManager::getRepository(\models\summit\SummitPushNotification::class);
});
}
}

View File

@ -22,6 +22,7 @@ use utils\PagingResponse;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Tools\Pagination\Paginator;
use Doctrine\ORM\Query\Expr\Join;
/**
* Class DoctrineEventFeedbackRepository
*/

View File

@ -0,0 +1,97 @@
<?php namespace repositories\summit;
/**
* Copyright 2016 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\Tools\Pagination\Paginator;
use models\summit\ISummitNotificationRepository;
use models\summit\Summit;
use repositories\SilverStripeDoctrineRepository;
use utils\Filter;
use utils\Order;
use utils\PagingInfo;
use utils\PagingResponse;
/**
* Class DoctrineSummitNotificationRepository
* @package repositories\summit
*/
final class DoctrineSummitNotificationRepository
extends SilverStripeDoctrineRepository
implements ISummitNotificationRepository
{
/**
* @param Summit $summit
* @param PagingInfo $paging_info
* @param Filter|null $filter
* @param Order|null $order
* @return PagingResponse
*/
public function getAllByPage(Summit $summit, PagingInfo $paging_info, Filter $filter = null, Order $order = null)
{
$query = $this->getEntityManager()->createQueryBuilder()
->select("n")
->from(\models\summit\SummitPushNotification::class, "n")
->leftJoin('n.summit_event', 'e')
->join('n.summit', 's', Join::WITH, " s.id = :summit_id")
->setParameter('summit_id', $summit->getId());
if (!is_null($filter)) {
$filter->apply2Query($query, array
(
'event_id' => 'e.id:json_int',
'channel' => 'n.channel:json_string',
'sent_date' => 'n.sent_date:datetime_epoch',
'created' => 'n.created:datetime_epoch',
'is_sent' => 'n.is_sent:json_int',
));
}
if (!is_null($order)) {
$order->apply2Query($query, array
(
'sent_date' => 'n.sent_date',
'created' => 'n.created',
'id' => 'n.id',
));
} else {
//default order
$query = $query->orderBy('n.id', Criteria::DESC);
}
$query = $query
->setFirstResult($paging_info->getOffset())
->setMaxResults($paging_info->getPerPage());
$paginator = new Paginator($query, $fetchJoinCollection = true);
$total = $paginator->count();
$data = array();
foreach ($paginator as $entity)
array_push($data, $entity);
return new PagingResponse
(
$total,
$paging_info->getPerPage(),
$paging_info->getCurrentPage(),
$paging_info->getLastPage($total),
$data
);
}
}

View File

@ -573,6 +573,19 @@ class ApiEndpointsSeeder extends Seeder
)
);
// notifications
ApiEndpoint::create(
array(
'name' => 'get-notifications',
'active' => true,
'api_id' => $summit->id,
'route' => '/api/v1/summits/{id}/notifications',
'http_method' => 'GET'
)
);
$member_read_scope = ApiScope::where('name', '=', sprintf('%s/me/read', $current_realm))->first();
$summit_read_scope = ApiScope::where('name', '=', sprintf('%s/summits/read', $current_realm))->first();
$summit_write_scope = ApiScope::where('name', '=', sprintf('%s/summits/write', $current_realm))->first();
@ -582,6 +595,7 @@ class ApiEndpointsSeeder extends Seeder
$summit_external_order_read = ApiScope::where('name', '=', sprintf('%s/summits/read-external-orders', $current_realm))->first();
$summit_external_order_confirm = ApiScope::where('name', '=', sprintf('%s/summits/confirm-external-orders', $current_realm))->first();
$write_videos_scope = ApiScope::where('name', '=', sprintf('%s/summits/write-videos', $current_realm))->first();
$read_notifications = ApiScope::where('name', '=', sprintf('%s/summits/read-notifications', $current_realm))->first();
// read
$endpoint = ApiEndpoint::where('name', '=', 'get-summits')->first();
@ -630,11 +644,16 @@ class ApiEndpointsSeeder extends Seeder
$endpoint->scopes()->attach($summit_read_scope->id);
$endpoint = ApiEndpoint::where('name', '=', 'get-location-events')->first();
$endpoint->scopes()->attach($summit_read_scope->id);
//read external orders
// read external orders
$endpoint = ApiEndpoint::where('name', '=', 'get-external-order')->first();
$endpoint->scopes()->attach($summit_external_order_read->id);
// read notifications
$endpoint = ApiEndpoint::where('name', '=', 'get-notifications')->first();
$endpoint->scopes()->attach($read_notifications->id);
// write
$endpoint = ApiEndpoint::where('name', '=', 'delete-event-attendee-schedule')->first();

View File

@ -180,6 +180,16 @@ class ApiScopesSeeder extends Seeder
'system' => false
)
);
ApiScope::create(
array(
'name' => sprintf('%s/summits/read-notifications', $current_realm),
'short_description' => 'Allow to read summit notifications',
'description' => 'Allow to read summit notifications',
'api_id' => $summits->id,
'system' => false
)
);
}
}

View File

@ -1624,11 +1624,11 @@ final class OAuth2SummitApiTest extends ProtectedApiTest
{
$params = array
(
'id' => 6,
'location_id' => 25,
'id' => 7,
'location_id' => 143,
'filter' => array
(
'speaker=@Alex',
'speaker=@Morgan',
)
);
@ -1718,4 +1718,41 @@ final class OAuth2SummitApiTest extends ProtectedApiTest
$this->assertTrue(!is_null($member));
}
public function testGetSummitNotifications(){
$params = array
(
'id' => 7,
'page' => 1,
'per_page' => 15,
'filter' => [
'channel=='.\models\summit\SummitPushNotificationChannel::Event.',channel=='.\models\summit\SummitPushNotificationChannel::Group,
],
'order' => '+sent_date'
);
$headers = array
(
"HTTP_Authorization" => " Bearer " .$this->access_token,
"CONTENT_TYPE" => "application/json"
);
$response = $this->action
(
"GET",
"OAuth2SummitNotificationsApiController@getAll",
$params,
array(),
array(),
array(),
$headers
);
$content = $response->getContent();
$this->assertResponseStatus(200);
$notifications = json_decode($content);
$this->assertTrue(!is_null($notifications));
}
}

View File

@ -11,6 +11,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use models\oauth2\AccessToken;
@ -46,6 +47,7 @@ class AccessTokenServiceStub implements IAccessTokenService
$url . '/summits/confirm-external-orders',
$url . '/summits/write-videos',
$url . '/me/read',
$url . '/summits/read-notifications',
);
return AccessToken::createFromParams('123456789', implode(' ', $scopes), '1', $realm, '1','11624', 3600, 'WEB_APPLICATION', '', '');
@ -80,6 +82,7 @@ class AccessTokenServiceStub2 implements IAccessTokenService
$url . '/summits/write-videos',
$url . '/summits/write-videos',
$url . '/me/read',
$url . '/summits/read-notifications',
);
return AccessToken::createFromParams('123456789', implode(' ', $scopes), '1', $realm, null,null, 3600, 'SERVICE', '', '');

5
update_doctrine.sh Executable file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env bash
php artisan doctrine:generate:proxies
php artisan doctrine:clear:metadata:cache
php artisan doctrine:clear:query:cache
php artisan doctrine:clear:result:cache