Open Preprint Systems  3.3.0
ArticleSearchIndex.inc.php
1 <?php
2 
16 import('lib.pkp.classes.search.SubmissionSearchIndex');
17 
19 
23  public function submissionMetadataChanged($submission) {
24  // Check whether a search plug-in jumps in.
25  $hookResult = HookRegistry::call(
26  'ArticleSearchIndex::articleMetadataChanged',
27  array($submission)
28  );
29 
30  if (!empty($hookResult)) {
31  return;
32  }
33 
34  $publication = $submission->getCurrentPublication();
35 
36  // Build author keywords
37  $authorText = [];
38  foreach ($publication->getData('authors') as $author) {
39  $authorText = array_merge(
40  $authorText,
41  array_values((array) $author->getData('givenName')),
42  array_values((array) $author->getData('familyName')),
43  array_values(array_map('strip_tags', (array) $author->getData('affiliation'))),
44  array_values(array_map('strip_tags', (array) $author->getData('biography')))
45  );
46  }
47 
48  // Update search index
49  import('classes.search.ArticleSearch');
50  $submissionId = $submission->getId();
51  $this->_updateTextIndex($submissionId, SUBMISSION_SEARCH_AUTHOR, $authorText);
52  $this->_updateTextIndex($submissionId, SUBMISSION_SEARCH_TITLE, $publication->getFullTitles());
53  $this->_updateTextIndex($submissionId, SUBMISSION_SEARCH_ABSTRACT, $publication->getData('abstract'));
54 
55  $this->_updateTextIndex($submissionId, SUBMISSION_SEARCH_SUBJECT, (array) $publication->getData('subjects'));
56  $this->_updateTextIndex($submissionId, SUBMISSION_SEARCH_DISCIPLINE, (array) $publication->getData('disciplines'));
57  $this->_updateTextIndex($submissionId, SUBMISSION_SEARCH_TYPE, (array) $publication->getData('type'));
58  $this->_updateTextIndex($submissionId, SUBMISSION_SEARCH_COVERAGE, (array) $publication->getData('coverage'));
59  // FIXME Index sponsors too?
60  }
61 
68  public function deleteTextIndex($articleId, $type = null, $assocId = null) {
69  $searchDao = DAORegistry::getDAO('ArticleSearchDAO');
70  return $searchDao->deleteSubmissionKeywords($articleId, $type, $assocId);
71  }
72 
83  public function submissionFileChanged($articleId, $type, $fileId) {
84  // Check whether a search plug-in jumps in.
85  $hookResult = HookRegistry::call(
86  'ArticleSearchIndex::submissionFileChanged',
87  array($articleId, $type, $fileId)
88  );
89 
90  // If no search plug-in is activated then fall back to the
91  // default database search implementation.
92  if ($hookResult === false || is_null($hookResult)) {
93  $submissionFileDao = DAORegistry::getDAO('SubmissionFileDAO'); /* @var $submissionFileDao SubmissionFileDAO */
94  $file = $submissionFileDao->getLatestRevision($fileId);
95  if (isset($file)) {
96  $parser = SearchFileParser::fromFile($file);
97  }
98 
99  if (isset($parser) && $parser->open()) {
100  $searchDao = DAORegistry::getDAO('ArticleSearchDAO');
101  $objectId = $searchDao->insertObject($articleId, $type, $fileId);
102 
103  $position = 0;
104  while(($text = $parser->read()) !== false) {
105  $this->_indexObjectKeywords($objectId, $text, $position);
106  }
107  $parser->close();
108  }
109  }
110  }
111 
116  public function clearSubmissionFiles($submission) {
117  $searchDao = DAORegistry::getDAO('ArticleSearchDAO');
118  $searchDao->deleteSubmissionKeywords($submission->getId(), SUBMISSION_SEARCH_GALLEY_FILE);
119  }
120 
130  public function submissionFilesChanged($article) {
131  // Check whether a search plug-in jumps in.
132  $hookResult = HookRegistry::call(
133  'ArticleSearchIndex::submissionFilesChanged',
134  array($article)
135  );
136 
137  // If no search plug-in is activated then fall back to the
138  // default database search implementation.
139  if ($hookResult === false || is_null($hookResult)) {
140  $fileDao = DAORegistry::getDAO('SubmissionFileDAO');
141  import('lib.pkp.classes.submission.SubmissionFile'); // Constants
142  // Index galley files
143  $files = $fileDao->getLatestRevisions(
144  $article->getId(), SUBMISSION_FILE_PROOF
145  );
146  foreach ($files as $file) {
147  if ($file->getFileId()) {
148  $this->submissionFileChanged($article->getId(), SUBMISSION_SEARCH_GALLEY_FILE, $file->getFileId());
149  // Index dependent files associated with any galley files.
150  $dependentFiles = $fileDao->getLatestRevisionsByAssocId(ASSOC_TYPE_SUBMISSION_FILE, $file->getFileId(), $article->getId(), SUBMISSION_FILE_DEPENDENT);
151  foreach ($dependentFiles as $depFile) {
152  if ($depFile->getFileId()) {
153  $this->submissionFileChanged($article->getId(), SUBMISSION_SEARCH_SUPPLEMENTARY_FILE, $depFile->getFileId());
154  }
155  }
156  }
157  }
158  }
159  }
160 
171  public function submissionFileDeleted($articleId, $type = null, $assocId = null) {
172  // Check whether a search plug-in jumps in.
173  $hookResult = HookRegistry::call(
174  'ArticleSearchIndex::submissionFileDeleted',
175  array($articleId, $type, $assocId)
176  );
177 
178  // If no search plug-in is activated then fall back to the
179  // default database search implementation.
180  if ($hookResult === false || is_null($hookResult)) {
181  $searchDao = DAORegistry::getDAO('ArticleSearchDAO'); /* @var $searchDao ArticleSearchDAO */
182  return $searchDao->deleteSubmissionKeywords($articleId, $type, $assocId);
183  }
184  }
185 
195  public function articleDeleted($articleId) {
196  // Trigger a hook to let the indexing back-end know that
197  // an article was deleted.
199  'ArticleSearchIndex::articleDeleted',
200  array($articleId)
201  );
202 
203  // The default indexing back-end does nothing when an
204  // article is deleted (FIXME?).
205  }
206 
210  public function submissionChangesFinished() {
211  // Trigger a hook to let the indexing back-end know that
212  // the index may be updated.
214  'ArticleSearchIndex::articleChangesFinished'
215  );
216 
217  // The default indexing back-end works completely synchronously
218  // and will therefore not do anything here.
219  }
220 
224  public function articleChangesFinished() {
225  if (Config::getVar('debug', 'deprecation_warnings')) trigger_error('Deprecated call to articleChangesFinished. Use submissionChangesFinished instead.');
226  $this->submissionChangesFinished();
227  }
228 
240  public function rebuildIndex($log = false, $journal = null, $switches = array()) {
241  // Check whether a search plug-in jumps in.
242  $hookResult = HookRegistry::call(
243  'ArticleSearchIndex::rebuildIndex',
244  array($log, $journal, $switches)
245  );
246 
247  // If no search plug-in is activated then fall back to the
248  // default database search implementation.
249  if ($hookResult === false || is_null($hookResult)) {
250 
251  AppLocale::requireComponents(LOCALE_COMPONENT_APP_COMMON);
252 
253  // Check that no journal was given as we do
254  // not support journal-specific re-indexing.
255  if (is_a($journal, 'Journal')) die(__('search.cli.rebuildIndex.indexingByJournalNotSupported') . "\n");
256 
257  // Clear index
258  if ($log) echo __('search.cli.rebuildIndex.clearingIndex') . ' ... ';
259  $searchDao = DAORegistry::getDAO('ArticleSearchDAO');
260  $searchDao->clearIndex();
261  if ($log) echo __('search.cli.rebuildIndex.done') . "\n";
262 
263  // Build index
264  $journalDao = DAORegistry::getDAO('JournalDAO'); /* @var $journalDao JournalDAO */
265 
266  $journals = $journalDao->getAll();
267  while ($journal = $journals->next()) {
268  $numIndexed = 0;
269 
270  if ($log) echo __('search.cli.rebuildIndex.indexing', array('journalName' => $journal->getLocalizedName())) . ' ... ';
271 
272  $submissionsIterator = Services::get('submission')->getMany(['contextId' => $journal->getId()]);
273  foreach ($submissionsIterator as $submission) {
274  if ($submission->getSubmissionProgress() == 0) { // Not incomplete
275  $this->submissionMetadataChanged($submission);
276  $this->submissionFilesChanged($submission);
277  $numIndexed++;
278  }
279  }
280  $this->submissionChangesFinished();
281 
282  if ($log) echo __('search.cli.rebuildIndex.result', array('numIndexed' => $numIndexed)) . "\n";
283  }
284  }
285  }
286 
287 
288  //
289  // Private helper methods
290  //
297  protected function _indexObjectKeywords($objectId, $text, &$position) {
298  $searchDao = DAORegistry::getDAO('ArticleSearchDAO');
299  $keywords = $this->filterKeywords($text);
300  for ($i = 0, $count = count($keywords); $i < $count; $i++) {
301  if ($searchDao->insertObjectKeyword($objectId, $keywords[$i], $position) !== null) {
302  $position += 1;
303  }
304  }
305  }
306 
314  protected function _updateTextIndex($articleId, $type, $text, $assocId = null) {
315  $searchDao = DAORegistry::getDAO('ArticleSearchDAO');
316  $objectId = $searchDao->insertObject($articleId, $type, $assocId);
317  $position = 0;
318  $this->_indexObjectKeywords($objectId, $text, $position);
319  }
320 }
321 
322 
SubmissionSearchIndex\filterKeywords
filterKeywords($text, $allowWildcards=false)
Definition: SubmissionSearchIndex.inc.php:32
AppLocale\requireComponents
static requireComponents()
Definition: env1/MockAppLocale.inc.php:56
ArticleSearchIndex\articleChangesFinished
articleChangesFinished()
Definition: ArticleSearchIndex.inc.php:224
ArticleSearchIndex\submissionChangesFinished
submissionChangesFinished()
Definition: ArticleSearchIndex.inc.php:210
DAORegistry\getDAO
static & getDAO($name, $dbconn=null)
Definition: DAORegistry.inc.php:57
ArticleSearchIndex\submissionFileChanged
submissionFileChanged($articleId, $type, $fileId)
Definition: ArticleSearchIndex.inc.php:83
ArticleSearchIndex\articleDeleted
articleDeleted($articleId)
Definition: ArticleSearchIndex.inc.php:195
ArticleSearchIndex\submissionFileDeleted
submissionFileDeleted($articleId, $type=null, $assocId=null)
Definition: ArticleSearchIndex.inc.php:171
ArticleSearchIndex\submissionMetadataChanged
submissionMetadataChanged($submission)
Definition: ArticleSearchIndex.inc.php:23
ArticleSearchIndex\_indexObjectKeywords
_indexObjectKeywords($objectId, $text, &$position)
Definition: ArticleSearchIndex.inc.php:297
SearchFileParser\fromFile
static fromFile($file)
Definition: SearchFileParser.inc.php:106
ArticleSearchIndex\submissionFilesChanged
submissionFilesChanged($article)
Definition: ArticleSearchIndex.inc.php:130
Config\getVar
static getVar($section, $key, $default=null)
Definition: Config.inc.php:35
SubmissionSearchIndex
Class to maintain a submission search index.
Definition: SubmissionSearchIndex.inc.php:25
ArticleSearchIndex\deleteTextIndex
deleteTextIndex($articleId, $type=null, $assocId=null)
Definition: ArticleSearchIndex.inc.php:68
ArticleSearchIndex\_updateTextIndex
_updateTextIndex($articleId, $type, $text, $assocId=null)
Definition: ArticleSearchIndex.inc.php:314
ArticleSearchIndex\clearSubmissionFiles
clearSubmissionFiles($submission)
Definition: ArticleSearchIndex.inc.php:116
HookRegistry\call
static call($hookName, $args=null)
Definition: HookRegistry.inc.php:86
ArticleSearchIndex
Class to maintain the article search index.
Definition: ArticleSearchIndex.inc.php:18
ArticleSearchIndex\rebuildIndex
rebuildIndex($log=false, $journal=null, $switches=array())
Definition: ArticleSearchIndex.inc.php:240
PKPServices\get
static get($service)
Definition: PKPServices.inc.php:49