/** * Display user login form. * Redirect to user index page if user is already validated. */ function index($args, $request) { $this->setupTemplate($request); if (Validation::isLoggedIn()) { $this->sendHome($request); } if (Config::getVar('security', 'force_login_ssl') && $request->getProtocol() != 'https') { // Force SSL connections for login $request->redirectSSL(); } $sessionManager = SessionManager::getManager(); $session = $sessionManager->getUserSession(); $templateMgr = TemplateManager::getManager($request); // If the user wasn't expecting a login page, i.e. if they're new to the // site and want to submit a paper, it helps to explain why they need to // register. if ($request->getUserVar('loginMessage')) { $templateMgr->assign('loginMessage', $request->getUserVar('loginMessage')); } $templateMgr->assign('username', $session->getSessionVar('username')); $templateMgr->assign('remember', $request->getUserVar('remember')); $templateMgr->assign('source', $request->getUserVar('source')); $templateMgr->assign('showRemember', Config::getVar('general', 'session_lifetime') > 0); // For force_login_ssl with base_url[...]: make sure SSL used for login form $loginUrl = $this->_getLoginUrl($request); if (Config::getVar('security', 'force_login_ssl')) { $loginUrl = PKPString::regexp_replace('/^http:/', 'https:', $loginUrl); } $templateMgr->assign('loginUrl', $loginUrl); $templateMgr->display('frontend/pages/userLogin.tpl'); }
/** * Generate a filename for a library file. * @param $type int LIBRARY_FILE_TYPE_... * @param $originalFileName string * @return string */ function generateFileName($type, $originalFileName) { $libraryFileDao = DAORegistry::getDAO('LibraryFileDAO'); $suffix = $this->getFileSuffixFromType($type); $ext = $this->getExtension($originalFileName); $truncated = $this->truncateFileName($originalFileName, 127 - PKPString::strlen($suffix) - 1); $baseName = PKPString::substr($truncated, 0, PKPString::strpos($originalFileName, $ext) - 1); // Try a simple syntax first $fileName = $baseName . '-' . $suffix . '.' . $ext; if (!$libraryFileDao->filenameExists($this->contextId, $fileName)) { return $fileName; } for ($i = 1;; $i++) { $fullSuffix = $suffix . '-' . $i; //truncate more if necessary $truncated = $this->truncateFileName($originalFileName, 127 - PKPString::strlen($fullSuffix) - 1); // get the base name and append the suffix $baseName = PKPString::substr($truncated, 0, PKPString::strpos($originalFileName, $ext) - 1); //try the following $fileName = $baseName . '-' . $fullSuffix . '.' . $ext; if (!$libraryFileDao->filenameExists($this->contextId, $fileName)) { return $fileName; } } }
/** * Format XML for single DC element. * @param $propertyName string * @param $value array * @param $multilingual boolean optional */ function formatElement($propertyName, $values, $multilingual = false) { if (!is_array($values)) { $values = array($values); } // Translate the property name to XML syntax. $openingElement = str_replace(array('[@', ']'), array(' ', ''), $propertyName); $closingElement = PKPString::regexp_replace('/\\[@.*/', '', $propertyName); // Create the actual XML entry. $response = ''; foreach ($values as $key => $value) { if ($multilingual) { $key = str_replace('_', '-', $key); assert(is_array($value)); foreach ($value as $subValue) { if ($key == METADATA_DESCRIPTION_UNKNOWN_LOCALE) { $response .= "\t<{$openingElement}>" . OAIUtils::prepOutput($subValue) . "</{$closingElement}>\n"; } else { $response .= "\t<{$openingElement} xml:lang=\"{$key}\">" . OAIUtils::prepOutput($subValue) . "</{$closingElement}>\n"; } } } else { assert(is_scalar($value)); $response .= "\t<{$openingElement}>" . OAIUtils::prepOutput($value) . "</{$closingElement}>\n"; } } return $response; }
/** * Split a string into a clean array of keywords * @param $text string * @param $allowWildcards boolean * @return array of keywords */ static function filterKeywords($text, $allowWildcards = false) { $minLength = Config::getVar('search', 'min_word_length'); $stopwords = self::_loadStopwords(); // Join multiple lines into a single string if (is_array($text)) { $text = join("\n", $text); } $cleanText = Core::cleanVar($text); // Remove punctuation $cleanText = PKPString::regexp_replace('/[!"\\#\\$%\'\\(\\)\\.\\?@\\[\\]\\^`\\{\\}~]/', '', $cleanText); $cleanText = PKPString::regexp_replace('/[\\+,:;&\\/<=>\\|\\\\]/', ' ', $cleanText); $cleanText = PKPString::regexp_replace('/[\\*]/', $allowWildcards ? '%' : ' ', $cleanText); $cleanText = PKPString::strtolower($cleanText); // Split into words $words = PKPString::regexp_split('/\\s+/', $cleanText); // FIXME Do not perform further filtering for some fields, e.g., author names? // Remove stopwords $keywords = array(); foreach ($words as $k) { if (!isset($stopwords[$k]) && PKPString::strlen($k) >= $minLength && !is_numeric($k)) { $keywords[] = PKPString::substr($k, 0, SEARCH_KEYWORD_MAX_LENGTH); } } return $keywords; }
/** * @see TypeDescription::parseTypeName() */ function parseTypeName($typeName) { // Standard validators are based on string input. parent::parseTypeName('string'); // Split the type name into validator name and arguments. $typeNameParts = explode('(', $typeName, 2); switch (count($typeNameParts)) { case 1: // no argument $this->_validatorArgs = ''; break; case 2: // parse arguments (no UTF8-treatment necessary) if (substr($typeNameParts[1], -1) != ')') { return false; } // FIXME: Escape for PHP code inclusion? $this->_validatorArgs = substr($typeNameParts[1], 0, -1); break; } // Validator name must start with a lower case letter // and may contain only alphanumeric letters. if (!PKPString::regexp_match('/^[a-z][a-zA-Z0-9]+$/', $typeNameParts[0])) { return false; } // Translate the validator name into a validator class name. $this->_validatorClassName = 'Validator' . PKPString::ucfirst($typeNameParts[0]); return true; }
/** * @copydoc Filter::process() * @param $citationString string * @return MetadataDescription */ function &process(&$input) { $nullVar = null; $queryParams = array('demo' => '3', 'textlines' => $input); // Parscit web form - the result is (mal-formed) HTML if (is_null($result = $this->callWebService(PARSCIT_WEBSERVICE, $queryParams, XSL_TRANSFORMER_DOCTYPE_STRING, 'POST'))) { return $nullVar; } $result = html_entity_decode($result); // Detect errors. if (!PKPString::regexp_match('/.*<algorithm[^>]+>.*<\\/algorithm>.*/s', $result)) { $translationParams = array('filterName' => $this->getDisplayName()); $this->addError(__('submission.citations.filter.webserviceResultTransformationError', $translationParams)); return $nullVar; } // Screen-scrape the tagged portion and turn it into XML. $xmlResult = PKPString::regexp_replace('/.*<algorithm[^>]+>(.*)<\\/algorithm>.*/s', '\\1', $result); $xmlResult = PKPString::regexp_replace('/&/', '&', $xmlResult); // Transform the result into an array of meta-data. if (is_null($metadata = $this->transformWebServiceResults($xmlResult, dirname(__FILE__) . DIRECTORY_SEPARATOR . 'parscit.xsl'))) { return $nullVar; } // Extract a publisher from the place string if possible. $metadata =& $this->fixPublisherNameAndLocation($metadata); return $this->getNlm30CitationDescriptionFromMetadataArray($metadata); }
/** * @copydoc Form::display */ function display($request = null, $template = null) { import('lib.pkp.classes.xslt.XSLTransformer'); $templateMgr = TemplateManager::getManager($request); $templateMgr->assign(array('localeOptions' => $this->supportedLocales, 'localesComplete' => $this->localesComplete, 'clientCharsetOptions' => $this->supportedClientCharsets, 'connectionCharsetOptions' => $this->supportedConnectionCharsets, 'databaseCharsetOptions' => $this->supportedDatabaseCharsets, 'allowFileUploads' => get_cfg_var('file_uploads') ? __('common.yes') : __('common.no'), 'maxFileUploadSize' => get_cfg_var('upload_max_filesize'), 'databaseDriverOptions' => $this->checkDBDrivers(), 'supportsMBString' => PKPString::hasMBString() ? __('common.yes') : __('common.no'), 'phpIsSupportedVersion' => version_compare(PHP_REQUIRED_VERSION, PHP_VERSION) != 1, 'xslEnabled' => XSLTransformer::checkSupport(), 'xslRequired' => REQUIRES_XSL, 'phpRequiredVersion' => PHP_REQUIRED_VERSION, 'phpVersion' => PHP_VERSION)); parent::display(); }
/** * Assign parameters to template * @param $paramArray array */ function assignParams($paramArray = array()) { $submission = $this->submission; $application = PKPApplication::getApplication(); $request = $application->getRequest(); parent::assignParams(array_merge(array('submissionTitle' => strip_tags($submission->getLocalizedTitle()), 'submissionId' => $submission->getId(), 'submissionAbstract' => PKPString::html2text($submission->getLocalizedAbstract()), 'authorString' => strip_tags($submission->getAuthorString())), $paramArray)); }
/** * @copydoc Filter::process() * @param $isbn string * @return MetadataDescription a looked up citation description * or null if the filter fails */ function &process($isbn) { $nullVar = null; // Instantiate the web service request $lookupParams = array('access_key' => $this->getApiKey(), 'index1' => 'isbn', 'results' => 'details,authors', 'value1' => $isbn); // Call the web service if (is_null($resultDOM =& $this->callWebService(ISBNDB_WEBSERVICE_URL, $lookupParams))) { return $nullVar; } // Transform and pre-process the web service result if (is_null($metadata =& $this->transformWebServiceResults($resultDOM, dirname(__FILE__) . DIRECTORY_SEPARATOR . 'isbndb.xsl'))) { return $nullVar; } // Extract place and publisher from the combined entry. $metadata['publisher-loc'] = PKPString::trimPunctuation(PKPString::regexp_replace('/^(.+):.*/', '\\1', $metadata['place-publisher'])); $metadata['publisher-name'] = PKPString::trimPunctuation(PKPString::regexp_replace('/.*:([^,]+),?.*/', '\\1', $metadata['place-publisher'])); unset($metadata['place-publisher']); // Reformat the publication date $metadata['date'] = PKPString::regexp_replace('/^[^\\d{4}]+(\\d{4}).*/', '\\1', $metadata['date']); // Clean non-numerics from ISBN $metadata['isbn'] = PKPString::regexp_replace('/[^\\dX]*/', '', $isbn); // Set the publicationType $metadata['[@publication-type]'] = NLM30_PUBLICATION_TYPE_BOOK; return $this->getNlm30CitationDescriptionFromMetadataArray($metadata); }
/** * Get the chapter full title (with title and subtitle). * @return string */ function getLocalizedFullTitle() { $fullTitle = $this->getLocalizedTitle(); if ($subtitle = $this->getLocalizedSubtitle()) { $fullTitle = PKPString::concatTitleFields(array($fullTitle, $subtitle)); } return $fullTitle; }
/** * Query parsing helper routine. * Returned structure is based on that used by the Search::QueryParser Perl module. */ function _parseQueryInternal($signTokens, $tokens, &$pos, $total) { $return = array('+' => array(), '' => array(), '-' => array()); $postBool = $preBool = ''; $submissionSearchIndex = new SubmissionSearchIndex(); $notOperator = PKPString::strtolower(__('search.operator.not')); $andOperator = PKPString::strtolower(__('search.operator.and')); $orOperator = PKPString::strtolower(__('search.operator.or')); while ($pos < $total) { if (!empty($signTokens[$pos])) { $sign = $signTokens[$pos]; } else { if (empty($sign)) { $sign = '+'; } } $token = PKPString::strtolower($tokens[$pos++]); switch ($token) { case $notOperator: $sign = '-'; break; case ')': return $return; case '(': $token = $this->_parseQueryInternal($signTokens, $tokens, $pos, $total); default: $postBool = ''; if ($pos < $total) { $peek = PKPString::strtolower($tokens[$pos]); if ($peek == $orOperator) { $postBool = 'or'; $pos++; } else { if ($peek == $andOperator) { $postBool = 'and'; $pos++; } } } $bool = empty($postBool) ? $preBool : $postBool; $preBool = $postBool; if ($bool == 'or') { $sign = ''; } if (is_array($token)) { $k = $token; } else { $k = $submissionSearchIndex->filterKeywords($token, true); } if (!empty($k)) { $return[$sign][] = $k; } $sign = ''; break; } } return $return; }
/** * @see OAIMetadataFormat#toXml */ function toXml(&$record, $format = null) { $article = $record->getData('article'); $journal = $record->getData('journal'); $templateMgr = TemplateManager::getManager(); $templateMgr->assign(array('journal' => $journal, 'article' => $article, 'issue' => $record->getData('issue'), 'section' => $record->getData('section'))); $subjects = array_merge_recursive($this->stripAssocArray((array) $article->getDiscipline(null)), $this->stripAssocArray((array) $article->getSubject(null))); $templateMgr->assign(array('subject' => isset($subjects[$journal->getPrimaryLocale()]) ? $subjects[$journal->getPrimaryLocale()] : '', 'abstract' => PKPString::html2text($article->getAbstract($article->getLocale())), 'language' => AppLocale::get3LetterIsoFromLocale($article->getLocale()))); return $templateMgr->fetch(dirname(__FILE__) . '/record.tpl'); }
/** * 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; }
/** * Get the series full title (with title and subtitle). * @return string */ function getLocalizedFullTitle() { $fullTitle = null; if ($prefix = $this->getLocalizedPrefix()) { $fullTitle = $prefix . ' '; } $fullTitle .= $this->getLocalizedTitle(); if ($subtitle = $this->getLocalizedSubtitle()) { $fullTitle = PKPString::concatTitleFields(array($fullTitle, $subtitle)); } return $fullTitle; }
/** * Extracts variables for a given column from a data element * so that they may be assigned to template before rendering. * @param $row GridRow * @param $column GridColumn * @return array */ function getTemplateVarsFromRowColumn($row, $column) { $element =& $row->getData(); $columnId = $column->getId(); assert(!empty($columnId)); switch ($columnId) { case 'url': return array('label' => '<a href="' . PKPString::stripUnsafeHtml($element['url']) . '" target="_blank">' . PKPString::stripUnsafeHtml($element['url']) . '</a>'); case 'shares': return array('label' => $element['shares']); } }
/** * Get a set of GalleryPlugin objects describing the available * compatible plugins in their newest versions. * @param $application PKPApplication * @param $category string Optional category name to use as filter * @param $search string Optional text to use as filter * @return array GalleryPlugin objects */ function getNewestCompatible($application, $category = null, $search = null) { $doc = $this->_getDocument(); $plugins = array(); foreach ($doc->getElementsByTagName('plugin') as $element) { $plugin = $this->_compatibleFromElement($element, $application); // May be null if no compatible version exists; also // apply search filters if any supplied. if ($plugin && ($category == '' || $plugin->getCategory() == $category) && ($search == '' || PKPString::strpos(PKPString::strtolower(serialize($plugin)), PKPString::strtolower($search)) !== false)) { $plugins[] = $plugin; } } return $plugins; }
/** * 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; }
/** * Get cell actions associated with this row/column combination * @param $row GridRow * @param $column GridColumn * @return array an array of LinkAction instances */ function getCellActions($request, $row, $column, $position = GRID_ACTION_POSITION_DEFAULT) { assert($column->getId() == 'task'); $templateMgr = TemplateManager::getManager($request); $notification = $row->getData(); $contextDao = Application::getContextDAO(); $context = $contextDao->getById($notification->getContextId()); $notificationMgr = new NotificationManager(); $router = $request->getRouter(); $templateMgr->assign(array('notificationMgr' => $notificationMgr, 'notification' => $notification, 'context' => $context, 'notificationObjectTitle' => $this->_getTitle($notification), 'message' => PKPString::stripUnsafeHtml($notificationMgr->getNotificationMessage($request, $notification)))); // See if we're working in a multi-context environment $user = $request->getUser(); $contextDao = Application::getContextDAO(); $contexts = $contextDao->getAvailable($user ? $user->getId() : null)->toArray(); $templateMgr->assign('isMultiContext', count($contexts) > 1); return array(new LinkAction('details', new AjaxAction($router->url($request, null, null, 'markRead', null, array('redirect' => 1, 'selectedElements' => array($notification->getId())))), $templateMgr->fetch('controllers/grid/tasks/task.tpl'))); }
/** * Display the form. */ function display() { $templateMgr = TemplateManager::getManager($this->_request); $templateMgr->assign('localeOptions', $this->supportedLocales); $templateMgr->assign('localesComplete', $this->localesComplete); $templateMgr->assign('clientCharsetOptions', $this->supportedClientCharsets); $templateMgr->assign('connectionCharsetOptions', $this->supportedConnectionCharsets); $templateMgr->assign('databaseCharsetOptions', $this->supportedDatabaseCharsets); $templateMgr->assign('allowFileUploads', get_cfg_var('file_uploads') ? __('common.yes') : __('common.no')); $templateMgr->assign('maxFileUploadSize', get_cfg_var('upload_max_filesize')); $templateMgr->assign('databaseDriverOptions', $this->checkDBDrivers()); $templateMgr->assign('supportsMBString', PKPString::hasMBString() ? __('common.yes') : __('common.no')); $templateMgr->assign('phpIsSupportedVersion', version_compare(PHP_REQUIRED_VERSION, PHP_VERSION) != 1); import('lib.pkp.classes.xslt.XSLTransformer'); $templateMgr->assign('xslEnabled', XSLTransformer::checkSupport()); $templateMgr->assign('xslRequired', REQUIRES_XSL); $templateMgr->assign('phpRequiredVersion', PHP_REQUIRED_VERSION); $templateMgr->assign('phpVersion', PHP_VERSION); parent::display(); }
/** * @see Filter::process() * @param $input string * @return mixed array */ function &process(&$input) { // The default implementation assumes that raw citations are // separated with line endings. // 1) Remove empty lines and normalize line endings. $input = PKPString::regexp_replace('/[\\r\\n]+/s', "\n", $input); // 2) Remove trailing/leading line breaks. $input = trim($input, "\n"); // 3) Break up at line endings. if (empty($input)) { $citations = array(); } else { $citations = explode("\n", $input); } // 4) Remove numbers from the beginning of each citation. foreach ($citations as $index => $citation) { $citations[$index] = PKPString::regexp_replace('/^\\s*[\\[#]?[0-9]+[.)\\]]?\\s*/', '', $citation); } return $citations; }
/** * @copydoc NotificationManagerDelegate::getNotificationMessage() */ public function getNotificationMessage($request, $notification) { assert($notification->getAssocType() == ASSOC_TYPE_QUERY); $queryDao = DAORegistry::getDAO('QueryDAO'); $query = $queryDao->getById($notification->getAssocId()); $headNote = $query->getHeadNote(); assert($headNote); switch ($notification->getType()) { case NOTIFICATION_TYPE_NEW_QUERY: $user = $headNote->getUser(); return __('submission.query.new', array('creatorName' => $user->getFullName(), 'noteContents' => substr(PKPString::html2text($headNote->getContents()), 0, 200), 'noteTitle' => substr($headNote->getTitle(), 0, 200))); case NOTIFICATION_TYPE_QUERY_ACTIVITY: $notes = $query->getReplies(null, NOTE_ORDER_ID, SORT_DIRECTION_DESC); $latestNote = $notes->next(); $user = $latestNote->getUser(); $notes->close(); return __('submission.query.activity', array('responderName' => $user->getFullName(), 'noteContents' => substr(PKPString::html2text($latestNote->getContents()), 0, 200), 'noteTitle' => substr($headNote->getTitle(), 0, 200))); default: assert(false); } }
/** * @covers PKPString::diff */ public function testDiff() { // Test two strings that have common substrings. $originalString = 'The original string.'; $editedString = 'The edited original.'; $expectedDiff = array(array(0 => 'The'), array(1 => ' edited'), array(0 => ' original'), array(-1 => ' string'), array(0 => '.')); $resultDiff = PKPString::diff($originalString, $editedString); self::assertEquals($expectedDiff, $resultDiff); // Test two completely different strings. $originalString = 'abc'; $editedString = 'def'; $expectedDiff = array(array(-1 => 'abc'), array(1 => 'def')); $resultDiff = PKPString::diff($originalString, $editedString); self::assertEquals($expectedDiff, $resultDiff); // A more realistic example from the citation editor use case $originalString = 'Willinsky, B. (2006). The access principle: The case for open acces to research and scholarship. Cambridge, MA: MIT Press.'; $editedString = 'Willinsky, J. (2006). The access principle: The case for open access to research and scholarship. Cambridge, MA: MIT Press.'; $expectedDiff = array(array(0 => 'Willinsky, '), array(-1 => 'B'), array(1 => 'J'), array(0 => '. (2006). The access principle: The case for open acce'), array(1 => 's'), array(0 => 's to research and scholarship. Cambridge, MA: MIT Press.')); $resultDiff = PKPString::diff($originalString, $editedString); self::assertEquals($expectedDiff, $resultDiff); }
/** * Retrieve all published authors for a press in an associative array by * the first letter of the last name, for example: * $returnedArray['S'] gives array($misterSmithObject, $misterSmytheObject, ...) * Keys will appear in sorted order. Note that if pressId is null, * alphabetized authors for all presses are returned. * @param $pressId int * @param $initial An initial the last names must begin with * @return array Authors ordered by sequence */ function getAuthorsAlphabetizedByPress($pressId = null, $initial = null, $rangeInfo = null) { $params = array('affiliation', AppLocale::getPrimaryLocale(), 'affiliation', AppLocale::getLocale()); if (isset($pressId)) { $params[] = $pressId; } if (isset($initial)) { $params[] = PKPString::strtolower($initial) . '%'; $initialSql = ' AND LOWER(a.last_name) LIKE LOWER(?)'; } else { $initialSql = ''; } $result = $this->retrieveRange('SELECT DISTINCT CAST(\'\' AS CHAR) AS url, a.author_id AS author_id, a.submission_id AS submission_id, CAST(\'\' AS CHAR) AS email, 0 AS primary_contact, 0 AS seq, a.first_name AS first_name, a.middle_name AS middle_name, a.last_name AS last_name, asl.setting_value AS affiliation_l, asl.locale, aspl.setting_value AS affiliation_pl, aspl.locale AS primary_locale, a.suffix AS suffix, a.user_group_id AS user_group_id, a.include_in_browse AS include_in_browse, 0 AS show_title, a.country FROM authors a LEFT JOIN author_settings aspl ON (a.author_id = aspl.author_id AND aspl.setting_name = ? AND aspl.locale = ?) LEFT JOIN author_settings asl ON (a.author_id = asl.author_id AND asl.setting_name = ? AND asl.locale = ?) JOIN submissions s ON (a.submission_id = s.submission_id) WHERE s.status = ' . STATUS_PUBLISHED . ' ' . (isset($pressId) ? 'AND s.context_id = ? ' : '') . ' AND (a.last_name IS NOT NULL AND a.last_name <> \'\')' . $initialSql . ' ORDER BY a.last_name, a.first_name', $params, $rangeInfo); return new DAOResultFactory($result, $this, '_fromRow'); }
/** * Display user login form. * Redirect to user index page if user is already validated. */ function index($args, $request) { $this->setupTemplate($request); if (Validation::isLoggedIn()) { $this->sendHome($request); } if (Config::getVar('security', 'force_login_ssl') && $request->getProtocol() != 'https') { // Force SSL connections for login $request->redirectSSL(); } $sessionManager = SessionManager::getManager(); $session = $sessionManager->getUserSession(); $templateMgr = TemplateManager::getManager($request); $templateMgr->assign(array('loginMessage' => $request->getUserVar('loginMessage'), 'username' => $session->getSessionVar('username'), 'remember' => $request->getUserVar('remember'), 'source' => $request->getUserVar('source'), 'showRemember' => Config::getVar('general', 'session_lifetime') > 0)); // For force_login_ssl with base_url[...]: make sure SSL used for login form $loginUrl = $this->_getLoginUrl($request); if (Config::getVar('security', 'force_login_ssl')) { $loginUrl = PKPString::regexp_replace('/^http:/', 'https:', $loginUrl); } $templateMgr->assign('loginUrl', $loginUrl); $templateMgr->display('frontend/pages/userLogin.tpl'); }
/** * @see FormValidator::isValid() * Value is valid if it is empty and optional or meets the specified length requirements. * @return boolean */ function isValid() { if ($this->isEmptyAndOptional()) { return true; } else { $length = PKPString::strlen($this->getFieldValue()); switch ($this->_comparator) { case '==': return $length == $this->_length; case '!=': return $length != $this->_length; case '<': return $length < $this->_length; case '>': return $length > $this->_length; case '<=': return $length <= $this->_length; case '>=': return $length >= $this->_length; } return false; } }
/** * 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; }
/** * @verbatim * Helper method that configures and optionally * installs a filter based on the given XML node * which represents a <filter> element. * @endverbatim * @param $filterNode XMLNode * @param $persist boolean whether to install the filter * @return PersistableFilter the installed filter. */ function &configureFilter($filterNode, $persist = true) { // Install filters. $filterDao = DAORegistry::getDAO('FilterDAO'); /* @var $filterDao FilterDAO */ $filterGroupSymbolic = $filterNode->getAttribute('inGroup'); $filterClassName = $filterNode->getAttribute('class'); $isTemplate = $filterNode->getAttribute('isTemplate'); // We have to include the filter class before going on // so that all required constants are defined before they // might be used in settings. if (PKPString::regexp_match('/^[a-zA-Z0-9.]+$/', $filterClassName)) { import($filterClassName); } // Go through the filter sub-nodes. This can be nested // filters or filter settings. $subNodes = $filterNode->getChildren(); $settings = array(); $subFilters = array(); foreach ($subNodes as $subNode) { /* @var $subNode XMLNode */ switch ($subNode->getName()) { case 'setting': // Get the filter setting. list($name, $value) = $this->getFilterSetting($subNode); $settings[$name] = $value; unset($name, $value); break; case 'filter': // Recursively configure sub-filters. $subFilter =& $this->configureFilter($subNode, false); $subFilters[] =& $subFilter; unset($subFilter); break; } } // We ensure idempotence of plug-in installation by checking // for existing identical filters. $similarFilterFactory =& $filterDao->getObjectsByGroupAndClass($filterGroupSymbolic, $filterClassName, 0, $isTemplate); if ($similarFilterFactory->getCount() > 0) { // 1) Find similar filters. $similarFilters =& $similarFilterFactory->toArray(); // 2) Go through similar filters and eliminate them // if they don't have the exact same settings. foreach ($similarFilters as $index => $similarFilter) { /* @var $similarFilter PersistableFilter */ if (!$this->compareFilters($similarFilter, $settings, $subFilters)) { unset($similarFilters[$index]); } } // There can be a maximum of exactly one identical transformation // in the database otherwise we've somehow installed a duplicate filter. $identicalFilters = count($similarFilters); assert($identicalFilters <= 1); // 3) If the filter has been installed before then return the existing filter. if ($identicalFilters) { $existingFilter = array_pop($similarFilters); return $existingFilter; } } // Configure (and optionally install) the filter. $installedFilter = $filterDao->configureObject($filterClassName, $filterGroupSymbolic, $settings, $isTemplate, 0, $subFilters, $persist); assert(is_a($installedFilter, 'PersistableFilter')); return $installedFilter; }
/** * @see Validator::isValid() * @param $value mixed * @return boolean */ function isValid($value) { return (bool) PKPString::regexp_match_get($this->_regExp, $value, $this->_matches); }
/** * Retrieve all published authors for a journal in an associative array by * the first letter of the last name, for example: * $returnedArray['S'] gives array($misterSmithObject, $misterSmytheObject, ...) * Keys will appear in sorted order. Note that if journalId is null, * alphabetized authors for all enabled journals are returned. * @param $journalId int Optional journal ID to restrict results to * @param $initial An initial the last names must begin with * @param $rangeInfo Range information * @param $includeEmail Whether or not to include the email in the select distinct * @return DAOResultFactory Authors ordered by sequence */ function getAuthorsAlphabetizedByJournal($journalId = null, $initial = null, $rangeInfo = null, $includeEmail = false) { $params = array('affiliation', AppLocale::getPrimaryLocale(), 'affiliation', AppLocale::getLocale()); if (isset($journalId)) { $params[] = $journalId; } if (isset($initial)) { $params[] = PKPString::strtolower($initial) . '%'; $initialSql = ' AND LOWER(aa.last_name) LIKE LOWER(?)'; } else { $initialSql = ''; } $result = $this->retrieveRange('SELECT DISTINCT CAST(\'\' AS CHAR) AS url, 0 AS author_id, 0 AS submission_id, ' . ($includeEmail ? 'aa.email AS email,' : 'CAST(\'\' AS CHAR) AS email,') . ' 0 AS primary_contact, 0 AS seq, aa.first_name, aa.middle_name, aa.last_name, SUBSTRING(asl.setting_value FROM 1 FOR 255) AS affiliation_l, asl.locale, SUBSTRING(aspl.setting_value FROM 1 FOR 255) AS affiliation_pl, aspl.locale AS primary_locale, aa.country FROM authors aa LEFT JOIN author_settings aspl ON (aa.author_id = aspl.author_id AND aspl.setting_name = ? AND aspl.locale = ?) LEFT JOIN author_settings asl ON (aa.author_id = asl.author_id AND asl.setting_name = ? AND asl.locale = ?) JOIN submissions a ON (a.submission_id = aa.submission_id AND a.status = ' . STATUS_PUBLISHED . ') JOIN journals j ON (a.context_id = j.journal_id) JOIN published_submissions pa ON (pa.submission_id = a.submission_id) JOIN issues i ON (pa.issue_id = i.issue_id AND i.published = 1) WHERE ' . (isset($journalId) ? 'j.journal_id = ?' : 'j.enabled = 1') . ' AND (aa.last_name IS NOT NULL AND aa.last_name <> \'\')' . $initialSql . ' ORDER BY aa.last_name, aa.first_name', $params, $rangeInfo); return new DAOResultFactory($result, $this, '_returnSimpleAuthorFromRow'); }
/** * @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; }