mirror of
https://github.com/joomla-extensions/jedchecker.git
synced 2024-12-29 04:42:36 +00:00
Merge PR #120 into develop
This commit is contained in:
commit
055a9b1378
@ -45,12 +45,14 @@ COM_JEDCHECKER_INFO_XML_NAME_XML="The name tag in this file is: <b>%s</b>"
|
||||
COM_JEDCHECKER_INFO_XML_VERSION_XML="Version tag has the value: %s"
|
||||
COM_JEDCHECKER_INFO_XML_CREATIONDATE_XML="The creationDate tag has the value: %s"
|
||||
COM_JEDCHECKER_INFO_XML_NO_MANIFEST="No manifest file found"
|
||||
COM_JEDCHECKER_INFO_XML_NAME_MODULE_PLUGIN="Listing name ('%s') contains 'module' or 'plugin'"
|
||||
COM_JEDCHECKER_INFO_XML_NAME_RESERVED_KEYWORDS="Keywords such as module, plugin or template are considered reserved words and can't be used in the extension names ('%s')"
|
||||
COM_JEDCHECKER_INFO_XML_NAME_RESERVED_KEYWORDS="Keywords such as module, plugin or template are considered reserved words ('%2$s') and can't be used in the extension names ('%1$s')"
|
||||
COM_JEDCHECKER_INFO_XML_NAME_PREFIXED="Listing name ('%s') starts with extension type prefix"
|
||||
COM_JEDCHECKER_INFO_XML_NAME_VERSION="Version in name/title ('%s')"
|
||||
COM_JEDCHECKER_INFO_XML_NAME_JOOMLA="An extension name ('%s') can't start with the word 'Joomla'"
|
||||
COM_JEDCHECKER_INFO_XML_NAME_JOOMLA_DERIVATIVE="Extensions that use 'Joomla' or a derivative of Joomla in the extension name ('%s') need to be licensed by OSM"
|
||||
COM_JEDCHECKER_INFO_XML_URL_JOOMLA_DERIVATIVE="Domain names that use 'Joomla' or a derivative of Joomla ('%1$s') need to be licensed by OSM. Please, check your domain name is listed on the <a href='%2$s'>Joomla! Trademark Approval Registry</a> page."
|
||||
COM_JEDCHECKER_INFO_XML_NAME_JOOMLA_DERIVATIVE="Extensions that use 'Joomla' or a derivative of Joomla! in the extension name ('%s') need to be licensed by OSM"
|
||||
COM_JEDCHECKER_INFO_XML_NAME_NON_ASCII="Listing name ('%s') contains non-ASCII characters"
|
||||
COM_JEDCHECKER_INFO_XML_URL_JOOMLA_DERIVATIVE="Domain names that use 'Joomla' or a derivative of Joomla! ('%1$s') need to be licensed by OSM. Please, check your domain name is listed on the <a href='%2$s'>Joomla! Trademark Approval Registry</a> page."
|
||||
COM_JEDCHECKER_INFO_XML_NAME_TOO_LONG="Listing name ('%s') is too long, consider to shorten it"
|
||||
COM_JEDCHECKER_INFO_XML_NAME_ADMIN_MENU="The admin menu name '%1$s' isn't the same as the extension name '%2$s'"
|
||||
COM_JEDCHECKER_INFO_XML_NAME_PLUGIN_FORMAT="The name of the plugin ('%s') must comply with the JED naming conventions in the form '{Type} - {Extension Name}'"
|
||||
COM_JEDCHECKER_RULE_PH1="PHP Headers missing GPL License Notice"
|
||||
|
@ -16,6 +16,9 @@ defined('_JEXEC') or die('Restricted access');
|
||||
// Include the rule base class
|
||||
require_once JPATH_COMPONENT_ADMINISTRATOR . '/models/rule.php';
|
||||
|
||||
// Include the helper class
|
||||
require_once JPATH_COMPONENT_ADMINISTRATOR . '/libraries/helper.php';
|
||||
|
||||
|
||||
/**
|
||||
* class JedcheckerRulesXMLinfo
|
||||
@ -47,6 +50,15 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule
|
||||
*/
|
||||
protected $description = 'COM_JEDCHECKER_INFO_XML_DESC';
|
||||
|
||||
/**
|
||||
* List of JED extension types
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $jedTypes = array(
|
||||
'component', 'module', 'package', 'plugin'
|
||||
);
|
||||
|
||||
/**
|
||||
* Mapping of the plugin title prefix to the plugin group
|
||||
*
|
||||
@ -67,17 +79,24 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule
|
||||
public function check()
|
||||
{
|
||||
// Find all XML files of the extension
|
||||
$files = JFolder::files($this->basedir, '\.xml$', true, true);
|
||||
$files = JEDCheckerHelper::findManifests($this->basedir);
|
||||
|
||||
$manifestFound = false;
|
||||
|
||||
// Iterate through all the xml files
|
||||
foreach ($files as $file)
|
||||
if (count($files))
|
||||
{
|
||||
// Try to find the license
|
||||
if ($this->find($file))
|
||||
$topLevelDepth = substr_count($files[0], '/');
|
||||
|
||||
// Iterate through all the xml files
|
||||
foreach ($files as $file)
|
||||
{
|
||||
$manifestFound = true;
|
||||
$isTopLevel = substr_count($file, '/') === $topLevelDepth;
|
||||
|
||||
// Try to find the license
|
||||
if ($this->find($file, $isTopLevel))
|
||||
{
|
||||
$manifestFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,11 +109,12 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule
|
||||
/**
|
||||
* Reads a file and searches for the license
|
||||
*
|
||||
* @param string $file - The path to the file
|
||||
* @param string $file - The path to the file
|
||||
* @param bool $isTopLevel - Is the file located in the top-level manifests directory?
|
||||
*
|
||||
* @return boolean True if the manifest file was found, otherwise False.
|
||||
*/
|
||||
protected function find($file)
|
||||
protected function find($file, $isTopLevel)
|
||||
{
|
||||
$xml = JFactory::getXml($file);
|
||||
|
||||
@ -120,39 +140,137 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule
|
||||
// Get extension type
|
||||
$type = (string) $xml['type'];
|
||||
|
||||
// Get extension's element name (simulates work of Joomla's installer)
|
||||
// Load the language of the extension (if any)
|
||||
$this->loadExtensionLanguage($xml, dirname($file));
|
||||
|
||||
// Firstly, check for <element> node
|
||||
if (isset($xml->element))
|
||||
{
|
||||
$extension = (string) $xml->element;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, use <name> node or plugin/module attribute in the <files> section
|
||||
$extension = (string) $xml->name;
|
||||
// Get the real extension's name now that the language has been loaded
|
||||
$lang = JFactory::getLanguage();
|
||||
$extensionName = $lang->_((string) $xml->name);
|
||||
|
||||
if (isset($xml->files))
|
||||
$info[] = JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_XML', $extensionName);
|
||||
$info[] = JText::sprintf('COM_JEDCHECKER_INFO_XML_VERSION_XML', (string) $xml->version);
|
||||
$info[] = JText::sprintf('COM_JEDCHECKER_INFO_XML_CREATIONDATE_XML', (string) $xml->creationDate);
|
||||
|
||||
$this->report->addInfo($file, implode('<br />', $info));
|
||||
|
||||
if ($isTopLevel)
|
||||
{
|
||||
// JED allows components, modules, plugins, and packages (as a container) only
|
||||
if (!in_array($type, $this->jedTypes, true))
|
||||
{
|
||||
foreach ($xml->files->children() as $child)
|
||||
$this->report->addError($file, JText::sprintf('COM_JEDCHECKER_MANIFEST_TYPE_NOT_ACCEPTED', $type));
|
||||
}
|
||||
|
||||
// NM3 - Listing name contains “module” or “plugin”
|
||||
// (and other reserved words)
|
||||
if (preg_match('/\b(?:module|plugin|component|template|extension|free)\b/i', $extensionName, $match))
|
||||
{
|
||||
$this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_RESERVED_KEYWORDS', $extensionName, strtolower($match[0])));
|
||||
}
|
||||
|
||||
// Extension name shouldn't start with extension type prefix
|
||||
if (preg_match('/^\s*(?:mod|com|plg|tpl|pkg)_/i', $extensionName))
|
||||
{
|
||||
$this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_PREFIXED', $extensionName));
|
||||
}
|
||||
|
||||
// NM5 - Version in name/title
|
||||
if (preg_match('/(?:\bversion\b|\d\.\d)/i', $extensionName))
|
||||
{
|
||||
$this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_VERSION', $extensionName));
|
||||
}
|
||||
|
||||
// Check for "Joomla" in the name
|
||||
if (stripos($extensionName, 'joomla') === 0)
|
||||
{
|
||||
// An extension name can't start with the word "Joomla"
|
||||
$this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_JOOMLA', $extensionName));
|
||||
}
|
||||
else
|
||||
{
|
||||
$cleanName = preg_replace('/\s+for\s+Joomla!?$/', '', $extensionName);
|
||||
|
||||
if (stripos($cleanName, 'joom') !== false)
|
||||
{
|
||||
if (isset($child[$type]))
|
||||
{
|
||||
$extension = (string) $child[$type];
|
||||
}
|
||||
// Extensions that use "Joomla" or a derivative of Joomla in the extension name need to be licensed by OSM
|
||||
$this->report->addWarning($file,
|
||||
JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_JOOMLA_DERIVATIVE', $extensionName, 'https://tm.joomla.org/approved-domains.html')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Check extension name consists of ASCII characters only
|
||||
if (preg_match('/[^\x20-\x7E]/', $extensionName))
|
||||
{
|
||||
$this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_NON_ASCII', $extensionName));
|
||||
}
|
||||
|
||||
// Extension name shouldn't be too long
|
||||
$nameLen = strlen($extensionName);
|
||||
|
||||
if ($nameLen > 80)
|
||||
{
|
||||
$this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_TOO_LONG', $extensionName));
|
||||
}
|
||||
elseif ($nameLen > 40)
|
||||
{
|
||||
$this->report->addWarning($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_TOO_LONG', $extensionName));
|
||||
}
|
||||
}
|
||||
|
||||
// Filter extension's element name
|
||||
$extension = strtolower(JFilterInput::getInstance()->clean($extension, 'cmd'));
|
||||
// Validate URLs
|
||||
$this->validateDomain($file, (string) $xml->authorUrl);
|
||||
|
||||
// Component's element name starts with com_
|
||||
if ($type === 'component' && strpos($extension, 'com_') !== 0)
|
||||
if ($type === 'package' && (string) $xml->packagerurl !== (string) $xml->authorUrl)
|
||||
{
|
||||
$extension = 'com_' . $extension;
|
||||
$this->validateDomain($file, (string) $xml->packagerurl);
|
||||
}
|
||||
|
||||
if ($type === 'component' && isset($xml->administration->menu))
|
||||
{
|
||||
$menuName = $lang->_((string) $xml->administration->menu);
|
||||
// Do name the Component's admin menu the same as the extension name
|
||||
if ($extensionName !== $menuName)
|
||||
{
|
||||
$this->report->addWarning($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_ADMIN_MENU', $menuName, $extensionName));
|
||||
}
|
||||
}
|
||||
|
||||
if ($isTopLevel && $type === 'plugin')
|
||||
{
|
||||
// The name of your plugin must comply with the JED naming conventions - plugins in the form “{Type} - {Extension Name}”.
|
||||
$parts = explode(' - ', $extensionName, 2);
|
||||
$extensionNameGroup = isset($parts[1]) ? strtolower(preg_replace('/\s/', '', $parts[0])) : false;
|
||||
$group = (string) $xml['group'];
|
||||
|
||||
if ($extensionNameGroup !== $group && $extensionNameGroup !== str_replace('-', '', $group)
|
||||
&& !(isset($this->pluginsGroupMap[$extensionNameGroup]) && $this->pluginsGroupMap[$extensionNameGroup] === $group)
|
||||
)
|
||||
{
|
||||
$this->report->addWarning($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_PLUGIN_FORMAT', $extensionName));
|
||||
}
|
||||
}
|
||||
|
||||
// All checks passed. Return true
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate and load extension's .sys.ini translation file
|
||||
*
|
||||
* @param SimpleXMLElement $xml Extension's XML manifest
|
||||
* @param string $langDir The basepath
|
||||
* @param string $langTag The language to load
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function loadExtensionLanguage($xml, $langDir, $langTag = 'en-GB')
|
||||
{
|
||||
// Get extension's element name (simulates work of Joomla's installer)
|
||||
$extension = JEDCheckerHelper::getElementName($xml);
|
||||
|
||||
$type = (string) $xml['type'];
|
||||
|
||||
// Plugin's element name starts with plg_
|
||||
if ($type === 'plugin' && isset($xml['group']) && strpos($extension, 'plg_') !== 0)
|
||||
{
|
||||
@ -162,10 +280,6 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule
|
||||
// Load the language of the extension (if any)
|
||||
$lang = JFactory::getLanguage();
|
||||
|
||||
// Search for .sys.ini translation file
|
||||
$langDir = dirname($file);
|
||||
$langTag = 'en-GB'; // $lang->getDefault();
|
||||
|
||||
// Populate list of directories to look for
|
||||
$lookupLangDirs = array();
|
||||
|
||||
@ -226,79 +340,6 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the real extension's name now that the language has been loaded
|
||||
$extensionName = $lang->_((string) $xml->name);
|
||||
|
||||
$info[] = JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_XML', $extensionName);
|
||||
$info[] = JText::sprintf('COM_JEDCHECKER_INFO_XML_VERSION_XML', (string) $xml->version);
|
||||
$info[] = JText::sprintf('COM_JEDCHECKER_INFO_XML_CREATIONDATE_XML', (string) $xml->creationDate);
|
||||
|
||||
$this->report->addInfo($file, implode('<br />', $info));
|
||||
|
||||
// NM3 - Listing name contains “module” or “plugin”
|
||||
if (preg_match('/module|plugin/i', $extensionName))
|
||||
{
|
||||
$this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_MODULE_PLUGIN', $extensionName));
|
||||
}
|
||||
|
||||
// The "template" is reserved keyword
|
||||
if (stripos($extensionName, 'template') !== false)
|
||||
{
|
||||
$this->report->addWarning($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_RESERVED_KEYWORDS', $extensionName));
|
||||
}
|
||||
|
||||
// NM5 - Version in name/title
|
||||
if (preg_match('/(?:\bversion\b|\d\.\d)/i', $extensionName))
|
||||
{
|
||||
$this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_VERSION', $extensionName));
|
||||
}
|
||||
|
||||
if (stripos($extensionName, 'joomla') === 0)
|
||||
{
|
||||
// An extension name can't start with the word "Joomla"
|
||||
$this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_JOOMLA', $extensionName));
|
||||
}
|
||||
elseif (stripos($extensionName, 'joom') !== false)
|
||||
{
|
||||
// Extensions that use "Joomla" or a derivative of Joomla in the extension name need to be licensed by OSM
|
||||
$this->report->addWarning($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_JOOMLA_DERIVATIVE', $extensionName));
|
||||
}
|
||||
|
||||
$this->validateDomain($file, (string) $xml->authorUrl);
|
||||
|
||||
if ($type === 'package' && (string) $xml->packagerurl !== (string) $xml->authorUrl)
|
||||
{
|
||||
$this->validateDomain($file, (string) $xml->packagerurl);
|
||||
}
|
||||
|
||||
if ($type === 'component' && isset($xml->administration->menu))
|
||||
{
|
||||
$menuName = $lang->_((string) $xml->administration->menu);
|
||||
// Do name the Component's admin menu the same as the extension name
|
||||
if ($extensionName !== $menuName)
|
||||
{
|
||||
$this->report->addWarning($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_ADMIN_MENU', $menuName, $extensionName));
|
||||
}
|
||||
}
|
||||
|
||||
if ($type === 'plugin')
|
||||
{
|
||||
// The name of your plugin must comply with the JED naming conventions - plugins in the form “{Type} - {Extension Name}”.
|
||||
$parts = explode(' - ', $extensionName, 2);
|
||||
$extensionNameGroup = isset($parts[1]) ? strtolower(preg_replace('/\s/', '', $parts[0])) : false;
|
||||
$group = (string) $xml['group'];
|
||||
|
||||
if ($extensionNameGroup !== $group && $extensionNameGroup !== str_replace('-', '', $group)
|
||||
&& !(isset($this->pluginsGroupMap[$extensionNameGroup]) && $this->pluginsGroupMap[$extensionNameGroup] === $group)
|
||||
)
|
||||
{
|
||||
$this->report->addWarning($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_PLUGIN_FORMAT', $extensionName));
|
||||
}
|
||||
}
|
||||
|
||||
// All checks passed. Return true
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user