Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,18 @@
## Unreleased

- Added the “Field Limit” field setting, which can be set to a character limit or word limit. ([#384](https://github.com/craftcms/ckeditor/pull/384))
- Added the “GraphQL Mode” field setting. ([#403](https://github.com/craftcms/ckeditor/pull/403))
- Improved the styling of CKEditor fields. ([craftcms/cms#17164](https://github.com/craftcms/cms/discussions/17164))
- The “Anchors” CKEditor plugin has been replaced with CKEditor’s new built-in [Bookmarks](https://ckeditor.com/docs/ckeditor5/latest/features/bookmarks.html) plugin. ([#397](https://github.com/craftcms/ckeditor/pull/397))
- Updated to CKEditor 5 45.0.0. ([#397](https://github.com/craftcms/ckeditor/pull/397))
- Added `craft\ckeditor\Field::$characterLimit`.
- Added `craft\ckeditor\Field::$fullGraphqlData`.
- Added `craft\ckeditor\data\FieldData::getEntries()`.
- Added `craft\ckeditor\data\Markup::getMarkdown()`.
- Added `craft\ckeditor\data\Markup::getPlainText()`.
- Added `craft\ckeditor\gql\CkeditorData`.
- Added `craft\ckeditor\gql\CkeditorMarkup`.
- Added `craft\ckeditor\gql\Generator`.
- Fixed a bug where it wasn’t easily possible to drag a toolbar button to the last position in the toolbar, if that meant wrapping the buttons to a new row.

## 4.7.0 - 2025-04-21
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"require": {
"php": "^8.2",
"craftcms/cms": "^5.6.0",
"craftcms/html-field": "^3.1.0",
"craftcms/html-field": "^3.4.0",
"nystudio107/craft-code-editor": ">=1.0.8 <=1.0.13 || ^1.0.16"
},
"require-dev": {
Expand Down
16 changes: 9 additions & 7 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions src/Field.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use craft\ckeditor\data\Markup;
use craft\ckeditor\events\DefineLinkOptionsEvent;
use craft\ckeditor\events\ModifyConfigEvent;
use craft\ckeditor\gql\Generator;
use craft\ckeditor\web\assets\BaseCkeditorPackageAsset;
use craft\ckeditor\web\assets\ckeditor\CkeditorAsset;
use craft\db\FixedOrderExpression;
Expand Down Expand Up @@ -56,6 +57,7 @@
use craft\models\Volume;
use craft\services\ElementSources;
use craft\web\View;
use GraphQL\Type\Definition\Type;
use HTMLPurifier_Config;
use HTMLPurifier_Exception;
use HTMLPurifier_HTMLDefinition;
Expand Down Expand Up @@ -439,6 +441,12 @@ private static function adjustFieldValues(
*/
public ?string $createButtonLabel = null;

/**
* @var bool Whether GraphQL values should be returned as objects with `content`, `chunks`, etc., sub-fields.
* @since 4.8.0
*/
public bool $fullGraphqlData = true;

/**
* @var EntryType[] The field’s available entry types
* @see getEntryTypes()
Expand Down Expand Up @@ -478,6 +486,15 @@ public function __construct($config = [])
$config['entryTypes'] = [];
}

if (isset($config['graphqlMode'])) {
$config['fullGraphqlData'] = ArrayHelper::remove($config, 'graphqlMode') === 'full';
}

// Default fullGraphqlData to false for existing fields
if (isset($config['id']) && !isset($config['fullGraphqlData'])) {
$config['fullGraphqlData'] = false;
}

parent::__construct($config);
}

Expand Down Expand Up @@ -559,6 +576,18 @@ function(ElementInterface $element) {
return $rules;
}

/**
* @inheritdoc
*/
public function getContentGqlType(): Type|array
{
if (!$this->fullGraphqlData) {
return parent::getContentGqlType();
}

return Generator::generateType($this);
}

/**
* @inheritdoc
*/
Expand Down
51 changes: 37 additions & 14 deletions src/data/FieldData.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use ArrayIterator;
use Countable;
use Craft;
use craft\elements\db\EntryQuery;
use craft\elements\Entry as EntryElement;
use craft\helpers\Html;
use craft\htmlfield\HtmlFieldData;
Expand Down Expand Up @@ -50,6 +51,15 @@ public function __toString()
return parent::__toString();
}

public function __get(string $name)
{
return match ($name) {
'chunks' => $this->getChunks(),
'entries' => $this->getEntries(),
default => parent::__get($name),
};
}

public function getIterator(): Traversable
{
return new ArrayIterator($this->getChunks()->all());
Expand Down Expand Up @@ -135,38 +145,51 @@ private function addContentChunk(string $content): void
}
}

public function loadEntries(): void
/**
* Returns an entry query prepped to fetch the nested entries.
*
* @return EntryQuery
* @since 4.8.0
*/
public function getEntries(): EntryQuery
{
if ($this->loadedEntries) {
return;
}

$this->parse();
$entryChunks = $this->chunks->filter(fn(BaseChunk $chunk) => $chunk instanceof Entry);
$entryIds = $entryChunks->map(fn(Entry $chunk) => $chunk->entryId)->all();
$query = EntryElement::find();

if (!empty($entryIds)) {
$query = EntryElement::find()
$query
->id($entryIds)
->siteId($this->siteId)
->status(null)
->drafts(null)
->revisions(null)
->trashed(null)
->indexBy('id');
->trashed(null);

if (Craft::$app->getRequest()->getIsPreview()) {
$query->withProvisionalDrafts();
}

$entries = $query->all();
} else {
$entries = [];
$query->id(false);
}

$entryChunks->each(function(Entry $chunk) use ($entries) {
$chunk->setEntry($entries[$chunk->entryId] ?? null);
});
return $query;
}

public function loadEntries(): void
{
if ($this->loadedEntries) {
return;
}

$entryChunks = $this->chunks->filter(fn(BaseChunk $chunk) => $chunk instanceof Entry);
if ($entryChunks->isNotEmpty()) {
$entries = $this->getEntries()->indexBy('id')->all();
$entryChunks->each(function(Entry $chunk) use ($entries) {
$chunk->setEntry($entries[$chunk->entryId] ?? null);
});
}

$this->loadedEntries = true;
}
Expand Down
36 changes: 36 additions & 0 deletions src/data/Markup.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
namespace craft\ckeditor\data;

use Craft;
use craft\htmlfield\HtmlFieldData;
use League\HTMLToMarkdown\HtmlConverter;
use yii\base\UnknownPropertyException;

/**
* Represents HTML markup within a CKEditor field’s content.
Expand All @@ -26,6 +29,15 @@ public function __construct(
) {
}

public function __get($name)
{
return match ($name) {
'type' => $this->getType(),
'html' => $this->getHtml(),
default => throw new UnknownPropertyException(sprintf('Getting unknown property: %s::%s', static::class, $name)),
};
}

public function getType(): string
{
return 'markup';
Expand All @@ -38,4 +50,28 @@ public function getHtml(): string
}
return $this->html;
}

/**
* Returns the markup as Markdown.
*
* @param array $config HtmlConverter configuration
* @return string
* @since 4.8.0
*/
public function getMarkdown(array $config = []): string
{
return HtmlFieldData::toMarkdown($this->getHtml(), $config);
}

/**
* Returns the markup as Markdown.
*
* @return string
* @since 4.8.0
*/
public function getPlainText(): string
{
// link href's and images get removed, so no need to run the HTML through parseRefs()
return HtmlFieldData::toPlainText($this->rawHtml);
}
}
36 changes: 36 additions & 0 deletions src/gql/CkeditorData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php
/**
* @link https://craftcms.com/
* @copyright Copyright (c) Pixel & Tonic, Inc.
* @license GPL-3.0-or-later
*/

namespace craft\ckeditor\gql;

use craft\ckeditor\data\FieldData;
use craft\gql\base\ObjectType;
use craft\gql\resolvers\elements\Entry as EntryResolver;
use GraphQL\Type\Definition\ResolveInfo;

/**
* GraphQL data type
*
* @author Pixel & Tonic, Inc. <support@pixelandtonic.com>
* @since 4.8.0
*/
class CkeditorData extends ObjectType
{
protected function resolve(mixed $source, array $arguments, mixed $context, ResolveInfo $resolveInfo): mixed
{
/** @var FieldData $source */
$fieldName = $resolveInfo->fieldName;
/** @phpstan-ignore-next-line */
return match ($fieldName) {
'html' => $source->getParsedContent(),
'rawHtml' => $source->getRawContent(),
'markdown' => $source->getMarkdown($arguments),
'plainText' => $source->getPlainText(),
'entries' => EntryResolver::resolve($source, $arguments, $context, $resolveInfo),
};
}
}
33 changes: 33 additions & 0 deletions src/gql/CkeditorMarkup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php
/**
* @link https://craftcms.com/
* @copyright Copyright (c) Pixel & Tonic, Inc.
* @license GPL-3.0-or-later
*/

namespace craft\ckeditor\gql;

use craft\ckeditor\data\Markup;
use craft\gql\base\ObjectType;
use GraphQL\Type\Definition\ResolveInfo;

/**
* Markup GraphQL data type
*
* @author Pixel & Tonic, Inc. <support@pixelandtonic.com>
* @since 4.8.0
*/
class CkeditorMarkup extends ObjectType
{
protected function resolve(mixed $source, array $arguments, mixed $context, ResolveInfo $resolveInfo): mixed
{
/** @var Markup $source */
/** @phpstan-ignore-next-line */
return match ($resolveInfo->fieldName) {
'html' => $source->getHtml(),
'rawHtml' => $source->rawHtml,
'markdown' => $source->getMarkdown($arguments),
'plainText' => $source->getPlainText(),
};
}
}
Loading