Open Journal 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 
65  public function articleMetadataChanged($article) {
66  if (Config::getVar('debug', 'deprecation_warnings')) trigger_error('Deprecated call to articleMetadataChanged. Use submissionMetadataChanged instead.');
67  $this->submissionMetadataChanged($article);
68  }
69 
76  public function deleteTextIndex($articleId, $type = null, $assocId = null) {
77  $searchDao = DAORegistry::getDAO('ArticleSearchDAO'); /* @var $searchDao ArticleSearchDAO */
78  return $searchDao->deleteSubmissionKeywords($articleId, $type, $assocId);
79  }
80 
91  public function submissionFileChanged($articleId, $type, $fileId) {
92  // Check whether a search plug-in jumps in.
93  $hookResult = HookRegistry::call(
94  'ArticleSearchIndex::submissionFileChanged',
95  array($articleId, $type, $fileId)
96  );
97 
98  // If no search plug-in is activated then fall back to the
99  // default database search implementation.
100  if ($hookResult === false || is_null($hookResult)) {
101  $submissionFileDao = DAORegistry::getDAO('SubmissionFileDAO'); /* @var $submissionFileDao SubmissionFileDAO */
102  $file = $submissionFileDao->getLatestRevision($fileId);
103  if (isset($file)) {
104  $parser = SearchFileParser::fromFile($file);
105  }
106 
107  if (isset($parser) && $parser->open()) {
108  $searchDao = DAORegistry::getDAO('ArticleSearchDAO'); /* @var $searchDao ArticleSearchDAO */
109  $objectId = $searchDao->insertObject($articleId, $type, $fileId);
110 
111  $position = 0;
112  while(($text = $parser->read()) !== false) {
113  $this->_indexObjectKeywords($objectId, $text, $position);
114  }
115  $parser->close();
116  }
117  }
118  }
119 
124  public function clearSubmissionFiles($submission) {
125  $searchDao = DAORegistry::getDAO('ArticleSearchDAO'); /* @var $searchDao ArticleSearchDAO */
126  $searchDao->deleteSubmissionKeywords($submission->getId(), SUBMISSION_SEARCH_GALLEY_FILE);
127  }
128 
138  public function submissionFilesChanged($article) {
139  // Check whether a search plug-in jumps in.
140  $hookResult = HookRegistry::call(
141  'ArticleSearchIndex::submissionFilesChanged',
142  array($article)
143  );
144 
145  // If no search plug-in is activated then fall back to the
146  // default database search implementation.
147  if ($hookResult === false || is_null($hookResult)) {
148  $fileDao = DAORegistry::getDAO('SubmissionFileDAO'); /* @var $fileDao SubmissionFileDAO */
149  import('lib.pkp.classes.submission.SubmissionFile'); // Constants
150  // Index galley files
151  $files = $fileDao->getLatestRevisions(
152  $article->getId(), SUBMISSION_FILE_PROOF
153  );
154  foreach ($files as $file) {
155  if ($file->getFileId()) {
156  $this->submissionFileChanged($article->getId(), SUBMISSION_SEARCH_GALLEY_FILE, $file->getFileId());
157  // Index dependent files associated with any galley files.
158  $dependentFiles = $fileDao->getLatestRevisionsByAssocId(ASSOC_TYPE_SUBMISSION_FILE, $file->getFileId(), $article->getId(), SUBMISSION_FILE_DEPENDENT);
159  foreach ($dependentFiles as $depFile) {
160  if ($depFile->getFileId()) {
161  $this->submissionFileChanged($article->getId(), SUBMISSION_SEARCH_SUPPLEMENTARY_FILE, $depFile->getFileId());
162  }
163  }
164  }
165  }
166  }
167  }
168 
179  public function submissionFileDeleted($articleId, $type = null, $assocId = null) {
180  // Check whether a search plug-in jumps in.
181  $hookResult = HookRegistry::call(
182  'ArticleSearchIndex::submissionFileDeleted',
183  array($articleId, $type, $assocId)
184  );
185 
186  // If no search plug-in is activated then fall back to the
187  // default database search implementation.
188  if ($hookResult === false || is_null($hookResult)) {
189  $searchDao = DAORegistry::getDAO('ArticleSearchDAO'); /* @var $searchDao ArticleSearchDAO */
190  return $searchDao->deleteSubmissionKeywords($articleId, $type, $assocId);
191  }
192  }
193 
203  public function articleDeleted($articleId) {
204  // Trigger a hook to let the indexing back-end know that
205  // an article was deleted.
207  'ArticleSearchIndex::articleDeleted',
208  array($articleId)
209  );
210 
211  // The default indexing back-end does nothing when an
212  // article is deleted (FIXME?).
213  }
214 
218  public function submissionChangesFinished() {
219  // Trigger a hook to let the indexing back-end know that
220  // the index may be updated.
222  'ArticleSearchIndex::articleChangesFinished'
223  );
224 
225  // The default indexing back-end works completely synchronously
226  // and will therefore not do anything here.
227  }
228 
232  public function articleChangesFinished() {
233  if (Config::getVar('debug', 'deprecation_warnings')) trigger_error('Deprecated call to articleChangesFinished. Use submissionChangesFinished instead.');
234  $this->submissionChangesFinished();
235  }
236 
248  public function rebuildIndex($log = false, $journal = null, $switches = array()) {
249  // Check whether a search plug-in jumps in.
250  $hookResult = HookRegistry::call(
251  'ArticleSearchIndex::rebuildIndex',
252  array($log, $journal, $switches)
253  );
254 
255  // If no search plug-in is activated then fall back to the
256  // default database search implementation.
257  if ($hookResult === false || is_null($hookResult)) {
258 
259  AppLocale::requireComponents(LOCALE_COMPONENT_APP_COMMON);
260 
261  // Check that no journal was given as we do
262  // not support journal-specific re-indexing.
263  if (is_a($journal, 'Journal')) die(__('search.cli.rebuildIndex.indexingByJournalNotSupported') . "\n");
264 
265  // Clear index
266  if ($log) echo __('search.cli.rebuildIndex.clearingIndex') . ' ... ';
267  $searchDao = DAORegistry::getDAO('ArticleSearchDAO'); /* @var $searchDao ArticleSearchDAO */
268  $searchDao->clearIndex();
269  if ($log) echo __('search.cli.rebuildIndex.done') . "\n";
270 
271  // Build index
272  $journalDao = DAORegistry::getDAO('JournalDAO'); /* @var $journalDao JournalDAO */
273 
274  $journals = $journalDao->getAll();
275  while ($journal = $journals->next()) {
276  $numIndexed = 0;
277 
278  if ($log) echo __('search.cli.rebuildIndex.indexing', array('journalName' => $journal->getLocalizedName())) . ' ... ';
279 
280  $submissionsIterator = Services::get('submission')->getMany(['contextId' => $journal->getId()]);
281  foreach ($submissionsIterator as $submission) {
282  if ($submission->getSubmissionProgress() == 0) { // Not incomplete
283  $this->submissionMetadataChanged($submission);
284  $this->submissionFilesChanged($submission);
285  $numIndexed++;
286  }
287  }
288  $this->submissionChangesFinished();
289 
290  if ($log) echo __('search.cli.rebuildIndex.result', array('numIndexed' => $numIndexed)) . "\n";
291  }
292  }
293  }
294 
295 
296  //
297  // Private helper methods
298  //
305  protected function _indexObjectKeywords($objectId, $text, &$position) {
306  $searchDao = DAORegistry::getDAO('ArticleSearchDAO'); /* @var $searchDao ArticleSearchDAO */
307  $keywords = $this->filterKeywords($text);
308  for ($i = 0, $count = count($keywords); $i < $count; $i++) {
309  if ($searchDao->insertObjectKeyword($objectId, $keywords[$i], $position) !== null) {
310  $position += 1;
311  }
312  }
313  }
314 
322  protected function _updateTextIndex($articleId, $type, $text, $assocId = null) {
323  $searchDao = DAORegistry::getDAO('ArticleSearchDAO'); /* @var $searchDao ArticleSearchDAO */
324  $objectId = $searchDao->insertObject($articleId, $type, $assocId);
325  $position = 0;
326  $this->_indexObjectKeywords($objectId, $text, $position);
327  }
328 }
329 
330 
SubmissionSearchIndex\filterKeywords
filterKeywords($text, $allowWildcards=false)
Definition: SubmissionSearchIndex.inc.php:32
AppLocale\requireComponents
static requireComponents()
Definition: env1/MockAppLocale.inc.php:56
ArticleSearchIndex\articleMetadataChanged
articleMetadataChanged($article)
Definition: ArticleSearchIndex.inc.php:65
ArticleSearchIndex\articleChangesFinished
articleChangesFinished()
Definition: ArticleSearchIndex.inc.php:232
ArticleSearchIndex\submissionChangesFinished
submissionChangesFinished()
Definition: ArticleSearchIndex.inc.php:218
DAORegistry\getDAO
static & getDAO($name, $dbconn=null)
Definition: DAORegistry.inc.php:57
ArticleSearchIndex\submissionFileChanged
submissionFileChanged($articleId, $type, $fileId)
Definition: ArticleSearchIndex.inc.php:91
ArticleSearchIndex\articleDeleted
articleDeleted($articleId)
Definition: ArticleSearchIndex.inc.php:203
ArticleSearchIndex\submissionFileDeleted
submissionFileDeleted($articleId, $type=null, $assocId=null)
Definition: ArticleSearchIndex.inc.php:179
ArticleSearchIndex\submissionMetadataChanged
submissionMetadataChanged($submission)
Definition: ArticleSearchIndex.inc.php:23
ArticleSearchIndex\_indexObjectKeywords
_indexObjectKeywords($objectId, $text, &$position)
Definition: ArticleSearchIndex.inc.php:305
SearchFileParser\fromFile
static fromFile($file)
Definition: SearchFileParser.inc.php:106
ArticleSearchIndex\submissionFilesChanged
submissionFilesChanged($article)
Definition: ArticleSearchIndex.inc.php:138
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:76
ArticleSearchIndex\_updateTextIndex
_updateTextIndex($articleId, $type, $text, $assocId=null)
Definition: ArticleSearchIndex.inc.php:322
ArticleSearchIndex\clearSubmissionFiles
clearSubmissionFiles($submission)
Definition: ArticleSearchIndex.inc.php:124
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:248
PKPServices\get
static get($service)
Definition: PKPServices.inc.php:49