regexp_match_get() static public method

See also: http://ca.php.net/manual/en/function.regexp_match_get.php
static public regexp_match_get ( $pattern, $subject, &$matches ) : integer | boolean
$pattern string Regular expression
$subject string String to apply regular expression to
$matches array Reference to receive matches
return integer | boolean Returns 1 if the pattern matches given subject, 0 if it does not, or FALSE if an error occurred.
 /**
  * Retrieve the export as an XML string.
  * @param $pluginUrl string the url to be requested for export.
  * @param $postParams array additional post parameters
  * @return string
  */
 protected function getXmlOnExport($pluginUrl, $postParams = array())
 {
     // Prepare HTTP session.
     $curlCh = curl_init();
     curl_setopt($curlCh, CURLOPT_POST, true);
     // Create a cookie file (required for log-in).
     $cookies = tempnam(sys_get_temp_dir(), 'curlcookies');
     // Log in.
     $loginUrl = $this->baseUrl . '/index.php/test/login/signIn';
     // Bug #8518 safety work-around
     if ($this->password[0] == '@') {
         die('CURL parameters may not begin with @.');
     }
     $loginParams = array('username' => 'admin', 'password' => $this->password);
     curl_setopt($curlCh, CURLOPT_URL, $loginUrl);
     curl_setopt($curlCh, CURLOPT_POSTFIELDS, $loginParams);
     curl_setopt($curlCh, CURLOPT_COOKIEJAR, $cookies);
     self::assertTrue(curl_exec($curlCh));
     // Request export document.
     $exportUrl = $this->baseUrl . '/index.php/test/manager/importexport/plugin/' . $pluginUrl;
     curl_setopt($curlCh, CURLOPT_URL, $exportUrl);
     // Bug #8518 safety work-around
     foreach ($postParams as $paramValue) {
         if ($paramValue[0] == '@') {
             die('CURL parameters may not begin with @.');
         }
     }
     curl_setopt($curlCh, CURLOPT_POSTFIELDS, $postParams);
     curl_setopt($curlCh, CURLOPT_HTTPHEADER, array('Accept: application/xml, application/x-gtar, */*'));
     curl_setopt($curlCh, CURLOPT_RETURNTRANSFER, true);
     curl_setopt($curlCh, CURLOPT_HEADER, true);
     $response = curl_exec($curlCh);
     do {
         list($header, $response) = explode("\r\n\r\n", $response, 2);
     } while (PKPString::regexp_match('#HTTP/.*100#', $header));
     // Check whether we got a tar file.
     if (PKPString::regexp_match('#Content-Type: application/x-gtar#', $header)) {
         // Save the data to a temporary file.
         $tempfile = tempnam(sys_get_temp_dir(), 'tst');
         file_put_contents($tempfile, $response);
         // Recursively extract tar file.
         $result = $this->extractTarFile($tempfile);
         unlink($tempfile);
     } else {
         $matches = null;
         PKPString::regexp_match_get('#filename="([^"]+)"#', $header, $matches);
         self::assertTrue(isset($matches[1]));
         $result = array($matches[1] => $response);
     }
     // Destroy HTTP session.
     curl_close($curlCh);
     unlink($cookies);
     return $result;
 }
 /**
  * Extract and validate a plugin (prior to installation)
  * @param $filePath string Full path to plugin archive
  * @param $originalFileName string Original filename of plugin archive
  * @return string|null Extracted plugin path on success; null on error
  */
 function extractPlugin($filePath, $originalFileName, &$errorMsg)
 {
     $fileManager = new FileManager();
     // tar archive basename (less potential version number) must
     // equal plugin directory name and plugin files must be in a
     // directory named after the plug-in (potentially with version)
     $matches = array();
     PKPString::regexp_match_get('/^[a-zA-Z0-9]+/', basename($originalFileName, '.tar.gz'), $matches);
     $pluginShortName = array_pop($matches);
     if (!$pluginShortName) {
         $errorMsg = __('manager.plugins.invalidPluginArchive');
         $fileManager->deleteFile($filePath);
         return null;
     }
     // Create random dirname to avoid symlink attacks.
     $pluginExtractDir = dirname($filePath) . DIRECTORY_SEPARATOR . $pluginShortName . substr(md5(mt_rand()), 0, 10);
     mkdir($pluginExtractDir);
     // Test whether the tar binary is available for the export to work
     $tarBinary = Config::getVar('cli', 'tar');
     if (!empty($tarBinary) && file_exists($tarBinary)) {
         exec($tarBinary . ' -xzf ' . escapeshellarg($filePath) . ' -C ' . escapeshellarg($pluginExtractDir));
     } else {
         $errorMsg = __('manager.plugins.tarCommandNotFound');
     }
     $fileManager->deleteFile($filePath);
     if (empty($errorMsg)) {
         // Look for a directory named after the plug-in's short
         // (alphanumeric) name within the extracted archive.
         if (is_dir($tryDir = $pluginExtractDir . '/' . $pluginShortName)) {
             return $tryDir;
             // Success
         }
         // Failing that, look for a directory named after the
         // archive. (Typically also contains the version number
         // e.g. with github generated release archives.)
         PKPString::regexp_match_get('/^[a-zA-Z0-9.-]+/', basename($originalFileName, '.tar.gz'), $matches);
         if (is_dir($tryDir = $pluginExtractDir . '/' . array_pop($matches))) {
             // We found a directory named after the archive
             // within the extracted archive. (Typically also
             // contains the version number, e.g. github
             // generated release archives.)
             return $tryDir;
         }
         $errorMsg = __('manager.plugins.invalidPluginArchive');
     }
     $fileManager->rmtree($pluginExtractDir);
     return null;
 }
 /**
  * Normalize incoming date string.
  * @see Filter::process()
  * @param $input string
  * @return string
  */
 function &process(&$input)
 {
     // FIXME: We have to i18nize this when expanding citation parsing to other languages
     static $monthNames = array('Jan' => '01', 'Feb' => '02', 'Mar' => '03', 'Apr' => '04', 'May' => '05', 'Jun' => '06', 'Jul' => '07', 'Aug' => '08', 'Sep' => '09', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12');
     $dateExpressions = array('/(?P<year>\\d{4})-(?P<month>\\d{2})-(?P<day>\\d{2})/', '/(?P<year>\\d{4})(\\s|-)*(?P<monthName>[a-z]\\w+)?(\\s|-)*(?P<day>\\d+)?/i');
     $normalizedDate = null;
     foreach ($dateExpressions as $dateExpression) {
         if (PKPString::regexp_match_get($dateExpression, $input, $parsedDate)) {
             if (isset($parsedDate['year'])) {
                 $normalizedDate = $parsedDate['year'];
                 $month = '';
                 if (isset($parsedDate['monthName'])) {
                     $monthName = substr($parsedDate['monthName'], 0, 3);
                     if (isset($monthNames[$monthName])) {
                         // Convert the month name to a two digit numeric month representation.
                         $month = $monthNames[$monthName];
                     }
                 }
                 if (isset($parsedDate['month'])) {
                     // Convert month to a two digit representation.
                     $month = str_pad($parsedDate['month'], 2, '0', STR_PAD_LEFT);
                 }
                 if (!empty($month)) {
                     $normalizedDate .= '-' . $month;
                     if (isset($parsedDate['day'])) {
                         $normalizedDate .= '-' . str_pad($parsedDate['day'], 2, '0', STR_PAD_LEFT);
                     }
                 }
             }
             if (!empty($normalizedDate)) {
                 break;
             }
         }
     }
     return $normalizedDate;
 }
 /**
  * @see Validator::isValid()
  * @param $value mixed
  * @return boolean
  */
 function isValid($value)
 {
     return (bool) PKPString::regexp_match_get($this->_regExp, $value, $this->_matches);
 }
 /**
  * @see OAIMetadataFormat#toXml
  * TODO:
  *  <copyright-holder>
  *  In Isabelle's mapping document:
  *   Article order in the issue's Table of Contents
  */
 function toXml(&$record, $format = null)
 {
     $article =& $record->getData('article');
     $journal =& $record->getData('journal');
     $section =& $record->getData('section');
     $issue =& $record->getData('issue');
     $galleys =& $record->getData('galleys');
     $articleId = $article->getId();
     // Cache issue ordering information.
     static $issueId;
     static $sectionSeq;
     if (!isset($issueId) || $issueId != $issue->getId()) {
         $sectionDao = DAORegistry::getDAO('SectionDAO');
         $issueId = $issue->getId();
         $sections = $sectionDao->getByIssueId($issueId);
         $sectionSeq = array();
         $i = 0;
         foreach ($sections as $thisSection) {
             $sectionSeq[$thisSection->getId()] = $i++;
         }
         unset($sections);
     }
     $abbreviation = $journal->getLocalizedSetting('abbreviation');
     $printIssn = $journal->getSetting('printIssn');
     $onlineIssn = $journal->getSetting('onlineIssn');
     $primaryLocale = $article->getLanguage() != '' ? $article->getLanguage() : $journal->getPrimaryLocale();
     $publisherInstitution = $journal->getSetting('publisherInstitution');
     $datePublished = $article->getDatePublished();
     if (!$datePublished) {
         $datePublished = $issue->getDatePublished();
     }
     if ($datePublished) {
         $datePublished = strtotime($datePublished);
     }
     $response = "<article\n" . "\txmlns=\"http://dtd.nlm.nih.gov/publishing/2.3\"\n" . "\txmlns:xlink=\"http://www.w3.org/1999/xlink\"\n" . "\txmlns:mml=\"http://www.w3.org/1998/Math/MathML\"\n" . "\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" . "\txsi:schemaLocation=\"http://dtd.nlm.nih.gov/publishing/2.3\n" . "\thttp://dtd.nlm.nih.gov/publishing/2.3/xsd/journalpublishing.xsd\"\n" . (($s = $section->getLocalizedIdentifyType()) != '' ? "\tarticle-type=\"" . htmlspecialchars(Core::cleanVar($s)) . "\"" : '') . "\txml:lang=\"" . strtoupper(substr($primaryLocale, 0, 2)) . "\">\n" . "\t<front>\n" . "\t\t<journal-meta>\n" . "\t\t\t<journal-id journal-id-type=\"other\">" . htmlspecialchars(Core::cleanVar(($s = Config::getVar('oai', 'nlm_journal_id')) != '' ? $s : $journal->getPath())) . "</journal-id>\n" . "\t\t\t<journal-title>" . htmlspecialchars(Core::cleanVar($journal->getLocalizedName())) . "</journal-title>\n";
     // Include translated journal titles
     foreach ($journal->getName(null) as $locale => $title) {
         if ($locale == $primaryLocale) {
             continue;
         }
         $response .= "\t\t\t<trans-title xml:lang=\"" . strtoupper(substr($locale, 0, 2)) . "\">" . htmlspecialchars(Core::cleanVar($title)) . "</trans-title>\n";
     }
     $response .= (!empty($onlineIssn) ? "\t\t\t<issn pub-type=\"epub\">" . htmlspecialchars(Core::cleanVar($onlineIssn)) . "</issn>" : '') . (!empty($printIssn) ? "\t\t\t<issn pub-type=\"ppub\">" . htmlspecialchars(Core::cleanVar($printIssn)) . "</issn>" : '') . ($publisherInstitution != '' ? "\t\t\t<publisher><publisher-name>" . htmlspecialchars(Core::cleanVar($publisherInstitution)) . "</publisher-name></publisher>\n" : '') . "\t\t</journal-meta>\n" . "\t\t<article-meta>\n" . "\t\t\t<article-id pub-id-type=\"other\">" . htmlspecialchars(Core::cleanVar($article->getBestArticleId())) . "</article-id>\n" . (($s = $article->getPubId('doi')) ? "\t\t\t<article-id pub-id-type=\"doi\">" . htmlspecialchars(Core::cleanVar($s)) . "</article-id>\n" : '') . "\t\t\t<article-categories><subj-group subj-group-type=\"heading\"><subject>" . htmlspecialchars(Core::cleanVar($section->getLocalizedTitle())) . "</subject></subj-group></article-categories>\n" . "\t\t\t<title-group>\n" . "\t\t\t\t<article-title>" . htmlspecialchars(Core::cleanVar(strip_tags($article->getLocalizedTitle()))) . "</article-title>\n";
     // Include translated journal titles
     foreach ($article->getTitle(null) as $locale => $title) {
         if ($locale == $primaryLocale) {
             continue;
         }
         $response .= "\t\t\t\t<trans-title xml:lang=\"" . strtoupper(substr($locale, 0, 2)) . "\">" . htmlspecialchars(Core::cleanVar(strip_tags($title))) . "</trans-title>\n";
     }
     $response .= "\t\t\t</title-group>\n" . "\t\t\t<contrib-group>\n";
     // Include authors
     foreach ($article->getAuthors() as $author) {
         $response .= "\t\t\t\t<contrib " . ($author->getPrimaryContact() ? 'corresp="yes" ' : '') . "contrib-type=\"author\">\n" . "\t\t\t\t\t<name name-style=\"western\">\n" . "\t\t\t\t\t\t<surname>" . htmlspecialchars(Core::cleanVar($author->getLastName())) . "</surname>\n" . "\t\t\t\t\t\t<given-names>" . htmlspecialchars(Core::cleanVar($author->getFirstName()) . (($s = $author->getMiddleName()) != '' ? " {$s}" : '')) . "</given-names>\n" . "\t\t\t\t\t</name>\n" . (($s = $author->getLocalizedAffiliation()) != '' ? "\t\t\t\t\t<aff>" . htmlspecialchars(Core::cleanVar($s)) . "</aff>\n" : '') . "\t\t\t\t\t<email>" . htmlspecialchars(Core::cleanVar($author->getEmail())) . "</email>\n" . (($s = $author->getUrl()) != '' ? "\t\t\t\t\t<uri>" . htmlspecialchars(Core::cleanVar($s)) . "</uri>\n" : '') . "\t\t\t\t</contrib>\n";
     }
     // Include editorships (optimized)
     $response .= $this->getEditorialInfo($journal->getId());
     $response .= "\t\t\t</contrib-group>\n";
     if ($datePublished) {
         $response .= "\t\t\t<pub-date pub-type=\"epub\">\n" . "\t\t\t\t<day>" . strftime('%d', $datePublished) . "</day>\n" . "\t\t\t\t<month>" . strftime('%m', $datePublished) . "</month>\n" . "\t\t\t\t<year>" . strftime('%Y', $datePublished) . "</year>\n" . "\t\t\t</pub-date>\n";
     }
     $response .= ($issue->getShowYear() ? "\t\t\t<pub-date pub-type=\"collection\"><year>" . htmlspecialchars(Core::cleanVar($issue->getYear())) . "</year></pub-date>\n" : '') . ($issue->getShowVolume() ? "\t\t\t<volume>" . htmlspecialchars(Core::cleanVar($issue->getVolume())) . "</volume>\n" : '') . ($issue->getShowNumber() ? "\t\t\t<issue seq=\"" . htmlspecialchars(Core::cleanVar($sectionSeq[$section->getId()] * 100 + $article->getSequence())) . "\">" . htmlspecialchars(Core::cleanVar($issue->getNumber())) . "</issue>\n" : '') . "\t\t\t<issue-id pub-id-type=\"other\">" . htmlspecialchars(Core::cleanVar($issue->getBestIssueId())) . "</issue-id>\n" . ($issue->getShowTitle() ? "\t\t\t<issue-title>" . htmlspecialchars(Core::cleanVar($issue->getLocalizedTitle())) . "</issue-title>\n" : '');
     // Include page info, if available and parseable.
     $matches = null;
     if (PKPString::regexp_match_get('/^[Pp][Pp]?[.]?[ ]?(\\d+)$/', $article->getPages(), $matches)) {
         $matchedPage = htmlspecialchars(Core::cleanVar($matches[1]));
         $response .= "\t\t\t\t<fpage>{$matchedPage}</fpage><lpage>{$matchedPage}</lpage>\n";
         $pageCount = 1;
     } elseif (PKPString::regexp_match_get('/^[Pp][Pp]?[.]?[ ]?(\\d+)[ ]?(-|–)[ ]?([Pp][Pp]?[.]?[ ]?)?(\\d+)$/', $article->getPages(), $matches)) {
         $matchedPageFrom = htmlspecialchars(Core::cleanVar($matches[1]));
         $matchedPageTo = htmlspecialchars(Core::cleanVar($matches[4]));
         $response .= "\t\t\t\t<fpage>{$matchedPageFrom}</fpage>\n" . "\t\t\t\t<lpage>{$matchedPageTo}</lpage>\n";
         $pageCount = $matchedPageTo - $matchedPageFrom + 1;
     }
     $response .= "\t\t\t<permissions>\n" . "\t\t\t\t<copyright-statement>" . htmlspecialchars(__('submission.copyrightStatement', array('copyrightYear' => $article->getCopyrightYear(), 'copyrightHolder' => $article->getLocalizedCopyrightHolder()))) . "</copyright-statement>\n" . ($datePublished ? "\t\t\t\t<copyright-year>" . $article->getCopyrightYear() . "</copyright-year>\n" : '') . "\t\t\t\t<license xlink:href=\"" . $article->getLicenseURL() . "\">\n" . (($s = Application::getCCLicenseBadge($article->getLicenseURL())) ? "\t\t\t\t\t<license-p>" . strip_tags($s) . "</license-p>\n" : '') . "\t\t\t\t</license>\n" . "\t\t\t</permissions>\n" . "\t\t\t<self-uri xlink:href=\"" . htmlspecialchars(Core::cleanVar(Request::url($journal->getPath(), 'article', 'view', $article->getBestArticleId()))) . "\" />\n";
     // Include galley links
     foreach ($article->getGalleys() as $galley) {
         $response .= "\t\t\t<self-uri content-type=\"" . htmlspecialchars(Core::cleanVar($galley->getFileType())) . "\" xlink:href=\"" . htmlspecialchars(Core::cleanVar(Request::url($journal->getPath(), 'article', 'view', array($article->getBestArticleId(), $galley->getId())))) . "\" />\n";
     }
     // Include abstract(s)
     $abstract = htmlspecialchars(Core::cleanVar(strip_tags($article->getLocalizedAbstract())));
     if (!empty($abstract)) {
         $abstract = "<p>{$abstract}</p>";
         // $abstract = '<p>' . PKPString::regexp_replace('/\n+/', '</p><p>', $abstract) . '</p>';
         $response .= "\t\t\t<abstract xml:lang=\"" . strtoupper(substr($primaryLocale, 0, 2)) . "\">{$abstract}</abstract>\n";
     }
     if (is_array($article->getAbstract(null))) {
         foreach ($article->getAbstract(null) as $locale => $abstract) {
             if ($locale == $primaryLocale || empty($abstract)) {
                 continue;
             }
             $abstract = htmlspecialchars(Core::cleanVar(strip_tags($abstract)));
             if (empty($abstract)) {
                 continue;
             }
             $abstract = "<p>{$abstract}</p>";
             //$abstract = '<p>' . PKPString::regexp_replace('/\n+/', '</p><p>', $abstract) . '</p>';
             $response .= "\t\t\t<abstract-trans xml:lang=\"" . strtoupper(substr($locale, 0, 2)) . "\">{$abstract}</abstract-trans>\n";
         }
     }
     $subjects = array();
     if (is_array($article->getSubject(null))) {
         foreach ($article->getSubject(null) as $locale => $subject) {
             $s = array_map('trim', explode(';', Core::cleanVar($subject)));
             if (!empty($s)) {
                 $subjects[$locale] = $s;
             }
         }
     }
     if (!empty($subjects)) {
         foreach ($subjects as $locale => $s) {
             $response .= "\t\t\t<kwd-group xml:lang=\"" . strtoupper(substr($locale, 0, 2)) . "\">\n";
             foreach ($s as $subject) {
                 $response .= "\t\t\t\t<kwd>" . htmlspecialchars($subject) . "</kwd>\n";
             }
             $response .= "\t\t\t</kwd-group>\n";
         }
     }
     $response .= (isset($pageCount) ? "\t\t\t<counts><page-count count=\"" . (int) $pageCount . "\" /></counts>\n" : '') . "\t\t</article-meta>\n" . "\t</front>\n";
     // Include body text (for search indexing only)
     import('classes.search.ArticleSearchIndex');
     $text = '';
     $galleys = $article->getGalleys();
     // Give precedence to HTML galleys, as they're quickest to parse
     usort($galleys, create_function('$a, $b', 'return $a->getFileType()==\'text/html\')?-1:1;'));
     // Determine any access limitations. If there are, do not
     // provide the full-text.
     import('classes.issue.IssueAction');
     $issueAction = new IssueAction();
     $subscriptionRequired = $issueAction->subscriptionRequired($issue);
     $isSubscribedDomain = $issueAction->subscribedDomain($journal, $issue->getId(), $article->getId());
     if (!$subscriptionRequired || $isSubscribedDomain) {
         foreach ($galleys as $galley) {
             $parser =& SearchFileParser::fromFile($galley);
             if ($parser && $parser->open()) {
                 while (($s = $parser->read()) !== false) {
                     $text .= $s;
                 }
                 $parser->close();
             }
             if ($galley->getFileType() == 'text/html') {
                 $text = strip_tags($text);
             }
             unset($galley);
             // Use the first parseable galley.
             if (!empty($text)) {
                 break;
             }
         }
     }
     if (!empty($text)) {
         $response .= "\t<body><p>" . htmlspecialchars(Core::cleanVar(Core::cleanVar($text))) . "</p></body>\n";
     }
     // Add NLM citation info
     $filterDao = DAORegistry::getDAO('FilterDAO');
     /* @var $filterDao FilterDAO */
     $nlmFilters = $filterDao->getObjectsByGroup('submission=>nlm23-article-xml');
     assert(count($nlmFilters) == 1);
     $nlmFilter = array_pop($nlmFilters);
     $nlmXmlDom = new DOMDocument();
     $nlmXmlDom->loadXML($nlmFilter->execute($article));
     $documentElement =& $nlmXmlDom->documentElement;
     // Work-around for hasChildNodes being stupid about whitespace.
     $hasChildren = false;
     if (isset($documentElement->childNodes)) {
         foreach ($documentElement->childNodes as $c) {
             if ($c->nodeType == XML_ELEMENT_NODE) {
                 $hasChildren = true;
             }
         }
     }
     // If there were any citations, include them.
     if ($hasChildren) {
         $innerXml = $nlmXmlDom->saveXML($documentElement);
         $response .= "<back>{$innerXml}</back>\n";
     }
     $response .= "</article>";
     return $response;
 }
 /**
  * Submit a new test article.
  * @param $title string
  * @return integer the id of the new article
  */
 protected function submitArticle($title = 'Editing test article')
 {
     // We need to be logged in to submit an article.
     $this->logIn();
     $submissionPage = $this->baseUrl . '/index.php/lucene-test/author/submit/';
     //
     // First submission page.
     //
     $this->verifyAndOpen($submissionPage . '1');
     $this->waitForElementPresent('css=input.defaultButton');
     // Set Section.
     $this->select('sectionId', 'value=3');
     // Accept submission conditions.
     $checkboxId = 1;
     while ($this->isElementPresent("checklist-{$checkboxId}")) {
         $this->check("checklist-{$checkboxId}");
         $checkboxId++;
     }
     // Submit first submission page.
     $this->clickAndWait('css=input.defaultButton');
     //
     // Second submission page.
     //
     $this->waitForLocation($submissionPage . '2*');
     $this->waitForElementPresent('css=input.defaultButton');
     // We should now have the article ID in the URL.
     $url = $this->getLocation();
     $matches = null;
     PKPString::regexp_match_get('/articleId=([0-9]+)/', $url, $matches);
     self::assertTrue(count($matches) == 2);
     $articleId = $matches[1];
     self::assertTrue(is_numeric($articleId));
     $articleId = (int) $articleId;
     // Submit the second submission page.
     $this->clickAndWait('css=input.defaultButton');
     $this->waitForConfirmation('*Are you sure you wish to continue*');
     //
     // Third submission page.
     //
     $this->waitForLocation($submissionPage . '3*');
     $this->waitForElementPresent('css=input.defaultButton');
     // Fill in article metadata.
     $this->type('authors-0-firstName', 'Arthur');
     $this->type('authors-0-lastName', 'McAutomatic');
     $this->type('title', $title);
     $this->verifyElementPresent('id=abstract_ifr');
     if ($this->verified()) {
         // TinyMCE hack.
         $jsScript = "selenium.browserbot.getCurrentWindow().document" . ".getElementById('abstract_ifr').contentDocument.body.innerHTML = " . "'{$title} abstract'";
         $this->getEval($jsScript);
     } else {
         $this->type('abstract', $title . ' abstract');
     }
     // Submit metadata.
     $this->clickAndWait('css=input.defaultButton');
     //
     // Fourth and fifth submission page.
     //
     $this->waitForLocation($submissionPage . '4*');
     $this->waitForElementPresent('css=input.defaultButton');
     // Do not upload any supplementary file and continue.
     $this->clickAndWait('css=input.defaultButton');
     $this->waitForLocation($submissionPage . '5*');
     $this->waitForElementPresent('css=input.defaultButton');
     // Confirm the submission.
     $this->clickAndWait('css=input.defaultButton');
     return $articleId;
 }
Esempio n. 7
0
 /**
  * Do the actual web service request.
  * @param $action string
  * @param $arg string
  * @param $attachment array
  * @return boolean|string True for success, an error message otherwise.
  */
 function _doRequest($action, $arg, $attachment = null)
 {
     // Build the multipart SOAP message from scratch.
     $soapMessage = '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" ' . 'xmlns:med="http://www.medra.org">' . '<SOAP-ENV:Header/>' . '<SOAP-ENV:Body>' . "<med:{$action}>{$arg}</med:{$action}>" . '</SOAP-ENV:Body>' . '</SOAP-ENV:Envelope>';
     $soapMessageId = $this->_getContentId($action);
     if ($attachment) {
         assert(count($attachment) == 1);
         $request = "--MIME_boundary\r\n" . $this->_getMimePart($soapMessageId, $soapMessage) . "--MIME_boundary\r\n" . $this->_getMimePart(key($attachment), current($attachment)) . "--MIME_boundary--\r\n";
         $contentType = 'multipart/related; type="text/xml"; boundary="MIME_boundary"';
     } else {
         $request = $soapMessage;
         $contentType = 'text/xml';
     }
     // Prepare HTTP session.
     $curlCh = curl_init();
     curl_setopt($curlCh, CURLOPT_RETURNTRANSFER, true);
     curl_setopt($curlCh, CURLOPT_POST, true);
     // Set up basic authentication.
     curl_setopt($curlCh, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
     curl_setopt($curlCh, CURLOPT_USERPWD, $this->_auth);
     // Set up SSL.
     curl_setopt($curlCh, CURLOPT_SSL_VERIFYPEER, false);
     // Make SOAP request.
     curl_setopt($curlCh, CURLOPT_URL, $this->_endpoint);
     $extraHeaders = array('SOAPAction: "' . $action . '"', 'Content-Type: ' . $contentType, 'UserAgent: OJS-mEDRA');
     curl_setopt($curlCh, CURLOPT_HTTPHEADER, $extraHeaders);
     curl_setopt($curlCh, CURLOPT_POSTFIELDS, $request);
     $result = true;
     $response = curl_exec($curlCh);
     // We do not localize our error messages as they are all
     // fatal errors anyway and must be analyzed by technical staff.
     if ($response === false) {
         $result = 'OJS-mEDRA: Expected string response.';
     }
     if ($result === true && ($status = curl_getinfo($curlCh, CURLINFO_HTTP_CODE)) != MEDRA_WS_RESPONSE_OK) {
         $result = 'OJS-mEDRA: Expected ' . MEDRA_WS_RESPONSE_OK . ' response code, got ' . $status . ' instead.';
     }
     curl_close($curlCh);
     // Check SOAP response by simple string manipulation rather
     // than instantiating a DOM.
     if (is_string($response)) {
         $matches = array();
         PKPString::regexp_match_get('#<faultstring>([^<]*)</faultstring>#', $response, $matches);
         if (empty($matches)) {
             if ($attachment) {
                 assert(PKPString::regexp_match('#<returnCode>success</returnCode>#', $response));
             } else {
                 $parts = explode("\r\n\r\n", $response);
                 $result = array_pop($parts);
                 $result = PKPString::regexp_replace('/>[^>]*$/', '>', $result);
             }
         } else {
             $result = 'mEDRA: ' . $status . ' - ' . $matches[1];
         }
     } else {
         $result = 'OJS-mEDRA: Expected string response.';
     }
     return $result;
 }
 /**
  * Converts a string with a single person
  * to an NLM name description.
  *
  * TODO: add initials from all given names to initials
  *       element
  *
  * @param $personString string
  * @param $title boolean true to parse for title
  * @param $degrees boolean true to parse for degrees
  * @return MetadataDescription an NLM name description or null
  *  if the string could not be converted
  */
 function &_parsePersonString($personString, $title, $degrees)
 {
     // Expressions to parse person strings, ported from CiteULike person
     // plugin, see http://svn.citeulike.org/svn/plugins/person.tcl
     static $personRegex = array('title' => '(?:His (?:Excellency|Honou?r)\\s+|Her (?:Excellency|Honou?r)\\s+|The Right Honou?rable\\s+|The Honou?rable\\s+|Right Honou?rable\\s+|The Rt\\.? Hon\\.?\\s+|The Hon\\.?\\s+|Rt\\.? Hon\\.?\\s+|Mr\\.?\\s+|Ms\\.?\\s+|M\\/s\\.?\\s+|Mrs\\.?\\s+|Miss\\.?\\s+|Dr\\.?\\s+|Sir\\s+|Dame\\s+|Prof\\.?\\s+|Professor\\s+|Doctor\\s+|Mister\\s+|Mme\\.?\\s+|Mast(?:\\.|er)?\\s+|Lord\\s+|Lady\\s+|Madam(?:e)?\\s+|Priv\\.-Doz\\.\\s+)+', 'degrees' => '(,\\s+(?:[A-Z\\.]+))+', 'initials' => '(?:(?:[A-Z]\\.){1,3}[A-Z]\\.?)|(?:(?:[A-Z]\\.\\s){1,3}[A-Z]\\.?)|(?:[A-Z]{1,4})|(?:(?:[A-Z]\\.-?){1,4})|(?:(?:[A-Z]\\.-?){1,3}[A-Z]\\.?)|(?:(?:[A-Z]-){1,3}[A-Z])|(?:(?:[A-Z]\\s){1,3}[A-Z]\\.?)|(?:(?:[A-Z]-){1,3}[A-Z]\\.?)', 'prefix' => 'Dell(?:[a|e])?(?:\\s|$)|Dalle(?:\\s|$)|D[a|e]ll\'(?:\\s|$)|Dela(?:\\s|$)|Del(?:\\s|$)|[Dd]e(?:\\s|$)(?:La(?:\\s|$)|Los(?:\\s|$))?|[Dd]e(?:\\s|$)|[Dd][a|i|u](?:\\s|$)|L[a|e|o](?:\\s|$)|[D|L|O]\'|St\\.?(?:\\s|$)|San(?:\\s|$)|[Dd]en(?:\\s|$)|[Vv]on(?:\\s|$)(?:[Dd]er(?:\\s|$))?|(?:[Ll][ea](?:\\s|$))?[Vv]an(?:\\s|$)(?:[Dd]e(?:n|r)?(?:\\s|$))?', 'givenName' => '(?:[^ \\t\\n\\r\\f\\v,.;()]{2,}|[^ \\t\\n\\r\\f\\v,.;()]{2,}\\-[^ \\t\\n\\r\\f\\v,.;()]{2,})');
     // The expressions for given name, suffix and surname are the same
     $personRegex['surname'] = $personRegex['suffix'] = $personRegex['givenName'];
     $personRegex['double-surname'] = "(?:" . $personRegex['surname'] . "\\s)*" . $personRegex['surname'];
     // Shortcut for prefixed surname
     $personRegexPrefixedSurname = "(?P<prefix>(?:" . $personRegex['prefix'] . ")?)(?P<surname>" . $personRegex['surname'] . ")";
     $personRegexPrefixedDoubleSurname = "(?P<prefix>(?:" . $personRegex['prefix'] . ")?)(?P<surname>" . $personRegex['double-surname'] . ")";
     // Instantiate the target person description
     $personDescription = new MetadataDescription('lib.pkp.plugins.metadata.nlm30.schema.Nlm30NameSchema', $this->_assocType);
     // Clean the person string
     $personString = trim($personString);
     // 1. Extract title and degree from the person string and use this as suffix
     $suffixString = '';
     $results = array();
     if ($title && PKPString::regexp_match_get('/^(' . $personRegex['title'] . ')/i', $personString, $results)) {
         $suffixString = trim($results[1], ',:; ');
         $personString = PKPString::regexp_replace('/^(' . $personRegex['title'] . ')/i', '', $personString);
     }
     if ($degrees && PKPString::regexp_match_get('/(' . $personRegex['degrees'] . ')$/i', $personString, $results)) {
         $degreesArray = explode(',', trim($results[1], ','));
         foreach ($degreesArray as $key => $degree) {
             $degreesArray[$key] = PKPString::trimPunctuation($degree);
         }
         $suffixString .= ' - ' . implode('; ', $degreesArray);
         $personString = PKPString::regexp_replace('/(' . $personRegex['degrees'] . ')$/i', '', $personString);
     }
     if (!empty($suffixString)) {
         $personDescription->addStatement('suffix', $suffixString);
     }
     // Space initials when followed by a given name or last name.
     $personString = PKPString::regexp_replace('/([A-Z])\\.([A-Z][a-z])/', '\\1. \\2', $personString);
     // 2. Extract names and initials from the person string
     // The parser expressions are ordered by specificity. The most specific expressions
     // come first. Only if these specific expressions don't work will we turn to less
     // specific ones. This avoids parsing errors. It also explains why we don't use the
     // ?-quantifier for optional elements like initials or middle name where they could
     // be misinterpreted.
     $personExpressions = array('/^' . $personRegexPrefixedSurname . '$/i', '/^(?P<initials>' . $personRegex['initials'] . ')\\s' . $personRegexPrefixedSurname . '$/', '/^' . $personRegexPrefixedSurname . ',?\\s(?P<initials>' . $personRegex['initials'] . ')$/', '/^' . $personRegexPrefixedDoubleSurname . ',\\s(?P<givenName>' . $personRegex['givenName'] . ')\\s(?P<initials>' . $personRegex['initials'] . ')$/', '/^(?P<givenName>' . $personRegex['givenName'] . ')\\s(?P<initials>' . $personRegex['initials'] . ')\\s' . $personRegexPrefixedSurname . '$/', '/^' . $personRegexPrefixedDoubleSurname . ',\\s(?P<givenName>(?:' . $personRegex['givenName'] . '\\s)+)(?P<initials>' . $personRegex['initials'] . ')$/', '/^(?P<givenName>(?:' . $personRegex['givenName'] . '\\s)+)(?P<initials>' . $personRegex['initials'] . ')\\s' . $personRegexPrefixedSurname . '$/', '/^' . $personRegexPrefixedDoubleSurname . ',(?P<givenName>(?:\\s' . $personRegex['givenName'] . ')+)$/', '/^(?P<givenName>(?:' . $personRegex['givenName'] . '\\s)+)' . $personRegexPrefixedSurname . '$/', '/^\\s*(?P<surname>' . $personRegex['surname'] . ')(?P<suffix>(?:\\s+' . $personRegex['suffix'] . ')?)\\s*,\\s*(?P<initials>(?:' . $personRegex['initials'] . ')?)\\s*\\((?P<givenName>(?:\\s*' . $personRegex['givenName'] . ')+)\\s*\\)\\s*(?P<prefix>(?:' . $personRegex['prefix'] . ')?)$/', '/^(?P<givenName>' . $personRegex['givenName'] . ')\\.(?P<surname>' . $personRegex['double-surname'] . ')$/', '/^(?P<surname>.*)$/');
     $results = array();
     foreach ($personExpressions as $expressionId => $personExpression) {
         if ($nameFound = PKPString::regexp_match_get($personExpression, $personString, $results)) {
             // Given names
             if (!empty($results['givenName'])) {
                 // Split given names
                 $givenNames = explode(' ', trim($results['givenName']));
                 foreach ($givenNames as $givenName) {
                     $personDescription->addStatement('given-names', $givenName);
                     unset($givenName);
                 }
             }
             // Initials (will also be saved as given names)
             if (!empty($results['initials'])) {
                 $results['initials'] = str_replace(array('.', '-', ' '), array('', '', ''), $results['initials']);
                 for ($initialNum = 0; $initialNum < PKPString::strlen($results['initials']); $initialNum++) {
                     $initial = $results['initials'][$initialNum];
                     $personDescription->addStatement('given-names', $initial);
                     unset($initial);
                 }
             }
             // Surname
             if (!empty($results['surname'])) {
                 // Correct all-upper surname
                 if (strtoupper($results['surname']) == $results['surname']) {
                     $results['surname'] = ucwords(strtolower($results['surname']));
                 }
                 $personDescription->addStatement('surname', $results['surname']);
             }
             // Prefix/Suffix
             foreach (array('prefix', 'suffix') as $propertyName) {
                 if (!empty($results[$propertyName])) {
                     $results[$propertyName] = trim($results[$propertyName]);
                     $personDescription->addStatement($propertyName, $results[$propertyName]);
                 }
             }
             break;
         }
     }
     return $personDescription;
 }
Esempio n. 9
0
 /**
  * Processes form-submitted addresses for inclusion in
  * the recipient list
  * @param $currentList array Current recipient/cc/bcc list
  * @param $newAddresses array "Raw" form parameter for additional addresses
  */
 function &processAddresses($currentList, &$newAddresses)
 {
     foreach ($newAddresses as $newAddress) {
         $regs = array();
         // Match the form "My Name <*****@*****.**>"
         if (PKPString::regexp_match_get('/^([^<>' . "\n" . ']*[^<> ' . "\n" . '])[ ]*<(?P<email>' . PCRE_EMAIL_ADDRESS . ')>$/i', $newAddress, $regs)) {
             $currentList[] = array('name' => $regs[1], 'email' => $regs['email']);
         } elseif (PKPString::regexp_match_get('/^<?(?P<email>' . PCRE_EMAIL_ADDRESS . ')>?$/i', $newAddress, $regs)) {
             $currentList[] = array('name' => '', 'email' => $regs['email']);
         } elseif ($newAddress != '') {
             $this->errorMessages[] = array('type' => MAIL_ERROR_INVALID_EMAIL, 'address' => $newAddress);
         }
     }
     return $currentList;
 }
 /**
  * @copydoc Filter::process()
  * @param $input string
  * @return MetadataDescription
  */
 function &process(&$input)
 {
     $citationString =& $input;
     // Initialize the parser result array
     $matches = array();
     $metadata = array();
     // Parse out any embedded URLs
     $urlPattern = '(<?(https?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.,]*(\\?[^\\s>]+)?)?)?)>?)';
     if (PKPString::regexp_match_get($urlPattern, $citationString, $matches)) {
         // Assume that the URL is a link to the resource.
         $metadata['uri'] = $matches[1];
         // Remove the URL from the citation string
         $citationString = PKPString::regexp_replace($urlPattern, '', $citationString);
         // If the URL is a link to PubMed, save the PMID
         $pmIdExpressions = array('/list_uids=(?P<pmId>\\d+)/i', '/pubmed.*details_term=(?P<pmId>\\d+)/i', '/pubmedid=(?P<pmId>\\d+)/i');
         foreach ($pmIdExpressions as $pmIdExpression) {
             if (PKPString::regexp_match_get($pmIdExpression, $matches[1], $pmIdMatches)) {
                 $metadata['pub-id[@pub-id-type="pmid"]'] = $pmIdMatches['pmId'];
                 break;
             }
         }
     }
     // Parse out an embedded PMID and remove from the citation string
     $pmidPattern = '/pmid:?\\s*(\\d+)/i';
     if (PKPString::regexp_match_get($pmidPattern, $citationString, $matches)) {
         $metadata['pub-id[@pub-id-type="pmid"]'] = $matches[1];
         $citationString = PKPString::regexp_replace($pmidPattern, '', $citationString);
     }
     // Parse out an embedded DOI and remove it from the citation string
     $doiPattern = '/doi:?\\s*(\\S+)/i';
     if (PKPString::regexp_match_get($doiPattern, $citationString, $matches)) {
         $metadata['pub-id[@pub-id-type="doi"]'] = $matches[1];
         $citationString = PKPString::regexp_replace($doiPattern, '', $citationString);
     }
     // Parse out the access date if we have one and remove it from the citation string
     $accessDatePattern = '/accessed:?\\s*([\\s\\w]+)/i';
     if (PKPString::regexp_match_get($accessDatePattern, $citationString, $matches)) {
         $metadata['access-date'] = $matches[1];
         $citationString = PKPString::regexp_replace($accessDatePattern, '', $citationString);
     }
     // Clean out square brackets
     $citationString = PKPString::regexp_replace('/\\[(\\s*(pubmed|medline|full text)\\s*)*]/i', '', $citationString);
     // Book citation
     $unparsedTail = '';
     if (PKPString::regexp_match_get("/\\s*(?P<authors>[^\\.]+)\\.\\s*(?P<source>.*?)\\s*(?P<publisherLoc>[^\\.]*):\\s*(?P<publisherName>[^:]*?);\\s*(?P<date>\\d\\d\\d\\d.*?)(?P<tail>.*)/", $citationString, $matches)) {
         $metadata['[@publication-type]'] = NLM30_PUBLICATION_TYPE_BOOK;
         $metadata['author'] = $matches['authors'];
         $metadata['source'] = $matches['source'];
         $metadata['publisher-loc'] = $matches['publisherLoc'];
         $metadata['publisher-name'] = $matches['publisherName'];
         $metadata['date'] = $matches['date'];
         $unparsedTail = $matches['tail'];
         // Journal citation
     } elseif (PKPString::regexp_match_get("/\\s*(?P<authors>[^\\.]+)\\.\\s*(?P<titleSource>.*)\\s*(?P<date>\\d\\d\\d\\d.*?);(?P<volumeAndIssue>[^:]+):(?P<tail>.*)/", $citationString, $matches)) {
         $metadata['[@publication-type]'] = NLM30_PUBLICATION_TYPE_JOURNAL;
         $metadata['author'] = $matches['authors'];
         $titleSource = array();
         if (PKPString::regexp_match_get("/(.*[\\.!\\?])(.*)/", trim($matches['titleSource'], " ."), $titleSource)) {
             $metadata['article-title'] = $titleSource[1];
             $metadata['source'] = $titleSource[2];
         }
         $metadata['date'] = $matches['date'];
         $volumeAndIssue = array();
         if (PKPString::regexp_match_get("/([^\\(]+)(\\(([^\\)]+)\\))?/", $matches['volumeAndIssue'], $volumeAndIssue)) {
             $metadata['volume'] = $volumeAndIssue[1];
             if (isset($volumeAndIssue[3])) {
                 $metadata['issue'] = $volumeAndIssue[3];
             }
         }
         $unparsedTail = $matches['tail'];
         // Web citation with or without authors
     } elseif (PKPString::regexp_match_get("/\\s*(?P<citationSource>.*?)\\s*URL:\\s*(?P<tail>.*)/", $citationString, $matches)) {
         $unparsedTail = $matches['tail'];
         $citationParts = explode(".", trim($matches['citationSource'], '. '));
         switch (count($citationParts)) {
             case 0:
                 // This case should never occur...
                 assert(false);
                 break;
             case 1:
                 // Assume this to be a title for the web site.
                 $metadata['article-title'] = $citationParts[0];
                 break;
             case 2:
                 // Assume the format: Authors. Title.
                 $metadata['author'] = $citationParts[0];
                 $metadata['article-title'] = $citationParts[1];
                 break;
             default:
                 // Assume the format: Authors. Article Title. Journal Title.
                 $metadata['author'] = array_shift($citationParts);
                 // The last part is assumed to be the journal title
                 $metadata['source'] = array_pop($citationParts);
                 // Everything in between is assumed to belong to the article title
                 $metadata['article-title'] = implode('.', $citationParts);
         }
     }
     // TODO: Handle in-ref titles, eg. with editor lists
     // Extract page numbers if possible
     $pagesPattern = "/^[:p\\.\\s]*(?P<fpage>[Ee]?\\d+)(-(?P<lpage>\\d+))?/";
     if (!empty($unparsedTail) && PKPString::regexp_match_get($pagesPattern, $unparsedTail, $matches)) {
         $metadata['fpage'] = $matches['fpage'];
         if (isset($matches['lpage'])) {
             $metadata['lpage'] = $matches['lpage'];
         }
         // Add the unparsed part of the citation string as a comment so it doesn't get lost.
         $comment = PKPString::trimPunctuation(PKPString::regexp_replace($pagesPattern, '', $unparsedTail));
         if (!empty($comment)) {
             $metadata['comment'] = $comment;
         }
     }
     // Make the meta-data fully NLM citation compliant
     $metadata =& $this->postProcessMetadataArray($metadata);
     // Create the NLM citation description
     return $this->getNlm30CitationDescriptionFromMetadataArray($metadata);
 }
Esempio n. 11
0
 /**
  * Handle fetch requests for this plugin.
  */
 function fetch($args, $request)
 {
     if (!$this->getEnabled()) {
         return false;
     }
     $scheme = array_shift($args);
     switch ($scheme) {
         case 'doi':
             $doi = implode('/', $args);
             $journal = $request->getJournal();
             $publishedArticleDao = DAORegistry::getDAO('PublishedArticleDAO');
             /* @var $publishedArticleDao PublishedArticleDAO */
             $article = $publishedArticleDao->getPublishedArticleByPubId('doi', $doi, $journal ? $journal->getId() : null);
             if (is_a($article, 'PublishedArticle')) {
                 $request->redirect(null, 'article', 'view', $article->getBestArticleId());
             }
             break;
         case 'vnp':
             // Volume, number, page
         // Volume, number, page
         case 'ynp':
             // Volume, number, year, page
             // This can only be used from within a journal context
             $journal = $request->getJournal();
             if (!$journal) {
                 break;
             }
             if ($scheme == 'vnp') {
                 $volume = (int) array_shift($args);
                 $year = null;
             } elseif ($scheme == 'ynp') {
                 $year = (int) array_shift($args);
                 $volume = null;
             } else {
                 return;
                 // Suppress scrutinizer warn
             }
             $number = array_shift($args);
             $page = (int) array_shift($args);
             $issueDao = DAORegistry::getDAO('IssueDAO');
             $issues = $issueDao->getPublishedIssuesByNumber($journal->getId(), $volume, $number, $year);
             // Ensure only one issue matched, and fetch it.
             $issue = $issues->next();
             if (!$issue || $issues->next()) {
                 break;
             }
             unset($issues);
             $publishedArticleDao = DAORegistry::getDAO('PublishedArticleDAO');
             $articles =& $publishedArticleDao->getPublishedArticles($issue->getId());
             foreach ($articles as $article) {
                 // Look for the correct page in the list of articles.
                 $matches = null;
                 if (PKPString::regexp_match_get('/^[Pp][Pp]?[.]?[ ]?(\\d+)$/', $article->getPages(), $matches)) {
                     $matchedPage = $matches[1];
                     if ($page == $matchedPage) {
                         $request->redirect(null, 'article', 'view', $article->getBestArticleId());
                     }
                 }
                 if (PKPString::regexp_match_get('/^[Pp][Pp]?[.]?[ ]?(\\d+)[ ]?-[ ]?([Pp][Pp]?[.]?[ ]?)?(\\d+)$/', $article->getPages(), $matches)) {
                     $matchedPageFrom = $matches[1];
                     $matchedPageTo = $matches[3];
                     if ($page >= $matchedPageFrom && ($page < $matchedPageTo || $page == $matchedPageTo && ($matchedPageFrom = $matchedPageTo))) {
                         $request->redirect(null, 'article', 'view', $article->getBestArticleId());
                     }
                 }
                 unset($article);
             }
     }
     // Failure.
     header("HTTP/1.0 500 Internal Server Error");
     $templateMgr = TemplateManager::getManager($request);
     AppLocale::requireComponents(LOCALE_COMPONENT_APP_COMMON);
     $templateMgr->assign('message', 'plugins.gateways.resolver.errors.errorMessage');
     $templateMgr->display('frontend/pages/message.tpl');
     exit;
 }
 /**
  * Fills the given citation object with
  * meta-data retrieved from PubMed.
  * @param $pmid string
  * @return MetadataDescription
  */
 function &_lookup($pmid)
 {
     $nullVar = null;
     // Use eFetch to get XML metadata for the given PMID
     $lookupParams = array('db' => 'pubmed', 'mode' => 'xml', 'tool' => 'pkp-wal', 'id' => $pmid);
     if (!is_null($this->getEmail())) {
         $lookupParams['email'] = $this->getEmail();
     }
     // Call the eFetch URL and get an XML result
     if (is_null($resultDOM = $this->callWebService(PUBMED_WEBSERVICE_EFETCH, $lookupParams))) {
         return $nullVar;
     }
     $articleTitleNodes = $resultDOM->getElementsByTagName('ArticleTitle');
     $articleTitleFirstNode = $articleTitleNodes->item(0);
     $medlineTaNodes = $resultDOM->getElementsByTagName('MedlineTA');
     $medlineTaFirstNode = $medlineTaNodes->item(0);
     $metadata = array('pub-id[@pub-id-type="pmid"]' => $pmid, 'article-title' => $articleTitleFirstNode->textContent, 'source' => $medlineTaFirstNode->textContent);
     $volumeNodes = $resultDOM->getElementsByTagName('Volume');
     $issueNodes = $resultDOM->getElementsByTagName('Issue');
     if ($volumeNodes->length > 0) {
         $volumeFirstNode = $volumeNodes->item(0);
     }
     $metadata['volume'] = $volumeFirstNode->textContent;
     if ($issueNodes->length > 0) {
         $issueFirstNode = $issueNodes->item(0);
     }
     $metadata['issue'] = $issueFirstNode->textContent;
     // Get list of author full names
     foreach ($resultDOM->getElementsByTagName("Author") as $authorNode) {
         if (!isset($metadata['person-group[@person-group-type="author"]'])) {
             $metadata['person-group[@person-group-type="author"]'] = array();
         }
         // Instantiate an NLM name description
         $authorDescription = new MetadataDescription('lib.pkp.plugins.metadata.nlm30.schema.Nlm30NameSchema', ASSOC_TYPE_AUTHOR);
         // Surname
         $lastNameNodes = $authorNode->getElementsByTagName('LastName');
         $lastNameFirstNode = $lastNameNodes->item(0);
         $authorDescription->addStatement('surname', $lastNameFirstNode->textContent);
         // Given names
         $givenNamesString = '';
         $firstNameNodes = $authorNode->getElementsByTagName('FirstName');
         if ($firstNameNodes->length > 0) {
             $firstNameFirstNode = $firstNameNodes->item(0);
             $givenNamesString = $firstNameFirstNode->textContent;
         } else {
             $foreNameNodes = $authorNode->getElementsByTagName('ForeName');
             if ($foreNameNodes->length > 0) {
                 $foreNameFirstNode = $foreNameNodes->item(0);
                 $givenNamesString = $foreNameFirstNode->textContent;
             }
         }
         if (!empty($givenNamesString)) {
             foreach (explode(' ', $givenNamesString) as $givenName) {
                 $authorDescription->addStatement('given-names', PKPString::trimPunctuation($givenName));
             }
         }
         // Suffix
         $suffixNodes = $authorNode->getElementsByTagName('Suffix');
         if ($suffixNodes->length > 0) {
             $suffixFirstNode = $suffixNodes->item(0);
             $authorDescription->addStatement('suffix', $suffixFirstNode->textContent);
         }
         // Include collective names
         // FIXME: This corresponds to an NLM-citation <collab> tag and should be part of the Metadata implementation
         /*if ($resultDOM->getElementsByTagName("CollectiveName")->length > 0 && $authorNode->getElementsByTagName("CollectiveName")->item(0)->textContent != '') {
         		}*/
         $metadata['person-group[@person-group-type="author"]'][] =& $authorDescription;
         unset($authorDescription);
     }
     // Extract pagination
     $medlinePgnNodes = $resultDOM->getElementsByTagName('MedlinePgn');
     $medlinePgnFirstNode = $medlinePgnNodes->item(0);
     if (PKPString::regexp_match_get("/^[:p\\.\\s]*(?P<fpage>[Ee]?\\d+)(-(?P<lpage>\\d+))?/", $medlinePgnFirstNode->textContent, $pages)) {
         $fPage = (int) $pages['fpage'];
         $metadata['fpage'] = $fPage;
         if (!empty($pages['lpage'])) {
             $lPage = (int) $pages['lpage'];
             // Deal with shortcuts like '382-7'
             if ($lPage < $fPage) {
                 $lPage = (int) (PKPString::substr($pages['fpage'], 0, -PKPString::strlen($pages['lpage'])) . $pages['lpage']);
             }
             $metadata['lpage'] = $lPage;
         }
     }
     // Get publication date (can be in several places in PubMed).
     $dateNode = null;
     $articleDateNodes = $resultDOM->getElementsByTagName('ArticleDate');
     if ($articleDateNodes->length > 0) {
         $dateNode = $articleDateNodes->item(0);
     } else {
         $pubDateNodes = $resultDOM->getElementsByTagName('PubDate');
         if ($pubDateNodes->length > 0) {
             $dateNode = $pubDateNodes->item(0);
         }
     }
     // Retrieve the data parts and assemble date.
     if (!is_null($dateNode)) {
         $publicationDate = '';
         $requiresNormalization = false;
         foreach (array('Year' => 4, 'Month' => 2, 'Day' => 2) as $dateElement => $padding) {
             $dateElementNodes = $dateNode->getElementsByTagName($dateElement);
             if ($dateElementNodes->length > 0) {
                 if (!empty($publicationDate)) {
                     $publicationDate .= '-';
                 }
                 $dateElementFirstNode = $dateElementNodes->item(0);
                 $datePart = str_pad($dateElementFirstNode->textContent, $padding, '0', STR_PAD_LEFT);
                 if (!is_numeric($datePart)) {
                     $requiresNormalization = true;
                 }
                 $publicationDate .= $datePart;
             } else {
                 break;
             }
         }
         // Normalize the date to NLM standard if necessary.
         if ($requiresNormalization) {
             $dateFilter = new DateStringNormalizerFilter();
             $publicationDate = $dateFilter->execute($publicationDate);
         }
         if (!empty($publicationDate)) {
             $metadata['date'] = $publicationDate;
         }
     }
     // Get publication type
     $publicationTypeNodes = $resultDOM->getElementsByTagName('PublicationType');
     if ($publicationTypeNodes->length > 0) {
         foreach ($publicationTypeNodes as $publicationType) {
             // The vast majority of items on PubMed are articles so catch these...
             if (PKPString::strpos(PKPString::strtolower($publicationType->textContent), 'article') !== false) {
                 $metadata['[@publication-type]'] = NLM30_PUBLICATION_TYPE_JOURNAL;
                 break;
             }
         }
     }
     // Get DOI if it exists
     $articleIdNodes = $resultDOM->getElementsByTagName('ArticleId');
     foreach ($articleIdNodes as $idNode) {
         if ($idNode->getAttribute('IdType') == 'doi') {
             $metadata['pub-id[@pub-id-type="doi"]'] = $idNode->textContent;
         }
     }
     // Use eLink utility to find fulltext links
     $lookupParams = array('dbfrom' => 'pubmed', 'cmd' => 'llinks', 'tool' => 'pkp-wal', 'id' => $pmid);
     if (!is_null($resultDOM = $this->callWebService(PUBMED_WEBSERVICE_ELINK, $lookupParams))) {
         // Get a list of possible links
         foreach ($resultDOM->getElementsByTagName("ObjUrl") as $linkOut) {
             $attributes = '';
             foreach ($linkOut->getElementsByTagName("Attribute") as $attribute) {
                 $attributes .= PKPString::strtolower($attribute->textContent) . ' / ';
             }
             // Only add links to open access resources
             if (PKPString::strpos($attributes, "subscription") === false && PKPString::strpos($attributes, "membership") === false && PKPString::strpos($attributes, "fee") === false && $attributes != "") {
                 $urlNodes = $linkOut->getElementsByTagName('Url');
                 $urlFirstNode = $urlNodes->item(0);
                 $links[] = $urlFirstNode->textContent;
             }
         }
         // Take the first link if we have any left (presumably pubmed returns them in preferential order)
         if (isset($links[0])) {
             $metadata['uri'] = $links[0];
         }
     }
     return $this->getNlm30CitationDescriptionFromMetadataArray($metadata);
 }
/**
 * Convert a Windows path to a cygwin path.
 * @param string $path Windows path
 * @return string Cygwin path.
 */
function cygwinConversion($path)
{
    $path = str_replace('\\', '/', $path);
    $matches = null;
    PKPString::regexp_match_get('/^([A-Z]):/i', $path, $matches);
    if (isset($matches[1]) && strlen($matches[1]) === 1) {
        $path = PKPString::regexp_replace('/^[A-Z]:/i', '/cygdrive/' . strtolower($matches[1]), $path);
    }
    return $path;
}