Skip to content
Extraits de code Groupes Projets
Valider b67827bb rédigé par Thomas Steur's avatar Thomas Steur
Parcourir les fichiers

refs #4053 cleanup code of marketplace integration

parent 4620a36a
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
...@@ -37,13 +37,8 @@ class Controller extends \Piwik\Controller\Admin ...@@ -37,13 +37,8 @@ class Controller extends \Piwik\Controller\Admin
$view = $this->configureView('@CorePluginsAdmin/' . $template); $view = $this->configureView('@CorePluginsAdmin/' . $template);
$pluginName = Common::getRequestVar('pluginName', '', 'string'); $pluginName = Common::getRequestVar('pluginName', null, 'string');
$pluginName = strip_tags($pluginName); $nonce = Common::getRequestVar('nonce', null, 'string');
$nonce = Common::getRequestVar('nonce', '', 'string');
if (empty($pluginName)) {
throw new \Exception('Plugin parameter is missing');
}
$view->plugin = array('name' => $pluginName); $view->plugin = array('name' => $pluginName);
...@@ -58,7 +53,7 @@ class Controller extends \Piwik\Controller\Admin ...@@ -58,7 +53,7 @@ class Controller extends \Piwik\Controller\Admin
$pluginInstaller = new PluginInstaller($pluginName); $pluginInstaller = new PluginInstaller($pluginName);
$pluginInstaller->installOrUpdatePluginFromMarketplace(); $pluginInstaller->installOrUpdatePluginFromMarketplace();
} catch (PluginInstallerException $e) { } catch (\Exception $e) {
$view->errorMessage = $e->getMessage(); $view->errorMessage = $e->getMessage();
return $view; return $view;
} }
...@@ -85,12 +80,7 @@ class Controller extends \Piwik\Controller\Admin ...@@ -85,12 +80,7 @@ class Controller extends \Piwik\Controller\Admin
public function pluginDetails() public function pluginDetails()
{ {
$pluginName = Common::getRequestVar('pluginName', '', 'string'); $pluginName = Common::getRequestVar('pluginName', null, 'string');
$pluginName = strip_tags($pluginName);
if (empty($pluginName)) {
return;
}
$view = $this->configureView('@CorePluginsAdmin/pluginDetails'); $view = $this->configureView('@CorePluginsAdmin/pluginDetails');
...@@ -107,7 +97,6 @@ class Controller extends \Piwik\Controller\Admin ...@@ -107,7 +97,6 @@ class Controller extends \Piwik\Controller\Admin
private function createBrowsePluginsOrThemesView($template, $themesOnly) private function createBrowsePluginsOrThemesView($template, $themesOnly)
{ {
$query = Common::getRequestVar('query', '', 'string', $_POST); $query = Common::getRequestVar('query', '', 'string', $_POST);
$query = strip_tags($query);
$sort = Common::getRequestVar('sort', $this->defaultSortMethod, 'string'); $sort = Common::getRequestVar('sort', $this->defaultSortMethod, 'string');
if (!in_array($sort, $this->validSortMethods)) { if (!in_array($sort, $this->validSortMethods)) {
...@@ -263,13 +252,8 @@ class Controller extends \Piwik\Controller\Admin ...@@ -263,13 +252,8 @@ class Controller extends \Piwik\Controller\Admin
{ {
Piwik::checkUserIsSuperUser(); Piwik::checkUserIsSuperUser();
$pluginName = Common::getRequestVar('pluginName', '', 'string'); $pluginName = Common::getRequestVar('pluginName', null, 'string');
$pluginName = strip_tags($pluginName); $nonce = Common::getRequestVar('nonce', null, 'string');
$nonce = Common::getRequestVar('nonce', '', 'string');
if (empty($pluginName)) {
throw new \Exception('Plugin parameter is missing');
}
if (!Nonce::verifyNonce('CorePluginsAdmin.activatePlugin', $nonce)) { if (!Nonce::verifyNonce('CorePluginsAdmin.activatePlugin', $nonce)) {
throw new \Exception(Piwik_Translate('General_ExceptionNonceMismatch')); throw new \Exception(Piwik_Translate('General_ExceptionNonceMismatch'));
...@@ -283,11 +267,12 @@ class Controller extends \Piwik\Controller\Admin ...@@ -283,11 +267,12 @@ class Controller extends \Piwik\Controller\Admin
$params = array('activated' => 1, 'pluginName' => $pluginName); $params = array('activated' => 1, 'pluginName' => $pluginName);
$plugin = PluginsManager::getInstance()->loadPlugin($pluginName); $plugin = PluginsManager::getInstance()->loadPlugin($pluginName);
$actionToRedirect = 'plugins';
if ($plugin->isTheme()) { if ($plugin->isTheme()) {
$this->redirectToIndex('CorePluginsAdmin', 'themes', null, null, null, $params); $actionToRedirect = 'themes';
} else {
$this->redirectToIndex('CorePluginsAdmin', 'plugins', null, null, null, $params);
} }
$this->redirectToIndex('CorePluginsAdmin', $actionToRedirect, null, null, null, $params);
} }
} }
......
...@@ -47,10 +47,10 @@ class Marketplace ...@@ -47,10 +47,10 @@ class Marketplace
$dateFormat = Piwik_Translate('CoreHome_ShortDateFormatWithYear'); $dateFormat = Piwik_Translate('CoreHome_ShortDateFormatWithYear');
foreach ($plugins as $plugin) { foreach ($plugins as &$plugin) {
$plugin->canBeUpdated = $this->hasPluginUpdate($plugin); $plugin['canBeUpdated'] = $this->hasPluginUpdate($plugin);
$plugin->isInstalled = PluginsManager::getInstance()->isPluginLoaded($plugin->name); $plugin['isInstalled'] = PluginsManager::getInstance()->isPluginLoaded($plugin['name']);
$plugin->lastUpdated = Date::factory($plugin->lastUpdated)->getLocalized($dateFormat); $plugin['lastUpdated'] = Date::factory($plugin['lastUpdated'])->getLocalized($dateFormat);
} }
return $plugins; return $plugins;
...@@ -58,14 +58,14 @@ class Marketplace ...@@ -58,14 +58,14 @@ class Marketplace
private function hasPluginUpdate($plugin) private function hasPluginUpdate($plugin)
{ {
if (empty($plugin->name)) { if (empty($plugin['name'])) {
return false; return false;
} }
$pluginsHavingUpdate = $this->getPluginsHavingUpdate($plugin->isTheme); $pluginsHavingUpdate = $this->getPluginsHavingUpdate($plugin['isTheme']);
foreach ($pluginsHavingUpdate as $pluginHavingUpdate) { foreach ($pluginsHavingUpdate as $pluginHavingUpdate) {
if ($plugin->name == $pluginHavingUpdate->name) { if ($plugin['name'] == $pluginHavingUpdate['name']) {
return true; return true;
} }
} }
...@@ -89,12 +89,14 @@ class Marketplace ...@@ -89,12 +89,14 @@ class Marketplace
$pluginsHavingUpdate = array(); $pluginsHavingUpdate = array();
} }
foreach ($pluginsHavingUpdate as $updatePlugin) { foreach ($pluginsHavingUpdate as &$updatePlugin) {
foreach ($loadedPlugins as $loadedPlugin) { foreach ($loadedPlugins as $loadedPlugin) {
if (!empty($updatePlugin->name) && $loadedPlugin->getPluginName() == $updatePlugin->name) { if (!empty($updatePlugin['name'])
$updatePlugin->currentVersion = $loadedPlugin->getVersion(); && $loadedPlugin->getPluginName() == $updatePlugin['name']) {
$updatePlugin->isActivated = $pluginManager->isPluginActivated($updatePlugin->name);
$updatePlugin['currentVersion'] = $loadedPlugin->getVersion();
$updatePlugin['isActivated'] = $pluginManager->isPluginActivated($updatePlugin['name']);
break; break;
} }
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
namespace Piwik\Plugins\CorePluginsAdmin; namespace Piwik\Plugins\CorePluginsAdmin;
use Piwik\CacheFile; use Piwik\CacheFile;
use Piwik\Http; use Piwik\Http;
use Piwik\PluginsManager;
/** /**
* *
...@@ -18,6 +19,9 @@ use Piwik\Http; ...@@ -18,6 +19,9 @@ use Piwik\Http;
*/ */
class MarketplaceApiClient class MarketplaceApiClient
{ {
const CACHE_TIMEOUT_IN_SECONDS = 1200;
const HTTP_REQUEST_TIMEOUT = 30;
private $domain = 'http://plugins.piwik.org'; private $domain = 'http://plugins.piwik.org';
/** /**
...@@ -27,7 +31,7 @@ class MarketplaceApiClient ...@@ -27,7 +31,7 @@ class MarketplaceApiClient
public function __construct() public function __construct()
{ {
$this->cache = new CacheFile('marketplace', 1200); $this->cache = new CacheFile('marketplace', self::CACHE_TIMEOUT_IN_SECONDS);
} }
public static function clearAllCacheEntries() public static function clearAllCacheEntries()
...@@ -45,16 +49,13 @@ class MarketplaceApiClient ...@@ -45,16 +49,13 @@ class MarketplaceApiClient
public function download($pluginOrThemeName, $target) public function download($pluginOrThemeName, $target)
{ {
$plugin = $this->getPluginInfo($pluginOrThemeName); $downloadUrl = $this->getDownloadUrl($pluginOrThemeName);
if (empty($plugin->versions)) { if (empty($downloadUrl)) {
return false; return false;
} }
$latestVersion = array_pop($plugin->versions); $success = Http::fetchRemoteFile($downloadUrl, $target, 0, static::HTTP_REQUEST_TIMEOUT);
$downloadUrl = $latestVersion->download;
$success = Http::fetchRemoteFile($this->domain . $downloadUrl, $target);
return $success; return $success;
} }
...@@ -68,7 +69,10 @@ class MarketplaceApiClient ...@@ -68,7 +69,10 @@ class MarketplaceApiClient
$params = array(); $params = array();
foreach ($plugins as $plugin) { foreach ($plugins as $plugin) {
$params[] = array('name' => $plugin->getPluginName(), 'version' => $plugin->getVersion()); $pluginName = $plugin->getPluginName();
if (!PluginsManager::getInstance()->isPluginBundledWithCore($pluginName)) {
$params[] = array('name' => $plugin->getPluginName(), 'version' => $plugin->getVersion());
}
} }
$params = array('plugins' => $params); $params = array('plugins' => $params);
...@@ -94,9 +98,9 @@ class MarketplaceApiClient ...@@ -94,9 +98,9 @@ class MarketplaceApiClient
$pluginDetails = array(); $pluginDetails = array();
foreach ($hasUpdates as $pluginHavingUpdate) { foreach ($hasUpdates as $pluginHavingUpdate) {
$plugin = $this->getPluginInfo($pluginHavingUpdate->name); $plugin = $this->getPluginInfo($pluginHavingUpdate['name']);
if (!empty($plugin->isTheme) == $themesOnly) { if (!empty($plugin['isTheme']) == $themesOnly) {
$pluginDetails[] = $plugin; $pluginDetails[] = $plugin;
} }
} }
...@@ -108,8 +112,8 @@ class MarketplaceApiClient ...@@ -108,8 +112,8 @@ class MarketplaceApiClient
{ {
$response = $this->fetch('plugins', array('keywords' => $keywords, 'query' => $query, 'sort' => $sort)); $response = $this->fetch('plugins', array('keywords' => $keywords, 'query' => $query, 'sort' => $sort));
if (!empty($response->plugins)) { if (!empty($response['plugins'])) {
return $response->plugins; return $response['plugins'];
} }
return array(); return array();
...@@ -119,8 +123,8 @@ class MarketplaceApiClient ...@@ -119,8 +123,8 @@ class MarketplaceApiClient
{ {
$response = $this->fetch('themes', array('keywords' => $keywords, 'query' => $query, 'sort' => $sort)); $response = $this->fetch('themes', array('keywords' => $keywords, 'query' => $query, 'sort' => $sort));
if (!empty($response->plugins)) { if (!empty($response['plugins'])) {
return $response->plugins; return $response['plugins'];
} }
return array(); return array();
...@@ -128,24 +132,27 @@ class MarketplaceApiClient ...@@ -128,24 +132,27 @@ class MarketplaceApiClient
private function fetch($action, $params) private function fetch($action, $params)
{ {
ksort($params);
$query = http_build_query($params); $query = http_build_query($params);
$result = $this->getCachedResult($action, $query); $result = $this->getCachedResult($action, $query);
if (false === $result) { if (false === $result) {
$endpoint = $this->domain . '/api/1.0/'; $endpoint = $this->domain . '/api/1.0/';
$url = sprintf('%s%s?%s', $endpoint, $action, $query); $url = sprintf('%s%s?%s', $endpoint, $action, $query);
$result = Http::sendHttpRequest($url, 5); $response = Http::sendHttpRequest($url, static::HTTP_REQUEST_TIMEOUT);
$this->cacheResult($action, $query, $result); $result = json_decode($response, true);
}
$result = json_decode($result); if (is_null($result)) {
$message = sprintf('There was an error reading the response from the Marketplace: %s. Please try again later.',
substr($response, 0, 50));
throw new MarketplaceApiException($message);
}
if (is_null($result)) { if (!empty($result['error'])) {
throw new MarketplaceApiException('Failure during communication with marketplace, unable to read response'); throw new MarketplaceApiException($result['error']);
} }
if (!empty($result->error)) { $this->cacheResult($action, $query, $result);
throw new MarketplaceApiException($result->error);
} }
return $result; return $result;
...@@ -170,4 +177,23 @@ class MarketplaceApiClient ...@@ -170,4 +177,23 @@ class MarketplaceApiClient
return sprintf('api.1.0.%s.%s', str_replace('/', '.', $action), md5($query)); return sprintf('api.1.0.%s.%s', str_replace('/', '.', $action), md5($query));
} }
/**
* @param $pluginOrThemeName
* @throws MarketplaceApiException
* @return string
*/
public function getDownloadUrl($pluginOrThemeName)
{
$plugin = $this->getPluginInfo($pluginOrThemeName);
if (empty($plugin['versions'])) {
throw new MarketplaceApiException('Plugin has no versions.');
}
$latestVersion = array_pop($plugin['versions']);
$downloadUrl = $latestVersion['download'];
return $this->domain . $downloadUrl;
}
} }
...@@ -35,6 +35,7 @@ class PluginInstaller ...@@ -35,6 +35,7 @@ class PluginInstaller
$tmpPluginFolder = PIWIK_USER_PATH . self::PATH_TO_DOWNLOAD . $this->pluginName; $tmpPluginFolder = PIWIK_USER_PATH . self::PATH_TO_DOWNLOAD . $this->pluginName;
$this->makeSureFoldersAreWritable(); $this->makeSureFoldersAreWritable();
$this->makeSurePluginNameIsValid();
$this->downloadPluginFromMarketplace($tmpPluginZip); $this->downloadPluginFromMarketplace($tmpPluginZip);
$this->extractPluginFiles($tmpPluginZip, $tmpPluginFolder); $this->extractPluginFiles($tmpPluginZip, $tmpPluginFolder);
$this->makeSurePluginJsonExists($tmpPluginFolder); $this->makeSurePluginJsonExists($tmpPluginFolder);
...@@ -53,21 +54,21 @@ class PluginInstaller ...@@ -53,21 +54,21 @@ class PluginInstaller
{ {
$this->removeFileIfExists($pluginZipTargetFile); $this->removeFileIfExists($pluginZipTargetFile);
try { $marketplace = new MarketplaceApiClient();
$marketplace = new MarketplaceApiClient();
$pluginDetails = $marketplace->getPluginInfo($this->pluginName);
} catch (\Exception $e) {
throw new PluginInstallerException($e->getMessage());
}
if (empty($pluginDetails)) {
throw new PluginInstallerException('A plugin with this name does not exist');
}
try { try {
$marketplace->download($this->pluginName, $pluginZipTargetFile); $marketplace->download($this->pluginName, $pluginZipTargetFile);
} catch (\Exception $e) { } catch (\Exception $e) {
throw new PluginInstallerException('Failed to download plugin: ' . $e->getMessage());
try {
$downloadUrl = $marketplace->getDownloadUrl($this->pluginName);
$errorMessage = sprintf('Failed to download plugin from %s: %s', $downloadUrl, $e->getMessage());
} catch (\Exception $ex) {
$errorMessage = sprintf('Failed to download plugin: %s', $e->getMessage());
}
throw new PluginInstallerException($errorMessage);
} }
} }
...@@ -94,7 +95,7 @@ class PluginInstaller ...@@ -94,7 +95,7 @@ class PluginInstaller
private function makeSurePluginJsonExists($tmpPluginFolder) private function makeSurePluginJsonExists($tmpPluginFolder)
{ {
if (!file_exists($tmpPluginFolder . DIRECTORY_SEPARATOR . $this->pluginName . DIRECTORY_SEPARATOR . 'plugin.json')) { if (!file_exists($tmpPluginFolder . DIRECTORY_SEPARATOR . $this->pluginName . DIRECTORY_SEPARATOR . 'plugin.json')) {
throw new PluginInstallerException('Plugin is not valid, missing plugin.json'); throw new PluginInstallerException('Plugin is not valid, it is missing the plugin.json file.');
} }
} }
...@@ -112,9 +113,7 @@ class PluginInstaller ...@@ -112,9 +113,7 @@ class PluginInstaller
*/ */
private function removeFolderIfExists($pathExtracted) private function removeFolderIfExists($pathExtracted)
{ {
if (file_exists($pathExtracted)) { Filesystem::unlinkRecursive($pathExtracted, true);
Filesystem::unlinkRecursive($pathExtracted, true);
}
} }
/** /**
...@@ -127,4 +126,21 @@ class PluginInstaller ...@@ -127,4 +126,21 @@ class PluginInstaller
} }
} }
/**
* @throws PluginInstallerException
*/
private function makeSurePluginNameIsValid()
{
try {
$marketplace = new MarketplaceApiClient();
$pluginDetails = $marketplace->getPluginInfo($this->pluginName);
} catch (\Exception $e) {
throw new PluginInstallerException($e->getMessage());
}
if (empty($pluginDetails)) {
throw new PluginInstallerException('This plugin was not found in the Marketplace.');
}
}
} }
...@@ -18,30 +18,29 @@ ...@@ -18,30 +18,29 @@
<p>Unzipping theme</p> <p>Unzipping theme</p>
<p>Installing theme</p>
<p>You have successfully installed the theme {{ plugin.name }} {{ plugin.latestVersion }}.</p> <p>You have successfully installed the theme {{ plugin.name }} {{ plugin.latestVersion }}.</p>
<p><strong><a href="{{ linkTo({'action': 'activate', 'pluginName': plugin.name, 'nonce': nonce}) }}">Activate Theme</a></strong> <p><strong><a href="{{ linkTo({'action': 'activate', 'pluginName': plugin.name, 'nonce': nonce}) }}">Activate Theme</a></strong>
|
<a href="{{ linkTo({'action': 'extend'}) }}">Back to Extend Piwik</a></p>
{% else %} {% else %}
<p>Downloading plugin from Marketplace</p> <p>Downloading plugin from Marketplace</p>
<p>Unzipping plugin</p> <p>Unzipping plugin</p>
<p>Installing plugin</p>
<p>You have successfully installed the Plugin {{ plugin.name }} {{ plugin.latestVersion }}.</p> <p>You have successfully installed the Plugin {{ plugin.name }} {{ plugin.latestVersion }}.</p>
<p><strong><a href="{{ linkTo({'action': 'activate', 'pluginName': plugin.name, 'nonce': nonce}) }}">Activate Plugin</a></strong> <p><strong><a href="{{ linkTo({'action': 'activate', 'pluginName': plugin.name, 'nonce': nonce}) }}">Activate Plugin</a></strong>
|
<a href="{{ linkTo({'action': 'extend'}) }}">Back to Extend Piwik</a></p>
{% endif %} {% endif %}
</div> </div>
|
<a href="{{ linkTo({'action': 'extend'}) }}">Back to Extend Piwik</a></p>
{% endif %} {% endif %}
</div> </div>
......
<hr class="metadataSeparator"> <hr class="metadataSeparator"/>
<ul class="metadata"> <ul class="metadata">
<li>{{ 'CorePluginsAdmin_Version'|translate }}: <strong>{{ plugin.latestVersion }}</strong></li> <li>{{ 'CorePluginsAdmin_Version'|translate }}: <strong>{{ plugin.latestVersion }}</strong></li>
<li class="even">Updated: <strong>{{ plugin.lastUpdated }}</strong></li> <li class="even">Updated: <strong>{{ plugin.lastUpdated }}</strong></li>
......
{% if not isSuperUser %} {% if isSuperUser %}
{% elseif plugin.canBeUpdated %} {% if plugin.canBeUpdated %}
<a class="update" <a class="update"
href="{{ linkTo({'action':'updatePlugin', 'pluginName': plugin.name, 'nonce': updateNonce}) }}" href="{{ linkTo({'action':'updatePlugin', 'pluginName': plugin.name, 'nonce': updateNonce}) }}"
>Update</a> >Update</a>
{% elseif plugin.isInstalled %} {% elseif plugin.isInstalled %}
<span class="install">Installed</span> <span class="install">Installed</span>
{% else %} {% else %}
<a href="{{ linkTo({'action': 'installPlugin', 'pluginName': plugin.name, 'nonce': installNonce}) }}" <a href="{{ linkTo({'action': 'installPlugin', 'pluginName': plugin.name, 'nonce': installNonce}) }}"
class="install">Install</a> class="install">Install</a>
{% endif %}
{% endif %} {% endif %}
<h3 class="header"> <h3 class="header" title="Click for more details">
<a href="javascript:return;" data-pluginName="{{ plugin.name }}" class="more">{{ plugin.name }}</a> <a href="javascript:return;" data-pluginName="{{ plugin.name }}" class="more">{{ plugin.name }}</a>
</h3> </h3>
<p class="description">{{ plugin.description }} <p class="description">{{ plugin.description }}
<br /> <br />
<a href="javascript:return;" data-pluginName="{{ plugin.name }}" class="more">&gt;&gt; more</a> <a href="javascript:return;" title="Click for more details" data-pluginName="{{ plugin.name }}" class="more">&gt;&gt; more</a>
</p> </p>
{% if plugin.canBeUpdated %} {% if plugin.canBeUpdated %}
<p class="updateAvailableNotice">You can update this plugin to version {{ plugin.latestVersion }}</p> <p class="updateAvailableNotice">You can update this plugin to version {{ plugin.latestVersion }}</p>
......
...@@ -6,12 +6,14 @@ ...@@ -6,12 +6,14 @@
<div style="max-width:980px;"> <div style="max-width:980px;">
{% if activatedPluginName %} {% if activatedPluginName %}
<div id="feedback-success">You have successfully activated plugin {{ activatedPluginName }}</div> <div id="feedback-success"><strong>Well done!</strong> You have successfully activated plugin {{ activatedPluginName }}</div>
{% endif %} {% endif %}
{% if pluginsHavingUpdate|length %} {% if pluginsHavingUpdate|length %}
<h2>{{ pluginsHavingUpdate|length }} Update(s) available</h2> <h2>{{ pluginsHavingUpdate|length }} Update(s) available</h2>
<p>{{ 'Update your plugins now to benefit from the latest improvements.'|translate }}</p>
{{ plugins.tablePluginUpdates(pluginsHavingUpdate, updateNonce, activateNonce, 0) }} {{ plugins.tablePluginUpdates(pluginsHavingUpdate, updateNonce, activateNonce, 0) }}
{% endif %} {% endif %}
......
{% if not isSuperUser %} {% if isSuperUser %}
{% elseif plugin.canBeUpdated %} {% if plugin.canBeUpdated %}
<a href="{{ linkTo({'action':'updatePlugin', 'pluginName': plugin.name, 'nonce': updateNonce}) }}" <a href="{{ linkTo({'action':'updatePlugin', 'pluginName': plugin.name, 'nonce': updateNonce}) }}"
class="update" class="update"
>{{ 'CoreUpdater_UpdateTitle'|translate }}</a> >{{ 'CoreUpdater_UpdateTitle'|translate }}</a>
{% elseif plugin.isInstalled %} {% elseif plugin.isInstalled %}
<span class="install">{{ 'General_Installed'|translate }}</span> <span class="install">{{ 'General_Installed'|translate }}</span>
{% else %} {% else %}
<a href="{{ linkTo({'action': 'installPlugin', 'pluginName': plugin.name, 'nonce': installNonce}) }}" <a href="{{ linkTo({'action': 'installPlugin', 'pluginName': plugin.name, 'nonce': installNonce}) }}"
class="install">Install</a> class="install">Install</a>
{% endif %}
{% endif %} {% endif %}
<h3 class="header"> <h3 class="header" title="Click for more details">
<a href="javascript:return;" data-pluginName="{{ plugin.name }}" class="more">{{ plugin.name }}</a> <a href="javascript:return;" data-pluginName="{{ plugin.name }}" class="more">{{ plugin.name }}</a>
</h3> </h3>
<p class="description">{{ plugin.description }}</p> <p class="description">{{ plugin.description }}</p>
<a href="javascript:return;" data-pluginName="{{ plugin.name }}" class="more"><img <a href="javascript:return;" data-pluginName="{{ plugin.name }}" class="more"><img title="Click for more details"
class="preview" src="{{ plugin.screenshots|first }}?w=250&h=250"/></a> class="preview" src="{{ plugin.screenshots|first }}?w=250&h=250"/></a>
{% if plugin.canBeUpdated %} {% if plugin.canBeUpdated %}
<p class="updateAvailableNotice">You can update this theme to version {{ plugin.latestVersion }}</p> <p class="updateAvailableNotice">You can update this theme to version {{ plugin.latestVersion }}</p>
{% endif %} {% endif %}
\ No newline at end of file
...@@ -6,12 +6,14 @@ ...@@ -6,12 +6,14 @@
<div style="max-width:980px;"> <div style="max-width:980px;">
{% if activatedPluginName %} {% if activatedPluginName %}
<div id="feedback-success">You have successfully activated plugin {{ activatedPluginName }}</div> <div id="feedback-success"><strong>Well done!</strong> You have successfully activated theme {{ activatedPluginName }}</div>
{% endif %} {% endif %}
{% if pluginsHavingUpdate|length %} {% if pluginsHavingUpdate|length %}
<h2>{{ pluginsHavingUpdate|length }} Update(s) available</h2> <h2>{{ pluginsHavingUpdate|length }} Update(s) available</h2>
<p>{{ 'Update your themes to enjoy the latest version.'|translate }}</p>
{{ plugins.tablePluginUpdates(pluginsHavingUpdate, updateNonce, true) }} {{ plugins.tablePluginUpdates(pluginsHavingUpdate, updateNonce, true) }}
{% endif %} {% endif %}
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter