Based on CAPTCHA module experience
Artem Miroshnyk
Web developer
Propeople Ukraine






PHP OOP, OOD, Symfony 2, PSR4, Composer, new D8 APIs, Twig, etc


Any IDE or configured Text Editor will show most of broken places:
Other wrong places you will notice from runtime errors/notices.
Left parts of your code could be changed into completely new system.
if (!empty($views_field_options['fieldset']['id'])) {
$id = $views_field_options['fieldset']['id'];
$id = $views_field->handler->tokenize_value($id, $view->row_index);
$vars['attributes_array']['id'] = drupal_html_id($id);
}Most IDEs will highlight deprecated function.
Also all deprecated function/classes/methods in D8 has comments when it will be removed and what to use instead.
/**
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.0.
* Use \Drupal\Component\Utility\Html::getUniqueId()
*/
function drupal_html_id($id) {
return Html::getUniqueId($id);
}
Fatal error: Call to undefined function Drupal\image_captcha\Plugin\Captcha\watchdog() in
/var/www/modules/captcha/image_captcha/src/Plugin/Captcha/ImageCaptcha.php on line 35Stunning error... But thanks Drupal team we have "Change records for Drupal core" that has record for our problem - "hook_watchdog() and watchdog() removed" and some other useful stuff if you will try to search using "watchdog" keyword.
No D8 procedural code looks like that:
<?php
// Logs a notice
\Drupal::logger('my_module')->notice($message);
// Logs an error
\Drupal::logger('my_module')->error($message);
?>YML, HTTP Foundation, HTTPKernel, Routing, Controllers

