diff --git a/public/css/icons.css b/public/css/icons.css index b5ad831848..afa8085da1 100644 --- a/public/css/icons.css +++ b/public/css/icons.css @@ -1558,6 +1558,11 @@ background: url(/bundles/pimcoreadmin/img/flat-color-icons/focal_point.svg) center center no-repeat !important; } +.pimcore_icon_focal_point_remove { + background: url(/bundles/pimcoreadmin/img/flat-color-icons/focal_point.svg) center center no-repeat !important; + filter: invert(1); +} + .pimcore_icon_icons { background: url(/bundles/pimcoreadmin/img/flat-color-icons/library.svg) center center no-repeat !important; } diff --git a/public/js/pimcore/asset/image.js b/public/js/pimcore/asset/image.js index 2fff4ff54d..9b34d00ffb 100644 --- a/public/js/pimcore/asset/image.js +++ b/public/js/pimcore/asset/image.js @@ -16,7 +16,7 @@ pimcore.registerNS("pimcore.asset.image"); * @private */ pimcore.asset.image = Class.create(pimcore.asset.asset, { - + focalPointCoordinates: {'x': -100,'y': -100}, initialize: function (id, options) { this.options = options; @@ -134,6 +134,7 @@ pimcore.asset.image = Class.create(pimcore.asset.asset, { bodyStyle: "padding: 10px;", items: [{ xtype: "button", + id: "add_focal_point_" + this.id, text: t("set_focal_point"), iconCls: "pimcore_icon_focal_point", width: "100%", @@ -141,6 +142,17 @@ pimcore.asset.image = Class.create(pimcore.asset.asset, { handler: function () { this.addFocalPoint(); }.bind(this) + },{ + xtype: "button", + id: "remove_focal_point_" + this.id, + text: t("remove_focal_point"), + iconCls: "pimcore_icon_focal_point_remove", + width: "100%", + textAlign: "left", + hidden: this["marker"] !== false, + handler: function () { + this.removeFocalPoint(); + }.bind(this) }, { xtype: "container", html: "
" @@ -368,6 +380,7 @@ pimcore.asset.image = Class.create(pimcore.asset.asset, { }); this.displayPanel.on('resize', function () { + this.updateFocalPointCoordinates(); this.initPreviewImage(); }.bind(this)); } @@ -377,7 +390,7 @@ pimcore.asset.image = Class.create(pimcore.asset.asset, { initPreviewImage: function () { - var html = ''; + let html = ''; Ext.get(this.previewContainerId).setHtml(html); let area = this.displayPanel.getEl().down('img'); @@ -386,9 +399,18 @@ pimcore.asset.image = Class.create(pimcore.asset.asset, { area.setStyle('max-height', (this.displayPanel.getHeight() - 40) + "px"); } - if(this.data['customSettings']) { - if (this.data['customSettings']['focalPointX']) { - this.addFocalPoint(this.data['customSettings']['focalPointX'], this.data['customSettings']['focalPointY']); + let focalPointX = this.focalPointCoordinates['x']; + let focalPointY = this.focalPointCoordinates['y']; + + //on init, the marker is undefined (on init) or set (on resize), is false when removing focal point + if (this.marker !== false) { + this.marker = false; + if (focalPointX > -100 && focalPointY > -100) { + this.addFocalPoint(focalPointX, focalPointY); + } else if (this.data['customSettings']) { + if (this.data['customSettings']['focalPointX'] && this.data['customSettings']['focalPointY']) { + this.addFocalPoint(this.data['customSettings']['focalPointX'], this.data['customSettings']['focalPointY']); + } } } }, @@ -410,8 +432,7 @@ pimcore.asset.image = Class.create(pimcore.asset.asset, { text: t("delete"), iconCls: "pimcore_icon_delete", handler: function (el) { - marker.remove(); - this.marker = false; + this.removeFocalPoint(); }.bind(this) })); @@ -426,30 +447,46 @@ pimcore.asset.image = Class.create(pimcore.asset.asset, { var markerDD = new Ext.dd.DD(marker); - this.marker = marker; - }, + Ext.getCmp('remove_focal_point_' + this.id).setVisible(true); + Ext.getCmp('add_focal_point_' + this.id).setVisible(false); - getSaveData : function ($super, only) { - var parameters = $super(only); + this.marker = marker; + }, + removeFocalPoint: function () { if(this["marker"]) { + this.marker.remove(); + this["marker"] = false; + Ext.getCmp('remove_focal_point_' + this.id).setVisible(false); + Ext.getCmp('add_focal_point_' + this.id).setVisible(true); + this.focalPointCoordinates = {x: -100, y: -100}; + } + }, + updateFocalPointCoordinates: function () { + if (this["marker"]) { + let top = intval(this.marker.getStyle('top')); + let left = intval(this.marker.getStyle('left')); - var top = intval(this.marker.getStyle('top')); - var left = intval(this.marker.getStyle('left')); + let boundingBox = this.marker.up().getSize(); - var boundingBox = this.marker.up().getSize(); + let x = round(left * 100 / boundingBox.width, 8); + let y = round(top * 100 / boundingBox.height, 8); + this.focalPointCoordinates = {x: x, y: y}; + } + }, + getSaveData: function ($super, only) { + let parameters = $super(only); - var x = round(left * 100 / boundingBox.width, 8); - var y = round(top * 100 / boundingBox.height, 8); + if (this["marker"]) { + this.updateFocalPointCoordinates(); parameters["image"] = Ext.encode({ "focalPoint": { - "x": x, - "y": y + "x": this.focalPointCoordinates['x'], + "y": this.focalPointCoordinates['y'] } }); } - return parameters; } }); diff --git a/public/js/pimcore/document/editables/link.js b/public/js/pimcore/document/editables/link.js index f8b990dfa8..0b1a1f2f7f 100644 --- a/public/js/pimcore/document/editables/link.js +++ b/public/js/pimcore/document/editables/link.js @@ -92,7 +92,6 @@ pimcore.document.editables.link = Class.create(pimcore.document.editable, { getLinkContent: function () { - let text = "[" + t("not_set") + "]"; if (this.data.text) { text = this.data.text; @@ -101,7 +100,7 @@ pimcore.document.editables.link = Class.create(pimcore.document.editable, { } let displayHtml = Ext.util.Format.htmlEncode(text); if (this.data.path || this.data.anchor || this.data.parameters) { - let fullpath = this.data.path + (this.data.parameters ? '?' + Ext.util.Format.htmlEncode(this.data.parameters) : '') + (this.data.anchor ? '#' + Ext.util.Format.htmlEncode(this.data.anchor) : ''); + let fullpath = Ext.util.Format.htmlEncode(this.data.path + (this.data.parameters ? '?' + this.data.parameters : '') + (this.data.anchor ? '#' + this.data.anchor : '')); let displayHtml = Ext.util.Format.htmlEncode(text); if (this.config.textPrefix !== undefined) { diff --git a/public/js/pimcore/object/tags/checkbox.js b/public/js/pimcore/object/tags/checkbox.js index 419d4698a5..1a823900f6 100644 --- a/public/js/pimcore/object/tags/checkbox.js +++ b/public/js/pimcore/object/tags/checkbox.js @@ -39,7 +39,6 @@ pimcore.object.tags.checkbox = Class.create(pimcore.object.tags.abstract, { getGridColumnConfig:function (field) { var columnConfig = { xtype: "checkcolumn", - disabled: field.layout.noteditable, text: t(field.label), dataIndex:field.key, renderer:function (key, value, metaData, record, rowIndex, colIndex, store) { diff --git a/public/js/pimcore/object/tags/localizedfields.js b/public/js/pimcore/object/tags/localizedfields.js index 27ff84bab4..d01d2de42f 100644 --- a/public/js/pimcore/object/tags/localizedfields.js +++ b/public/js/pimcore/object/tags/localizedfields.js @@ -276,12 +276,8 @@ pimcore.object.tags.localizedfields = Class.create(pimcore.object.tags.abstract, if (oldLanguage == newLanguage) { return; } + this.switchLocalizedPanels(oldLanguage, newLanguage); - this.availablePanels[oldLanguage].hide(); - this.component.updateLayout(); - this.availablePanels[newLanguage].show(); - this.currentLanguage = newLanguage; - this.component.updateLayout(); }.bind(this), pimcoreGlobalLanguageChanged: function (language) { let globalLanguageIndex = 0; @@ -289,6 +285,8 @@ pimcore.object.tags.localizedfields = Class.create(pimcore.object.tags.abstract, globalLanguageIndex = this.frontendLanguages.indexOf(language); } this.countrySelect.setValue(this.frontendLanguages[globalLanguageIndex]); + this.switchLocalizedPanels(this.currentLanguage, language); + }.bind(this) } }; @@ -1004,6 +1002,14 @@ pimcore.object.tags.localizedfields = Class.create(pimcore.object.tags.abstract, languageTab.setActiveTab(tabLanguage); } }); + }, + + switchLocalizedPanels: function (oldLanguage, newLanguage){ + this.availablePanels[oldLanguage].hide(); + this.component.updateLayout(); + this.availablePanels[newLanguage].show(); + this.currentLanguage = newLanguage; + this.component.updateLayout(); } }); diff --git a/src/Controller/Admin/Asset/AssetController.php b/src/Controller/Admin/Asset/AssetController.php index 3a08e2ee50..f6a9c4ca07 100644 --- a/src/Controller/Admin/Asset/AssetController.php +++ b/src/Controller/Admin/Asset/AssetController.php @@ -616,6 +616,9 @@ public function replaceAssetAction(Request $request, TranslatorInterface $transl $stream = fopen($_FILES['Filedata']['tmp_name'], 'r+'); $asset->setStream($stream); $asset->setCustomSetting('thumbnails', null); + if (method_exists($asset, 'getEmbeddedMetaData')) { + $asset->getEmbeddedMetaData(true); + } $asset->setUserModification($this->getAdminUser()->getId()); $newFileExt = pathinfo($newFilename, PATHINFO_EXTENSION); diff --git a/src/Controller/Admin/Asset/AssetHelperController.php b/src/Controller/Admin/Asset/AssetHelperController.php index 330d18715d..3b12f4f129 100644 --- a/src/Controller/Admin/Asset/AssetHelperController.php +++ b/src/Controller/Admin/Asset/AssetHelperController.php @@ -26,8 +26,8 @@ use Pimcore\Bundle\AdminBundle\Model\GridConfigShare; use Pimcore\Bundle\AdminBundle\Tool; use Pimcore\Db; +use Pimcore\File; use Pimcore\Loader\ImplementationLoader\Exception\UnsupportedException; -use Pimcore\Localization\LocaleServiceInterface; use Pimcore\Logger; use Pimcore\Model\Asset; use Pimcore\Model\Element; @@ -722,17 +722,13 @@ public function getExportJobsAction(Request $request, GridHelperService $gridHel /** * @Route("/do-export", name="pimcore_admin_asset_assethelper_doexport", methods={"POST"}) * - * @param Request $request - * @param LocaleServiceInterface $localeService - * - * @return JsonResponse + * @throws FilesystemException */ - public function doExportAction(Request $request, LocaleServiceInterface $localeService): JsonResponse + public function doExportAction(Request $request): JsonResponse { - $fileHandle = \Pimcore\File::getValidFilename($request->get('fileHandle')); + $fileHandle = File::getValidFilename($request->get('fileHandle')); $ids = $request->get('ids'); - $settings = $request->get('settings'); - $settings = json_decode($settings, true); + $settings = json_decode($request->get('settings'), true); $delimiter = $settings['delimiter'] ?? ';'; $language = str_replace('default', '', $request->get('language')); @@ -752,27 +748,37 @@ public function doExportAction(Request $request, LocaleServiceInterface $localeS $csv = $this->getCsvData($request, $language, $list, $fields, $addTitles); - $storage = Storage::get('temp'); - $csvFile = $this->getCsvFile($fileHandle); + try { + $storage = Storage::get('temp'); + $csvFile = $this->getCsvFile($fileHandle); - $fileStream = $storage->readStream($csvFile); + $fileStream = $storage->readStream($csvFile); - $temp = tmpfile(); - stream_copy_to_stream($fileStream, $temp, null, 0); + $temp = tmpfile(); + stream_copy_to_stream($fileStream, $temp, null, 0); - $firstLine = true; - foreach ($csv as $line) { - if ($addTitles && $firstLine) { - $firstLine = false; - $line = implode($delimiter, $line) . "\r\n"; - fwrite($temp, $line); - } else { - fwrite($temp, implode($delimiter, array_map([$this, 'encodeFunc'], $line)) . "\r\n"); + $firstLine = true; + foreach ($csv as $line) { + if ($addTitles && $firstLine) { + $firstLine = false; + $line = implode($delimiter, $line) . "\r\n"; + fwrite($temp, $line); + } else { + fwrite($temp, implode($delimiter, array_map([$this, 'encodeFunc'], $line)) . "\r\n"); + } } + $storage->writeStream($csvFile, $temp); + } catch (UnableToReadFile $exception) { + Logger::err($exception->getMessage()); + + return $this->adminJson( + [ + 'success' => false, + 'message' => sprintf('export file not found: %s', $fileHandle), + ] + ); } - $storage->writeStream($csvFile, $temp); - return $this->adminJson(['success' => true]); } @@ -860,7 +866,7 @@ protected function getCsvFile(string $fileHandle): string public function downloadCsvFileAction(Request $request): Response { $storage = Storage::get('temp'); - $fileHandle = \Pimcore\File::getValidFilename($request->get('fileHandle')); + $fileHandle = File::getValidFilename($request->get('fileHandle')); $csvFile = $this->getCsvFile($fileHandle); try { @@ -893,7 +899,7 @@ public function downloadCsvFileAction(Request $request): Response public function downloadXlsxFileAction(Request $request, GridHelperService $gridHelperService): BinaryFileResponse { $storage = Storage::get('temp'); - $fileHandle = \Pimcore\File::getValidFilename($request->get('fileHandle')); + $fileHandle = File::getValidFilename($request->get('fileHandle')); $csvFile = $this->getCsvFile($fileHandle); try { diff --git a/src/Controller/Admin/DataObject/DataObjectHelperController.php b/src/Controller/Admin/DataObject/DataObjectHelperController.php index 017702a9bd..4be5b1161a 100644 --- a/src/Controller/Admin/DataObject/DataObjectHelperController.php +++ b/src/Controller/Admin/DataObject/DataObjectHelperController.php @@ -26,9 +26,11 @@ use Pimcore\Bundle\AdminBundle\Model\GridConfigShare; use Pimcore\Config; use Pimcore\Db; +use Pimcore\File; use Pimcore\Localization\LocaleServiceInterface; use Pimcore\Logger; use Pimcore\Model\DataObject; +use Pimcore\Model\DataObject\Listing; use Pimcore\Model\User; use Pimcore\Security\SecurityHelper; use Pimcore\Tool; @@ -1283,38 +1285,34 @@ public function getExportJobsAction(Request $request, GridHelperService $gridHel /** * @Route("/do-export", name="doexport", methods={"POST"}) * - * @param Request $request - * @param LocaleServiceInterface $localeService - * @param EventDispatcherInterface $eventDispatcher - * - * @return JsonResponse - * - * @throws \Exception + * @throws \Exception|FilesystemException */ - public function doExportAction(Request $request, LocaleServiceInterface $localeService, EventDispatcherInterface $eventDispatcher): JsonResponse - { - $fileHandle = \Pimcore\File::getValidFilename($request->get('fileHandle')); + public function doExportAction( + Request $request, + LocaleServiceInterface $localeService, + EventDispatcherInterface $eventDispatcher + ): JsonResponse { + $fileHandle = File::getValidFilename($request->get('fileHandle')); $ids = $request->get('ids'); - $settings = $request->get('settings'); - $settings = json_decode($settings, true); + $settings = json_decode($request->get('settings'), true); $delimiter = $settings['delimiter'] ?? ';'; $header = $settings['header'] ?? 'title'; $allParams = array_merge($request->request->all(), $request->query->all()); - $enableInheritance = $settings['enableInheritance'] ?? null; + $enableInheritance = $settings['enableInheritance'] ?? false; DataObject\Concrete::setGetInheritedValues($enableInheritance); $class = DataObject\ClassDefinition::getById($request->get('classId')); if (!$class) { - throw new \Exception('No class definition found'); + throw new \InvalidArgumentException('No class definition found'); } $className = $class->getName(); $listClass = '\\Pimcore\\Model\\DataObject\\' . ucfirst($className) . '\\Listing'; - /** @var \Pimcore\Model\DataObject\Listing $list */ + /** @var Listing $list */ $list = new $listClass(); $quotedIds = []; @@ -1340,56 +1338,72 @@ public function doExportAction(Request $request, LocaleServiceInterface $localeS $requestedLanguage = $this->extractLanguage($request); - $contextFromRequest = $request->get('context'); - if ($contextFromRequest) { - $contextFromRequest = json_decode($contextFromRequest, true); - } - $context = [ 'source' => 'pimcore-export', ]; - if (is_array($contextFromRequest)) { + $contextFromRequest = $request->get('context'); + if ($contextFromRequest) { + $contextFromRequest = json_decode($contextFromRequest, true); $context = array_merge($context, $contextFromRequest); } - $csv = DataObject\Service::getCsvData($requestedLanguage, $localeService, $list, $fields, $header, $addTitles, $context); - - $storage = Storage::get('temp'); - $csvFile = $this->getCsvFile($fileHandle); - - $fileStream = $storage->readStream($csvFile); - - $temp = tmpfile(); - stream_copy_to_stream($fileStream, $temp, null, 0); + $csv = DataObject\Service::getCsvData( + $requestedLanguage, + $localeService, + $list, + $fields, + $header, + $addTitles, + $context + ); - $firstLine = true; + try { + $storage = Storage::get('temp'); + $csvFile = $this->getCsvFile($fileHandle); - if ($request->get('initial') && $header === 'no_header') { - array_shift($csv); - $firstLine = false; - } + $fileStream = $storage->readStream($csvFile); - $lineCount = count($csv); + $temp = tmpfile(); + stream_copy_to_stream($fileStream, $temp, null, 0); - if (!$addTitles && $lineCount > 0) { - fwrite($temp, "\r\n"); - } + $firstLine = true; - for ($i = 0; $i < $lineCount; $i++) { - $line = $csv[$i]; - if ($addTitles && $firstLine) { + if ($request->get('initial') && $header === 'no_header') { + array_shift($csv); $firstLine = false; - $line = implode($delimiter, $line); - fwrite($temp, $line); - } else { - fwrite($temp, implode($delimiter, array_map([$this, 'encodeFunc'], $line))); } - if ($i < $lineCount - 1) { + + $lineCount = count($csv); + + if (!$addTitles && $lineCount > 0) { fwrite($temp, "\r\n"); } + + for ($i = 0; $i < $lineCount; $i++) { + $line = $csv[$i]; + if ($addTitles && $firstLine) { + $firstLine = false; + $line = implode($delimiter, $line); + fwrite($temp, $line); + } else { + fwrite($temp, implode($delimiter, array_map([$this, 'encodeFunc'], $line))); + } + if ($i < $lineCount - 1) { + fwrite($temp, "\r\n"); + } + } + $storage->writeStream($csvFile, $temp); + } catch (UnableToReadFile $exception) { + Logger::err($exception->getMessage()); + + return $this->adminJson( + [ + 'success' => false, + 'message' => sprintf('export file not found: %s', $fileHandle), + ] + ); } - $storage->writeStream($csvFile, $temp); return $this->adminJson(['success' => true]); } @@ -1412,7 +1426,7 @@ public function encodeFunc(string $value): string public function downloadCsvFileAction(Request $request): Response { $storage = Storage::get('temp'); - $fileHandle = \Pimcore\File::getValidFilename($request->get('fileHandle')); + $fileHandle = File::getValidFilename($request->get('fileHandle')); $csvFile = $this->getCsvFile($fileHandle); try { @@ -1445,7 +1459,7 @@ public function downloadCsvFileAction(Request $request): Response public function downloadXlsxFileAction(Request $request, GridHelperService $gridHelperService): BinaryFileResponse { $storage = Storage::get('temp'); - $fileHandle = \Pimcore\File::getValidFilename($request->get('fileHandle')); + $fileHandle = File::getValidFilename($request->get('fileHandle')); $csvFile = $this->getCsvFile($fileHandle); try { diff --git a/translations/admin.en.yaml b/translations/admin.en.yaml index fd63b958c7..e927aadcda 100644 --- a/translations/admin.en.yaml +++ b/translations/admin.en.yaml @@ -723,6 +723,7 @@ setup_two_factor: 'Setup Two Factor Authentication' 2fa_setup_message: 'Two Factor Authentication is required for your account! You have to set it up in your profile settings, otherwise you will not be able to sign in again.' 2fa_wrong: 'Wrong code entered!' set_focal_point: 'Set Focal Point' +remove_focal_point: 'Remove Focal Point' quicksearch: 'Quick Search' standard_preview: 'Standard Preview' upload_new_version: 'Upload new version'