CraftCMS v3.3.0 Release Notes

Release Date: 2019-08-27 // over 4 years ago
  • ➕ Added

    • ➕ Added a built-in, autogenerated GraphQL API for content (Craft Pro only). (#4540)
    • ➕ Added “Headless Mode”, which optimizes the system and Control Panel for headless CMS implementations.
    • It’s now possible to create Single sections without URLs. (#3883)
    • ➕ Added the hiddenInput() Twig function, which generates a hidden input tag.
    • ➕ Added the input() Twig function, which generates an input tag.
    • ➕ Added the tag() Twig function, which generates an HTML tag.
    • ➕ Added the |attr Twig filter, which modifies the attributes on an HTML tag. (#4660)
    • ➕ Added the |append and |prepend Twig filters, which add new HTML elements as children of an HTML tag. (#3937)
    • ➕ Added the headlessMode config setting.
    • ➕ Added the purgeStaleUserSessionDuration config setting.
    • 👻 Admin users can now opt into getting the full stack trace view when an uncaught exception occurs when Dev Mode isn’t enabled. (#4765)
    • Admin users can now opt into having Twig templates profiled when Dev Mode isn’t enabled.
    • ➕ Added the graphql/api controller action.
    • ➕ Added craft\base\ApplicationTrait::getGql().
    • ➕ Added craft\base\EagerLoadingFieldInterface::getEagerLoadingGqlConditions().
    • ➕ Added craft\base\ElementInterface::getGqlTypeName().
    • ➕ Added craft\base\ElementInterface::gqlScopesByContext().
    • ➕ Added craft\base\ElementInterface::gqlTypeNameByContext().
    • ➕ Added craft\base\Field::getEagerLoadingGqlConditions().
    • ➕ Added craft\base\FieldInterface::getContentGqlType().
    • ➕ Added craft\base\GqlInlineFragmentFieldInterface.
    • ➕ Added craft\base\GqlInlineFragmentInterface.
    • ➕ Added craft\controllers\GraphqlController.
    • ➕ Added craft\errors\GqlException.
    • ➕ Added craft\events\RegisterGqlDirectivesEvent.
    • ➕ Added craft\events\RegisterGqlQueriesEvent.
    • ➕ Added craft\events\RegisterGqlTypesEvent.
    • ➕ Added craft\gql\arguments\elements\Asset.
    • ➕ Added craft\gql\arguments\elements\Category.
    • ➕ Added craft\gql\arguments\elements\Entry.
    • ➕ Added craft\gql\arguments\elements\GlobalSet.
    • ➕ Added craft\gql\arguments\elements\MatrixBlock.
    • ➕ Added craft\gql\arguments\elements\Tag.
    • ➕ Added craft\gql\arguments\elements\User.
    • ➕ Added craft\gql\base\Arguments.
    • ➕ Added craft\gql\base\Directive.
    • ➕ Added craft\gql\base\ElementArguments.
    • ➕ Added craft\gql\base\ElementResolver.
    • ➕ Added craft\gql\base\GeneratorInterface.
    • ➕ Added craft\gql\base\GqlTypeTrait.
    • ➕ Added craft\gql\base\InterfaceType.
    • ➕ Added craft\gql\base\ObjectType.
    • ➕ Added craft\gql\base\Query.
    • ➕ Added craft\gql\base\Resolver.
    • ➕ Added craft\gql\base\StructureElementArguments.
    • ➕ Added craft\gql\directives\FormatDateTime.
    • ➕ Added craft\gql\directives\Transform.
    • ➕ Added craft\gql\GqlEntityRegistry.
    • ➕ Added craft\gql\interfaces\Element.
    • ➕ Added craft\gql\interfaces\elements\Asset.
    • ➕ Added craft\gql\interfaces\elements\Category.
    • ➕ Added craft\gql\interfaces\elements\Entry.
    • ➕ Added craft\gql\interfaces\elements\GlobalSet.
    • ➕ Added craft\gql\interfaces\elements\MatrixBlock.
    • ➕ Added craft\gql\interfaces\elements\Tag.
    • ➕ Added craft\gql\interfaces\elements\User.
    • ➕ Added craft\gql\interfaces\Structure.
    • ➕ Added craft\gql\queries\Asset.
    • ➕ Added craft\gql\queries\Category.
    • ➕ Added craft\gql\queries\Entry.
    • ➕ Added craft\gql\queries\GlobalSet.
    • ➕ Added craft\gql\queries\Ping.
    • ➕ Added craft\gql\queries\Tag.
    • ➕ Added craft\gql\queries\User.
    • ➕ Added craft\gql\resolvers\elements\Asset.
    • ➕ Added craft\gql\resolvers\elements\Category.
    • ➕ Added craft\gql\resolvers\elements\Entry.
    • ➕ Added craft\gql\resolvers\elements\GlobalSet.
    • ➕ Added craft\gql\resolvers\elements\MatrixBlock.
    • ➕ Added craft\gql\resolvers\elements\Tag.
    • ➕ Added craft\gql\resolvers\elements\User.
    • ➕ Added craft\gql\TypeLoader.
    • ➕ Added craft\gql\types\DateTime.
    • ➕ Added craft\gql\types\elements\Asset.
    • ➕ Added craft\gql\types\elements\Category.
    • ➕ Added craft\gql\types\elements\Element.
    • ➕ Added craft\gql\types\elements\Entry.
    • ➕ Added craft\gql\types\elements\GlobalSet.
    • ➕ Added craft\gql\types\elements\MatrixBlock.
    • ➕ Added craft\gql\types\elements\Tag.
    • ➕ Added craft\gql\types\elements\User.
    • ➕ Added craft\gql\types\generators\AssetType.
    • ➕ Added craft\gql\types\generators\CategoryType.
    • ➕ Added craft\gql\types\generators\ElementType.
    • ➕ Added craft\gql\types\generators\EntryType.
    • ➕ Added craft\gql\types\generators\GlobalSetType.
    • ➕ Added craft\gql\types\generators\MatrixBlockType.
    • ➕ Added craft\gql\types\generators\TableRowType.
    • ➕ Added craft\gql\types\generators\TagType.
    • ➕ Added craft\gql\types\generators\UserType.
    • ➕ Added craft\gql\types\Query.
    • ➕ Added craft\gql\types\TableRow.
    • ➕ Added craft\helpers\App::webResponseConfig().
    • ➕ Added craft\helpers\ArrayHelper::whereMultiple().
    • ➕ Added craft\helpers\ElementHelper::sourceElement().
    • ➕ Added craft\helpers\Gql.
    • ➕ Added craft\helpers\Html::a().
    • ➕ Added craft\helpers\Html::actionInput().
    • ➕ Added craft\helpers\Html::appendToTag().
    • ➕ Added craft\helpers\Html::csrfInput().
    • ➕ Added craft\helpers\Html::modifyTagAttributes().
    • ➕ Added craft\helpers\Html::normalizeTagAttributes().
    • ➕ Added craft\helpers\Html::parseTag().
    • ➕ Added craft\helpers\Html::parseTagAttributes().
    • ➕ Added craft\helpers\Html::prependToTag().
    • ➕ Added craft\helpers\Html::redirectInput().
    • ➕ Added craft\helpers\StringHelper::afterFirst().
    • ➕ Added craft\helpers\StringHelper::afterLast().
    • ➕ Added craft\helpers\StringHelper::append().
    • ➕ Added craft\helpers\StringHelper::appendRandomString().
    • ➕ Added craft\helpers\StringHelper::appendUniqueIdentifier().
    • ➕ Added craft\helpers\StringHelper::at().
    • ➕ Added craft\helpers\StringHelper::beforeFirst().
    • ➕ Added craft\helpers\StringHelper::beforeLast().
    • ➕ Added craft\helpers\StringHelper::capitalizePersonalName().
    • ➕ Added craft\helpers\StringHelper::count().
    • ➕ Added craft\helpers\StringHelper::dasherize().
    • ➕ Added craft\helpers\StringHelper::endsWithAny().
    • ➕ Added craft\helpers\StringHelper::escape().
    • ➕ Added craft\helpers\StringHelper::extractText().
    • ➕ Added craft\helpers\StringHelper::htmlDecode().
    • ➕ Added craft\helpers\StringHelper::htmlEncode().
    • ➕ Added craft\helpers\StringHelper::humanize().
    • ➕ Added craft\helpers\StringHelper::is().
    • ➕ Added craft\helpers\StringHelper::isBase64().
    • ➕ Added craft\helpers\StringHelper::isBlank().
    • ➕ Added craft\helpers\StringHelper::isHexadecimal().
    • ➕ Added craft\helpers\StringHelper::isHtml().
    • ➕ Added craft\helpers\StringHelper::isJson().
    • ➕ Added craft\helpers\StringHelper::isSerialized().
    • ➕ Added craft\helpers\StringHelper::isUtf8().
    • ➕ Added craft\helpers\StringHelper::isWhitespace().
    • ➕ Added craft\helpers\StringHelper::lastSubstringOf().
    • ➕ Added craft\helpers\StringHelper::lineWrapAfterWord().
    • ➕ Added craft\helpers\StringHelper::pad().
    • ➕ Added craft\helpers\StringHelper::padBoth().
    • ➕ Added craft\helpers\StringHelper::padLeft().
    • ➕ Added craft\helpers\StringHelper::padRight().
    • ➕ Added craft\helpers\StringHelper::removeHtml().
    • ➕ Added craft\helpers\StringHelper::removeHtmlBreak().
    • ➕ Added craft\helpers\StringHelper::repeat().
    • ➕ Added craft\helpers\StringHelper::replaceAll().
    • ➕ Added craft\helpers\StringHelper::replaceBeginning().
    • ➕ Added craft\helpers\StringHelper::replaceEnding().
    • ➕ Added craft\helpers\StringHelper::replaceFirst().
    • ➕ Added craft\helpers\StringHelper::replaceLast().
    • ➕ Added craft\helpers\StringHelper::safeTruncate().
    • ➕ Added craft\helpers\StringHelper::shortenAfterWord().
    • ➕ Added craft\helpers\StringHelper::shuffle().
    • ➕ Added craft\helpers\StringHelper::slice().
    • ➕ Added craft\helpers\StringHelper::slugify().
    • ➕ Added craft\helpers\StringHelper::split().
    • ➕ Added craft\helpers\StringHelper::startsWithAny().
    • ➕ Added craft\helpers\StringHelper::stripCssMediaQueries().
    • ➕ Added craft\helpers\StringHelper::stripEmptyHtmlTags().
    • ➕ Added craft\helpers\StringHelper::stripHtml().
    • ➕ Added craft\helpers\StringHelper::stripWhitespace().
    • ➕ Added craft\helpers\StringHelper::substringOf().
    • ➕ Added craft\helpers\StringHelper::surround().
    • ➕ Added craft\helpers\StringHelper::tidy().
    • ➕ Added craft\helpers\StringHelper::titleizeForHumans().
    • ➕ Added craft\helpers\StringHelper::toBoolean().
    • ➕ Added craft\helpers\StringHelper::toSpaces().
    • ➕ Added craft\helpers\StringHelper::toTabs().
    • ➕ Added craft\helpers\StringHelper::toTransliterate().
    • ➕ Added craft\helpers\StringHelper::trimLeft().
    • ➕ Added craft\helpers\StringHelper::trimRight().
    • ➕ Added craft\helpers\StringHelper::upperCamelize().
    • ➕ Added craft\helpers\StringHelper::upperCaseFirst().
    • ➕ Added craft\helpers\Template::beginProfile().
    • ➕ Added craft\helpers\Template::endProfile().
    • ➕ Added craft\helpers\UrlHelper::buildQuery().
    • ➕ Added craft\model\MatrixBlockType::getField().
    • ➕ Added craft\models\GqlSchema.
    • ➕ Added craft\records\GqlSchema.
    • ➕ Added craft\services\Fields::getGroupByUid().
    • ➕ Added craft\services\Gql.
    • ➕ Added craft\services\Matrix::getAllBlockTypes().
    • ➕ Added craft\services\Sections::getAllEntryTypes().
    • ➕ Added craft\web\assets\graphiql\GraphiqlAsset.
    • ➕ Added craft\web\assets\graphiql\VendorAsset.
    • ➕ Added craft\web\twig\nodes\ProfileNode.
    • ➕ Added craft\web\twig\nodevisitors\Profiler.

    🔄 Changed

    • 0️⃣ Relational fields without a specific target site will now only return related elements from the same site as the source element by default, as they did before Craft 3.2. (#4751)
    • 0️⃣ Element arrays no longer include hasDescendants or totalDescendants keys by default. (#4820)
    • 0️⃣ Matrix block queries no longer include blocks owned by drafts or revisions by default. (#4790)
    • ⏪ Entries’ drafts and revisions are now soft-deleted and restored along with their source elements. (#4797)
    • Global set reference tags can now refer to the global set by its handle. (#4645)
    • 👌 Improved Twig template profiling to include blocks and macros.
    • Twig template profiling no longer occurs when Dev Mode isn’t enabled, unless an admin user is logged in and has opted into it.
    • 👍 The actionInput(), csrfInput(), and redirectInput() Twig functions now support an options argument for customizing the HTML tag attributes.
    • ⚠ The _layouts/forms/field.html template now supports label, instructions, tip, warning, and input blocks that can be overridden when including the template with an {% embed %} tag.
    • 👍 Editable tables now support a fullWidth setting, which can be set to false to prevent the table from spanning the full width of the page.
    • 👍 Editable tables now support thin column settings.
    • 👍 Editable tables now support headingHtml column settings.
    • 🗄 Craft no longer overrides the base Twig template class, unless the now-deprecated suppressTemplateErrors config setting is enabled. (#4755)
    • ⚡️ Edit Entry pages now get updated preview target URLs after saving a draft, in case the URLs have changed.
    • The confirmation dialog that can appear after running the Asset Indexes utility no longer will close by pressing the Esc key or clicking outside of the modal. (#4795)
    • ⚠ Section and Matrix “Propagation Method” settings now display warnings about the potential for data loss when appropriate.
    • ⚠ Site group settings now display a warning about the potential for data loss.
    • Control Panel subnav items can now have badge counts. (#4756)
    • 👌 Improved the performance of element duplication on multi-site installs.
    • 👌 Improved the performance of craft\web\View::renderString() for templates that don’t contain any Twig code.
    • craft\behaviors\DraftBehavior::getCreator() can now return null.
    • 📜 craft\helpers\Db::parseParam() now has an optional $columnType argument. (#4807)
    • craft\test\TestSetup::setupCraftDb() no longer accepts a second argument. Ensure that craft\test\Craft::$testConfig is set before calling this function. (#4804)
    • 🌐 craft\web\Request::post() and getBodyParam() will now work with posted JSON data, if the request’s content type is set to application/json.
    • Switched from the stringy/stringy library to voku/stringy. (#4753)

    🗄 Deprecated

    • 🗄 Deprecated the suppressTemplateErrors config setting.
    • 🗄 Deprecated craft\services\Sections::isSectionTemplateValid().
    • 🗄 Deprecated craft\web\twig\Template.

    ✂ Removed

    • ✂ Removed craft\base\ElementInterface::getSource(). (#4754)
    • ✂ Removed craft\web\twig\Extension::actionInputFunction().
    • ✂ Removed craft\web\twig\Extension::csrfInputFunction().
    • ✂ Removed craft\web\twig\Extension::redirectInputFunction().

    🛠 Fixed

    • 🛠 Fixed an error that could occur if garbage collection was run while Craft 3.2 migrations were pending. (#4720)
    • 🛠 Fixed a bug where the “Publish live changes for other authors’ entries” permission was being enforced when saving another author’s entry as a new entry. (#4758)
    • 🛠 Fixed a bug where craft\helpers\UrlHelper methods would strip out array params in the query string. (#4778)
    • 🛠 Fixed a SQL error that occurred when a {% cache %} tag was used on a page with a 4-byte character in the URI. (#4780)
    • 🛠 Fixed a bug where Craft could show a nondescript error when navigating away from a Control Panel page if an Ajax request was currently in progress. (#4796)
    • 🛠 Fixed an error that occurred when editing an entry with a draft that was created by a soft-deleted user. (#4800)
    • 🛠 Fixed a bug where entry revisions and drafts would be deleted when the user that created them was hard-deleted.
    • 🛠 Fixed a SQL error that could occur when executing an element query that had custom JOIN and WHERE clauses if the search param was also set. (#4788)
    • 🛠 Fixed a bug where default field values weren’t being applied to Matrix blocks that were autocreated per the Min Blocks setting. (#4806)
    • 🛠 Fixed Plugin Store dropdowns which were not working properly with Windows Edge browsers.
    • 🛠 Fixed a SQL error that could occur when :empty: or not :empty: was passed to a date param on an element query when running MySQL 8. (#4808)
    • 🛠 Fixed a bug where Dropdown and Multi-select fields’ Dropdown Options settings weren’t autofocusing on the first input when adding a new row with the keyboard. (#4823)