/** * Task : updatePlugin() * * Note: This function does direct output, * in fact it builds the log string * that concerns the update of a * plugin. */ private function updatePlugin($plugin, $index = null, $length = null, $subtasks) { // Displaying index / length $this->outputStr('Plugin (' . $index . '/' . $length . ') (id #' . $plugin->id . '): '); $update = false; // This can be used to detect the state // in some way (think about it) $this->currentXml = null; $this->currentPluginState = null; // fetching via http $unableToFetch = false; $httpClient = new GuzzleHttpClient(); try { $pluginXmlRequest = $httpClient->get($plugin->xml_url, ["headers" => ["User-Agent" => Tool::getConfig()['glpi_plugin_directory_user_agent']]]); } catch (\GuzzleHttp\Exception\ConnectException $e) { $unableToFetch = true; } finally { if ($unableToFetch || !$unableToFetch && $pluginXmlRequest->getStatusCode() != 200) { if ($this->pluginMaxConsecutiveXmlFetchFails) { $fetchFailCount = $plugin->incrementXmlFetchFailCount(); if ($fetchFailCount == $this->pluginMaxConsecutiveXmlFetchFails) { $this->triggerPluginXmlStateChange($plugin, 'bad_xml_url', true, in_array('alert_plugin_team_on_xml_state_change', $subtasks)); $plugin->resetXmlFetchFailCount(); } } else { $this->triggerPluginXmlStateChange($plugin, 'bad_xml_url', true, in_array('alert_plugin_team_on_xml_state_change', $subtasks)); } $this->outputStr($plugin->xml_url . "\" Cannot get XML file via HTTP, Skipping.\n"); if ($this->throwsExceptions) { throw new InvalidXML('url', $plugin->xml_url); } return false; } else { $plugin->resetXmlFetchFailCount(); } } $xml = $pluginXmlRequest->getBody(); $this->currentXml = (string) $xml; $crc = md5($xml); // compute crc if ($plugin->xml_crc != $crc || $plugin->name == NULL) { $update = true; // if we got // missing name or changing // crc, then we're going to // update that one. // missing name means it's // the first time the plugin // is updated } else { $this->outputStr("\"" . $plugin->name . "\" Already up-to-date, Skipping.\n"); $this->triggerPluginXmlStateChange($plugin, 'passing', true, in_array('alert_plugin_team_on_xml_state_change', $subtasks)); return false; } try { $xml = new ValidableXMLPluginDescription($xml); $xml->validate(); } catch (\API\Exception\InvalidXML $e) { $_unreadable = ''; if (isset($xml->contents) && $xml->contents->name && sizeof($xml->contents->name->children()) < 1 && strlen((string) $xml->contents->name) < 80) { $_unreadable .= '"' . (string) $xml->contents->key . '" '; } elseif ($plugin->name) { $_unreadable .= '"' . $plugin->name . '" '; } $this->triggerPluginXmlStateChange($plugin, 'xml_error', true, in_array('alert_plugin_team_on_xml_state_change', $subtasks)); $_unreadable .= "Unreadable/Non validable XML, error: " . $e->getRepresentation() . " Skipping.\n"; $this->outputStr($_unreadable); if ($this->throwsExceptions) { throw $e; } return false; } $xml = $xml->contents; if (!$plugin->name) { $this->outputStr("first time update, found name \"" . $xml->name . "\"..."); if (Plugin::where('name', '=', $xml->name)->first()) { $this->outputStr(" already exists. skipping."); // this would be amazing to alert the administrators // of that. new Mailer; ? return false; } $firstTimeUpdate = true; } else { if ($plugin->name != $xml->name) { $this->outputStr(" requested name change to \"" . $xml->name . "\" ..."); if (Plugin::where('name', '=', $xml->name)->first()) { $this->outputStr(" but name already exists. skipping."); // this would be amazing to alert the administrators // of that. new Mailer; ? return false; } } $firstTimeUpdate = false; $this->outputStr("\"" . $plugin->name . "\""); } $this->outputStr(" going to be synced with xml ..."); $this->triggerPluginXmlStateChange($plugin, 'passing', true, in_array('alert_plugin_team_on_xml_state_change', $subtasks)); // Updating basic infos $plugin->logo_url = $xml->logo; $plugin->name = $xml->name; $plugin->key = $xml->key; $plugin->homepage_url = $xml->homepage; $plugin->download_url = $xml->download; $plugin->issues_url = $xml->issues; $plugin->readme_url = $xml->readme; $plugin->license = $xml->license; // reading descriptions, // mapping type=>lang relation to lang=>type $descriptions = []; foreach ($xml->description->children() as $type => $descs) { if (in_array($type, ['short', 'long'])) { foreach ($descs->children() as $_lang => $content) { $descriptions[$_lang][$type] = (string) $content; } } } // Delete current descriptions $plugin->descriptions()->delete(); // Refreshing descriptions foreach ($descriptions as $lang => $_type) { $description = new PluginDescription(); $description->lang = $lang; foreach ($_type as $type => $html) { $description[$type . '_description'] = $html; } $description->plugin_id = $plugin->id; $description->save(); } // Refreshing authors $plugin->authors()->detach(); $clean_authors = []; foreach ($xml->authors->children() as $author) { $_clean_authors = Author::fixKnownDuplicates((string) $author); foreach ($_clean_authors as $author) { $clean_authors[] = $author; } } foreach ($clean_authors as $_author) { $found = Author::where('name', '=', $_author)->first(); if (sizeof($found) < 1) { $author = new Author(); $author->name = $_author; $author->save(); } else { $author = $found; } if (!$plugin->authors->find($author->id)) { $plugin->authors()->attach($author); } } // Refreshing versions $plugin->versions()->delete(); foreach ($xml->versions->children() as $_version) { foreach ($_version->compatibility as $compat) { $version = new PluginVersion(); $version->num = trim((string) $_version->num); $version->compatibility = trim((string) $compat); $version->plugin_id = $plugin->id; $version->save(); } } // Refreshing screenshots if (isset($xml->screenshots)) { $plugin->screenshots()->delete(); foreach ($xml->screenshots->children() as $url) { $screenshot = new PluginScreenshot(); $screenshot->url = (string) $url; $screenshot->plugin_id = $plugin->id; $screenshot->save(); } } // Reassociating plugin to tags $plugin->tags()->detach(); foreach ($xml->tags->children() as $lang => $tags) { foreach ($tags->children() as $_tag) { $found = Tag::where('tag', '=', (string) $_tag)->where('lang', '=', $lang)->first(); if (sizeof($found) < 1) { $tag = new Tag(); $tag->tag = (string) $_tag; $tag->lang = $lang; $tag->key = Tool::getUrlSlug((string) $_tag); $tag->save(); } else { $tag = $found; } $tag->plugins()->attach($plugin); } } // Reassociating plugin to langs $plugin->langs()->detach(); foreach ($xml->langs->children() as $lang) { $lang = (string) $lang; $_lang = PluginLang::where('lang', '=', $lang)->first(); if (!$_lang) { $_lang = new PluginLang(); $_lang->lang = $lang; $_lang->save(); } $_lang->plugins()->attach($plugin); } // new crc $plugin->xml_crc = $crc; // new updated timestamp $plugin->date_updated = \Illuminate\Database\Capsule\Manager::raw('NOW()'); $plugin->save(); $this->outputStr(" OK."); if (in_array('alert_watchers', $subtasks)) { $this->alertWatchers($plugin); $this->outputStr("\n"); } else { $this->outputStr("\n"); } }
use API\Core\Tool; use Illuminate\Database\Capsule\Manager as DB; $all = function () use($app) { $all = Tool::paginateCollection(\API\Model\Author::mostActive()->contributorsOnly()); Tool::endWithJson($all); }; $top = function () use($app) { $top = \API\Model\Author::mostActive(10)->get(); Tool::endWithJson($top); }; $single = function ($id) use($app) { $single = \API\Model\Author::withPluginCount()->find($id); Tool::endWithJson($single); }; $author_plugins = function ($id) use($app) { $author_plugins = \API\Model\Author::find($id); if (!$author_plugins) { return Tool::endWithJson(["error" => "Cannot find author"]); } Tool::endWithJson(Tool::paginateCollection(\API\Model\Plugin::with('versions', 'authors')->short()->withDownloads()->withAverageNote()->descWithLang(Tool::getRequestLang())->whereAuthor($author_plugins->id))); }; // HTTP REST Map $app->get('/author', $all); $app->get('/author/top', $top); $app->get('/author/:id', $single); $app->get('/author/:id/plugin', $author_plugins); $app->options('/author', function () { }); $app->options('/author/top', function () { }); $app->options('/author/:id', function ($id) {
$claim_authorship = Tool::makeEndpoint(function () use($app, $resourceServer) { OAuthHelper::needsScopes(['user']); $body = Tool::getBody(); $user_id = $resourceServer->getAccessToken()->getSession()->getOwnerId(); $user = User::where('id', '=', $user_id)->first(); // We ensure the recatpcha_response // is provided as a string if (!isset($body->recaptcha_response) || gettype($body->recaptcha_response) != 'string') { throw new InvalidRecaptcha(); } // and we verify it with recaptcha Tool::assertRecaptchaValid($body->recaptcha_response); if (!isset($body->author) || gettype($body->author) != 'string' || strlen($body->author) > 90) { throw new InvalidField('author'); } if (!($author = Author::where('name', '=', $body->author)->first())) { throw new ResourceNotFound('Author', $body->author); } $mailer = new Mailer(); $mailer->sendMail('authorship_claim.html', Tool::getConfig()['msg_alerts']['local_admins'], 'User ' . $user->username . ' claim authorship', ['user' => $user->toArray(), 'author' => $author->toArray()]); $app->halt(200); }); // HTTP REST Map $app->get('/author', $all); $app->get('/author/top', $top); $app->get('/author/:id', $single); $app->get('/author/:id/plugin', $author_plugins); $app->post('/claimauthorship', $claim_authorship); $app->options('/author', function () { }); $app->options('/author/top', function () {
public function updatePlugin($plugin, $xml, $new_crc) { if (strlen($plugin->name) == 0) { echo "first time update, found name \"" . $xml->name . "\"..."; $firstTimeUpdate = true; } else { if ($plugin->name != $xml->name) { echo "\"" . $plugin->name . "\" going to become \"" . $xml->name . "\" ..."; } else { echo "\"" . $xml->name . "\" going to be updated ..."; } } // Updating basic infos $plugin->logo_url = $xml->logo; $plugin->name = $xml->name; $plugin->key = $xml->key; $plugin->homepage_url = $xml->homepage; $plugin->download_url = $xml->download; $plugin->issues_url = $xml->issues; $plugin->readme_url = $xml->readme; $plugin->license = $xml->license; // reading descriptions, // mapping type=>lang relation to lang=>type $descriptions = []; foreach ($xml->description->children() as $type => $descs) { if (in_array($type, ['short', 'long'])) { foreach ($descs->children() as $_lang => $content) { $descriptions[$_lang][$type] = (string) $content; } } } // Delete current descriptions $plugin->descriptions()->delete(); // Refreshing descriptions foreach ($descriptions as $lang => $_type) { $description = new PluginDescription(); $description->lang = $lang; foreach ($_type as $type => $html) { $description[$type . '_description'] = $html; } $description->plugin_id = $plugin->id; $description->save(); } // Refreshing authors $plugin->authors()->detach(); $clean_authors = []; foreach ($xml->authors->children() as $author) { $_clean_authors = $this->fixParseAuthors((string) $author); foreach ($_clean_authors as $author) { $clean_authors[] = $author; } } foreach ($clean_authors as $_author) { $found = Author::where('name', '=', $_author)->first(); if (sizeof($found) < 1) { $author = new Author(); $author->name = $_author; $author->save(); } else { $author = $found; } if (!$plugin->authors->find($author->id)) { $plugin->authors()->attach($author); } } // Refreshing versions $plugin->versions()->delete(); foreach ($xml->versions->children() as $_version) { foreach ($_version->compatibility as $compat) { $version = new PluginVersion(); $version->num = trim((string) $_version->num); $version->compatibility = trim((string) $compat); $version->plugin_id = $plugin->id; $version->save(); } } // Refreshing screenshots if (isset($xml->screenshots)) { $plugin->screenshots()->delete(); foreach ($xml->screenshots->children() as $url) { $screenshot = new PluginScreenshot(); $screenshot->url = (string) $url; $screenshot->plugin_id = $plugin->id; $screenshot->save(); } } // Reassociating plugin to tags $plugin->tags()->detach(); foreach ($xml->tags->children() as $lang => $tags) { foreach ($tags->children() as $_tag) { $found = Tag::where('tag', '=', (string) $_tag)->where('lang', '=', $lang)->first(); if (sizeof($found) < 1) { $tag = new Tag(); $tag->tag = (string) $_tag; $tag->lang = $lang; $tag->key = Tool::getUrlSlug((string) $_tag); $tag->save(); } else { $tag = $found; } $tag->plugins()->attach($plugin); } } // new crc $plugin->xml_crc = $new_crc; // new timestamp if (!isset($firstTimeUpdate)) { $plugin->date_updated = DB::raw('NOW()'); } $plugin->save(); echo " OK\n"; }
} // Verifying that at least the authors we knew // are present in the new xml, to do that, // we compare what is in the xml $_xml_authors = (array) $xml->authors; $_xml_authors = $_xml_authors['author']; // simplexml API returns a string if there // is a single 'author' node in authors // here if (gettype($_xml_authors) == 'string') { $_xml_authors = [$_xml_authors]; } $xml_authors = []; // while applying the fixKnownDuplicates patch foreach ($_xml_authors as $author) { $fkd_detected_authors = Author::fixKnownDuplicates($author); $xml_authors = array_merge($xml_authors, $fkd_detected_authors); } // with what we already had $authors = $plugin->authors()->get(); foreach ($authors as $author) { if (!in_array($author->name, $xml_authors)) { throw new DifferentPluginSignature('authors'); } } $plugin->xml_url = $body->xml_url; $plugin->save(); } $app->halt(200); }); $plugin_view_permissions = Tool::makeEndpoint(function ($key) use($app) {