DefaultRequestListener.php
1 <?php
3 
8 
9 /**
10  * DefaultRequestListener normalizes various search, sort and paging parameters
11  * into those understood by wcmf controllers.
12  *
13  * @author ingo herwig <ingo@wemove.com>
14  */
16 
17  private $eventManager = null;
18  private $persistenceFacade = null;
19 
20  /**
21  * Constructor
22  */
23  public function __construct(EventManager $eventManager, PersistenceFacade $persistenceFacade) {
24  $this->eventManager = $eventManager;
25  $this->eventManager->addListener(ApplicationEvent::NAME, [$this, 'listen']);
26  $this->persistenceFacade = $persistenceFacade;
27  }
28 
29  /**
30  * Destructor
31  */
32  public function __destruct() {
33  $this->eventManager->removeListener(ApplicationEvent::NAME, [$this, 'listen']);
34  }
35 
36  /**
37  * Listen to ApplicationEvent
38  * @param $event ApplicationEvent instance
39  */
40  public function listen(ApplicationEvent $event) {
42  $request = $event->getRequest();
43  if ($request != null) {
44  $this->transformRequest($request);
45  }
46  }
48  $request = $event->getRequest();
49  $response = $event->getResponse();
50  if ($request != null && $response != null) {
51  $this->transformResponse($request, $response);
52  }
53  }
54  }
55 
56  protected function transformRequest($request) {
57  // transform range header into paging parameters
58  if ($request->hasHeader('Range')) {
59  if (preg_match('/^items=([\-]?[0-9]+)-([\-]?[0-9]+)$/', $request->getHeader('Range'), $matches)) {
60  $offset = intval($matches[1]);
61  $limit = intval($matches[2])-$offset+1;
62  $request->setValue('offset', $offset);
63  $request->setValue('limit', $limit);
64  }
65  }
66 
67  // transform position header into reference oid parameter for sorting
68  if ($request->hasHeader('Position')) {
69  $position = $request->getHeader('Position');
70  if ($position == 'last') {
71  $referenceOid = 'ORDER_BOTTOM';
72  }
73  else {
74  list($ignore, $orderReferenceIdStr) = preg_split('/ /', $position);
75  if ($request->hasValue('relation') && $request->hasValue('sourceOid')) {
76  // sort in relation
77  $sourceOid = ObjectId::parse($request->getValue('sourceOid'));
78  $relatedType = $this->getRelatedType($sourceOid, $request->getValue('relation'));
79  $referenceOid = new ObjectId($relatedType, $orderReferenceIdStr);
80  }
81  else {
82  // sort in root
83  $referenceOid = new ObjectId($request->getValue('className'), $orderReferenceIdStr);
84  }
85  }
86  $request->setValue('referenceOid', $referenceOid);
87  }
88 
89  // parse get parameters
90  foreach ($request->getValues() as $key => $value) {
91  // sort definition
92  if (preg_match('/^sort\(([^\)]+)\)$|sortBy=([.]+)$/', $key, $matches)) {
93  $sortDefs = preg_split('/,/', $matches[1]);
94  // ListController allows only one sortfield
95  $sortDef = $sortDefs[0];
96  $sortFieldName = substr($sortDef, 1);
97  $sortDirection = preg_match('/^-/', $sortDef) ? 'desc' : 'asc';
98  $request->setValue('sortFieldName', $sortFieldName);
99  $request->setValue('sortDirection', $sortDirection);
100  }
101  // limit
102  if (preg_match('/^limit\(([^\)]+)\)$/', $key, $matches)) {
103  $rangeDefs = preg_split('/,/', $matches[1]);
104  $limit = intval($rangeDefs[0]);
105  $offset = sizeof($rangeDefs) > 1 ? intval($rangeDefs[1]) : 0;
106  $request->setValue('offset', $offset);
107  $request->setValue('limit', $limit);
108  }
109  }
110  }
111 
112  protected function transformResponse($request, $response) {
113  // set content-range header
114  if ($response->hasValue('list')) {
115  $objects = $response->getValue('list');
116  $size = sizeof($objects);
117 
118  // set response range header
119  $offset = $request->getValue('offset');
120  $limit = $size == 0 ? $offset : $offset+$size-1;
121  $total = $response->getValue('totalCount');
122  $response->setHeader('Content-Range', 'items '.$offset.'-'.$limit.'/'.$total);
123  }
124  }
125 
126  /**
127  * Get the type that is used in the given role related to the
128  * given source object.
129  * @param $sourceOid ObjectId of the source object
130  * @param $role The role name
131  * @return String
132  */
133  protected function getRelatedType(ObjectId $sourceOid, $role) {
134  $sourceMapper = $this->persistenceFacade->getMapper($sourceOid->getType());
135  $relation = $sourceMapper->getRelation($role);
136  return $relation->getOtherType();
137  }
138 }
139 ?>
const AFTER_EXECUTE_CONTROLLER
A AFTER_EXECUTE_CONTROLLER event occurs after the current controller is executed.
EventManager is responsible for dispatching events to registered listeners.
getStage()
Get the stage at which the event occurred.
const BEFORE_ROUTE_ACTION
A BEFORE_ROUTE_ACTION event occurs before the request is mapped to an action key.
__construct(EventManager $eventManager, PersistenceFacade $persistenceFacade)
Constructor.
ObjectId is the unique identifier of an object.
Definition: ObjectId.php:28
listen(ApplicationEvent $event)
Listen to ApplicationEvent.
static parse($oid)
Parse a serialized object id string into an ObjectId instance.
Definition: ObjectId.php:135
PersistenceFacade defines the interface for PersistenceFacade implementations.
getType()
Get the type (including namespace)
Definition: ObjectId.php:97
ApplicationEvent instances are fired at different stages of the program flow.
addListener($eventName, $callback)
Register a listener for a given event.
getRelatedType(ObjectId $sourceOid, $role)
Get the type that is used in the given role related to the given source object.
DefaultRequestListener normalizes various search, sort and paging parameters into those understood by...