Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Open sidebar
drupal.org
captcha
Commits
e8d540bb
Commit
e8d540bb
authored
Apr 16, 2021
by
Jakob Perry
Browse files
Issue #2036925 by japerry: d7 to D8/9 Migration Path
parent
e1dc28f8
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
1073 additions
and
0 deletions
+1073
-0
migrations/d7_captcha_points.yml
migrations/d7_captcha_points.yml
+17
-0
migrations/d7_captcha_sessions.yml
migrations/d7_captcha_sessions.yml
+35
-0
migrations/d7_captcha_settings.yml
migrations/d7_captcha_settings.yml
+36
-0
src/Plugin/migrate/destination/Table.php
src/Plugin/migrate/destination/Table.php
+309
-0
src/Plugin/migrate/process/CaptchaTypeFormatter.php
src/Plugin/migrate/process/CaptchaTypeFormatter.php
+34
-0
src/Plugin/migrate/source/CaptchaPoints.php
src/Plugin/migrate/source/CaptchaPoints.php
+77
-0
src/Plugin/migrate/source/CaptchaSessions.php
src/Plugin/migrate/source/CaptchaSessions.php
+50
-0
tests/fixtures/drupal7.php
tests/fixtures/drupal7.php
+256
-0
tests/src/Kernel/Migrate/d7/MigrateCaptchaPointsTest.php
tests/src/Kernel/Migrate/d7/MigrateCaptchaPointsTest.php
+90
-0
tests/src/Kernel/Migrate/d7/MigrateCaptchaSessionsTest.php
tests/src/Kernel/Migrate/d7/MigrateCaptchaSessionsTest.php
+103
-0
tests/src/Kernel/Migrate/d7/MigrateCaptchaSimpleConfigurationTest.php
...rnel/Migrate/d7/MigrateCaptchaSimpleConfigurationTest.php
+66
-0
No files found.
migrations/d7_captcha_points.yml
0 → 100644
View file @
e8d540bb
id
:
d7_captcha_points
label
:
'
Captcha
Points
Table'
migration_tags
:
-
Drupal
7
source
:
plugin
:
d7_captcha_points
process
:
formId
:
form_id
label
:
form_id
captchaType
:
plugin
:
captcha_type_formatter
source
:
captcha_type
status
:
plugin
:
default_value
default_value
:
TRUE
destination
:
plugin
:
entity:captcha_point
\ No newline at end of file
migrations/d7_captcha_sessions.yml
0 → 100644
View file @
e8d540bb
id
:
d7_captcha_sessions
label
:
'
Captcha
Sessions
Table'
migration_tags
:
-
Drupal
7
source
:
plugin
:
d7_captcha_sessions
process
:
csid
:
csid
token
:
token
uid
:
uid
sid
:
sid
ip_address
:
ip_address
timestamp
:
timestamp
form_id
:
form_id
solution
:
solution
status
:
status
attempts
:
attempts
destination
:
plugin
:
table
table_name
:
captcha_sessions
id_fields
:
csid
:
type
:
integer
fields
:
csid
:
csid
token
:
token
uid
:
uid
sid
:
sid
ip_address
:
ip_address
timestamp
:
timestamp
form_id
:
form_id
solution
:
solution
status
:
status
attempts
:
attempts
migration_dependencies
:
{
}
migrations/d7_captcha_settings.yml
0 → 100644
View file @
e8d540bb
id
:
d7_captcha_settings
label
:
'
Captcha
Settings'
migration_tags
:
-
Drupal
7
-
Configuration
source
:
plugin
:
variable
variables
:
-
captcha_add_captcha_description
-
captcha_administration_mode
-
captcha_allow_on_admin_pages
-
captcha_default_challenge
-
captcha_default_challenge_on_nonlisted_forms
-
captcha_default_validation
-
captcha_description
-
captcha_enable_stats
-
captcha_error_message
-
captcha_log_wrong_responses
-
captcha_persistence
-
captcha_placement_map_cache
source_module
:
-
captcha
process
:
enabled_default
:
captcha_default_challenge_on_nonlisted_forms
default_challenge
:
captcha_default_challenge
description
:
captcha_description
administration_mode
:
captcha_administration_mode
allow_on_admin_pages
:
captcha_allow_on_admin_pages
add_captcha_description
:
captcha_add_captcha_description
default_validation
:
captcha_default_validation
persistence
:
captcha_persistence
enable_stats
:
captcha_enable_stats
log_wrong_responses
:
captcha_log_wrong_responses
destination
:
plugin
:
config
config_name
:
captcha.settings
src/Plugin/migrate/destination/Table.php
0 → 100644
View file @
e8d540bb
<?php
namespace
Drupal\captcha\Plugin\migrate\destination
;
use
Drupal\Core\Database\Connection
;
use
Drupal\Core\Database\Database
;
use
Drupal\Core\Plugin\ContainerFactoryPluginInterface
;
use
Drupal\migrate\Event\ImportAwareInterface
;
use
Drupal\migrate\Event\MigrateImportEvent
;
use
Drupal\migrate\MigrateException
;
use
Drupal\migrate\MigrateSkipProcessException
;
use
Drupal\migrate\Plugin\migrate\destination\DestinationBase
;
use
Drupal\migrate\Plugin\MigrationInterface
;
use
Drupal\migrate\Row
;
use
Symfony\Component\DependencyInjection\ContainerInterface
;
/**
* Provides table destination plugin.
*
* Copied from the 'migrate_plus' module to avoid a dependency.
* Use this plugin for a table not registered with Drupal Schema API.
*
* Examples:
*
* @code
* destination:
* plugin: table
* # Key for the database connection to use for inserting records.
* database_key: roads_db
* # DB table for storage.
* table_name: roads
* # Maximum number of rows to insert in one query.
* batch_size: 3
* # Fields used by migrate to identify table rows uniquely. At least one
* # field is required.
* id_fields:
* name:
* type: string
* suburb:
* type: string
* ward:
* type: string
* # Mapping of column names to values set in migrate process.
* fields:
* name: name
* owner: owner
* suburb: suburb
* ward: ward
* type: type
* @endcode
*
* For numeric id fields, migrate can generate the values on-the-fly, by
* enabling use_auto_increment; in such case, the id field may be ommitted from
* the 'fields' section:
*
* @code
* destination:
* plugin: table
* # ...
* id_fields:
* my_id_field:
* type: integer
* use_auto_increment: true
* # ...
* fields:
* non_my_id_field_1: non_my_id_field_1
* non_my_id_field_2: non_my_id_field_2
* @endcode
*
* @MigrateDestination(
* id = "table"
* )
*/
class
Table
extends
DestinationBase
implements
ContainerFactoryPluginInterface
,
ImportAwareInterface
{
/**
* The name of the destination table.
*
* @var string
*/
protected
$tableName
;
/**
* IDMap compatible array of id fields.
*
* @var array
*/
protected
$idFields
;
/**
* Array of fields present on the destination table.
*
* @var array
*/
protected
$fields
;
/**
* The database connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected
$dbConnection
;
/**
* Maximum number of rows to insert in one query.
*
* @var int
*/
protected
$batchSize
;
/**
* The query object being built row-by-row.
*
* @var array
*/
protected
$rowsToInsert
=
[];
/**
* The highest ID seen or created so far on this table.
*
* @var int
*/
protected
$lastId
=
0
;
/**
* Constructs a new Table.
*
* @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\migrate\Plugin\MigrationInterface $migration
* The migration.
* @param \Drupal\Core\Database\Connection $connection
* The database connection.
*/
public
function
__construct
(
array
$configuration
,
$plugin_id
,
$plugin_definition
,
MigrationInterface
$migration
,
Connection
$connection
)
{
parent
::
__construct
(
$configuration
,
$plugin_id
,
$plugin_definition
,
$migration
);
$this
->
dbConnection
=
$connection
;
$this
->
tableName
=
$configuration
[
'table_name'
];
$this
->
idFields
=
$configuration
[
'id_fields'
];
$this
->
fields
=
isset
(
$configuration
[
'fields'
])
?
$configuration
[
'fields'
]
:
[];
$this
->
batchSize
=
isset
(
$configuration
[
'batch_size'
])
?
$configuration
[
'batch_size'
]
:
1
;
$this
->
supportsRollback
=
TRUE
;
}
/**
* {@inheritdoc}
*/
public
static
function
create
(
ContainerInterface
$container
,
array
$configuration
,
$plugin_id
,
$plugin_definition
,
MigrationInterface
$migration
=
NULL
)
{
$db_key
=
!
empty
(
$configuration
[
'database_key'
])
?
$configuration
[
'database_key'
]
:
NULL
;
return
new
static
(
$configuration
,
$plugin_id
,
$plugin_definition
,
$migration
,
Database
::
getConnection
(
'default'
,
$db_key
)
);
}
/**
* {@inheritdoc}
*/
public
function
getIds
()
{
if
(
empty
(
$this
->
idFields
))
{
throw
new
MigrateException
(
'Id fields are required for a table destination'
);
}
return
$this
->
idFields
;
}
/**
* {@inheritdoc}
*/
public
function
fields
(
MigrationInterface
$migration
=
NULL
)
{
return
$this
->
fields
;
}
/**
* {@inheritdoc}
*/
public
function
import
(
Row
$row
,
array
$old_destination_id_values
=
[])
{
// Skip batching (if configured) for updates.
$batch_inserts
=
(
$this
->
batchSize
>
1
&&
empty
(
$old_destination_id_values
));
$ids
=
[];
foreach
(
$this
->
idFields
as
$field
=>
$fieldInfo
)
{
if
(
$row
->
hasDestinationProperty
(
$field
))
{
$ids
[
$field
]
=
$row
->
getDestinationProperty
(
$field
);
}
elseif
(
!
$row
->
hasDestinationProperty
(
$field
)
&&
empty
(
$fieldInfo
[
'use_auto_increment'
]))
{
throw
new
MigrateSkipProcessException
(
'All the id fields are required for a table migration.'
);
}
// When batching, we do the auto-incrementing ourselves.
elseif
(
$batch_inserts
&&
$fieldInfo
[
'use_auto_increment'
])
{
if
(
count
(
$this
->
rowsToInsert
)
===
0
)
{
// Get the highest existing ID, so we will create IDs above it.
$this
->
lastId
=
$this
->
dbConnection
->
query
(
"SELECT MAX(
$field
) AS MaxId FROM
{
{$this->tableName}
}
"
)
->
fetchField
();
if
(
!
$this
->
lastId
)
{
$this
->
lastId
=
0
;
}
}
$id
=
++
$this
->
lastId
;
$ids
[
$field
]
=
$id
;
$row
->
setDestinationProperty
(
$field
,
$id
);
}
}
// When batching, make sure we have the same properties in the same order
// every time.
$values
=
[];
if
(
$batch_inserts
)
{
$destination_properties
=
array_keys
(
$this
->
migration
->
getProcess
());
$destination_properties
=
array_merge
(
$destination_properties
,
array_keys
(
$this
->
idFields
));
sort
(
$destination_properties
);
$destination_values
=
$row
->
getDestination
();
foreach
(
$destination_properties
as
$property_name
)
{
$values
[
$property_name
]
=
$destination_values
[
$property_name
]
??
NULL
;
}
}
else
{
$values
=
$row
->
getDestination
();
}
if
(
$this
->
fields
)
{
$values
=
array_intersect_key
(
$values
,
$this
->
fields
);
}
if
(
$batch_inserts
)
{
$this
->
rowsToInsert
[]
=
$values
;
if
(
count
(
$this
->
rowsToInsert
)
>=
$this
->
batchSize
)
{
$this
->
flushInserts
();
}
$status
=
TRUE
;
}
// Row contains empty id field with use_auto_increment enabled.
elseif
(
count
(
$ids
)
<
count
(
$this
->
idFields
))
{
$status
=
$id
=
$this
->
dbConnection
->
insert
(
$this
->
tableName
)
->
fields
(
$values
)
->
execute
();
foreach
(
$this
->
idFields
as
$field
=>
$fieldInfo
)
{
if
(
isset
(
$fieldInfo
[
'use_auto_increment'
])
&&
$fieldInfo
[
'use_auto_increment'
]
===
TRUE
&&
!
$row
->
hasDestinationProperty
(
$field
))
{
$row
->
setDestinationProperty
(
$field
,
$id
);
$ids
[
$field
]
=
$id
;
}
}
}
else
{
$status
=
$this
->
dbConnection
->
merge
(
$this
->
tableName
)
->
keys
(
$ids
)
->
fields
(
$values
)
->
execute
();
}
return
$status
?
$ids
:
NULL
;
}
/**
* {@inheritdoc}
*/
public
function
rollback
(
array
$destination_identifier
)
{
$delete
=
$this
->
dbConnection
->
delete
(
$this
->
tableName
);
foreach
(
$destination_identifier
as
$field
=>
$value
)
{
$delete
->
condition
(
$field
,
$value
);
}
$delete
->
execute
();
}
/**
* Execute the insert query and reset everything.
*/
public
function
flushInserts
()
{
if
(
count
(
$this
->
rowsToInsert
)
>
0
)
{
$batch_query
=
$this
->
dbConnection
->
insert
(
$this
->
tableName
)
->
fields
(
array_keys
(
$this
->
rowsToInsert
[
0
]));
foreach
(
$this
->
rowsToInsert
as
$row
)
{
$batch_query
->
values
(
array_values
(
$row
));
}
// Empty the queue first, so if the statement throws an error we don't
// end up here trying to execute the same statement (plus one row).
$this
->
rowsToInsert
=
[];
$batch_query
->
execute
();
}
}
/**
* {@inheritDoc}
*/
public
function
preImport
(
MigrateImportEvent
$event
)
{
}
/**
* {@inheritDoc}
*/
public
function
postImport
(
MigrateImportEvent
$event
)
{
// At the conclusion of a given migration, make sure batched inserts go in.
$this
->
flushInserts
();
}
/**
* Make absolutely sure batched inserts are processed (especially for stubs).
*/
public
function
__destruct
()
{
// At the conclusion of a given migration, make sure batched inserts go in.
$this
->
flushInserts
();
}
}
src/Plugin/migrate/process/CaptchaTypeFormatter.php
0 → 100644
View file @
e8d540bb
<?php
namespace
Drupal\captcha\Plugin\migrate\process
;
use
Drupal\migrate\MigrateExecutableInterface
;
use
Drupal\migrate\ProcessPluginBase
;
use
Drupal\migrate\Row
;
/**
* Perform captcha type transformation.
*
* @MigrateProcessPlugin(
* id = "captcha_type_formatter"
* )
*
* To do custom value transformations use the following:
*
* @code
* field_text:
* plugin: captcha_type_formatter
* source: text
* @endcode
*/
class
CaptchaTypeFormatter
extends
ProcessPluginBase
{
/**
* Transforms the d7 separate captcha type and module into one row.
*/
public
function
transform
(
$value
,
MigrateExecutableInterface
$migrate_executable
,
Row
$row
,
$destination_property
)
{
$module
=
$row
->
getSourceProperty
(
'module'
)
??
'captcha'
;
$type
=
$row
->
getSourceProperty
(
'captcha_type'
);
return
$module
.
'/'
.
$type
;
}
}
src/Plugin/migrate/source/CaptchaPoints.php
0 → 100644
View file @
e8d540bb
<?php
namespace
Drupal\captcha\Plugin\migrate\source
;
use
Drupal\Core\Entity\EntityTypeManagerInterface
;
use
Drupal\Core\Extension\ModuleHandlerInterface
;
use
Drupal\Core\State\StateInterface
;
use
Drupal\migrate\Plugin\MigrationInterface
;
use
Drupal\migrate\Row
;
use
Drupal\migrate_drupal
\
Plugin\migrate\source\DrupalSqlBase
;
use
Symfony\Component\DependencyInjection\ContainerInterface
;
/**
* Drupal 7 captcha point source from database.
*
* @MigrateSource(
* id = "d7_captcha_points",
* source_module = "captcha"
* )
*/
class
CaptchaPoints
extends
DrupalSqlBase
{
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected
$moduleHandler
;
/**
* {@inheritdoc}
*/
public
function
__construct
(
array
$configuration
,
$plugin_id
,
$plugin_definition
,
MigrationInterface
$migration
,
StateInterface
$state
,
EntityTypeManagerInterface
$entity_type_manager
,
ModuleHandlerInterface
$module_handler
)
{
parent
::
__construct
(
$configuration
,
$plugin_id
,
$plugin_definition
,
$migration
,
$state
,
$entity_type_manager
);
$this
->
moduleHandler
=
$module_handler
;
}
/**
* {@inheritdoc}
*/
public
static
function
create
(
ContainerInterface
$container
,
array
$configuration
,
$plugin_id
,
$plugin_definition
,
MigrationInterface
$migration
=
NULL
)
{
return
new
static
(
$configuration
,
$plugin_id
,
$plugin_definition
,
$migration
,
$container
->
get
(
'state'
),
$container
->
get
(
'entity_type.manager'
),
$container
->
get
(
'module_handler'
)
);
}
/**
* {@inheritdoc}
*/
public
function
query
()
{
return
$this
->
select
(
'captcha_points'
,
'c'
)
->
fields
(
'c'
);
}
/**
* {@inheritdoc}
*/
public
function
fields
()
{
return
[
'form_id'
=>
$this
->
t
(
'The name of the form'
),
'module'
=>
$this
->
t
(
'The captcha point providing module.'
),
'captcha_type'
=>
$this
->
t
(
'The captcha type.'
),
];
}
/**
* {@inheritdoc}
*/
public
function
getIds
()
{
$ids
[
'form_id'
][
'type'
]
=
'string'
;
return
$ids
;
}
}
\ No newline at end of file
src/Plugin/migrate/source/CaptchaSessions.php
0 → 100644
View file @
e8d540bb
<?php
namespace
Drupal\captcha\Plugin\migrate\source
;
use
Drupal\migrate\Row
;
use
Drupal\migrate_drupal
\
Plugin\migrate\source\DrupalSqlBase
;
/**
* Drupal 7 captcha sessions from database.
*
* @MigrateSource(
* id = "d7_captcha_sessions",
* source_module = "captcha"
* )
*/
class
CaptchaSessions
extends
DrupalSqlBase
{
/**
* {@inheritdoc}
*/
public
function
query
()
{
return
$this
->
select
(
'captcha_sessions'
,
'c'
)
->
fields
(
'c'
);
}
/**
* {@inheritdoc}
*/
public
function
fields
()
{
return
[
'csid'
=>
$this
->
t
(
'CAPTCHA session ID.'
),
'token'
=>
$this
->
t
(
'One time CAPTCHA token.'
),
'uid'
=>
$this
->
t
(
"User's
{
users
}
.uid."
),
'sid'
=>
$this
->
t
(
"Session ID of the user."
),
'ip_address'
=>
$this
->
t
(
'IP address of the visitor.'
),
'timestamp'
=>
$this
->
t
(
'A Unix timestamp indicating when the challenge was generated.'
),
'form_id'
=>
$this
->
t
(
'The form_id of the form where the CAPTCHA is added to.'
),
'solution'
=>
$this
->
t
(
'Solution of the challenge.'
),
'status'
=>
$this
->
t
(
'Status of the CAPTCHA session (unsolved, solved, ...)'
),
'attempts'
=>
$this
->
t
(
'The number of attempts.'
),
];
}
/**
* {@inheritdoc}
*/
public
function
getIds
()
{
$ids
[
'csid'
][
'type'
]
=
'integer'
;
return
$ids
;
}
}
\ No newline at end of file
tests/fixtures/drupal7.php
0 → 100644
View file @
e8d540bb
<?php
/**
* @file
* A database agnostic dump for testing purposes.
*/
use
Drupal\Core\Database\Database
;
$connection
=
Database
::
getConnection
();
$connection
->
insert
(
'variable'
)
->
fields
([
'name'
,
'value'
,
])
->
values
([
'name'
=>
'captcha_add_captcha_description'
,
'value'
=>
'i:1;'
,
])
->
values
([
'name'
=>
'captcha_administration_mode'
,
'value'
=>
'i:1;'
,
])
->
values
([
'name'
=>
'captcha_allow_on_admin_pages'
,
'value'
=>
'i:0;'
,
])
->
values
([
'name'
=>
'captcha_default_challenge'
,
'value'
=>
's:12:"captcha/Math";'
,
])
->
values
([
'name'
=>
'captcha_default_challenge_on_nonlisted_forms'
,
'value'
=>
'i:1;'
,
])
->
values
([
'name'
=>
'captcha_default_validation'
,
'value'
=>
's:1:"1";'
,
])
->
values
([
'name'
=>
'captcha_description'
,
'value'
=>
's:110:"This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.";'
,
])
->
values
([
'name'
=>
'captcha_enable_stats'
,
'value'
=>
'i:1;'
,
])
->
values
([
'name'
=>
'captcha_error_message'
,