OER_OERSI_ONLY_DOWNLOADABLE ? ' AND _exists_:encoding.contentUrl' : ''; if ($tag) { $endpoint_url .= '?q=' . urlencode("keywords:" . $tag . $appendix); } else { $endpoint_url .= '?q=' . urlencode($text . $appendix); } $cr = curl_init(); curl_setopt($cr, CURLOPT_URL, $endpoint_url); curl_setopt($cr, CURLOPT_RETURNTRANSFER, 1); curl_setopt($cr, CURLOPT_FOLLOWLOCATION, true); curl_setopt($cr, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($cr, CURLOPT_SSL_VERIFYHOST, false); $stream_context_options = stream_context_get_options(get_default_http_stream_context($endpoint_url)); curl_setopt($cr, CURLOPT_PROXY, isset($stream_context_options['http']['proxy']) ? Config::get()->HTTP_PROXY : ''); $output = curl_exec($cr); $error = curl_error($cr); if ($error) { $error_number = curl_getinfo($cr, CURLINFO_HTTP_CODE); error_log('OERSI search is not working. '.$error_number.': '.$error); } curl_close($cr); if ($output) { $json = json_decode($output, true); if ($json !== null) { foreach ((array)$json['hits']['hits'] as $material_data) { //check if material already in database from this or another OER Campus host if (OERHost::URIExists($material_data['_source']['id'])) { continue; } $material = OERMaterial::findOneBySQL('foreign_material_id = ? AND host_id = ?', [ md5($material_data['_source']['id']), $this->getId() ]); if (!$material) { $material = new OERMaterial(); $material['foreign_material_id'] = md5($material_data['_source']['id']); $material['host_id'] = $this->getId(); } $material['name'] = mb_substr($material_data['_source']['name'], 0, 64); $material['draft'] = '0'; $material['filename'] = ''; $material['short_description'] = ''; $material['description'] = trim($material_data['_source']['description'] ?? ''); $material['difficulty_start'] = 0; $material['difficulty_end'] = 12; $material['uri'] = $material_data['_source']['id']; $material['source_url'] = $material_data['_source']['id']; $material['content_type'] = $material_data['_source']['encoding'][0]['encodingFormat'] ?? ''; $material['license_identifier'] = !empty($material_data['_source']['license']['id']) ? $this->getLicenseID($material_data['_source']['license']['id']): ''; if (!$material['category']) { $material['category'] = $material->autoDetectCategory(); } $material['front_image_content_type'] = !empty($material_data['_source']['image']) ? 'image/jpg' : null; $material['data'] = [ 'front_image_url' => $material_data['_source']['image'] ?? null, 'download' => $material_data['_source']['encoding'][0]['contentUrl'] ?: '', 'id' => $material_data['_id'], 'organization' => $material_data['_source']['sourceOrganization'][0]['name'] ?? $material_data['_source']['publisher'][0]['name'] ?? '', ]; $material->store(); //set users: $userdata = []; if ( isset($material_data['_source']['creator']) && is_array($material_data['_source']['creator']) ) { foreach ($material_data['_source']['creator'] as $creator) { $userdata[] = [ 'user_id' => md5($creator['name']), 'name' => $creator['name'], 'host_url' => $this['url'] ]; } } $material->setUsers($userdata); //set topics: if (isset($material_data['_source']['keywords'])) { $material->setTopics($material_data['_source']['keywords']); } } } else { error_log('OERSI returns bad JSON data: '.$output); } } } /** * Pushes some data to the foreign OERHost. * @param string $endpoint : part behind the host-url like "push_data" * @param array $data : the data to be pushed as an associative array * @return bool|CurlHandle|resource */ public function pushDataToEndpoint($endpoint, $data) { return true; } /** * Fetches all information of an item from that host. This is a request. * @param string $foreign_material_id : foreign id of that oer-material * @return array|null : data of that material or null on error. */ public function fetchItemData(OERMaterial $material) { $endpoint_url = 'https://oersi.org/resources/' . urlencode($material['data']['id']) . '?format=json'; $output = @file_get_contents($endpoint_url, false, get_default_http_stream_context($endpoint_url)); if ($output) { $output = json_decode($output, true); if ($output) { $data = []; $data['name'] = mb_substr($output['name'], 0, 64); $data['draft'] = '0'; $data['filename'] = ''; $data['short_description'] = ''; $data['description'] = $output['description'] ?? ''; $data['difficulty_start'] = 12; $data['uri'] = $output['encoding'][0]['contentUrl'] ?? ''; $data['source_url'] = $output['id']; $data['content_type'] = $output['encoding'][0]['encodingFormat'] ?? ''; $data['license_identifier'] = !empty($output['license']['id']) ? $this->getLicenseID($output['license']['id']) : ''; if (empty($data['category'])) { $data['category'] = $material->autoDetectCategory(); } $data['front_image_content_type'] = !empty($output['image']) ? 'image/jpg' : null; $data['data'] = $material['data']->getArrayCopy(); $data['data']['download'] = $output['encoding'][0]['contentUrl'] ?? ''; $data['data']['front_image_url'] = $output['image'] ?? ''; $data['data']['organization'] = $output['sourceOrganization'][0]['name'] ?? $output['publisher'][0]['name'] ?? ''; return [ 'data' => $data, 'topics' => $output['keywords'] ?? [] ]; } } else { return ['deleted' => 1]; } } public function getFrontImageURL(OERMaterial $material) { return $material['data'] ? $material['data']['front_image_url'] : null; } /** * Tries to match the CC-license URL from OERSI to an spdx-identifier, which is used in Stud.IP * @param $license : an URL * @return string */ protected function getLicenseID($license) { $matched = preg_match("^https:\/\/creativecommons.org\/licenses\/([\w\d\-\.]+)\/([\w\d\-\.]+)^", $license, $matches); if ($matched) { $spdx_id = 'CC-' . strtoupper($matches[1]) . '-' . strtoupper($matches[2]); if (License::find($spdx_id)) { return $spdx_id; } } return ''; } public function isReviewable() { return false; } public function getDownloadURLForMaterial(OERMaterial $material) { return $material['data']['download'] ?? $material['uri']; } public function cbCreateKeysIfNecessary() { //do nothing } }