Entity&Field API
// Forget about:
$node->body[LANGUAGE_NONE][0]['value']
$node->title
$tid = $node->field_tags[LANGUAGE_NONE][2]['tid']
$term = taxonomy_term_load($tid);
$term->name
// Meet new D8!
$node->body->value
$node->title->value
$node->field_tags[2]->name
Plugins API
/**
* Class ImageCaptcha
* @package Drupal\image_captcha\Plugin\Captcha
*
* @Captcha(
* id = "image",
* title = @Translation("Image captcha")
* )
*/
class ImageCaptcha extends PluginBase implements CaptchaInterface, ContainerFactoryPluginInterface {How could we handle it?

"Do you need X feature? Drupal just has module X for this feature!"
The same magic with similar mages are available in other local communities: Symfony, Composer, Assets, Zend, etc
Let's become friends!

drush dmu-analyze MODULE_NAMEThis will print a report showing any relevant change notices where you can read more.
The script will output a few lines as it attempts various conversions. Go into your modules/MODULE_NAME directory and check out all of your new YAML files and such.
drush dmu-upgrade MODULE_NAME



PHP_CodeSniffer
PHP Mess Detector
PHP Copy/Paste Detector

GitHub
TravisCI
neutron/recaptcha - The most used implementation of reCAPTCHA and compatible with HTTP Foundation
gregwar/captcha - The most used stadalone image captcha library also compatible with HTTP Foundation
/**
* Defines the CaptchaPoint entity.
*
* @ConfigEntityType(
* id = "captcha_point",
* label = @Translation("Captcha Point"),
* handlers = {
* "list_builder" = "Drupal\captcha\CaptchaPointListBuilder",
* "form" = {
* "add" = "Drupal\captcha\Form\CaptchaPointForm",
* "edit" = "Drupal\captcha\Form\CaptchaPointForm",
* "delete" = "Drupal\captcha\Form\CaptchaPointDeleteForm"
* }
* },
* fieldable = FALSE,
* config_prefix = "captcha_point",
* admin_permission = "administer CAPTCHA settings",
* entity_keys = {
* "id" = "formId",
* "label" = "label",
* },
* links = {
* "edit-form" = "captcha_point.edit",
* "delete-form" = "captcha_point.delete",
* }
* )
*/
class CaptchaPoint extends ConfigEntityBase implements CaptchaPointInterface {/**
* MathCaptcha class.
*
* @Captcha(
* id = "math",
* title = @Translation("Math Captcha")
* )
*/
class MathCaptcha extends PluginBase implements CaptchaInterface {
public function __construct(array $configuration, $plugin_id, $plugin_definition) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->firstAddendum = mt_rand(1, 20);
$this->solution = mt_rand(1, $this->firstAddendum);
$this->secondAddendum = $this->solution + $this->firstAddendum;
}
public function getQuestionFormElement(array $form, FormStateInterface $form_state, $captcha_sid) {
return array(
'#markup' => $this->firstAddendum . ' + ' . $this->secondAddendum
);
}
public function getAnswerFormElement(array $form, FormStateInterface $form_state) {
return array(
'#type' => 'textfield',
'#title' => t('Math question'),
'#description' => t('Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.'),
'#field_prefix' => t('@x + @y = ', array('@x' => $this->firstAddendum, '@y' => $this->secondAddendum)),
'#size' => 4,
'#maxlength' => 2,
'#required' => TRUE,
'#attributes' => array(
'autocomplete' => 'off',
),
);
}
public function getChallengeDescription() {
return $this->t('Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.');
}
public function getQuestionDescription() {
return $this->t('Math');
}
public function getSolutionValue($captcha_sid) {
return $this->solution;
}
}
services:
controller.image_captcha:
class: Drupal\image_captcha\Controller\CaptchaImageGenerator
image_captcha.generator:
class: Drupal\image_captcha\Generator\ImageCaptchaGenerator
arguments:
- @gregwar_captcha.captcha_builder
- @gregwar_captcha.phrase_builder
gregwar_captcha.captcha_builder:
class: Gregwar\Captcha\CaptchaBuilder
gregwar_captcha.phrase_builder:
class: Gregwar\Captcha\PhraseBuilderPHPUnit, WebTests, Code Styles, Drupal Build
- composer global require drush/drush:dev-master
- composer global require youngj/httpserver:dev-master
- composer global require squizlabs/php_codesniffer:$PHPCS_VERSION
- composer global require drupal/coder:$CODER_VERSION
- sudo apt-get update
- sudo apt-get install apache2 libapache2-mod-fastcgi
- sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf
- sudo a2enmod rewrite actions fastcgi alias
- echo "cgi.fix_pathinfo = 1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- ~/.phpenv/versions/$(phpenv version-name)/sbin/php-fpm
- echo "$(curl -fsSL https://gist.githubusercontent.com/nickveenhof/11386315/raw/b8abaf9304fe12b5cc7752d39c29c1edae8ac2e6/gistfile1.txt)" | sed -e "s,PATH,$TRAVIS_BUILD_DIR/../drupal,g" | sudo tee /etc/apache2/sites-available/default > /dev/null
- sudo service apache2 restart
- curl -v "http://localhost"
before_script:
- ln -s ~/.composer/vendor/drupal/coder/coder_sniffer/Drupal ~/.composer/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards
- TESTDIR=$(pwd)
- cd ..
- mysql -e 'create database drupal'
- git clone --depth 1 --branch $DRUPAL_VERSION $DRUPAL_REPO drupal
- cd drupal
- php -d sendmail_path=`which true` ~/.composer/vendor/bin/drush.php --yes site-install --db-url=mysql://root:@127.0.0.1/drupal testing
- composer require gregwar/captcha:1.0.11
- ln -s $TESTDIR modules/$MODULE_NAME
- drush --yes pm-enable simpletest $MODULE_NAME
script:
- phpcs --report=full --standard=Drupal ./modules/$MODULE_NAME
- php ./core/scripts/run-tests.sh --php `which php` --concurrency 12 --url http://localhost/ --verbose --color "$MODULE_TEST_GROUP"
- ./core/vendor/phpunit/phpunit/phpunit -c ./core/phpunit.xml.dist ./modules/$MODULE_NAME