New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cannot copy / paste areablock elements #559
Comments
UPDATE
Ok, found it. In replace if (\Zend_Registry::isRegistered("pimcore_tag_block_current")) {
$blocks = \Zend_Registry::get("pimcore_tag_block_current");
$numeration = \Zend_Registry::get("pimcore_tag_block_numeration");
if (is_array($blocks) and count($blocks) > 0) {
if ($type == "block") {
$tmpBlocks = $blocks;
$tmpNumeration = $numeration;
array_pop($tmpBlocks);
array_pop($tmpNumeration);
$tmpName = $name;
if (is_array($tmpBlocks)) {
$tmpName = $name . implode("_", $tmpBlocks) . implode("_", $tmpNumeration);
}
if ($blocks[count($blocks) - 1] == $tmpName) {
array_pop($blocks);
array_pop($numeration);
}
}
$name = $name . implode("_", $blocks) . implode("_", $numeration);
}
} with if (\Zend_Registry::isRegistered("pimcore_tag_block_current")) {
$blocks = \Zend_Registry::get("pimcore_tag_block_current");
$numeration = \Zend_Registry::get("pimcore_tag_block_numeration");
if (is_array($blocks) and count($blocks) > 0) {
if ($type == "block") {
$tmpBlocks = $blocks;
$tmpNumeration = $numeration;
array_pop($tmpBlocks);
array_pop($tmpNumeration);
$tmpName = $name;
if (is_array($tmpBlocks)) {
$tmpName = $name . implode("_", $tmpBlocks) . implode("_", $tmpNumeration);
}
if ($blocks[count($blocks) - 1] == $tmpName) {
array_pop($blocks);
array_pop($numeration);
}
}
if( count( $numeration ) > 1 ) {
$numeration = array_pop( $numeration );
$blocks = array_pop( $blocks );
} else {
$numeration = $numeration[0];
$blocks = $blocks[0];
}
$name = $name . $blocks . $numeration;
}
} But this fix comes with a "big downside": Every placed content inside nested areablock elements will be lost, because the reference to the "documents_elements" table does not exist anymore. maybe someone can check that? |
after several hours of debugging i finally found a solution, i think - and it's pretty easy though... i just updated my previous answer. i would be great if someone can check this out. |
i can confirm the problem @solverat has and his fix-suggestion works. |
bump. any progress on this? i think the fix isn't to hard to implement but also important. Although the integration into a seamless update process seems to be an issue, right? i tried to find another way without changing the given structure but i think that's impossible: the php save event creates a different style than javascript on clientside. our support team is crying for salvation, can't you hear it? :) |
Hmm, the suggest fix is no option. This will completely break the backward compatibility and I don't see any possible migration path. |
i just tried the last three days and nights to find a solution but i failed (i have to admit, i'm a little bit frustrated). It seems to be impossible to find a continuous way. whatever i tried, at least one of my goals couldn't be done:
Because the "child area" elements aren't real children, just some elements with a merged id of the nested parents, it's very difficult to update their ids. what i tried to do:extend the editableConfiguration with a new field "tagData"
$options = [
"options" => $this->getOptions(),
"data" => $data,
"name" => $this->getName(),
"id" => "pimcore_editable_" . $this->getName(),
"type" => $this->getType(),
"inherited" => $this->getInherited(),
"tagData" => $this->getTagStructureData()
];
$options = @\Zend_Json::encode($options, false, ['enableJsonExprFinder' => true]);
if ($this->editmode) {
echo '
<script type="text/javascript">
editableConfigurations.push(' . $options . ');
</script>
<div id="pimcore_editable_' . $this->getName() . '" class="pimcore_editable pimcore_tag_' . $this->getType() . '">
';
} update Pimcore\Model\Document\Tag.php protected $tagStructureData = array();
public function setTagStructureData($data)
{
$this->tagStructureData = $data;
}
public function getTagStructureData()
{
return $this->tagStructureData;
}
/**
* @param $type
* @param $name
* @param null $document
* @return string
* @throws \Exception
* @throws \Zend_Exception
*/
public static function buildTagName($type, $name, $document = null)
{
if (!preg_match("@^[ -~]+$@", $name)) {
throw new \Exception("Only ASCII characters are allowed as the name for an editable, your name was: " . $name);
}
// check for persona content
if ($document && $document instanceof Document\Page && $document->getUsePersona()) {
$name = $document->getPersonaElementName($name);
}
$tagStructure = self::buildTagNameStructure($type, $name);
if (count($tagStructure['blocks']) > 0) {
$blocks = $tagStructure['blocks'];
$numeration = $tagStructure['numeration'];
$name = $name . implode("_", $blocks) . implode("_", $numeration);
var_dump($name);
}
if (strlen($name) > 750) {
throw new \Exception("Composite name is longer than 750 characters - use shorter names for your editables or reduce amount of nesting levels. Name is: " . $name);
}
return $name;
}
public static function buildTagNameStructure($type, $name)
{
$blocks = array();
$numeration = array();
// @todo add document-id to registry key | for example for embeded snippets
// set suffixes if the tag is inside a block
if (\Zend_Registry::isRegistered("pimcore_tag_block_current")) {
$blocks = \Zend_Registry::get("pimcore_tag_block_current");
$numeration = \Zend_Registry::get("pimcore_tag_block_numeration");
if (is_array($blocks) and count($blocks) > 0) {
if ($type == "block") {
$tmpBlocks = $blocks;
$tmpNumeration = $numeration;
array_pop($tmpBlocks);
array_pop($tmpNumeration);
$tmpName = $name;
if (is_array($tmpBlocks)) {
$tmpName = $name . implode("_", $tmpBlocks) . implode("_", $tmpNumeration);
}
if ($blocks[count($blocks) - 1] == $tmpName) {
array_pop($blocks);
array_pop($numeration);
}
}
}
}
return array('blocks' => $blocks, 'numeration' => $numeration);
} update startup.js
function getEditable(config) {
var id = config.id;
var type = config.type;
var name = config.name;
var options = config.options;
var data = config.data;
var tagData = config.tagData ? config.tagData : [];
var inherited = false;
if(typeof config["inherited"] != "undefined") {
inherited = config["inherited"];
}
if(in_array(name,editableNames)) {
pimcore.helpers.showNotification("ERROR", "Duplicate editable name: " + name, "error");
}
editableNames.push(name);
var tag = new pimcore.document.tags[type](id, name, options, data, inherited, tagData);
tag.setInherited(inherited);
return tag;
} update pimcore/document/tags/areablock.js
copyToClipboard: function (element) {
var ea;
var areaIdentifier = {name: this.getName(), key: parseInt(element.getAttribute("key")), tagData : this.tagData};
var item = {
identifier: areaIdentifier,
type: element.getAttribute("type"),
values: {}
};
// check which editables are inside this area and get the data
for (var i = 0; i < editables.length; i++) {
try {
ea = editables[i];
var blockJoin = areaIdentifier["tagData"]["blocks"].length > 0 ? areaIdentifier["tagData"]["blocks"].join('_') + '_' : '';
var key = areaIdentifier["tagData"]["numeration"].length > 0 ? areaIdentifier["tagData"]["numeration"].join('_') : areaIdentifier['key'];
if (ea.getName().indexOf( blockJoin + areaIdentifier["name"] + key ) > 0 && ea.getName() && !ea.getInherited()) {
item.values[ea.getName()] = {};
item.values[ea.getName()].parent = false;
item.values[ea.getName()].data = ea.getValue();
item.values[ea.getName()].type = ea.getType();
item.values[ea.getName()].tagData = ea.tagData;
}
} catch (e) { }
}
//now define each parent
Ext.Object.each(item.values, function(name, data) {
if( data["tagData"] && data["tagData"]["blocks"] && data["tagData"]["blocks"].length > 0 ) {
var currentElementBlocks = data["tagData"]["blocks"];
var posParentStr = currentElementBlocks[currentElementBlocks.length-1];
//this element does not have any parents.
if(currentElementBlocks.length === 1) {
return;
}
Ext.Object.each(item.values, function(subName, subData) {
if( subData["tagData"] && subData["tagData"]["blocks"] && subData["tagData"]["blocks"].length > 0 ) {
var subBlocks = subData["tagData"]["blocks"].slice(0);
var subPosParentStr = subBlocks[subBlocks.length-1];
//console.log(subName, posParentStr);
if( subName === posParentStr )
{
item.values[ name ].parent = {name : subName, blocks : subBlocks, numeration : subData.tagData.numeration};
}
}
});
}
});
pimcore.globalmanager.add("areablock_clipboard", item);
},
optionsClickhandler: function (element, btn, e) {
var menu = new Ext.menu.Menu();
if(element != false) {
menu.add(new Ext.menu.Item({
text: t('copy'),
iconCls: "pimcore_icon_copy",
handler: function (item) {
item.parentMenu.destroy();
this.copyToClipboard(element);
}.bind(this)
}));
menu.add(new Ext.menu.Item({
text: t('cut'),
iconCls: "pimcore_icon_cut",
handler: function (item) {
item.parentMenu.destroy();
this.copyToClipboard(element);
this.removeBlock(element);
}.bind(this)
}));
}
if(pimcore.globalmanager.exists("areablock_clipboard")) {
menu.add(new Ext.menu.Item({
text: t('paste'),
iconCls: "pimcore_icon_paste",
handler: function (item) {
item.parentMenu.destroy();
var item = pimcore.globalmanager.get("areablock_clipboard");
var areaIdentifier = {
name: this.getName(),
key: (this.getNextKey()+1),
tagData : this.tagData
};
var fromAreaTagDataBlocks = item["identifier"]["tagData"]['blocks'],
fromAreaTagDataNumeration = item["identifier"]["tagData"]['numeration'];
var fromAreaName = item["identifier"]["name"],
fromAreaKey = item["identifier"]["key"];
var toAreaTagDataBlocks = areaIdentifier["tagData"]['blocks'],
toAreaTagDataNumeration = areaIdentifier["tagData"]['numeration'];
var toAreaName = areaIdentifier["name"],
toAreaKey = areaIdentifier["key"];
console.log('from', fromAreaTagDataBlocks, fromAreaTagDataNumeration, fromAreaName, fromAreaKey);
console.log('to', toAreaTagDataBlocks, toAreaTagDataNumeration, toAreaName, toAreaKey);
// push the data as an object compatible to the pimcore.document.tag interface to the rest of
// available editables so that they get read by pimcore.document.edit.getValues()
Ext.iterate(item.values, function (key, value) {
editables.push({
getName: function () {
var currentElementTagData = value["tagData"];
var realName = key.replace(currentElementTagData["blocks"].join('_') + currentElementTagData["numeration"].join('_'), '');
console.log('realName', realName);
console.log('elementKey', key);
console.log('elementParent', value["parent"]);
console.log('elementTagData', currentElementTagData);
var subPosItemStr = key;
var f1 = fromAreaName + fromAreaKey + fromAreaKey;
var f2 = fromAreaName + fromAreaKey;
var f3 = fromAreaName;
var toAreaNameWithPrefix = toAreaName;
if(toAreaTagDataBlocks.length > 0 && fromAreaTagDataBlocks.join('_') !== toAreaTagDataBlocks.join('_')) {
toAreaNameWithPrefix = toAreaTagDataBlocks.join('_') + '_' + toAreaName;
}
subPosItemStr = subPosItemStr.replace( new RegExp(f1, 'g'), toAreaNameWithPrefix + toAreaKey + toAreaKey);
subPosItemStr = subPosItemStr.replace( new RegExp(f2, 'g'), toAreaNameWithPrefix + toAreaKey);
subPosItemStr = subPosItemStr.replace( new RegExp(f3, 'g'), toAreaNameWithPrefix);
if(fromAreaTagDataBlocks.length > 0) {
subPosItemStr = subPosItemStr.replace( new RegExp(fromAreaTagDataBlocks.join('_'), 'g'), (toAreaTagDataBlocks.length>0 ? toAreaTagDataBlocks.join('_') : '') );
subPosItemStr = subPosItemStr.replace( new RegExp(fromAreaTagDataNumeration.join('_'), 'g'), (toAreaTagDataNumeration.length>0 ? toAreaTagDataNumeration.join('_') : '') );
}
var newSlug = subPosItemStr;
if( value["parent"] !== false && value["parent"]["numeration"].length > 0) {
var parentNumeration = value["parent"]["numeration"].slice(0);
if( parentNumeration.length > 1 ) {
var oldParentNumerationStr = parentNumeration.join("_");
parentNumeration[0] = toAreaKey;
var newParentNumerationStr = parentNumeration.join("_");
console.log("replace parent: ", newSlug, oldParentNumerationStr, newParentNumerationStr);
newSlug = newSlug.replace(new RegExp(oldParentNumerationStr, 'g'), newParentNumerationStr);
}
} else {
newSlug = newSlug.replace(new RegExp(fromAreaKey +'$'), toAreaKey );
}
//cleanup
newSlug = newSlug.replace( new RegExp('__', 'g'), '');
newSlug = newSlug.replace(/_$/, "");
var newKey = newSlug;
console.warn(newKey);
return newKey;
},
getValue: function () {
return value["data"];
},
getInherited: function () {
return false;
},
getType: function () {
return value["type"];
}
});
});
this.addBlock(element, item.type);
}.bind(this)
}));
}
if(menu.items && menu.items.getCount()) {
menu.showAt(e.getXY());
}
e.stopEvent();
} |
second thought: |
The company i am working for is now also evaluating pimcore as our alternative CMS and we have come across the same issue with copy&pasting brick elements across different areablocks: Content will not be copied. |
I have tried different approach with md5 hash ids for elements which was also rejected as not way to go but I still think it will be good way to go. It is backward compatible and it can automatically update document_elements table on element update. My solution just needs extend document_elements table with one column with element hierarchy inside. It also solve this issue. I have stopped working on it when partially working #876 was just rejected without further communication. I will be more than happy to finish it but need to know it will be considered as the way to go... |
hey @alesak the coreteam added the 5.0.0 milestone to this issue. meaning they're working on a solution. because there is a feature implemention stop on 4.x i think you should stop with investing more time on this "build-in" feature. but maybe you could finish it as patch/plugin somehow? I'm sure that a lot of pimcore 4.x users (count me in) are interested to check out your solution. :) |
Hi @solverat I will definitely pause my effort on this for now unless there will be some communication from core team @brusch . Any solution needs to be backward but more importantly forward compatible with new solution which pimcore team hopefully comes with.... Anyway I consider this as a BUG and not a feature so as long as there is planed 4.5.1 version it should be considered... I will probably try to patch 4.x & 3.x branch when solution comes to 5.x branch from core team as we have many instances running previous versions of pimcore . Hopefully this new solution will bring unlimited brick inheritance which is crucial for me... |
you're right - it's a bug, not a feature. :) |
fixed in v5 |
1.) create area element (named "test") with a areablock:
2.) place "test" in content two times.
3.) add a wysiwyg element in first area.
4.) try to copy wysiwyg element and paste into second "test" area element.
result
element has been copied but lost its content.
i debugged the
pimcore/document/tags/areablock.js
:copyToClipboard(): This method searches after a
myAreablockcontent71
element but only findsmyAreablockcontent77_1
. I think there's a problem inModel\Document\Tag::buildTagName()
. Probably the method creates wrong numeration as soon elements are nested.The text was updated successfully, but these errors were encountered: