diff --git a/.gitignore b/.gitignore index 592bcdc9..10542ea2 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,4 @@ phpunit.xml .settings .DS_Store .idea -.vscode \ No newline at end of file +.vscode diff --git a/.travis.yml b/.travis.yml index 50f8bda3..e37258cd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,9 +17,11 @@ matrix: - php: 7.0 - php: 7.1 - php: 7.2 + - php: 7.3 + - php: 7.4 - php: nightly allow_failures: - - php: 7.2 + - php: 7.4 - php: nightly before_script: diff --git a/Joomla/ExampleRulesets/Joomla-CMS/ruleset.xml b/Joomla/ExampleRulesets/Joomla-CMS/ruleset.xml index a2cda6fb..f5a3012a 100644 --- a/Joomla/ExampleRulesets/Joomla-CMS/ruleset.xml +++ b/Joomla/ExampleRulesets/Joomla-CMS/ruleset.xml @@ -1,31 +1,429 @@ + + + + - - - - - + + ^build/* + docs/* + cache/* + tmp/* + logs/* - - */build/* - */tests/* - */lib/* - */tmpl/* - */layouts/* + + libraries/compat/password/* + libraries/fof/* + libraries/idna_convert/* + libraries/php-encryption/* + libraries/phputf8/* + libraries/simplepie/* + libraries/phpass/* + libraries/vendor/* + libraries/joomla/* + plugins/editors/* + plugins/editors-xtd/* + plugins/captcha/recaptcha/recaptcha.php + plugins/captcha/recaptcha/recaptchalib.php + */vendor/* + */fof/* - - */libraries/* - */vendor/* - */editors/* - - - - - - - - - - + + administrator/components/com_joomlaupdate/restore_finalisation.php + administrator/components/com_joomlaupdate/restore.php + configuration.php + installation/template/index.php + + + tests/unit/suites/libraries/joomla/model/stubs/barbaz.php + tests/unit/suites/libraries/joomla/view/layouts1/fringe/division.php + tests/unit/suites/libraries/joomla/view/layouts1/olivia.php + tests/unit/suites/libraries/joomla/view/layouts1/peter.php + tests/unit/suites/libraries/joomla/view/layouts2/fauxlivia.php + tests/unit/suites/libraries/joomla/view/layouts2/olivia.php + tests/unit/suites/libraries/legacy/controller/stubs/component1/controller.json.php + tests/unit/suites/libraries/legacy/controller/stubs/component2/controller.php + + + RoboFile.php + + + + + tests/codeception/* + + + + */tmpl/* + + + + */tmpl/* + templates/* + layouts/* + + + + */tmpl/* + templates/* + layouts/* + plugins/system/* + plugins/search/* + tests/unit/suites/libraries/cms/* + tests/unit/suites/database/driver/* + libraries/src/Access/Access.php + libraries/src/Application/* + libraries/src/Categories/Categories.php + libraries/src/Renderer/* + libraries/src/Client/FtpClient.php + libraries/src/Component/* + libraries/src/Document/Document.php + libraries/src/Environment/Browser.php + libraries/src/Factory.php + libraries/src/Form/* + libraries/src/Helper/* + libraries/src/HTML/* + libraries/src/Http/* + libraries/src/Installer/* + libraries/src/Language/* + libraries/src/Log/* + libraries/src/MVC/* + libraries/src/Pathway/* + libraries/src/Router/* + libraries/src/Table/* + libraries/src/Document/Renderer/Feed/AtomRenderer.php + libraries/src/Document/Renderer/Html/HeadRenderer.php + libraries/legacy/* + libraries/cms/html/* + administrator/components/com_users/* + administrator/components/com_redirect/* + administrator/components/com_postinstall/* + administrator/components/com_newsfeeds/* + administrator/components/com_modules/* + administrator/components/com_menus/* + administrator/components/com_media/* + administrator/components/com_languages/* + administrator/components/com_installer/* + administrator/components/com_finder/* + administrator/components/com_fields/* + administrator/components/com_content/* + administrator/components/com_contact/* + administrator/components/com_categories/* + administrator/components/com_banners/* + administrator/components/com_associations/* + administrator/components/com_admin/* + administrator/modules/mod_latest/helper.php + administrator/modules/mod_logged/helper.php + components/com_finder/helpers/html/filter.php + components/com_content/views/featured/view.feed.php + components/com_content/views/category/view.html.php + components/com_content/views/category/view.feed.php + components/com_content/views/article/view.html.php + components/com_content/models/article.php + components/com_contact/views/contact/view.html.php + components/com_tags/controller.php + installation/model/database.php + installation/form/field/sample.php + modules/mod_articles_category/mod_articles_category.php + libraries/src/Updater/Adapter/ExtensionAdapter.php + libraries/src/Table/Table.php + libraries/loader.php + libraries/legacy/error/error.php + plugins/user/profile/profile.php + plugins/content/pagebreak/pagebreak.php + plugins/authentication/cookie/cookie.php + tests/unit/suites/plugins/content/emailcloak/PlgContentEmailcloakTest.php + tests/unit/core/case/cache.php + tests/unit/core/case/database/sqlsrv.php + + + + */tmpl/* + templates/* + layouts/* + + + + */tmpl/* + templates/* + layouts/* + libraries/src/Helper/ContentHistoryHelper.php + libraries/src/Helper/TagsHelper.php + libraries/src/Table/Nested.php + administrator/components/com_modules/models/module.php + modules/mod_tags_popular/helper.php + plugins/search/content/content.php + plugins/system/debug/debug.php + components/com_content/models/articles.php + administrator/modules/mod_menus/models/menus.php + administrator/components/com_joomlaupdate/models/default.php + administrator/components/com_menus/models/menus.php + administrator/components/com_menus/models/items.php + administrator/components/com_associations/models/associations.php + tests/unit/suites/libraries/legacy/application/JApplicationTest.php + + + + */tmpl/* + templates/* + layouts/* + + + + + + */tmpl/* + templates/* + layouts/* + + + + plugins/system/languagefilter/languagefilter.php + + + + */tmpl/* + templates/* + layouts/* + + + + */tmpl/* + templates/* + layouts/* + + + + administrator/components/com_contact/helpers/html/contact.php + administrator/components/com_content/helpers/html/contentadministrator.php + libraries/cms/component/router/stubs/ComContentRouter.php + libraries/cms/pagination/JPaginationObjectTest.php + modules/mod_articles_category/helper.php + + + + installation/controller/install/database_backup.php + installation/controller/install/database_remove.php + + + + + + */tmpl/* + templates/* + plugins/editors/* + layouts/* + + + + tests/unit/core/mock/menu.php + tests/unit/stubs/bogusload.php + tests/unit/stubs/config.wrongclass.php + tests/unit/suites/database/driver/mysql/JDatabaseExporterMysqlTest.php + tests/unit/suites/libraries/cms/application/stubs/JApplicationCmsInspector.php + tests/unit/suites/libraries/cms/component/router/stubs/ComContentRouter.php + tests/unit/suites/libraries/cms/html/testfiles/inspector.php + tests/unit/suites/libraries/cms/html/TestHelpers/JHtmlSelect-helper-dataset.php + tests/unit/suites/libraries/cms/installer/JInstallerAdapterTest.php + tests/unit/suites/libraries/legacy/view/JViewLegacyTest.php + plugins/content/loadmodule/loadmodule.php + plugins/system/debug/debug.php + components/com_users/views/* + components/com_tags/views/* + components/com_newsfeeds/helpers/* + components/com_redirect/helpers/* + components/com_redirect/views/* + components/com_search/views/* + libraries/src/Form/Field/MediaField.php + libraries/src/Menu/Node.php + libraries/src/MVC/View/CategoryView.php + administrator/components/com_plugins/* + administrator/components/com_installer/models/database.php + administrator/components/com_content/helpers/content.php + administrator/components/com_contenthistory/views/* + administrator/components/com_templates/views/* + administrator/components/com_messages/views/* + administrator/components/com_installer/views/* + administrator/components/com_languages/views/* + administrator/components/com_messages/models/* + administrator/components/com_fields/models/* + administrator/components/com_fields/libraries/* + administrator/components/com_fields/helpers/* + administrator/components/com_fields/controllers/* + administrator/components/com_categories/helpers/* + administrator/components/com_associations/helpers/associations.php + administrator/components/com_menus/helpers/menus.php + components/com_config/view/* + components/com_contact/views/* + components/com_modules/views/* + components/com_contact/models/* + components/com_content/models/* + components/com_tags/helpers/route.php + components/com_newsfeeds/models/category.php + components/com_newsfeeds/models/categories.php + components/com_finder/views/search/view.html.php + components/com_content/views/form/view.html.php + components/com_content/views/featured/view.html.php + components/com_content/views/article/view.html.php + components/com_content/views/archive/view.html.php + components/com_contact/views/contact/view.html.php + components/com_contact/views/catagory/view.html.php + components/com_contact/models/featured.php + components/com_contact/models/contact.php + components/com_contact/models/catagory.php + components/com_contact/models/catagories.php + components/com_contact/router.php + components/com_content/router.php + components/com_newsfeeds/router.php + components/com_content/models/catagory.php + components/com_content/models/catagories.php + libraries/src/User/User.php + libraries/src/Updater/UpdateAdapter.php + libraries/src/Updater/Update.php + libraries/cms/less/formatter/joomla.php + administrator/modules/mod_menu/menu.php + administrator/modules/mod_quickicon/helper.php + + + + */tmpl/* + templates/* + layouts/* + + + + */tmpl/* + templates/* + layouts/* + + + + */tmpl/* + templates/* + layouts/* + + + + */tmpl/* + templates/* + layouts/* + + + + + + */tmpl/* + templates/* + layouts/* + + + + + + tests/* + + + + templates/* + layouts/* + modules/* + plugins/* + */tests/* + libraries/legacy/* + libraries/cms/html/* + installation/model/* + installation/application/* + libraries/src/Application/CMSApplication.php + libraries/src/Application/DaemonApplication.php + libraries/src/Application/WebApplication.php + libraries/src/Captcha/Captcha.php + libraries/src/Client/FtpClient.php + libraries/src/Utility/BufferStreamHandler.php + libraries/src/User/User.php + libraries/src/Updater/UpdateAdapter.php + libraries/src/Toolbar/ToolbarButton.php + libraries/src/Toolbar/Toolbar.php + libraries/src/Toolbar/Button/SeparatorButton.php + libraries/loader.php + libraries/legacy/error/error.php + libraries/src/Component/Router/* + libraries/src/Document/* + libraries/src/Editor/Editor.php + libraries/src/Environment/Browser.php + libraries/src/Filter/Wrapper/OutputFilterWrapper.php + libraries/src/Form/* + libraries/src/Helper/* + libraries/src/Input/* + libraries/src/Installer/* + libraries/src/Language/* + libraries/src/Log/* + libraries/src/Menu/* + libraries/src/MVC/* + libraries/src/Plugin/* + libraries/src/Router/* + libraries/src/Session/Session.php + libraries/src/String/PunycodeHelper.php + libraries/src/Table/* + libraries/src/HTML/HTMLHelper.php + libraries/src/Layout/FileLayout.php + components/com_wrapper/views/wrapper/view.html.php + administrator/components/* + components/com_banners/router.php + components/com_config/* + components/com_contact/* + components/com_content/* + components/com_finder/* + components/com_newsfeeds* + components/com_search/* + components/com_tags/* + components/com_users/* + components/com_wrapper/router.php + + + + */tmpl/* + templates/* + layouts/* + + + + tests/* + + + + */tmpl/* + templates/* + layouts/* + + + + */tmpl/* + templates/* + layouts/* + + + + */tmpl/* + templates/* + layouts/* + + + + */tmpl/* + templates/* + layouts/* + + + + + + + + + + + + + diff --git a/Joomla/Sniffs/Commenting/FunctionCommentSniff.php b/Joomla/Sniffs/Commenting/FunctionCommentSniff.php index 8e6d7cfa..6c95de78 100644 --- a/Joomla/Sniffs/Commenting/FunctionCommentSniff.php +++ b/Joomla/Sniffs/Commenting/FunctionCommentSniff.php @@ -147,7 +147,7 @@ protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) { if ($tokens[$returnToken]['code'] === T_CLOSURE || $tokens[$returnToken]['code'] === T_ANON_CLASS - ) + ) { $returnToken = $tokens[$returnToken]['scope_closer']; continue; @@ -156,7 +156,7 @@ protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) if ($tokens[$returnToken]['code'] === T_RETURN || $tokens[$returnToken]['code'] === T_YIELD || $tokens[$returnToken]['code'] === T_YIELD_FROM - ) + ) { break; } @@ -186,7 +186,7 @@ protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) { if ($tokens[$returnToken]['code'] === T_CLOSURE || $tokens[$returnToken]['code'] === T_ANON_CLASS - ) + ) { $returnToken = $tokens[$returnToken]['scope_closer']; continue; @@ -195,7 +195,7 @@ protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) if ($tokens[$returnToken]['code'] === T_RETURN || $tokens[$returnToken]['code'] === T_YIELD || $tokens[$returnToken]['code'] === T_YIELD_FROM - ) + ) { break; } diff --git a/Joomla/Sniffs/ControlStructures/ControlStructuresBracketsSniff.php b/Joomla/Sniffs/ControlStructures/ControlStructuresBracketsSniff.php index ef86cd3a..4d256461 100644 --- a/Joomla/Sniffs/ControlStructures/ControlStructuresBracketsSniff.php +++ b/Joomla/Sniffs/ControlStructures/ControlStructuresBracketsSniff.php @@ -177,17 +177,51 @@ public function process(File $phpcsFile, $stackPtr) } } - // Anonymous classes and functions set the indent at one plus their own indent level. - if ($phpcsFile->hasCondition($stackPtr, T_CLOSURE) === true - || $phpcsFile->hasCondition($stackPtr, T_ANON_CLASS) === true) - { - $expected = ($tokens[$stackPtr]['level'] + 1) * $this->indent; - } - else + $baseLevel = $tokens[$stackPtr]['level']; + + /** + * Take into account any nested parenthesis that don't contribute to the level (often required for + * closures and anonymous classes + */ + if (array_key_exists('nested_parenthesis', $tokens[$stackPtr]) === true) { - $expected = $tokens[$stackPtr]['level'] * $this->indent; + $nestedStructures = $tokens[$stackPtr]['nested_parenthesis']; + $nestedCount = 0; + + foreach ($nestedStructures as $start => $end) + { + /** + * Crude way of checking for a chained method which requires an extra indent. We navigate to the open + * parenthesis of the nested structure. The element before that is the function name. Before that we + * check for an operator (->) and a whitespace before it (which makes it a chained method on a new line) + * TODO: Is there a better way to check for a chained method? This feels very dirty! + */ + if ($tokens[$start - 2]['type'] === 'T_OBJECT_OPERATOR' && $tokens[$start - 3]['type'] === 'T_WHITESPACE') + { + /** + * If we have an anonymous function/class on the same line as our chained method then we + * balance out so only increase the count by 1. Else by 2. + */ + if ($tokens[$start + 1]['type'] === 'T_CLOSURE' || $tokens[$start + 1]['type'] === 'T_ANON_CLASS') + { + $nestedCount++; + } + else + { + $nestedCount += 2; + } + } + else + { + $nestedCount++; + } + } + + $baseLevel += $nestedCount; } + $expected = $baseLevel * $this->indent; + // We need to divide by 4 here since there is a space vs tab intent in the check vs token $expected /= $this->indent; $spaces /= $this->indent; diff --git a/Joomla/Tests/ControlStructures/ControlStructuresBracketsUnitTest.inc b/Joomla/Tests/ControlStructures/ControlStructuresBracketsUnitTest.inc index 03dde967..9511b7f8 100644 --- a/Joomla/Tests/ControlStructures/ControlStructuresBracketsUnitTest.inc +++ b/Joomla/Tests/ControlStructures/ControlStructuresBracketsUnitTest.inc @@ -168,3 +168,141 @@ $this->attachRule( } } ); + +// Round 2 Closure indentation tests +$i = 1; +$func = function ($match) use ($query, $args, &$i) +{ + if (isset($match[6]) && $match[6] === '%') + { + return '%'; + } + // No argument required, do not increment the argument index. + switch ($match[5]) +{ + case 't': + return $query->currentTimestamp(); + break; + case 'z': + if (true) + { + return $query->nullDate(true); + } + return $query->nullDate(false); + break; + case 'Z': + return $query->nullDate(true); + break; + } +}; + +class Foo +{ + public function format($format) + { + $query = $this; + $args = \array_slice(\func_get_args(), 1); + array_unshift($args, null); + + $i = 1; + $func = function ($match) use ($query, $args, &$i) { + if (isset($match[6]) && $match[6] === '%') + { + return '%'; + } + + }; + } +} + +// Anonymous classes test +$this->attachRule( + new class($this) implements RulesInterface + { + public function parse(&$segments, &$vars) + { + // Move forward based on view + switch ($segments) + { + case 'tracker': + usort( + $view, + function($a, $b) use ($vars) + { + $ordering = $vars->getState('list.ordering'); + + if (strtolower($vars->getState('list.direction')) === 'asc') + { + return StringHelper::strcmp($a->$ordering, $b->$ordering); + } + else + { + return StringHelper::strcmp($b->$ordering, $a->$ordering); + } + } + ); + break; + } + + return; + } + } +); + +class Application +{ + public function doThings($container) + { + $container->alias(MyClass::class, 'MyClass') + ->share( + 'MyClass', + function (Container $container) { + doThing(); + + if ($thing) + { + bar(); + } + + return foo(); + }, + true + ); + } +} + +class Application +{ + public function doThings($container) + { + $container->share( + 'MyClass', + function (Container $container) { + doThing(); + + if ($thing) + { + bar(); + } + else { + something(); + + if (somethingelse()) + { + bar(); + } + + anotherFunction() + ->withNested(function() { + if ($foo){ + bar(); + } + }); + + return foo(); + } + }, + true + ); + } +} diff --git a/Joomla/Tests/ControlStructures/ControlStructuresBracketsUnitTest.inc.fixed b/Joomla/Tests/ControlStructures/ControlStructuresBracketsUnitTest.inc.fixed index 108a7d80..5703d39c 100644 --- a/Joomla/Tests/ControlStructures/ControlStructuresBracketsUnitTest.inc.fixed +++ b/Joomla/Tests/ControlStructures/ControlStructuresBracketsUnitTest.inc.fixed @@ -167,3 +167,143 @@ $this->attachRule( } } ); + +// Round 2 Closure indentation tests +$i = 1; +$func = function ($match) use ($query, $args, &$i) +{ + if (isset($match[6]) && $match[6] === '%') + { + return '%'; + } + // No argument required, do not increment the argument index. + switch ($match[5]) + { + case 't': + return $query->currentTimestamp(); + break; + case 'z': + if (true) + { + return $query->nullDate(true); + } + return $query->nullDate(false); + break; + case 'Z': + return $query->nullDate(true); + break; + } +}; + +class Foo +{ + public function format($format) + { + $query = $this; + $args = \array_slice(\func_get_args(), 1); + array_unshift($args, null); + + $i = 1; + $func = function ($match) use ($query, $args, &$i) { + if (isset($match[6]) && $match[6] === '%') + { + return '%'; + } + + }; + } +} + +// Anonymous classes test +$this->attachRule( + new class($this) implements RulesInterface + { + public function parse(&$segments, &$vars) + { + // Move forward based on view + switch ($segments) + { + case 'tracker': + usort( + $view, + function($a, $b) use ($vars) + { + $ordering = $vars->getState('list.ordering'); + + if (strtolower($vars->getState('list.direction')) === 'asc') + { + return StringHelper::strcmp($a->$ordering, $b->$ordering); + } + else + { + return StringHelper::strcmp($b->$ordering, $a->$ordering); + } + } + ); + break; + } + + return; + } + } +); + +class Application +{ + public function doThings($container) + { + $container->alias(MyClass::class, 'MyClass') + ->share( + 'MyClass', + function (Container $container) { + doThing(); + + if ($thing) + { + bar(); + } + + return foo(); + }, + true + ); + } +} + +class Application +{ + public function doThings($container) + { + $container->share( + 'MyClass', + function (Container $container) { + doThing(); + + if ($thing) + { + bar(); + } + else + { + something(); + + if (somethingelse()) + { + bar(); + } + + anotherFunction() + ->withNested(function() { + if ($foo) + { + bar(); + } + }); + + return foo(); + } + }, + true + ); + } +} diff --git a/Joomla/Tests/ControlStructures/ControlStructuresBracketsUnitTest.php b/Joomla/Tests/ControlStructures/ControlStructuresBracketsUnitTest.php index a9f4c7fc..d4bf5bc6 100644 --- a/Joomla/Tests/ControlStructures/ControlStructuresBracketsUnitTest.php +++ b/Joomla/Tests/ControlStructures/ControlStructuresBracketsUnitTest.php @@ -43,6 +43,16 @@ public function getErrorList() 120 => 1, 126 => 1, 135 => 1, + 182 => 1, + 188 => 1, + 210 => 1, + 226 => 1, + 235 => 1, + 263 => 1, + 284 => 1, + 287 => 1, + 291 => 1, + 297 => 1, ); } diff --git a/manual/README.md b/manual/README.md new file mode 100644 index 00000000..0a4d614b --- /dev/null +++ b/manual/README.md @@ -0,0 +1,10 @@ +# Joomla Coding Standards Manual +This manual documents the Joomla Coding Standards + +## Meta Information +The documentation in this repository is optimised for display in the [coding standards section](https://developer.joomla.org/coding-standards.html) of the Joomla! Developer Network. When formatting and proposing changes to this documentation, please keep the following in mind: + +- Heading levels should start at `

` +- The document title does NOT need to be included in the document, these are displayed as the page heading based on the Joomla component configuration and would result in duplicated titles if included +- Because the GitHub Markdown parser interprets line breaks as `
` tags, arbitrary line breaks to keep lines from becoming too long should not be used +- Links to documents in this manual should be formatted for use on the Joomla! Developer Network, such as `[a link to the Basic Guidelines page](/coding-standards/basic-guidelines.html)` diff --git a/manual/appendices/analysis.md b/manual/appendices/analysis.md index 6f36fe56..5391b360 100644 --- a/manual/appendices/analysis.md +++ b/manual/appendices/analysis.md @@ -1,16 +1,12 @@ -## Coding Standards Analysis - For new contributions we are going to be enforcing coding standards to ensure that the coding style in the source code is consistent. Ensuring that your code meets these standards will make the process of code contribution smoother. -## Configuring Code Analysis Tools +### Configuring Code Analysis Tools -In order to improve the consistency and readability of the source code, the Joomla project runs a coding style analysis tool, CodeSniffer, everytime changes are pushed to a Joomla project's repository. +In order to improve the consistency and readability of the source code, the Joomla project runs a coding style analysis tool, PHP_CodeSniffer, everytime changes are pushed to a Joomla project's repository. -### Running CodeSniffer +#### Running PHP_CodeSniffer -The Joomla Coding Standards sniffer rules are written to be used with a tool called PHP CodeSniffer. Please see the [PHP CodeSniffer Pear -Page](http://pear.php.net/package/PHP_CodeSniffer) for information on -installing PHP CodeSniffer on your system. +The Joomla Coding Standards sniffer rules are written to be used with a tool called PHP CodeSniffer. Please see the [PHP_CodeSniffer PEAR Page](http://pear.php.net/package/PHP_CodeSniffer) for information on installing PHP_CodeSniffer on your system. You can run the CodeSniffer by going to the CMS, Framework, or Issue Tracker's root directory and executing @@ -24,16 +20,10 @@ Alternatively, if you have Ant installed on your system, you may run the CodeSni ant phpcs ``` -#### Known Issues - -- There is currently an issue with running the Code Sniffer on the - Simplepie library. Pointing the sniffs at the libraries/joomla - directory or below will avoid the issue. - -## Other Tools +### Other Tools Here are some other tools available to developers who are planning to submit source code to the project. -### Set up the codesniffer +#### Set up PHP_CodeSniffer See in the documentation https://docs.joomla.org/Joomla_CodeSniffer#3._IDE_Integration diff --git a/manual/appendices/examples.md b/manual/appendices/examples.md index 7fda47f1..dfd54129 100644 --- a/manual/appendices/examples.md +++ b/manual/appendices/examples.md @@ -1 +1 @@ -## Code Examples \ No newline at end of file +Please contribute to this documentation page. diff --git a/manual/basic-guidelines.md b/manual/basic-guidelines.md index effbfe3d..c892129d 100644 --- a/manual/basic-guidelines.md +++ b/manual/basic-guidelines.md @@ -1,12 +1,11 @@ -## Basic Guidelines - This chapter outlines the basic guidelines covering files contributed to the Joomla project. The most important rule to remember when coding for the Joomla project, **if in doubt, please ask**. ### File Format All files contributed to Joomla must be: -* Stored as ASCII text +* Stored as ASCII text + Exceptions: languages locales and some test files containing non-ASCII characters * Use UTF-8 character encoding * Be Unix formatted following these rules. 1. Lines must end only with a line feed (LF). @@ -15,8 +14,7 @@ All files contributed to Joomla must be: ### Spelling -The spelling of words and terms used in code comments and in the naming of class, functions, variables and constant should generally be in accordance with British English rules (en\_GB). -Some exceptions are permitted, for example where common programming names are used that align with the PHP API or other established conventions such as for `color` where is it common practice to maintain US English spelling. +The spelling of words and terms used in code comments and in the naming of class, functions, variables and constant should generally be in accordance with British English rules (en\_GB). Some exceptions are permitted, for example where common programming names are used that align with the PHP API or other established conventions such as for `color` where is it common practice to maintain US English spelling. ### Indenting @@ -25,7 +23,3 @@ Tabs are used for indenting code (not spaces as required by the PEAR standard). ### Line Length There is no maximum limit for line lengths in files, however, a notional value of about 150 characters is recommended to achieve a good level of readability without horizontal scrolling. Longer lines are permitted if the nature of the code for individual lines requires it and line breaks would have an adverse affect on the final output (such as for mixed PHP/HTML layout files). - -## Best Practices - -TODO Any words of wisdom about PHP best practice, maybe even references for design patterns? Can/should we link out to the JRD, Doc wiki and Developer site for additional resources? diff --git a/manual/css.md b/manual/css.md index 1a7f1963..befaa5f8 100644 --- a/manual/css.md +++ b/manual/css.md @@ -1,29 +1,30 @@ -## CSS These guidelines have been assembled following an examination of emerging practices, ideas and existing styleguides, namely: 1. [OOCSS Code Standards](https://github.com/stubbornella/oocss-code-standards) 2. [Oneweb Style Guide](https://github.com/nternetinspired/OneWeb/blob/master/STYLEGUIDE.md) 3. [Idiomatic CSS](https://github.com/necolas/idiomatic-css) +### Commenting -## Commenting - -### Major sections +#### Major sections Major code sections should be named in caps and within a full comment block, eg: + ```css /* ========================================================================== PRIMARY NAVIGATION ========================================================================== */ ``` -### Sub sections +#### Sub sections Subsections should be normally cased and within an open comment block. + ```css /* Mobile navigation ========================================================================== */ ``` -### Verbose comments +#### Verbose comments + ```css /** * Short description using Doxygen-style comment format @@ -43,22 +44,24 @@ Subsections should be normally cased and within an open comment block. */ ``` -### Basic comments +#### Basic comments + ```css /* Basic comment */ ``` -### Uncompiled LESS/Scss comments +#### Uncompiled LESS/Scss comments + ```css // These are stripped on compile. ``` -## CSS selectors -Only use classes for CSS selectors, *never IDs* as they introduce unwanted specificity to the cascade. Using an ID as a css selector is like firing the first nuke; you begin a specifity war that can only escalate, with terrible consequence. +### CSS selectors +Only use classes for CSS selectors, *never IDs* as they introduce unwanted specificity to the cascade. Using an ID as a CSS selector is like firing the first nuke; you begin a specifity war that can only escalate, with terrible consequence. To put it another way; Don't use a Sith Lord when just two Storm Troopers will suffice: [CSS Specificity Wars](http://www.stuffandnonsense.co.uk/archives/css_specificity_wars.html) -### Class naming convention +#### Class naming convention Use dashes to create compound class names: ```css @@ -75,7 +78,7 @@ Use dashes to create compound class names: .compoundclassname {…} ``` -### Indentation +#### Indentation Rules should be indented one tab (equal to 4 spaces): ```css @@ -89,7 +92,7 @@ Rules should be indented one tab (equal to 4 spaces): .example {color: #000; visibility: hidden;} ``` -### Alignment +#### Alignment The opening brace must be on the same line as the last selector and preceded by a space. The closing brace must be on its own line after the last property and be indented to the same level as the opening brace. ```css @@ -109,7 +112,7 @@ The opening brace must be on the same line as the last selector and preceded by } ``` -### Property Format +#### Property Format Each property must be on its own line and indented one level. There should be no space before the colon and one space after. All properties must end with a semicolon. ```css @@ -132,8 +135,9 @@ Each property must be on its own line and indented one level. There should be no } ``` -### HEX values +#### HEX values HEX values must be declared in lowercase and shorthand: + ```css /* Good */ .example { @@ -146,7 +150,7 @@ HEX values must be declared in lowercase and shorthand: } ``` -### Attribute selectors +#### Attribute selectors Always use double quotes around attribute selectors. ```css @@ -166,7 +170,7 @@ input[type='button'] { } ``` -### Zero value units +#### Zero value units Zero values should not carry units. ```css diff --git a/manual/docblocks.md b/manual/docblocks.md index 1761479b..8661b05a 100644 --- a/manual/docblocks.md +++ b/manual/docblocks.md @@ -1,5 +1,3 @@ -## DocBlocks - Documentation headers for PHP code in: files, classes, class properties, methods and functions, called the docblocks, follow a convention similar to JavaDoc or phpDOC. These "DocBlocks" borrow from the PEAR standard but have some variations specific for Joomla and the Joomla projects. @@ -18,7 +16,7 @@ Short description (optional unless the file contains more than two classes or fu * @category (optional and rarely used) * @package (generally optional but required when files contain only procedural code. Always optional in namespaced code) * @subpackage (optional) -* @author (optional but only permitted in non-Joomla source files, for example, included third-party libraries like Geshi) +* @author (optional but only permitted in non-Joomla source files) * @copyright (required) * @license (required and must be compatible with the Joomla license) * @link (optional) @@ -39,8 +37,7 @@ Example of a DocBlock Header: ``` ### Class Definitions -Class definitions start on a new line and the opening and closing braces are also placed on new lines. Class methods must follow the guidelines for Function Definitions. Properties and methods must follow OOP standards and be declared appropriately (using public, protected, private and static as applicable). -Class definitions, properties and methods must each be provided with a DocBlock in accordance with the following sections. +Class definitions start on a new line and the opening and closing braces are also placed on new lines. Class methods must follow the guidelines for Function Definitions. Properties and methods must follow OOP standards and be declared appropriately (using public, protected, private and static as applicable). Class definitions, properties and methods must each be provided with a DocBlock in accordance with the following sections. #### Class DocBlock Headers The class Docblock consists of the following required and optional elements in the fol-lowing order. @@ -49,7 +46,7 @@ Short description (required, unless the file contains more than two classes or f * @category (optional and rarely used) * @package (optional) * @subpackage (optional) -* @author (optional but only permitted in non-Joomla source files, for example, included third-party libraries like Geshi) +* @author (optional but only permitted in non-Joomla source files) * @copyright (optional unless different from the file Docblock) * @license (optional unless different from the file Docblock) * @link (optional) @@ -88,8 +85,6 @@ Example of Class property DocBlock: protected static $userId = 0; ``` - - #### Class Method DocBlocks and Functions DocBlocks Function definitions start on a new line and the opening and closing braces are also placed on new lines. An empty line should precede lines specifying the return value. diff --git a/manual/html.md b/manual/html.md index fbd4e78c..2278e023 100644 --- a/manual/html.md +++ b/manual/html.md @@ -1,14 +1,11 @@ -## html - These guidelines have been assembled following an examination of emerging practices, ideas and existing styleguides, and include items from: -1. [Google's html styleguide](https://google.github.io/styleguide/htmlcssguide.html) -2. [JQuery's HTML Styleguide](http://contribute.jquery.org/style-guide/html/) +1. [Google's HTML styleguide](https://google.github.io/styleguide/htmlcssguide.html) +2. [jQuery's HTML Styleguide](http://contribute.jquery.org/style-guide/html/) 3. [Nicolas Ghallager's "Principles of writing consistent, idiomatic HTML"](https://github.com/necolas/idiomatic-html) 4. [Harry Robert's "My HTML/CSS coding style"](http://csswizardry.com/2012/04/my-html-css-coding-style/) 4. [The BBC's Media Standards and Guidelines](http://www.bbc.co.uk/guidelines/futuremedia/technical/semantic_markup.shtml) - ### Doctype Always use the minimal, versionless doctype. @@ -26,19 +23,17 @@ Always define which language the page is written in. ``` ### Encoding -Always define the character encoding. The encoding should be defined as early as possible. -Make sure your editor uses UTF-8 as character encoding, without a byte order mark (UTF-8, no BOM). -Do not specify the encoding of style sheets as these assume UTF-8. + +Always define the character encoding. The encoding should be defined as early as possible. Make sure your editor uses UTF-8 as character encoding, without a byte order mark (UTF-8, no BOM). Do not specify the encoding of style sheets as these assume UTF-8. ```html ``` -[More on encodings and when and how to specify them can be found in Handling character encodings in HTML and CSS](http://www.w3.org/International/tutorials/tutorial-char-enc/) - +More on encodings and when and how to specify them can be found in [Handling character encodings in HTML and CSS](http://www.w3.org/International/tutorials/tutorial-char-enc/) ### Capitalisation -All html should be lowercase; element names, attributes, attribute values (unless text/CDATA), CSS selectors, properties, and property values (with the exception of strings). Additionally, there is no need to use CDATA to escape inline JavaScript, formerly a requirement to meet XML strictness in XHTML. +All HTML should be lowercase; element names, attributes, attribute values (unless text/CDATA), CSS selectors, properties, and property values (with the exception of strings). Additionally, there is no need to use CDATA to escape inline JavaScript, formerly a requirement to meet XML strictness in XHTML. ```html @@ -76,10 +71,12 @@ This prevents mixed content issues and results in minor file size savings. ### Elements and Attributes -Always include html, head, and body tags. +Always include ``, ``, and `` tags. ### Type attributes + Do not use type or attributes for style sheets (unless not using CSS) and scripts (unless not using JavaScript). + ```html @@ -89,6 +86,7 @@ Do not use type or attributes for style sheets (unless not using CSS) and script ``` ### Language attributes + Do not use language attributes on script tags. ```html @@ -98,21 +96,24 @@ Do not use language attributes on script tags. + ``` Use attribute/value pairs for boolean attributes + ```html + ``` @@ -127,6 +128,7 @@ HTML attributes should be listed in an order that reflects the fact that class n ```html Text + Text ``` @@ -143,33 +145,38 @@ Elements with multiple attributes can have attributes arranged across multiple l ``` ### Elements + Optional closing tags may not be omitted. + ```html

The quick brown fox jumps over the lazy dog.

+

The quick brown fox jumps over the lazy dog. ``` Self-closing (void) elements should not be closed. Trailing forward slashes and spaces should be omitted. + ```html + ``` - ### Formatting + Use a new line for every block, list, or table element, and indent every such child element. ```html

- +
@@ -205,17 +212,17 @@ Tip: configure your editor to "show invisibles". This will allow you to eliminat Taxes - - $ 5.00 - $ 4.50 - + + $ 5.00 + $ 4.50 + + ``` ### Indentation -Don't indent inside html, body, script, or style. Indent inside head and all other elements. -Indent by four spaces at a time. Don’t use tabs or mix tabs and spaces for indentation. +Don't indent inside ``, ``, `