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; }
protected static function processItemText($item) { $details = array(); if (preg_match('/Author\\:\\ \\;([^<]*)\\</', $item, $matches)) { $details['author'] = ucname(trim($matches[1])); } if (preg_match('/Edition\\:\\ \\;([^<]*)\\</', $item, $matches)) { $details['edition'] = trim($matches[1]); } if (preg_match('/src\\="(http[^"]+([X0-9]{10,13}|noBookImage)[^"]+?)"[^>]*?alt\\="([^"]+?)"/', $item, $matches)) { if (strpos($matches[1], 'noBookImage')) { $details['imageUrl'] = false; $details['isbn'] = null; } else { $details['imageUrl'] = trim($matches[1]); $details['isbn'] = Isbn::to13(Isbn::clean($matches[2])); } $details['title'] = titleCase(trim(html_entity_decode($matches[3]))); } $details['newPrice'] = $details['usedPrice'] = null; if (!strpos($item, 'Buy Digital') && preg_match('/buynewradio[^>]+?\\>\\s*?\\$([\\d\\.]+)/', $item, $matches)) { $details['newPrice'] = $matches[1]; } if (preg_match('/buyusedradio[^>]+?\\>\\s*?\\$([\\d\\.]+)/', $item, $matches)) { $details['usedPrice'] = $matches[1]; } if (preg_match('/ISBN:\\s*(?:\\ \\;)?(\\d{10,13})/', $item, $matches)) { $details['isbn'] = Isbn::to13(Isbn::clean($matches[1])); } // lowercase c in catEntry ensures that the rental item id is not selected, because it is like rentalCatEntry. // the new item id seems to always be exactly one less than the used // note: we don't use this as a unique identifier because we don't want to deal with which // is used and which is new, and because availability changes if (preg_match_all('/catEntryId_\\d+[^>]+?value\\="(\\d*)"/', $item, $matches)) { //$details['productId'] = count($matches[1] == 1) ? $matches[1][0] : call_user_func_array('min', $matches[1]); } $details['partNumber'] = null; $details['publisher'] = null; $details['isPackage'] = false; $details['components'] = array(); return $details; }
public function testClean() { $this->assertEquals('9780671552343', Isbn::clean($this->uncleanedValidIsbn)); $this->assertEquals('0671552341', Isbn::to10($this->uncleanedValidIsbn)); }