Commit bdd0e743 authored by alunyov's avatar alunyov Committed by elachlan

Issue #2855165 by alunyov, Znak, gg24, bapi_22: Deprecated methods and function

parent 3ec4ae4a
......@@ -84,7 +84,7 @@ function _captcha_generate_captcha_session($form_id = NULL, $status = CAPTCHA_ST
// Insert an entry and thankfully receive the value
// of the autoincrement field 'csid'.
$captcha_sid = db_insert('captcha_sessions')
$captcha_sid = \Drupal::database()->insert('captcha_sessions')
->fields([
'uid' => $user->id(),
'sid' => session_id(),
......@@ -108,7 +108,7 @@ function _captcha_generate_captcha_session($form_id = NULL, $status = CAPTCHA_ST
* The new solution to associate with the given CAPTCHA session.
*/
function _captcha_update_captcha_session($captcha_sid, $solution) {
db_update('captcha_sessions')
\Drupal::database()->update('captcha_sessions')
->condition('csid', $captcha_sid)
->fields([
'timestamp' => REQUEST_TIME,
......@@ -134,7 +134,13 @@ function _captcha_required_for_user($captcha_sid, $form_id) {
}
// Get the status of the current CAPTCHA session.
$captcha_session_status = db_query('SELECT status FROM {captcha_sessions} WHERE csid = :csid', [':csid' => $captcha_sid])->fetchField();
$captcha_session_status = \Drupal::database()
->select('captcha_sessions', 'cs')
->fields('cs', ['status'])
->condition('csid', $captcha_sid)
->execute()
->fetchField();
// Second check: if the current session is already
// solved: omit further CAPTCHAs.
if ($captcha_session_status == CAPTCHA_STATUS_SOLVED) {
......
......@@ -14,8 +14,10 @@ use Drupal\Component\Utility\Unicode;
use Drupal\Core\Database\Database;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Render\Markup;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Drupal\Core\Render\Element;
/**
* Constants for CAPTCHA persistence.
......@@ -52,8 +54,8 @@ function captcha_help($route_name, RouteMatchInterface $route_match) {
$output = '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('"CAPTCHA" is an acronym for "Completely Automated Public Turing test to tell Computers and Humans Apart". It is typically a challenge-response test to determine whether the user is human. The CAPTCHA module is a tool to fight automated submission by malicious users (spamming) of for example comments forms, user registration forms, guestbook forms, etc. You can extend the desired forms with an additional challenge, which should be easy for a human to solve correctly, but hard enough to keep automated scripts and spam bots out.') . '</p>';
$output .= '<p>' . t('Note that the CAPTCHA module interacts with page caching (see <a href=":performancesettings">performance settings</a>). Because the challenge should be unique for each generated form, the caching of the page it appears on is prevented. Make sure that these forms do not appear on too many pages or you will lose much caching efficiency. For example, if you put a CAPTCHA on the user login block, which typically appears on each page for anonymous visitors, caching will practically be disabled. The comment submission forms are another example. In this case you should set the <em>Location of comment submission form</em> to <em>Display on separate page</em> in the comment settings of the relevant <a href=":contenttypes">content types</a> for better caching efficiency.', [
':performancesettings' => \Drupal::url('system.performance_settings'),
':contenttypes' => \Drupal::url('entity.node_type.collection'),
':performancesettings' => Url::fromRoute('system.performance_settings'),
':contenttypes' => Url::fromRoute('entity.node_type.collection'),
]) . '</p>';
$output .= '<p>' . t('CAPTCHA is a trademark of Carnegie Mellon University.') . '</p>';
return ['#markup' => $output];
......@@ -61,10 +63,10 @@ function captcha_help($route_name, RouteMatchInterface $route_match) {
case 'captcha_settings':
$output = '<p>' . t('A CAPTCHA can be added to virtually each Drupal form. Some default forms are already provided in the form list, but arbitrary forms can be easily added and managed when the option <em>Add CAPTCHA administration links to forms</em> is enabled.') . '</p>';
$output .= '<p>' . t('Users with the <em>Skip CAPTCHA</em> <a href=":perm">permission</a> won\'t be offered a challenge. Be sure to grant this permission to the trusted users (e.g. site administrators). If you want to test a protected form, be sure to do it as a user without the <em>Skip CAPTCHA</em> permission (e.g. as anonymous user).', [
':perm' => \Drupal::url('user.admin_permissions'),
':perm' => Url::fromRoute('user.admin_permissions'),
]) . '</p>';
$output .= '<p><b>' . t('Note that the CAPTCHA module disables <a href=":performancesettings">page caching</a> of pages that include a CAPTCHA challenge.', [
':performancesettings' => \Drupal::url('system.performance_settings'),
':performancesettings' => Url::fromRoute('system.performance_settings'),
]) . '</b></p>';
return ['#markup' => $output];
}
......@@ -119,11 +121,19 @@ function template_preprocess_captcha(&$variables) {
$element = $variables['element'];
if (!empty($element['#description']) && isset($element['captcha_widgets'])) {
$children_keys = Element::children($element);
$captcha_children_output = '';
foreach ($children_keys as $key) {
if (!empty($element[$key])) {
$captcha_children_output .= \Drupal::service('renderer')->render($element[$key]);
}
}
$variables['details'] = [
'#type' => 'details',
'#title' => t('CAPTCHA'),
'#description' => $element['#description'],
'#children' => drupal_render_children($element),
'#children' => Markup::create($captcha_children_output),
'#attributes' => [
'class' => ['captcha'],
'open' => [''],
......@@ -356,17 +366,20 @@ function _captcha_get_posted_captcha_info(array $element, FormStateInterface $fo
// and the database query should also be more efficient (because there is
// an index on the CAPTCHA session ID).
if ($posted_captcha_sid != NULL) {
$expected_captcha_token = db_query(
"SELECT token FROM {captcha_sessions} WHERE csid = :csid",
[':csid' => $posted_captcha_sid]
)->fetchField();
$expected_captcha_token = \Drupal::database()
->select('captcha_sessions', 'cs')
->fields('cs', ['token'])
->condition('csid', $posted_captcha_sid)
->execute()
->fetchField();
if ($expected_captcha_token !== $posted_captcha_token) {
drupal_set_message(t('CAPTCHA session reuse attack detected.'), 'error');
// Invalidate the CAPTCHA session.
$posted_captcha_sid = NULL;
}
// Invalidate CAPTCHA token to avoid reuse.
db_update('captcha_sessions')
\Drupal::database()->update('captcha_sessions')
->fields(['token' => NULL])
->condition('csid', $posted_captcha_sid);
}
......@@ -400,10 +413,11 @@ function captcha_validate($element, FormStateInterface &$form_state) {
// TODO: is this correct in all cases: see comments in previous revisions?
$csid = $captcha_info['captcha_sid'];
$solution = db_query(
'SELECT solution FROM {captcha_sessions} WHERE csid = :csid',
[':csid' => $csid]
)
$solution = \Drupal::database()
->select('captcha_sessions', 'cs')
->fields('cs', ['solution'])
->condition('csid', $csid)
->execute()
->fetchField();
// @todo: what is the result when there is no entry for
......@@ -431,7 +445,7 @@ function captcha_validate($element, FormStateInterface &$form_state) {
// Correct answer.
$_SESSION['captcha_success_form_ids'][$form_id] = $form_id;
// Record success.
db_update('captcha_sessions')
\Drupal::database()->update('captcha_sessions')
->condition('csid', $csid)
->fields(['status' => CAPTCHA_STATUS_SOLVED])
->expression('attempts', 'attempts + 1')
......@@ -439,7 +453,7 @@ function captcha_validate($element, FormStateInterface &$form_state) {
}
else {
// Wrong answer.
db_update('captcha_sessions')
\Drupal::database()->update('captcha_sessions')
->condition('csid', $csid)
->expression('attempts', 'attempts + 1')
->execute();
......
services:
captcha.config_subscriber:
class: Drupal\captcha\EventSubscriber\CaptchaCachedSettingsSubscriber
arguments: ['@element_info']
tags:
- { name: event_subscriber }
......@@ -51,9 +51,12 @@ class CaptchaImageResponse extends Response {
public function prepare(Request $request) {
$session_id = $request->get('session_id');
$code = db_query("SELECT solution FROM {captcha_sessions} WHERE csid = :csid",
[':csid' => $session_id]
)->fetchField();
$code = \Drupal::database()
->select('captcha_sessions', 'cs')
->fields('cs', ['solution'])
->condition('csid', $session_id)
->execute()
->fetchField();
if ($code !== FALSE) {
$this->image = @$this->generateImage($code);
......@@ -374,7 +377,7 @@ class CaptchaImageResponse extends Response {
// Get character dimensions for TrueType fonts.
if ($font != 'BUILTIN') {
putenv('GDFONTPATH=' . realpath('.'));
$bbox = imagettfbbox($font_size, 0, drupal_realpath($font), $character);
$bbox = imagettfbbox($font_size, 0, \Drupal::service('file_system')->realpath($font), $character);
// In very rare cases with some versions of the GD library, the x-value
// of the left side of the bounding box as returned by the first call of
// imagettfbbox is corrupt (value -2147483648 = 0x80000000).
......@@ -382,7 +385,7 @@ class CaptchaImageResponse extends Response {
// can be used as workaround.
// This issue is discussed at http://drupal.org/node/349218.
if ($bbox[2] < 0) {
$bbox = imagettfbbox($font_size, 0, drupal_realpath($font), $character);
$bbox = imagettfbbox($font_size, 0, \Drupal::service('file_system')->realpath($font), $character);
}
}
else {
......@@ -438,7 +441,7 @@ class CaptchaImageResponse extends Response {
imagestring($image, 5, $pos_x, $pos_y, $character, $color);
}
else {
imagettftext($image, $font_size, $angle, $pos_x, $pos_y, $color, drupal_realpath($font), $character);
imagettftext($image, $font_size, $angle, $pos_x, $pos_y, $color, \Drupal::service('file_system')->realpath($font), $character);
}
}
......
......@@ -2,15 +2,52 @@
namespace Drupal\captcha\Element;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Render\Element\FormElement;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Defines the CAPTCHA form element with default properties.
*
* @FormElement("captcha")
*/
class Captcha extends FormElement {
class Captcha extends FormElement implements ContainerFactoryPluginInterface {
/**
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* Captcha constructor.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin ID for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
* The configuration factory.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $configFactory) {
$this->configFactory = $configFactory;
parent::__construct($configuration, $plugin_id, $plugin_definition);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('config.factory')
);
}
/**
* {@inheritdoc}
......@@ -32,7 +69,7 @@ class Captcha extends FormElement {
// Override the default CAPTCHA validation function for case
// insensitive validation.
// TODO: shouldn't this be done somewhere else, e.g. in form_alter?
if (CAPTCHA_DEFAULT_VALIDATION_CASE_INSENSITIVE == \Drupal::config('captcha.settings')
if (CAPTCHA_DEFAULT_VALIDATION_CASE_INSENSITIVE == $this->configFactory->get('captcha.settings')
->get('default_validation')
) {
$captcha_element['#captcha_validate'] = 'captcha_validate_case_insensitive_equality';
......@@ -74,7 +111,7 @@ class Captcha extends FormElement {
// not reuse one from a posted form.
$captcha_sid = _captcha_generate_captcha_session($this_form_id, CAPTCHA_STATUS_UNSOLVED);
$captcha_token = md5(mt_rand());
db_update('captcha_sessions')
\Drupal::database()->update('captcha_sessions')
->fields(['token' => $captcha_token])
->condition('csid', $captcha_sid)
->execute();
......@@ -96,7 +133,14 @@ class Captcha extends FormElement {
// ->fields(['token' => $captcha_token])
// ->condition('csid', $captcha_sid)
// ->execute();
$captcha_token = db_query("SELECT token FROM {captcha_sessions} WHERE csid = :csid", [':csid' => $captcha_sid])->fetchField();
$captcha_token = \Drupal::database()
->select('captcha_sessions', 'cs')
->fields('cs', ['token'])
->condition('csid', $captcha_sid)
->execute()
->fetchField();
$element['captcha_token'] = [
'#type' => 'hidden',
'#value' => $captcha_token,
......
......@@ -99,8 +99,10 @@ class CaptchaPoint extends ConfigEntityBase implements CaptchaPointInterface {
return $this->captchaType;
}
else {
// @Todo inject config via DI.
return \Drupal::config('captcha.settings')->get('default_challenge');
return static::getConfigManager()
->getConfigFactory()
->get('captcha.settings')
->get('default_challenge');
}
}
......
......@@ -4,6 +4,7 @@ namespace Drupal\captcha\EventSubscriber;
use Drupal\Core\Config\ConfigCrudEvent;
use Drupal\Core\Config\ConfigEvents;
use Drupal\Core\Render\ElementInfoManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
......@@ -11,6 +12,20 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
*/
class CaptchaCachedSettingsSubscriber implements EventSubscriberInterface {
/**
* @var \Drupal\Core\Render\ElementInfoManagerInterface
*/
protected $elementInfo;
/**
* CaptchaCachedSettingsSubscriber constructor.
*
* @param \Drupal\Core\Render\ElementInfoManagerInterface $elementInfo
*/
public function __construct(ElementInfoManagerInterface $elementInfo) {
$this->elementInfo = $elementInfo;
}
/**
* Clearing the cached definitions whenever the settings are modified.
*
......@@ -21,7 +36,7 @@ class CaptchaCachedSettingsSubscriber implements EventSubscriberInterface {
// Changing the Captcha settings means that any page might result in other
// settings for captcha so the cached definitions need to be cleared.
if ($event->getConfig()->getName() === 'captcha.settings') {
\Drupal::service('element_info')->clearCachedDefinitions();
$this->elementInfo->clearCachedDefinitions();
}
}
......
......@@ -2,16 +2,41 @@
namespace Drupal\captcha\Form;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Displays the captcha settings form.
*/
class CaptchaExamplesForm extends FormBase {
/**
* @var \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler
*/
protected $moduleHandler;
/**
* CaptchaExamplesForm constructor.
*
* @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler
*/
public function __construct(ModuleHandlerInterface $moduleHandler) {
$this->moduleHandler = $moduleHandler;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('module_handler')
);
}
/**
* {@inheritdoc}
*/
......@@ -38,7 +63,7 @@ class CaptchaExamplesForm extends FormBase {
'#markup' => $this->t('This page gives an overview of all available challenge types, generated with their current settings.'),
];
$modules_list = \Drupal::moduleHandler()->getImplementations('captcha');
$modules_list = $this->moduleHandler->getImplementations('captcha');
foreach ($modules_list as $mkey => $module) {
$challenges = call_user_func_array($module . '_captcha', ['list']);
......
......@@ -4,12 +4,39 @@ namespace Drupal\captcha\Form;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* Entity Form to edit CAPTCHA points.
*/
class CaptchaPointForm extends EntityForm {
/**
* @var \Symfony\Component\HttpFoundation\RequestStack
*/
protected $requestStack;
/**
* CaptchaPointForm constructor.
*
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
*/
public function __construct(RequestStack $request_stack) {
$this->requestStack = $request_stack;
}
/**
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
*
* @return static
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('request_stack')
);
}
/**
* {@inheritdoc}
*/
......@@ -22,7 +49,7 @@ class CaptchaPointForm extends EntityForm {
$captcha_point = $this->entity;
// Support to set a default form_id through a query argument.
$request = \Drupal::request();
$request = $this->requestStack->getCurrentRequest();
if ($captcha_point->isNew() && !$captcha_point->id() && $request->query->has('form_id')) {
$captcha_point->set('formId', $request->query->get('form_id'));
$captcha_point->set('label', $request->query->get('form_id'));
......
......@@ -4,6 +4,7 @@ namespace Drupal\captcha\Form;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
......@@ -21,6 +22,11 @@ class CaptchaSettingsForm extends ConfigFormBase {
*/
protected $cacheBackend;
/**
* @var \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler
*/
protected $moduleHandler;
/**
* Constructs a \Drupal\captcha\Form\CaptchaSettingsForm object.
*
......@@ -28,10 +34,13 @@ class CaptchaSettingsForm extends ConfigFormBase {
* The factory for configuration objects.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
* Cache backend instance to use.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler
* Module handler.
*/
public function __construct(ConfigFactoryInterface $config_factory, CacheBackendInterface $cache_backend) {
public function __construct(ConfigFactoryInterface $config_factory, CacheBackendInterface $cache_backend, ModuleHandlerInterface $moduleHandler) {
parent::__construct($config_factory);
$this->cacheBackend = $cache_backend;
$this->moduleHandler = $moduleHandler;
}
/**
......@@ -40,7 +49,8 @@ class CaptchaSettingsForm extends ConfigFormBase {
public static function create(ContainerInterface $container) {
return new static(
$container->get('config.factory'),
$container->get('cache.default')
$container->get('cache.default'),
$container->get('module_handler')
);
}
......@@ -179,7 +189,7 @@ class CaptchaSettingsForm extends ConfigFormBase {
];
// Replace the description with a link if dblog.module is enabled.
if (\Drupal::moduleHandler()->moduleExists('dblog')) {
if ($this->moduleHandler->moduleExists('dblog')) {
$form['log_wrong_responses']['#description'] = $this->t('Report information about wrong responses to the <a href=":dblog">log</a>.', [
':dblog' => Url::fromRoute('dblog.overview')->toString(),
]);
......
......@@ -6,6 +6,7 @@ use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
use Drupal\comment\Tests\CommentTestTrait;
use Drupal\field\Entity\FieldConfig;
use Drupal\simpletest\WebTestBase;
use Drupal\Core\Session\AccountInterface;
/**
* The TODO list.
......@@ -270,7 +271,7 @@ abstract class CaptchaBaseWebTestCase extends WebTestBase {
*/
protected function allowCommentPostingForAnonymousVisitors() {
// Enable anonymous comments.
user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, [
user_role_grant_permissions(AccountInterface::ANONYMOUS_ROLE, [
'access comments',
'post comments',
'skip comment approval',
......
......@@ -2,6 +2,7 @@
namespace Drupal\captcha\Tests;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
......@@ -39,7 +40,7 @@ class CaptchaTestCase extends CaptchaBaseWebTestCase {
$captcha_point->enable()->save();
// Check if there is a CAPTCHA on the login form (look for the title).
$this->drupalGet('');
$this->drupalGet('user');
$this->assertCaptchaPresence(TRUE);
// Try to log in, which should fail.
......@@ -218,7 +219,7 @@ class CaptchaTestCase extends CaptchaBaseWebTestCase {
*/
public function testAjaxFormRebuild() {
// Setup captcha point for user edit form.
\Drupal::entityManager()->getStorage('captcha_point')->create([
\Drupal::entityTypeManager()->getStorage('captcha_point')->create([
'id' => 'user_form',
'formId' => 'user_form',
'status' => TRUE,
......@@ -237,7 +238,18 @@ class CaptchaTestCase extends CaptchaBaseWebTestCase {
'field_storage' => $field_storage_config,
'bundle' => 'user',
])->save();
entity_get_form_display('user', 'user', 'default')
$entity_form_display = EntityFormDisplay::load('user.user.default');
if (!$entity_form_display) {
$entity_form_display = EntityFormDisplay::create(array(
'targetEntityType' => 'user',
'bundle' => 'user',
'mode' => 'default',
'status' => TRUE,
));
}
$entity_form_display
->setComponent('field_texts', [
'type' => 'string_textfield',
'weight' => 10,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment