text: /**
   * Pimcore
   *
   * This source file is available under two different licenses:
   * - GNU General Public License version 3 (GPLv3)
   * - Pimcore Enterprise License (PEL)
   * Full copyright and license information is available in
   * LICENSE.md which is distributed with this source code.
   *
   * @copyright  Copyright (c) 2009-2016 pimcore GmbH (http://www.pimcore.org)
   * @license    http://www.pimcore.org/license     GPLv3 and PEL
   */
  
  pimcore.registerNS("pimcore.object.classes.klass");
  pimcore.object.classes.klass = Class.create({
  
      allowedInType: 'object',
      disallowedDataTypes: [],
      uploadUrl: '/admin/class/import-class',
      exportUrl: "/admin/class/export-class",
      context: "class",
  
      initialize: function (data, parentPanel, reopen, editorPrefix) {
          this.parentPanel = parentPanel;
          this.data = data;
          this.editorPrefix = editorPrefix;
          this.reopen = reopen;
  
          this.addLayout();
          this.initLayoutFields();
  
      },
  
      getUploadUrl: function(){
          return this.uploadUrl + '?id=' + this.getId();
      },
  
      getExportUrl: function() {
          return  this.exportUrl + "?id=" + this.getId();
      },
  
      addLayout: function () {
  
          this.editpanel = new Ext.Panel({
              region: "center",
              bodyStyle: "padding: 10px;",
              autoScroll: true
          });
  
          this.tree = Ext.create('Ext.tree.Panel', {
              region: "west",
              width: 300,
              split: true,
              enableDD: true,
              autoScroll: true,
              root: {
                  id: "0",
                  root: true,
                  text: t("base"),
                  leaf: true,
                  iconCls: "pimcore_icon_class",
                  isTarget: true
              },
              listeners: this.getTreeNodeListeners(),
              tbar: {
                  items: [
                        "->",
                      {
                          text: t("configure_custom_layouts"),
                          iconCls: "pimcore_icon_class pimcore_icon_overlay_add",
                          hidden: (this instanceof pimcore.object.fieldcollections.field) || (this instanceof pimcore.object.objectbricks.field),
                          handler: this.configureCustomLayouts.bind(this)
                      }
                  ]
              },
              viewConfig: {
                  plugins: {
                      ptype: 'treeviewdragdrop',
                      ddGroup: "element"
                  }
              }
          });
  
          var displayId = this.data.key ? this.data.key : this.data.id; // because the field-collections use that also
  
          var panelButtons = [];
  
          panelButtons.push({
              text: t('reload_definition'),
              handler: this.onRefresh.bind(this),
              iconCls: "pimcore_icon_reload"
          });
  
          panelButtons.push({
              text: t("import"),
              iconCls: "pimcore_icon_class pimcore_icon_overlay_upload",
              handler: this.upload.bind(this)
          });
  
          panelButtons.push({
              text: t("export"),
              iconCls: "pimcore_icon_class pimcore_icon_overlay_download",
              handler: function() {
                  pimcore.helpers.download(this.getExportUrl());
              }.bind(this)
          });
  
  
          panelButtons.push({
              text: t("save"),
              iconCls: "pimcore_icon_apply",
              handler: this.save.bind(this)
          });
  
  
          var name = "";
          if(this.data.name) {
              name = this.data.name + " ( ID: " + displayId + ")";
          } else {
              name = "ID: " + displayId;
          }
  
          this.panel = new Ext.Panel({
              border: false,
              layout: "border",
              closable: true,
              title: name,
              //id: "pimcore_class_editor_panel_" + this.getId(),
              id: this.editorPrefix + this.getId(),
              items: [
                  this.tree,
                  this.editpanel
              ],
              buttons: panelButtons
          });
  
  
          this.parentPanel.getEditPanel().add(this.panel);
  
          this.editpanel.add(this.getRootPanel());
          this.setCurrentNode("root");
          this.parentPanel.getEditPanel().setActiveTab(this.panel);
  
          pimcore.layout.refresh();
      },
  
      configureCustomLayouts: function() {
          try {
              var dialog = new pimcore.object.helpers.customLayoutEditor(this.data);
          } catch (e) {
              console.log(e);
          }
      },
  
      getId: function(){
          return  this.data.id;
      },
  
      upload: function() {
  
          pimcore.helpers.uploadDialog(this.getUploadUrl(), "Filedata", function() {
              Ext.Ajax.request({
                  url: "/admin/class/get",
                  params: {
                      id: this.data.id
                  },
                  success: function(response) {
                      this.data = Ext.decode(response.responseText);
                      this.parentPanel.getEditPanel().removeAll();
                      this.addLayout();
                      this.initLayoutFields();
                      pimcore.layout.refresh();
                  }.bind(this)
              });
          }.bind(this), function () {
              Ext.MessageBox.alert(t("error"), t("error"));
          });
      },
  
      reload: function(response) {
  
      },
  
      initLayoutFields: function () {
  
          if (this.data.layoutDefinitions) {
              if (this.data.layoutDefinitions.childs) {
                  for (var i = 0; i < this.data.layoutDefinitions.childs.length; i++) {
                      this.tree.getRootNode().appendChild(this.recursiveAddNode(this.data.layoutDefinitions.childs[i],
                          this.tree.getRootNode()));
                  }
                  this.tree.getRootNode().expand();
              }
          }
      },
  
      recursiveAddNode: function (con, scope) {
  
          var fn = null;
          var newNode = null;
  
          if (con.datatype == "layout") {
              fn = this.addLayoutChild.bind(scope, con.fieldtype, con, this.context);
          }
          else if (con.datatype == "data") {
              fn = this.addDataChild.bind(scope, con.fieldtype, con, this.context);
          }
  
          newNode = fn();
  
          if (con.childs) {
              for (var i = 0; i < con.childs.length; i++) {
                  this.recursiveAddNode(con.childs[i], newNode);
              }
          }
  
          return newNode;
      },
  
  
      getTreeNodeListeners: function () {
  
          var listeners = {
              "itemclick" : this.onTreeNodeClick.bind(this),
              "itemcontextmenu": this.onTreeNodeContextmenu.bind(this)
          };
          return listeners;
      },
  
  
  
      onTreeNodeClick: function (tree, record, item, index, e, eOpts ) {
  
          try {
              this.saveCurrentNode();
          } catch (e) {
              console.log(e);
          }
  
  
          try {
              this.editpanel.removeAll();
  
              if (record.data.editor) {
  
                  if (record.data.editor.datax.locked) {
                      return;
                  }
  
                  this.editpanel.add(record.data.editor.getLayout());
  
                  this.setCurrentNode(record.data.editor);
              }
  
              if (record.data.root) {
                  this.editpanel.add(this.getRootPanel());
                  this.setCurrentNode("root");
              }
  
              this.editpanel.updateLayout();
          } catch (e) {
              console.log(e);
          }
      },
  
       getDataMenu: function(tree, record, allowedTypes, parentType, editMode) {
          // get available data types
          var dataMenu = [];
          var dataComps = Object.keys(pimcore.object.classes.data);
  
          var parentRestrictions;
          var groups = new Array();
          var groupNames = ["text","numeric","date","select","relation","structured","geo","other"];
          for (var i = 0; i < dataComps.length; i++) {
              var dataCompName = dataComps[i];
              var dataComp = pimcore.object.classes.data[dataCompName];
  
              // check for disallowed types
              var allowed = false;
  
              if('object' !== typeof dataComp) {
                  var tt = typeof dataComp;
                  if (dataComp.prototype.allowIn[this.allowedInType]) {
                      allowed = true;
                  }
              }
  
              if (!allowed) {
                  continue;
              }
  
  
              if (dataComps[i] != "data") { // class data is an abstract class => disallow
                  if (in_array("data", allowedTypes[parentType]) || in_array(dataComps[i], allowedTypes[parentType]) ) {
  
                      // check for restrictions from a parent field (eg. localized fields)
                      if(in_array("data", allowedTypes[parentType])) {
                          parentRestrictions = this.getRestrictionsFromParent(record);
                          if(parentRestrictions != null) {
                              if(!in_array(dataComps[i], allowedTypes[parentRestrictions])) {
                                  continue;
                              }
                          }
                      }
  
                      var group = pimcore.object.classes.data[dataComps[i]].prototype.getGroup();
                      if (!groups[group]) {
                          if (!in_array(group, groupNames)) {
                              groupNames.push(group);
                          }
                          groups[group] = new Array();
                      }
                      var handler;
                      if (editMode) {
                          handler = this.changeDataType.bind(this, tree, record, dataComps[i], true, this.context);
                      } else {
                          handler = this.addDataChild.bind(record, dataComps[i], {}, this.context);
                      }
  
                      groups[group].push({
                          text: pimcore.object.classes.data[dataComps[i]].prototype.getTypeName(),
                          iconCls: pimcore.object.classes.data[dataComps[i]].prototype.getIconClass(),
                          handler: handler
                      });
                  }
              }
          }
  
          for (i = 0; i < groupNames.length; i++) {
              if (groups[groupNames[i]] && groups[groupNames[i]].length > 0) {
                  dataMenu.push(new Ext.menu.Item({
                      text: t(groupNames[i]),
                      iconCls: "pimcore_icon_data_group_" + groupNames[i],
                      hideOnClick: false,
                      menu: groups[groupNames[i]]
                  }));
              }
          }
          return dataMenu;
      },
  
  
      onTreeNodeContextmenu: function (tree, record, item, index, e, eOpts ) {
          e.stopEvent();
          tree.select();
  
          var menu = new Ext.menu.Menu();
  
          var allowedTypes = pimcore.object.helpers.layout.getAllowedTypes(this);
  
          var dataComps = Object.keys(pimcore.object.classes.data);
  
          for (var i = 0; i < dataComps.length; i++) {
              var dataCompName = dataComps[i];
              if ('object' === typeof pimcore.object.classes.data[dataCompName]) {
                  continue;
              }
              var component = pimcore.object.classes.data[dataCompName];
              if(component.prototype.allowIn['localizedfield']) {
                  allowedTypes.localizedfields.push(dataCompName);
              }
  
              if(component.prototype.allowIn['block']) {
                  allowedTypes.block.push(dataCompName);
              }
          }
  
  
          // the child-type "data" is a placehoder for all data components
  
  
          var parentType = "root";
  
          if (record.data.editor) {
              parentType = record.data.editor.type;
          }
  
          var changeTypeAllowed = false;
          if (record.data.type == "data") {
              changeTypeAllowed = true;
          }
  
          var childsAllowed = false;
          if (allowedTypes[parentType] && allowedTypes[parentType].length > 0) {
              childsAllowed = true;
          }
  
          if (childsAllowed || changeTypeAllowed) {
              // get available layouts
              var layoutMenu = [];
              var layouts = Object.keys(pimcore.object.classes.layout);
  
              for (var i = 0; i < layouts.length; i++) {
                  if (layouts[i] != "layout") {
                      if (in_array(layouts[i], allowedTypes[parentType])) {
                          layoutMenu.push({
                              text: pimcore.object.classes.layout[layouts[i]].prototype.getTypeName(),
                              iconCls: pimcore.object.classes.layout[layouts[i]].prototype.getIconClass(),
                              handler: this.addLayoutChild.bind(record, layouts[i], this.context)
                          });
                      }
  
                  }
              }
  
              var getDataMenu = this.getDataMenu.bind(this, tree, record);
              var addDataMenu = getDataMenu(allowedTypes, parentType, false);
  
              if (layoutMenu.length > 0) {
                  menu.add(new Ext.menu.Item({
                      text: t('add_layout_component'),
                      iconCls: "pimcore_icon_add",
                      hideOnClick: false,
                      menu: layoutMenu
                  }));
              }
  
              if (addDataMenu.length > 0) {
                  menu.add(new Ext.menu.Item({
                      text: t('add_data_component'),
                      iconCls: "pimcore_icon_add",
                      hideOnClick: false,
                      menu: addDataMenu
                  }));
              }
  
              if (changeTypeAllowed) {
                  var changeDataMenu = getDataMenu(allowedTypes, record.parentNode.data.editor.type, true);
                  menu.add(new Ext.menu.Item({
                      text: t('change_type'),
                      iconCls: "pimcore_icon_convert",
                      hideOnClick: false,
                      menu: changeDataMenu
                  }));
              }
  
              if (record.data.type == "data") {
                  var dataComps = Object.keys(pimcore.object.classes.data);
                  menu.add(new Ext.menu.Item({
                      text: t('duplicate'),
                      iconCls: "pimcore_icon_clone",
                      hideOnClick: true,
                      handler: this.changeDataType.bind(this, tree, record, record.data.editor.type, false, this.context)
                  }));
              }
  
              menu.add(new Ext.menu.Item({
                  text: t('copy'),
                  iconCls: "pimcore_icon_copy",
                  hideOnClick: true,
                  handler: this.copyNode.bind(this, tree, record)
              }));
  
              if (pimcore && pimcore.classEditor && pimcore.classEditor.clipboard) {
                  menu.add(new Ext.menu.Item({
                      text: t('paste'),
                      iconCls: "pimcore_icon_paste",
                      hideOnClick: true,
                      handler: this.dropNode.bind(this, tree, record)
                  }));
              }
          }
  
          var deleteAllowed = true;
  
          if (record.data.editor) {
              if (record.data.editor.datax.locked) {
                  deleteAllowed = false;
              }
          }
  
          if (this.id != 0 && deleteAllowed) {
              menu.add(new Ext.menu.Item({
                  text: t('delete'),
                  iconCls: "pimcore_icon_delete",
                  handler: this.removeChild.bind(this, tree, record)
              }));
          }
  
          menu.showAt(e.pageX, e.pageY);
      },
  
      getRestrictionsFromParent: function (node) {
          if(node.data.editor.type == "localizedfields") {
              return "localizedfields";
          } else {
              if(node.parentNode && node.parentNode.getDepth() > 0) {
                  var parentType = this.getRestrictionsFromParent(node.parentNode);
                  if(parentType != null) {
                      return parentType;
                  }
              }
          }
  
          return null;
      },
  
      cloneNode:  function(tree, node) {
          var theReference = this;
          var nodeLabel = node.data.text;
          var nodeType = node.data.type;
  
          var config = {
              text: nodeLabel,
              type: nodeType,
              leaf: node.data.leaf,
              expanded: node.data.expanded
          };
  
  
          config.listeners = theReference.getTreeNodeListeners();
  
          if (node.data.editor) {
              config.iconCls = node.data.editor.getIconClass();
          }
  
          var newNode = node.createNode(config);
  
          var theData = {};
  
          if (node.data.editor) {
              theData = Ext.apply(theData, node.data.editor.datax);
          }
  
          if (node.data.editor) {
              var definitions = newNode.data.editor = pimcore.object.classes[nodeType];
              var editorType = node.data.editor.type;
              var editor = definitions[editorType];
  
              newNode.data.editor = new editor(newNode, theData);
          }
  
          if (nodeType == "data") {
              var availableFields = newNode.data.editor.availableSettingsFields;
              for (var i = 0; i < availableFields.length; i++) {
                  var field = availableFields[i];
                  if (node.data.editor.datax[field]) {
                      if (field != "name") {
                          newNode.data.editor.datax[field] = node.data.editor.datax[field];
                      }
                  }
              }
  
              newNode.data.editor.applySpecialData(node.data.editor);
          }
  
  
          var len = node.childNodes ? node.childNodes.length : 0;
  
          var i = 0;
  
          // Move child nodes across to the copy if required
          for (i = 0; i < len; i++) {
              var childNode = node.childNodes[i];
              var clonedChildNode = this.cloneNode(tree, childNode);
  
              newNode.appendChild(clonedChildNode);
          }
          return newNode;
      },
  
  
      copyNode: function(tree, record) {
          if (!pimcore.classEditor) {
              pimcore.classEditor = {};
          }
  
          var newNode = this.cloneNode(tree, record);
          pimcore.classEditor.clipboard = newNode;
  
      },
  
      dropNode: function(tree, record) {
          var node = pimcore.classEditor.clipboard;
          var newNode = this.cloneNode(tree, node);
  
          record.appendChild(newNode);
          tree.updateLayout();
      },
  
  
      setCurrentNode: function (cn) {
          this.currentNode = cn;
      },
  
      saveCurrentNode: function () {
          if (this.currentNode) {
              if (this.currentNode != "root") {
                  this.currentNode.applyData();
              }  else {
                  // save root node data
                  var items = this.rootPanel.queryBy(function() {
                      return true;
                  });
  
                  for (var i = 0; i < items.length; i++) {
                      var item = items[i];
                      if (typeof item.getValue == "function") {
                          this.data[item.name] = item.getValue();
                      }
                  }
              }
          }
      },
  
      getRootPanel: function () {
          this.allowInheritance = new Ext.form.Checkbox({
              fieldLabel: t("allow_inherit"),
              name: "allowInherit",
              checked: this.data.allowInherit,
              listeners: {
                  "change": function(field, checked) {
                      if(checked == true) {
                          this.allowVariants.setDisabled(false);
                      } else {
                          this.allowVariants.setValue(false);
                          this.allowVariants.setDisabled(true);
                          this.showVariants.setValue(false);
                          this.showVariants.setDisabled(true);
                      }
                  }.bind(this)
              }
          });
  
  
          this.allowVariants = new Ext.form.Checkbox({
              fieldLabel: t("allow_variants"),
              name: "allowVariants",
              checked: this.data.allowVariants,
              disabled: !this.data.allowInherit,
              listeners: {
                  "change": function(field, checked) {
                      if(checked == true) {
                          this.showVariants.setDisabled(false);
                      } else {
                          this.showVariants.setValue(false);
                          this.showVariants.setDisabled(true);
                      }
                  }.bind(this)
              }
          });
  
          this.showVariants = new Ext.form.Checkbox({
              fieldLabel: t("show_variants"),
              name: "showVariants",
              checked: this.data.showVariants,
              disabled: !this.data.allowInherit
          });
  
          var getPhpClassName = function (name) {
              return "Pimcore\\Model\\Object\\" + ucfirst(name);
          };
  
          this.rootPanel = new Ext.form.FormPanel({
              title: t("basic_configuration"),
              //border: true,
              bodyStyle: "padding: 10px;",
              defaults: {
                  labelWidth: 200
              },
              items: [
                  {
                      xtype: "textfield",
                      fieldLabel: t("name"),
                      name: "name",
                      width: 500,
                      enableKeyEvents: true,
                      value: this.data.name,
                      listeners: {
                          keyup: function (el) {
                              this.rootPanel.getComponent("phpClassName").setValue(getPhpClassName(el.getValue()))
                          }.bind(this)
                      }
                  },
                  {
                      xtype: "textfield",
                      fieldLabel: t("PHP Class Name"),
                      name: "phpClassName",
                      itemId: "phpClassName",
                      width: 500,
                      disabled: true,
                      value: getPhpClassName(this.data.name)
                  },
                  {
                      xtype: "textarea",
                      fieldLabel: t("description"),
                      name: "description",
                      width: 500,
                      value: this.data.description
                  },
                  this.allowInheritance,
                  this.allowVariants,
                  this.showVariants,
                  {
                      xtype: "textfield",
                      fieldLabel: t("parent_class"),
                      name: "parentClass",
                      width: 600,
                      value: this.data.parentClass
                  },
                  {
                      xtype: "textfield",
                      fieldLabel: t("use_traits"),
                      name: "useTraits",
                      width: 600,
                      value: this.data.useTraits
                  },
                  {
                      xtype: "textfield",
                      fieldLabel: t("icon"),
                      name: "icon",
                      width: 600,
                      value: this.data.icon,
                      enableKeyEvents: true,
                      listeners: {
                          "keyup": function (el) {
                              el.inputEl.applyStyles("background:url(" + el.getValue() + ") right center no-repeat;");
                          },
                          "afterrender": function (el) {
                              el.inputEl.applyStyles("background:url(" + el.getValue() + ") right center no-repeat;");
                          }
                      }
                  },
                  {
                      xtype: "textfield",
                      fieldLabel: t("preview_url"),
                      name: "previewUrl",
                      width: 600,
                      value: this.data.previewUrl
                  },
                  {
                      xtype: "textfield",
                      fieldLabel: t("group"),
                      name: "group",
                      width: 600,
                      value: this.data.group
                  },
                  {
                      xtype: "displayfield",
                      hideLabel: true,
                      width: 600,
                      value: "<b>" + t('visibility_of_system_properties') + "</b>",
                      cls: "pimcore_extra_label_headline"
                  },
                  {
                      xtype: "checkbox",
                      fieldLabel: "ID (" + t("gridview") + ")",
                      name: "propertyVisibility.grid.id",
                      checked: this.data.propertyVisibility.grid.id
                  },
                  {
                      xtype: "checkbox",
                      fieldLabel: "ID (" + t("search") + ")",
                      name: "propertyVisibility.search.id",
                      checked: this.data.propertyVisibility.search.id
                  },
                  {
                      xtype: "checkbox",
                      fieldLabel: t("path") + " (" + t("gridview") + ")",
                      name: "propertyVisibility.grid.path",
                      checked: this.data.propertyVisibility.grid.path
                  },
                  {
                      xtype: "checkbox",
                      fieldLabel: t("path") + " (" + t("search") + ")",
                      name: "propertyVisibility.search.path",
                      checked: this.data.propertyVisibility.search.path
                  },
                  {
                      xtype: "checkbox",
                      fieldLabel: t("published") + " (" + t("gridview") + ")",
                      name: "propertyVisibility.grid.published",
                      checked: this.data.propertyVisibility.grid.published
                  },
                  {
                      xtype: "checkbox",
                      fieldLabel: t("published") + " (" + t("search") + ")",
                      name: "propertyVisibility.search.published",
                      checked: this.data.propertyVisibility.search.published
                  },
                  {
                      xtype: "checkbox",
                      fieldLabel: t("modificationDate") + " (" + t("gridview") + ")",
                      name: "propertyVisibility.grid.modificationDate",
                      checked: this.data.propertyVisibility.grid.modificationDate
                  },
                  {
                      xtype: "checkbox",
                      fieldLabel: t("modificationDate") + " (" + t("search") + ")",
                      name: "propertyVisibility.search.modificationDate",
                      checked: this.data.propertyVisibility.search.modificationDate
                  },
                  {
                      xtype: "checkbox",
                      fieldLabel: t("creationDate") + " (" + t("gridview") + ")",
                      name: "propertyVisibility.grid.creationDate",
                      checked: this.data.propertyVisibility.grid.creationDate
                  },
                  {
                      xtype: "checkbox",
                      fieldLabel: t("creationDate") + " (" + t("search") + ")",
                      name: "propertyVisibility.search.creationDate",
                      checked: this.data.propertyVisibility.search.creationDate
                  }
              ]
          });
  
          return this.rootPanel;
      },
  
      addLayoutChild: function (type, initData, context) {
  
          var nodeLabel = t(type);
  
          if (initData) {
              if (initData.name) {
                  nodeLabel = initData.name;
              }
          }
  
          var newNode = {
              text: nodeLabel,
              type: "layout",
              iconCls: "pimcore_icon_" + type,
              leaf: false,
              expandable: false,
              expanded: true
          };
          newNode = this.appendChild(newNode);
  
          //to hide or show the expanding icon depending if childs are available or not
          newNode.addListener('remove', function(node, removedNode, isMove) {
              if(!node.hasChildNodes()) {
                  node.set('expandable', false);
              }
          });
          newNode.addListener('append', function(node) {
              node.set('expandable', true);
          });
  
  
          var editor = new pimcore.object.classes.layout[type](newNode, initData);
          newNode.set("editor", editor);
  
          this.expand();
  
          return newNode;
      },
  
      addDataChild: function (type, initData, context) {
  
          var nodeLabel = t(type);
  
          if (initData) {
              if (initData.name) {
                  nodeLabel = initData.name;
              }
          }
  
          var newNode = {
              text: nodeLabel,
              type: "data",
              leaf: true,
              iconCls: "pimcore_icon_" + type
          };
  
          if (type == "localizedfields") {
              newNode.leaf = false;
              newNode.expanded = true;
              newNode.expandable = false;
          }
  
          newNode = this.appendChild(newNode);
  
          var editor = new pimcore.object.classes.data[type](newNode, initData);
          editor.setContext(context);
          newNode.set("editor", editor);
  
          this.expand();
  
          return newNode;
      },
  
      changeDataType: function (tree, record, type, removeExisting, context) {
          try {
              this.saveCurrentNode();
  
              var nodeLabel = record.data.text;
  
              var theData = {};
  
              theData.name = nodeLabel;
              theData.datatype = "data";
              theData.fieldtype = type;
  
              var isLeaf = this.leaf;
  
              if (!removeExisting) {
                  var matches = nodeLabel.match(/\d+$/);
  
                  if (matches) {
                      var number = matches[0];
  
                      var numberLength = number.length;
                      number = parseInt(number);
                      number = number + 1;
  
                      var l = nodeLabel.length;
  
                      nodeLabel = nodeLabel.substring(0, l - numberLength);
                  } else {
                      number = 1;
                  }
                  nodeLabel = nodeLabel + number;
              }
  
  
              var parentNode = record.parentNode;
  
              var newNode = {
                  text: nodeLabel,
                  type: "data",
                  leaf: true,
                  iconCls: "pimcore_icon_" + type
                  //,
                  //listeners: this.getTreeNodeListeners()
              };
  
              newNode = parentNode.createNode(newNode);
  
              if (!removeExisting) {
                  theData.name = nodeLabel;
              }
  
              var editor = new pimcore.object.classes.data[type](newNode, theData);
              editor.setContext(context);
              newNode = record.parentNode.insertBefore(newNode, record);
  
              var availableFields = editor.availableSettingsFields;
              for (var i = 0;  i < availableFields.length; i++) {
                  var field = availableFields[i];
                  if (record.data.editor.datax[field]) {
                      if (field != "name") {
                          editor.datax[field] = record.data.editor.datax[field];
                      }
                  }
              }
  
              newNode.data.editor = editor;
              newNode.data.editor.applySpecialData(record.data.editor);
  
  
              if (removeExisting) {
                  parentNode.removeChild(record);
  
              } else {
                  parentNode.insertBefore(record, newNode);
              }
  
              //newNode.select();
              var f = this.onTreeNodeClick.bind(this, newNode.getOwnerTree(), newNode);
              f();
  
              var ownerTree = newNode.getOwnerTree();
              var selModel = ownerTree.getSelectionModel();
              selModel.select(newNode);
  
  
              return newNode;
          } catch (e) {
           console.log(e);
          }
      },
  
  
  
  
      removeChild: function (tree, record) {
          if (this.id != 0) {
              if (this.currentNode == record.data.editor) {
                  this.currentNode = null;
                  var rootNode = this.tree.getRootNode();
                  var f = this.onTreeNodeClick.bind(this, this.tree, rootNode);
                  f();
              }
              record.remove();
          }
      },
  
      getNodeData: function (node) {
  
          var data = {};
  
          if (node.data.editor) {
              if (typeof node.data.editor.getData == "function") {
                  data = node.data.editor.getData();
  
                  data.name = trim(data.name);
  
                  // field specific validation
                  var fieldValidation = true;
                  if(typeof node.data.editor.isValid == "function") {
                      fieldValidation = node.data.editor.isValid();
                  }
  
                  var view = this.tree.getView();
                  // check if the name is unique, localizedfields can be used more than once
                  var nodeEl = Ext.fly(view.getNodeByRecord(node));
  
                  var containerAwareDataName = data.name;
                  var parentNode = node.parentNode;
                  while (parentNode) {
                      if (parentNode.data.editor && Ext.isFunction(parentNode.data.editor.getData)) {
                          var parentData = parentNode.data.editor.getData();
                          if (parentData.datatype == "data" && parentNode.data.editor.type == "block") {
                              containerAwareDataName = "block-" + parentData.name + "-" + containerAwareDataName;
                              break;
                          }
                      }
  
                      parentNode = parentNode.parentNode;
                  }
  
                  if ((fieldValidation && in_arrayi(containerAwareDataName,this.usedFieldNames) == false) || data.name == "localizedfields") {
  
                      if(data.datatype == "data") {
                          this.usedFieldNames.push(containerAwareDataName);
                      }
  
                      if(nodeEl) {
                          nodeEl.removeCls("tree_node_error");
                      }
                  }
                  else {
                      if(nodeEl) {
                          nodeEl.addCls("tree_node_error");
                      }
  
                      var invalidFieldsText = t("class_field_name_error") + ": '" + data.name + "'";
  
                      if(node.data.editor.invalidFieldNames){
                          invalidFieldsText = t("reserved_field_names_error")
                              +(implode(',',node.data.editor.forbiddenNames));
                      }
  
                      pimcore.helpers.showNotification(t("error"), t("some_fields_cannot_be_saved"), "error",
                          invalidFieldsText);
  
                      this.getDataSuccess = false;
                      return false;
                  }
              }
          }
  
          data.childs = null;
          if (node.childNodes.length > 0) {
              data.childs = [];
  
              for (var i = 0; i < node.childNodes.length; i++) {
                  data.childs.push(this.getNodeData(node.childNodes[i]));
              }
          }
  
          return data;
      },
  
      getData: function () {
  
          this.getDataSuccess = true;
  
          this.usedFieldNames = [];
  
          var rootNode = this.tree.getRootNode();
          var nodeData = this.getNodeData(rootNode);
  
          return nodeData;
      },
  
      save: function () {
  
          this.saveCurrentNode();
  
          var regresult = this.data["name"].match(/[a-zA-Z][a-zA-Z0-9]+/);
  
          if (this.data["name"].length > 2 && regresult == this.data["name"] && !in_array(this.data["name"].toLowerCase(),
              this.parentPanel.forbiddennames)) {
              delete this.data.layoutDefinitions;
  
              var m = Ext.encode(this.getData());
              var n = Ext.encode(this.data);
  
              if (this.getDataSuccess) {
                  Ext.Ajax.request({
                      url: "/admin/class/save",
                      method: "post",
                      params: {
                          configuration: m,
                          values: n,
                          id: this.data.id
                      },
                      success: this.saveOnComplete.bind(this),
                      failure: this.saveOnError.bind(this)
                  });
              }
          } else {
              Ext.Msg.alert(t('add_class'), t('invalid_class_name'));
          }
      },
  
      saveOnComplete: function (response) {
  
          try {
              var res = Ext.decode(response.responseText);
              if(res.success) {
                  // refresh all class stores
                  this.parentPanel.tree.getStore().load();
                  pimcore.globalmanager.get("object_types_store").load();
                  pimcore.globalmanager.get("object_types_store_create").load();
  
                  // set the current modification date, to detect modifcations on the class which are not made here
                  this.data.modificationDate = res['class'].modificationDate;
  
                  pimcore.helpers.showNotification(t("success"), t("class_saved_successfully"), "success");
              } else {
                  throw "save was not successful, see debug.log";
              }
          } catch (e) {
              this.saveOnError();
          }
  
      },
  
      saveOnError: function () {
          pimcore.helpers.showNotification(t("error"), t("class_save_error"), "error");
      },
  
      onRefresh: function() {
          this.parentPanel.getEditPanel().remove(this.panel);
          this.reopen();
      }
  });
  