rorschach
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
curl --silent --compressed http://example.com/cron/YOURKEY
|
||||
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
/usr/bin/lynx -source http://example.com/cron/YOURKEY > /dev/null 2>&1
|
||||
@@ -0,0 +1,15 @@
|
||||
const fs = require('fs');
|
||||
const log = require('./log');
|
||||
const compile = require('./compile');
|
||||
|
||||
module.exports = (filePath) => {
|
||||
log(`'${filePath}' is being processed.`);
|
||||
// Transform the file.
|
||||
compile(filePath, function write(code) {
|
||||
const fileName = filePath.slice(0, -9);
|
||||
// Write the result to the filesystem.
|
||||
fs.writeFile(`${fileName}.css`, code, () => {
|
||||
log(`'${filePath}' is finished.`);
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
const chalk = require('chalk');
|
||||
const fs = require('fs');
|
||||
const log = require('./log');
|
||||
const compile = require('./compile');
|
||||
|
||||
module.exports = (filePath) => {
|
||||
log(`'${filePath}' is being checked.`);
|
||||
// Transform the file.
|
||||
compile(filePath, function check(code) {
|
||||
const fileName = filePath.slice(0, -9);
|
||||
fs.readFile(`${fileName}.css`, function read(err, data) {
|
||||
if (err) {
|
||||
log(chalk.red(err));
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
if (code !== data.toString()) {
|
||||
log(chalk.red(`'${filePath}' is not updated.`));
|
||||
process.exitCode = 1;
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,95 @@
|
||||
const chalk = require('chalk');
|
||||
const log = require('./log');
|
||||
const fs = require('fs');
|
||||
const postcss = require('postcss');
|
||||
const postcssCalc = require("postcss-calc");
|
||||
const postcssImport = require('postcss-import');
|
||||
const postcssHeader = require('postcss-header');
|
||||
const postcssUrl = require('postcss-url');
|
||||
const postcssPresetEnv = require('postcss-preset-env');
|
||||
// cspell:ignore pxtorem
|
||||
const postcssPixelsToRem = require('postcss-pxtorem');
|
||||
const stylelint = require('stylelint');
|
||||
|
||||
module.exports = (filePath, callback) => {
|
||||
// Transform the file.
|
||||
fs.readFile(filePath, (err, css) => {
|
||||
postcss([
|
||||
postcssImport({
|
||||
plugins: [
|
||||
// On import, remove the comments from variables.pcss.css so they don't
|
||||
// appear as useless comments at the top files that import these
|
||||
// variables.
|
||||
postcss.plugin('remove-unwanted-comments-from-variables', (options) => {
|
||||
return css => {
|
||||
if (css.source.input.file.indexOf('variables.pcss.css') !== -1) {
|
||||
css.walk(node => {
|
||||
if (node.type === 'comment') {
|
||||
node.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}),
|
||||
],
|
||||
}),
|
||||
postcssPresetEnv({
|
||||
stage: 1,
|
||||
preserve: false,
|
||||
autoprefixer: {
|
||||
cascade: false,
|
||||
grid: 'no-autoplace',
|
||||
},
|
||||
features: {
|
||||
'blank-pseudo-class': false,
|
||||
'focus-visible-pseudo-class': false,
|
||||
'focus-within-pseudo-class': false,
|
||||
'has-pseudo-class': false,
|
||||
'image-set-function': false,
|
||||
'prefers-color-scheme-query': false,
|
||||
}
|
||||
}),
|
||||
postcssCalc,
|
||||
postcssPixelsToRem({
|
||||
propList: [
|
||||
'*',
|
||||
'!background-position',
|
||||
'!border',
|
||||
'!border-width',
|
||||
'!box-shadow',
|
||||
'!border-top*',
|
||||
'!border-right*',
|
||||
'!border-bottom*',
|
||||
'!border-left*',
|
||||
'!border-start*',
|
||||
'!border-end*',
|
||||
'!outline*',
|
||||
],
|
||||
mediaQuery: true,
|
||||
minPixelValue: 3,
|
||||
}),
|
||||
postcssHeader({
|
||||
header: `/*\n * DO NOT EDIT THIS FILE.\n * See the following change record for more information,\n * https://www.drupal.org/node/3084859\n * @preserve\n */\n`,
|
||||
}),
|
||||
postcssUrl({
|
||||
filter: '**/*.svg',
|
||||
url: 'inline',
|
||||
optimizeSvgEncode: true,
|
||||
})
|
||||
])
|
||||
.process(css, { from: filePath })
|
||||
.then(result => {
|
||||
return stylelint.lint({
|
||||
code: result.css,
|
||||
fix: true
|
||||
});
|
||||
})
|
||||
.then(result => {
|
||||
callback(result.output);
|
||||
})
|
||||
.catch(error => {
|
||||
log(chalk.red(error));
|
||||
process.exitCode = 1;
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
module.exports = (message) => {
|
||||
// Logging human-readable timestamp.
|
||||
console.log(`[${new Date().toTimeString().slice(0, 8)}] ${message}`);
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Provides the build:css command to compile *.pcss.css files to CSS.
|
||||
*
|
||||
* Run build:css with --file to only parse a specific file. Using the --check
|
||||
* flag build:css can be run to check if files are compiled correctly.
|
||||
* @example <caption>Only process misc/drupal.es6.js and misc/drupal.init.es6.js</caption
|
||||
* yarn run build:css -- --file misc/drupal.pcss.css --file misc/drupal.init.pcss.css
|
||||
* @example <caption>Check if all files have been compiled correctly</caption
|
||||
* yarn run build:css -- --check
|
||||
*
|
||||
* @internal This file is part of the core CSS build process and is only
|
||||
* designed to be used in that context.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const glob = require('glob');
|
||||
const argv = require('minimist')(process.argv.slice(2));
|
||||
const changeOrAdded = require('./changeOrAdded');
|
||||
const check = require('./check');
|
||||
const log = require('./log');
|
||||
|
||||
// Match only on .pcss.css files.
|
||||
const fileMatch = './**/*.pcss.css';
|
||||
// Ignore everything in node_modules
|
||||
const globOptions = {
|
||||
ignore: './node_modules/**'
|
||||
};
|
||||
const processFiles = (error, filePaths) => {
|
||||
if (error) {
|
||||
process.exitCode = 1;
|
||||
}
|
||||
// Process all the found files.
|
||||
let callback = changeOrAdded;
|
||||
if (argv.check) {
|
||||
callback = check;
|
||||
}
|
||||
filePaths.forEach(callback);
|
||||
};
|
||||
|
||||
if (argv.file) {
|
||||
processFiles(null, [].concat(argv.file));
|
||||
}
|
||||
else {
|
||||
glob(fileMatch, globOptions, processFiles);
|
||||
}
|
||||
process.exitCode = 0;
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Watch changes to *.pcss.css files and compile them to CSS during development.
|
||||
*
|
||||
* @internal This file is part of the core CSS build process and is only
|
||||
* designed to be used in that context.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const chokidar = require('chokidar');
|
||||
|
||||
const changeOrAdded = require('./changeOrAdded');
|
||||
const log = require('./log');
|
||||
|
||||
// Match only on .pcss.css files.
|
||||
const fileMatch = './**/*.pcss.css';
|
||||
// Ignore everything in node_modules
|
||||
const watcher = chokidar.watch(fileMatch, {
|
||||
ignoreInitial: true,
|
||||
ignored: './node_modules/**'
|
||||
});
|
||||
|
||||
const unlinkHandler = (err) => {
|
||||
if (err) {
|
||||
log(err);
|
||||
}
|
||||
};
|
||||
|
||||
// Watch for filesystem changes.
|
||||
watcher
|
||||
.on('add', changeOrAdded)
|
||||
.on('change', changeOrAdded)
|
||||
.on('unlink', (filePath) => {
|
||||
const fileName = filePath.slice(0, -9);
|
||||
fs.stat(`${fileName}.css`, () => {
|
||||
fs.unlink(`${fileName}.css`, unlinkHandler);
|
||||
});
|
||||
})
|
||||
.on('ready', () => log(`Watching '${fileMatch}' for changes.`));
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* A command line application to import a database generation script.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Command\DbToolsApplication;
|
||||
use Drupal\Core\DrupalKernel;
|
||||
use Drupal\Core\Site\Settings;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Bootstrap.
|
||||
$autoloader = require __DIR__ . '/../../autoload.php';
|
||||
$request = Request::createFromGlobals();
|
||||
Settings::initialize(dirname(__DIR__, 2), DrupalKernel::findSitePath($request), $autoloader);
|
||||
DrupalKernel::createFromRequest($request, $autoloader, 'prod')->boot();
|
||||
|
||||
// Run the database dump command.
|
||||
$application = new DbToolsApplication();
|
||||
$application->run();
|
||||
@@ -0,0 +1,522 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# This script performs code quality checks.
|
||||
#
|
||||
# @internal
|
||||
# This script is not covered by Drupal core's backwards compatibility promise.
|
||||
# It exists only for core development purposes.
|
||||
#
|
||||
# The script makes the following checks:
|
||||
# - Spell checking.
|
||||
# - File modes.
|
||||
# - No changes to core/node_modules directory.
|
||||
# - PHPCS checks PHP and YAML files.
|
||||
# - ESLint checks JavaScript and YAML files.
|
||||
# - Checks .es6.js and .js files are equivalent.
|
||||
# - Stylelint checks CSS files.
|
||||
# - Checks .pcss.css and .css files are equivalent.
|
||||
|
||||
# cSpell:disable
|
||||
|
||||
# Searches an array.
|
||||
contains_element() {
|
||||
local e
|
||||
for e in ${@:2}; do [[ "$e" == "$1" ]] && return 0; done
|
||||
return 1
|
||||
}
|
||||
|
||||
CACHED=0
|
||||
DRUPALCI=0
|
||||
BRANCH=""
|
||||
while test $# -gt 0; do
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
echo "Drupal code quality checks"
|
||||
echo " "
|
||||
echo "options:"
|
||||
echo "-h, --help show brief help"
|
||||
echo "--branch BRANCH creates list of files to check by comparing against a branch"
|
||||
echo "--cached checks staged files"
|
||||
echo "--drupalci a special mode for DrupalCI"
|
||||
echo " "
|
||||
echo "Example usage: sh ./core/scripts/dev/commit-code-check.sh --branch 9.2.x"
|
||||
exit 0
|
||||
;;
|
||||
--branch)
|
||||
BRANCH="$2"
|
||||
if [[ "$BRANCH" == "" ]]; then
|
||||
printf "The --branch option requires a value. For example: --branch 9.2.x\n"
|
||||
exit;
|
||||
fi
|
||||
shift 2
|
||||
;;
|
||||
--cached)
|
||||
CACHED=1
|
||||
shift
|
||||
;;
|
||||
--drupalci)
|
||||
DRUPALCI=1
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Set up variables to make colored output simple. Color output is disabled on
|
||||
# DrupalCI because it is breaks reporting.
|
||||
# @todo https://www.drupal.org/project/drupalci_testbot/issues/3181869
|
||||
if [[ "$DRUPALCI" == "1" ]]; then
|
||||
red=""
|
||||
green=""
|
||||
reset=""
|
||||
DRUPAL_VERSION=$(php -r "include 'vendor/autoload.php'; print preg_replace('#\.[0-9]+-dev#', '.x', \Drupal::VERSION);")
|
||||
GIT="sudo -u www-data git"
|
||||
else
|
||||
red=$(tput setaf 1 && tput bold)
|
||||
green=$(tput setaf 2)
|
||||
reset=$(tput sgr0)
|
||||
GIT="git"
|
||||
fi
|
||||
|
||||
# Gets list of files to check.
|
||||
if [[ "$BRANCH" != "" ]]; then
|
||||
FILES=$($GIT diff --name-only $BRANCH HEAD);
|
||||
elif [[ "$CACHED" == "0" ]]; then
|
||||
# For DrupalCI patch testing or when running without --cached or --branch,
|
||||
# list of all changes in the working directory.
|
||||
FILES=$($GIT ls-files --other --modified --exclude-standard --exclude=vendor)
|
||||
else
|
||||
# Check staged files only.
|
||||
if $GIT rev-parse --verify HEAD >/dev/null 2>&1
|
||||
then
|
||||
AGAINST=HEAD
|
||||
else
|
||||
# Initial commit: diff against an empty tree object
|
||||
AGAINST=4b825dc642cb6eb9a060e54bf8d69288fbee4904
|
||||
fi
|
||||
FILES=$($GIT diff --cached --name-only $AGAINST);
|
||||
fi
|
||||
|
||||
if [[ "$FILES" == "" ]] && [[ "$DRUPALCI" == "1" ]]; then
|
||||
# If the FILES is empty we might be testing a merge request on DrupalCI. We
|
||||
# need to diff against the Drupal branch or tag related to the Drupal version.
|
||||
printf "Creating list of files to check by comparing branch to %s\n" "$DRUPAL_VERSION"
|
||||
# On DrupalCI there's a merge commit so we can compare to HEAD~1.
|
||||
FILES=$($GIT diff --name-only HEAD~1 HEAD);
|
||||
fi
|
||||
|
||||
TOP_LEVEL=$($GIT rev-parse --show-toplevel)
|
||||
|
||||
# This variable will be set to one when the file core/phpcs.xml.dist is changed.
|
||||
PHPCS_XML_DIST_FILE_CHANGED=0
|
||||
|
||||
# This variable will be set to one when one of the eslint config file is
|
||||
# changed:
|
||||
# - core/.eslintrc.passing.json
|
||||
# - core/.eslintrc.json
|
||||
# - core/.eslintrc.jquery.json
|
||||
ESLINT_CONFIG_PASSING_FILE_CHANGED=0
|
||||
|
||||
# This variable will be set to one when the stylelint config file is changed.
|
||||
# changed:
|
||||
# - core/.stylelintignore
|
||||
# - core/.stylelintrc.json
|
||||
STYLELINT_CONFIG_FILE_CHANGED=0
|
||||
|
||||
# This variable will be set to one when JavaScript packages files are changed.
|
||||
# changed:
|
||||
# - core/package.json
|
||||
# - core/yarn.lock
|
||||
JAVASCRIPT_PACKAGES_CHANGED=0
|
||||
|
||||
# This variable will be set when a Drupal-specific CKEditor 5 plugin has changed
|
||||
# it is used to make sure the compiled JS is valid.
|
||||
CKEDITOR5_PLUGINS_CHANGED=0
|
||||
|
||||
# Build up a list of absolute file names.
|
||||
ABS_FILES=
|
||||
for FILE in $FILES; do
|
||||
ABS_FILES="$ABS_FILES $TOP_LEVEL/$FILE"
|
||||
|
||||
if [[ $FILE == "core/phpcs.xml.dist" ]]; then
|
||||
PHPCS_XML_DIST_FILE_CHANGED=1;
|
||||
fi;
|
||||
|
||||
if [[ $FILE == "core/.eslintrc.json" || $FILE == "core/.eslintrc.passing.json" || $FILE == "core/.eslintrc.jquery.json" ]]; then
|
||||
ESLINT_CONFIG_PASSING_FILE_CHANGED=1;
|
||||
fi;
|
||||
|
||||
if [[ $FILE == "core/.stylelintignore" || $FILE == "core/.stylelintrc.json" ]]; then
|
||||
STYLELINT_CONFIG_FILE_CHANGED=1;
|
||||
fi;
|
||||
|
||||
# If JavaScript packages change, then rerun all JavaScript style checks.
|
||||
if [[ $FILE == "core/package.json" || $FILE == "core/yarn.lock" ]]; then
|
||||
ESLINT_CONFIG_PASSING_FILE_CHANGED=1;
|
||||
STYLELINT_CONFIG_FILE_CHANGED=1;
|
||||
JAVASCRIPT_PACKAGES_CHANGED=1;
|
||||
fi;
|
||||
|
||||
if [[ -f "$TOP_LEVEL/$FILE" ]] && [[ $FILE =~ \.js$ ]] && [[ $FILE =~ ^core/modules/ckeditor5/js/build || $FILE =~ ^core/modules/ckeditor5/js/ckeditor5_plugins ]]; then
|
||||
CKEDITOR5_PLUGINS_CHANGED=1;
|
||||
fi;
|
||||
done
|
||||
|
||||
# Exit early if there are no files.
|
||||
if [[ "$ABS_FILES" == "" ]]; then
|
||||
printf "There are no files to check. If you have staged a commit use the --cached option.\n"
|
||||
exit;
|
||||
fi;
|
||||
|
||||
# This script assumes that composer install and yarn install have already been
|
||||
# run and all dependencies are updated.
|
||||
FINAL_STATUS=0
|
||||
|
||||
DEPENDENCIES_NEED_INSTALLING=0
|
||||
# Ensure PHP development dependencies are installed.
|
||||
# @todo https://github.com/composer/composer/issues/4497 Improve this to
|
||||
# determine if dependencies in the lock file match the installed versions.
|
||||
# Using composer install --dry-run is not valid because it would depend on
|
||||
# user-facing strings in Composer.
|
||||
if ! [[ -f 'vendor/bin/phpcs' ]]; then
|
||||
printf "Drupal's PHP development dependencies are not installed. Run 'composer install' from the root directory.\n"
|
||||
DEPENDENCIES_NEED_INSTALLING=1;
|
||||
fi
|
||||
|
||||
cd "$TOP_LEVEL/core"
|
||||
|
||||
# Ensure JavaScript development dependencies are installed.
|
||||
yarn check -s 2>/dev/null
|
||||
if [ "$?" -ne "0" ]; then
|
||||
printf "Drupal's JavaScript development dependencies are not installed or cannot be resolved. Run 'yarn install' inside the core directory, or 'yarn check -s' to list other errors.\n"
|
||||
DEPENDENCIES_NEED_INSTALLING=1;
|
||||
fi
|
||||
|
||||
if [ $DEPENDENCIES_NEED_INSTALLING -ne 0 ]; then
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# Check all files for spelling in one go for better performance.
|
||||
yarn run -s spellcheck --no-must-find-files -c $TOP_LEVEL/core/.cspell.json $ABS_FILES
|
||||
if [ "$?" -ne "0" ]; then
|
||||
# If there are failures set the status to a number other than 0.
|
||||
FINAL_STATUS=1
|
||||
printf "\nCSpell: ${red}failed${reset}\n"
|
||||
else
|
||||
printf "\nCSpell: ${green}passed${reset}\n"
|
||||
fi
|
||||
cd "$TOP_LEVEL"
|
||||
|
||||
# Add a separator line to make the output easier to read.
|
||||
printf "\n"
|
||||
printf -- '-%.0s' {1..100}
|
||||
printf "\n"
|
||||
|
||||
# Run PHPCS on all files on DrupalCI or when phpcs files are changed.
|
||||
if [[ $PHPCS_XML_DIST_FILE_CHANGED == "1" ]] || [[ "$DRUPALCI" == "1" ]]; then
|
||||
# Test all files with phpcs rules.
|
||||
vendor/bin/phpcs -ps --parallel=$(nproc) --standard="$TOP_LEVEL/core/phpcs.xml.dist"
|
||||
PHPCS=$?
|
||||
if [ "$PHPCS" -ne "0" ]; then
|
||||
# If there are failures set the status to a number other than 0.
|
||||
FINAL_STATUS=1
|
||||
printf "\nPHPCS: ${red}failed${reset}\n"
|
||||
else
|
||||
printf "\nPHPCS: ${green}passed${reset}\n"
|
||||
fi
|
||||
# Add a separator line to make the output easier to read.
|
||||
printf "\n"
|
||||
printf -- '-%.0s' {1..100}
|
||||
printf "\n"
|
||||
fi
|
||||
|
||||
# When the eslint config has been changed, then eslint must check all files.
|
||||
if [[ $ESLINT_CONFIG_PASSING_FILE_CHANGED == "1" ]]; then
|
||||
cd "$TOP_LEVEL/core"
|
||||
yarn run -s lint:core-js-passing "$TOP_LEVEL/core"
|
||||
CORRECTJS=$?
|
||||
if [ "$CORRECTJS" -ne "0" ]; then
|
||||
# If there are failures set the status to a number other than 0.
|
||||
FINAL_STATUS=1
|
||||
printf "\neslint: ${red}failed${reset}\n"
|
||||
else
|
||||
printf "\neslint: ${green}passed${reset}\n"
|
||||
fi
|
||||
cd $TOP_LEVEL
|
||||
# Add a separator line to make the output easier to read.
|
||||
printf "\n"
|
||||
printf -- '-%.0s' {1..100}
|
||||
printf "\n"
|
||||
fi
|
||||
|
||||
# When the stylelint config has been changed, then stylelint must check all files.
|
||||
if [[ $STYLELINT_CONFIG_FILE_CHANGED == "1" ]]; then
|
||||
cd "$TOP_LEVEL/core"
|
||||
yarn run -s lint:css
|
||||
if [ "$?" -ne "0" ]; then
|
||||
# If there are failures set the status to a number other than 0.
|
||||
FINAL_STATUS=1
|
||||
printf "\nstylelint: ${red}failed${reset}\n"
|
||||
else
|
||||
printf "\nstylelint: ${green}passed${reset}\n"
|
||||
fi
|
||||
cd $TOP_LEVEL
|
||||
# Add a separator line to make the output easier to read.
|
||||
printf "\n"
|
||||
printf -- '-%.0s' {1..100}
|
||||
printf "\n"
|
||||
fi
|
||||
|
||||
# When a Drupal-specific CKEditor 5 plugin changed ensure that it is compiled
|
||||
# properly. Only check on DrupalCI, since we're concerned about the build being
|
||||
# run with the expected package versions and making sure the result of the build
|
||||
# is in sync and conform to expectations.
|
||||
if [[ "$DRUPALCI" == "1" ]] && [[ $CKEDITOR5_PLUGINS_CHANGED == "1" ]]; then
|
||||
cd "$TOP_LEVEL/core"
|
||||
yarn run -s check:ckeditor5
|
||||
if [ "$?" -ne "0" ]; then
|
||||
# If there are failures set the status to a number other than 0.
|
||||
FINAL_STATUS=1
|
||||
printf "\nDrupal-specific CKEditor 5 plugins: ${red}failed${reset}\n"
|
||||
else
|
||||
printf "\nDrupal-specific CKEditor 5 plugins: ${green}passed${reset}\n"
|
||||
fi
|
||||
cd $TOP_LEVEL
|
||||
# Add a separator line to make the output easier to read.
|
||||
printf "\n"
|
||||
printf -- '-%.0s' {1..100}
|
||||
printf "\n"
|
||||
fi
|
||||
|
||||
# When JavaScript packages change, then rerun all JavaScript style checks.
|
||||
if [[ "$JAVASCRIPT_PACKAGES_CHANGED" == "1" ]]; then
|
||||
cd "$TOP_LEVEL/core"
|
||||
yarn run build:css --check
|
||||
CORRECTCSS=$?
|
||||
if [ "$CORRECTCSS" -ne "0" ]; then
|
||||
FINAL_STATUS=1
|
||||
printf "\n${red}ERROR: The compiled CSS from the PCSS files"
|
||||
printf "\n does not match the current CSS files. Some added"
|
||||
printf "\n or updated JavaScript package made changes."
|
||||
printf "\n Recompile the CSS with: yarn run build:css${reset}\n\n"
|
||||
fi
|
||||
cd $TOP_LEVEL
|
||||
# Add a separator line to make the output easier to read.
|
||||
printf "\n"
|
||||
printf -- '-%.0s' {1..100}
|
||||
printf "\n"
|
||||
fi
|
||||
|
||||
for FILE in $FILES; do
|
||||
STATUS=0;
|
||||
# Print a line to separate spellcheck output from per file output.
|
||||
printf "Checking %s\n" "$FILE"
|
||||
printf "\n"
|
||||
|
||||
# Ensure the file still exists (i.e. is not being deleted).
|
||||
if [ -a $FILE ]; then
|
||||
if [ ${FILE: -3} != ".sh" ]; then
|
||||
# Ensure the file has the correct mode.
|
||||
STAT="$(stat -f "%A" $FILE 2>/dev/null)"
|
||||
if [ $? -ne 0 ]; then
|
||||
STAT="$(stat -c "%a" $FILE 2>/dev/null)"
|
||||
fi
|
||||
if [ "$STAT" -ne "644" ]; then
|
||||
printf "${red}check failed:${reset} file $FILE should be 644 not $STAT\n"
|
||||
STATUS=1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Don't commit changes to vendor.
|
||||
if [[ "$FILE" =~ ^vendor/ ]]; then
|
||||
printf "${red}check failed:${reset} file in vendor directory being committed ($FILE)\n"
|
||||
STATUS=1
|
||||
fi
|
||||
|
||||
# Don't commit changes to core/node_modules.
|
||||
if [[ "$FILE" =~ ^core/node_modules/ ]]; then
|
||||
printf "${red}check failed:${reset} file in core/node_modules directory being committed ($FILE)\n"
|
||||
STATUS=1
|
||||
fi
|
||||
|
||||
############################################################################
|
||||
### PHP AND YAML FILES
|
||||
############################################################################
|
||||
if [[ -f "$TOP_LEVEL/$FILE" ]] && [[ $FILE =~ \.(inc|install|module|php|profile|test|theme|yml)$ ]] && [[ $PHPCS_XML_DIST_FILE_CHANGED == "0" ]] && [[ "$DRUPALCI" == "0" ]]; then
|
||||
# Test files with phpcs rules.
|
||||
vendor/bin/phpcs "$TOP_LEVEL/$FILE" --standard="$TOP_LEVEL/core/phpcs.xml.dist"
|
||||
PHPCS=$?
|
||||
if [ "$PHPCS" -ne "0" ]; then
|
||||
# If there are failures set the status to a number other than 0.
|
||||
STATUS=1
|
||||
else
|
||||
printf "PHPCS: $FILE ${green}passed${reset}\n"
|
||||
fi
|
||||
fi
|
||||
|
||||
############################################################################
|
||||
### YAML FILES
|
||||
############################################################################
|
||||
if [[ -f "$TOP_LEVEL/$FILE" ]] && [[ $FILE =~ \.yml$ ]]; then
|
||||
# Test files with ESLint.
|
||||
cd "$TOP_LEVEL/core"
|
||||
node ./node_modules/eslint/bin/eslint.js --quiet --resolve-plugins-relative-to . "$TOP_LEVEL/$FILE"
|
||||
YAMLLINT=$?
|
||||
if [ "$YAMLLINT" -ne "0" ]; then
|
||||
# If there are failures set the status to a number other than 0.
|
||||
STATUS=1
|
||||
else
|
||||
printf "ESLint: $FILE ${green}passed${reset}\n"
|
||||
fi
|
||||
cd $TOP_LEVEL
|
||||
fi
|
||||
|
||||
############################################################################
|
||||
### JAVASCRIPT FILES
|
||||
############################################################################
|
||||
if [[ -f "$TOP_LEVEL/$FILE" ]] && [[ $FILE =~ \.js$ ]] && [[ ! $FILE =~ ^core/tests/Drupal/Nightwatch ]] && [[ ! $FILE =~ /tests/src/Nightwatch/ ]] && [[ ! $FILE =~ ^core/modules/ckeditor5/js/ckeditor5_plugins ]]; then
|
||||
# Work out the root name of the JavaScript so we can ensure that the ES6
|
||||
# version has been compiled correctly.
|
||||
if [[ $FILE =~ \.es6\.js$ ]]; then
|
||||
BASENAME=${FILE%.es6.js}
|
||||
COMPILE_CHECK=1
|
||||
else
|
||||
BASENAME=${FILE%.js}
|
||||
# We only need to compile check if the .es6.js file is not also
|
||||
# changing. This is because the compile check will occur for the
|
||||
# .es6.js file. This might occur if the compile scripts have changed.
|
||||
contains_element "$BASENAME.es6.js" "${FILES[@]}"
|
||||
HASES6=$?
|
||||
if [ "$HASES6" -ne "0" ]; then
|
||||
COMPILE_CHECK=1
|
||||
else
|
||||
COMPILE_CHECK=0
|
||||
fi
|
||||
fi
|
||||
if [[ "$COMPILE_CHECK" == "1" ]] && [[ -f "$TOP_LEVEL/$BASENAME.es6.js" ]]; then
|
||||
cd "$TOP_LEVEL/core"
|
||||
yarn run build:js --check --file "$TOP_LEVEL/$BASENAME.es6.js"
|
||||
CORRECTJS=$?
|
||||
if [ "$CORRECTJS" -ne "0" ]; then
|
||||
# No need to write any output the yarn run command will do this for
|
||||
# us.
|
||||
STATUS=1
|
||||
fi
|
||||
# Check the coding standards.
|
||||
if [[ -f ".eslintrc.passing.json" ]]; then
|
||||
node ./node_modules/eslint/bin/eslint.js --quiet --config=.eslintrc.passing.json "$TOP_LEVEL/$BASENAME.es6.js"
|
||||
CORRECTJS=$?
|
||||
if [ "$CORRECTJS" -ne "0" ]; then
|
||||
# No need to write any output the node command will do this for us.
|
||||
STATUS=1
|
||||
fi
|
||||
fi
|
||||
cd $TOP_LEVEL
|
||||
else
|
||||
# If there is no .es6.js file then there should be unless the .js is
|
||||
# not really Drupal's.
|
||||
if ! [[ "$FILE" =~ ^core/assets/vendor ]] && ! [[ "$FILE" =~ ^core/modules/ckeditor5/js/build ]] && ! [[ "$FILE" =~ ^core/scripts/js ]] && ! [[ "$FILE" =~ ^core/scripts/css ]] && ! [[ "$FILE" =~ webpack.config.js$ ]] && ! [[ -f "$TOP_LEVEL/$BASENAME.es6.js" ]] && ! [[ "$FILE" =~ core/modules/ckeditor5/tests/modules/ckeditor5_test/js/build/layercake.js ]]; then
|
||||
printf "${red}FAILURE${reset} $FILE does not have a corresponding $BASENAME.es6.js\n"
|
||||
STATUS=1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# Check coding standards of Nightwatch files.
|
||||
if [[ -f "$TOP_LEVEL/$FILE" ]] && [[ $FILE =~ \.js$ ]]; then
|
||||
cd "$TOP_LEVEL/core"
|
||||
# Check the coding standards.
|
||||
if [[ -f ".eslintrc.passing.json" ]]; then
|
||||
node ./node_modules/eslint/bin/eslint.js --quiet --config=.eslintrc.passing.json "$TOP_LEVEL/$FILE"
|
||||
CORRECTJS=$?
|
||||
if [ "$CORRECTJS" -ne "0" ]; then
|
||||
# No need to write any output the node command will do this for us.
|
||||
STATUS=1
|
||||
fi
|
||||
fi
|
||||
cd $TOP_LEVEL
|
||||
fi
|
||||
fi
|
||||
|
||||
############################################################################
|
||||
### CSS FILES
|
||||
############################################################################
|
||||
if [[ -f "$TOP_LEVEL/$FILE" ]] && [[ $FILE =~ \.css$ ]]; then
|
||||
# Work out the root name of the CSS so we can ensure that the PostCSS
|
||||
# version has been compiled correctly.
|
||||
if [[ $FILE =~ \.pcss\.css$ ]]; then
|
||||
BASENAME=${FILE%.pcss.css}
|
||||
COMPILE_CHECK=1
|
||||
else
|
||||
BASENAME=${FILE%.css}
|
||||
# We only need to compile check if the .pcss.css file is not also
|
||||
# changing. This is because the compile check will occur for the
|
||||
# .pcss.css file. This might occur if the compiled stylesheets have
|
||||
# changed.
|
||||
contains_element "$BASENAME.pcss.css" "${FILES[@]}"
|
||||
HASPOSTCSS=$?
|
||||
if [ "$HASPOSTCSS" -ne "0" ]; then
|
||||
COMPILE_CHECK=1
|
||||
else
|
||||
COMPILE_CHECK=0
|
||||
fi
|
||||
fi
|
||||
# PostCSS
|
||||
if [[ "$COMPILE_CHECK" == "1" ]] && [[ -f "$TOP_LEVEL/$BASENAME.pcss.css" ]]; then
|
||||
cd "$TOP_LEVEL/core"
|
||||
yarn run build:css --check --file "$TOP_LEVEL/$BASENAME.pcss.css"
|
||||
CORRECTCSS=$?
|
||||
if [ "$CORRECTCSS" -ne "0" ]; then
|
||||
# If the CSS does not match the PCSS, set the status to a number other
|
||||
# than 0.
|
||||
STATUS=1
|
||||
printf "\n${red}ERROR: The compiled CSS from"
|
||||
printf "\n ${BASENAME}.pcss.css"
|
||||
printf "\n does not match its CSS file. Recompile the CSS with:"
|
||||
printf "\n yarn run build:css${reset}\n\n"
|
||||
fi
|
||||
cd $TOP_LEVEL
|
||||
fi
|
||||
fi
|
||||
if [[ -f "$TOP_LEVEL/$FILE" ]] && [[ $FILE =~ \.css$ ]] && [[ -f "core/node_modules/.bin/stylelint" ]]; then
|
||||
BASENAME=${FILE%.css}
|
||||
# We only need to use stylelint on the .pcss.css file. So if this CSS file
|
||||
# has a corresponding .pcss don't do stylelint.
|
||||
if [[ $FILE =~ \.pcss\.css$ ]] || [[ ! -f "$TOP_LEVEL/$BASENAME.pcss.css" ]]; then
|
||||
cd "$TOP_LEVEL/core"
|
||||
node_modules/.bin/stylelint --allow-empty-input "$TOP_LEVEL/$FILE"
|
||||
if [ "$?" -ne "0" ]; then
|
||||
STATUS=1
|
||||
else
|
||||
printf "STYLELINT: $FILE ${green}passed${reset}\n"
|
||||
fi
|
||||
cd $TOP_LEVEL
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$STATUS" == "1" ]]; then
|
||||
FINAL_STATUS=1
|
||||
# There is no need to print a failure message. The fail will be described
|
||||
# already.
|
||||
else
|
||||
printf "%s ${green}passed${reset}\n" "$FILE"
|
||||
fi
|
||||
|
||||
# Print a line to separate each file's checks.
|
||||
printf "\n"
|
||||
printf -- '-%.0s' {1..100}
|
||||
printf "\n"
|
||||
done
|
||||
|
||||
if [[ "$FINAL_STATUS" == "1" ]] && [[ "$DRUPALCI" == "1" ]]; then
|
||||
printf "${red}Drupal code quality checks failed.${reset}\n"
|
||||
printf "To reproduce this output locally:\n"
|
||||
printf "* Apply the change as a patch\n"
|
||||
printf "* Run this command locally: sh ./core/scripts/dev/commit-code-check.sh\n"
|
||||
printf "OR:\n"
|
||||
printf "* From the merge request branch\n"
|
||||
printf "* Run this command locally: sh ./core/scripts/dev/commit-code-check.sh --branch %s\n" "$DRUPAL_VERSION"
|
||||
fi
|
||||
exit $FINAL_STATUS
|
||||
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides CLI commands for Drupal.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Command\GenerateTheme;
|
||||
use Drupal\Core\Command\QuickStartCommand;
|
||||
use Drupal\Core\Command\InstallCommand;
|
||||
use Drupal\Core\Command\ServerCommand;
|
||||
use Symfony\Component\Console\Application;
|
||||
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
return;
|
||||
}
|
||||
|
||||
$classloader = require_once __DIR__ . '/../../autoload.php';
|
||||
|
||||
$application = new Application('drupal', \Drupal::VERSION);
|
||||
|
||||
$application->add(new QuickStartCommand());
|
||||
$application->add(new InstallCommand($classloader));
|
||||
$application->add(new ServerCommand($classloader));
|
||||
$application->add(new GenerateTheme());
|
||||
|
||||
$application->run();
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Drupal shell execution script
|
||||
*
|
||||
* Check for your PHP interpreter - on Windows you'll probably have to
|
||||
* replace line 1 with
|
||||
* #!c:/program files/php/php.exe
|
||||
*
|
||||
* @param path Drupal's absolute root directory in local file system (optional).
|
||||
* @param URI A URI to execute, including HTTP protocol prefix.
|
||||
*/
|
||||
|
||||
$script = basename(array_shift($_SERVER['argv']));
|
||||
|
||||
if (in_array('--help', $_SERVER['argv']) || empty($_SERVER['argv'])) {
|
||||
echo <<<EOF
|
||||
|
||||
Execute a Drupal page from the shell.
|
||||
|
||||
Usage: {$script} [OPTIONS] "<URI>"
|
||||
Example: {$script} "http://mysite.org/node"
|
||||
|
||||
All arguments are long options.
|
||||
|
||||
--help This page.
|
||||
|
||||
--root Set the working directory for the script to the specified path.
|
||||
To execute Drupal this has to be the root directory of your
|
||||
Drupal installation, f.e. /home/www/foo/drupal (assuming Drupal
|
||||
running on Unix). Current directory is not required.
|
||||
Use surrounding quotation marks on Windows.
|
||||
|
||||
--verbose This option displays the options as they are set, but will
|
||||
produce errors from setting the session.
|
||||
|
||||
URI The URI to execute, i.e. http://default/foo/bar for executing
|
||||
the path '/foo/bar' in your site 'default'. URI has to be
|
||||
enclosed by quotation marks if there are ampersands in it
|
||||
(f.e. index.php?q=node&foo=bar). Prefix 'http://' is required,
|
||||
and the domain must exist in Drupal's sites-directory.
|
||||
|
||||
If the given path and file exists it will be executed directly,
|
||||
i.e. if URI is set to http://default/bar/foo.php
|
||||
and bar/foo.php exists, this script will be executed without
|
||||
bootstrapping Drupal. To execute Drupal's update.php, specify
|
||||
http://default/update.php as the URI.
|
||||
|
||||
|
||||
To run this script without --root argument invoke it from the root directory
|
||||
of your Drupal installation with
|
||||
|
||||
./scripts/{$script}
|
||||
\n
|
||||
EOF;
|
||||
exit;
|
||||
}
|
||||
|
||||
$cmd = 'index.php';
|
||||
// define default settings
|
||||
$_SERVER['HTTP_HOST'] = 'default';
|
||||
$_SERVER['PHP_SELF'] = '/index.php';
|
||||
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
||||
$_SERVER['SERVER_SOFTWARE'] = NULL;
|
||||
$_SERVER['REQUEST_METHOD'] = 'GET';
|
||||
$_SERVER['QUERY_STRING'] = '';
|
||||
$_SERVER['PHP_SELF'] = $_SERVER['REQUEST_URI'] = '/';
|
||||
$_SERVER['HTTP_USER_AGENT'] = 'console';
|
||||
|
||||
// toggle verbose mode
|
||||
if (in_array('--verbose', $_SERVER['argv'])) {
|
||||
$_verbose_mode = TRUE;
|
||||
}
|
||||
else {
|
||||
$_verbose_mode = FALSE;
|
||||
}
|
||||
|
||||
// parse invocation arguments
|
||||
while ($param = array_shift($_SERVER['argv'])) {
|
||||
switch ($param) {
|
||||
case '--root':
|
||||
// change working directory
|
||||
$path = array_shift($_SERVER['argv']);
|
||||
if (is_dir($path)) {
|
||||
chdir($path);
|
||||
if ($_verbose_mode) {
|
||||
echo "cwd changed to: {$path}\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
echo "\nERROR: {$path} not found.\n\n";
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (substr($param, 0, 2) == '--') {
|
||||
// ignore unknown options
|
||||
break;
|
||||
}
|
||||
else {
|
||||
// parse the URI
|
||||
$path = parse_url($param);
|
||||
|
||||
// set site name
|
||||
if (isset($path['host'])) {
|
||||
$_SERVER['HTTP_HOST'] = $path['host'];
|
||||
}
|
||||
|
||||
// set query string
|
||||
if (isset($path['query'])) {
|
||||
$_SERVER['QUERY_STRING'] = $path['query'];
|
||||
parse_str($path['query'], $_GET);
|
||||
$_REQUEST = $_GET;
|
||||
}
|
||||
|
||||
// set file to execute or Drupal path (clean URLs enabled)
|
||||
if (isset($path['path']) && file_exists(substr($path['path'], 1))) {
|
||||
$_SERVER['PHP_SELF'] = $_SERVER['REQUEST_URI'] = $path['path'];
|
||||
$cmd = substr($path['path'], 1);
|
||||
}
|
||||
elseif (isset($path['path'])) {
|
||||
$_SERVER['SCRIPT_NAME'] = '/' . $cmd;
|
||||
$_SERVER['REQUEST_URI'] = $path['path'];
|
||||
}
|
||||
|
||||
// display setup in verbose mode
|
||||
if ($_verbose_mode) {
|
||||
echo "Hostname set to: {$_SERVER['HTTP_HOST']}\n";
|
||||
echo "Script name set to: {$cmd}\n";
|
||||
echo "Path set to: {$path['path']}\n";
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (file_exists($cmd)) {
|
||||
include $cmd;
|
||||
}
|
||||
else {
|
||||
echo "\nERROR: {$cmd} not found.\n\n";
|
||||
}
|
||||
exit();
|
||||
@@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Dump a Drupal 6 database into a Drupal 7 PHP script to test the upgrade
|
||||
* process.
|
||||
*
|
||||
* Run this script at the root of an existing Drupal 6 installation.
|
||||
*
|
||||
* The output of this script is a PHP script that can be ran inside Drupal 7
|
||||
* and recreates the Drupal 6 database as dumped. Transient data from cache
|
||||
* session and watchdog tables are not recorded.
|
||||
*/
|
||||
|
||||
// Define default settings.
|
||||
$cmd = 'index.php';
|
||||
$_SERVER['HTTP_HOST'] = 'default';
|
||||
$_SERVER['PHP_SELF'] = '/index.php';
|
||||
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
||||
$_SERVER['SERVER_SOFTWARE'] = NULL;
|
||||
$_SERVER['REQUEST_METHOD'] = 'GET';
|
||||
$_SERVER['QUERY_STRING'] = '';
|
||||
$_SERVER['PHP_SELF'] = $_SERVER['REQUEST_URI'] = '/';
|
||||
$_SERVER['HTTP_USER_AGENT'] = 'console';
|
||||
|
||||
// Bootstrap Drupal.
|
||||
include_once './includes/bootstrap.inc';
|
||||
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
|
||||
|
||||
// Include the utility drupal_var_export() function.
|
||||
include_once __DIR__ . '/../includes/utility.inc';
|
||||
|
||||
// Output the PHP header.
|
||||
$output = <<<ENDOFHEADER
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Filled installation of Drupal 6.17, for test purposes.
|
||||
*
|
||||
* This file was generated by the dump-database-d6.sh tool, from an
|
||||
* installation of Drupal 6, filled with data using the generate-d6-content.sh
|
||||
* tool. It has the following modules installed:
|
||||
|
||||
ENDOFHEADER;
|
||||
|
||||
foreach (\Drupal::moduleHandler()->getModuleList() as $module => $filename) {
|
||||
$output .= " * - $module\n";
|
||||
}
|
||||
$output .= " */\n\n";
|
||||
|
||||
// Get the current schema, order it by table name.
|
||||
$schema = drupal_get_schema();
|
||||
ksort($schema);
|
||||
|
||||
// Override the field type of the filename primary key to bypass the
|
||||
// InnoDB 191 character limitation.
|
||||
if (isset($schema['system']['primary key']) && $schema['system']['primary key'] == 'filename' && isset($schema['system']['fields']['filename']['type']) && $schema['system']['fields']['filename']['type'] == 'varchar') {
|
||||
$schema['system']['fields']['filename']['type'] = 'varchar_ascii';
|
||||
}
|
||||
// Export all the tables in the schema.
|
||||
foreach ($schema as $table => $data) {
|
||||
// Remove descriptions to save time and code.
|
||||
unset($data['description']);
|
||||
foreach ($data['fields'] as &$field) {
|
||||
unset($field['description']);
|
||||
}
|
||||
|
||||
// Dump the table structure.
|
||||
$output .= "db_create_table('" . $table . "', " . drupal_var_export($data) . ");\n";
|
||||
|
||||
// Don't output values for those tables.
|
||||
if (substr($table, 0, 5) == 'cache' || $table == 'sessions' || $table == 'watchdog') {
|
||||
$output .= "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Prepare the export of values.
|
||||
$result = db_query('SELECT * FROM {'. $table .'}');
|
||||
$insert = '';
|
||||
while ($record = db_fetch_array($result)) {
|
||||
// users.uid is a serial and inserting 0 into a serial can break MySQL.
|
||||
// So record uid + 1 instead of uid for every uid and once all records
|
||||
// are in place, fix them up.
|
||||
if ($table == 'users') {
|
||||
$record['uid']++;
|
||||
}
|
||||
$insert .= '->values('. drupal_var_export($record) .")\n";
|
||||
}
|
||||
|
||||
// Dump the values if there are some.
|
||||
if ($insert) {
|
||||
$output .= "db_insert('". $table . "')->fields(". drupal_var_export(array_keys($data['fields'])) .")\n";
|
||||
$output .= $insert;
|
||||
$output .= "->execute();\n";
|
||||
}
|
||||
|
||||
// Add the statement fixing the serial in the user table.
|
||||
if ($table == 'users') {
|
||||
$output .= "db_query('UPDATE {users} SET uid = uid - 1');\n";
|
||||
}
|
||||
|
||||
$output .= "\n";
|
||||
}
|
||||
|
||||
print $output;
|
||||
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Dumps a Drupal 7 database into a Drupal 7 PHP script to test the upgrade
|
||||
* process.
|
||||
*
|
||||
* Run this script at the root of an existing Drupal 7 installation.
|
||||
*
|
||||
* The output of this script is a PHP script that can be run inside Drupal 7
|
||||
* and recreates the Drupal 7 database as dumped. Transient data from cache,
|
||||
* session, and watchdog tables are not recorded.
|
||||
*/
|
||||
|
||||
// Define default settings.
|
||||
define('DRUPAL_ROOT', getcwd());
|
||||
$cmd = 'index.php';
|
||||
$_SERVER['HTTP_HOST'] = 'default';
|
||||
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
||||
$_SERVER['SERVER_SOFTWARE'] = NULL;
|
||||
$_SERVER['REQUEST_METHOD'] = 'GET';
|
||||
$_SERVER['QUERY_STRING'] = '';
|
||||
$_SERVER['PHP_SELF'] = $_SERVER['REQUEST_URI'] = '/';
|
||||
$_SERVER['HTTP_USER_AGENT'] = 'console';
|
||||
|
||||
// Bootstrap Drupal.
|
||||
include_once './includes/bootstrap.inc';
|
||||
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
|
||||
|
||||
// Include the utility drupal_var_export() function.
|
||||
include_once dirname(__FILE__) . '/../includes/utility.inc';
|
||||
|
||||
// Output the PHP header.
|
||||
$output = <<<ENDOFHEADER
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Filled installation of Drupal 7.0, for test purposes.
|
||||
*
|
||||
* This file was generated by the dump-database-d7.sh tool, from an
|
||||
* installation of Drupal 7, filled with data using the generate-d7-content.sh
|
||||
* tool. It has the following modules installed:
|
||||
|
||||
ENDOFHEADER;
|
||||
|
||||
foreach (\Drupal::moduleHandler()->getModuleList() as $module => $filename) {
|
||||
$output .= " * - $module\n";
|
||||
}
|
||||
$output .= " */\n\n";
|
||||
|
||||
// Get the current schema, order it by table name.
|
||||
$schema = drupal_get_schema();
|
||||
ksort($schema);
|
||||
|
||||
// Export all the tables in the schema.
|
||||
foreach ($schema as $table => $data) {
|
||||
// Remove descriptions to save time and code.
|
||||
unset($data['description']);
|
||||
foreach ($data['fields'] as &$field) {
|
||||
unset($field['description']);
|
||||
}
|
||||
|
||||
// Dump the table structure.
|
||||
$output .= "db_create_table('" . $table . "', " . drupal_var_export($data) . ");\n";
|
||||
|
||||
// Don't output values for those tables.
|
||||
if (substr($table, 0, 5) == 'cache' || $table == 'sessions' || $table == 'watchdog') {
|
||||
$output .= "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Prepare the export of values.
|
||||
$result = db_query('SELECT * FROM {'. $table .'}', array(), array('fetch' => PDO::FETCH_ASSOC));
|
||||
$insert = '';
|
||||
foreach ($result as $record) {
|
||||
$insert .= '->values('. drupal_var_export($record) .")\n";
|
||||
}
|
||||
|
||||
// Dump the values if there are some.
|
||||
if ($insert) {
|
||||
$output .= "db_insert('". $table . "')->fields(". drupal_var_export(array_keys($data['fields'])) .")\n";
|
||||
$output .= $insert;
|
||||
$output .= "->execute();\n";
|
||||
}
|
||||
|
||||
$output .= "\n";
|
||||
}
|
||||
|
||||
print $output;
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* A command line application to dump a database to a generation script.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Command\DbDumpApplication;
|
||||
use Drupal\Core\DrupalKernel;
|
||||
use Drupal\Core\Site\Settings;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Bootstrap.
|
||||
$autoloader = require __DIR__ . '/../../autoload.php';
|
||||
$request = Request::createFromGlobals();
|
||||
Settings::initialize(dirname(__DIR__, 2), DrupalKernel::findSitePath($request), $autoloader);
|
||||
DrupalKernel::createFromRequest($request, $autoloader, 'prod')->boot();
|
||||
|
||||
// Run the database dump command.
|
||||
$application = new DbDumpApplication();
|
||||
$application->run();
|
||||
@@ -1,278 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* External links js file.
|
||||
*/
|
||||
|
||||
(function ($, Drupal, drupalSettings) {
|
||||
|
||||
'use strict';
|
||||
|
||||
Drupal.extlink = Drupal.extlink || {};
|
||||
|
||||
Drupal.extlink.attach = function (context, drupalSettings) {
|
||||
if (typeof drupalSettings.data === 'undefined' || !drupalSettings.data.hasOwnProperty('extlink')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Define the jQuery method (either 'append' or 'prepend') of placing the
|
||||
// icon, defaults to 'append'.
|
||||
var extIconPlacement = 'append';
|
||||
if (drupalSettings.data.extlink.extIconPlacement && drupalSettings.data.extlink.extIconPlacement != '0') {
|
||||
extIconPlacement = drupalSettings.data.extlink.extIconPlacement;
|
||||
}
|
||||
|
||||
// Strip the host name down, removing ports, subdomains, or www.
|
||||
var pattern = /^(([^\/:]+?\.)*)([^\.:]{1,})((\.[a-z0-9]{1,253})*)(:[0-9]{1,5})?$/;
|
||||
var host = window.location.host.replace(pattern, '$2$3$6');
|
||||
var subdomain = window.location.host.replace(host, '');
|
||||
|
||||
// Determine what subdomains are considered internal.
|
||||
var subdomains;
|
||||
if (drupalSettings.data.extlink.extSubdomains) {
|
||||
subdomains = '([^/]*\\.)?';
|
||||
}
|
||||
else if (subdomain === 'www.' || subdomain === '') {
|
||||
subdomains = '(www\\.)?';
|
||||
}
|
||||
else {
|
||||
subdomains = subdomain.replace('.', '\\.');
|
||||
}
|
||||
|
||||
// Whitelisted domains.
|
||||
var whitelistedDomains = false;
|
||||
if (drupalSettings.data.extlink.whitelistedDomains) {
|
||||
whitelistedDomains = [];
|
||||
for (var i = 0; i < drupalSettings.data.extlink.whitelistedDomains.length; i++) {
|
||||
whitelistedDomains.push(new RegExp('^https?:\\/\\/' + drupalSettings.data.extlink.whitelistedDomains[i].replace(/(\r\n|\n|\r)/gm,'') + '.*$', 'i'));
|
||||
}
|
||||
}
|
||||
|
||||
// Build regular expressions that define an internal link.
|
||||
var internal_link = new RegExp('^https?://([^@]*@)?' + subdomains + host, 'i');
|
||||
|
||||
// Extra internal link matching.
|
||||
var extInclude = false;
|
||||
if (drupalSettings.data.extlink.extInclude) {
|
||||
extInclude = new RegExp(drupalSettings.data.extlink.extInclude.replace(/\\/, '\\'), 'i');
|
||||
}
|
||||
|
||||
// Extra external link matching.
|
||||
var extExclude = false;
|
||||
if (drupalSettings.data.extlink.extExclude) {
|
||||
extExclude = new RegExp(drupalSettings.data.extlink.extExclude.replace(/\\/, '\\'), 'i');
|
||||
}
|
||||
|
||||
// Extra external link CSS selector exclusion.
|
||||
var extCssExclude = false;
|
||||
if (drupalSettings.data.extlink.extCssExclude) {
|
||||
extCssExclude = drupalSettings.data.extlink.extCssExclude;
|
||||
}
|
||||
|
||||
// Extra external link CSS selector explicit.
|
||||
var extCssExplicit = false;
|
||||
if (drupalSettings.data.extlink.extCssExplicit) {
|
||||
extCssExplicit = drupalSettings.data.extlink.extCssExplicit;
|
||||
}
|
||||
|
||||
// Find all links which are NOT internal and begin with http as opposed
|
||||
// to ftp://, javascript:, etc. other kinds of links.
|
||||
// When operating on the 'this' variable, the host has been appended to
|
||||
// all links by the browser, even local ones.
|
||||
// In jQuery 1.1 and higher, we'd use a filter method here, but it is not
|
||||
// available in jQuery 1.0 (Drupal 5 default).
|
||||
var external_links = [];
|
||||
var mailto_links = [];
|
||||
$('a:not([data-extlink]), area:not([data-extlink])', context).each(function (el) {
|
||||
try {
|
||||
var url = '';
|
||||
if (typeof this.href == 'string') {
|
||||
url = this.href.toLowerCase();
|
||||
}
|
||||
// Handle SVG links (xlink:href).
|
||||
else if (typeof this.href == 'object') {
|
||||
url = this.href.baseVal;
|
||||
}
|
||||
if (url.indexOf('http') === 0
|
||||
&& ((!internal_link.test(url) && !(extExclude && extExclude.test(url))) || (extInclude && extInclude.test(url)))
|
||||
&& !(extCssExclude && $(this).is(extCssExclude))
|
||||
&& !(extCssExclude && $(this).parents(extCssExclude).length > 0)
|
||||
&& !(extCssExplicit && $(this).parents(extCssExplicit).length < 1)) {
|
||||
var match = false;
|
||||
if (whitelistedDomains) {
|
||||
for (var i = 0; i < whitelistedDomains.length; i++) {
|
||||
if (whitelistedDomains[i].test(url)) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!match) {
|
||||
external_links.push(this);
|
||||
}
|
||||
}
|
||||
// Do not include area tags with begin with mailto: (this prohibits
|
||||
// icons from being added to image-maps).
|
||||
else if (this.tagName !== 'AREA'
|
||||
&& url.indexOf('mailto:') === 0
|
||||
&& !(extCssExclude && $(this).parents(extCssExclude).length > 0)
|
||||
&& !(extCssExplicit && $(this).parents(extCssExplicit).length < 1)) {
|
||||
mailto_links.push(this);
|
||||
}
|
||||
}
|
||||
// IE7 throws errors often when dealing with irregular links, such as:
|
||||
// <a href="node/10"></a> Empty tags.
|
||||
// <a href="http://user:pass@example.com">example</a> User:pass syntax.
|
||||
catch (error) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (drupalSettings.data.extlink.extClass !== '0' && drupalSettings.data.extlink.extClass !== '') {
|
||||
Drupal.extlink.applyClassAndSpan(external_links, drupalSettings.data.extlink.extClass, extIconPlacement);
|
||||
}
|
||||
|
||||
if (drupalSettings.data.extlink.mailtoClass !== '0' && drupalSettings.data.extlink.mailtoClass !== '') {
|
||||
Drupal.extlink.applyClassAndSpan(mailto_links, drupalSettings.data.extlink.mailtoClass, extIconPlacement);
|
||||
}
|
||||
|
||||
if (drupalSettings.data.extlink.extTarget) {
|
||||
// Apply the target attribute to all links.
|
||||
$(external_links).filter(function () {
|
||||
// Filter out links with target set if option specified.
|
||||
return !(drupalSettings.data.extlink.extTargetNoOverride && $(this).is('a[target]'));
|
||||
}).attr({target: '_blank'});
|
||||
|
||||
// Add noopener rel attribute to combat phishing.
|
||||
$(external_links).attr('rel', function (i, val) {
|
||||
// If no rel attribute is present, create one with the value noopener.
|
||||
if (val === null || typeof val === 'undefined') {
|
||||
return 'noopener';
|
||||
}
|
||||
// Check to see if rel contains noopener. Add what doesn't exist.
|
||||
if (val.indexOf('noopener') > -1) {
|
||||
if (val.indexOf('noopener') === -1) {
|
||||
return val + ' noopener';
|
||||
}
|
||||
// Noopener exists. Nothing needs to be added.
|
||||
else {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
// Else, append noopener to val.
|
||||
else {
|
||||
return val + ' noopener';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (drupalSettings.data.extlink.extNofollow) {
|
||||
$(external_links).attr('rel', function (i, val) {
|
||||
// When the link does not have a rel attribute set it to 'nofollow'.
|
||||
if (val === null || typeof val === 'undefined') {
|
||||
return 'nofollow';
|
||||
}
|
||||
var target = 'nofollow';
|
||||
// Change the target, if not overriding follow.
|
||||
if (drupalSettings.data.extlink.extFollowNoOverride) {
|
||||
target = 'follow';
|
||||
}
|
||||
if (val.indexOf(target) === -1) {
|
||||
return val + ' nofollow';
|
||||
}
|
||||
return val;
|
||||
});
|
||||
}
|
||||
|
||||
if (drupalSettings.data.extlink.extNoreferrer) {
|
||||
$(external_links).attr('rel', function (i, val) {
|
||||
// When the link does not have a rel attribute set it to 'noreferrer'.
|
||||
if (val === null || typeof val === 'undefined') {
|
||||
return 'noreferrer';
|
||||
}
|
||||
if (val.indexOf('noreferrer') === -1) {
|
||||
return val + ' noreferrer';
|
||||
}
|
||||
return val;
|
||||
});
|
||||
}
|
||||
|
||||
Drupal.extlink = Drupal.extlink || {};
|
||||
|
||||
// Set up default click function for the external links popup. This should be
|
||||
// overridden by modules wanting to alter the popup.
|
||||
Drupal.extlink.popupClickHandler = Drupal.extlink.popupClickHandler || function () {
|
||||
if (drupalSettings.data.extlink.extAlert) {
|
||||
return confirm(drupalSettings.data.extlink.extAlertText);
|
||||
}
|
||||
};
|
||||
|
||||
$(external_links).off("click.extlink");
|
||||
$(external_links).on("click.extlink", function (e) {
|
||||
return Drupal.extlink.popupClickHandler(e, this);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Apply a class and a trailing <span> to all links not containing images.
|
||||
*
|
||||
* @param {object[]} links
|
||||
* An array of DOM elements representing the links.
|
||||
* @param {string} class_name
|
||||
* The class to apply to the links.
|
||||
* @param {string} icon_placement
|
||||
* 'append' or 'prepend' the icon to the link.
|
||||
*/
|
||||
Drupal.extlink.applyClassAndSpan = function (links, class_name, icon_placement) {
|
||||
var $links_to_process;
|
||||
if (drupalSettings.data.extlink.extImgClass) {
|
||||
$links_to_process = $(links);
|
||||
}
|
||||
else {
|
||||
var links_with_images = $(links).find('img, svg').parents('a');
|
||||
$links_to_process = $(links).not(links_with_images);
|
||||
}
|
||||
|
||||
if (class_name !== '0') {
|
||||
$links_to_process.addClass(class_name);
|
||||
}
|
||||
|
||||
// Add data-extlink attribute.
|
||||
$links_to_process.attr('data-extlink', '');
|
||||
|
||||
var i;
|
||||
var length = $links_to_process.length;
|
||||
for (i = 0; i < length; i++) {
|
||||
var $link = $($links_to_process[i]);
|
||||
if (drupalSettings.data.extlink.extUseFontAwesome) {
|
||||
if (class_name === drupalSettings.data.extlink.mailtoClass) {
|
||||
$link[icon_placement]('<span class="fa-' + class_name + ' extlink"><span class="' + drupalSettings.data.extlink.extFaMailtoClasses + '" aria-label="' + drupalSettings.data.extlink.mailtoLabel + '"></span></span>');
|
||||
}
|
||||
else {
|
||||
$link[icon_placement]('<span class="fa-' + class_name + ' extlink"><span class="' + drupalSettings.data.extlink.extFaLinkClasses + '" aria-label="' + drupalSettings.data.extlink.extLabel + '"></span></span>');
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (class_name === drupalSettings.data.extlink.mailtoClass) {
|
||||
$link[icon_placement]('<svg focusable="false" class="' + class_name + '" role="img" aria-label="' + drupalSettings.data.extlink.mailtoLabel + '" xmlns="http://www.w3.org/2000/svg" viewBox="0 10 70 20"><metadata><sfw xmlns="http://ns.adobe.com/SaveForWeb/1.0/"><sliceSourceBounds y="-8160" x="-8165" width="16389" height="16384" bottomLeftOrigin="true"/><optimizationSettings><targetSettings targetSettingsID="0" fileFormat="PNG24Format"><PNG24Format transparency="true" filtered="false" interlaced="false" noMatteColor="false" matteColor="#FFFFFF"/></targetSettings></optimizationSettings></sfw></metadata><title>' + drupalSettings.data.extlink.mailtoLabel + '</title><path d="M56 14H8c-1.1 0-2 0.9-2 2v32c0 1.1 0.9 2 2 2h48c1.1 0 2-0.9 2-2V16C58 14.9 57.1 14 56 14zM50.5 18L32 33.4 13.5 18H50.5zM10 46V20.3l20.7 17.3C31.1 37.8 31.5 38 32 38s0.9-0.2 1.3-0.5L54 20.3V46H10z"/></svg>');
|
||||
}
|
||||
else {
|
||||
$link[icon_placement]('<svg focusable="false" class="' + class_name + '" role="img" aria-label="' + drupalSettings.data.extlink.extLabel + '" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 40"><metadata><sfw xmlns="http://ns.adobe.com/SaveForWeb/1.0/"><sliceSourceBounds y="-8160" x="-8165" width="16389" height="16384" bottomLeftOrigin="true"/><optimizationSettings><targetSettings targetSettingsID="0" fileFormat="PNG24Format"><PNG24Format transparency="true" filtered="false" interlaced="false" noMatteColor="false" matteColor="#FFFFFF"/></targetSettings></optimizationSettings></sfw></metadata><title>' + drupalSettings.data.extlink.extLabel + '</title><path d="M48 26c-1.1 0-2 0.9-2 2v26H10V18h26c1.1 0 2-0.9 2-2s-0.9-2-2-2H8c-1.1 0-2 0.9-2 2v40c0 1.1 0.9 2 2 2h40c1.1 0 2-0.9 2-2V28C50 26.9 49.1 26 48 26z"/><path d="M56 6H44c-1.1 0-2 0.9-2 2s0.9 2 2 2h7.2L30.6 30.6c-0.8 0.8-0.8 2 0 2.8C31 33.8 31.5 34 32 34s1-0.2 1.4-0.6L54 12.8V20c0 1.1 0.9 2 2 2s2-0.9 2-2V8C58 6.9 57.1 6 56 6z"/></svg>');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Drupal.behaviors.extlink = Drupal.behaviors.extlink || {};
|
||||
Drupal.behaviors.extlink.attach = function (context, drupalSettings) {
|
||||
// Backwards compatibility, for the benefit of modules overriding extlink
|
||||
// functionality by defining an "extlinkAttach" global function.
|
||||
if (typeof extlinkAttach === 'function') {
|
||||
extlinkAttach(context);
|
||||
}
|
||||
else {
|
||||
Drupal.extlink.attach(context, drupalSettings);
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery, Drupal, drupalSettings);
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Generate content for a Drupal 6 database to test the upgrade process.
|
||||
*
|
||||
* Run this script at the root of an existing Drupal 6 installation.
|
||||
* Steps to use this generation script:
|
||||
* - Install drupal 6.
|
||||
* - Run this script from your Drupal ROOT directory.
|
||||
* - Use the dump-database-d6.sh to generate the D7 file
|
||||
* modules/simpletest/tests/upgrade/database.filled.php
|
||||
*/
|
||||
|
||||
// Define settings.
|
||||
$cmd = 'index.php';
|
||||
$_SERVER['HTTP_HOST'] = 'default';
|
||||
$_SERVER['PHP_SELF'] = '/index.php';
|
||||
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
||||
$_SERVER['SERVER_SOFTWARE'] = NULL;
|
||||
$_SERVER['REQUEST_METHOD'] = 'GET';
|
||||
$_SERVER['QUERY_STRING'] = '';
|
||||
$_SERVER['PHP_SELF'] = $_SERVER['REQUEST_URI'] = '/';
|
||||
$_SERVER['HTTP_USER_AGENT'] = 'console';
|
||||
$modules_to_enable = array('path', 'poll');
|
||||
|
||||
// Bootstrap Drupal.
|
||||
include_once './includes/bootstrap.inc';
|
||||
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
|
||||
|
||||
// Enable requested modules
|
||||
include_once './modules/system/system.admin.inc';
|
||||
$form = system_modules();
|
||||
foreach ($modules_to_enable as $module) {
|
||||
$form_state['values']['status'][$module] = TRUE;
|
||||
}
|
||||
$form_state['values']['disabled_modules'] = $form['disabled_modules'];
|
||||
system_modules_submit(NULL, $form_state);
|
||||
unset($form_state);
|
||||
|
||||
// Run cron after installing
|
||||
drupal_cron_run();
|
||||
|
||||
// Create six users
|
||||
for ($i = 0; $i < 6; $i++) {
|
||||
$name = "test user $i";
|
||||
$pass = md5("test PassW0rd $i !(.)");
|
||||
$mail = "test$i@example.com";
|
||||
$now = mktime(0, 0, 0, 1, $i + 1, 2010);
|
||||
db_query("INSERT INTO {users} (name, pass, mail, status, created, access) VALUES ('%s', '%s', '%s', %d, %d, %d)", $name, $pass, $mail, 1, $now, $now);
|
||||
}
|
||||
|
||||
|
||||
// Create vocabularies and terms
|
||||
|
||||
$terms = array();
|
||||
|
||||
// All possible combinations of these vocabulary properties.
|
||||
$hierarchy = array(0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2);
|
||||
$multiple = array(0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1);
|
||||
$required = array(0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1);
|
||||
|
||||
$voc_id = 0;
|
||||
$term_id = 0;
|
||||
for ($i = 0; $i < 24; $i++) {
|
||||
$vocabulary = array();
|
||||
++$voc_id;
|
||||
$vocabulary['name'] = "vocabulary $voc_id (i=$i)";
|
||||
$vocabulary['description'] = "description of ". $vocabulary['name'];
|
||||
$vocabulary['nodes'] = $i > 11 ? array('page' => TRUE) : array();
|
||||
$vocabulary['multiple'] = $multiple[$i % 12];
|
||||
$vocabulary['required'] = $required[$i % 12];
|
||||
$vocabulary['relations'] = 1;
|
||||
$vocabulary['hierarchy'] = $hierarchy[$i % 12];
|
||||
$vocabulary['weight'] = $i;
|
||||
taxonomy_save_vocabulary($vocabulary);
|
||||
$parents = array();
|
||||
// Vocabularies without hierarchy get one term, single parent vocabularies get
|
||||
// one parent and one child term. Multiple parent vocabularies get three
|
||||
// terms: t0, t1, t2 where t0 is a parent of both t1 and t2.
|
||||
for ($j = 0; $j < $vocabulary['hierarchy'] + 1; $j++) {
|
||||
$term = array();
|
||||
$term['vid'] = $vocabulary['vid'];
|
||||
// For multiple parent vocabularies, omit the t0-t1 relation, otherwise
|
||||
// every parent in the vocabulary is a parent.
|
||||
$term['parent'] = $vocabulary['hierarchy'] == 2 && i == 1 ? array() : $parents;
|
||||
++$term_id;
|
||||
$term['name'] = "term $term_id of vocabulary $voc_id (j=$j)";
|
||||
$term['description'] = 'description of ' . $term['name'];
|
||||
$term['weight'] = $i * 3 + $j;
|
||||
taxonomy_save_term($term);
|
||||
$terms[] = $term['tid'];
|
||||
$parents[] = $term['tid'];
|
||||
}
|
||||
}
|
||||
|
||||
$node_id = 0;
|
||||
$revision_id = 0;
|
||||
module_load_include('inc', 'node', 'node.pages');
|
||||
for ($i = 0; $i < 24; $i++) {
|
||||
$uid = intval($i / 8) + 3;
|
||||
$user = user_load($uid);
|
||||
$node = new stdClass();
|
||||
$node->uid = $uid;
|
||||
$node->type = $i < 12 ? 'page' : 'story';
|
||||
$node->sticky = 0;
|
||||
++$node_id;
|
||||
++$revision_id;
|
||||
$node->title = "node title $node_id rev $revision_id (i=$i)";
|
||||
$type = node_get_types('type', $node->type);
|
||||
if ($type->has_body) {
|
||||
$node->body = str_repeat("node body ($node->type) - $i", 100);
|
||||
$node->teaser = node_teaser($node->body);
|
||||
$node->filter = variable_get('filter_default_format', 1);
|
||||
$node->format = FILTER_FORMAT_DEFAULT;
|
||||
}
|
||||
$node->status = intval($i / 4) % 2;
|
||||
$node->language = '';
|
||||
$node->revision = $i < 12;
|
||||
$node->promote = $i % 2;
|
||||
$node->created = $now + $i * 86400;
|
||||
$node->log = "added $i node";
|
||||
// Make every term association different a little. For nodes with revisions,
|
||||
// make the initial revision have a different set of terms than the
|
||||
// newest revision.
|
||||
$node_terms = $terms;
|
||||
unset($node_terms[$i], $node_terms[47 - $i]);
|
||||
if ($node->revision) {
|
||||
$node->taxonomy = array($i => $terms[$i], 47-$i => $terms[47 - $i]);
|
||||
}
|
||||
else {
|
||||
$node->taxonomy = $node_terms;
|
||||
}
|
||||
node_save($node);
|
||||
path_set_alias("node/$node->nid", "content/$node->created");
|
||||
if ($node->revision) {
|
||||
$user = user_load($uid + 3);
|
||||
++$revision_id;
|
||||
$node->title .= " rev2 $revision_id";
|
||||
$node->body = str_repeat("node revision body ($node->type) - $i", 100);
|
||||
$node->log = "added $i revision";
|
||||
$node->taxonomy = $node_terms;
|
||||
node_save($node);
|
||||
}
|
||||
}
|
||||
|
||||
// Create poll content
|
||||
for ($i = 0; $i < 12; $i++) {
|
||||
$uid = intval($i / 4) + 3;
|
||||
$user = user_load($uid);
|
||||
$node = new stdClass();
|
||||
$node->uid = $uid;
|
||||
$node->type = 'poll';
|
||||
$node->sticky = 0;
|
||||
$node->title = "poll title $i";
|
||||
$type = node_get_types('type', $node->type);
|
||||
if ($type->has_body) {
|
||||
$node->body = str_repeat("node body ($node->type) - $i", 100);
|
||||
$node->teaser = node_teaser($node->body);
|
||||
$node->filter = variable_get('filter_default_format', 1);
|
||||
$node->format = FILTER_FORMAT_DEFAULT;
|
||||
}
|
||||
$node->status = intval($i / 2) % 2;
|
||||
$node->language = '';
|
||||
$node->revision = 1;
|
||||
$node->promote = $i % 2;
|
||||
$node->created = $now + $i * 43200;
|
||||
$node->log = "added $i poll";
|
||||
|
||||
$nbchoices = ($i % 4) + 2;
|
||||
for ($c = 0; $c < $nbchoices; $c++) {
|
||||
$node->choice[] = array('chtext' => "Choice $c for poll $i");
|
||||
}
|
||||
node_save($node);
|
||||
path_set_alias("node/$node->nid", "content/poll/$i");
|
||||
path_set_alias("node/$node->nid/results", "content/poll/$i/results");
|
||||
|
||||
// Add some votes
|
||||
for ($v = 0; $v < ($i % 4) + 5; $v++) {
|
||||
$c = $v % $nbchoices;
|
||||
$form_state = array();
|
||||
$form_state['values']['choice'] = $c;
|
||||
$form_state['values']['op'] = t('Vote');
|
||||
drupal_execute('poll_view_voting', $form_state, $node);
|
||||
}
|
||||
}
|
||||
|
||||
$uid = 6;
|
||||
$user = user_load($uid);
|
||||
$node = new stdClass();
|
||||
$node->uid = $uid;
|
||||
$node->type = 'broken';
|
||||
$node->sticky = 0;
|
||||
$node->title = "node title 24";
|
||||
$node->body = str_repeat("node body ($node->type) - 37", 100);
|
||||
$node->teaser = node_teaser($node->body);
|
||||
$node->filter = variable_get('filter_default_format', 1);
|
||||
$node->format = FILTER_FORMAT_DEFAULT;
|
||||
$node->status = 1;
|
||||
$node->language = '';
|
||||
$node->revision = 0;
|
||||
$node->promote = 0;
|
||||
$node->created = 1263769200;
|
||||
$node->log = "added $i node";
|
||||
node_save($node);
|
||||
path_set_alias("node/$node->nid", "content/1263769200");
|
||||
@@ -0,0 +1,318 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Generate content for a Drupal 7 database to test the upgrade process.
|
||||
*
|
||||
* Run this script at the root of an existing Drupal 7 installation.
|
||||
*
|
||||
* Steps to use this generation script:
|
||||
* - Install drupal 7.
|
||||
* - Run this script from your Drupal ROOT directory.
|
||||
* - Use the dump-database-d7.sh to generate the D7 file
|
||||
* modules/simpletest/tests/upgrade/database.filled.php
|
||||
*/
|
||||
|
||||
// Define settings.
|
||||
$cmd = 'index.php';
|
||||
define('DRUPAL_ROOT', getcwd());
|
||||
$_SERVER['HTTP_HOST'] = 'default';
|
||||
$_SERVER['PHP_SELF'] = '/index.php';
|
||||
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
||||
$_SERVER['SERVER_SOFTWARE'] = NULL;
|
||||
$_SERVER['REQUEST_METHOD'] = 'GET';
|
||||
$_SERVER['QUERY_STRING'] = '';
|
||||
$_SERVER['PHP_SELF'] = $_SERVER['REQUEST_URI'] = '/';
|
||||
$_SERVER['HTTP_USER_AGENT'] = 'console';
|
||||
$modules_to_enable = array('path', 'poll', 'taxonomy');
|
||||
|
||||
// Bootstrap Drupal.
|
||||
include_once './includes/bootstrap.inc';
|
||||
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
|
||||
|
||||
// Enable requested modules
|
||||
require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc');
|
||||
include_once './modules/system/system.admin.inc';
|
||||
$form = system_modules();
|
||||
foreach ($modules_to_enable as $module) {
|
||||
$form_state['values']['status'][$module] = TRUE;
|
||||
}
|
||||
$form_state['values']['disabled_modules'] = $form['disabled_modules'];
|
||||
system_modules_submit(NULL, $form_state);
|
||||
unset($form_state);
|
||||
|
||||
// Run cron after installing
|
||||
drupal_cron_run();
|
||||
|
||||
// Create six users
|
||||
$query = db_insert('users')->fields(array('uid', 'name', 'pass', 'mail', 'status', 'created', 'access'));
|
||||
for ($i = 0; $i < 6; $i++) {
|
||||
$name = "test user $i";
|
||||
$pass = md5("test PassW0rd $i !(.)");
|
||||
$mail = "test$i@example.com";
|
||||
$now = mktime(0, 0, 0, 1, $i + 1, 2010);
|
||||
$query->values(array(db_next_id(), $name, user_hash_password($pass), $mail, 1, $now, $now));
|
||||
}
|
||||
$query->execute();
|
||||
|
||||
// Create vocabularies and terms
|
||||
|
||||
$terms = array();
|
||||
|
||||
// All possible combinations of these vocabulary properties.
|
||||
$hierarchy = array(0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2);
|
||||
$multiple = array(0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1);
|
||||
$required = array(0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1);
|
||||
|
||||
$voc_id = 0;
|
||||
$term_id = 0;
|
||||
for ($i = 0; $i < 24; $i++) {
|
||||
$vocabulary = new stdClass;
|
||||
++$voc_id;
|
||||
$vocabulary->name = "vocabulary $voc_id (i=$i)";
|
||||
$vocabulary->machine_name = 'vocabulary_' . $voc_id . '_' . $i;
|
||||
$vocabulary->description = "description of ". $vocabulary->name;
|
||||
$vocabulary->multiple = $multiple[$i % 12];
|
||||
$vocabulary->required = $required[$i % 12];
|
||||
$vocabulary->relations = 1;
|
||||
$vocabulary->hierarchy = $hierarchy[$i % 12];
|
||||
$vocabulary->weight = $i;
|
||||
taxonomy_vocabulary_save($vocabulary);
|
||||
$field = array(
|
||||
'field_name' => 'taxonomy_'. $vocabulary->machine_name,
|
||||
'module' => 'taxonomy',
|
||||
'type' => 'taxonomy_term_reference',
|
||||
'cardinality' => $vocabulary->multiple || $vocabulary->tags ? FIELD_CARDINALITY_UNLIMITED : 1,
|
||||
'settings' => array(
|
||||
'required' => $vocabulary->required ? TRUE : FALSE,
|
||||
'allowed_values' => array(
|
||||
array(
|
||||
'vocabulary' => $vocabulary->machine_name,
|
||||
'parent' => 0,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
field_create_field($field);
|
||||
$node_types = $i > 11 ? array('page') : array_keys(node_type_get_types());
|
||||
foreach ($node_types as $bundle) {
|
||||
$instance = array(
|
||||
'label' => $vocabulary->name,
|
||||
'field_name' => $field['field_name'],
|
||||
'bundle' => $bundle,
|
||||
'entity_type' => 'node',
|
||||
'settings' => array(),
|
||||
'description' => $vocabulary->help,
|
||||
'required' => $vocabulary->required,
|
||||
'widget' => array(),
|
||||
'display' => array(
|
||||
'default' => array(
|
||||
'type' => 'taxonomy_term_reference_link',
|
||||
'weight' => 10,
|
||||
),
|
||||
'teaser' => array(
|
||||
'type' => 'taxonomy_term_reference_link',
|
||||
'weight' => 10,
|
||||
),
|
||||
),
|
||||
);
|
||||
if ($vocabulary->tags) {
|
||||
$instance['widget'] = array(
|
||||
'type' => 'taxonomy_autocomplete',
|
||||
'module' => 'taxonomy',
|
||||
'settings' => array(
|
||||
'size' => 60,
|
||||
'autocomplete_path' => 'taxonomy/autocomplete',
|
||||
),
|
||||
);
|
||||
}
|
||||
else {
|
||||
$instance['widget'] = array(
|
||||
'type' => 'options_select',
|
||||
'settings' => array(),
|
||||
);
|
||||
}
|
||||
field_create_instance($instance);
|
||||
}
|
||||
$parents = array();
|
||||
// Vocabularies without hierarchy get one term, single parent vocabularies get
|
||||
// one parent and one child term. Multiple parent vocabularies get three
|
||||
// terms: t0, t1, t2 where t0 is a parent of both t1 and t2.
|
||||
for ($j = 0; $j < $vocabulary->hierarchy + 1; $j++) {
|
||||
++$term_id;
|
||||
$term = entity_create('taxonomy_term', array(
|
||||
'vocabulary_machine_name' => $vocabulary->machine_name,
|
||||
// For multiple parent vocabularies, omit the t0-t1 relation, otherwise
|
||||
// every parent in the vocabulary is a parent.
|
||||
'parent' => $vocabulary->hierarchy == 2 && i == 1 ? array() : $parents,
|
||||
'name' => "term $term_id of vocabulary $voc_id (j=$j)",
|
||||
'description' => 'description of ' . $term->name,
|
||||
'format' => 'filtered_html',
|
||||
'weight' => $i * 3 + $j,
|
||||
));
|
||||
taxonomy_term_save($term);
|
||||
$terms[] = $term->tid;
|
||||
$term_vocabs[$term->tid] = 'taxonomy_' . $vocabulary->machine_name;
|
||||
$parents[] = $term->tid;
|
||||
}
|
||||
}
|
||||
$node_id = 0;
|
||||
$revision_id = 0;
|
||||
module_load_include('inc', 'node', 'node.pages');
|
||||
for ($i = 0; $i < 36; $i++) {
|
||||
$uid = intval($i / 8) + 3;
|
||||
$user = user_load($uid);
|
||||
$node = new stdClass();
|
||||
$node->uid = $uid;
|
||||
$node->type = 'page';
|
||||
if ($i < 12) {
|
||||
$node->type = 'page';
|
||||
}
|
||||
elseif ($i < 24) {
|
||||
$node->type = 'story';
|
||||
}
|
||||
elseif (module_exists('blog')) {
|
||||
$node->type = 'blog';
|
||||
}
|
||||
$node->sticky = 0;
|
||||
++$node_id;
|
||||
++$revision_id;
|
||||
$node->title = "node title $node_id rev $revision_id (i=$i)";
|
||||
$node->language = LANGUAGE_NONE;
|
||||
$body_text = str_repeat("node body ($node->type) - $i", 100);
|
||||
$node->body[$node->language][0]['value'] = $body_text;
|
||||
$node->body[$node->language][0]['summary'] = text_summary($body_text);
|
||||
$node->body[$node->language][0]['format'] = 'filtered_html';
|
||||
$node->status = intval($i / 4) % 2;
|
||||
$node->revision = $i < 12;
|
||||
$node->promote = $i % 2;
|
||||
$node->created = $now + $i * 86400;
|
||||
$node->log = "added $i node";
|
||||
// Make every term association different a little. For nodes with revisions,
|
||||
// make the initial revision have a different set of terms than the
|
||||
// newest revision.
|
||||
$items = array();
|
||||
if ($node->revision) {
|
||||
$node_terms = array($terms[$i], $terms[47-$i]);
|
||||
}
|
||||
else {
|
||||
$node_terms = $terms;
|
||||
unset($node_terms[$i], $node_terms[47 - $i]);
|
||||
}
|
||||
foreach ($node_terms as $tid) {
|
||||
$field_name = $term_vocabs[$tid];
|
||||
$node->{$field_name}[LANGUAGE_NONE][] = array('tid' => $tid);
|
||||
}
|
||||
$node->path = array('alias' => "content/$node->created");
|
||||
node_save($node);
|
||||
if ($node->revision) {
|
||||
$user = user_load($uid + 3);
|
||||
++$revision_id;
|
||||
$node->title .= " rev2 $revision_id";
|
||||
$body_text = str_repeat("node revision body ($node->type) - $i", 100);
|
||||
$node->body[$node->language][0]['value'] = $body_text;
|
||||
$node->body[$node->language][0]['summary'] = text_summary($body_text);
|
||||
$node->body[$node->language][0]['format'] = 'filtered_html';
|
||||
$node->log = "added $i revision";
|
||||
$node_terms = $terms;
|
||||
unset($node_terms[$i], $node_terms[47 - $i]);
|
||||
foreach ($node_terms as $tid) {
|
||||
$field_name = $term_vocabs[$tid];
|
||||
$node->{$field_name}[LANGUAGE_NONE][] = array('tid' => $tid);
|
||||
}
|
||||
node_save($node);
|
||||
}
|
||||
}
|
||||
|
||||
// Create poll content
|
||||
for ($i = 0; $i < 12; $i++) {
|
||||
$uid = intval($i / 4) + 3;
|
||||
$user = user_load($uid);
|
||||
$node = new stdClass();
|
||||
$node->uid = $uid;
|
||||
$node->type = 'poll';
|
||||
$node->sticky = 0;
|
||||
$node->title = "poll title $i";
|
||||
$node->language = LANGUAGE_NONE;
|
||||
$node->status = intval($i / 2) % 2;
|
||||
$node->revision = 1;
|
||||
$node->promote = $i % 2;
|
||||
$node->created = $_SERVER['REQUEST_TIME'] + $i * 43200;
|
||||
$node->runtime = 0;
|
||||
$node->active = 1;
|
||||
$node->log = "added $i poll";
|
||||
$node->path = array('alias' => "content/poll/$i");
|
||||
|
||||
$nbchoices = ($i % 4) + 2;
|
||||
for ($c = 0; $c < $nbchoices; $c++) {
|
||||
$node->choice[] = array('chtext' => "Choice $c for poll $i", 'chvotes' => 0, 'weight' => 0);
|
||||
}
|
||||
node_save($node);
|
||||
$path = array(
|
||||
'alias' => "content/poll/$i/results",
|
||||
'source' => "node/$node->nid/results",
|
||||
);
|
||||
path_save($path);
|
||||
|
||||
// Add some votes
|
||||
$node = node_load($node->nid);
|
||||
$choices = array_keys($node->choice);
|
||||
$original_user = $GLOBALS['user'];
|
||||
for ($v = 0; $v < ($i % 4); $v++) {
|
||||
drupal_static_reset('ip_address');
|
||||
$_SERVER['REMOTE_ADDR'] = "127.0.$v.1";
|
||||
$GLOBALS['user'] = drupal_anonymous_user();// We should have already allowed anon to vote.
|
||||
$c = $v % $nbchoices;
|
||||
$form_state = array();
|
||||
$form_state['values']['choice'] = $choices[$c];
|
||||
$form_state['values']['op'] = t('Vote');
|
||||
drupal_form_submit('poll_view_voting', $form_state, $node);
|
||||
}
|
||||
}
|
||||
|
||||
$uid = 6;
|
||||
$node_type = 'broken';
|
||||
$user = user_load($uid);
|
||||
$node = new stdClass();
|
||||
$node->uid = $uid;
|
||||
$node->type = 'article';
|
||||
$body_text = str_repeat("node body ($node_type) - 37", 100);
|
||||
$node->sticky = 0;
|
||||
$node->title = "node title 24";
|
||||
$node->language = LANGUAGE_NONE;
|
||||
$node->body[$node->language][0]['value'] = $body_text;
|
||||
$node->body[$node->language][0]['summary'] = text_summary($body_text);
|
||||
$node->body[$node->language][0]['format'] = 'filtered_html';
|
||||
$node->status = 1;
|
||||
$node->revision = 0;
|
||||
$node->promote = 0;
|
||||
$node->created = 1263769200;
|
||||
$node->log = "added a broken node";
|
||||
$node->path = array('alias' => "content/1263769200");
|
||||
node_save($node);
|
||||
db_update('node')
|
||||
->fields(array(
|
||||
'type' => $node_type,
|
||||
))
|
||||
->condition('nid', $node->nid)
|
||||
->execute();
|
||||
db_update('field_data_body')
|
||||
->fields(array(
|
||||
'bundle' => $node_type,
|
||||
))
|
||||
->condition('entity_id', $node->nid)
|
||||
->condition('entity_type', 'node')
|
||||
->execute();
|
||||
db_update('field_revision_body')
|
||||
->fields(array(
|
||||
'bundle' => $node_type,
|
||||
))
|
||||
->condition('entity_id', $node->nid)
|
||||
->condition('entity_type', 'node')
|
||||
->execute();
|
||||
db_update('field_config_instance')
|
||||
->fields(array(
|
||||
'bundle' => $node_type,
|
||||
))
|
||||
->condition('bundle', 'article')
|
||||
->execute();
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* A script to generate proxy classes for lazy services.
|
||||
*
|
||||
* For help, type this command from the root directory of an installed Drupal
|
||||
* site: php core/scripts/generate-proxy-class.php -h generate-proxy-class
|
||||
*
|
||||
* @ingroup container
|
||||
*
|
||||
* @see lazy_services
|
||||
*/
|
||||
|
||||
use Drupal\Core\Command\GenerateProxyClassApplication;
|
||||
use Drupal\Core\DrupalKernel;
|
||||
use Drupal\Core\ProxyBuilder\ProxyBuilder;
|
||||
use Drupal\Core\Site\Settings;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Bootstrap.
|
||||
$autoloader = require __DIR__ . '/../../autoload.php';
|
||||
$request = Request::createFromGlobals();
|
||||
Settings::initialize(dirname(__DIR__, 2), DrupalKernel::findSitePath($request), $autoloader);
|
||||
DrupalKernel::createFromRequest($request, $autoloader, 'prod')->boot();
|
||||
|
||||
// Run the database dump command.
|
||||
$application = new GenerateProxyClassApplication(new ProxyBuilder());
|
||||
$application->run();
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"rules": {
|
||||
"strict": [2, "global"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @file
|
||||
* Callback returning the list of files to copy to the assets/vendor directory.
|
||||
*/
|
||||
const glob = require('glob');
|
||||
// There are a lot of CKEditor 5 packages, generate the list dynamically.
|
||||
// Drupal-specific mapping between CKEditor 5 name and Drupal library name.
|
||||
const ckeditor5PluginMapping = {
|
||||
'block-quote': 'blockquote',
|
||||
essentials: 'internal',
|
||||
'basic-styles': 'basic',
|
||||
};
|
||||
|
||||
/**
|
||||
* Build the list of assets to be copied based on what exists in the filesystem.
|
||||
*
|
||||
* @param {string} packageFolder
|
||||
* The path to node_modules folder.
|
||||
*
|
||||
* @return {DrupalLibraryAsset[]}
|
||||
* List of libraries and files to process.
|
||||
*/
|
||||
module.exports = (packageFolder) => {
|
||||
const fileList = [];
|
||||
// Get all the CKEditor 5 packages.
|
||||
const ckeditor5Dirs = glob.sync(`{${packageFolder}/@ckeditor/ckeditor5*,${packageFolder}/ckeditor5}`);
|
||||
for (const ckeditor5package of ckeditor5Dirs) {
|
||||
// Add all the files in the build/ directory to the process array for
|
||||
// copying.
|
||||
const buildFiles = glob.sync(`${ckeditor5package}/build/**/*.js`, {
|
||||
nodir: true,
|
||||
});
|
||||
if (buildFiles.length) {
|
||||
// Clean up the path to get the original package name.
|
||||
const pack = ckeditor5package.replace(`${packageFolder}/`, '');
|
||||
// Use the package name to generate the plugin name. There are some
|
||||
// exceptions that needs to be handled. Ideally remove the special cases.
|
||||
let pluginName = pack.replace('@ckeditor/ckeditor5-', '');
|
||||
// Target folder in the vendor/assets folder.
|
||||
let folder = `ckeditor5/${pluginName.replace('@ckeditor/ckeditor5-', '')}`;
|
||||
// Transform kebab-case to CamelCase.
|
||||
let library = pluginName.replace(/-./g, (match) => match[1].toUpperCase());
|
||||
// Special case for Drupal implementation.
|
||||
if (ckeditor5PluginMapping.hasOwnProperty(pluginName)) {
|
||||
library = ckeditor5PluginMapping[pluginName];
|
||||
}
|
||||
if (library === 'ckeditor5') {
|
||||
folder = 'ckeditor5/ckeditor5-dll';
|
||||
} else {
|
||||
library = `ckeditor5.${library}`;
|
||||
}
|
||||
fileList.push({
|
||||
pack,
|
||||
library,
|
||||
folder,
|
||||
files: buildFiles.map((absolutePath) => ({
|
||||
from: absolutePath.replace(`${ckeditor5package}/`, ''),
|
||||
to: absolutePath.replace(`${ckeditor5package}/build/`, ''),
|
||||
})),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return fileList;
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
const Terser = require('terser');
|
||||
const path = require('path');
|
||||
|
||||
/**
|
||||
* Process jQuery UI source files.
|
||||
*
|
||||
* Each file being processed creates 3 files under assets/vendor/jquery.ui/:
|
||||
* - The original source for audit purposes, with a `.js` suffix.
|
||||
* - The minified version for production use, with a `-min.js` suffix.
|
||||
* - The source map for debugging purposes, with a `-min.js.map` suffix.
|
||||
*
|
||||
* @param {object} data
|
||||
* Object passed to the callback.
|
||||
* @param {object} data.file
|
||||
* Normalized file information object.
|
||||
* @param {string} data.file.from
|
||||
* Path of the file in node_modules/ directory.
|
||||
* @param {string} data.file.to
|
||||
* Path of the file in core assets/vendor/ directory.
|
||||
* @param {string} data.contents
|
||||
* Content of the file being processed.
|
||||
*
|
||||
* @return {Promise<[{filename: string, contents: string}]>}
|
||||
* Return a Promise that resolves into an array of file and content to create
|
||||
* in the assets/vendor/ directory.
|
||||
*/
|
||||
module.exports = async ({ file: { from, to }, contents }) => {
|
||||
const filename = `${to.slice(0, -3)}-min.js`;
|
||||
const sourcemap = `${filename}.map`;
|
||||
|
||||
const { code, map } = await Terser.minify(
|
||||
{ [path.basename(from)]: contents }, {
|
||||
sourceMap: {
|
||||
filename: path.basename(filename),
|
||||
url: path.basename(sourcemap),
|
||||
},
|
||||
});
|
||||
|
||||
return [
|
||||
// Original file.
|
||||
{ filename: to, contents },
|
||||
// Minified file.
|
||||
{ filename, contents: code },
|
||||
// Sourcemap file.
|
||||
{ filename: sourcemap, contents: map },
|
||||
];
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Process map files.
|
||||
*
|
||||
* In the `sources` member, remove all "../" values at the start of the file
|
||||
* names to avoid virtual files located outside of the library vendor folder.
|
||||
*
|
||||
* @param {object} data
|
||||
* Object passed to the callback.
|
||||
* @param {string} data.contents
|
||||
* Content of the file being processed.
|
||||
*
|
||||
* @return {Promise<[{contents: string}]>}
|
||||
* Return a Promise that resolves into an array of file and content to create
|
||||
* in the assets/vendor/ directory.
|
||||
*/
|
||||
module.exports = ({ contents }) => {
|
||||
const json = JSON.parse(contents);
|
||||
json.sources = json.sources.map((source) => source.replace(/^(\.\.\/)+/, ''));
|
||||
return [{ contents: JSON.stringify(json) }];
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Provides the build:js command to compile *.es6.js files to ES5.
|
||||
*
|
||||
* Run build:js with --file to only parse a specific file. Using the --check
|
||||
* flag build:js can be run to check if files are compiled correctly.
|
||||
* @example <caption>Only process misc/drupal.es6.js and misc/drupal.init.es6.js</caption
|
||||
* yarn run build:js -- --file misc/drupal.es6.js --file misc/drupal.init.es6.js
|
||||
* @example <caption>Check if all files have been compiled correctly</caption
|
||||
* yarn run build:js -- --check
|
||||
*
|
||||
* @internal This file is part of the core javascript build process and is only
|
||||
* meant to be used in that context.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const glob = require('glob');
|
||||
const argv = require('minimist')(process.argv.slice(2));
|
||||
const changeOrAdded = require('./changeOrAdded');
|
||||
const check = require('./check');
|
||||
const log = require('./log');
|
||||
|
||||
console.warn('⚠️ yarn `build:js` command is deprecated in drupal:9.4.0 and will be removed from drupal:10.0.0. This command is no longer needed in Drupal 10.0.0 once https://www.drupal.org/project/drupal/issues/3278415 is committed.️');
|
||||
|
||||
// Match only on .es6.js files.
|
||||
const fileMatch = './**/*.es6.js';
|
||||
// Ignore everything in node_modules
|
||||
const globOptions = {
|
||||
ignore: './node_modules/**'
|
||||
};
|
||||
const processFiles = (error, filePaths) => {
|
||||
if (error) {
|
||||
process.exitCode = 1;
|
||||
}
|
||||
// Process all the found files.
|
||||
let callback = changeOrAdded;
|
||||
if (argv.check) {
|
||||
callback = check;
|
||||
}
|
||||
filePaths.forEach(callback);
|
||||
};
|
||||
|
||||
if (argv.file) {
|
||||
processFiles(null, [].concat(argv.file));
|
||||
}
|
||||
else {
|
||||
glob(fileMatch, globOptions, processFiles);
|
||||
}
|
||||
process.exitCode = 0;
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Watch changes to *.es6.js files and compile them to ES5 during development.
|
||||
*
|
||||
* @internal This file is part of the core javascript build process and is only
|
||||
* meant to be used in that context.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const chokidar = require('chokidar');
|
||||
|
||||
const changeOrAdded = require('./changeOrAdded');
|
||||
const log = require('./log');
|
||||
|
||||
console.warn('⚠️ yarn `watch:js` command is deprecated in drupal:9.4.0 and will be removed from drupal:10.0.0. This command is no longer needed in Drupal 10.0.0 once https://www.drupal.org/project/drupal/issues/3278415 is committed.️');
|
||||
|
||||
// Match only on .es6.js files.
|
||||
const fileMatch = './**/*.es6.js';
|
||||
// Ignore everything in node_modules
|
||||
const watcher = chokidar.watch(fileMatch, {
|
||||
ignoreInitial: true,
|
||||
ignored: './node_modules/**'
|
||||
});
|
||||
|
||||
const unlinkHandler = (err) => {
|
||||
if (err) {
|
||||
log(err);
|
||||
}
|
||||
};
|
||||
|
||||
// Watch for filesystem changes.
|
||||
watcher
|
||||
.on('add', changeOrAdded)
|
||||
.on('change', changeOrAdded)
|
||||
.on('unlink', (filePath) => {
|
||||
const fileName = filePath.slice(0, -7);
|
||||
fs.stat(`${fileName}.js`, () => {
|
||||
fs.unlink(`${fileName}.js`, unlinkHandler);
|
||||
});
|
||||
})
|
||||
.on('ready', () => log(`Watching '${fileMatch}' for changes.`));
|
||||
@@ -0,0 +1,15 @@
|
||||
const fs = require('fs');
|
||||
const log = require('./log');
|
||||
const compile = require('./compile');
|
||||
|
||||
module.exports = (filePath) => {
|
||||
log(`'${filePath}' is being processed.`);
|
||||
// Transform the file.
|
||||
compile(filePath, function write(code) {
|
||||
const fileName = filePath.slice(0, -7);
|
||||
// Write the result to the filesystem.
|
||||
fs.writeFile(`${fileName}.js`, code, () => {
|
||||
log(`'${filePath}' is finished.`);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
const chalk = require('chalk');
|
||||
const fs = require('fs');
|
||||
const log = require('./log');
|
||||
const compile = require('./compile');
|
||||
|
||||
module.exports = (filePath) => {
|
||||
log(`'${filePath}' is being checked.`);
|
||||
// Transform the file.
|
||||
compile(filePath, function check(code) {
|
||||
const fileName = filePath.slice(0, -7);
|
||||
fs.readFile(`${fileName}.js`, function read(err, data) {
|
||||
if (err) {
|
||||
log(chalk.red(err));
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
if (code !== data.toString()) {
|
||||
log(chalk.red(`'${filePath}' is not updated.`));
|
||||
process.exitCode = 1;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Provides the `check:ckeditor5` command.
|
||||
*
|
||||
* Check that the plugins are built with the appropriate dependencies. This is
|
||||
* only run on DrupalCI.
|
||||
*
|
||||
* @internal This file is part of the core JavaScript build process and is only
|
||||
* meant to be used in that context.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const glob = require("glob");
|
||||
const log = require("./log");
|
||||
const fs = require("fs").promises;
|
||||
const child_process = require("child_process");
|
||||
|
||||
async function getContents(files) {
|
||||
return Object.fromEntries(
|
||||
await Promise.all(
|
||||
files.map(async (file) => [file, (await fs.readFile(file)).toString()])
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
(async () => {
|
||||
const files = glob.sync("./modules/ckeditor5/js/build/*.js");
|
||||
|
||||
const pluginsBefore = await getContents(files);
|
||||
// Execute the plugin build script.
|
||||
child_process.execSync("yarn run build:ckeditor5");
|
||||
const pluginsAfter = await getContents(files);
|
||||
|
||||
if (JSON.stringify(pluginsBefore) !== JSON.stringify(pluginsAfter)) {
|
||||
process.exitCode = 1;
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Provides the `build:ckeditor5-types` command.
|
||||
*
|
||||
* This command is used for generating documentation for mapping CKEditor 5
|
||||
* types so that they can be parsed by IDEs.
|
||||
*
|
||||
* @internal This file is part of the core javascript build process and is only
|
||||
* meant to be used in that context.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const glob = require('glob');
|
||||
const log = require('./log');
|
||||
const fs = require('fs');
|
||||
|
||||
/**
|
||||
* A list of regex used to alias CKEditor 5 types.
|
||||
*
|
||||
* @type {RegExp[]}
|
||||
*/
|
||||
const regexList = [
|
||||
// Makes sure that `export default class` code can be referenced with the
|
||||
// class name and not the module name only.
|
||||
/ * @module \b(.*)\b[\s\S]*?export default(?: class| function)? \b(\w+)\b/g,
|
||||
|
||||
// Pick up CKEditor 5 own aliases to alias them too.
|
||||
/ * @module \b(.*)\b[\s\S]*?@(?:typedef|interface) (?:.*~)?(\w+)/g,
|
||||
];
|
||||
|
||||
const globOptions = {
|
||||
// Search within the ckeditor npm namespace.
|
||||
cwd: process.cwd() + '/node_modules/@ckeditor/',
|
||||
absolute: true,
|
||||
};
|
||||
|
||||
/**
|
||||
* Template for the generated typedef comment.
|
||||
*
|
||||
* @param {string} file
|
||||
* The path to the file containing the type definition.
|
||||
* @param {string} module
|
||||
* The module name as defined by the @module jsdoc comment.
|
||||
* @param {string} name
|
||||
* The name of the class being exported
|
||||
*
|
||||
* @return {string}
|
||||
* The comment aliasing the module name to the specific named exports.
|
||||
*/
|
||||
function generateTypeDef(file, module, name) {
|
||||
const cleanModule = module.replace('module:', '');
|
||||
return `/**
|
||||
* Declared in file @ckeditor/${file.replace(globOptions.cwd, '')}
|
||||
*
|
||||
* @typedef {module:${cleanModule}} module:${cleanModule}~${name}
|
||||
*/
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper to get the file contents as a string.
|
||||
*
|
||||
* @param {string} filePath
|
||||
* Absolute path to the file.
|
||||
*
|
||||
* @return {string}
|
||||
*/
|
||||
function getFile(filePath) {
|
||||
try {
|
||||
return fs.readFileSync(filePath, 'utf8');
|
||||
} catch (err) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a callback function.
|
||||
*
|
||||
* @param {string} filePath
|
||||
* The CKEditor 5 source file to inspect for exports or type definitions.
|
||||
*
|
||||
* @return {function}
|
||||
* The aliased typedef string.
|
||||
*
|
||||
* @see generateTypeDef
|
||||
*/
|
||||
function processFile(filePath) {
|
||||
const fileData = getFile(filePath);
|
||||
// Use a for loop to be able to return early.
|
||||
for (const regex of regexList) {
|
||||
// Reset the match index of the Regex to make sure we search from the
|
||||
// beginning of the file every time.
|
||||
regex.lastIndex = 0;
|
||||
const m = regex.exec(fileData);
|
||||
if (m) {
|
||||
return generateTypeDef(filePath, m[1], m[2]);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const definitions = glob.sync('./ckeditor5*/src/**/*.+(js|jsdoc)', globOptions).map(processFile);
|
||||
// Filter definitions that do not match any regex.
|
||||
const existingDefinitions = definitions.filter((e) => !!e);
|
||||
|
||||
// Write the file in the ckeditor module, use the JSDoc extension to make sure
|
||||
// the JSDoc extension is associated with the JavaScript file type and it
|
||||
// prevents core JavaScript lint rules to be run. Add it to the build folder to
|
||||
// prevent cspell checks on this file.
|
||||
fs.writeFile(`./modules/ckeditor5/js/build/ckeditor5.types.jsdoc`, existingDefinitions.join('\n'), () => {
|
||||
log(`CKEditor 5 types have been generated: ${existingDefinitions.length} declarations aliased, ${definitions.length - existingDefinitions.length} files ignored`);
|
||||
});
|
||||
|
||||
process.exitCode = 0;
|
||||
@@ -0,0 +1,31 @@
|
||||
const chalk = require('chalk');
|
||||
const log = require('./log');
|
||||
const babel = require('@babel/core');
|
||||
|
||||
module.exports = (filePath, callback) => {
|
||||
// Transform the file.
|
||||
// Check process.env.NODE_ENV to see if we should create sourcemaps.
|
||||
babel.transformFile(
|
||||
filePath,
|
||||
{
|
||||
sourceMaps: process.env.NODE_ENV === 'development' ? 'inline' : false,
|
||||
comments: false,
|
||||
plugins: [
|
||||
['add-header-comment', {
|
||||
'header': [
|
||||
`DO NOT EDIT THIS FILE.\nSee the following change record for more information,\nhttps://www.drupal.org/node/2815083\n@preserve`
|
||||
]
|
||||
}]
|
||||
]
|
||||
},
|
||||
(err, result) => {
|
||||
if (err) {
|
||||
log(chalk.red(err));
|
||||
process.exitCode = 1;
|
||||
}
|
||||
else {
|
||||
callback(result.code);
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
module.exports = function (results) {
|
||||
results = results || [];
|
||||
|
||||
const errorType = {
|
||||
warnings: {},
|
||||
errors: {},
|
||||
};
|
||||
|
||||
results.reduce((result, current) => {
|
||||
current.messages.forEach((msg) => {
|
||||
if (msg.severity === 1) {
|
||||
errorType.warnings[msg.ruleId] = errorType.warnings[msg.ruleId] + 1 || 1
|
||||
}
|
||||
if (msg.severity === 2) {
|
||||
errorType.errors[msg.ruleId] = errorType.errors[msg.ruleId] + 1 || 1
|
||||
}
|
||||
});
|
||||
return result;
|
||||
});
|
||||
|
||||
const reduceErrorCounts = (errorType) => Object.entries(errorType).sort((a, b) => b[1] - a[1])
|
||||
.reduce((result, current) => result.concat([`${current[0]}: ${current[1]}`]), []).join('\n');
|
||||
|
||||
const warnings = reduceErrorCounts(errorType.warnings);
|
||||
const errors = reduceErrorCounts(errorType.errors);
|
||||
|
||||
return `
|
||||
Errors:
|
||||
${'='.repeat(30)}
|
||||
${errors}
|
||||
${'\n'.repeat(4)}
|
||||
Warnings:
|
||||
${'='.repeat(30)}
|
||||
${warnings}`;
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
module.exports = (message) => {
|
||||
// Logging human-readable timestamp.
|
||||
console.log(`[${new Date().toTimeString().slice(0, 8)}] ${message}`);
|
||||
}
|
||||
@@ -0,0 +1,348 @@
|
||||
/**
|
||||
* @file
|
||||
* Copy files for JS vendor dependencies from node_modules to the assets/vendor
|
||||
* folder.
|
||||
*
|
||||
* This script handles all dependencies except CKEditor and Modernizr, which
|
||||
* require a custom build step.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const { copyFile, writeFile, readFile, chmod, mkdir } = require('fs').promises;
|
||||
const ckeditor5Files = require('./assets/ckeditor5Files');
|
||||
const jQueryUIProcess = require('./assets/process/jqueryui');
|
||||
const mapProcess = require('./assets/process/map');
|
||||
|
||||
const coreFolder = path.resolve(__dirname, '../../');
|
||||
const packageFolder = `${coreFolder}/node_modules`;
|
||||
const assetsFolder = `${coreFolder}/assets/vendor`;
|
||||
|
||||
(async () => {
|
||||
const librariesPath = `${coreFolder}/core.libraries.yml`;
|
||||
// Open the core.libraries.yml file to update version information
|
||||
// automatically.
|
||||
const libraries = (await readFile(librariesPath)).toString().split('\n\n');
|
||||
|
||||
function updateLibraryVersion(libraryName, { version }) {
|
||||
const libraryIndex = libraries.findIndex((lib) =>
|
||||
lib.startsWith(libraryName),
|
||||
);
|
||||
if (libraryIndex > 0) {
|
||||
const libraryDeclaration = libraries[libraryIndex];
|
||||
// Get the previous package version from the yaml file, versions can be
|
||||
// declared with a yaml anchor such as `version: &yaml_anchor "xxx"`
|
||||
const currentVersion = libraryDeclaration.match(/version:(?: [&\w_]+)? "(.*)"\n/)[1];
|
||||
// Replace the version value and the version in the license URL.
|
||||
libraries[libraryIndex] = libraryDeclaration.replace(
|
||||
new RegExp(currentVersion, 'g'),
|
||||
version,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Structure of the object defining a library to copy to the assets/ folder.
|
||||
*
|
||||
* @typedef DrupalLibraryAsset
|
||||
*
|
||||
* @prop {string} pack
|
||||
* The name of the npm package (used to get the name of the folder where
|
||||
* the files are situated inside of the node_modules folder). Note that we
|
||||
* use `pack` and not `package` because `package` is a future reserved word.
|
||||
* @prop {string} [folder]
|
||||
* The folder under `assets/vendor/` where the files will be copied. If
|
||||
* this
|
||||
* is not defined the value of `pack` is used.
|
||||
* @prop {string} [library]
|
||||
* The key under which the library is declared in core.libraries.yml.
|
||||
* @prop {Array} [files]
|
||||
* An array of files to be copied over.
|
||||
* - A string if the file has the same name and is at the same level in
|
||||
* the source and target folder.
|
||||
* - An object with a `from` and `to` property if the source and target
|
||||
* have a different name or if the folder nesting is different.
|
||||
* @prop {object} [process]
|
||||
* An object containing a file extension as a key and a callback as the
|
||||
* value. The callback will be called for each file matching the file
|
||||
* extension. It can be used to minify the file content before saving to
|
||||
* the target directory.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Declare the array that defines what needs to be copied over.
|
||||
*
|
||||
* @type {DrupalLibraryAsset[]}
|
||||
*/
|
||||
const ASSET_LIST = [
|
||||
{
|
||||
pack: 'backbone',
|
||||
library: 'internal.backbone',
|
||||
files: ['backbone.js', 'backbone-min.js', 'backbone-min.js.map'],
|
||||
},
|
||||
// Only used to update the version number of the deprecated library.
|
||||
{
|
||||
pack: 'backbone',
|
||||
},
|
||||
{
|
||||
pack: 'css.escape',
|
||||
folder: 'css-escape',
|
||||
library: 'css.escape',
|
||||
files: ['css.escape.js'],
|
||||
},
|
||||
{
|
||||
pack: 'es6-promise',
|
||||
files: [
|
||||
{ from: 'dist/es6-promise.auto.min.js', to: 'es6-promise.auto.min.js' },
|
||||
{
|
||||
from: 'dist/es6-promise.auto.min.map',
|
||||
to: 'es6-promise.auto.min.map',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
pack: 'farbtastic',
|
||||
library: 'jquery.farbtastic',
|
||||
files: [
|
||||
'marker.png',
|
||||
'mask.png',
|
||||
'wheel.png',
|
||||
'farbtastic.css',
|
||||
{ from: 'farbtastic.min.js', to: 'farbtastic.js' },
|
||||
],
|
||||
},
|
||||
{
|
||||
pack: 'jquery',
|
||||
files: [
|
||||
{ from: 'dist/jquery.js', to: 'jquery.js' },
|
||||
{ from: 'dist/jquery.min.js', to: 'jquery.min.js' },
|
||||
{ from: 'dist/jquery.min.map', to: 'jquery.min.map' },
|
||||
],
|
||||
},
|
||||
{
|
||||
pack: 'jquery-form',
|
||||
library: 'internal.jquery.form',
|
||||
files: [
|
||||
{ from: 'dist/jquery.form.min.js', to: 'jquery.form.min.js' },
|
||||
{ from: 'dist/jquery.form.min.js.map', to: 'jquery.form.min.js.map' },
|
||||
{ from: 'src/jquery.form.js', to: 'src/jquery.form.js' },
|
||||
],
|
||||
},
|
||||
// Only used to update the version number of the deprecated library.
|
||||
{
|
||||
pack: 'jquery-form',
|
||||
},
|
||||
{
|
||||
pack: 'joyride',
|
||||
folder: 'jquery-joyride',
|
||||
library: 'jquery.joyride',
|
||||
files: ['jquery.joyride-2.1.js'],
|
||||
},
|
||||
{
|
||||
pack: 'jquery-once',
|
||||
library: 'jquery.once',
|
||||
files: ['jquery.once.js', 'jquery.once.min.js', 'jquery.once.min.js.map'],
|
||||
},
|
||||
{
|
||||
pack: 'js-cookie',
|
||||
files: [{ from: 'dist/js.cookie.min.js', to: 'js.cookie.min.js' }],
|
||||
},
|
||||
{
|
||||
pack: 'normalize.css',
|
||||
folder: 'normalize-css',
|
||||
library: 'normalize',
|
||||
files: ['normalize.css'],
|
||||
},
|
||||
{
|
||||
pack: '@drupal/once',
|
||||
folder: 'once',
|
||||
files: [
|
||||
{ from: 'dist/once.js', to: 'once.js' },
|
||||
{ from: 'dist/once.min.js', to: 'once.min.js' },
|
||||
{ from: 'dist/once.min.js.map', to: 'once.min.js.map' },
|
||||
],
|
||||
},
|
||||
{
|
||||
pack: 'picturefill',
|
||||
files: [{ from: 'dist/picturefill.min.js', to: 'picturefill.min.js' }],
|
||||
},
|
||||
{
|
||||
pack: '@popperjs/core',
|
||||
folder: 'popperjs',
|
||||
files: [
|
||||
{ from: 'dist/umd/popper.min.js', to: 'popper.min.js' },
|
||||
{ from: 'dist/umd/popper.min.js.map', to: 'popper.min.js.map' },
|
||||
],
|
||||
},
|
||||
{
|
||||
pack: 'shepherd.js',
|
||||
library: 'shepherd',
|
||||
},
|
||||
{
|
||||
pack: 'shepherd.js',
|
||||
folder: 'shepherd',
|
||||
library: 'internal.shepherd',
|
||||
files: [
|
||||
{ from: 'dist/js/shepherd.min.js', to: 'shepherd.min.js' },
|
||||
{ from: 'dist/js/shepherd.min.js.map', to: 'shepherd.min.js.map' },
|
||||
],
|
||||
},
|
||||
{ pack: 'sortablejs', folder: 'sortable', files: ['Sortable.min.js'] },
|
||||
{
|
||||
pack: 'tabbable',
|
||||
files: [
|
||||
{ from: 'dist/index.umd.min.js', to: 'index.umd.min.js' },
|
||||
{ from: 'dist/index.umd.min.js.map', to: 'index.umd.min.js.map' },
|
||||
],
|
||||
},
|
||||
{
|
||||
pack: 'underscore',
|
||||
library: 'internal.underscore',
|
||||
files: ['underscore-min.js', 'underscore-min.js.map'],
|
||||
},
|
||||
// Only used to update the version number of the deprecated library.
|
||||
{
|
||||
pack: 'underscore',
|
||||
},
|
||||
{
|
||||
pack: 'loadjs',
|
||||
files: [{ from: 'dist/loadjs.min.js', to: 'loadjs.min.js' }],
|
||||
},
|
||||
{
|
||||
pack: 'jquery-ui',
|
||||
folder: 'jquery.ui',
|
||||
process: {
|
||||
// This will automatically minify the files and update the destination
|
||||
// filename before saving.
|
||||
'.js': jQueryUIProcess,
|
||||
},
|
||||
files: [
|
||||
'themes/base/autocomplete.css',
|
||||
'themes/base/button.css',
|
||||
'themes/base/checkboxradio.css',
|
||||
'themes/base/controlgroup.css',
|
||||
'themes/base/core.css',
|
||||
'themes/base/dialog.css',
|
||||
'themes/base/draggable.css',
|
||||
'themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png',
|
||||
'themes/base/images/ui-icons_444444_256x240.png',
|
||||
'themes/base/images/ui-icons_555555_256x240.png',
|
||||
'themes/base/images/ui-icons_777620_256x240.png',
|
||||
'themes/base/images/ui-icons_777777_256x240.png',
|
||||
'themes/base/images/ui-icons_cc0000_256x240.png',
|
||||
'themes/base/images/ui-icons_ffffff_256x240.png',
|
||||
'themes/base/menu.css',
|
||||
'themes/base/resizable.css',
|
||||
'themes/base/theme.css',
|
||||
'ui/data.js',
|
||||
'ui/disable-selection.js',
|
||||
'ui/focusable.js',
|
||||
'ui/form-reset-mixin.js',
|
||||
'ui/form.js',
|
||||
'ui/ie.js',
|
||||
'ui/jquery-patch.js',
|
||||
'ui/keycode.js',
|
||||
'ui/labels.js',
|
||||
'ui/plugin.js',
|
||||
'ui/position.js',
|
||||
'ui/safe-active-element.js',
|
||||
'ui/safe-blur.js',
|
||||
'ui/scroll-parent.js',
|
||||
'ui/tabbable.js',
|
||||
'ui/unique-id.js',
|
||||
'ui/version.js',
|
||||
'ui/widget.js',
|
||||
'ui/widgets/autocomplete.js',
|
||||
'ui/widgets/button.js',
|
||||
'ui/widgets/checkboxradio.js',
|
||||
'ui/widgets/controlgroup.js',
|
||||
'ui/widgets/dialog.js',
|
||||
'ui/widgets/draggable.js',
|
||||
'ui/widgets/menu.js',
|
||||
'ui/widgets/mouse.js',
|
||||
'ui/widgets/resizable.js',
|
||||
],
|
||||
},
|
||||
// CKEditor 5 builds the list of files dynamically based on what exists
|
||||
// in the filesystem.
|
||||
...ckeditor5Files(packageFolder),
|
||||
];
|
||||
|
||||
/**
|
||||
* Default callback for processing map files.
|
||||
*/
|
||||
const defaultProcessCallbacks = {
|
||||
'.map': mapProcess,
|
||||
};
|
||||
|
||||
/**
|
||||
* Return an object with a 'from' and 'to' member.
|
||||
*
|
||||
* @param {string|object} file
|
||||
*
|
||||
* @return {{from: string, to: string}}
|
||||
*/
|
||||
function normalizeFile(file) {
|
||||
let normalized = file;
|
||||
if (typeof file === 'string') {
|
||||
normalized = {
|
||||
from: file,
|
||||
to: file,
|
||||
};
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
for (const { pack, files = [], folder = false, library = false, process = {} } of ASSET_LIST) {
|
||||
const sourceFolder = pack;
|
||||
const libraryName = library || folder || pack;
|
||||
const destFolder = folder || pack;
|
||||
// Add a callback for map files by default.
|
||||
const processCallbacks = { ...defaultProcessCallbacks, ...process };
|
||||
|
||||
// Update the library version in core.libraries.yml with the version
|
||||
// from the npm package.
|
||||
try {
|
||||
const packageInfo = JSON.parse((await readFile(`${packageFolder}/${sourceFolder}/package.json`)).toString());
|
||||
updateLibraryVersion(libraryName, packageInfo);
|
||||
} catch (e) {
|
||||
// The package.json file doesn't exist, so nothing to do.
|
||||
}
|
||||
|
||||
for (const file of files.map(normalizeFile)) {
|
||||
const sourceFile = `${packageFolder}/${sourceFolder}/${file.from}`;
|
||||
const destFile = `${assetsFolder}/${destFolder}/${file.to}`;
|
||||
const extension = path.extname(file.from);
|
||||
|
||||
try {
|
||||
await mkdir(path.dirname(destFile), { recursive: true });
|
||||
} catch (e) {
|
||||
// Nothing to do if the folder already exists.
|
||||
}
|
||||
|
||||
// There is a callback that transforms the file contents, we are not
|
||||
// simply copying a file from A to B.
|
||||
if (processCallbacks[extension]) {
|
||||
const contents = (await readFile(sourceFile)).toString();
|
||||
const results = await processCallbacks[extension]({ file, contents });
|
||||
|
||||
console.log(`Process ${sourceFolder}/${file.from} and save ${results.length} files:\n ${results.map(({ filename = file.to }) => filename).join(', ')}`);
|
||||
for (const { filename = file.to, contents } of results) {
|
||||
// The filename key can be used to change the name of the saved file.
|
||||
await writeFile(`${assetsFolder}/${destFolder}/${filename}`, contents);
|
||||
}
|
||||
} else {
|
||||
// There is no callback simply copy the file.
|
||||
console.log(`Copy ${sourceFolder}/${file.from} to ${destFolder}/${file.to}`);
|
||||
await copyFile(sourceFile, destFile);
|
||||
}
|
||||
|
||||
// These 2 files come from a zip file that hasn't been updated in years
|
||||
// hardcode the permission fix to pass the commit checks.
|
||||
if (['jquery.joyride-2.1.js', 'marker.png'].includes(file.to)) {
|
||||
await chmod(destFile, 0o644);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await writeFile(librariesPath, libraries.join('\n\n'));
|
||||
})();
|
||||
@@ -1,233 +0,0 @@
|
||||
console.log('salut');
|
||||
// menu burger open
|
||||
|
||||
var burger = document.getElementById("block-burger");
|
||||
var burgertitle = document.getElementById("block-burger-menu");
|
||||
|
||||
|
||||
burgertitle.addEventListener("click", toggleMenu);
|
||||
|
||||
function toggleMenu(event) {
|
||||
// console.log(event);
|
||||
burger.classList.toggle('opened');
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
// faq reponse open
|
||||
|
||||
var answers = document.getElementsByClassName("field--name-field-reponse");
|
||||
var fichiers = document.getElementsByClassName("field--name-field-fichiers");
|
||||
var questions = document.getElementsByClassName("field--name-field-question");
|
||||
|
||||
for (let i = 0; i < questions.length; i++) {
|
||||
const question = questions[i]
|
||||
question.addEventListener("click", toggleFaq);
|
||||
}
|
||||
function toggleFaq(event) {
|
||||
// console.log(event, this);
|
||||
// fermé tout
|
||||
for (let i = 0; i < answers.length; i++) {
|
||||
answers[i].classList.remove('opened');
|
||||
}
|
||||
// la réponse correspndante a la question clické
|
||||
// | this c'est l'élément sur le quel on a clické
|
||||
// | |le parent |la réponse dans le parent
|
||||
let answer = this.parentNode.querySelector('.field--name-field-reponse');
|
||||
// console.log(answer);
|
||||
answer.classList.add('opened');
|
||||
|
||||
}
|
||||
///// répète fonction pour les fichiers, les liens et ressources
|
||||
//// il faudrait créer un tableau d'objet ?
|
||||
|
||||
var fichiers = document.getElementsByClassName("field--name-field-fichiers");
|
||||
var questions = document.getElementsByClassName("field--name-field-question");
|
||||
|
||||
for (let i = 0; i < questions.length; i++) {
|
||||
const question = questions[i]
|
||||
question.addEventListener("click", toggleFaqFichiers);
|
||||
}
|
||||
function toggleFaqFichiers(event) {
|
||||
// console.log(event, this);
|
||||
for (let i = 0; i < fichiers.length; i++) {
|
||||
fichiers[i].classList.remove('opened');
|
||||
}
|
||||
let fichier = this.parentNode.querySelector('.field--name-field-fichiers');
|
||||
|
||||
fichier.classList.add('opened');
|
||||
}
|
||||
|
||||
|
||||
////////////////////////
|
||||
var liens = document.getElementsByClassName("field--name-field-liens");
|
||||
var questions = document.getElementsByClassName("field--name-field-question");
|
||||
|
||||
for (let i = 0; i < questions.length; i++) {
|
||||
const question = questions[i]
|
||||
question.addEventListener("click", toggleFaqLiens);
|
||||
}
|
||||
function toggleFaqLiens(event) {
|
||||
// console.log(event, this);
|
||||
for (let i = 0; i < liens.length; i++) {
|
||||
liens[i].classList.remove('opened');
|
||||
}
|
||||
let lien = this.parentNode.querySelector('.field--name-field-liens');
|
||||
|
||||
lien.classList.add('opened');
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
var ressources = document.getElementsByClassName("field--name-field-ress");
|
||||
var questions = document.getElementsByClassName("field--name-field-question");
|
||||
|
||||
for (let i = 0; i < questions.length; i++) {
|
||||
const question = questions[i]
|
||||
question.addEventListener("click", toggleFaqRessources);
|
||||
}
|
||||
function toggleFaqRessources(event) {
|
||||
// console.log(event, this);
|
||||
for (let i = 0; i < resources.length; i++) {
|
||||
ressources[i].classList.remove('opened');
|
||||
}
|
||||
let ressource = this.parentNode.querySelector('.field--name-field-ress');
|
||||
|
||||
ressource.classList.add('opened');
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
////////////////////////////////
|
||||
// fleche qui tourne faq
|
||||
|
||||
// var questions = document.getElementsByClassName("field--name-field-question");
|
||||
// var paragraph = document.querySelector('.field--name-field-question p::after');
|
||||
// console.log(paragraph)
|
||||
// var styles = window.getComputedStyle(element,':after')
|
||||
// console.log(styles)
|
||||
// var content = styles['content']
|
||||
// console.log(content)
|
||||
|
||||
|
||||
// for (let i = 0; i < questions.length; i++) {
|
||||
// const question = questions[i]
|
||||
// question.addEventListener("click", rotateFleche);
|
||||
// }
|
||||
// function rotateFleche(event) {
|
||||
// console.log(event, this);
|
||||
// // for (let i = 0; i < answers.length; i++) {
|
||||
// // answers[i].classList.remove('opened');
|
||||
// // }
|
||||
// }
|
||||
|
||||
//////////////////////////////////////////
|
||||
// block collection reste bleu quand actif
|
||||
|
||||
jQuery(function($) {
|
||||
var path = window.location.href; // because the 'href' property of the DOM element is the absolute path
|
||||
console.log(path);
|
||||
$(".view-id-collections .view-content .views-row a").each(function() {
|
||||
if (this.href === path) {
|
||||
$(this).parent().closest('.views-row').addClass('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// /////////////////
|
||||
//// ancre dans texte au click parragraphe correspondant arrive en dessous du header
|
||||
|
||||
|
||||
(function($, window) {
|
||||
var adjustAnchor = function() {
|
||||
var $anchor = $('.block-entity-fieldnodefield-textes'),
|
||||
fixedElementHeight = 350;
|
||||
if ($anchor.length > 0) {
|
||||
$('html, body').stop().animate({scrollTop: $anchor.offset().top - fixedElementHeight}, 250);
|
||||
}
|
||||
};
|
||||
|
||||
$(window).on('hashchange load', function() {
|
||||
adjustAnchor();
|
||||
});
|
||||
|
||||
})(jQuery, window);
|
||||
|
||||
|
||||
// ///////////////////////////////
|
||||
// (function(document, history, location) {
|
||||
// var HISTORY_SUPPORT = !!(history && history.pushState);
|
||||
|
||||
// var anchorScrolls = {
|
||||
// ANCHOR_REGEX: /^#[^ ]+$/,
|
||||
// OFFSET_HEIGHT_PX: 50,
|
||||
|
||||
// /**
|
||||
// * Establish events, and fix initial scroll position if a hash is provided.
|
||||
// */
|
||||
// init: function() {
|
||||
// this.scrollToCurrent();
|
||||
// $(window).on('hashchange', $.proxy(this, 'scrollToCurrent'));
|
||||
// $('body').on('click', 'a', $.proxy(this, 'delegateAnchors'));
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * Return the offset amount to deduct from the normal scroll position.
|
||||
// * Modify as appropriate to allow for dynamic calculations
|
||||
// */
|
||||
// getFixedOffset: function() {
|
||||
// return this.OFFSET_HEIGHT_PX;
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * If the provided href is an anchor which resolves to an element on the
|
||||
// * page, scroll to it.
|
||||
// * @param {String} href
|
||||
// * @return {Boolean} - Was the href an anchor.
|
||||
// */
|
||||
// scrollIfAnchor: function(href, pushToHistory) {
|
||||
// var match, anchorOffset;
|
||||
|
||||
// if(!this.ANCHOR_REGEX.test(href)) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// match = document.getElementById(href.slice(1));
|
||||
|
||||
// if(match) {
|
||||
// anchorOffset = $(match).offset().top - this.getFixedOffset();
|
||||
// $('html, body').animate({ scrollTop: anchorOffset});
|
||||
|
||||
// // Add the state to history as-per normal anchor links
|
||||
// if(HISTORY_SUPPORT && pushToHistory) {
|
||||
// history.pushState({}, document.title, location.pathname + href);
|
||||
// }
|
||||
// }
|
||||
|
||||
// return !!match;
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * Attempt to scroll to the current location's hash.
|
||||
// */
|
||||
// scrollToCurrent: function(e) {
|
||||
// if(this.scrollIfAnchor(window.location.hash) && e) {
|
||||
// e.preventDefault();
|
||||
// }
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * If the click event's target was an anchor, fix the scroll position.
|
||||
// */
|
||||
// delegateAnchors: function(e) {
|
||||
// var elem = e.target;
|
||||
|
||||
// if(this.scrollIfAnchor(elem.getAttribute('href'), true)) {
|
||||
// e.preventDefault();
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
// $(document).ready($.proxy(anchorScrolls, 'init'));
|
||||
// })(window.document, window.history, window.location);
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Drupal hash script - to generate a hash from a plaintext password
|
||||
*
|
||||
* @param password1 [password2 [password3 ...]]
|
||||
* Plain-text passwords in quotes (or with spaces backslash escaped).
|
||||
*
|
||||
* @todo Port to a console command. https://www.drupal.org/node/2289409
|
||||
*/
|
||||
|
||||
use Drupal\Core\DrupalKernel;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
return;
|
||||
}
|
||||
|
||||
$script = basename(array_shift($_SERVER['argv']));
|
||||
|
||||
if (in_array('--help', $_SERVER['argv']) || empty($_SERVER['argv'])) {
|
||||
echo <<<EOF
|
||||
|
||||
Generate Drupal password hashes from the shell.
|
||||
|
||||
Usage: {$script} [OPTIONS] "<plaintext password>"
|
||||
Example: {$script} "my-new-password"
|
||||
|
||||
All arguments are long options.
|
||||
|
||||
--help Print this page.
|
||||
|
||||
"<password1>" ["<password2>" ["<password3>" ...]]
|
||||
|
||||
One or more plaintext passwords enclosed by double quotes. The
|
||||
output hash may be manually entered into the
|
||||
{users_field_data}.pass field to change a password via SQL to a
|
||||
known value.
|
||||
|
||||
|
||||
EOF;
|
||||
exit;
|
||||
}
|
||||
|
||||
// Password list to be processed.
|
||||
$passwords = $_SERVER['argv'];
|
||||
|
||||
$autoloader = require __DIR__ . '/../../autoload.php';
|
||||
|
||||
$request = Request::createFromGlobals();
|
||||
$kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod', FALSE);
|
||||
$kernel->boot();
|
||||
|
||||
$password_hasher = $kernel->getContainer()->get('password');
|
||||
|
||||
foreach ($passwords as $password) {
|
||||
print("\npassword: $password \t\thash: " . $password_hasher->hash($password) . "\n");
|
||||
}
|
||||
print("\n");
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Command line token calculator for rebuild.php.
|
||||
*/
|
||||
|
||||
use Drupal\Component\Utility\Crypt;
|
||||
use Drupal\Core\DrupalKernel;
|
||||
use Drupal\Core\Site\Settings;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
return;
|
||||
}
|
||||
|
||||
$autoloader = require __DIR__ . '/../../autoload.php';
|
||||
|
||||
$request = Request::createFromGlobals();
|
||||
Settings::initialize(DRUPAL_ROOT, DrupalKernel::findSitePath($request), $autoloader);
|
||||
|
||||
$timestamp = time();
|
||||
$token = Crypt::hmacBase64($timestamp, Settings::get('hash_salt'));
|
||||
|
||||
print "timestamp=$timestamp&token=$token\n";
|
||||
+1517
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* A command line application to install Drupal for tests.
|
||||
*/
|
||||
|
||||
use Drupal\TestSite\TestSiteApplication;
|
||||
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Use the PHPUnit bootstrap to prime an autoloader that works for test classes.
|
||||
// Note we have to disable the SYMFONY_DEPRECATIONS_HELPER to ensure deprecation
|
||||
// notices are not triggered.
|
||||
putenv('SYMFONY_DEPRECATIONS_HELPER=disabled');
|
||||
require_once __DIR__ . '/../tests/bootstrap.php';
|
||||
|
||||
// The application version is 0.1.0 to indicate that it is for internal use only
|
||||
// and not currently API.
|
||||
$app = new TestSiteApplication('test-site', '0.1.0');
|
||||
$app->run();
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
#!/bin/php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Updates CLDR codes in CountryManager.php to latest data.
|
||||
*
|
||||
* We rely on the CLDR data set, because it is easily accessible, scriptable,
|
||||
* and in the right human-readable format.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Locale\CountryManager;
|
||||
|
||||
// Determine DRUPAL_ROOT.
|
||||
$dir = dirname(__FILE__);
|
||||
while (!defined('DRUPAL_ROOT')) {
|
||||
if (is_dir($dir . '/core')) {
|
||||
define('DRUPAL_ROOT', $dir);
|
||||
}
|
||||
$dir = dirname($dir);
|
||||
}
|
||||
|
||||
// Determine source data file URI to process.
|
||||
$uri = DRUPAL_ROOT . '/territories.json';
|
||||
|
||||
if (!file_exists($uri)) {
|
||||
$usage = <<< USAGE
|
||||
- Choose the latest release data from http://cldr.unicode.org/index/downloads
|
||||
and download the json.zip file.
|
||||
- Unzip the json.zip file and place the main/en/territories.json in the
|
||||
Drupal root directory.
|
||||
- Run this script.
|
||||
USAGE;
|
||||
exit('CLDR data file not found. (' . $uri . ")\n\n" . $usage . "\n");
|
||||
}
|
||||
|
||||
// Fake the t() function used in CountryManager.php instead of attempting a full
|
||||
// Drupal bootstrap of core/includes/bootstrap.inc (where t() is declared).
|
||||
if (!function_exists('t')) {
|
||||
|
||||
function t($string) {
|
||||
return $string;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Read in existing codes.
|
||||
// @todo Allow to remove previously existing country codes.
|
||||
// @see https://www.drupal.org/node/1436754
|
||||
require_once DRUPAL_ROOT . '/core/lib/Drupal/Core/Locale/CountryManagerInterface.php';
|
||||
require_once DRUPAL_ROOT . '/core/lib/Drupal/Core/Locale/CountryManager.php';
|
||||
$existing_countries = CountryManager::getStandardList();
|
||||
$countries = $existing_countries;
|
||||
|
||||
// Parse the source data into an array.
|
||||
$data = json_decode(file_get_contents($uri));
|
||||
|
||||
foreach ($data->main->en->localeDisplayNames->territories as $code => $name) {
|
||||
// Use any alternate codes the Drupal community wishes to.
|
||||
$alt_codes = [
|
||||
// 'CI-alt-variant', // Use CI-alt-variant instead of the CI entry.
|
||||
];
|
||||
if (in_array($code, $alt_codes)) {
|
||||
// Just use the first 2 character part of the alt code.
|
||||
$code = strtok($code, '-');
|
||||
}
|
||||
|
||||
// Skip any codes we wish to exclude from our country list.
|
||||
$exclude_codes = [
|
||||
// The European Union is not a country.
|
||||
'EU',
|
||||
// The Eurozone is not a country.
|
||||
'EZ',
|
||||
// The United Nations is not a country.
|
||||
'UN',
|
||||
// "Pseudo-Accents" is not a country.
|
||||
'XA',
|
||||
// "Pseudo-Bidi" is not a country.
|
||||
'XB',
|
||||
// Don't allow "Unknown Region".
|
||||
'ZZ',
|
||||
];
|
||||
if (in_array($code, $exclude_codes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore every territory that doesn't have a 2 character code.
|
||||
if (strlen($code) !== 2) {
|
||||
continue;
|
||||
}
|
||||
$countries[(string) $code] = $name;
|
||||
}
|
||||
if (empty($countries)) {
|
||||
echo 'ERROR: Did not find expected country names.' . PHP_EOL;
|
||||
exit;
|
||||
}
|
||||
// Sort by country code (to minimize diffs).
|
||||
ksort($countries);
|
||||
|
||||
// Produce PHP code.
|
||||
$out = '';
|
||||
foreach ($countries as $code => $name) {
|
||||
// For .po translation file's sake, use double-quotes instead of escaped
|
||||
// single-quotes.
|
||||
$name = (strpos($name, '\'') !== FALSE ? '"' . $name . '"' : "'" . $name . "'");
|
||||
$out .= ' ' . var_export($code, TRUE) . ' => t(' . $name . '),' . "\n";
|
||||
}
|
||||
|
||||
// Replace the actual PHP code in standard.inc.
|
||||
$file = DRUPAL_ROOT . '/core/lib/Drupal/Core/Locale/CountryManager.php';
|
||||
$content = file_get_contents($file);
|
||||
$content = preg_replace('/(\$countries = \[\n)(.+?)(^\s+\];)/ms', '$1' . $out . '$3', $content, -1, $count);
|
||||
file_put_contents($file, $content);
|
||||
Reference in New Issue
Block a user