/** * Generate and display the CAPTCHA image. * @param $captcha object Captcha */ function generateImage(&$captcha) { $width = $this->getWidth(); $height = $this->getHeight(); $length = String::strlen($captcha->getValue()); $value = $captcha->getValue(); $image = imagecreatetruecolor($width, $height); $fg = imagecolorallocate($image, rand(128, 255), rand(128, 255), rand(128, 255)); $bg = imagecolorallocate($image, rand(0, 64), rand(0, 64), rand(0, 64)); imagefill($image, $width / 2, $height / 2, $bg); $xStart = rand($width / 12, $width / 3); $xEnd = rand($width * 2 / 3, $width * 11 / 12); for ($i = 0; $i < $length; $i++) { imagefttext($image, rand(20, 34), rand(-15, 15), $xStart + ($xEnd - $xStart) * $i / $length + rand(-5, 5), rand(40, 60), $fg, Config::getVar('captcha', 'font_location'), String::substr($value, $i, 1)); } // Add some noise to the image. for ($i = 0; $i < 20; $i++) { $color = imagecolorallocate($image, rand(0, 255), rand(0, 255), rand(0, 255)); for ($j = 0; $j < 20; $j++) { imagesetpixel($image, rand(0, $this->getWidth()), rand(0, $this->getHeight()), $color); } } header('Content-type: ' . $this->getMimeType()); imagepng($image); imagedestroy($image); }
/** * 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 = String::regexp_replace('/[!"\\#\\$%\'\\(\\)\\.\\?@\\[\\]\\^`\\{\\}~]/', '', $cleanText); $cleanText = String::regexp_replace('/[\\+,:;&\\/<=>\\|\\\\]/', ' ', $cleanText); $cleanText = String::regexp_replace('/[\\*]/', $allowWildcards ? '%' : ' ', $cleanText); $cleanText = String::strtolower($cleanText); // Split into words $words = String::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]) && String::strlen($k) >= $minLength && !is_numeric($k)) { $keywords[] = String::substr($k, 0, SEARCH_KEYWORD_MAX_LENGTH); } } return $keywords; }
/** * 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 - String::strlen($suffix) - 1); $baseName = String::substr($truncated, 0, String::strpos($originalFileName, $ext) - 1); // Try a simple syntax first $fileName = $baseName . '-' . $suffix . '.' . $ext; if (!$libraryFileDao->filenameExists($this->pressId, $fileName)) { return $fileName; } for ($i = 1;; $i++) { $fullSuffix = $suffix . '-' . $i; //truncate more if necessary $truncated = $this->truncateFileName($originalFileName, 127 - String::strlen($fullSuffix) - 1); // get the base name and append the suffix $baseName = String::substr($truncated, 0, String::strpos($originalFileName, $ext) - 1); //try the following $fileName = $baseName . '-' . $fullSuffix . '.' . $ext; if (!$libraryFileDao->filenameExists($this->pressId, $fileName)) { return $fileName; } } }
/** * @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 = String::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; } }
/** * Check if field value is valid. * 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 = String::strlen(trim($this->form->getData($this->field))); 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; } }
/** * Truncate a filename to fit in the specified length. */ function truncateFileName($fileName, $length = 127) { if (String::strlen($fileName) <= $length) { return $fileName; } $ext = $this->getExtension($fileName); $truncated = String::substr($fileName, 0, $length - 1 - String::strlen($ext)) . '.' . $ext; return String::substr($truncated, 0, $length); }
/** * 格式化字段 * * @access private * @param mixed $typeInfo * @param mixed $value * @return mixed */ private function formatField($typeInfo, $value) { preg_match("/(\\w+)(\\((\\d+)\\))?/", $typeInfo, $matches); if (isset($matches[1])) { $type = $matches[1]; } if (isset($matches[3])) { $len = $matches[3]; } $_type = "string"; $type = strtolower($type); switch ($type) { case 'bit': case 'bigbit': case 'bool': case 'boolean': case 'decimal': case 'decimal': case 'dec': case 'double': case 'float': case 'int': case 'bigint': case 'mediumint': case 'smallint': case 'tinyint': case 'real': if (!is_numeric($value)) { $value = 0; } if ($value == '' || $value == null || empty($value)) { $value = 0; } $_type = 'numeric'; break; } if (isset($len)) { if (!is_array($value) && String::strlen($value) > $len) { $value = String::msubstr($value, 0, $len, 'utf-8', ''); } } if (is_array($value)) { $value = serialize($value); } if ($_type == 'string') { $value = '\'' . $value . '\''; } return $value; }
/** * Calculate the differences between two strings and * produce an array with three types of entries: added * substrings, deleted substrings and unchanged substrings. * * The calculation is optimized to identify the common * largest substring. * * The return value is an array of the following format: * * array( * array( diff-type => substring ), * array(...) * ) * * whereby diff-type can be one of: * -1 = deletion * 0 = common substring * 1 = addition * * @param $originalString string * @param $editedString string * @return array */ static function diff($originalString, $editedString) { // Split strings into character arrays (multi-byte compatible). foreach (array('originalStringCharacters' => $originalString, 'editedStringCharacters' => $editedString) as $characterArrayName => $string) { ${$characterArrayName} = array(); String::regexp_match_all('/./', $string, ${$characterArrayName}); if (isset(${$characterArrayName}[0])) { ${$characterArrayName} = ${$characterArrayName}[0]; } } // Determine the length of the strings. $originalStringLength = count($originalStringCharacters); $editedStringLength = count($editedStringCharacters); // Is there anything to compare? if ($originalStringLength == 0 && $editedStringLength == 0) { return array(); } // Is the original string empty? if ($originalStringLength == 0) { // Return the edited string as addition. return array(array(1 => $editedString)); } // Is the edited string empty? if ($editedStringLength == 0) { // Return the original string as deletion. return array(array(-1 => $originalString)); } // Initialize the local indices: // 1) Create a character index for the edited string. $characterIndex = array(); for ($characterPosition = 0; $characterPosition < $editedStringLength; $characterPosition++) { $characterIndex[$editedStringCharacters[$characterPosition]][] = $characterPosition; } // 2) Initialize the substring and the length index. $substringIndex = $lengthIndex = array(); // Iterate over the original string to identify // the largest common string. for ($originalPosition = 0; $originalPosition < $originalStringLength; $originalPosition++) { // Find all occurrences of the original character // in the target string. $comparedCharacter = $originalStringCharacters[$originalPosition]; // Do we have a commonality between the original string // and the edited string? if (isset($characterIndex[$comparedCharacter])) { // Loop over all commonalities. foreach ($characterIndex[$comparedCharacter] as $editedPosition) { // Calculate the current and the preceding position // ids for indexation. $currentPosition = $originalPosition . '-' . $editedPosition; $previousPosition = $originalPosition - 1 . '-' . ($editedPosition - 1); // Does the occurrence in the target string continue // an existing common substring or does it start // a new one? if (isset($substringIndex[$previousPosition])) { // This is a continuation of an existing common // substring... $newSubstring = $substringIndex[$previousPosition] . $comparedCharacter; $newSubstringLength = String::strlen($newSubstring); // Move the substring in the substring index. $substringIndex[$currentPosition] = $newSubstring; unset($substringIndex[$previousPosition]); // Move the substring in the length index. $lengthIndex[$newSubstringLength][$currentPosition] = $newSubstring; unset($lengthIndex[$newSubstringLength - 1][$previousPosition]); } else { // Start a new common substring... // Add the substring to the substring index. $substringIndex[$currentPosition] = $comparedCharacter; // Add the substring to the length index. $lengthIndex[1][$currentPosition] = $comparedCharacter; } } } } // If we have no commonalities at all then mark the original // string as deleted and the edited string as added and // return. if (empty($lengthIndex)) { return array(array(-1 => $originalString), array(1 => $editedString)); } // Pop the largest common substrings from the length index. end($lengthIndex); $largestSubstringLength = key($lengthIndex); // Take the first common substring if we have more than // one substring with the same length. // FIXME: Find a better heuristic for this decision. reset($lengthIndex[$largestSubstringLength]); $largestSubstringPosition = key($lengthIndex[$largestSubstringLength]); list($largestSubstringEndOriginal, $largestSubstringEndEdited) = explode('-', $largestSubstringPosition); $largestSubstring = $lengthIndex[$largestSubstringLength][$largestSubstringPosition]; // Add the largest common substring to the result set $diffResult = array(array(0 => $largestSubstring)); // Prepend the diff of the substrings before the common substring // to the result diff (by recursion). $precedingSubstringOriginal = String::substr($originalString, 0, $largestSubstringEndOriginal - $largestSubstringLength + 1); $precedingSubstringEdited = String::substr($editedString, 0, $largestSubstringEndEdited - $largestSubstringLength + 1); $diffResult = array_merge(String::diff($precedingSubstringOriginal, $precedingSubstringEdited), $diffResult); // Append the diff of the substrings after thr common substring // to the result diff (by recursion). $succeedingSubstringOriginal = String::substr($originalString, $largestSubstringEndOriginal + 1); $succeedingSubstringEdited = String::substr($editedString, $largestSubstringEndEdited + 1); $diffResult = array_merge($diffResult, String::diff($succeedingSubstringOriginal, $succeedingSubstringEdited)); // Return the array representing the diff. return $diffResult; }
/** * Fills the given citation object with * meta-data retrieved from PubMed. * @param $pmid string * @param $citationDescription MetadataDescription * @return MetadataDescription */ function &_lookup($pmid, &$citationDescription) { $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; } $metadata = array('pub-id[@pub-id-type="pmid"]' => $pmid, 'article-title' => $resultDOM->getElementsByTagName("ArticleTitle")->item(0)->textContent, 'source' => $resultDOM->getElementsByTagName("MedlineTA")->item(0)->textContent); if ($resultDOM->getElementsByTagName("Volume")->length > 0) { $metadata['volume'] = $resultDOM->getElementsByTagName("Volume")->item(0)->textContent; } if ($resultDOM->getElementsByTagName("Issue")->length > 0) { $metadata['issue'] = $resultDOM->getElementsByTagName("Issue")->item(0)->textContent; } // get list of author full names $nlmNameSchema = new NlmNameSchema(); 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($nlmNameSchema, ASSOC_TYPE_AUTHOR); // Surname $authorDescription->addStatement('surname', $authorNode->getElementsByTagName("LastName")->item(0)->textContent); // Given names $givenNamesString = ''; if ($authorNode->getElementsByTagName("FirstName")->length > 0) { $givenNamesString = $authorNode->getElementsByTagName("FirstName")->item(0)->textContent; } elseif ($authorNode->getElementsByTagName("ForeName")->length > 0) { $givenNamesString = $authorNode->getElementsByTagName("ForeName")->item(0)->textContent; } if (!empty($givenNamesString)) { foreach (explode(' ', $givenNamesString) as $givenName) { $authorDescription->addStatement('given-names', String::trimPunctuation($givenName)); } } // Suffix if ($authorNode->getElementsByTagName("Suffix")->length > 0) { $authorDescription->addStatement('suffix', $authorNode->getElementsByTagName("Suffix")->item(0)->textContent); } // Include collective names /*if ($resultDOM->getElementsByTagName("CollectiveName")->length > 0 && $authorNode->getElementsByTagName("CollectiveName")->item(0)->textContent != '') { // FIXME: This corresponds to an NLM-citation <collab> tag and should be part of the Metadata implementation }*/ $metadata['person-group[@person-group-type="author"]'][] =& $authorDescription; unset($authorDescription); } // Extract pagination if (String::regexp_match_get("/^[:p\\.\\s]*(?P<fpage>[Ee]?\\d+)(-(?P<lpage>\\d+))?/", $resultDOM->getElementsByTagName("MedlinePgn")->item(0)->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) (String::substr($pages['fpage'], 0, -String::strlen($pages['lpage'])) . $pages['lpage']); } $metadata['lpage'] = $lPage; } } // Get publication date // TODO: The publication date could be in multiple places if ($resultDOM->getElementsByTagName("ArticleDate")->length > 0) { $publicationDate = $resultDOM->getElementsByTagName("ArticleDate")->item(0)->getElementsByTagName("Year")->item(0)->textContent . '-' . $resultDOM->getElementsByTagName("ArticleDate")->item(0)->getElementsByTagName("Month")->item(0)->textContent . '-' . $resultDOM->getElementsByTagName("ArticleDate")->item(0)->getElementsByTagName("Day")->item(0)->textContent; $metadata['date'] = $publicationDate; } // Get publication type if ($resultDOM->getElementsByTagName("PublicationType")->length > 0) { foreach ($resultDOM->getElementsByTagName("PublicationType") as $publicationType) { // The vast majority of items on PubMed are articles so catch these... if (String::strpos(String::strtolower($publicationType->textContent), 'article') !== false) { $metadata['[@publication-type]'] = NLM_PUBLICATION_TYPE_JOURNAL; break; } } } // Get DOI if it exists foreach ($resultDOM->getElementsByTagName("ArticleId") 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 .= String::strtolower($attribute->textContent) . ' / '; } // Only add links to open access resources if (String::strpos($attributes, "subscription") === false && String::strpos($attributes, "membership") === false && String::strpos($attributes, "fee") === false && $attributes != "") { $links[] = $linkOut->getElementsByTagName("Url")->item(0)->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->addMetadataArrayToNlmCitationDescription($metadata, $citationDescription); }
/** * Retrieve auto-suggestions from the faceting service. * @param $url string * @param $searchRequest SolrSearchRequest * @param $userInput string * @param $fieldName string * @return array The generated suggestions. */ function _getFacetingAutosuggestions($url, $searchRequest, $userInput, $fieldName) { // Remove special characters from the user input. $searchTerms = strtr($userInput, '"()+-|&!', ' '); // Cut off the last search term. $searchTerms = explode(' ', $searchTerms); $facetPrefix = array_pop($searchTerms); if (empty($facetPrefix)) { return array(); } // Use the remaining search query to pre-filter // facet results. This may be an invalid query // but edismax will deal gracefully with syntax // errors. $userInput = String::substr($userInput, 0, -String::strlen($facetPrefix)); switch ($fieldName) { case 'query': // The 'query' filter goes agains all fields. $articleSearch = new ArticleSearch(); $solrFields = array_values($articleSearch->getIndexFieldMap()); break; case 'indexTerms': // The 'index terms' filter goes against keyword index fields. $solrFields = array('discipline', 'subject', 'type', 'coverage'); break; default: // All other filters can be used directly. $solrFields = array($fieldName); } $solrFieldString = implode('|', $solrFields); $searchRequest->addQueryFieldPhrase($solrFieldString, $userInput); // Construct the main query. $params = $this->_getSearchQueryParameters($searchRequest); if (!isset($params['q'])) { // Use a catch-all query in case we have no limiting // search. $params['q'] = '*:*'; } if ($fieldName == 'query') { $params['facet.field'] = 'default_spell'; } else { $params['facet.field'] = $fieldName . '_spell'; } $facetPrefixLc = String::strtolower($facetPrefix); $params['facet.prefix'] = $facetPrefixLc; // Make the request. $response = $this->_makeRequest($url, $params); if (!is_a($response, 'DOMXPath')) { return array(); } // Extract term suggestions. $nodeList = $response->query('//lst[@name="facet_fields"]/lst/int/@name'); if ($nodeList->length == 0) { return array(); } $termSuggestions = array(); foreach ($nodeList as $childNode) { $termSuggestions[] = $childNode->value; } // Add the term suggestion to the remaining user input. $suggestions = array(); foreach ($termSuggestions as $termSuggestion) { // Restore case if possible. if (strpos($termSuggestion, $facetPrefixLc) === 0) { $termSuggestion = $facetPrefix . String::substr($termSuggestion, String::strlen($facetPrefix)); } $suggestions[] = $userInput . $termSuggestion; } return $suggestions; }
/** * Parse an XML file using the specified handler. * If no handler has been specified, XMLParserDOMHandler is used by default, returning a tree structure representing the document. * @param $file string full path to the XML file * @return object actual return type depends on the handler */ function &parse($file) { $parser =& $this->createParser(); if (!isset($this->handler)) { // Use default handler for parsing $handler = new XMLParserDOMHandler(); $this->setHandler($handler); } xml_set_object($parser, $this->handler); xml_set_element_handler($parser, "startElement", "endElement"); xml_set_character_data_handler($parser, "characterData"); import('lib.pkp.classes.file.FileWrapper'); $wrapper =& FileWrapper::wrapper($file); // Handle responses of various types while (true) { $newWrapper = $wrapper->open(); if (is_object($newWrapper)) { // Follow a redirect unset($wrapper); $wrapper =& $newWrapper; unset($newWrapper); } elseif (!$newWrapper) { // Could not open resource -- error $returner = false; return $returner; } else { // OK, we've found the end result break; } } if (!$wrapper) { $result = false; return $result; } while (!$wrapper->eof() && ($data = $wrapper->read()) !== false) { // if the string contains non-UTF8 characters, convert it to UTF-8 for parsing if (Config::getVar('i18n', 'charset_normalization') == 'On' && !String::utf8_compliant($data)) { $utf8_last = String::substr($data, String::strlen($data) - 1); // if the string ends in a "bad" UTF-8 character, maybe it's truncated while (!$wrapper->eof() && String::utf8_bad_find($utf8_last) === 0) { // read another chunk of data $data .= $wrapper->read(); $utf8_last = String::substr($data, String::strlen($data) - 1); } $data = String::utf8_normalize($data); // strip any invalid UTF-8 sequences $data = String::utf8_bad_strip($data); // convert named entities to numeric entities $data = strtr($data, String::getHTMLEntities()); } // strip any invalid ASCII control characters $data = String::utf8_strip_ascii_ctrl($data); if (!xml_parse($parser, $data, $wrapper->eof())) { $this->addError(xml_error_string(xml_get_error_code($parser))); } } $wrapper->close(); $result =& $this->handler->getResult(); $this->destroyParser($parser); if (isset($handler)) { $handler->destroy(); unset($handler); } return $result; }
function mb_substr_replace($string, $replacement, $start, $length = null) { if (extension_loaded('mbstring') === true) { $string_length = String::strlen($string); if ($start < 0) { $start = max(0, $string_length + $start); } else { if ($start > $string_length) { $start = $string_length; } } if ($length < 0) { $length = max(0, $string_length - $start + $length); } else { if (is_null($length) === true || $length > $string_length) { $length = $string_length; } } if ($start + $length > $string_length) { $length = $string_length - $start; } return String::substr($string, 0, $start) . $replacement . String::substr($string, $start + $length, $string_length - $start - $length); } }
/** * @function abntDateFormatWithDay Format date taking in consideration ABNT month abbreviations * @param $string string * @return string */ function abntDateFormatWithDay($string) { if (is_numeric($string)) { // it is a numeric string, we handle it as timestamp $timestamp = (int) $string; } else { $timestamp = strtotime($string); } $format = "%d %B %Y"; if (String::strlen(strftime("%B", $timestamp)) > 4) { $format = "%d %b. %Y"; } return String::strtolower(strftime($format, $timestamp)); }
<?php class String { private $_string; public function __construct($string) { $this->_string = $string; } public function __call($method, $arguments) { $this->_string = call_user_func($method, $this->_string); return $this; } public function getValue() { return $this->_string; } } $test = new String(' test, test2 '); $test->trim(); var_dump($test->getValue()); $test->strlen(); var_dump($test->getValue());
/** * Override the built-in smarty truncate modifier to support mbstring * text properly, if possible. */ function smartyTruncate($string, $length = 80, $etc = '...', $break_words = false, $middle = false) { // Re-implement Smarty version, with multibyte-capable calls. if ($length == 0) { return ''; } if (String::strlen($string) > $length) { $length -= min($length, String::strlen($etc)); if (!$break_words && !$middle) { $string = String::regexp_replace('/\\s+?(\\S+)?$/', '', substr($string, 0, $length + 1)); } if (!$middle) { return String::substr($string, 0, $length) . $etc; } else { return String::substr($string, 0, $length / 2) . $etc . String::substr($string, -$length / 2); } } else { return $string; } }
/** * Construct an array of search strings from a citation * description and an array of search templates. * The templates may contain the placeholders * %aulast%: the first author's surname * %au%: the first author full name * %title%: the article-title (if it exists), * otherwise the source * %date%: the publication year * %isbn%: ISBN * @param $searchTemplates an array of templates * @param $citationDescription MetadataDescription * @return array */ function constructSearchStrings(&$searchTemplates, &$citationDescription) { // Convert first authors' name description to a string import('lib.pkp.plugins.metadata.nlm30.filter.Nlm30NameSchemaPersonStringFilter'); $personStringFilter = new Nlm30NameSchemaPersonStringFilter(); // Retrieve the authors $firstAuthorSurname = $firstAuthor = ''; $authors = $citationDescription->getStatement('person-group[@person-group-type="author"]'); if (is_array($authors) && count($authors)) { $firstAuthorSurname = (string) $authors[0]->getStatement('surname'); $firstAuthor = $personStringFilter->execute($authors[0]); } // Retrieve the editors $firstEditorSurname = $firstEditor = ''; $editors = $citationDescription->getStatement('person-group[@person-group-type="editor"]'); if (is_array($editors) && count($editors)) { $firstEditorSurname = (string) $editors[0]->getStatement('surname'); $firstEditor = $personStringFilter->execute($editors[0]); } // Retrieve (default language) title $title = (string) ($citationDescription->hasStatement('article-title') ? $citationDescription->getStatement('article-title') : $citationDescription->getStatement('source')); // Extract the year from the publication date $year = (string) $citationDescription->getStatement('date'); $year = String::strlen($year) > 4 ? String::substr($year, 0, 4) : $year; // Retrieve ISBN $isbn = (string) $citationDescription->getStatement('isbn'); // Replace the placeholders in the templates $searchStrings = array(); foreach ($searchTemplates as $searchTemplate) { // Try editors and authors separately $searchStrings[] = str_replace(array('%aulast%', '%au%', '%title%', '%date%', '%isbn%'), array($firstAuthorSurname, $firstAuthor, $title, $year, $isbn), $searchTemplate); $searchStrings[] = str_replace(array('%aulast%', '%au%', '%title%', '%date%', '%isbn%'), array($firstEditorSurname, $firstEditor, $title, $year, $isbn), $searchTemplate); } // Remove empty or duplicate searches $searchStrings = array_map(array('String', 'trimPunctuation'), $searchStrings); $searchStrings = array_unique($searchStrings); $searchStrings = arrayClean($searchStrings); return $searchStrings; }
/** * Checks whether the given string is an ISBN. * @param $isbn * @return boolean */ function isValidIsbn($isbn) { return is_string($isbn) && is_numeric($isbn) && String::strlen($isbn) == 13; }
/** * 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', String::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 (String::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) (String::substr($pages['fpage'], 0, -String::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 (String::strpos(String::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 .= String::strtolower($attribute->textContent) . ' / '; } // Only add links to open access resources if (String::strpos($attributes, "subscription") === false && String::strpos($attributes, "membership") === false && String::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); }
function parseDate($fieldName, $value, $attributes = null) { switch ($fieldName) { case '005': // YYYYMMDDHHMMSS.0 Date and time of latest transaction if (String::strlen($value) < 14) { return null; } $year = String::substr($value, 0, 4); $month = String::substr($value, 4, 2); $day = String::substr($value, 6, 2); $hour = String::substr($value, 8, 2); $minute = String::substr($value, 10, 2); $second = String::substr($value, 12); // Make sure the values fetched are all numeric foreach (array('year', 'month', 'day', 'hour', 'minute', 'second') as $var) { if (!is_numeric(${$var})) { return null; } } return mktime($hour, $minute, $second, $month, $day, $year); case '008': // YYMMDD[junk] Date entered on file $date = String::substr($value, 0, 6); $date = strtotime($date); if ($date !== -1 && $date !== false) { return $date; } break; case '260': if (isset($attributes['label']) && $attributes['label'] == 'c') { $date = strtotime($value); if ($date !== -1 && $date !== false) { return $date; } } break; } return null; }
/** * Get the localized, truncated description of the book for review. * @return string */ function getLocalizedDescriptionShort() { $end = ''; if (String::strlen($this->getLocalizedData('description'))) { $end = ' ...'; } return String::substr($this->getLocalizedData('description'), 0, 250) . $end; }
/** * Transform a single NLM name description to a person string. * NB: We use the style: surname suffix, initials (first-name) prefix * which is relatively easy to parse back. * @param $personDescription MetadataDescription * @return string */ function _flattenPersonDescription(&$personDescription) { $nameVars['%surname%'] = (string) $personDescription->getStatement('surname'); $givenNames = $personDescription->getStatement('given-names'); $nameVars['%firstname%'] = $nameVars['%initials%'] = ''; if (is_array($givenNames) && count($givenNames)) { if (String::strlen($givenNames[0]) > 1) { $nameVars['%firstname%'] = array_shift($givenNames); } foreach ($givenNames as $givenName) { $nameVars['%initials%'] .= String::substr($givenName, 0, 1) . '.'; } } if (!empty($nameVars['%initials%'])) { $nameVars['%initials%'] = ' ' . $nameVars['%initials%']; } $nameVars['%prefix%'] = (string) $personDescription->getStatement('prefix'); if (!empty($nameVars['%prefix%'])) { $nameVars['%prefix%'] = ' ' . $nameVars['%prefix%']; } $nameVars['%suffix%'] = (string) $personDescription->getStatement('suffix'); if (!empty($nameVars['%suffix%'])) { $nameVars['%suffix%'] = ' ' . $nameVars['%suffix%']; } // Fill placeholders in person template. $personString = str_replace(array_keys($nameVars), array_values($nameVars), $this->getTemplate()); // Remove empty brackets and trailing/leading whitespace $personString = trim(str_replace('()', '', $personString)); return $personString; }
/** * 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 && String::regexp_match_get('/^(' . $personRegex['title'] . ')/i', $personString, $results)) { $suffixString = trim($results[1], ',:; '); $personString = String::regexp_replace('/^(' . $personRegex['title'] . ')/i', '', $personString); } if ($degrees && String::regexp_match_get('/(' . $personRegex['degrees'] . ')$/i', $personString, $results)) { $degreesArray = explode(',', trim($results[1], ',')); foreach ($degreesArray as $key => $degree) { $degreesArray[$key] = String::trimPunctuation($degree); } $suffixString .= ' - ' . implode('; ', $degreesArray); $personString = String::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 = String::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 = String::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 < String::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; }
/** * Derive a confidence score calculated as the similarity of the * original raw citation and the citation text generated from the * citation description. * @param $metadataDescription MetadataDescription * @return integer filter confidence score */ function _filterConfidenceScore(&$metadataDescription) { // Retrieve the original plain text citation. $originalCitation = $this->getOriginalRawCitation(); // Generate the formatted citation output from the description. $citationOutputFilter =& $this->getCitationOutputFilter(); $generatedCitation = $citationOutputFilter->execute($metadataDescription); // Strip formatting and the Google Scholar tag so that we get a plain // text string that is comparable with the raw citation. $generatedCitation = trim(str_replace(GOOGLE_SCHOLAR_TAG, '', strip_tags($generatedCitation))); // Compare the original to the generated citation. $citationDiff = String::diff($originalCitation, $generatedCitation); // Calculate similarity as the number of deleted characters in relation to the // number of characters in the original citation. This intentionally excludes // additions as these can represent useful data like a DOI or an external link. $deletedCharacters = 0; foreach ($citationDiff as $diffPart) { // Identify deletions. if (key($diffPart) == -1) { $deletedCharacters += String::strlen(current($diffPart)); } } $originalCharacters = String::strlen($originalCitation); $partOfCommonCharacters = ($originalCharacters - $deletedCharacters) / $originalCharacters; $filterConfidenceScore = (int) round(min($partOfCommonCharacters * 100, 100)); return $filterConfidenceScore; }
/** * Determine whether or not the lengths of the two supplied values are * "similar". * @param $reference string * @param $value string * @return boolean True if the lengths match very roughly. */ function checkLengths($reference, $value) { $referenceLength = String::strlen($reference); $length = String::strlen($value); $lengthDifference = abs($referenceLength - $length); if ($referenceLength == 0) { return $length == 0; } if ($lengthDifference / $referenceLength > 1 && $lengthDifference > 10) { return false; } return true; }
function truncate($value, $length = 80, $ellipsis = '...') { if (String::strlen($value) > $length) { $value = String::substr($value, 0, $length - String::strlen($ellipsis)); return $value . $ellipsis; } return $value; }
/** * Helper function: Reinsert tags from the tag array into their original position in the string * @author Matt Crider * @param string * @param array * @param boolean Set to true to reinsert tags starting at the back of the string * @return string */ function _reinsertTags($string, &$tags, $reverse = false) { if (empty($tags)) { return $string; } for ($i = 0; $i < count($tags); $i++) { $length = String::strlen($string); if ($tags[$i][1] < String::strlen($string)) { if ($reverse) { if ($tags[$i][1] == 0) { // Cannot use -0 as the start index (its same as +0) $string = String::substr_replace($string, $tags[$i][0], $length, 0); } else { $string = String::substr_replace($string, $tags[$i][0], -$tags[$i][1], 0); } } else { $string = String::substr_replace($string, $tags[$i][0], $tags[$i][1], 0); } } } return $string; }
private function parseCondition() { $page = intval(Req::args("p")); $page_size = 36; $sort = Filter::int(Req::args("sort")); $sort = $sort == null ? 0 : $sort; $cid = Filter::int(Req::args("cid")); $cid = $cid == null ? 0 : $cid; $brand = Filter::int(Req::args("brand")); $price = Req::args("price"); //下面已进行拆分过滤 $keyword = urldecode(Req::args('keyword')); $keyword = Filter::text($keyword); $keyword = Filter::commonChar($keyword); //初始化数据 $attrs = $specs = $spec_attr = $category_child = $spec_attr_selected = $selected = $has_category = $category = $current_category = array(); $where = $spec_attr_where = $url = ""; $condition_num = 0; $model = $this->model; //基本条件的建立 //关于搜索的处理 $action = strtolower(Req::args("act")); if ($action == 'search') { // xuzhongyi $seo_title = "分类检索"; $seo_keywords = "全部分类"; $seo_description = "所有分类商品"; //取得商品的子分类 $category_ids = ""; $categ = Category::getInstance(); //set:$cid = 5; if ($cid == 0) { $category_child = $categ->getCategoryChild(0, 1); } else { $current_category = $this->model->table("goods_category as gc")->fields("gc.*,gt.name as gname,gt.attr,gt.spec,gc.seo_title,gc.seo_keywords,gc.seo_description")->join("left join goods_type as gt on gc.type_id = gt.id")->where("gc.id = {$cid}")->find(); if ($current_category) { $path = trim($current_category['path'], ','); $rows = $this->model->table("goods_category")->where("path like '{$current_category['path']}%'")->order("field(`id`,{$path})")->findAll(); $category = $this->model->table("goods_category")->where("id in ({$path})")->order("field(`id`,{$path})")->findAll(); foreach ($rows as $row) { $category_ids .= $row['id'] . ','; } $category_ids = trim($category_ids, ","); $category_child = $categ->getCategoryChild($path, 1); $attrs = unserialize($current_category['attr']); $specs = unserialize($current_category['spec']); $attrs = is_array($attrs) ? $attrs : array(); $specs = is_array($specs) ? $specs : array(); } } $seo_category = $model->table('goods_category')->where("id={$cid}")->find(); if ($seo_category) { if ($seo_category['seo_title'] != '') { $seo_title = $seo_category['seo_title']; } else { $seo_title = $seo_category['name']; } if ($seo_category['seo_keywords'] != '') { $seo_keywords = $seo_category['name'] . ',' . $seo_category['seo_keywords']; } else { $seo_keywords = $seo_category['name']; } if ($seo_category['seo_description'] != '') { $seo_description = $seo_category['seo_description']; } else { $seo_description = $seo_category['name']; } } if ($category_ids != "") { $where = "go.category_id in ({$category_ids})"; } else { $where = "1=1"; } //关于类型的处理 ////提取商品下的类型 $seo_title = $seo_keywords = $keyword; $where = "name like '%{$keyword}%'"; $rows = $model->table("goods")->fields("category_id,count(id) as num")->where($where)->group("category_id")->findAll(); $category_ids = ""; $category_count = array(); foreach ($rows as $row) { $category_ids .= $row['category_id'] . ','; $category_count[$row['category_id']] = $row['num']; } $category_ids = trim($category_ids, ","); $has_category = array(); $seo_description = ''; if ($category_ids) { //搜索到内容且真正的点击搜索时进行统计 if ($this->getModule()->checkToken()) { $keyword = urldecode(Req::args('keyword')); $keyword = Filter::sql($keyword); $keyword = trim($keyword); $len = String::strlen($keyword); if ($len >= 2 && $len <= 8) { $model = new Model("tags"); $obj = $model->where("name='{$keyword}'")->find(); if ($obj) { $model->data(array('num' => "`num`+1"))->where("id=" . $obj['id'])->update(); } else { $model->data(array('name' => $keyword))->insert(); } } } $rows = $model->table("goods_category")->where("id in ({$category_ids})")->findAll(); foreach ($rows as $row) { $path = trim($row['path'], ','); $paths = explode(',', $path); $root = 0; if (is_array($paths)) { $root = $paths[0]; } $row['num'] = $category_count[$row['id']]; $has_category[$root][] = $row; $seo_description .= $row['name'] . ','; } } if ($cid != 0) { $where = "category_id={$cid} and name like '%{$keyword}%'"; $category = $model->table("goods_category as gc ")->join("left join goods_type as gt on gc.type_id = gt.id")->where("gc.id={$cid}")->find(); if ($category) { $attrs = unserialize($category['attr']); $specs = unserialize($category['spec']); if ($category['seo_title'] != '') { $seo_title = $category['seo_title']; } else { $seo_title = $category['name']; } if ($category['seo_keywords'] != '') { $seo_keywords = $category['seo_keywords']; } if ($category['seo_description'] != '') { $seo_description = $category['seo_description']; } } } //关于分类检索的处理 } else { if ($action == 'category') { $seo_title = "分类检索"; $seo_keywords = "全部分类"; $seo_description = "所有分类商品"; //取得商品的子分类 $category_ids = ""; $categ = Category::getInstance(); if ($cid == 0) { $category_child = $categ->getCategoryChild(0, 1); } else { $current_category = $this->model->table("goods_category as gc")->fields("gc.*,gt.name as gname,gt.attr,gt.spec,gc.seo_title,gc.seo_keywords,gc.seo_description")->join("left join goods_type as gt on gc.type_id = gt.id")->where("gc.id = {$cid}")->find(); if ($current_category) { $path = trim($current_category['path'], ','); $rows = $this->model->table("goods_category")->where("path like '{$current_category['path']}%'")->order("field(`id`,{$path})")->findAll(); $category = $this->model->table("goods_category")->where("id in ({$path})")->order("field(`id`,{$path})")->findAll(); foreach ($rows as $row) { $category_ids .= $row['id'] . ','; } $category_ids = trim($category_ids, ","); $category_child = $categ->getCategoryChild($path, 1); $attrs = unserialize($current_category['attr']); $specs = unserialize($current_category['spec']); $attrs = is_array($attrs) ? $attrs : array(); $specs = is_array($specs) ? $specs : array(); } } $seo_category = $model->table('goods_category')->where("id={$cid}")->find(); if ($seo_category) { if ($seo_category['seo_title'] != '') { $seo_title = $seo_category['seo_title']; } else { $seo_title = $seo_category['name']; } if ($seo_category['seo_keywords'] != '') { $seo_keywords = $seo_category['name'] . ',' . $seo_category['seo_keywords']; } else { $seo_keywords = $seo_category['name']; } if ($seo_category['seo_description'] != '') { $seo_description = $seo_category['seo_description']; } else { $seo_description = $seo_category['name']; } } if ($category_ids != "") { $where = "go.category_id in ({$category_ids})"; } else { $where = "1=1"; } } } //品牌筛选 $rows = $model->table("goods as go")->fields("brand_id,count(id) as num")->where($where)->group("brand_id")->findAll(); $brand_ids = ''; $brand_num = $has_brand = array(); foreach ($rows as $row) { $brand_ids .= $row['brand_id'] . ','; $brand_num[$row['brand_id']] = $row['num']; } $brand_ids = trim($brand_ids, ','); //价格区间 $prices = $model->table("goods as go")->fields("max(sell_price) as max,min(sell_price) as min,avg(sell_price) as avg")->where($where)->find(); $price_range = Common::priceRange($prices); if ($brand_ids) { $has_brand = $model->table("brand")->where("id in ({$brand_ids})")->findAll(); } //var_dump($price_range);exit(); if (!empty($price_range)) { $has_price = array_flip($price_range); } else { $has_price = array(); } if ($price && isset($has_price[$price])) { $prices = explode('-', $price); if (count($prices) == 2) { $where .= " and sell_price>=" . Filter::int($prices[0]) . " and sell_price <=" . Filter::int($prices[1]); } else { $where .= " and sell_price>=" . Filter::int($prices[0]); } $url .= "/price/{$price}"; } if ($brand && isset($brand_num[$brand])) { $url .= "/brand/{$brand}"; $where .= " and brand_id = {$brand} "; } //规格与属性的处理 if ($attrs != null) { foreach ($attrs as $attr) { if ($attr['show_type'] == 1) { $spec_attr[$attr['id']] = $attr; } } } if ($specs != null) { foreach ($specs as $spec) { $spec['values'] = unserialize($spec['value']); unset($spec['value'], $spec['spec']); $spec_attr[$spec['id']] = $spec; } } foreach ($selected as $key => $value) { if (isset($spec_attr[$key])) { $spec_attr_selected[$key] = $spec_attr[$key]; foreach ($spec_attr_selected[$key]['values'] as $k => $v) { if ($value == $v['id']) { $spec_attr_selected[$key]['values'] = $v; break; } } } } //规格处属性的筛选 $args = Req::args(); unset($args['con'], $args['act'], $args['p'], $args['sort'], $args['brand'], $args['price']); foreach ($args as $key => $value) { if (is_numeric($key) && is_numeric($value)) { if (isset($spec_attr[$key])) { $spec_attr_where .= "or (`key`={$key} and `value` = {$value}) "; $condition_num++; $url .= '/' . $key . '/' . $value; } } $selected[$key] = $value; } $selected['price'] = $price; $selected['brand'] = $brand; $spec_attr_where = trim($spec_attr_where, "or"); $where .= ' and go.is_online =0'; if ($condition_num > 0) { $where .= " and go.id in (select goods_id from tiny_spec_attr where {$spec_attr_where} group by goods_id having count(goods_id) >= {$condition_num})"; } //排序的处理 switch ($sort) { case '1': $goods_model = $model->table("goods as go")->join("left join tiny_order_goods as og on go.id = og.goods_id")->fields("go.*,sum(og.goods_nums) as sell_num")->order("sell_num desc")->group("go.id"); break; case '2': $goods_model = $model->table("goods as go")->join("left join tiny_review as re on go.id = re.goods_id")->fields("go.*,count(re.goods_id) as renum")->group("go.id")->order("renum desc"); break; case '3': $goods_model = $model->table("goods as go")->order("sell_price desc"); break; case '4': $goods_model = $model->table("goods as go")->order("sell_price"); break; case '5': $goods_model = $model->table("goods as go")->order("id desc"); break; default: $goods_model = $model->table("goods as go")->order("sort desc"); break; } //var_dump($where);exit; //提取商品 $goods = $goods_model->where($where)->findPage($page, $page_size); //品牌处理 preg_match_all('!(<(a|span)[^>]+>(上一页|下一页)</\\2>)!', $goods['html'], $matches); $topPageBar = ""; if (count($matches[0]) > 0) { $topPageBar = implode("", $matches[0]); } $this->assign("topPageBar", $topPageBar); //赋值处理 $this->assign('seo_title', $seo_title); $this->assign('seo_keywords', $seo_keywords); $this->assign('seo_description', '对应的商品共有' . $goods['page']['total'] . '件商品,包括以下分类:' . $seo_description); $this->assign("keyword", $keyword); $this->assign("sort", $sort); $this->assign("has_brand", $has_brand); $this->assign("brand_num", $brand_num); $this->assign("current_category", $current_category); $this->assign("goods", $goods); $this->assign("selected", $selected); $this->assign("spec_attr", $spec_attr); $this->assign("spec_attr_selected", $spec_attr_selected); $this->assign("category_child", $category_child); $this->assign("price_range", $price_range); $this->assign("category_nav", $category); $this->assign("has_category", $has_category); if ($action == 'search') { $this->assign("url", "/index/search/keyword/" . $keyword . "/cid/{$cid}/sort/{$sort}" . $url); } else { $this->assign("url", "/index/category/cid/" . $cid . "/sort/{$sort}" . $url); } $this->redirect(); }