Open Monograph Press  3.3.0
PKPContextService.inc.php
1 <?php
16 namespace PKP\Services;
17 
18 use \DBResultRange;
19 use \Application;
20 use \DAOResultFactory;
21 use \DAORegistry;
22 use \Services;
23 use \PKP\Services\interfaces\EntityPropertyInterface;
24 use \PKP\Services\interfaces\EntityReadInterface;
25 use \PKP\Services\interfaces\EntityWriteInterface;
26 use \APP\Services\QueryBuilders\ContextQueryBuilder;
27 
28 import('lib.pkp.classes.db.DBResultRange');
29 
30 abstract class PKPContextService implements EntityPropertyInterface, EntityReadInterface, EntityWriteInterface {
31 
36  var $installFileDirs;
37 
43 
47  public function get($contextId) {
48  return Application::getContextDAO()->getById($contextId);
49  }
50 
54  public function getCount($args = []) {
55  return $this->getQueryBuilder($args)->getCount();
56  }
57 
61  public function getIds($args = []) {
62  return $this->getQueryBuilder($args)->getIds();
63  }
64 
77  public function getManySummary($args = []) {
78  return $this->getQueryBuilder($args)->getManySummary();
79  }
80 
94  public function getMany($args = array()) {
95  $range = null;
96  if (isset($args['count'])) {
97  import('lib.pkp.classes.db.DBResultRange');
98  $range = new \DBResultRange($args['count'], null, isset($args['offset']) ? $args['offset'] : 0);
99  }
100  // Pagination is handled by the DAO, so don't pass count and offset
101  // arguments to the QueryBuilder.
102  if (isset($args['count'])) unset($args['count']);
103  if (isset($args['offset'])) unset($args['offset']);
104  $contextListQO = $this->getQueryBuilder($args)->getQuery();
105  $contextDao = Application::getContextDAO();
106  $result = $contextDao->retrieveRange($contextListQO->toSql(), $contextListQO->getBindings(), $range);
107  $queryResults = new DAOResultFactory($result, $contextDao, '_fromRow');
108 
109  return $queryResults->toIterator();
110  }
111 
115  public function getMax($args = array()) {
116  // Don't accept args to limit the results
117  if (isset($args['count'])) unset($args['count']);
118  if (isset($args['offset'])) unset($args['offset']);
119  return $this->getQueryBuilder($args)->getCount();
120  }
121 
126  public function getQueryBuilder($args = array()) {
127 
128  $defaultArgs = array(
129  'isEnabled' => null,
130  'userId' => null,
131  'searchPhrase' => null,
132  );
133 
134  $args = array_merge($defaultArgs, $args);
135 
136  $contextListQB = new ContextQueryBuilder();
137  $contextListQB
138  ->filterByIsEnabled($args['isEnabled'])
139  ->filterByUserId($args['userId'])
140  ->searchPhrase($args['searchPhrase']);
141 
142  \HookRegistry::call('Context::getMany::queryBuilder', array($contextListQB, $args));
143 
144  return $contextListQB;
145  }
146 
150  public function getProperties($context, $props, $args = null) {
151  $slimRequest = $args['slimRequest'];
152  $request = $args['request'];
153  $dispatcher = $request->getDispatcher();
154 
155  $values = array();
156 
157  foreach ($props as $prop) {
158  switch ($prop) {
159  case 'url':
160  $values[$prop] = $dispatcher->url(
161  $request,
162  ROUTE_PAGE,
163  $context->getPath()
164  );
165  break;
166  case '_href':
167  $values[$prop] = null;
168  if (!empty($slimRequest)) {
169  $route = $slimRequest->getAttribute('route');
170  $values[$prop] = $dispatcher->url(
171  $args['request'],
172  ROUTE_API,
173  $context->getData('urlPath'),
174  'contexts/' . $context->getId()
175  );
176  }
177  break;
178  default:
179  $values[$prop] = $context->getData($prop);
180  break;
181  }
182  }
183 
184  $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
185  $values = Services::get('schema')->addMissingMultilingualValues(SCHEMA_CONTEXT, $values, $supportedLocales);
186 
187  \HookRegistry::call('Context::getProperties', array(&$values, $context, $props, $args));
188 
189  ksort($values);
190 
191  return $values;
192  }
193 
197  public function getSummaryProperties($context, $args = null) {
198  $props = Services::get('schema')->getSummaryProps(SCHEMA_CONTEXT);
199 
200  return $this->getProperties($context, $props, $args);
201  }
202 
206  public function getFullProperties($context, $args = null) {
207  $props = Services::get('schema')->getFullProps(SCHEMA_CONTEXT);
208 
209  return $this->getProperties($context, $props, $args);
210  }
211 
215  public function validate($action, $props, $allowedLocales, $primaryLocale) {
217  LOCALE_COMPONENT_PKP_ADMIN,
218  LOCALE_COMPONENT_APP_ADMIN,
219  LOCALE_COMPONENT_PKP_MANAGER,
220  LOCALE_COMPONENT_APP_MANAGER
221  );
222  $schemaService = Services::get('schema');
223 
224  import('lib.pkp.classes.validation.ValidatorFactory');
225  $validator = \ValidatorFactory::make(
226  $props,
227  $schemaService->getValidationRules(SCHEMA_CONTEXT, $allowedLocales),
228  [
229  'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
230  'primaryLocale.regex' => __('validator.localeKey'),
231  'supportedFormLocales.regex' => __('validator.localeKey'),
232  'supportedLocales.regex' => __('validator.localeKey'),
233  'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
234  ]
235  );
236 
237  // Check required fields
239  $validator,
240  $action,
241  $schemaService->getRequiredProps(SCHEMA_CONTEXT),
242  $schemaService->getMultilingualProps(SCHEMA_CONTEXT),
243  $allowedLocales,
244  $primaryLocale
245  );
246 
247  // Check for input from disallowed locales
248  \ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(SCHEMA_CONTEXT), $allowedLocales);
249 
250  // Ensure that a urlPath, if provided, does not already exist
251  $validator->after(function($validator) use ($action, $props) {
252  if (isset($props['urlPath']) && !$validator->errors()->get('urlPath')) {
253  $contextDao = Application::getContextDAO();
254  $contextWithPath = $contextDao->getByPath($props['urlPath']);
255  if ($contextWithPath) {
256  if (!($action === VALIDATE_ACTION_EDIT
257  && isset($props['id'])
258  && (int) $contextWithPath->getId() === $props['id'])) {
259  $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
260  }
261  }
262  }
263  });
264 
265  // If a new file has been uploaded, check that the temporary file exists and
266  // the current user owns it
267  $user = Application::get()->getRequest()->getUser();
269  $validator,
270  ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
271  ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
272  $props,
273  $allowedLocales,
274  $user ? $user->getId() : null
275  );
276 
277  // If sidebar blocks are passed, ensure the block plugin exists and is
278  // enabled
279  $validator->after(function($validator) use ($props) {
280  if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
281  $plugins = \PluginRegistry::loadCategory('blocks', true);
282  foreach ($props['sidebar'] as $pluginName) {
283  if (empty($plugins[$pluginName])) {
284  $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
285  }
286  }
287  }
288  });
289 
290  // Ensure the theme plugin is installed and enabled
291  $validator->after(function($validator) use ($props) {
292  if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
293  $plugins = \PluginRegistry::loadCategory('themes', true);
294  $found = false;
295  foreach ($plugins as $plugin) {
296  if ($props['themePluginPath'] === $plugin->getDirName()) {
297  $found = true;
298  break;
299  }
300  }
301  if (!$found) {
302  $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
303  }
304  }
305  });
306 
307  if ($validator->fails()) {
308  $errors = $schemaService->formatValidationErrors($validator->errors(), $schemaService->get(SCHEMA_CONTEXT), $allowedLocales);
309  }
310 
311  \HookRegistry::call('Context::validate', array(&$errors, $action, $props, $allowedLocales, $primaryLocale));
312 
313  return $errors;
314  }
315 
319  public function add($context, $request) {
320  $site = $request->getSite();
321  $currentUser = $request->getUser();
322  $contextDao = Application::getContextDAO();
323 
324  if (!$context->getData('primaryLocale')) {
325  $context->setData('primaryLocale', $site->getPrimaryLocale());
326  }
327  if (!$context->getData('supportedLocales')) {
328  $context->setData('supportedLocales', $site->getSupportedLocales());
329  }
330 
331  // Specify values needed to render default locale strings
332  $localeParams = array(
333  'indexUrl' => $request->getIndexUrl(),
334  'primaryLocale' => $context->getData('primaryLocale'),
335  'contextName' => $context->getData('name', $context->getPrimaryLocale()),
336  'contextPath' => $context->getData('urlPath'),
337  'contextUrl' => $request->getDispatcher()->url(
338  $request,
339  ROUTE_PAGE,
340  $context->getPath()
341  ),
342  );
343 
344  // Allow plugins to extend the $localeParams for new property defaults
345  \HookRegistry::call('Context::defaults::localeParams', array(&$localeParams, $context, $request));
346 
347  $context = Services::get('schema')->setDefaults(
348  SCHEMA_CONTEXT,
349  $context,
350  $context->getData('supportedLocales'),
351  $context->getData('primaryLocale'),
352  $localeParams
353  );
354 
355  if (!$context->getData('supportedFormLocales')) {
356  $context->setData('supportedFormLocales', [$context->getData('primaryLocale')]);
357  }
358  if (!$context->getData('supportedSubmissionLocales')) {
359  $context->setData('supportedSubmissionLocales', [$context->getData('primaryLocale')]);
360  }
361 
362  $contextDao->insertObject($context);
363  $contextDao->resequence();
364 
365  $context = $this->get($context->getId());
366 
367  // Move uploaded files into place and update the settings
368  $supportedLocales = $context->getSupportedFormLocales();
369  $fileUploadProps = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
370  $params = [];
371  foreach ($fileUploadProps as $fileUploadProp) {
372  $value = $context->getData($fileUploadProp);
373  if (empty($value)) {
374  continue;
375  }
376  foreach ($supportedLocales as $localeKey) {
377  if (!array_key_exists($localeKey, $value)) {
378  continue;
379  }
380  $value[$localeKey] = $this->_saveFileParam($context, $value[$localeKey], $fileUploadProp, $currentUser->getId(), $localeKey, true);
381  }
382  $params[$fileUploadProp] = $value;
383  }
384  if (!empty($params['styleSheet'])) {
385  $params['styleSheet'] = $this->_saveFileParam($context, $params['styleSheet'], 'styleSheet', $userId);
386  }
387  $context = $this->edit($context, $params, $request);
388 
389  $genreDao = \DAORegistry::getDAO('GenreDAO');
390  $genreDao->installDefaults($context->getId(), $context->getData('supportedLocales'));
391 
392  $userGroupDao = \DAORegistry::getDAO('UserGroupDAO');
393  $userGroupDao->installSettings($context->getId(), 'registry/userGroups.xml');
394 
395  $managerUserGroup = $userGroupDao->getDefaultByRoleId($context->getId(), ROLE_ID_MANAGER);
396  $userGroupDao->assignUserToGroup($currentUser->getId(), $managerUserGroup->getId());
397 
398  import('lib.pkp.classes.file.FileManager');
399  $fileManager = new \FileManager();
400  foreach ($this->installFileDirs as $dir) {
401  $fileManager->mkdir(sprintf($dir, $this->contextsFileDirName, $context->getId()));
402  }
403 
404  $navigationMenuDao = \DAORegistry::getDAO('NavigationMenuDAO');
405  $navigationMenuDao->installSettings($context->getId(), 'registry/navigationMenus.xml');
406 
407  // Load all plugins so they can hook in and add their installation settings
409 
410  \HookRegistry::call('Context::add', array($context, $request));
411 
412  return $context;
413  }
414 
418  public function edit($context, $params, $request) {
419  $contextDao = Application::getContextDao();
420 
421  // Move uploaded files into place and update the params
422  $userId = $request->getUser() ? $request->getUser()->getId() : null;
423  $supportedLocales = $context->getSupportedFormLocales();
424  $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
425  foreach ($fileUploadParams as $fileUploadParam) {
426  if (!array_key_exists($fileUploadParam, $params)) {
427  continue;
428  }
429  foreach ($supportedLocales as $localeKey) {
430  if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
431  continue;
432  }
433  $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
434  }
435  }
436  if (array_key_exists('styleSheet', $params)) {
437  $params['styleSheet'] = $this->_saveFileParam($context, $params['styleSheet'], 'styleSheet', $userId);
438  }
439 
440  $newContext = $contextDao->newDataObject();
441  $newContext->_data = array_merge($context->_data, $params);
442 
443  \HookRegistry::call('Context::edit', array($newContext, $context, $params, $request));
444 
445  $contextDao->updateObject($newContext);
446  $newContext = $this->get($newContext->getId());
447 
448  return $newContext;
449  }
450 
454  public function delete($context) {
455  \HookRegistry::call('Context::delete::before', array($context));
456 
457  $contextDao = Application::getContextDao();
458  $contextDao->deleteObject($context);
459 
460  $userGroupDao = \DAORegistry::getDAO('UserGroupDAO');
461  $userGroupDao->deleteAssignmentsByContextId($context->getId());
462  $userGroupDao->deleteByContextId($context->getId());
463 
464  $genreDao = \DAORegistry::getDAO('GenreDAO');
465  $genreDao->deleteByContextId($context->getId());
466 
467  $announcementDao = \DAORegistry::getDAO('AnnouncementDAO');
468  $announcementDao->deleteByAssoc($context->getAssocType(), $context->getId());
469 
470  $announcementTypeDao = \DAORegistry::getDAO('AnnouncementTypeDAO');
471  $announcementTypeDao->deleteByAssoc($context->getAssocType(), $context->getId());
472 
473  Services::get('emailTemplate')->restoreDefaults($context->getId());
474 
475  $pluginSettingsDao = \DAORegistry::getDAO('PluginSettingsDAO');
476  $pluginSettingsDao->deleteByContextId($context->getId());
477 
478  $reviewFormDao = \DAORegistry::getDAO('ReviewFormDAO');
479  $reviewFormDao->deleteByAssoc($context->getAssocType(), $context->getId());
480 
481  $navigationMenuDao = \DAORegistry::getDAO('NavigationMenuDAO');
482  $navigationMenuDao->deleteByContextId($context->getId());
483 
484  $navigationMenuItemDao = \DAORegistry::getDAO('NavigationMenuItemDAO');
485  $navigationMenuItemDao->deleteByContextId($context->getId());
486 
487  import('lib.pkp.classes.file.FileManager');
488  $fileManager = new \FileManager($context->getId());
489  $contextPath = \Config::getVar('files', 'files_dir') . '/' . $this->contextsFileDirName . '/' . $context->getId();
490  $fileManager->rmtree($contextPath);
491 
492  \HookRegistry::call('Context::delete', array($context));
493  }
494 
507  public function restoreLocaleDefaults($context, $request, $locale) {
508  \AppLocale::reloadLocale($locale);
509  \AppLocale::requireComponents(LOCALE_COMPONENT_PKP_DEFAULT, LOCALE_COMPONENT_APP_DEFAULT, $locale);
510 
511  // Specify values needed to render default locale strings
512  $localeParams = array(
513  'indexUrl' => $request->getIndexUrl(),
514  'journalPath' => $context->getData('urlPath'),
515  'primaryLocale' => $context->getData('primaryLocale'),
516  'journalName' => $context->getData('name', $locale),
517  'contextName' => $context->getData('name', $locale),
518  'contextUrl' => $request->getDispatcher()->url(
519  $request,
520  ROUTE_PAGE,
521  $context->getPath()
522  ),
523  );
524 
525  // Allow plugins to extend the $localeParams for new property defaults
526  \HookRegistry::call('Context::restoreLocaleDefaults::localeParams', array(&$localeParams, $context, $request, $locale));
527 
528  $localeDefaults = Services::get('schema')->getLocaleDefaults(SCHEMA_CONTEXT, $locale, $localeParams);
529 
530  $params = [];
531  foreach ($localeDefaults as $paramName => $value) {
532  $params[$paramName] = array_merge(
533  (array) $context->getData($paramName),
534  [$locale => $localeDefaults[$paramName]]
535  );
536  }
537 
538  return $this->edit($context, $params, $request);
539  }
540 
553  public function moveTemporaryFile($context, $temporaryFile, $fileNameBase, $userId, $localeKey = '') {
554  import('classes.file.PublicFileManager');
555  $publicFileManager = new \PublicFileManager();
556  import('lib.pkp.classes.file.TemporaryFileManager');
557  $temporaryFileManager = new \TemporaryFileManager();
558 
559  $fileName = $fileNameBase;
560  if ($localeKey) {
561  $fileName .= '_' . $localeKey;
562  }
563 
564  $extension = $publicFileManager->getDocumentExtension($temporaryFile->getFileType());
565  if (!$extension) {
566  $extension = $publicFileManager->getImageExtension($temporaryFile->getFileType());
567  }
568  $fileName .= $extension;
569 
570  $result = $publicFileManager->copyContextFile(
571  $context->getId(),
572  $temporaryFile->getFilePath(),
573  $fileName
574  );
575 
576  if (!$result) {
577  return false;
578  }
579 
580  $temporaryFileManager->deleteById($temporaryFile->getId(), $userId);
581 
582  return $fileName;
583  }
584 
608  protected function _saveFileParam($context, $value, $settingName, $userId, $localeKey = '', $isImage = false) {
609  import('lib.pkp.classes.file.TemporaryFileManager');
610  $temporaryFileManager = new \TemporaryFileManager();
611 
612  // If the value is null, clean up any existing file in the system
613  if (is_null($value)) {
614  $setting = $context->getData($settingName, $localeKey);
615  if ($setting) {
616  $fileName = $isImage ? $setting['uploadName'] : $setting;
617  import('classes.file.PublicFileManager');
618  $publicFileManager = new \PublicFileManager();
619  $publicFileManager->removeContextFile($context->getId(), $fileName);
620  }
621  return null;
622  }
623 
624  // Check if there is something to upload
625  if (empty($value['temporaryFileId'])) {
626  return $value;
627  }
628 
629  $temporaryFile = $temporaryFileManager->getFile((int) $value['temporaryFileId'], $userId);
630  $fileName = $this->moveTemporaryFile($context, $temporaryFile, $settingName, $userId, $localeKey);
631 
632  if ($fileName) {
633  // Get the details for image uploads
634  if ($isImage) {
635  import('classes.file.PublicFileManager');
636  $publicFileManager = new \PublicFileManager();
637 
638  $filePath = $publicFileManager->getContextFilesPath($context->getId());
639  list($width, $height) = getimagesize($filePath . '/' . $fileName);
640  $altText = !empty($value['altText']) ? $value['altText'] : '';
641 
642  return [
643  'name' => $temporaryFile->getOriginalFileName(),
644  'uploadName' => $fileName,
645  'width' => $width,
646  'height' => $height,
647  'dateUploaded' => \Core::getCurrentDate(),
648  'altText' => $altText,
649  ];
650  } else {
651  return [
652  'name' => $temporaryFile->getOriginalFileName(),
653  'uploadName' => $fileName,
654  'dateUploaded' => \Core::getCurrentDate(),
655  ];
656  }
657  }
658 
659  return false;
660  }
661 }
PluginRegistry\loadAllPlugins
static loadAllPlugins($enabledOnly=false)
Definition: PluginRegistry.inc.php:208
PKP\Services
Application\getContextDAO
static getContextDAO()
Definition: Application.inc.php:145
PKP\Services\PKPContextService\getFullProperties
getFullProperties($context, $args=null)
Definition: PKPContextService.inc.php:212
AppLocale\requireComponents
static requireComponents()
Definition: env1/MockAppLocale.inc.php:56
DAOResultFactory
Wrapper around ADORecordSet providing "factory" features for generating objects from DAOs.
Definition: DAOResultFactory.inc.php:21
ValidatorFactory\temporaryFilesExist
static temporaryFilesExist($validator, $uploadProps, $multilingualUploadProps, $props, $allowedLocales, $userId)
Definition: ValidatorFactory.inc.php:354
PKP\Services\PKPContextService\_saveFileParam
_saveFileParam($context, $value, $settingName, $userId, $localeKey='', $isImage=false)
Definition: PKPContextService.inc.php:614
DAORegistry\getDAO
static & getDAO($name, $dbconn=null)
Definition: DAORegistry.inc.php:57
PKP\Services\PKPContextService\getProperties
getProperties($context, $props, $args=null)
Definition: PKPContextService.inc.php:156
PKP\Services\PKPContextService\getMax
getMax($args=array())
Definition: PKPContextService.inc.php:121
ValidatorFactory\allowedLocales
static allowedLocales($validator, $multilingualProps, $allowedLocales)
Definition: ValidatorFactory.inc.php:320
PKP\Services\PKPContextService\getSummaryProperties
getSummaryProperties($context, $args=null)
Definition: PKPContextService.inc.php:203
PKP\Services\PKPContextService\add
add($context, $request)
Definition: PKPContextService.inc.php:325
PKPLocale\reloadLocale
static reloadLocale($locale)
Definition: PKPLocale.inc.php:588
PKP\Services\PKPContextService
Definition: PKPContextService.inc.php:30
PKP\Services\SCHEMA_CONTEXT
const SCHEMA_CONTEXT
Definition: PKPSchemaService.inc.php:19
ValidatorFactory\required
static required($validator, $action, $requiredProps, $multilingualProps, $allowedLocales, $primaryLocale)
Definition: ValidatorFactory.inc.php:261
PKP\Services\PKPContextService\getMany
getMany($args=array())
Definition: PKPContextService.inc.php:100
PKP\Services\PKPContextService\$installFileDirs
$installFileDirs
Definition: PKPContextService.inc.php:39
Config\getVar
static getVar($section, $key, $default=null)
Definition: Config.inc.php:35
ValidatorFactory\make
static make($props, $rules, $messages=[])
Definition: ValidatorFactory.inc.php:38
PKP\Services\PKPContextService\edit
edit($context, $params, $request)
Definition: PKPContextService.inc.php:424
PKP\Services\PKPContextService\getIds
getIds($args=[])
Definition: PKPContextService.inc.php:67
PKP\Services\PKPContextService\$contextsFileDirName
$contextsFileDirName
Definition: PKPContextService.inc.php:48
PKP\Services\PKPContextService\restoreLocaleDefaults
restoreLocaleDefaults($context, $request, $locale)
Definition: PKPContextService.inc.php:513
PKP\Services\PKPContextService\moveTemporaryFile
moveTemporaryFile($context, $temporaryFile, $fileNameBase, $userId, $localeKey='')
Definition: PKPContextService.inc.php:559
Core\getCurrentDate
static getCurrentDate($ts=null)
Definition: Core.inc.php:63
APP\Services\QueryBuilders\ContextQueryBuilder
Definition: ContextQueryBuilder.inc.php:18
PKP\Services\PKPContextService\getQueryBuilder
getQueryBuilder($args=array())
Definition: PKPContextService.inc.php:132
PKP\Services\PKPContextService\validate
validate($action, $props, $allowedLocales, $primaryLocale)
Definition: PKPContextService.inc.php:221
PKPApplication\get
static get()
Definition: PKPApplication.inc.php:235
HookRegistry\call
static call($hookName, $args=null)
Definition: HookRegistry.inc.php:86
PKP\Services\PKPContextService\getManySummary
getManySummary($args=[])
Definition: PKPContextService.inc.php:83
PKP\Services\PKPContextService\getCount
getCount($args=[])
Definition: PKPContextService.inc.php:60
PKPServices\get
static get($service)
Definition: PKPServices.inc.php:49