Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/2.x' into manual_merge
Browse files Browse the repository at this point in the history
  • Loading branch information
kunicmarko20 committed May 19, 2019
2 parents 813789f + 7987b35 commit 7858870
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 24 deletions.
2 changes: 1 addition & 1 deletion docs/installation.rst
Expand Up @@ -141,7 +141,7 @@ Configure Twig

This step is not required if you installed the bundle using Symfony Flex and the recipe was installed.

Finally, add some configuration under the `twig.form_themes` config key:
Finally, add some configuration under the ``twig.form_themes`` config key:

.. code-block:: yaml
Expand Down
11 changes: 11 additions & 0 deletions docs/usage/ckeditor.rst
Expand Up @@ -61,6 +61,17 @@ You can choose which CKEditor release (full, standard or basic) to download:
$ php bin/console ckeditor:install --release=basic
CKEditor Custom Build
~~~~~~~~~~~~~~~~~~~~~

It's also possible to use custom build generated using CKEditor online builder:
https://ckeditor.com/cke4/builder. Download ZIP archive from CKEditor website
and use your custom build ID from `build-config.js` file:

.. code-block:: bash
$ php bin/console ckeditor:install --release=custom --custom-build-id=574a82a0d3e9226d94b0e91d10eaa372
CKEditor Version
~~~~~~~~~~~~~~~~

Expand Down
2 changes: 1 addition & 1 deletion docs/usage/toolbar.rst
Expand Up @@ -104,4 +104,4 @@ you want to just override one part of a configuration, just override it:
.. note::

If you want the full list of built-in items, check the
`FOS\\CKEditorBundle\\Model\\ToolbarManager` class.
`FOS\\CKEditorBundle\\Config\\CKEditorConfiguration` class.
16 changes: 15 additions & 1 deletion src/Command/CKEditorInstallerCommand.php
Expand Up @@ -50,7 +50,13 @@ protected function configure(): void
'release',
null,
InputOption::VALUE_OPTIONAL,
'CKEditor release (basic, standard or full)'
'CKEditor release (basic, standard, full or custom)'
)
->addOption(
'custom-build-id',
null,
InputOption::VALUE_OPTIONAL,
'CKEditor custom build ID'
)
->addOption('tag', null, InputOption::VALUE_OPTIONAL, 'CKEditor tag (x.y.z or latest)')
->addOption(
Expand Down Expand Up @@ -89,6 +95,10 @@ protected function configure(): void
<info>php %command.full_name% --tag=4.7.0</info>
You can install custom build generated on https://ckeditor.com/cke4/builder:
<info>php %command.full_name% --release=custom --custom-build-id=574a82a0d3e9226d94b0e91d10eaa372</info>
If there is a previous CKEditor installation detected,
you can control how it should be handled in non-interactive mode:
Expand Down Expand Up @@ -128,6 +138,10 @@ private function createOptions(InputInterface $input, OutputInterface $output):
$options['release'] = $input->getOption('release');
}

if ($input->hasOption('custom-build-id')) {
$options['custom_build_id'] = $input->getOption('custom-build-id');
}

if ($input->hasOption('tag')) {
$options['version'] = $input->getOption('tag');
}
Expand Down
57 changes: 42 additions & 15 deletions src/Installer/CKEditorInstaller.php
Expand Up @@ -27,6 +27,8 @@ final class CKEditorInstaller

const RELEASE_STANDARD = 'standard';

const RELEASE_CUSTOM = 'custom';

const VERSION_LATEST = 'latest';

const CLEAR_DROP = 'drop';
Expand Down Expand Up @@ -68,6 +70,11 @@ final class CKEditorInstaller
*/
private static $archive = 'https://github.com/ckeditor/ckeditor-releases/archive/%s/%s.zip';

/**
* @var string
*/
private static $customBuildArchive = 'https://ckeditor.com/cke4/builder/download/%s';

/**
* @var OptionsResolver
*/
Expand All @@ -82,14 +89,16 @@ public function __construct(array $options = [])
'notifier' => null,
'path' => dirname(__DIR__).'/Resources/public',
'release' => self::RELEASE_FULL,
'custom_build_id' => null,
'version' => self::VERSION_LATEST,
], $options))
->setAllowedTypes('excludes', 'array')
->setAllowedTypes('notifier', ['null', 'callable'])
->setAllowedTypes('path', 'string')
->setAllowedTypes('custom_build_id', ['null', 'string'])
->setAllowedTypes('version', 'string')
->setAllowedValues('clear', [self::CLEAR_DROP, self::CLEAR_KEEP, self::CLEAR_SKIP, null])
->setAllowedValues('release', [self::RELEASE_BASIC, self::RELEASE_FULL, self::RELEASE_STANDARD])
->setAllowedValues('release', [self::RELEASE_BASIC, self::RELEASE_FULL, self::RELEASE_STANDARD, self::RELEASE_CUSTOM])
->setNormalizer('path', function (Options $options, $path) {
return rtrim($path, '/');
});
Expand Down Expand Up @@ -157,7 +166,7 @@ private function clear(array $options): string

