/** * @brief get ISBN data for $isbn at ISBNdb * * @param string $isbn ISBN to search for * @param arrayref &$meta * @return int $status (0 on success, ERRORCODE otherwise) */ public static function get($isbn, &$meta) { if ($keyString = Config::getApp('isbndb-key', '')) { $keys = explode(',', $keyString); $key = $keys[rand(0, count($keys) - 1)]; $data = false; $isbn = preg_replace('/[^0-9X]/i', '', $isbn); if (Isbn::validate($isbn)) { $command = 'http://isbndb.com/api/v2/json/' . $key . '/book/' . $isbn; $data = json_decode(file_get_contents($command), true); if (isset($data['error'])) { Util::logWarn("ISBNDB: " . $data['error']); if (!(stripos($data['error'], 'Daily request limit exceeded') === false)) { return Isbn::REQUEST_LIMIT_EXCEEDED; } elseif (!(stripos($data['error'], 'Unable to locate') === false)) { return Isbn::NOT_FOUND; } else { return Isbn::ERROR; } } else { self::parse($data['data'][0], $meta); return Isbn::SUCCESS; } } } return false; }
protected function makeNewItem($sectionId, $details, $packageId = null, $status = null) { // undefined index errors if we have high error level reporting on. we // really don't care about these here, it's fine if they're interpreted as // falsy $oldLevel = error_reporting(0); if ($details['requiredStatus'] < SectionHasItem::GO_TO_CLASS_FIRST) { return true; } if (Isbn::validate(Isbn::clean($details['isbn']))) { $details['isbn'] = Isbn::to13(Isbn::clean($details['isbn'])); } else { $details['isbn'] = null; } $item = $this->getItemQuery()->filterByProductId($details['productId'])->filterByPartNumber($details['partNumber'])->filterByIsbn($details['isbn'])->findOne(); if (!$item) { $item = $this->newItem()->setIsbn($details['isbn'])->setProductId($details['productId'])->setPartNumber($details['partNumber']); } $item->setTitle($details['title'])->setAuthor($details['author'])->setEdition($details['edition'])->setPublisher($details['publisher'])->setImageUrl($details['imageUrl'])->setBNew($details['newPrice'])->setBUsed($details['usedPrice'])->setIsPackage($details['isPackage'] || $details['components'])->setPackageId($packageId)->save(); if (isset($details['components'])) { foreach ($details['components'] as $component) { $this->makeNewItem($sectionId, $component, $item->getId(), $details['requiredStatus']); } } if ($packageId === null) { $sectionHasItem = $this->getSectionHasItemQuery()->filterByItem($item)->filterBySectionId($sectionId)->findOne(); if (!$sectionHasItem) { $sectionHasItem = $this->newSectionHasItem()->setItem($item)->setSectionId($sectionId); } $sectionHasItem->setRequiredStatus($details['requiredStatus'] ?: $status)->setTouched(1)->save(); } error_reporting($oldLevel); }
public static function getSectionsHaveItems($sections) { $result_url = $base . 'Course/Results'; foreach ($sections as $section) { self::doRequest('CourseMaterials/AddSection?sectionId=' . urlencode($section['BId']), $sections[0]); } $doc = new DOMDocument(); @$doc->loadHTML(self::doRequest('Course/Results', $sections[0])); $finder = new DomXPath($doc); $ret = array(); foreach ($finder->query('//div[@class="course-info"]') as $course) { $tds = $finder->query('//td[@class="course-materials-description"]', $course); $items = array(); foreach ($tds as $td) { $item = array(); $item['Title'] = $finder->query('.//p[@class="title"]', $td)->item(0)->nodeValue; $info = explode('<br>', innerHTML($finder->query('.//p[@class="info"]', $td)->item(0))); foreach ($info as $subject) { list($key, $value) = array_map('trim', explode(':', strip_tags($subject))); if ($key == 'Edition') { //we need to get Edition and Publisher here.. $values = explode(',', $value); $item['edition'] = trim($values[0]); //$item['Year'] = preg_replace('([^0-9]*)', '', $values[1]); } else { if ($key == 'Author') { $item['author'] = $value; } else { if ($key == 'ISBN' && Isbn::validate(Isbn::clean($value))) { $item['isbn'] = $value; } } } } $required = strtolower($finder->query('.//a[@rel="/Help/RequirementHelp"]//strong', $td)->item(0)->nodeValue); $item['isComponent'] = $required == 'part of set'; if ($required == 'required') { $required = SectionHasItem::REQUIRED; } else { if ($required == 'recommended' || $required == 'optional') { $required = SectionHasItem::RECOMMENDED; } else { if ($required == 'neebo-suggested') { $required = SectionHasItem::BOOKSTORE_RECOMMENDED; } else { $required = SectionHasItem::REQUIRED; } } } $item['requiredStatus'] = $required; $prices = $finder->query('.//td[@class="course-product-price"]/label'); $priceList = array(); foreach ($prices as $price) { $priceList[] = preg_replace('([^0-9\\.]*)', '', $price->nodeValue); } $item['BNew'] = max($priceList); $items[] = $item; } list(, $sectionId) = explode('=', $finder->query('//h4/a', $course)->item(0)->getAttribute('href')); $ret[$sectionId] = self::processItems($items); } return $ret; }
/** * @param mixed $isbn10 * * @return bool */ public static function validate($isbn10) { trigger_error('Isbn10::validate validator is deprecated since 1.2 and will be removed in 2.0. Use Isbn::validate($value, 10) instead.', E_USER_DEPRECATED); return Isbn::validate($isbn10, 10); }
/** * @return an array of item metadata: productId, partNumber, isbn, title, author, * edition, publisher, imageUrl, usedPrice, newPrice, required */ protected static function getItemMetadata($itemText) { $details = array(); $productId = $partNumber = $isbn = $title = $author = $edition = $publisher = ""; $usedPrice = $newPrice = $required = $isPackage = $isComponent = ""; if (preg_match("/productId\\=(.+?)&/", $itemText, $matches)) { $details['productId'] = trim($matches[1]); } if (preg_match("/partNumber\\=(.+?)&/", $itemText, $matches)) { $details['partNumber'] = rtrim($matches[1], "&"); } if (preg_match("/ISBN\\:\\<\\/span\\>.+?(\\d+).+?\\</s", $itemText, $matches)) { $isbn = trim($matches[1]); $isbn = Isbn::validate($isbn) ? $isbn : ""; if ($isbn[0] == '2') { $isbn = ""; } $details['isbn'] = $isbn; } if (preg_match("/\\d{5}'\\stitle\\=\"(.+?)\"\\>.+?\\<img/s", $itemText, $matches)) { $details['title'] = titleCase(trim(htmlspecialchars_decode($matches[1], ENT_QUOTES))); } if (preg_match("/\\<span\\>Author:.*?\\<\\/span\\>(.+?)\\<\\/li/s", $itemText, $matches)) { $author = ucname(trim($matches[1])); $details['author'] = is_numeric($author) ? "" : $author; } if (preg_match("/Edition:\\<\\/span\\>(.+?)\\<br/", $itemText, $matches)) { $details['edition'] = strtolower(trim($matches[1])); } if (preg_match("/Publisher:\\<\\/span\\>(.+?)\\<br/", $itemText, $matches)) { $details['publisher'] = titleCase(trim($matches[1])); } if (preg_match("/Used.+?(\\d{1,3}\\.\\d{2})/s", $itemText, $matches)) { $details['usedPrice'] = $matches[1]; } if (preg_match("/New.+?(\\d{1,3}\\.\\d{2})/s", $itemText, $matches)) { $details['newPrice'] = $matches[1]; } if (strpos($itemText, "The price of the textbook is not yet available")) { $details['newPrice'] = $details['usedPrice'] = 0; } if (!$details['title'] && !$details['author']) { return false; } $details['imageUrl'] = ""; // todo $options = array("REQUIRED\\sPACKAGE", "RECOMMENDED\\sPACKAGE", "REQUIRED", "RECOMMENDED", "PACKAGE\\sCOMPONENT", "GO\\sTO\\sCLASS FIRST", "BOOKSTORE\\sRECOMMENDED"); preg_match("/" . implode('|', $options) . "/", $itemText, $matches); $required = trim($matches[0]); $details['isPackage'] = $required == "REQUIRED PACKAGE" || $required == "RECOMMENDED PACKAGE"; $details['isComponent'] = $required == "PACKAGE COMPONENT"; if ($required == "REQUIRED PACKAGE" || $required == "REQUIRED") { $required = SectionHasItem::REQUIRED; } else { if ($required == "RECOMMENDED PACKAGE" || $required == "RECOMMENDED") { $required = SectionHasItem::RECOMMENDED; } else { if ($required == "GO TO CLASS FIRST") { $required = SectionHasItem::GO_TO_CLASS_FIRST; } else { if ($required == "BOOKSTORE RECOMMENDED") { $required = SectionHasItem::BOOKSTORE_RECOMMENDED; } else { $required = SectionHasItem::REQUIRED; } } } } $details['requiredStatus'] = $required; return $details; }
/** * todo: this should be changed to use Amazon::getMultiAmazonData so only * one call is made if there are multiple isbns. however, that makes it * difficult to keep isbn10/isbn13 distinction. */ public function book($isbn) { global $app; $isbns = explode("-", $isbn); $ret = array(); foreach ($isbns as $isbn) { if (Isbn::validate($isbn) && ($data = Amazon::getAmazonData($isbn))) { // Occasionally Amazon returns data for the book we want, but // with a different ISBN. This preserves the original ISBN. if ($data['isbn'] != Isbn::to13($isbn)) { $itemId = $data['isbn']; } else { $itemId = $isbn; } $ret[] = array('itemId' => $itemId, 'slug' => $itemId, 'data' => $data); } else { $ret[] = array('itemId' => $isbn, 'slug' => $isbn, 'error' => true); } } echo json_encode($ret); $app->stop(); Results::fetchPrices($isbns); }
public function testValidateAndConvertIsbn13Only() { $this->assertTrue(Isbn::validate($this->validIsbn13Only)); $this->assertFalse(Isbn::to10($this->validIsbn13Only)); }