Open Monograph Press  3.3.0
PKPContextHandler.inc.php
1 <?php
15 import('lib.pkp.classes.handler.APIHandler');
16 
19  public $schemaName = SCHEMA_CONTEXT;
20 
24  public function __construct() {
25  $this->_handlerPath = 'contexts';
26  $roles = array(ROLE_ID_SITE_ADMIN, ROLE_ID_MANAGER);
27  $this->_endpoints = array(
28  'GET' => array(
29  array(
30  'pattern' => $this->getEndpointPattern(),
31  'handler' => array($this, 'getMany'),
32  'roles' => $roles,
33  ),
34  array(
35  'pattern' => $this->getEndpointPattern() . '/{contextId}',
36  'handler' => array($this, 'get'),
37  'roles' => $roles,
38  ),
39  array(
40  'pattern' => $this->getEndpointPattern() . '/{contextId}/theme',
41  'handler' => array($this, 'getTheme'),
42  'roles' => $roles,
43  ),
44  ),
45  'POST' => array(
46  array(
47  'pattern' => $this->getEndpointPattern(),
48  'handler' => array($this, 'add'),
49  'roles' => array(ROLE_ID_SITE_ADMIN),
50  ),
51  ),
52  'PUT' => array(
53  array(
54  'pattern' => $this->getEndpointPattern() . '/{contextId}',
55  'handler' => array($this, 'edit'),
56  'roles' => $roles,
57  ),
58  array(
59  'pattern' => $this->getEndpointPattern() . '/{contextId}/theme',
60  'handler' => array($this, 'editTheme'),
61  'roles' => $roles,
62  ),
63  ),
64  'DELETE' => array(
65  array(
66  'pattern' => $this->getEndpointPattern() . '/{contextId}',
67  'handler' => array($this, 'delete'),
68  'roles' => array(ROLE_ID_SITE_ADMIN),
69  ),
70  ),
71  );
72  parent::__construct();
73  }
74 
78  public function authorize($request, &$args, $roleAssignments) {
79  import('lib.pkp.classes.security.authorization.PolicySet');
80  $rolePolicy = new PolicySet(COMBINING_PERMIT_OVERRIDES);
81 
82  import('lib.pkp.classes.security.authorization.RoleBasedHandlerOperationPolicy');
83  foreach ($roleAssignments as $role => $operations) {
84  $rolePolicy->addPolicy(new RoleBasedHandlerOperationPolicy($request, $role, $operations));
85  }
86  $this->addPolicy($rolePolicy);
87 
88  return parent::authorize($request, $args, $roleAssignments);
89  }
90 
99  public function getMany($slimRequest, $response, $args) {
100  $request = $this->getRequest();
101 
102  $defaultParams = array(
103  'count' => 20,
104  'offset' => 0,
105  );
106 
107  $requestParams = array_merge($defaultParams, $slimRequest->getQueryParams());
108 
109  $allowedParams = array();
110 
111  // Process query params to format incoming data as needed
112  foreach ($requestParams as $param => $val) {
113  switch ($param) {
114  case 'isEnabled':
115  $allowedParams[$param] = (bool) $val;
116  break;
117 
118  case 'searchPhrase':
119  $allowedParams[$param] = trim($val);
120  break;
121 
122  case 'count':
123  $allowedParams[$param] = min(100, (int) $val);
124  break;
125 
126  case 'offset':
127  $allowedParams[$param] = (int) $val;
128  break;
129  }
130  }
131 
132  \HookRegistry::call('API::contexts::params', array(&$allowedParams, $slimRequest));
133 
134  // Anyone not a site admin should not be able to access contexts that are
135  // not enabled
136  if (empty($allowedParams['isEnabled'])) {
137  $userRoles = $this->getAuthorizedContextObject(ASSOC_TYPE_USER_ROLES);
138  $canAccessDisabledContexts = !empty(array_intersect(array(ROLE_ID_SITE_ADMIN), $userRoles));
139  if (!$canAccessDisabledContexts) {
140  return $response->withStatus(403)->withJsonError('api.contexts.403.requestedDisabledContexts');
141  }
142  }
143 
144  $items = array();
145  $contextsIterator = Services::get('context')->getMany($allowedParams);
146  if (count($contextsIterator)) {
147  $propertyArgs = array(
148  'request' => $request,
149  'slimRequest' => $slimRequest,
150  );
151  foreach ($contextsIterator as $context) {
152  $items[] = Services::get('context')->getSummaryProperties($context, $propertyArgs);
153  }
154  }
155 
156  $data = array(
157  'itemsMax' => Services::get('context')->getMax($allowedParams),
158  'items' => $items,
159  );
160 
161  return $response->withJson($data, 200);
162  }
163 
172  public function get($slimRequest, $response, $args) {
173  $request = $this->getRequest();
174  $user = $request->getUser();
175 
176  $contextService = Services::get('context');
177  $context = $contextService->get((int) $args['contextId']);
178 
179  if (!$context) {
180  return $response->withStatus(404)->withJsonError('api.contexts.404.contextNotFound');
181  }
182 
183  // Don't allow to get one context from a different context's endpoint
184  if ($request->getContext() && $request->getContext()->getId() !== $context->getId()) {
185  return $response->withStatus(403)->withJsonError('api.contexts.403.contextsDidNotMatch');
186  }
187 
188  // A disabled journal can only be access by site admins and users with a
189  // manager role in that journal
190  if (!$context->getEnabled()) {
191  $userRoles = $this->getAuthorizedContextObject(ASSOC_TYPE_USER_ROLES);
192  if (!in_array(ROLE_ID_SITE_ADMIN, $userRoles)) {
193  $roleDao = DaoRegistry::getDao('RoleDAO');
194  if (!$roleDao->userHasRole($context->getId(), $user->getId(), ROLE_ID_MANAGER)) {
195  return $response->withStatus(403)->withJsonError('api.contexts.403.notAllowed');
196  }
197  }
198  }
199 
200  $data = $contextService->getFullProperties($context, array(
201  'request' => $request,
202  'slimRequest' => $slimRequest
203  ));
204 
205  return $response->withJson($data, 200);
206  }
207 
216  public function getTheme($slimRequest, $response, $args) {
217  $request = $this->getRequest();
218  $user = $request->getUser();
219 
220  $contextService = Services::get('context');
221  $context = $contextService->get((int) $args['contextId']);
222 
223  if (!$context) {
224  return $response->withStatus(404)->withJsonError('api.contexts.404.contextNotFound');
225  }
226 
227  // Don't allow to get one context from a different context's endpoint
228  if ($request->getContext() && $request->getContext()->getId() !== $context->getId()) {
229  return $response->withStatus(403)->withJsonError('api.contexts.403.contextsDidNotMatch');
230  }
231 
232  // A disabled journal can only be access by site admins and users with a
233  // manager role in that journal
234  if (!$context->getEnabled()) {
235  $userRoles = $this->getAuthorizedContextObject(ASSOC_TYPE_USER_ROLES);
236  if (!in_array(ROLE_ID_SITE_ADMIN, $userRoles)) {
237  $roleDao = DaoRegistry::getDao('RoleDAO');
238  if (!$roleDao->userHasRole($context->getId(), $user->getId(), ROLE_ID_MANAGER)) {
239  return $response->withStatus(403)->withJsonError('api.contexts.403.notAllowed');
240  }
241  }
242  }
243 
244  $allThemes = PluginRegistry::loadCategory('themes', true);
245  $activeTheme = null;
246  foreach ($allThemes as $theme) {
247  if ($context->getData('themePluginPath') === $theme->getDirName()) {
248  $activeTheme = $theme;
249  break;
250  }
251  }
252 
253  if (!$activeTheme) {
254  return $response->withStatus(404)->withJsonError('api.themes.404.themeUnavailable');
255  }
256 
257  $data = array_merge(
258  $activeTheme->getOptionValues($context->getId()),
259  ['themePluginPath' => $theme->getDirName()]
260  );
261 
262  ksort($data);
263 
264  return $response->withJson($data, 200);
265  }
266 
275  public function add($slimRequest, $response, $args) {
276  $request = $this->getRequest();
277 
278  // This endpoint is only available at the site-wide level
279  if ($request->getContext()) {
280  return $response->withStatus(404)->withJsonError('api.submissions.404.siteWideEndpoint');
281  }
282 
283  $site = $request->getSite();
284  $params = $this->convertStringsToSchema(SCHEMA_CONTEXT, $slimRequest->getParsedBody());
285 
286  $primaryLocale = $site->getPrimaryLocale();
287  $allowedLocales = $site->getSupportedLocales();
288  $contextService = Services::get('context');
289  $errors = $contextService->validate(VALIDATE_ACTION_ADD, $params, $allowedLocales, $primaryLocale);
290 
291  if (!empty($errors)) {
292  return $response->withStatus(400)->withJson($errors);
293  }
294 
295  $context = Application::getContextDAO()->newDataObject();
296  $context->_data = $params;
297  $context = $contextService->add($context, $request);
298  $contextProps = $contextService->getFullProperties($context, array(
299  'request' => $request,
300  'slimRequest' => $slimRequest
301  ));
302 
303  return $response->withJson($contextProps, 200);
304  }
305 
314  public function edit($slimRequest, $response, $args) {
315  $request = $this->getRequest();
316  $requestContext = $request->getContext();
317 
318  $contextId = (int) $args['contextId'];
319 
320  // Don't allow to get one context from a different context's endpoint
321  if ($request->getContext() && $request->getContext()->getId() !== $contextId) {
322  return $response->withStatus(403)->withJsonError('api.contexts.403.contextsDidNotMatch');
323  }
324 
325  // Don't allow to edit the context from the site-wide API, because the
326  // context's plugins will not be enabled
327  if (!$request->getContext()) {
328  return $response->withStatus(403)->withJsonError('api.contexts.403.requiresContext');
329  }
330 
331  $contextService = Services::get('context');
332  $context = $contextService->get($contextId);
333 
334  if (!$context) {
335  return $response->withStatus(404)->withJsonError('api.contexts.404.contextNotFound');
336  }
337 
338  $userRoles = $this->getAuthorizedContextObject(ASSOC_TYPE_USER_ROLES);
339  if (!$requestContext && !in_array(ROLE_ID_SITE_ADMIN, $userRoles)) {
340  return $response->withStatus(403)->withJsonError('api.contexts.403.notAllowedEdit');
341  }
342 
343  $params = $this->convertStringsToSchema(SCHEMA_CONTEXT, $slimRequest->getParsedBody());
344  $params['id'] = $contextId;
345 
346  $site = $request->getSite();
347  $primaryLocale = $context->getPrimaryLocale();
348  $allowedLocales = $context->getSupportedFormLocales();
349 
350  $errors = $contextService->validate(VALIDATE_ACTION_EDIT, $params, $allowedLocales, $primaryLocale);
351 
352  if (!empty($errors)) {
353  return $response->withStatus(400)->withJson($errors);
354  }
355  $context = $contextService->edit($context, $params, $request);
356 
357  $contextProps = $contextService->getFullProperties($context, array(
358  'request' => $request,
359  'slimRequest' => $slimRequest
360  ));
361 
362  return $response->withJson($contextProps, 200);
363  }
364 
373  public function editTheme($slimRequest, $response, $args) {
374  $request = $this->getRequest();
375  $requestContext = $request->getContext();
376 
377  $contextId = (int) $args['contextId'];
378 
379  // Don't allow to get one context from a different context's endpoint
380  if ($request->getContext() && $request->getContext()->getId() !== $contextId) {
381  return $response->withStatus(403)->withJsonError('api.contexts.403.contextsDidNotMatch');
382  }
383 
384  // Don't allow to edit the context from the site-wide API, because the
385  // context's plugins will not be enabled
386  if (!$request->getContext()) {
387  return $response->withStatus(403)->withJsonError('api.contexts.403.requiresContext');
388  }
389 
390  $contextService = Services::get('context');
391  $context = $contextService->get($contextId);
392 
393  if (!$context) {
394  return $response->withStatus(404)->withJsonError('api.contexts.404.contextNotFound');
395  }
396 
397  $userRoles = $this->getAuthorizedContextObject(ASSOC_TYPE_USER_ROLES);
398  if (!$requestContext && !in_array(ROLE_ID_SITE_ADMIN, $userRoles)) {
399  return $response->withStatus(403)->withJsonError('api.contexts.403.notAllowedEdit');
400  }
401 
402  $params = $slimRequest->getParsedBody();
403 
404  // Validate the themePluginPath and allow themes to perform their own validation
405  $themePluginPath = empty($params['themePluginPath']) ? null : $params['themePluginPath'];
406  if ($themePluginPath !== $context->getData('themePluginPath')) {
407  $errors = $contextService->validate(
408  VALIDATE_ACTION_EDIT,
409  ['themePluginPath' => $themePluginPath],
410  $context->getSupportedFormLocales(),
411  $context->getPrimaryLocale()
412  );
413  if (!empty($errors)) {
414  return $response->withJson($errors, 400);
415  }
416  $newContext = $contextService->edit($context, ['themePluginPath' => $themePluginPath], $request);
417  }
418 
419  // Get the appropriate theme plugin
420  $allThemes = PluginRegistry::loadCategory('themes', true);
421  $selectedTheme = null;
422  foreach ($allThemes as $theme) {
423  if ($themePluginPath === $theme->getDirName()) {
424  $selectedTheme = $theme;
425  break;
426  }
427  }
428 
429  // Run the theme's init() method if a new theme has been selected
430  if (isset($newContext)) {
431  $selectedTheme->init();
432  }
433 
434  $errors = $selectedTheme->validateOptions($params, $themePluginPath, $context->getId(), $request);
435  if (!empty($errors)) {
436  return $response->withJson($errors, 400);
437  }
438 
439  // Only accept params that are defined in the theme options
440  $options = $selectedTheme->getOptionsConfig();
441  foreach ($options as $optionName => $optionConfig) {
442  if (!array_key_exists($optionName, $params)) {
443  continue;
444  }
445  $selectedTheme->saveOption($optionName, $params[$optionName], $context->getId());
446  }
447 
448  // Clear the template cache so that new settings can take effect
450  $templateMgr->clearTemplateCache();
451  $templateMgr->clearCssCache();
452 
453  $data = array_merge(
454  $selectedTheme->getOptionValues($context->getId()),
455  ['themePluginPath' => $themePluginPath]
456  );
457 
458  ksort($data);
459 
460  return $response->withJson($data, 200);
461  }
462 
471  public function delete($slimRequest, $response, $args) {
472 
473  // This endpoint is only available at the site-wide level
474  if ($this->getRequest()->getContext()) {
475  return $response->withStatus(404)->withJsonError('api.submissions.404.siteWideEndpoint');
476  }
477 
478  $userRoles = $this->getAuthorizedContextObject(ASSOC_TYPE_USER_ROLES);
479  if (!in_array(ROLE_ID_SITE_ADMIN, $userRoles)) {
480  $response->withStatus(403)->withJsonError('api.contexts.403.notAllowedDelete');
481  }
482 
483  $contextId = (int) $args['contextId'];
484 
485  $contextService = Services::get('context');
486  $context = $contextService->get($contextId);
487 
488  if (!$context) {
489  return $response->withStatus(404)->withJsonError('api.contexts.404.contextNotFound');
490  }
491 
492  $contextProps = $contextService->getSummaryProperties($context, array(
493  'request' => $this->getRequest(),
494  'slimRequest' => $slimRequest
495  ));
496 
497  $contextService->delete($context);
498 
499  return $response->withJson($contextProps, 200);
500  }
501 }
Application\getContextDAO
static getContextDAO()
Definition: Application.inc.php:145
PKPContextHandler\add
add($slimRequest, $response, $args)
Definition: PKPContextHandler.inc.php:278
PKPContextHandler\editTheme
editTheme($slimRequest, $response, $args)
Definition: PKPContextHandler.inc.php:376
PKPContextHandler
Base class to handle API requests for contexts (journals/presses).
Definition: PKPContextHandler.inc.php:17
PluginRegistry\loadCategory
static loadCategory($category, $enabledOnly=false, $mainContextId=null)
Definition: PluginRegistry.inc.php:103
PKPContextHandler\edit
edit($slimRequest, $response, $args)
Definition: PKPContextHandler.inc.php:317
PKPContextHandler\getMany
getMany($slimRequest, $response, $args)
Definition: PKPContextHandler.inc.php:102
APIHandler
Base request API handler.
Definition: APIHandler.inc.php:22
PKPContextHandler\$schemaName
$schemaName
Definition: PKPContextHandler.inc.php:22
PKPTemplateManager\getManager
static & getManager($request=null)
Definition: PKPTemplateManager.inc.php:1239
PKPHandler\getAuthorizedContextObject
& getAuthorizedContextObject($assocType)
Definition: PKPHandler.inc.php:174
PKPContextHandler\authorize
authorize($request, &$args, $roleAssignments)
Definition: PKPContextHandler.inc.php:81
PKPContextHandler\getTheme
getTheme($slimRequest, $response, $args)
Definition: PKPContextHandler.inc.php:219
APIHandler\convertStringsToSchema
convertStringsToSchema($schema, $params)
Definition: APIHandler.inc.php:281
RoleBasedHandlerOperationPolicy
Class to control access to handler operations via role based access control.
Definition: RoleBasedHandlerOperationPolicy.inc.php:18
PKPApplication\get
static get()
Definition: PKPApplication.inc.php:235
APIHandler\getRequest
getRequest()
Definition: APIHandler.inc.php:149
PKPHandler\addPolicy
addPolicy($authorizationPolicy, $addToTop=false)
Definition: PKPHandler.inc.php:157
APIHandler\getEndpointPattern
getEndpointPattern()
Definition: APIHandler.inc.php:186
HookRegistry\call
static call($hookName, $args=null)
Definition: HookRegistry.inc.php:86
PolicySet
An ordered list of policies. Policy sets can be added to decision managers like policies....
Definition: PolicySet.inc.php:26
PKPContextHandler\__construct
__construct()
Definition: PKPContextHandler.inc.php:27
PKPServices\get
static get($service)
Definition: PKPServices.inc.php:49