private function download(array $options): string
{
$url = sprintf(self::$archive, $options['release'], $options['version']);
$url = $this->getDownloadUrl($options);
$this->notify($options['notifier'], self::NOTIFY_DOWNLOAD, $url);

$zip = @file_get_contents($url, false, $this->createStreamContext($options['notifier']));
Expand All @@ -177,6 +186,23 @@ private function download(array $options): string
return $path;
}

private function getDownloadUrl(array $options): string
{
if (self::RELEASE_CUSTOM !== $options['release']) {
return sprintf(self::$archive, $options['release'], $options['version']);
}

if (null === $options['custom_build_id']) {
throw $this->createException('Unable to download CKEditor ZIP archive. Custom build ID is not specified.');
}

if (self::VERSION_LATEST !== $options['version']) {
throw $this->createException('Unable to download CKEditor ZIP archive. Specifying version for custom build is not supported.');
}

return sprintf(self::$customBuildArchive, $options['custom_build_id']);
}

/**
* @return resource
*/
Expand Down Expand Up @@ -236,15 +262,19 @@ private function extract(string $path, array $options): void

$this->notify($options['notifier'], self::NOTIFY_EXTRACT_SIZE, $zip->numFiles);

$offset = 20 + strlen($options['release']) + strlen($options['version']);
if (self::RELEASE_CUSTOM === $options['release']) {
$offset = 9;
} else {
$offset = 20 + strlen($options['release']) + strlen($options['version']);
}

for ($i = 0; $i < $zip->numFiles; ++$i) {
$this->extractFile(
$file = $zip->getNameIndex($i),
substr($file, $offset),
$path,
$options
);
$filename = $zip->getNameIndex($i);
$isDirectory = ('/' === substr($filename, -1, 1));

if (!$isDirectory) {
$this->extractFile($filename, substr($filename, $offset), $path, $options);
}
}

$zip->close();
Expand All @@ -270,12 +300,9 @@ private function extractFile(string $file, string $rewrite, string $origin, arra
}
}

if ('/' === substr($from, -1)) {
if (!is_dir($to) && !@mkdir($to)) {
throw $this->createException(sprintf('Unable to create the directory "%s".', $to));
}

return;
$targetDirectory = dirname($to);
if (!is_dir($targetDirectory) && !@mkdir($targetDirectory, 0777, true)) {
throw $this->createException(sprintf('Unable to create the directory "%s".', $targetDirectory));
}

if (!@copy($from, $to)) {
Expand Down
40 changes: 34 additions & 6 deletions tests/Installer/CKEditorInstallerTest.php
Expand Up @@ -74,6 +74,29 @@ public function testInstallWithRelease(): void
$this->assertInstall($options);
}

public function testInstallWithCustomBuild(): void
{
$this->installer->install($options = ['release' => CKEditorInstaller::RELEASE_CUSTOM, 'custom_build_id' => '574a82a0d3e9226d94b0e91d10eaa372']);

$this->assertInstall($options);
}

public function testInstallWithCustomBuildWithInvalidVersion(): void
{
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessageRegExp('/Specifying version for custom build is not supported/');

$this->installer->install($options = ['release' => CKEditorInstaller::RELEASE_CUSTOM, 'custom_build_id' => '574a82a0d3e9226d94b0e91d10eaa372', 'version' => '4.11.4']);
}

public function testInstallWithCustomBuildWithMissingId(): void
{
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessageRegExp('/Custom build ID is not specified/');

$this->installer->install($options = ['release' => CKEditorInstaller::RELEASE_CUSTOM]);
}

public function testInstallWithVersion(): void
{
$this->installer->install($options = ['version' => '4.6.0']);
Expand Down Expand Up @@ -209,12 +232,17 @@ private function assertInstall(array $options = []): void
{
$this->assertFileExists($this->path.'/ckeditor.js');

if (isset($options['release'])) {
$this->assertRelease($options['release']);
}

if (isset($options['version'])) {
$this->assertVersion($options['version']);
if (CKEditorInstaller::RELEASE_CUSTOM === ($options['release'] ?? '')) {
$this->assertFileExists($this->path.'/build-config.js');
$this->assertContains($options['custom_build_id'], file_get_contents($this->path.'/build-config.js'));
} else {
if (isset($options['release'])) {
$this->assertRelease($options['release']);
}

if (isset($options['version'])) {
$this->assertVersion($options['version']);
}
}

if (!isset($options['excludes'])) {
Expand Down

0 comments on commit 7858870

Please sign in to comment.