mirror of
https://github.com/silverstripe/silverstripe-cms
synced 2024-10-22 08:05:56 +02:00
91cfcb8229
Remove hardcoded references to pages and SiteTree Remove assumption that records are versioned Remove or validate assumptions about methods on the model class Improve general architecture of CMSMain
233 lines
9.6 KiB
PHP
233 lines
9.6 KiB
PHP
<?php
|
|
|
|
namespace SilverStripe\CMS\Forms;
|
|
|
|
use SilverStripe\Admin\LeftAndMain;
|
|
use SilverStripe\CMS\Controllers\CMSMain;
|
|
use SilverStripe\CMS\Controllers\CMSPageEditController;
|
|
use SilverStripe\CMS\Model\SiteTree;
|
|
use SilverStripe\Control\HTTPResponse;
|
|
use SilverStripe\Core\Config\Config;
|
|
use SilverStripe\Core\Convert;
|
|
use SilverStripe\Forms\FieldList;
|
|
use SilverStripe\Forms\Form;
|
|
use SilverStripe\Forms\FormAction;
|
|
use SilverStripe\Forms\LiteralField;
|
|
use SilverStripe\Forms\OptionsetField;
|
|
use SilverStripe\Forms\SelectionGroup;
|
|
use SilverStripe\Forms\SelectionGroup_Item;
|
|
use SilverStripe\Forms\TreeDropdownField;
|
|
use SilverStripe\ORM\DataObject;
|
|
use SilverStripe\ORM\FieldType\DBField;
|
|
use SilverStripe\Security\Security;
|
|
use SilverStripe\SiteConfig\SiteConfig;
|
|
|
|
class CMSMainAddForm extends Form
|
|
{
|
|
public function __construct(CMSMain $controller)
|
|
{
|
|
$modelClass = $controller->getModelClass();
|
|
$singleton = DataObject::singleton($modelClass);
|
|
$recordTypes = [];
|
|
$defaultIcon = Config::inst()->get($modelClass, 'icon_class'); // @TODO need a better place for default - maybe try default on class, and fallback to default on cmsmain?
|
|
$defaultRecordType = 'Page'; // @TODO GENERICALIFICATE THIS! Note it's not necessarily the same as $modelClass, 'cause SiteTree aint Page
|
|
|
|
foreach ($controller->RecordTypes() as $type) {
|
|
$class = $type->getField('ClassName');
|
|
$icon = Config::inst()->get($class, 'icon_class') ?: $defaultIcon;
|
|
|
|
// If the icon is the default and there's some specific icon being provided by `getPageIconURL`
|
|
// then we don't need to add the icon class. Otherwise the class take precedence.
|
|
if ($icon === $defaultIcon && !empty(DataObject::singleton($class)->getPageIconURL())) { // @TODO AHHH
|
|
$icon = '';
|
|
}
|
|
|
|
$html = sprintf(
|
|
'<span class="page-icon %s class-%s"></span><span class="title">%s</span><span class="form__field-description">%s</span>',
|
|
$icon,
|
|
Convert::raw2htmlid($class),
|
|
$type->getField('AddAction'),
|
|
$type->getField('Description')
|
|
);
|
|
$recordTypes[$class] = DBField::create_field('HTMLFragment', $html);
|
|
}
|
|
// Ensure default record type shows on top
|
|
if (isset($recordTypes[$defaultRecordType])) {
|
|
$typeName = $recordTypes[$defaultRecordType];
|
|
$recordTypes = array_merge([$defaultRecordType => $typeName], $recordTypes);
|
|
}
|
|
|
|
$numericLabelTmpl = '<span class="step-label"><span class="flyout">Step %d. </span><span class="title">%s</span></span>';
|
|
|
|
$topTitle = _t(__CLASS__ . '.ParentMode_top', 'Top level');
|
|
$childTitle = _t(
|
|
__CLASS__ . '.ParentMode_child',
|
|
'Under another {type}',
|
|
['type' => mb_strtolower($singleton->i18n_singular_name())]
|
|
);
|
|
|
|
$fields = FieldList::create(
|
|
$parentModeField = SelectionGroup::create(
|
|
'ParentModeField',
|
|
[
|
|
$topField = SelectionGroup_Item::create(
|
|
'top',
|
|
null,
|
|
$topTitle
|
|
),
|
|
SelectionGroup_Item::create(
|
|
'child',
|
|
$parentField = TreeDropdownField::create(
|
|
'ParentID',
|
|
'',
|
|
$modelClass,
|
|
'ID',
|
|
'TreeTitle'
|
|
),
|
|
$childTitle
|
|
)
|
|
]
|
|
),
|
|
LiteralField::create(
|
|
'RestrictedNote',
|
|
sprintf(
|
|
'<p class="alert alert-info message-restricted">%s</p>',
|
|
_t(
|
|
__CLASS__ . '.AddRecordRestriction',
|
|
'Note: Some {model} types are not allowed for this selection',
|
|
['model' => mb_strtolower($singleton->i18n_singular_name())]
|
|
)
|
|
)
|
|
),
|
|
OptionsetField::create(
|
|
'RecordType',
|
|
DBField::create_field(
|
|
'HTMLFragment',
|
|
sprintf($numericLabelTmpl, 2, _t(
|
|
__CLASS__ . '.ChooseRecordType',
|
|
'Choose {model} type',
|
|
['model' => mb_strtolower($singleton->i18n_singular_name())]
|
|
))
|
|
),
|
|
$recordTypes,
|
|
$defaultRecordType
|
|
)
|
|
);
|
|
|
|
$parentModeField->setTitle(DBField::create_field(
|
|
'HTMLFragment',
|
|
sprintf($numericLabelTmpl, 1, _t(__CLASS__ . '.ChooseParentMode', 'Choose where to create this record'))
|
|
));
|
|
|
|
$parentField->setSearchFunction(function ($sourceObject, $labelField, $search) {
|
|
return DataObject::get($sourceObject)
|
|
->filterAny([
|
|
'MenuTitle:PartialMatch' => $search,
|
|
'Title:PartialMatch' => $search,
|
|
]);
|
|
});
|
|
|
|
$parentModeField->addExtraClass('parent-mode');
|
|
|
|
// CMSMain->currentRecordID() automatically sets the homepage, // @TODO find out what this is about
|
|
// which we need to counteract in the default selection (which should default to root, ID=0)
|
|
if ($parentID = $controller->getRequest()->getVar('ParentID')) {
|
|
$parentModeField->setValue('child');
|
|
$parentField->setValue((int)$parentID);
|
|
} else {
|
|
$parentModeField->setValue('top');
|
|
}
|
|
|
|
// Check if the current user has enough permissions to create top level records
|
|
// If not, then disable the option to do that
|
|
if (is_a($modelClass, SiteTree::class, true) && !SiteConfig::current_site_config()->canCreateTopLevel()) { // @TODO probably need to make this generic
|
|
$topField->setDisabled(true);
|
|
$parentModeField->setValue('child');
|
|
}
|
|
|
|
$actions = FieldList::create(
|
|
FormAction::create('doAdd', _t(CMSMain::class . '.Create', 'Create'))
|
|
->addExtraClass('btn-primary font-icon-plus-circled')
|
|
->setUseButtonTag(true),
|
|
FormAction::create('doCancel', _t(CMSMain::class . '.Cancel', 'Cancel'))
|
|
->addExtraClass('btn-secondary')
|
|
->setUseButtonTag(true)
|
|
);
|
|
|
|
$this->extend('updateFields', $fields);
|
|
parent::__construct($controller, 'AddForm', $fields, $actions);
|
|
|
|
$negotiator = $controller->getResponseNegotiator();
|
|
$this->setHTMLID('Form_AddForm')->setStrictFormMethodCheck(false);
|
|
$this->setAttribute('data-hints', $controller->TreeHints());
|
|
$this->setAttribute('data-childfilter', $controller->Link('childfilter'));
|
|
$this->setValidationResponseCallback(function () use ($negotiator, $controller) {
|
|
$request = $controller->getRequest();
|
|
if ($request->isAjax() && $negotiator) {
|
|
$result = $this->forTemplate();
|
|
return $negotiator->respond($request, [
|
|
'CurrentForm' => function () use ($result) {
|
|
return $result;
|
|
}
|
|
]);
|
|
}
|
|
return null;
|
|
});
|
|
$this->addExtraClass('flexbox-area-grow fill-height cms-add-form cms-content cms-edit-form ' . $controller->BaseCSSClasses());
|
|
$this->setTemplate($controller->getTemplatesWithSuffix('_AddForm'));
|
|
}
|
|
|
|
public function doAdd(array $data, Form $form): HTTPResponse
|
|
{
|
|
$defaultRecordType = 'Page'; // @TODO GENERICALIFICATE THIS
|
|
$controller = $this->getController();
|
|
$modelClass = $controller->getModelClass();
|
|
$className = isset($data['RecordType']) ? $data['RecordType'] : $defaultRecordType; // @TODO shouldn't this throw an error??
|
|
$parentID = isset($data['ParentID']) ? (int)$data['ParentID'] : 0;
|
|
|
|
if (!$parentID && isset($data['Parent'])) {
|
|
$parentRecord = $modelClass::get_by_link($data['Parent']); // @TODO Obviously no good
|
|
if ($parentRecord) {
|
|
$parentID = $parentRecord->ID;
|
|
}
|
|
}
|
|
|
|
if (is_numeric($parentID) && $parentID > 0) {
|
|
$parentObj = DataObject::get($modelClass)->byID($parentID);
|
|
} else {
|
|
$parentObj = null;
|
|
}
|
|
|
|
if (!$parentObj || !$parentObj->ID) {
|
|
$parentID = 0;
|
|
}
|
|
|
|
if (!DataObject::singleton($className)->canCreate(Security::getCurrentUser(), ['Parent' => $parentObj])) {
|
|
return Security::permissionFailure($controller);
|
|
}
|
|
|
|
$record = $controller->getNewItem("new-$className-$parentID", false);
|
|
$controller->extend('updateDoAdd', $record, $form);
|
|
$record->write();
|
|
|
|
$editController = CMSPageEditController::singleton();
|
|
$editController->setRequest($controller->getRequest());
|
|
$editController->setCurrentRecordID($record->ID);
|
|
|
|
$controller->getResponse()->addHeader('X-Status', rawurlencode(_t(
|
|
LeftAndMain::class . '.CREATED_RECORD',
|
|
'Created {name} "{title}"',
|
|
[
|
|
'name' => $record->i18n_singular_name(),
|
|
'title' => $record->Title,
|
|
]
|
|
)));
|
|
return $controller->redirect($editController->Link('show/' . $record->ID));
|
|
}
|
|
|
|
public function doCancel(): HTTPResponse
|
|
{
|
|
return $this->getController()->redirect(CMSMain::singleton()->Link()); // @TODO when there's no CMSPageEditController anymore, change this to $this->getController()->Link()
|
|
}
|
|
}
|