hankeme_chameleon - Version 0.1.0

Version Notes

initial release

Download this release

Release Info

Developer Jan Strohmeier
Extension hankeme_chameleon
Version 0.1.0
Comparing to
See all releases


Version 0.1.0

Files changed (39) hide show
  1. app/code/community/Hankeme/Chameleon/Block/Adminhtml/Design/Edit.php +308 -0
  2. app/code/community/Hankeme/Chameleon/Block/Adminhtml/Design/Edit/Files.php +150 -0
  3. app/code/community/Hankeme/Chameleon/Block/Adminhtml/Design/Tree.php +109 -0
  4. app/code/community/Hankeme/Chameleon/Block/Adminhtml/Skin/Edit.php +308 -0
  5. app/code/community/Hankeme/Chameleon/Block/Adminhtml/Skin/Edit/Files.php +150 -0
  6. app/code/community/Hankeme/Chameleon/Block/Adminhtml/Skin/Tree.php +109 -0
  7. app/code/community/Hankeme/Chameleon/Helper/Data.php +290 -0
  8. app/code/community/Hankeme/Chameleon/Helper/Design.php +26 -0
  9. app/code/community/Hankeme/Chameleon/Model/Design/Storage.php +236 -0
  10. app/code/community/Hankeme/Chameleon/Model/Design/Storage/Collection.php +28 -0
  11. app/code/community/Hankeme/Chameleon/Model/Skin/Storage.php +236 -0
  12. app/code/community/Hankeme/Chameleon/Model/Skin/Storage/Collection.php +28 -0
  13. app/code/community/Hankeme/Chameleon/controllers/Adminhtml/Chameleon/DesignController.php +186 -0
  14. app/code/community/Hankeme/Chameleon/controllers/Adminhtml/Chameleon/SkinController.php +186 -0
  15. app/code/community/Hankeme/Chameleon/controllers/Adminhtml/ChameleonController.php +25 -0
  16. app/code/community/Hankeme/Chameleon/etc/adminhtml.xml +37 -0
  17. app/code/community/Hankeme/Chameleon/etc/config.xml +165 -0
  18. app/design/adminhtml/default/default/layout/hankeme_chameleon.xml +62 -0
  19. app/design/adminhtml/default/default/template/hankeme/chameleon/design/edit.phtml +38 -0
  20. app/design/adminhtml/default/default/template/hankeme/chameleon/design/edit/files.phtml +28 -0
  21. app/design/adminhtml/default/default/template/hankeme/chameleon/design/tree.phtml +66 -0
  22. app/design/adminhtml/default/default/template/hankeme/chameleon/skin/edit.phtml +38 -0
  23. app/design/adminhtml/default/default/template/hankeme/chameleon/skin/edit/files.phtml +28 -0
  24. app/design/adminhtml/default/default/template/hankeme/chameleon/skin/tree.phtml +66 -0
  25. app/etc/modules/Hankeme_Chameleon.xml +9 -0
  26. js/hankeme/chameleon/chameleon.js +545 -0
  27. package.xml +29 -0
  28. skin/adminhtml/default/default/hankeme/chameleon.css +103 -0
  29. skin/adminhtml/default/default/hankeme/images/chameleon_compressed.png +0 -0
  30. skin/adminhtml/default/default/hankeme/images/chameleon_css.png +0 -0
  31. skin/adminhtml/default/default/hankeme/images/chameleon_file.png +0 -0
  32. skin/adminhtml/default/default/hankeme/images/chameleon_html.png +0 -0
  33. skin/adminhtml/default/default/hankeme/images/chameleon_image.png +0 -0
  34. skin/adminhtml/default/default/hankeme/images/chameleon_js.png +0 -0
  35. skin/adminhtml/default/default/hankeme/images/chameleon_movie.png +0 -0
  36. skin/adminhtml/default/default/hankeme/images/chameleon_music.png +0 -0
  37. skin/adminhtml/default/default/hankeme/images/chameleon_phtml.png +0 -0
  38. skin/adminhtml/default/default/hankeme/images/chameleon_text.png +0 -0
  39. skin/adminhtml/default/default/hankeme/images/chameleon_xml.png +0 -0
app/code/community/Hankeme/Chameleon/Block/Adminhtml/Design/Edit.php ADDED
@@ -0,0 +1,308 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * HANKEME
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
9
+ * See http://opensource.org/licenses/osl-3.0.php for Details
10
+ * In case of questions regarding the use of this source file please
11
+ refer to the contact below.
12
+ *
13
+ * @project: [HANKEME Chameleon]
14
+ * @contact: info@hankeme.de
15
+ * @collaborators: [strohmeier]
16
+ */
17
+
18
+ class Hankeme_Chameleon_Block_Adminhtml_Design_Edit extends Mage_Adminhtml_Block_Widget_Container
19
+ {
20
+
21
+ private $_target_element_id = 'chameleon_edit_stage';
22
+
23
+ /**
24
+ * Array of action buttons
25
+ *
26
+ *
27
+ * @var array
28
+ */
29
+ protected $_actionbuttons = array(
30
+ -1 => array(),
31
+ 0 => array(),
32
+ 1 => array(),
33
+ );
34
+
35
+ public function __construct()
36
+ {
37
+ parent::__construct();
38
+ $this->_headerText = $this->__('Template & Layout Storage');
39
+ $this->_removeButton('back')->_removeButton('edit');
40
+ $this->_addButton('newfolder', array(
41
+ 'class' => 'save',
42
+ 'label' => $this->helper('hankeme_chameleon')->__('Create Folder...'),
43
+ 'type' => 'button',
44
+ 'onclick' => 'MediabrowserInstance.newFolder();'
45
+ ));
46
+
47
+ $this->_addButton('delete_folder', array(
48
+ 'class' => 'delete no-display',
49
+ 'label' => $this->helper('hankeme_chameleon')->__('Delete Folder'),
50
+ 'type' => 'button',
51
+ 'onclick' => 'MediabrowserInstance.deleteFolder();',
52
+ 'id' => 'button_delete_folder'
53
+ ));
54
+
55
+ $this->_addButton('new_file', array(
56
+ 'class' => 'save',
57
+ 'label' => $this->helper('hankeme_chameleon')->__('New File'),
58
+ 'type' => 'button',
59
+ 'onclick' => 'MediabrowserInstance.createFile();',
60
+ 'id' => 'button_create_file'
61
+ ));
62
+
63
+ $this->_addButton('delete_files', array(
64
+ 'class' => 'delete no-display',
65
+ 'label' => $this->helper('hankeme_chameleon')->__('Delete File'),
66
+ 'type' => 'button',
67
+ 'onclick' => 'MediabrowserInstance.deleteFiles();',
68
+ 'id' => 'button_delete_files'
69
+ ));
70
+
71
+ $this->_addButton('backup_files', array(
72
+ 'class' => 'save no-display',
73
+ 'label' => $this->helper('hankeme_chameleon')->__('Backup File'),
74
+ 'type' => 'button',
75
+ 'onclick' => 'MediabrowserInstance.backup();',
76
+ 'id' => 'button_backup_files'
77
+ ));
78
+
79
+ $this->_addButton('insert_files', array(
80
+ 'class' => 'save no-display',
81
+ 'label' => $this->helper('hankeme_chameleon')->__('Edit File'),
82
+ 'type' => 'button',
83
+ 'onclick' => 'MediabrowserInstance.insert();',
84
+ 'id' => 'button_insert_files'
85
+ ));
86
+
87
+ $this->_addActionButton('save_changes', array(
88
+ 'class' => 'save no-display f-right',
89
+ 'label' => $this->helper('hankeme_chameleon')->__('Save Changes'),
90
+ 'type' => 'button',
91
+ 'onclick' => 'MediabrowserInstance.save();',
92
+ 'id' => 'button_save_changes'
93
+ ));
94
+ }
95
+
96
+ public function getContentsUrl()
97
+ {
98
+ return $this->getUrl('*/*/contents', array('type' => $this->getRequest()->getParam('type')));
99
+ }
100
+
101
+ /**
102
+ * Javascript setup object for filebrowser instance
103
+ *
104
+ * @return string
105
+ */
106
+ public function getFilebrowserSetupObject()
107
+ {
108
+ $setupObject = new Varien_Object();
109
+
110
+ $setupObject->setData(array(
111
+ 'newFolderPrompt' => $this->helper('hankeme_chameleon')->__('New Folder Name:'),
112
+ 'newFilePrompt' => $this->helper('hankeme_chameleon')->__('New File Name:'),
113
+ 'deleteFolderConfirmationMessage' => $this->helper('hankeme_chameleon')->__('Are you sure you want to delete the current folder and all of its contents?'),
114
+ 'deleteFileConfirmationMessage' => $this->helper('hankeme_chameleon')->__('Are you sure you want to delete the selected file?'),
115
+ 'targetElementId' => $this->getTargetElementId(),
116
+ 'contentsUrl' => $this->getContentsUrl(),
117
+ 'onInsertUrl' => $this->getOnInsertUrl(),
118
+ 'onSaveUrl' => $this->getOnSaveUrl(),
119
+ 'newFolderUrl' => $this->getNewfolderUrl(),
120
+ 'newFileUrl' => $this->getNewfileUrl(),
121
+ 'deleteFolderUrl' => $this->getDeletefolderUrl(),
122
+ 'deleteFilesUrl' => $this->getDeleteFilesUrl(),
123
+ 'headerText' => $this->getHeaderText(),
124
+ 'onBackupUrl' => $this->getOnBackupUrl(),
125
+ ));
126
+
127
+ return Mage::helper('core')->jsonEncode($setupObject);
128
+ }
129
+
130
+ /**
131
+ * New directory action target URL
132
+ *
133
+ * @return string
134
+ */
135
+ public function getNewfolderUrl()
136
+ {
137
+ return $this->getUrl('*/*/newFolder');
138
+ }
139
+
140
+ /**
141
+ * New file action target URL
142
+ *
143
+ * @return string
144
+ */
145
+ public function getNewfileUrl()
146
+ {
147
+ return $this->getUrl('*/*/newFile');
148
+ }
149
+
150
+ /**
151
+ * Delete directory action target URL
152
+ *
153
+ * @return string
154
+ */
155
+ protected function getDeletefolderUrl()
156
+ {
157
+ return $this->getUrl('*/*/deleteFolder');
158
+ }
159
+
160
+ /**
161
+ * Description goes here...
162
+ *
163
+ * @param none
164
+ * @return void
165
+ */
166
+ public function getDeleteFilesUrl()
167
+ {
168
+ return $this->getUrl('*/*/deleteFiles');
169
+ }
170
+
171
+ /**
172
+ * New directory action target URL
173
+ *
174
+ * @return string
175
+ */
176
+ public function getOnInsertUrl()
177
+ {
178
+ return $this->getUrl('*/*/onInsert');
179
+ }
180
+
181
+
182
+
183
+ /**
184
+ * Save file contents action target URL
185
+ *
186
+ * @return string
187
+ */
188
+ public function getOnSaveUrl()
189
+ {
190
+ return $this->getUrl('*/*/onSave');
191
+ }
192
+
193
+ /**
194
+ * Create Backup action target URL
195
+ *
196
+ * @return string
197
+ */
198
+ public function getOnBackupUrl()
199
+ {
200
+ return $this->getUrl('*/*/onBackup');
201
+ }
202
+
203
+
204
+
205
+ /**
206
+ * Target element ID getter
207
+ *
208
+ * @return string
209
+ */
210
+ public function getTargetElementId()
211
+ {
212
+ return $this->_target_element_id;
213
+ //return $this->getRequest()->getParam('target_element_id');
214
+ }
215
+
216
+
217
+
218
+ /**
219
+ * Add action button
220
+ *
221
+ * @param string $id
222
+ * @param array $data
223
+ * @param integer $level
224
+ * @param integer $sortOrder
225
+ * @param string|null $placement area, that button should be displayed in ('header', 'footer', null)
226
+ * @return Mage_Adminhtml_Block_Widget_Container
227
+ */
228
+ protected function _addActionButton($id, $data, $level = 0, $sortOrder = 0, $area = 'header')
229
+ {
230
+ if (!isset($this->_actionbuttons[$level])) {
231
+ $this->_actionbuttons[$level] = array();
232
+ }
233
+ $this->_actionbuttons[$level][$id] = $data;
234
+ $this->_actionbuttons[$level][$id]['area'] = $area;
235
+ if ($sortOrder) {
236
+ $this->_actionbuttons[$level][$id]['sort_order'] = $sortOrder;
237
+ } else {
238
+ $this->_actionbuttons[$level][$id]['sort_order'] = count($this->_actionbuttons[$level]) * 10;
239
+ }
240
+ return $this;
241
+ }
242
+
243
+ /**
244
+ * Public wrapper for protected _addActionButton method
245
+ *
246
+ * @param string $id
247
+ * @param array $data
248
+ * @param integer $level
249
+ * @param integer $sortOrder
250
+ * @param string|null $placement area, that button should be displayed in ('header', 'footer', null)
251
+ * @return Mage_Adminhtml_Block_Widget_Container
252
+ */
253
+ public function addActionButton($id, $data, $level = 0, $sortOrder = 0, $area = 'header')
254
+ {
255
+ return $this->_addActionButton($id, $data, $level, $sortOrder, $area);
256
+ }
257
+
258
+
259
+
260
+
261
+
262
+ /**
263
+ * Produce more buttons HTML
264
+ *
265
+ * @param string $area
266
+ * @return string
267
+ */
268
+ public function getActionButtonsHtml($area = null)
269
+ {
270
+ $out = '';
271
+ foreach ($this->_actionbuttons as $level => $buttons) {
272
+ $_buttons = array();
273
+ foreach ($buttons as $id => $data) {
274
+ $_buttons[$data['sort_order']]['id'] = $id;
275
+ $_buttons[$data['sort_order']]['data'] = $data;
276
+ }
277
+ ksort($_buttons);
278
+ foreach ($_buttons as $button) {
279
+ $id = $button['id'];
280
+ $data = $button['data'];
281
+ if ($area && isset($data['area']) && ($area != $data['area'])) {
282
+ continue;
283
+ }
284
+ $childId = $this->_prepareButtonBlockId($id);
285
+ $child = $this->getChild($childId);
286
+
287
+ if (!$child) {
288
+ $child = $this->_addButtonChildBlock($childId);
289
+ }
290
+ if (isset($data['name'])) {
291
+ $data['element_name'] = $data['name'];
292
+ }
293
+ $child->setData($data);
294
+
295
+ $out .= $this->getChildHtml($childId);
296
+ }
297
+ }
298
+ return $out;
299
+ }
300
+
301
+ public function getFiletypeNotice() {
302
+
303
+ $allowed = Mage::getModel('hankeme_chameleon/design_storage')->getAllowedExtensions();
304
+ $impl = implode(', ', $allowed);
305
+ return $this->helper('hankeme_chameleon')->__('Only files of the following types are shown: %s', $impl);
306
+
307
+ }
308
+ }
app/code/community/Hankeme/Chameleon/Block/Adminhtml/Design/Edit/Files.php ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * HANKEME
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
8
+ * See http://opensource.org/licenses/osl-3.0.php for Details
9
+ * In case of questions regarding the use of this source file please
10
+ refer to the contact below.
11
+ *
12
+ * @project: [HANKEME Chameleon]
13
+ * @contact: info@hankeme.de
14
+ * @collaborators: [strohmeier]
15
+ */
16
+ class Hankeme_Chameleon_Block_Adminhtml_Design_Edit_Files extends Mage_Adminhtml_Block_Template
17
+ {
18
+ /**
19
+ * Files collection object
20
+ *
21
+ * @var Varien_Data_Collection_Filesystem
22
+ */
23
+ protected $_filesCollection;
24
+
25
+ /**
26
+ * Prepared Files collection for current directory
27
+ *
28
+ * @return Varien_Data_Collection_Filesystem
29
+ */
30
+ public function getFiles()
31
+ {
32
+ if (! $this->_filesCollection) {
33
+ $this->_filesCollection = Mage::getSingleton('hankeme_chameleon/design_storage')->getFilesCollection(Mage::helper('hankeme_chameleon/design')->getCurrentPath(), $this->_getMediaType());
34
+
35
+ }
36
+
37
+ return $this->_filesCollection;
38
+ }
39
+
40
+ /**
41
+ * Files collection count getter
42
+ *
43
+ * @return int
44
+ */
45
+ public function getFilesCount()
46
+ {
47
+ return $this->getFiles()->count();
48
+ }
49
+
50
+ /**
51
+ * File idetifier getter
52
+ *
53
+ * @param Varien_Object $file
54
+ * @return string
55
+ */
56
+ public function getFileId(Varien_Object $file)
57
+ {
58
+ return $file->getId();
59
+ }
60
+
61
+ /**
62
+ * File type getter
63
+ *
64
+ * @param Varien_Object $file
65
+ * @return string
66
+ */
67
+ public function getFileType(Varien_Object $file)
68
+ {
69
+ $bname = $file->getBasename();
70
+ $nparts = explode('.', $bname);
71
+ return end($nparts);
72
+ }
73
+
74
+ /**
75
+ * File thumb URL getter
76
+ *
77
+ * @param Varien_Object $file
78
+ * @return string
79
+ */
80
+ public function getFileThumbUrl(Varien_Object $file)
81
+ {
82
+ return $file->getThumbUrl();
83
+ }
84
+
85
+ /**
86
+ * File name URL getter
87
+ *
88
+ * @param Varien_Object $file
89
+ * @return string
90
+ */
91
+ public function getFileName(Varien_Object $file)
92
+ {
93
+ return $file->getName();
94
+ }
95
+
96
+ /**
97
+ * Image file width getter
98
+ *
99
+ * @param Varien_Object $file
100
+ * @return string
101
+ */
102
+ public function getFileWidth(Varien_Object $file)
103
+ {
104
+ return $file->getWidth();
105
+ }
106
+
107
+ /**
108
+ * Image file height getter
109
+ *
110
+ * @param Varien_Object $file
111
+ * @return string
112
+ */
113
+ public function getFileHeight(Varien_Object $file)
114
+ {
115
+ return $file->getHeight();
116
+ }
117
+
118
+ /**
119
+ * File short name getter
120
+ *
121
+ * @param Varien_Object $file
122
+ * @return string
123
+ */
124
+ public function getFileShortName(Varien_Object $file)
125
+ {
126
+ return $file->getShortName();
127
+ }
128
+
129
+ public function getImagesWidth()
130
+ {
131
+ return Mage::getSingleton('cms/wysiwyg_images_storage')->getConfigData('resize_width');
132
+ }
133
+
134
+ public function getImagesHeight()
135
+ {
136
+ return Mage::getSingleton('cms/wysiwyg_images_storage')->getConfigData('resize_height');
137
+ }
138
+
139
+ /**
140
+ * Return current media type based on request or data
141
+ * @return string
142
+ */
143
+ protected function _getMediaType()
144
+ {
145
+ if ($this->hasData('media_type')) {
146
+ return $this->_getData('media_type');
147
+ }
148
+ return $this->getRequest()->getParam('type');
149
+ }
150
+ }
app/code/community/Hankeme/Chameleon/Block/Adminhtml/Design/Tree.php ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * HANKEME
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
9
+ * See http://opensource.org/licenses/osl-3.0.php for Details
10
+ * In case of questions regarding the use of this source file please
11
+ refer to the contact below.
12
+ *
13
+ * @project: [HANKEME Chameleon]
14
+ * @contact: info@hankeme.de
15
+ * @collaborators: [strohmeier]
16
+ */
17
+
18
+ class Hankeme_Chameleon_Block_Adminhtml_Design_Tree extends Mage_Adminhtml_Block_Template
19
+ {
20
+ protected function _construct()
21
+ {
22
+ parent::_construct();
23
+ $this->setUseAjax(true);
24
+ }
25
+
26
+ /**
27
+ * Json tree builder
28
+ *
29
+ * @return string
30
+ */
31
+ public function getTreeJson()
32
+ {
33
+
34
+ //if(!$this->getStoreId()) return Zend_Json::encode($jsonArray); //force setting of store view level first
35
+
36
+ $helper = Mage::helper('hankeme_chameleon/design');
37
+ $storageRoot = $helper->getStorageRoot();
38
+ $collection = Mage::registry('design_storage')->getDirsCollection($helper->getCurrentPath($this->getStoreId()));
39
+ $jsonArray = array();
40
+
41
+ foreach ($collection as $item) {
42
+ if(is_dir($item->getFilename())) {
43
+ $jsonArray[] = array(
44
+ 'text' => $helper->getShortFilename($item->getBasename(), 20),
45
+ 'id' => $helper->convertPathToId($item->getFilename()),
46
+ 'cls' => 'folder'
47
+ );
48
+ }
49
+ else {
50
+ $jsonArray[] = array(
51
+ 'text' => $helper->getShortFilename($item->getBasename(), 20),
52
+ 'id' => $helper->convertPathToId($item->getFilename()),
53
+ 'cls' => 'file'
54
+ );
55
+ }
56
+ }
57
+ return Zend_Json::encode($jsonArray);
58
+ }
59
+
60
+ /**
61
+ * Json source URL
62
+ *
63
+ * @return string
64
+ */
65
+ public function getTreeLoaderUrl()
66
+ {
67
+ return $this->getUrl('*/*/treeJson', array('store' => $this->getStoreId()));
68
+ }
69
+
70
+ /**
71
+ * Root node name of tree
72
+ *
73
+ * @return string
74
+ */
75
+ public function getRootNodeName()
76
+ {
77
+
78
+ if($this->getStoreId()) return Mage::getStoreConfig('design/theme/template', $this->getStoreId());
79
+ return $this->__('design');
80
+ }
81
+
82
+ /**
83
+ * Return tree node full path based on current path
84
+ *
85
+ * @return string
86
+ */
87
+ public function getTreeCurrentPath()
88
+ {
89
+ $treePath = '/root';
90
+
91
+ $helper = Mage::helper('hankeme_chameleon/design');
92
+ $path = str_replace($helper->getStorageRoot(), '', $path);
93
+ $relative = '';
94
+ foreach (explode(DS, $path) as $dirName) {
95
+ if ($dirName) {
96
+ $relative .= DS . $dirName;
97
+ $treePath .= '/' . $helper->idEncode($relative);
98
+ }
99
+ }
100
+
101
+ return $treePath;
102
+ }
103
+
104
+ public function getStoreSwitcherHtml()
105
+ {
106
+ return $this->getChildHtml('store_switcher');
107
+ }
108
+
109
+ }
app/code/community/Hankeme/Chameleon/Block/Adminhtml/Skin/Edit.php ADDED
@@ -0,0 +1,308 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * HANKEME
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
9
+ * See http://opensource.org/licenses/osl-3.0.php for Details
10
+ * In case of questions regarding the use of this source file please
11
+ refer to the contact below.
12
+ *
13
+ * @project: [HANKEME Chameleon]
14
+ * @contact: info@hankeme.de
15
+ * @collaborators: [strohmeier]
16
+ */
17
+
18
+ class Hankeme_Chameleon_Block_Adminhtml_Skin_Edit extends Mage_Adminhtml_Block_Widget_Container
19
+ {
20
+
21
+ private $_target_element_id = 'chameleon_edit_stage';
22
+
23
+ /**
24
+ * Array of action buttons
25
+ *
26
+ *
27
+ * @var array
28
+ */
29
+ protected $_actionbuttons = array(
30
+ -1 => array(),
31
+ 0 => array(),
32
+ 1 => array(),
33
+ );
34
+
35
+ public function __construct()
36
+ {
37
+ parent::__construct();
38
+ $this->_headerText = $this->__('Skin Storage');
39
+ $this->_removeButton('back')->_removeButton('edit');
40
+ $this->_addButton('newfolder', array(
41
+ 'class' => 'save',
42
+ 'label' => $this->helper('hankeme_chameleon')->__('Create Folder...'),
43
+ 'type' => 'button',
44
+ 'onclick' => 'MediabrowserInstance.newFolder();'
45
+ ));
46
+
47
+ $this->_addButton('delete_folder', array(
48
+ 'class' => 'delete no-display',
49
+ 'label' => $this->helper('hankeme_chameleon')->__('Delete Folder'),
50
+ 'type' => 'button',
51
+ 'onclick' => 'MediabrowserInstance.deleteFolder();',
52
+ 'id' => 'button_delete_folder'
53
+ ));
54
+
55
+ $this->_addButton('new_file', array(
56
+ 'class' => 'save',
57
+ 'label' => $this->helper('hankeme_chameleon')->__('New File'),
58
+ 'type' => 'button',
59
+ 'onclick' => 'MediabrowserInstance.createFile();',
60
+ 'id' => 'button_create_file'
61
+ ));
62
+
63
+ $this->_addButton('delete_files', array(
64
+ 'class' => 'delete no-display',
65
+ 'label' => $this->helper('hankeme_chameleon')->__('Delete File'),
66
+ 'type' => 'button',
67
+ 'onclick' => 'MediabrowserInstance.deleteFiles();',
68
+ 'id' => 'button_delete_files'
69
+ ));
70
+
71
+ $this->_addButton('backup_files', array(
72
+ 'class' => 'save no-display',
73
+ 'label' => $this->helper('hankeme_chameleon')->__('Backup File'),
74
+ 'type' => 'button',
75
+ 'onclick' => 'MediabrowserInstance.backup();',
76
+ 'id' => 'button_backup_files'
77
+ ));
78
+
79
+ $this->_addButton('insert_files', array(
80
+ 'class' => 'save no-display',
81
+ 'label' => $this->helper('hankeme_chameleon')->__('Edit File'),
82
+ 'type' => 'button',
83
+ 'onclick' => 'MediabrowserInstance.insert();',
84
+ 'id' => 'button_insert_files'
85
+ ));
86
+
87
+ $this->_addActionButton('save_changes', array(
88
+ 'class' => 'save no-display f-right',
89
+ 'label' => $this->helper('hankeme_chameleon')->__('Save Changes'),
90
+ 'type' => 'button',
91
+ 'onclick' => 'MediabrowserInstance.save();',
92
+ 'id' => 'button_save_changes'
93
+ ));
94
+ }
95
+
96
+ public function getContentsUrl()
97
+ {
98
+ return $this->getUrl('*/*/contents', array('type' => $this->getRequest()->getParam('type')));
99
+ }
100
+
101
+ /**
102
+ * Javascript setup object for filebrowser instance
103
+ *
104
+ * @return string
105
+ */
106
+ public function getFilebrowserSetupObject()
107
+ {
108
+ $setupObject = new Varien_Object();
109
+
110
+ $setupObject->setData(array(
111
+ 'newFolderPrompt' => $this->helper('hankeme_chameleon')->__('New Folder Name:'),
112
+ 'newFilePrompt' => $this->helper('hankeme_chameleon')->__('New File Name:'),
113
+ 'deleteFolderConfirmationMessage' => $this->helper('hankeme_chameleon')->__('Are you sure you want to delete the current folder and all of its contents?'),
114
+ 'deleteFileConfirmationMessage' => $this->helper('hankeme_chameleon')->__('Are you sure you want to delete the selected file?'),
115
+ 'targetElementId' => $this->getTargetElementId(),
116
+ 'contentsUrl' => $this->getContentsUrl(),
117
+ 'onInsertUrl' => $this->getOnInsertUrl(),
118
+ 'onSaveUrl' => $this->getOnSaveUrl(),
119
+ 'newFolderUrl' => $this->getNewfolderUrl(),
120
+ 'newFileUrl' => $this->getNewfileUrl(),
121
+ 'deleteFolderUrl' => $this->getDeletefolderUrl(),
122
+ 'deleteFilesUrl' => $this->getDeleteFilesUrl(),
123
+ 'headerText' => $this->getHeaderText(),
124
+ 'onBackupUrl' => $this->getOnBackupUrl(),
125
+ ));
126
+
127
+ return Mage::helper('core')->jsonEncode($setupObject);
128
+ }
129
+
130
+ /**
131
+ * New directory action target URL
132
+ *
133
+ * @return string
134
+ */
135
+ public function getNewfolderUrl()
136
+ {
137
+ return $this->getUrl('*/*/newFolder');
138
+ }
139
+
140
+ /**
141
+ * New file action target URL
142
+ *
143
+ * @return string
144
+ */
145
+ public function getNewfileUrl()
146
+ {
147
+ return $this->getUrl('*/*/newFile');
148
+ }
149
+
150
+ /**
151
+ * Delete directory action target URL
152
+ *
153
+ * @return string
154
+ */
155
+ protected function getDeletefolderUrl()
156
+ {
157
+ return $this->getUrl('*/*/deleteFolder');
158
+ }
159
+
160
+ /**
161
+ * Description goes here...
162
+ *
163
+ * @param none
164
+ * @return void
165
+ */
166
+ public function getDeleteFilesUrl()
167
+ {
168
+ return $this->getUrl('*/*/deleteFiles');
169
+ }
170
+
171
+ /**
172
+ * New directory action target URL
173
+ *
174
+ * @return string
175
+ */
176
+ public function getOnInsertUrl()
177
+ {
178
+ return $this->getUrl('*/*/onInsert');
179
+ }
180
+
181
+
182
+
183
+ /**
184
+ * Save file contents action target URL
185
+ *
186
+ * @return string
187
+ */
188
+ public function getOnSaveUrl()
189
+ {
190
+ return $this->getUrl('*/*/onSave');
191
+ }
192
+
193
+ /**
194
+ * Create Backup action target URL
195
+ *
196
+ * @return string
197
+ */
198
+ public function getOnBackupUrl()
199
+ {
200
+ return $this->getUrl('*/*/onBackup');
201
+ }
202
+
203
+
204
+
205
+ /**
206
+ * Target element ID getter
207
+ *
208
+ * @return string
209
+ */
210
+ public function getTargetElementId()
211
+ {
212
+ return $this->_target_element_id;
213
+ //return $this->getRequest()->getParam('target_element_id');
214
+ }
215
+
216
+
217
+
218
+ /**
219
+ * Add action button
220
+ *
221
+ * @param string $id
222
+ * @param array $data
223
+ * @param integer $level
224
+ * @param integer $sortOrder
225
+ * @param string|null $placement area, that button should be displayed in ('header', 'footer', null)
226
+ * @return Mage_Adminhtml_Block_Widget_Container
227
+ */
228
+ protected function _addActionButton($id, $data, $level = 0, $sortOrder = 0, $area = 'header')
229
+ {
230
+ if (!isset($this->_actionbuttons[$level])) {
231
+ $this->_actionbuttons[$level] = array();
232
+ }
233
+ $this->_actionbuttons[$level][$id] = $data;
234
+ $this->_actionbuttons[$level][$id]['area'] = $area;
235
+ if ($sortOrder) {
236
+ $this->_actionbuttons[$level][$id]['sort_order'] = $sortOrder;
237
+ } else {
238
+ $this->_actionbuttons[$level][$id]['sort_order'] = count($this->_actionbuttons[$level]) * 10;
239
+ }
240
+ return $this;
241
+ }
242
+
243
+ /**
244
+ * Public wrapper for protected _addActionButton method
245
+ *
246
+ * @param string $id
247
+ * @param array $data
248
+ * @param integer $level
249
+ * @param integer $sortOrder
250
+ * @param string|null $placement area, that button should be displayed in ('header', 'footer', null)
251
+ * @return Mage_Adminhtml_Block_Widget_Container
252
+ */
253
+ public function addActionButton($id, $data, $level = 0, $sortOrder = 0, $area = 'header')
254
+ {
255
+ return $this->_addActionButton($id, $data, $level, $sortOrder, $area);
256
+ }
257
+
258
+
259
+
260
+
261
+
262
+ /**
263
+ * Produce more buttons HTML
264
+ *
265
+ * @param string $area
266
+ * @return string
267
+ */
268
+ public function getActionButtonsHtml($area = null)
269
+ {
270
+ $out = '';
271
+ foreach ($this->_actionbuttons as $level => $buttons) {
272
+ $_buttons = array();
273
+ foreach ($buttons as $id => $data) {
274
+ $_buttons[$data['sort_order']]['id'] = $id;
275
+ $_buttons[$data['sort_order']]['data'] = $data;
276
+ }
277
+ ksort($_buttons);
278
+ foreach ($_buttons as $button) {
279
+ $id = $button['id'];
280
+ $data = $button['data'];
281
+ if ($area && isset($data['area']) && ($area != $data['area'])) {
282
+ continue;
283
+ }
284
+ $childId = $this->_prepareButtonBlockId($id);
285
+ $child = $this->getChild($childId);
286
+
287
+ if (!$child) {
288
+ $child = $this->_addButtonChildBlock($childId);
289
+ }
290
+ if (isset($data['name'])) {
291
+ $data['element_name'] = $data['name'];
292
+ }
293
+ $child->setData($data);
294
+
295
+ $out .= $this->getChildHtml($childId);
296
+ }
297
+ }
298
+ return $out;
299
+ }
300
+
301
+ public function getFiletypeNotice() {
302
+
303
+ $allowed = Mage::getModel('hankeme_chameleon/skin_storage')->getAllowedExtensions();
304
+ $impl = implode(', ', $allowed);
305
+ return $this->helper('hankeme_chameleon')->__('Only files of the following types are shown: %s', $impl);
306
+
307
+ }
308
+ }
app/code/community/Hankeme/Chameleon/Block/Adminhtml/Skin/Edit/Files.php ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * HANKEME
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
8
+ * See http://opensource.org/licenses/osl-3.0.php for Details
9
+ * In case of questions regarding the use of this source file please
10
+ refer to the contact below.
11
+ *
12
+ * @project: [HANKEME Chameleon]
13
+ * @contact: info@hankeme.de
14
+ * @collaborators: [strohmeier]
15
+ */
16
+ class Hankeme_Chameleon_Block_Adminhtml_Skin_Edit_Files extends Mage_Adminhtml_Block_Template
17
+ {
18
+ /**
19
+ * Files collection object
20
+ *
21
+ * @var Varien_Data_Collection_Filesystem
22
+ */
23
+ protected $_filesCollection;
24
+
25
+ /**
26
+ * Prepared Files collection for current directory
27
+ *
28
+ * @return Varien_Data_Collection_Filesystem
29
+ */
30
+ public function getFiles()
31
+ {
32
+ if (! $this->_filesCollection) {
33
+ $this->_filesCollection = Mage::getSingleton('hankeme_chameleon/skin_storage')->getFilesCollection(Mage::helper('hankeme_chameleon')->getCurrentPath(), $this->_getMediaType());
34
+
35
+ }
36
+
37
+ return $this->_filesCollection;
38
+ }
39
+
40
+ /**
41
+ * Files collection count getter
42
+ *
43
+ * @return int
44
+ */
45
+ public function getFilesCount()
46
+ {
47
+ return $this->getFiles()->count();
48
+ }
49
+
50
+ /**
51
+ * File idetifier getter
52
+ *
53
+ * @param Varien_Object $file
54
+ * @return string
55
+ */
56
+ public function getFileId(Varien_Object $file)
57
+ {
58
+ return $file->getId();
59
+ }
60
+
61
+ /**
62
+ * File type getter
63
+ *
64
+ * @param Varien_Object $file
65
+ * @return string
66
+ */
67
+ public function getFileType(Varien_Object $file)
68
+ {
69
+ $bname = $file->getBasename();
70
+ $nparts = explode('.', $bname);
71
+ return end($nparts);
72
+ }
73
+
74
+ /**
75
+ * File thumb URL getter
76
+ *
77
+ * @param Varien_Object $file
78
+ * @return string
79
+ */
80
+ public function getFileThumbUrl(Varien_Object $file)
81
+ {
82
+ return $file->getThumbUrl();
83
+ }
84
+
85
+ /**
86
+ * File name URL getter
87
+ *
88
+ * @param Varien_Object $file
89
+ * @return string
90
+ */
91
+ public function getFileName(Varien_Object $file)
92
+ {
93
+ return $file->getName();
94
+ }
95
+
96
+ /**
97
+ * Image file width getter
98
+ *
99
+ * @param Varien_Object $file
100
+ * @return string
101
+ */
102
+ public function getFileWidth(Varien_Object $file)
103
+ {
104
+ return $file->getWidth();
105
+ }
106
+
107
+ /**
108
+ * Image file height getter
109
+ *
110
+ * @param Varien_Object $file
111
+ * @return string
112
+ */
113
+ public function getFileHeight(Varien_Object $file)
114
+ {
115
+ return $file->getHeight();
116
+ }
117
+
118
+ /**
119
+ * File short name getter
120
+ *
121
+ * @param Varien_Object $file
122
+ * @return string
123
+ */
124
+ public function getFileShortName(Varien_Object $file)
125
+ {
126
+ return $file->getShortName();
127
+ }
128
+
129
+ public function getImagesWidth()
130
+ {
131
+ return Mage::getSingleton('cms/wysiwyg_images_storage')->getConfigData('resize_width');
132
+ }
133
+
134
+ public function getImagesHeight()
135
+ {
136
+ return Mage::getSingleton('cms/wysiwyg_images_storage')->getConfigData('resize_height');
137
+ }
138
+
139
+ /**
140
+ * Return current media type based on request or data
141
+ * @return string
142
+ */
143
+ protected function _getMediaType()
144
+ {
145
+ if ($this->hasData('media_type')) {
146
+ return $this->_getData('media_type');
147
+ }
148
+ return $this->getRequest()->getParam('type');
149
+ }
150
+ }
app/code/community/Hankeme/Chameleon/Block/Adminhtml/Skin/Tree.php ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * HANKEME
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
9
+ * See http://opensource.org/licenses/osl-3.0.php for Details
10
+ * In case of questions regarding the use of this source file please
11
+ refer to the contact below.
12
+ *
13
+ * @project: [HANKEME Chameleon]
14
+ * @contact: info@hankeme.de
15
+ * @collaborators: [strohmeier]
16
+ */
17
+
18
+ class Hankeme_Chameleon_Block_Adminhtml_Skin_Tree extends Mage_Adminhtml_Block_Template
19
+ {
20
+ protected function _construct()
21
+ {
22
+ parent::_construct();
23
+ $this->setUseAjax(true);
24
+ }
25
+
26
+ /**
27
+ * Json tree builder
28
+ *
29
+ * @return string
30
+ */
31
+ public function getTreeJson()
32
+ {
33
+
34
+ //if(!$this->getStoreId()) return Zend_Json::encode($jsonArray); //force setting of store view level first
35
+
36
+ $helper = Mage::helper('hankeme_chameleon');
37
+ $storageRoot = $helper->getStorageRoot();
38
+ $collection = Mage::registry('skin_storage')->getDirsCollection($helper->getCurrentPath($this->getStoreId()));
39
+ $jsonArray = array();
40
+
41
+ foreach ($collection as $item) {
42
+ if(is_dir($item->getFilename())) {
43
+ $jsonArray[] = array(
44
+ 'text' => $helper->getShortFilename($item->getBasename(), 20),
45
+ 'id' => $helper->convertPathToId($item->getFilename()),
46
+ 'cls' => 'folder'
47
+ );
48
+ }
49
+ else {
50
+ $jsonArray[] = array(
51
+ 'text' => $helper->getShortFilename($item->getBasename(), 20),
52
+ 'id' => $helper->convertPathToId($item->getFilename()),
53
+ 'cls' => 'file'
54
+ );
55
+ }
56
+ }
57
+ return Zend_Json::encode($jsonArray);
58
+ }
59
+
60
+ /**
61
+ * Json source URL
62
+ *
63
+ * @return string
64
+ */
65
+ public function getTreeLoaderUrl()
66
+ {
67
+ return $this->getUrl('*/*/treeJson', array('store' => $this->getStoreId()));
68
+ }
69
+
70
+ /**
71
+ * Root node name of tree
72
+ *
73
+ * @return string
74
+ */
75
+ public function getRootNodeName()
76
+ {
77
+
78
+ if($this->getStoreId()) return Mage::getStoreConfig('design/theme/skin', $this->getStoreId());
79
+ return $this->__('skin');
80
+ }
81
+
82
+ /**
83
+ * Return tree node full path based on current path
84
+ *
85
+ * @return string
86
+ */
87
+ public function getTreeCurrentPath()
88
+ {
89
+ $treePath = '/root';
90
+
91
+ $helper = Mage::helper('hankeme_chameleon');
92
+ $path = str_replace($helper->getStorageRoot(), '', $path);
93
+ $relative = '';
94
+ foreach (explode(DS, $path) as $dirName) {
95
+ if ($dirName) {
96
+ $relative .= DS . $dirName;
97
+ $treePath .= '/' . $helper->idEncode($relative);
98
+ }
99
+ }
100
+
101
+ return $treePath;
102
+ }
103
+
104
+ public function getStoreSwitcherHtml()
105
+ {
106
+ return $this->getChildHtml('store_switcher');
107
+ }
108
+
109
+ }
app/code/community/Hankeme/Chameleon/Helper/Data.php ADDED
@@ -0,0 +1,290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * HANKEME
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
9
+ * See http://opensource.org/licenses/osl-3.0.php for Details
10
+ * In case of questions regarding the use of this source file please
11
+ refer to the contact below.
12
+ *
13
+ * @project: [HANKEME Chameleon]
14
+ * @contact: info@hankeme.de
15
+ * @collaborators: [strohmeier]
16
+ */
17
+
18
+ class Hankeme_Chameleon_Helper_Data extends Mage_Core_Helper_Abstract
19
+ {
20
+
21
+ /**
22
+ * Currenty selected store ID if applicable
23
+ *
24
+ * @var int
25
+ */
26
+ protected $_storeId = null;
27
+
28
+
29
+ /**
30
+ * Set a specified store ID value
31
+ *
32
+ * @param <type> $store
33
+ */
34
+ public function setStoreId($store)
35
+ {
36
+ $this->_storeId = $store;
37
+ return $this;
38
+ }
39
+
40
+
41
+ public function getStorageRoot($storeid){
42
+
43
+
44
+ if($storeid != 0) return Mage::getConfig()->getOptions()->getSkinDir() . DS . 'frontend' . DS . Mage::getStoreConfig('design/package/name', $storeid) . DS .Mage::getStoreConfig('design/theme/skin', $storeid) . DS;
45
+ else return Mage::getConfig()->getOptions()->getSkinDir() . DS . 'frontend' . DS;
46
+ }
47
+
48
+ public function getCurrentPath($storeid){
49
+ if (!$this->_currentPath) {
50
+ $currentPath = $this->getStorageRoot($storeid);
51
+ $path = $this->_getRequest()->getParam($this->getTreeNodeName());
52
+ if ($path) {
53
+ $path = $this->convertIdToPath($path);
54
+ if (is_dir($path)) {
55
+ $currentPath = $path;
56
+ }
57
+ }
58
+ $io = new Varien_Io_File();
59
+ if (!$io->isWriteable($currentPath) && !$io->mkdir($currentPath)) {
60
+ $message = Mage::helper('cms')->__('The directory %s is not writable by server.',$currentPath);
61
+ Mage::throwException($message);
62
+ }
63
+ $this->_currentPath = $currentPath;
64
+ }
65
+ return $this->_currentPath;
66
+ }
67
+
68
+ /**
69
+ * Return URL based on current selected directory or root directory for startup
70
+ *
71
+ * @return string
72
+ */
73
+ public function getCurrentUrl()
74
+ {
75
+ if (!$this->_currentUrl) {
76
+ $path = str_replace(Mage::getConfig()->getOptions()->getSkinDir(), '', $this->getCurrentPath());
77
+ $path = trim($path, DS);
78
+ $this->_currentUrl = Mage::app()->getStore($this->_storeId)->getBaseUrl('skin') .
79
+ $this->convertPathToUrl($path) . '/';
80
+ }
81
+ return $this->_currentUrl;
82
+ }
83
+
84
+ public function convertPathToUrl($path)
85
+ {
86
+ return str_replace(DS, '/', $path);
87
+ }
88
+
89
+ public function getTreeNodeName()
90
+ {
91
+ return 'node';
92
+ }
93
+
94
+ public function convertPathToId($path)
95
+ {
96
+ $path = str_replace($this->getStorageRoot(), '', $path);
97
+ return $this->idEncode($path);
98
+ }
99
+
100
+ public function convertIdToPath($id)
101
+ {
102
+ $path = $this->idDecode($id);
103
+ if (!strstr($path, $this->getStorageRoot())) {
104
+ $path = $this->getStorageRoot() . $path;
105
+ }
106
+ return $path;
107
+ }
108
+
109
+ public function idEncode($string)
110
+ {
111
+ return strtr(base64_encode($string), '+/=', ':_-');
112
+ }
113
+ public function idDecode($string)
114
+ {
115
+ $string = strtr($string, ':_-', '+/=');
116
+ return base64_decode($string);
117
+ }
118
+
119
+ public function getShortFilename($filename, $maxLength = 20)
120
+ {
121
+ if (strlen($filename) <= $maxLength) {
122
+ return $filename;
123
+ }
124
+ return substr($filename, 0, $maxLength) . '...';
125
+ }
126
+
127
+ /**
128
+ * Prepare File Content insertion for textarea (as_is mode)
129
+ *
130
+ * @param string $filename Filename transferred via Ajax
131
+ * @param bool $renderAsContent return plain file contents or link to file
132
+ * @return string
133
+ */
134
+ public function getFileContents($filename, $renderAsContent = false)
135
+ {
136
+
137
+ $path = $this->getCurrentPath($this->_storeId);
138
+
139
+ if ($renderAsContent) {
140
+ try{
141
+ $file = new Varien_Io_File();
142
+ $file->cd($path);
143
+ $data = $file->read($filename);
144
+ return $data;
145
+ }
146
+ catch(Exception $e) {
147
+ return $e->getMessage();
148
+ }
149
+
150
+ return $filePath;
151
+
152
+ } else {
153
+ $fileurl = $this->getCurrentUrl() . $filename;
154
+ return $fileurl;
155
+ }
156
+
157
+ }
158
+
159
+ /**
160
+ * Create File Backup
161
+ *
162
+ * @param string $filename Filename transferred via Ajax
163
+ * @return string
164
+ */
165
+
166
+ public function createBackup($filename)
167
+ {
168
+ $path = $this->getCurrentPath($this->_storeId);
169
+ try{
170
+ $dest = 'Backup_'.date('Y-m-d-H-i-s').'_'.$filename;
171
+ $file = new Varien_Io_File();
172
+ $file->cd($path);
173
+ $result = $file->cp($filename, $dest);
174
+ if($result) {
175
+ $data = $this->__('Backup %s was created', $dest);
176
+ }
177
+ else{
178
+ $data = $this->__('Failed to create Backup');
179
+ }
180
+ return $data;
181
+ }
182
+ catch(Exception $e) {
183
+ return $e->getMessage();
184
+ }
185
+ }
186
+
187
+
188
+ /**
189
+ * Save File Content
190
+ *
191
+ * @param string $filename Filename transferred via Ajax
192
+ * @return string
193
+ */
194
+
195
+ public function saveFileContent($filename, $content)
196
+ {
197
+ $path = $this->getCurrentPath($this->_storeId);
198
+
199
+ try{
200
+ $file = new Varien_Io_File();
201
+ $file->cd($path);
202
+ $data = $file->write($filename, $content);
203
+ if($data) return $this->__('%s was saved', $filename);
204
+ else return $this->__('Error saving %s', $filename);
205
+ }
206
+ catch(Exception $e) {
207
+ return $e->getMessage();
208
+ }
209
+ }
210
+
211
+ public function createFile($filename) {
212
+
213
+ $path = $this->getCurrentPath($this->_storeId);
214
+
215
+ try{
216
+ $file = new Varien_Io_File();
217
+ if(!$file->isWriteable($path)) {
218
+ return $this->__('Permission error, cant create %s', $filename);
219
+ }
220
+ $file->cd($path);
221
+ if($file->fileExists($filename)) return $this->__('File %s already exist.', $filename);
222
+
223
+ $content = (string) ' ';
224
+
225
+ $data = $file->write($filename, $content);
226
+ if($data) return $this->__('%s was created', $filename);
227
+ else return $this->__('Error creating %s', $filename);
228
+ }
229
+ catch(Exception $e) {
230
+ return $e->getMessage();
231
+ }
232
+ }
233
+
234
+ public function deleteFile($filename) {
235
+
236
+ $path = $this->getCurrentPath($this->_storeId);
237
+
238
+ try{
239
+ $file = new Varien_Io_File();
240
+
241
+ $file->cd($path);
242
+
243
+ if($file->fileExists($filename)) {
244
+ $result = $file->rm($filename);
245
+ if($result) return $this->__('File %s was deleted.', $filename);
246
+ return $this->__('File %s could not be deleted.', $filename);
247
+ }
248
+
249
+ return $this->__('File %s does not exist.', $filename);
250
+ }
251
+ catch(Exception $e) {
252
+ return $e->getMessage();
253
+ }
254
+ }
255
+
256
+ public function createDirectory($name, $path) {
257
+
258
+ try{
259
+ $file = new Varien_Io_File();
260
+
261
+ $file->cd($path);
262
+ $result = $file->mkdir($name, 0755);
263
+ if($result) return $this->__('Directory %s was created.', $name);
264
+ return $this->__('Directory %s could not be created.', $name);
265
+ }
266
+ catch(Exception $e) {
267
+ return $e->getMessage();
268
+ }
269
+ }
270
+
271
+ public function deleteDirectory($path) {
272
+ // prevent accidental root directory deleting
273
+ $rootCmp = rtrim($this->getStorageRoot(), DS);
274
+ $pathCmp = rtrim($path, DS);
275
+
276
+ $base = $rootCmp . DS . 'base';
277
+ $basedefault = $rootCmp . DS . 'base' . DS . 'default';
278
+ $default = $rootCmp . DS . 'default';
279
+
280
+ if (($base == $pathCmp) || ($basedefault == $pathCmp) || ($default == $pathCmp) || ($rootCmp == $pathCmp)) {
281
+ return $this->__('Cannot delete core storage directory %s.', $path);
282
+ };
283
+
284
+ $file = new Varien_Io_File();
285
+
286
+ if (!$file->rmdir($path, true)) return $this->__('Cannot delete directory %s.', $path);
287
+
288
+ return $this->__('Successfully deleted directory %s.', $path);
289
+ }
290
+ }
app/code/community/Hankeme/Chameleon/Helper/Design.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * HANKEME
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
9
+ * See http://opensource.org/licenses/osl-3.0.php for Details
10
+ * In case of questions regarding the use of this source file please
11
+ refer to the contact below.
12
+ *
13
+ * @project: [HANKEME Chameleon]
14
+ * @contact: info@hankeme.de
15
+ * @collaborators: [strohmeier]
16
+ */
17
+
18
+ class Hankeme_Chameleon_Helper_Design extends Hankeme_Chameleon_Helper_Data
19
+ {
20
+
21
+ public function getStorageRoot($storeid){
22
+
23
+ if($storeid != 0) return Mage::getConfig()->getOptions()->getDesignDir() . DS . 'frontend' . DS . Mage::getStoreConfig('design/package/name', $storeid) . DS .Mage::getStoreConfig('design/theme/skin', $storeid) . DS;
24
+ else return Mage::getConfig()->getOptions()->getDesignDir() . DS . 'frontend' . DS;
25
+ }
26
+ }
app/code/community/Hankeme/Chameleon/Model/Design/Storage.php ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * HANKEME
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
9
+ * See http://opensource.org/licenses/osl-3.0.php for Details
10
+ * In case of questions regarding the use of this source file please
11
+ refer to the contact below.
12
+ *
13
+ * @project: [HANKEME Chameleon]
14
+ * @contact: info@hankeme.de
15
+ * @collaborators: [strohmeier]
16
+ */
17
+
18
+ class Hankeme_Chameleon_Model_Design_Storage extends Varien_Object
19
+ {
20
+
21
+ /**
22
+ * Config object
23
+ *
24
+ * @var Mage_Core_Model_Config_Element
25
+ */
26
+ protected $_config;
27
+
28
+ /**
29
+ * Config object as array
30
+ *
31
+ * @var array
32
+ */
33
+ protected $_configAsArray;
34
+
35
+ const DIRECTORY_NAME_REGEXP = '/^[a-z0-9\-\_]+$/si';
36
+ const THUMBS_DIRECTORY_NAME = '.thumbs';
37
+ const THUMB_PLACEHOLDER_PATH_SUFFIX = 'images/placeholder/thumbnail.jpg';
38
+
39
+ public function getDirsCollection($path)
40
+ {
41
+ if (Mage::helper('core/file_storage_database')->checkDbUsage()) {
42
+ $subDirectories = Mage::getModel('core/file_storage_directory_database')->getSubdirectories($path);
43
+ foreach ($subDirectories as $directory) {
44
+ $fullPath = rtrim($path, DS) . DS . $directory['name'];
45
+ if (!file_exists($fullPath)) {
46
+ mkdir($fullPath, 0777, true);
47
+ }
48
+ }
49
+ }
50
+
51
+ $conditions = array('reg_exp' => array(), 'plain' => array());
52
+
53
+ foreach ($this->getConfig()->dirs->exclude->children() as $dir) {
54
+ $conditions[$dir->getAttribute('regexp') ? 'reg_exp' : 'plain'][(string) $dir] = true;
55
+ }
56
+ // "include" section takes precedence and can revoke directory exclusion
57
+ foreach ($this->getConfig()->dirs->include->children() as $dir) {
58
+ unset($conditions['regexp'][(string) $dir], $conditions['plain'][(string) $dir]);
59
+ }
60
+
61
+ $regExp = $conditions['reg_exp'] ? ('~' . implode('|', array_keys($conditions['reg_exp'])) . '~i') : null;
62
+
63
+ $collection = $this->getCollection($path)
64
+ ->setCollectDirs(true)
65
+ ->setCollectFiles(false)
66
+ ->setCollectRecursively(false);
67
+ $storageRootLength = strlen(Mage::helper('hankeme_chameleon')->getStorageRoot());
68
+
69
+ foreach ($collection as $key => $value) {
70
+ $rootChildParts = explode(DIRECTORY_SEPARATOR, substr($value->getFilename(), $storageRootLength));
71
+
72
+ if (array_key_exists($rootChildParts[0], $conditions['plain'])
73
+ || ($regExp && preg_match($regExp, $value->getFilename()))) {
74
+ $collection->removeItemByKey($key);
75
+ }
76
+ }
77
+
78
+ return $collection;
79
+ }
80
+
81
+
82
+ /**
83
+ * Return files
84
+ *
85
+ * @param string $path Parent directory path
86
+ * @param string $type Type of storage, e.g. image, media etc.
87
+ * @return Varien_Data_Collection_Filesystem
88
+ */
89
+ public function getFilesCollection($path, $type = null)
90
+ {
91
+ if (Mage::helper('core/file_storage_database')->checkDbUsage()) {
92
+ $files = Mage::getModel('core/file_storage_database')->getDirectoryFiles($path);
93
+
94
+ $fileStorageModel = Mage::getModel('core/file_storage_file');
95
+ foreach ($files as $file) {
96
+ $fileStorageModel->saveFile($file);
97
+ }
98
+ }
99
+
100
+ $collection = $this->getCollection($path)
101
+ ->setCollectDirs(false)
102
+ ->setCollectFiles(true)
103
+ ->setCollectRecursively(false)
104
+ ->setOrder('mtime', Varien_Data_Collection::SORT_ORDER_ASC);
105
+
106
+ // Add files extension filter
107
+ if ($allowed = $this->getAllowedExtensions($type)) {
108
+ $collection->setFilesFilter('/\.(' . implode('|', $allowed). ')$/i');
109
+ }
110
+
111
+ $helper = $this->getHelper();
112
+
113
+ // prepare items
114
+ foreach ($collection as $item) {
115
+ $item->setId($helper->idEncode($item->getBasename()));
116
+ $item->setName($item->getBasename());
117
+ $item->setShortName($helper->getShortFilename($item->getBasename()));
118
+ $item->setUrl($helper->getCurrentUrl() . $item->getBasename());
119
+
120
+ if ($this->isImage($item->getBasename())) {
121
+ $thumbUrl = $this->getThumbnailUrl($item->getFilename(), true);
122
+ // generate thumbnail "on the fly" if it does not exists
123
+ if(! $thumbUrl) {
124
+ $thumbUrl = Mage::getSingleton('adminhtml/url')->getUrl('*/*/thumbnail', array('file' => $item->getId()));
125
+ }
126
+
127
+ $size = @getimagesize($item->getFilename());
128
+
129
+ if (is_array($size)) {
130
+ $item->setWidth($size[0]);
131
+ $item->setHeight($size[1]);
132
+ }
133
+ } else {
134
+ //$thumbUrl = Mage::getDesign()->getSkinBaseUrl() . self::THUMB_PLACEHOLDER_PATH_SUFFIX;
135
+ $thumbUrl = false;
136
+ }
137
+
138
+ $item->setThumbUrl($thumbUrl);
139
+ }
140
+
141
+ return $collection;
142
+ }
143
+
144
+
145
+ public function getCollection($path = null)
146
+ {
147
+ $collection = Mage::getModel('hankeme_chameleon/design_storage_collection');
148
+
149
+ if ($path !== null) {
150
+ $collection->addTargetDir($path);
151
+ }
152
+ return $collection;
153
+ }
154
+
155
+ public function getConfig()
156
+ {
157
+ if (! $this->_config) {
158
+ $this->_config = Mage::getConfig()->getNode('design/browser', 'adminhtml');
159
+ }
160
+
161
+ return $this->_config;
162
+ }
163
+
164
+ /**
165
+ * Prepare allowed_extensions config settings
166
+ *
167
+ * @param string $type Type of storage, e.g. image, media etc.
168
+ * @return array Array of allowed file extensions
169
+ */
170
+ public function getAllowedExtensions($type = null)
171
+ {
172
+ $extensions = $this->getConfigData('extensions');
173
+
174
+ if (is_string($type) && array_key_exists("{$type}_allowed", $extensions)) {
175
+ $allowed = $extensions["{$type}_allowed"];
176
+ } else {
177
+ $allowed = $extensions['allowed'];
178
+ }
179
+
180
+ return array_keys(array_filter($allowed));
181
+ }
182
+
183
+ public function getSession()
184
+ {
185
+ return Mage::getSingleton('adminhtml/session');
186
+ }
187
+
188
+ public function getHelper()
189
+ {
190
+ return Mage::helper('hankeme_chameleon');
191
+ }
192
+
193
+ /**
194
+ * Simple way to check whether file is image or not based on extension
195
+ *
196
+ * @param string $filename
197
+ * @return bool
198
+ */
199
+ public function isImage($filename)
200
+ {
201
+ if (!$this->hasData('_image_extensions')) {
202
+ $this->setData('_image_extensions', $this->getAllowedExtensions('image'));
203
+ }
204
+ $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
205
+ return in_array($ext, $this->_getData('_image_extensions'));
206
+ }
207
+
208
+ /**
209
+ * Config object as array getter
210
+ *
211
+ * @return array
212
+ */
213
+ public function getConfigAsArray()
214
+ {
215
+ if (! $this->_configAsArray) {
216
+ $this->_configAsArray = $this->getConfig()->asCanonicalArray();
217
+ }
218
+
219
+ return $this->_configAsArray;
220
+ }
221
+
222
+ /**
223
+ * Wysiwyg Config reader
224
+ *
225
+ * @param string $key
226
+ * @param mixed $default
227
+ * @return mixed
228
+ */
229
+ public function getConfigData($key, $default=false)
230
+ {
231
+ $configArray = $this->getConfigAsArray();
232
+ $key = (string) $key;
233
+
234
+ return array_key_exists($key, $configArray) ? $configArray[$key] : $default;
235
+ }
236
+ }
app/code/community/Hankeme/Chameleon/Model/Design/Storage/Collection.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * HANKEME
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
8
+ * See http://opensource.org/licenses/osl-3.0.php for Details
9
+ * In case of questions regarding the use of this source file please
10
+ refer to the contact below.
11
+ *
12
+ * @project: [HANKEME Chameleon]
13
+ * @contact: info@hankeme.de
14
+ * @collaborators: [strohmeier]
15
+ */
16
+ class Hankeme_Chameleon_Model_Design_Storage_Collection extends Varien_Data_Collection_Filesystem
17
+ {
18
+ protected function _generateRow($filename)
19
+ {
20
+ $filename = preg_replace('~[/\\\]+~', DIRECTORY_SEPARATOR, $filename);
21
+
22
+ return array(
23
+ 'filename' => $filename,
24
+ 'basename' => basename($filename),
25
+ 'mtime' => filemtime($filename)
26
+ );
27
+ }
28
+ }
app/code/community/Hankeme/Chameleon/Model/Skin/Storage.php ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * HANKEME
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
9
+ * See http://opensource.org/licenses/osl-3.0.php for Details
10
+ * In case of questions regarding the use of this source file please
11
+ refer to the contact below.
12
+ *
13
+ * @project: [HANKEME Chameleon]
14
+ * @contact: info@hankeme.de
15
+ * @collaborators: [strohmeier]
16
+ */
17
+
18
+ class Hankeme_Chameleon_Model_Skin_Storage extends Varien_Object
19
+ {
20
+
21
+ /**
22
+ * Config object
23
+ *
24
+ * @var Mage_Core_Model_Config_Element
25
+ */
26
+ protected $_config;
27
+
28
+ /**
29
+ * Config object as array
30
+ *
31
+ * @var array
32
+ */
33
+ protected $_configAsArray;
34
+
35
+ const DIRECTORY_NAME_REGEXP = '/^[a-z0-9\-\_]+$/si';
36
+ const THUMBS_DIRECTORY_NAME = '.thumbs';
37
+ const THUMB_PLACEHOLDER_PATH_SUFFIX = 'images/placeholder/thumbnail.jpg';
38
+
39
+ public function getDirsCollection($path)
40
+ {
41
+ if (Mage::helper('core/file_storage_database')->checkDbUsage()) {
42
+ $subDirectories = Mage::getModel('core/file_storage_directory_database')->getSubdirectories($path);
43
+ foreach ($subDirectories as $directory) {
44
+ $fullPath = rtrim($path, DS) . DS . $directory['name'];
45
+ if (!file_exists($fullPath)) {
46
+ mkdir($fullPath, 0777, true);
47
+ }
48
+ }
49
+ }
50
+
51
+ $conditions = array('reg_exp' => array(), 'plain' => array());
52
+
53
+ foreach ($this->getConfig()->dirs->exclude->children() as $dir) {
54
+ $conditions[$dir->getAttribute('regexp') ? 'reg_exp' : 'plain'][(string) $dir] = true;
55
+ }
56
+ // "include" section takes precedence and can revoke directory exclusion
57
+ foreach ($this->getConfig()->dirs->include->children() as $dir) {
58
+ unset($conditions['regexp'][(string) $dir], $conditions['plain'][(string) $dir]);
59
+ }
60
+
61
+ $regExp = $conditions['reg_exp'] ? ('~' . implode('|', array_keys($conditions['reg_exp'])) . '~i') : null;
62
+
63
+ $collection = $this->getCollection($path)
64
+ ->setCollectDirs(true)
65
+ ->setCollectFiles(false)
66
+ ->setCollectRecursively(false);
67
+ $storageRootLength = strlen(Mage::helper('hankeme_chameleon')->getStorageRoot());
68
+
69
+ foreach ($collection as $key => $value) {
70
+ $rootChildParts = explode(DIRECTORY_SEPARATOR, substr($value->getFilename(), $storageRootLength));
71
+
72
+ if (array_key_exists($rootChildParts[0], $conditions['plain'])
73
+ || ($regExp && preg_match($regExp, $value->getFilename()))) {
74
+ $collection->removeItemByKey($key);
75
+ }
76
+ }
77
+
78
+ return $collection;
79
+ }
80
+
81
+
82
+ /**
83
+ * Return files
84
+ *
85
+ * @param string $path Parent directory path
86
+ * @param string $type Type of storage, e.g. image, media etc.
87
+ * @return Varien_Data_Collection_Filesystem
88
+ */
89
+ public function getFilesCollection($path, $type = null)
90
+ {
91
+ if (Mage::helper('core/file_storage_database')->checkDbUsage()) {
92
+ $files = Mage::getModel('core/file_storage_database')->getDirectoryFiles($path);
93
+
94
+ $fileStorageModel = Mage::getModel('core/file_storage_file');
95
+ foreach ($files as $file) {
96
+ $fileStorageModel->saveFile($file);
97
+ }
98
+ }
99
+
100
+ $collection = $this->getCollection($path)
101
+ ->setCollectDirs(false)
102
+ ->setCollectFiles(true)
103
+ ->setCollectRecursively(false)
104
+ ->setOrder('mtime', Varien_Data_Collection::SORT_ORDER_ASC);
105
+
106
+ // Add files extension filter
107
+ if ($allowed = $this->getAllowedExtensions($type)) {
108
+ $collection->setFilesFilter('/\.(' . implode('|', $allowed). ')$/i');
109
+ }
110
+
111
+ $helper = $this->getHelper();
112
+
113
+ // prepare items
114
+ foreach ($collection as $item) {
115
+ $item->setId($helper->idEncode($item->getBasename()));
116
+ $item->setName($item->getBasename());
117
+ $item->setShortName($helper->getShortFilename($item->getBasename()));
118
+ $item->setUrl($helper->getCurrentUrl() . $item->getBasename());
119
+
120
+ if ($this->isImage($item->getBasename())) {
121
+ $thumbUrl = $this->getThumbnailUrl($item->getFilename(), true);
122
+ // generate thumbnail "on the fly" if it does not exists
123
+ if(! $thumbUrl) {
124
+ $thumbUrl = Mage::getSingleton('adminhtml/url')->getUrl('*/*/thumbnail', array('file' => $item->getId()));
125
+ }
126
+
127
+ $size = @getimagesize($item->getFilename());
128
+
129
+ if (is_array($size)) {
130
+ $item->setWidth($size[0]);
131
+ $item->setHeight($size[1]);
132
+ }
133
+ } else {
134
+ //$thumbUrl = Mage::getDesign()->getSkinBaseUrl() . self::THUMB_PLACEHOLDER_PATH_SUFFIX;
135
+ $thumbUrl = false;
136
+ }
137
+
138
+ $item->setThumbUrl($thumbUrl);
139
+ }
140
+
141
+ return $collection;
142
+ }
143
+
144
+
145
+ public function getCollection($path = null)
146
+ {
147
+ $collection = Mage::getModel('hankeme_chameleon/skin_storage_collection');
148
+
149
+ if ($path !== null) {
150
+ $collection->addTargetDir($path);
151
+ }
152
+ return $collection;
153
+ }
154
+
155
+ public function getConfig()
156
+ {
157
+ if (! $this->_config) {
158
+ $this->_config = Mage::getConfig()->getNode('css/browser', 'adminhtml');
159
+ }
160
+
161
+ return $this->_config;
162
+ }
163
+
164
+ /**
165
+ * Prepare allowed_extensions config settings
166
+ *
167
+ * @param string $type Type of storage, e.g. image, media etc.
168
+ * @return array Array of allowed file extensions
169
+ */
170
+ public function getAllowedExtensions($type = null)
171
+ {
172
+ $extensions = $this->getConfigData('extensions');
173
+
174
+ if (is_string($type) && array_key_exists("{$type}_allowed", $extensions)) {
175
+ $allowed = $extensions["{$type}_allowed"];
176
+ } else {
177
+ $allowed = $extensions['allowed'];
178
+ }
179
+
180
+ return array_keys(array_filter($allowed));
181
+ }
182
+
183
+ public function getSession()
184
+ {
185
+ return Mage::getSingleton('adminhtml/session');
186
+ }
187
+
188
+ public function getHelper()
189
+ {
190
+ return Mage::helper('hankeme_chameleon');
191
+ }
192
+
193
+ /**
194
+ * Simple way to check whether file is image or not based on extension
195
+ *
196
+ * @param string $filename
197
+ * @return bool
198
+ */
199
+ public function isImage($filename)
200
+ {
201
+ if (!$this->hasData('_image_extensions')) {
202
+ $this->setData('_image_extensions', $this->getAllowedExtensions('image'));
203
+ }
204
+ $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
205
+ return in_array($ext, $this->_getData('_image_extensions'));
206
+ }
207
+
208
+ /**
209
+ * Config object as array getter
210
+ *
211
+ * @return array
212
+ */
213
+ public function getConfigAsArray()
214
+ {
215
+ if (! $this->_configAsArray) {
216
+ $this->_configAsArray = $this->getConfig()->asCanonicalArray();
217
+ }
218
+
219
+ return $this->_configAsArray;
220
+ }
221
+
222
+ /**
223
+ * Wysiwyg Config reader
224
+ *
225
+ * @param string $key
226
+ * @param mixed $default
227
+ * @return mixed
228
+ */
229
+ public function getConfigData($key, $default=false)
230
+ {
231
+ $configArray = $this->getConfigAsArray();
232
+ $key = (string) $key;
233
+
234
+ return array_key_exists($key, $configArray) ? $configArray[$key] : $default;
235
+ }
236
+ }
app/code/community/Hankeme/Chameleon/Model/Skin/Storage/Collection.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * HANKEME
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
8
+ * See http://opensource.org/licenses/osl-3.0.php for Details
9
+ * In case of questions regarding the use of this source file please
10
+ refer to the contact below.
11
+ *
12
+ * @project: [HANKEME Chameleon]
13
+ * @contact: info@hankeme.de
14
+ * @collaborators: [strohmeier]
15
+ */
16
+ class Hankeme_Chameleon_Model_Skin_Storage_Collection extends Varien_Data_Collection_Filesystem
17
+ {
18
+ protected function _generateRow($filename)
19
+ {
20
+ $filename = preg_replace('~[/\\\]+~', DIRECTORY_SEPARATOR, $filename);
21
+
22
+ return array(
23
+ 'filename' => $filename,
24
+ 'basename' => basename($filename),
25
+ 'mtime' => filemtime($filename)
26
+ );
27
+ }
28
+ }
app/code/community/Hankeme/Chameleon/controllers/Adminhtml/Chameleon/DesignController.php ADDED
@@ -0,0 +1,186 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * HANKEME
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
9
+ * See http://opensource.org/licenses/osl-3.0.php for Details
10
+ * In case of questions regarding the use of this source file please
11
+ refer to the contact below.
12
+ *
13
+ * @project: [HANKEME Chameleon]
14
+ * @contact: info@hankeme.de
15
+ * @collaborators: [strohmeier]
16
+ */
17
+
18
+ class Hankeme_Chameleon_Adminhtml_Chameleon_DesignController extends Mage_Adminhtml_Controller_Action
19
+ {
20
+
21
+ protected function _initAction()
22
+ {
23
+
24
+ $this->getStorage();
25
+ return $this;
26
+ }
27
+
28
+ public function indexAction()
29
+ {
30
+
31
+ $storeId = (int) $this->getRequest()->getParam('store');
32
+
33
+ $this->loadLayout();
34
+
35
+ $block = $this->getLayout()->getBlock('design_edit');
36
+ if ($block) {
37
+ $block->setStoreId($storeId);
38
+ }
39
+ $blocktree = $this->getLayout()->getBlock('design_tree');
40
+ if ($blocktree) {
41
+ $blocktree->setStoreId($storeId);
42
+ }
43
+
44
+ $this->renderLayout();
45
+ }
46
+
47
+ public function treeJsonAction()
48
+ {
49
+ try {
50
+
51
+ $storeId = (int) $this->getRequest()->getParam('store');
52
+ if(!$storeId) $this->getResponse()->setBody(Mage::helper('core')->jsonEncode(array()));
53
+
54
+ $this->_initAction();
55
+ $this->getResponse()->setBody(
56
+ $this->getLayout()->createBlock('hankeme_chameleon/adminhtml_design_tree')->setStoreId($storeId)
57
+ ->getTreeJson()
58
+ );
59
+ } catch (Exception $e) {
60
+ $this->getResponse()->setBody(Mage::helper('core')->jsonEncode(array()));
61
+ }
62
+ }
63
+
64
+ public function contentsAction()
65
+ {
66
+ try {
67
+ $this->_initAction()->_saveSessionCurrentPath();
68
+ $this->loadLayout('empty');
69
+ $this->renderLayout();
70
+ } catch (Exception $e) {
71
+ $result = array('error' => true, 'message' => $e->getMessage());
72
+ $this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
73
+ }
74
+ }
75
+
76
+ public function getStorage()
77
+ {
78
+ if (!Mage::registry('design_storage')) {
79
+ $storage = Mage::getModel('hankeme_chameleon/design_storage');
80
+ Mage::register('design_storage', $storage);
81
+ }
82
+ return Mage::registry('design_storage');
83
+ }
84
+
85
+ protected function _saveSessionCurrentPath()
86
+ {
87
+ $this->getStorage()
88
+ ->getSession()
89
+ ->setCurrentPath(Mage::helper('hankeme_chameleon/design')->getCurrentPath());
90
+ return $this;
91
+ }
92
+
93
+ /**
94
+ * Fire when select files
95
+ */
96
+ public function onInsertAction()
97
+ {
98
+ $helper = Mage::helper('hankeme_chameleon/design');
99
+ $storeId = $this->getRequest()->getParam('store');
100
+
101
+ $filename = $this->getRequest()->getParam('filename');
102
+ $filename = $helper->idDecode($filename);
103
+ $asIs = $this->getRequest()->getParam('as_is');
104
+
105
+ Mage::helper('catalog')->setStoreId($storeId);
106
+ $helper->setStoreId($storeId);
107
+
108
+ $data = $helper->getFileContents($filename, $asIs);
109
+ $this->getResponse()->setBody($data);
110
+ }
111
+
112
+ public function onBackupAction()
113
+ {
114
+ $helper = Mage::helper('hankeme_chameleon/design');
115
+ $storeId = $this->getRequest()->getParam('store');
116
+
117
+ $filename = $this->getRequest()->getParam('filename');
118
+ $filename = $helper->idDecode($filename);
119
+
120
+ $helper->setStoreId($storeId);
121
+ $data = $helper->createBackup($filename);
122
+ $this->getResponse()->setBody($data);
123
+ }
124
+
125
+ public function onSaveAction()
126
+ {
127
+ $helper = Mage::helper('hankeme_chameleon/design');
128
+ $storeId = $this->getRequest()->getParam('store');
129
+
130
+ $filename = $this->getRequest()->getParam('filename');
131
+ $filename = $helper->idDecode($filename);
132
+
133
+ $content = $this->getRequest()->getParam('content');
134
+
135
+ $helper->setStoreId($storeId);
136
+ $data = $helper->saveFileContent($filename, $content);
137
+ $this->getResponse()->setBody($data);
138
+ }
139
+
140
+ public function newFileAction()
141
+ {
142
+ $helper = Mage::helper('hankeme_chameleon/design');
143
+ $filename = $this->getRequest()->getParam('name');
144
+ $data = $helper->createFile($filename);
145
+ $this->getResponse()->setBody($data);
146
+ }
147
+
148
+ public function deleteFilesAction()
149
+ {
150
+ $helper = Mage::helper('hankeme_chameleon/design');
151
+ $storeId = $this->getRequest()->getParam('store');
152
+ $filename = $this->getRequest()->getParam('files');
153
+ $filename = $helper->idDecode($filename);
154
+ $helper->setStoreId($storeId);
155
+ $data = $helper->deleteFile($filename);
156
+ $this->getResponse()->setBody($data);
157
+ }
158
+
159
+ public function newFolderAction()
160
+ {
161
+ try {
162
+ $this->_initAction();
163
+ $name = $this->getRequest()->getPost('name');
164
+ $path = $this->getStorage()->getSession()->getCurrentPath();
165
+ $helper = Mage::helper('hankeme_chameleon/design');
166
+ $result = $helper->createDirectory($name, $path);
167
+ } catch (Exception $e) {
168
+ $result = array('error' => true, 'message' => $e->getMessage());
169
+ }
170
+ $this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
171
+ }
172
+
173
+ public function deleteFolderAction()
174
+ {
175
+ try {
176
+ $path = $this->getStorage()->getSession()->getCurrentPath();
177
+ $helper = Mage::helper('hankeme_chameleon/design');
178
+ $result = $helper->deleteDirectory($path);
179
+ } catch (Exception $e) {
180
+ $result = array('error' => true, 'message' => $e->getMessage());
181
+ $this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
182
+ }
183
+ $this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
184
+ }
185
+
186
+ }
app/code/community/Hankeme/Chameleon/controllers/Adminhtml/Chameleon/SkinController.php ADDED
@@ -0,0 +1,186 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * HANKEME
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
9
+ * See http://opensource.org/licenses/osl-3.0.php for Details
10
+ * In case of questions regarding the use of this source file please
11
+ refer to the contact below.
12
+ *
13
+ * @project: [HANKEME Chameleon]
14
+ * @contact: info@hankeme.de
15
+ * @collaborators: [strohmeier]
16
+ */
17
+
18
+ class Hankeme_Chameleon_Adminhtml_Chameleon_SkinController extends Mage_Adminhtml_Controller_Action
19
+ {
20
+
21
+ protected function _initAction()
22
+ {
23
+
24
+ $this->getStorage();
25
+ return $this;
26
+ }
27
+
28
+ public function indexAction()
29
+ {
30
+
31
+ $storeId = (int) $this->getRequest()->getParam('store');
32
+
33
+ $this->loadLayout();
34
+
35
+ $block = $this->getLayout()->getBlock('skin_edit');
36
+ if ($block) {
37
+ $block->setStoreId($storeId);
38
+ }
39
+ $blocktree = $this->getLayout()->getBlock('skin_tree');
40
+ if ($blocktree) {
41
+ $blocktree->setStoreId($storeId);
42
+ }
43
+
44
+ $this->renderLayout();
45
+ }
46
+
47
+ public function treeJsonAction()
48
+ {
49
+ try {
50
+
51
+ $storeId = (int) $this->getRequest()->getParam('store');
52
+ if(!$storeId) $this->getResponse()->setBody(Mage::helper('core')->jsonEncode(array()));
53
+
54
+ $this->_initAction();
55
+ $this->getResponse()->setBody(
56
+ $this->getLayout()->createBlock('hankeme_chameleon/adminhtml_skin_tree')->setStoreId($storeId)
57
+ ->getTreeJson()
58
+ );
59
+ } catch (Exception $e) {
60
+ $this->getResponse()->setBody(Mage::helper('core')->jsonEncode(array()));
61
+ }
62
+ }
63
+
64
+ public function contentsAction()
65
+ {
66
+ try {
67
+ $this->_initAction()->_saveSessionCurrentPath();
68
+ $this->loadLayout('empty');
69
+ $this->renderLayout();
70
+ } catch (Exception $e) {
71
+ $result = array('error' => true, 'message' => $e->getMessage());
72
+ $this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
73
+ }
74
+ }
75
+
76
+ public function getStorage()
77
+ {
78
+ if (!Mage::registry('skin_storage')) {
79
+ $storage = Mage::getModel('hankeme_chameleon/skin_storage');
80
+ Mage::register('skin_storage', $storage);
81
+ }
82
+ return Mage::registry('skin_storage');
83
+ }
84
+
85
+ protected function _saveSessionCurrentPath()
86
+ {
87
+ $this->getStorage()
88
+ ->getSession()
89
+ ->setCurrentPath(Mage::helper('hankeme_chameleon')->getCurrentPath());
90
+ return $this;
91
+ }
92
+
93
+ /**
94
+ * Fire when select files
95
+ */
96
+ public function onInsertAction()
97
+ {
98
+ $helper = Mage::helper('hankeme_chameleon');
99
+ $storeId = $this->getRequest()->getParam('store');
100
+
101
+ $filename = $this->getRequest()->getParam('filename');
102
+ $filename = $helper->idDecode($filename);
103
+ $asIs = $this->getRequest()->getParam('as_is');
104
+
105
+ Mage::helper('catalog')->setStoreId($storeId);
106
+ $helper->setStoreId($storeId);
107
+
108
+ $data = $helper->getFileContents($filename, $asIs);
109
+ $this->getResponse()->setBody($data);
110
+ }
111
+
112
+ public function onBackupAction()
113
+ {
114
+ $helper = Mage::helper('hankeme_chameleon');
115
+ $storeId = $this->getRequest()->getParam('store');
116
+
117
+ $filename = $this->getRequest()->getParam('filename');
118
+ $filename = $helper->idDecode($filename);
119
+
120
+ $helper->setStoreId($storeId);
121
+ $data = $helper->createBackup($filename);
122
+ $this->getResponse()->setBody($data);
123
+ }
124
+
125
+ public function onSaveAction()
126
+ {
127
+ $helper = Mage::helper('hankeme_chameleon');
128
+ $storeId = $this->getRequest()->getParam('store');
129
+
130
+ $filename = $this->getRequest()->getParam('filename');
131
+ $filename = $helper->idDecode($filename);
132
+
133
+ $content = $this->getRequest()->getParam('content');
134
+
135
+ $helper->setStoreId($storeId);
136
+ $data = $helper->saveFileContent($filename, $content);
137
+ $this->getResponse()->setBody($data);
138
+ }
139
+
140
+ public function newFileAction()
141
+ {
142
+ $helper = Mage::helper('hankeme_chameleon');
143
+ $filename = $this->getRequest()->getParam('name');
144
+ $data = $helper->createFile($filename);
145
+ $this->getResponse()->setBody($data);
146
+ }
147
+
148
+ public function deleteFilesAction()
149
+ {
150
+ $helper = Mage::helper('hankeme_chameleon');
151
+ $storeId = $this->getRequest()->getParam('store');
152
+ $filename = $this->getRequest()->getParam('files');
153
+ $filename = $helper->idDecode($filename);
154
+ $helper->setStoreId($storeId);
155
+ $data = $helper->deleteFile($filename);
156
+ $this->getResponse()->setBody($data);
157
+ }
158
+
159
+ public function newFolderAction()
160
+ {
161
+ try {
162
+ $this->_initAction();
163
+ $name = $this->getRequest()->getPost('name');
164
+ $path = $this->getStorage()->getSession()->getCurrentPath();
165
+ $helper = Mage::helper('hankeme_chameleon');
166
+ $result = $helper->createDirectory($name, $path);
167
+ } catch (Exception $e) {
168
+ $result = array('error' => true, 'message' => $e->getMessage());
169
+ }
170
+ $this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
171
+ }
172
+
173
+ public function deleteFolderAction()
174
+ {
175
+ try {
176
+ $path = $this->getStorage()->getSession()->getCurrentPath();
177
+ $helper = Mage::helper('hankeme_chameleon');
178
+ $result = $helper->deleteDirectory($path);
179
+ } catch (Exception $e) {
180
+ $result = array('error' => true, 'message' => $e->getMessage());
181
+ $this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
182
+ }
183
+ $this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
184
+ }
185
+
186
+ }
app/code/community/Hankeme/Chameleon/controllers/Adminhtml/ChameleonController.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * HANKEME
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
8
+ * See http://opensource.org/licenses/osl-3.0.php for Details
9
+ * In case of questions regarding the use of this source file please
10
+ refer to the contact below.
11
+ *
12
+ * @project: [HANKEME Chameleon]
13
+ * @contact: info@hankeme.de
14
+ * @collaborators: [strohmeier]
15
+ */
16
+ class Hankeme_Chameleon_Adminhtml_ChameleonController extends Mage_Adminhtml_Controller_Action
17
+ {
18
+
19
+ public function indexAction()
20
+ {
21
+ $this->loadLayout();
22
+ $this->renderLayout();
23
+ }
24
+
25
+ }
app/code/community/Hankeme/Chameleon/etc/adminhtml.xml ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * HANKEME
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
9
+ * See http://opensource.org/licenses/osl-3.0.php for Details
10
+ * In case of questions regarding the use of this source file please
11
+ refer to the contact below.
12
+ *
13
+ * @project: [HANKEME Chameleon]
14
+ * @contact: info@hankeme.de
15
+ * @collaborators: [strohmeier]
16
+ */
17
+ -->
18
+ <config>
19
+ <menu>
20
+ <chameleon translate="title" module="hankeme_chameleon">
21
+ <title>Template Editor</title>
22
+ <sort_order>999</sort_order>
23
+ <children>
24
+ <skin translate="title" module="hankeme_chameleon">
25
+ <title>Skin Files</title>
26
+ <action>adminhtml/chameleon_skin/index</action>
27
+ <sort_order>0</sort_order>
28
+ </skin>
29
+ <design translate="title" module="hankeme_chameleon">
30
+ <title>Template &amp; Layout Files</title>
31
+ <action>adminhtml/chameleon_design/index</action>
32
+ <sort_order>1</sort_order>
33
+ </design>
34
+ </children>
35
+ </chameleon>
36
+ </menu>
37
+ </config>
app/code/community/Hankeme/Chameleon/etc/config.xml ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * HANKEME
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
9
+ * See http://opensource.org/licenses/osl-3.0.php for Details
10
+ * In case of questions regarding the use of this source file please
11
+ refer to the contact below.
12
+ *
13
+ * @project: [HANKEME Chameleon]
14
+ * @contact: info@hankeme.de
15
+ * @collaborators: [strohmeier]
16
+ */
17
+ -->
18
+ <config>
19
+ <modules>
20
+ <Hankeme_Chameleon>
21
+ <version>0.1.0</version>
22
+ </Hankeme_Chameleon>
23
+ </modules>
24
+ <global>
25
+ <models>
26
+ <hankeme_chameleon>
27
+ <class>Hankeme_Chameleon_Model</class>
28
+ <resourceModel>hankeme_chameleon_resource_eav_mysql4</resourceModel>
29
+ </hankeme_chameleon>
30
+ </models>
31
+ <helpers>
32
+ <chameleon><class>Hankeme_Chameleon_Helper</class></chameleon>
33
+ <hankeme_chameleon><class>Hankeme_Chameleon_Helper</class></hankeme_chameleon>
34
+ </helpers>
35
+ <blocks>
36
+ <hankeme_chameleon>
37
+ <class>Hankeme_Chameleon_Block</class>
38
+ </hankeme_chameleon>
39
+ </blocks>
40
+ <resources>
41
+ <chameleon_setup>
42
+ <connection>
43
+ <use>core_setup</use>
44
+ </connection>
45
+ </chameleon_setup>
46
+ <chameleon_write>
47
+ <connection>
48
+ <use>core_write</use>
49
+ </connection>
50
+ </chameleon_write>
51
+ <chameleon_read>
52
+ <connection>
53
+ <use>core_read</use>
54
+ </connection>
55
+ </chameleon_read>
56
+ </resources>
57
+ </global>
58
+ <adminhtml>
59
+ <acl>
60
+ <resources>
61
+ <admin>
62
+ <children>
63
+ <system>
64
+ <children>
65
+ <config>
66
+ <children>
67
+ <chameleon>
68
+ <title>Administer Hankeme_Chameleon</title>
69
+ </chameleon>
70
+ </children>
71
+ </config>
72
+ </children>
73
+ </system>
74
+ <chameleon translate="title" module="hankeme_chameleon"><!-- this tag matches the menu tag, and the same for his children -->
75
+ <title>Template Editor</title>
76
+ <children>
77
+ <skin>
78
+ <title>Access Skin Files</title>
79
+ </skin>
80
+ <design>
81
+ <title>Access Template &amp; Layout Files Files</title>
82
+ </design>
83
+ </children>
84
+ </chameleon>
85
+ </children>
86
+ </admin>
87
+ </resources>
88
+ </acl>
89
+ <layout>
90
+ <updates>
91
+ <chameleon>
92
+ <file>hankeme_chameleon.xml</file>
93
+ </chameleon>
94
+ </updates>
95
+ </layout>
96
+ <translate>
97
+ <modules>
98
+ <Hankeme_Chameleon>
99
+ <files>
100
+ <default>Hankeme_Chameleon.csv</default>
101
+ </files>
102
+ </Hankeme_Chameleon>
103
+ </modules>
104
+ </translate>
105
+ <css>
106
+ <browser>
107
+ <dirs>
108
+ <exclude/>
109
+ <include/>
110
+ </dirs>
111
+ <extensions>
112
+ <allowed>
113
+ <sass>1</sass>
114
+ <txt>1</txt>
115
+ <css>1</css>
116
+ <js>1</js>
117
+ </allowed>
118
+ <image_allowed>
119
+ <jpg>1</jpg>
120
+ <jpeg>1</jpeg>
121
+ <png>1</png>
122
+ <gif>1</gif>
123
+ <ico>1</ico>
124
+ </image_allowed>
125
+ <media_allowed>
126
+ <flv>1</flv>
127
+ <swf>1</swf>
128
+ <avi>1</avi>
129
+ <mov>1</mov>
130
+ <rm>1</rm>
131
+ <wmv>1</wmv>
132
+ </media_allowed>
133
+ </extensions>
134
+ </browser>
135
+ </css>
136
+ <design>
137
+ <browser>
138
+ <dirs>
139
+ <exclude/>
140
+ <include/>
141
+ </dirs>
142
+ <extensions>
143
+ <allowed>
144
+ <xml>1</xml>
145
+ <phtml>1</phtml>
146
+ <txt>1</txt>
147
+ <html>1</html>
148
+ <csv>1</csv>
149
+ </allowed>
150
+ </extensions>
151
+ </browser>
152
+ </design>
153
+ </adminhtml>
154
+ <admin>
155
+ <routers>
156
+ <adminhtml>
157
+ <args>
158
+ <modules>
159
+ <hankeme_chameleon before="Mage_Adminhtml">Hankeme_Chameleon_Adminhtml</hankeme_chameleon>
160
+ </modules>
161
+ </args>
162
+ </adminhtml>
163
+ </routers>
164
+ </admin>
165
+ </config>
app/design/adminhtml/default/default/layout/hankeme_chameleon.xml ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * HANKEME
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
9
+ * See http://opensource.org/licenses/osl-3.0.php for Details
10
+ * In case of questions regarding the use of this source file please
11
+ refer to the contact below.
12
+ *
13
+ * @project: [HANKEME Chameleon]
14
+ * @contact: info@hankeme.de
15
+ * @collaborators: [strohmeier]
16
+ */
17
+ -->
18
+ <layout>
19
+ <adminhtml_chameleon_skin_index>
20
+ <reference name="head">
21
+ <action method="setTitle" translate="title"><title>Edit Skin Files</title></action>
22
+ <action method="addJs"><script>extjs/ext-tree.js</script></action>
23
+ <action method="addJs"><script>hankeme/chameleon/chameleon.js</script></action>
24
+ <action method="addItem"><type>js_css</type><name>extjs/resources/css/ext-all.css</name><params/></action>
25
+ <action method="addItem"><type>js_css</type><name>extjs/resources/css/ytheme-magento.css</name><params/></action>
26
+ <action method="addCss"><name>hankeme/chameleon.css</name></action>
27
+ </reference>
28
+ <reference name="left">
29
+ <block type="adminhtml/store_switcher" name="store_switcher" before="-"></block>
30
+ <block type="hankeme_chameleon/adminhtml_skin_tree" name="skin_tree" template="hankeme/chameleon/skin/tree.phtml"></block>
31
+ </reference>
32
+ <reference name="content">
33
+ <block type="hankeme_chameleon/adminhtml_skin_edit" name="skin_edit" template="hankeme/chameleon/skin/edit.phtml"></block>
34
+ </reference>
35
+ </adminhtml_chameleon_skin_index>
36
+
37
+ <adminhtml_chameleon_skin_contents>
38
+ <block name="chameleon.skin.files" type="hankeme_chameleon/adminhtml_skin_edit_files" template="hankeme/chameleon/skin/edit/files.phtml" output="toHtml" />
39
+ </adminhtml_chameleon_skin_contents>
40
+
41
+ <adminhtml_chameleon_design_index>
42
+ <reference name="head">
43
+ <action method="setTitle" translate="title"><title>Edit Layout and Template Files</title></action>
44
+ <action method="addJs"><script>extjs/ext-tree.js</script></action>
45
+ <action method="addJs"><script>hankeme/chameleon/chameleon.js</script></action>
46
+ <action method="addItem"><type>js_css</type><name>extjs/resources/css/ext-all.css</name><params/></action>
47
+ <action method="addItem"><type>js_css</type><name>extjs/resources/css/ytheme-magento.css</name><params/></action>
48
+ <action method="addCss"><name>hankeme/chameleon.css</name></action>
49
+ </reference>
50
+ <reference name="left">
51
+ <block type="adminhtml/store_switcher" name="store_switcher" before="-"></block>
52
+ <block type="hankeme_chameleon/adminhtml_design_tree" name="design_tree" template="hankeme/chameleon/design/tree.phtml"></block>
53
+ </reference>
54
+ <reference name="content">
55
+ <block type="hankeme_chameleon/adminhtml_design_edit" name="design_edit" template="hankeme/chameleon/design/edit.phtml"></block>
56
+ </reference>
57
+ </adminhtml_chameleon_design_index>
58
+
59
+ <adminhtml_chameleon_design_contents>
60
+ <block name="chameleon.design.files" type="hankeme_chameleon/adminhtml_design_edit_files" template="hankeme/chameleon/design/edit/files.phtml" output="toHtml" />
61
+ </adminhtml_chameleon_design_contents>
62
+ </layout>
app/design/adminhtml/default/default/template/hankeme/chameleon/design/edit.phtml ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * HANKEME
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
8
+ * See http://opensource.org/licenses/osl-3.0.php for Details
9
+ * In case of questions regarding the use of this source file please
10
+ refer to the contact below.
11
+ *
12
+ * @project: [HANKEME Chameleon]
13
+ * @contact: info@hankeme.de
14
+ * @collaborators: [strohmeier]
15
+ */
16
+ ?>
17
+ <script type="text/javascript">
18
+ //<![CDATA[
19
+ MediabrowserInstance = new Mediabrowser(<?php echo $this->getFilebrowserSetupObject() ?>);
20
+ MediabrowserInstance.storeId = '<?php echo $this->getStoreId() ?>';
21
+ //]]>
22
+ </script>
23
+ <div class="content-header skip-header" id="content_header">
24
+ <table cellspacing="0">
25
+ <tr>
26
+ <td><h3 id="content_header_text"><?php echo $this->getHeaderText() ?></h3></td>
27
+ <td class="form-buttons">
28
+ <?php echo $this->getButtonsHtml() ?>
29
+ </td>
30
+ </tr>
31
+ </table>
32
+ </div>
33
+ <div id="contents" class="chameleon_content_list"></div>
34
+ <div class="chameleon_hint"><small><?php echo $this->getFiletypeNotice();?></small></div>
35
+ <div id="chameleon_action_buttons" class="form-buttons">
36
+ <?php echo $this->getActionButtonsHtml() ?>
37
+ </div>
38
+ <textarea id="<?php echo $this->getTargetElementId(); ?>" class="chameleon_content_stage" style="display:none"></textarea>
app/design/adminhtml/default/default/template/hankeme/chameleon/design/edit/files.phtml ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * HANKEME
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
8
+ * See http://opensource.org/licenses/osl-3.0.php for Details
9
+ * In case of questions regarding the use of this source file please
10
+ refer to the contact below.
11
+ *
12
+ * @project: [HANKEME Chameleon]
13
+ * @contact: info@hankeme.de
14
+ * @collaborators: [strohmeier]
15
+ */
16
+ ?>
17
+ <?php if ($this->getFilesCount() > 0): ?>
18
+ <ul class="fileslist">
19
+ <?php foreach ($this->getFiles() as $file): ?>
20
+ <li>
21
+ <div class="filecnt chameleon-type-<?php echo $this->getFileType($file);?>" id="<?php echo $this->getFileId($file) ?>"></div>
22
+ <small><?php echo $this->getFileName($file); ?></small>
23
+ </li>
24
+ <?php endforeach; ?>
25
+ </ul>
26
+ <?php else: ?>
27
+ <?php echo $this->helper('cms')->__('No files found') ?>
28
+ <?php endif; ?>
app/design/adminhtml/default/default/template/hankeme/chameleon/design/tree.phtml ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * HANKEME
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
8
+ * See http://opensource.org/licenses/osl-3.0.php for Details
9
+ * In case of questions regarding the use of this source file please
10
+ refer to the contact below.
11
+ *
12
+ * @project: [HANKEME Chameleon]
13
+ * @contact: info@hankeme.de
14
+ * @collaborators: [strohmeier]
15
+ */
16
+ ?>
17
+
18
+ <div class="chameleon-side-col">
19
+ <?php echo $this->getStoreSwitcherHtml();?>
20
+ <div class="tree-actions">
21
+ <a href="#" id="tree_action_collapse"><?php echo $this->__('Collapse All'); ?></a>
22
+ <span class="separator">|</span>
23
+ <a href="#" id="tree_action_expand"><?php echo $this->__('Expand All'); ?></a>
24
+ </div>
25
+ <div id="tree" style="width:100%; overflow:auto;"></div>
26
+
27
+ <script type="text/javascript">
28
+ Ext.onReady(function(){
29
+ var Tree = Ext.tree;
30
+ var tree = new Tree.TreePanel('tree', {
31
+ animate:true,
32
+ loader: new Tree.TreeLoader({
33
+ dataUrl:'<?php echo $this->getTreeLoaderUrl() ?>'
34
+ }),
35
+ enableDD:false,
36
+ containerScroll: true
37
+ });
38
+
39
+ // set the root node
40
+ var root = new Tree.AsyncTreeNode({
41
+ text: '<?php echo $this->getRootNodeName() ?>',
42
+ draggable:false,
43
+ id:'root'
44
+ });
45
+ tree.setRootNode(root);
46
+
47
+ // render the tree
48
+ tree.render();
49
+ root.expand();
50
+
51
+ Event.observe($('tree_action_collapse'), 'click', function(){
52
+ tree.collapseAll();
53
+ });
54
+
55
+ Event.observe($('tree_action_expand'), 'click', function(){
56
+ tree.expandAll();
57
+ });
58
+
59
+ MediabrowserInstance.setTree(tree);
60
+ tree.addListener('click', MediabrowserInstance.selectFolder.bind(MediabrowserInstance));
61
+ tree.expandPath('<?php echo $this->getTreeCurrentPath() ?>','', function(success, node) {
62
+ MediabrowserInstance.selectFolder(node);
63
+ });
64
+ });
65
+ </script>
66
+ </div>
app/design/adminhtml/default/default/template/hankeme/chameleon/skin/edit.phtml ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * HANKEME
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
8
+ * See http://opensource.org/licenses/osl-3.0.php for Details
9
+ * In case of questions regarding the use of this source file please
10
+ refer to the contact below.
11
+ *
12
+ * @project: [HANKEME Chameleon]
13
+ * @contact: info@hankeme.de
14
+ * @collaborators: [strohmeier]
15
+ */
16
+ ?>
17
+ <script type="text/javascript">
18
+ //<![CDATA[
19
+ MediabrowserInstance = new Mediabrowser(<?php echo $this->getFilebrowserSetupObject() ?>);
20
+ MediabrowserInstance.storeId = '<?php echo $this->getStoreId() ?>';
21
+ //]]>
22
+ </script>
23
+ <div class="content-header skip-header" id="content_header">
24
+ <table cellspacing="0">
25
+ <tr>
26
+ <td><h3 id="content_header_text"><?php echo $this->getHeaderText() ?></h3></td>
27
+ <td class="form-buttons">
28
+ <?php echo $this->getButtonsHtml() ?>
29
+ </td>
30
+ </tr>
31
+ </table>
32
+ </div>
33
+ <div id="contents" class="chameleon_content_list"></div>
34
+ <div class="chameleon_hint"><small><?php echo $this->getFiletypeNotice();?></small></div>
35
+ <div id="chameleon_action_buttons" class="form-buttons">
36
+ <?php echo $this->getActionButtonsHtml() ?>
37
+ </div>
38
+ <textarea id="<?php echo $this->getTargetElementId(); ?>" class="chameleon_content_stage" style="display:none"></textarea>
app/design/adminhtml/default/default/template/hankeme/chameleon/skin/edit/files.phtml ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * HANKEME
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
8
+ * See http://opensource.org/licenses/osl-3.0.php for Details
9
+ * In case of questions regarding the use of this source file please
10
+ refer to the contact below.
11
+ *
12
+ * @project: [HANKEME Chameleon]
13
+ * @contact: info@hankeme.de
14
+ * @collaborators: [strohmeier]
15
+ */
16
+ ?>
17
+ <?php if ($this->getFilesCount() > 0): ?>
18
+ <ul class="fileslist">
19
+ <?php foreach ($this->getFiles() as $file): ?>
20
+ <li>
21
+ <div class="filecnt chameleon-type-<?php echo $this->getFileType($file);?>" id="<?php echo $this->getFileId($file) ?>"></div>
22
+ <small><?php echo $this->getFileName($file); ?></small>
23
+ </li>
24
+ <?php endforeach; ?>
25
+ </ul>
26
+ <?php else: ?>
27
+ <?php echo $this->helper('cms')->__('No files found') ?>
28
+ <?php endif; ?>
app/design/adminhtml/default/default/template/hankeme/chameleon/skin/tree.phtml ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * HANKEME
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
8
+ * See http://opensource.org/licenses/osl-3.0.php for Details
9
+ * In case of questions regarding the use of this source file please
10
+ refer to the contact below.
11
+ *
12
+ * @project: [HANKEME Chameleon]
13
+ * @contact: info@hankeme.de
14
+ * @collaborators: [strohmeier]
15
+ */
16
+ ?>
17
+
18
+ <div class="chameleon-side-col">
19
+ <?php echo $this->getStoreSwitcherHtml();?>
20
+ <div class="tree-actions">
21
+ <a href="#" id="tree_action_collapse"><?php echo $this->__('Collapse All'); ?></a>
22
+ <span class="separator">|</span>
23
+ <a href="#" id="tree_action_expand"><?php echo $this->__('Expand All'); ?></a>
24
+ </div>
25
+ <div id="tree" style="width:100%; overflow:auto;"></div>
26
+
27
+ <script type="text/javascript">
28
+ Ext.onReady(function(){
29
+ var Tree = Ext.tree;
30
+ var tree = new Tree.TreePanel('tree', {
31
+ animate:true,
32
+ loader: new Tree.TreeLoader({
33
+ dataUrl:'<?php echo $this->getTreeLoaderUrl() ?>'
34
+ }),
35
+ enableDD:false,
36
+ containerScroll: true
37
+ });
38
+
39
+ // set the root node
40
+ var root = new Tree.AsyncTreeNode({
41
+ text: '<?php echo $this->getRootNodeName() ?>',
42
+ draggable:false,
43
+ id:'root'
44
+ });
45
+ tree.setRootNode(root);
46
+
47
+ // render the tree
48
+ tree.render();
49
+ root.expand();
50
+
51
+ Event.observe($('tree_action_collapse'), 'click', function(){
52
+ tree.collapseAll();
53
+ });
54
+
55
+ Event.observe($('tree_action_expand'), 'click', function(){
56
+ tree.expandAll();
57
+ });
58
+
59
+ MediabrowserInstance.setTree(tree);
60
+ tree.addListener('click', MediabrowserInstance.selectFolder.bind(MediabrowserInstance));
61
+ tree.expandPath('<?php echo $this->getTreeCurrentPath() ?>','', function(success, node) {
62
+ MediabrowserInstance.selectFolder(node);
63
+ });
64
+ });
65
+ </script>
66
+ </div>
app/etc/modules/Hankeme_Chameleon.xml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Hankeme_Chameleon>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ </Hankeme_Chameleon>
8
+ </modules>
9
+ </config>
js/hankeme/chameleon/chameleon.js ADDED
@@ -0,0 +1,545 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * HANKEME
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
7
+ * See http://opensource.org/licenses/osl-3.0.php for Details
8
+ * In case of questions regarding the use of this source file please
9
+ refer to the contact below.
10
+ *
11
+ * @project: [HANKEME Chameleon]
12
+ * @contact: info@hankeme.de
13
+ * @collaborators: [strohmeier]
14
+ */
15
+
16
+ /* Based on magento core browser.js */
17
+
18
+
19
+ MediabrowserUtility = {
20
+ openDialog: function(url, width, height, title) {
21
+ if ($('browser_window') && typeof(Windows) != 'undefined') {
22
+ Windows.focus('browser_window');
23
+ return;
24
+ }
25
+ this.dialogWindow = Dialog.info(null, {
26
+ closable: true,
27
+ resizable: false,
28
+ draggable: true,
29
+ className: 'magento',
30
+ windowClassName: 'popup-window',
31
+ title: title || 'Insert File...',
32
+ top: 50,
33
+ width: width || 950,
34
+ height: height || 600,
35
+ zIndex: 1000,
36
+ recenterAuto: false,
37
+ hideEffect: Element.hide,
38
+ showEffect: Element.show,
39
+ id: 'browser_window',
40
+ onClose: this.closeDialog.bind(this)
41
+ });
42
+ new Ajax.Updater('modal_dialog_message', url, {evalScripts: true});
43
+ },
44
+ closeDialog: function(window) {
45
+ if (!window) {
46
+ window = this.dialogWindow;
47
+ }
48
+ if (window) {
49
+ // IE fix - hidden form select fields after closing dialog
50
+ WindowUtilities._showSelect();
51
+ window.close();
52
+ }
53
+ }
54
+ };
55
+
56
+ Mediabrowser = Class.create();
57
+ Mediabrowser.prototype = {
58
+ targetElementId: null,
59
+ contentsUrl: null,
60
+ onInsertUrl: null,
61
+ newFolderUrl: null,
62
+ deleteFolderUrl: null,
63
+ deleteFilesUrl: null,
64
+ headerText: null,
65
+ tree: null,
66
+ currentNode: null,
67
+ storeId: null,
68
+ initialize: function (setup) {
69
+ this.newFolderPrompt = setup.newFolderPrompt;
70
+ this.newFilePrompt = setup.newFilePrompt;
71
+ this.deleteFolderConfirmationMessage = setup.deleteFolderConfirmationMessage;
72
+ this.deleteFileConfirmationMessage = setup.deleteFileConfirmationMessage;
73
+ this.targetElementId = setup.targetElementId;
74
+ this.contentsUrl = setup.contentsUrl;
75
+ this.onInsertUrl = setup.onInsertUrl;
76
+ this.onSaveUrl = setup.onSaveUrl;
77
+ this.newFolderUrl = setup.newFolderUrl;
78
+ this.newFileUrl = setup.newFileUrl;
79
+ this.deleteFolderUrl = setup.deleteFolderUrl;
80
+ this.deleteFilesUrl = setup.deleteFilesUrl;
81
+ this.headerText = setup.headerText;
82
+ this.onBackupUrl = setup.onBackupUrl;
83
+ },
84
+ setTree: function (tree) {
85
+ this.tree = tree;
86
+ this.currentNode = tree.getRootNode();
87
+ },
88
+
89
+ getTree: function (tree) {
90
+ return this.tree;
91
+ },
92
+
93
+ selectFolder: function (node, event) {
94
+
95
+ var targetEl = this.getTargetElement();
96
+
97
+ if(targetEl.hasClassName('onduty')) {
98
+ var confirmed = confirm('Are you sure? All unsaved Data will be overwritten.');
99
+ if(!confirmed) return false;
100
+ else {
101
+ targetEl.value='';
102
+ targetEl.removeClassName('onduty').hide();
103
+ this.hideActionButtons();
104
+ }
105
+ }
106
+
107
+ this.currentNode = node;
108
+ this.hideFileButtons();
109
+ this.activateBlock('contents');
110
+
111
+ if(node.id == 'root') {
112
+ this.hideElement('button_delete_folder');
113
+ } else {
114
+ this.showElement('button_delete_folder');
115
+ }
116
+
117
+ this.updateHeader(this.currentNode);
118
+ this.drawBreadcrumbs(this.currentNode);
119
+
120
+ this.showElement('loading-mask');
121
+ new Ajax.Request(this.contentsUrl, {
122
+ parameters: {node: this.currentNode.id},
123
+ evalJS: true,
124
+ onSuccess: function(transport) {
125
+ try {
126
+ this.currentNode.select();
127
+ this.onAjaxSuccess(transport);
128
+ this.hideElement('loading-mask');
129
+ if ($('contents') != undefined) {
130
+ $('contents').update(transport.responseText);
131
+ $$('div.filecnt').each(function(s) {
132
+ Event.observe(s.id, 'click', this.selectFile.bind(this));
133
+ //Event.observe(s.id, 'dblclick', this.insert.bind(this));
134
+ }.bind(this));
135
+ }
136
+ } catch(e) {
137
+ alert(e.message);
138
+ }
139
+ }.bind(this)
140
+ });
141
+ },
142
+
143
+ selectFolderById: function (nodeId) {
144
+ var node = this.tree.getNodeById(nodeId);
145
+ if (node.id) {
146
+ this.selectFolder(node);
147
+ }
148
+ },
149
+
150
+ selectFile: function (event) {
151
+ var div = Event.findElement(event, 'DIV');
152
+ $$('div.filecnt.selected[id!="' + div.id + '"]').each(function(e) {
153
+ e.removeClassName('selected');
154
+ })
155
+ div.toggleClassName('selected');
156
+ if(div.hasClassName('selected')) {
157
+ this.showFileButtons();
158
+ } else {
159
+ this.hideFileButtons();
160
+ }
161
+ },
162
+
163
+ showFileButtons: function () {
164
+ this.showElement('button_delete_files');
165
+ this.showElement('button_insert_files');
166
+ this.showElement('button_backup_files');
167
+ },
168
+
169
+ hideFileButtons: function () {
170
+ this.hideElement('button_delete_files');
171
+ this.hideElement('button_insert_files');
172
+ this.hideElement('button_backup_files');
173
+ },
174
+
175
+ showActionButtons: function () {
176
+ this.showElement('button_save_changes');
177
+ },
178
+
179
+ hideActionButtons: function () {
180
+ this.hideElement('button_save_changes');
181
+ },
182
+
183
+ handleUploadComplete: function(files) {
184
+ $$('div[class*="file-row complete"]').each(function(e) {
185
+ $(e.id).remove();
186
+ });
187
+ this.selectFolder(this.currentNode);
188
+ },
189
+
190
+ backup: function(event) {
191
+ var div;
192
+
193
+ $$('div.selected').each(function (e) {
194
+ div = $(e.id);
195
+ });
196
+
197
+ if ($(div.id) == undefined) {
198
+ return false;
199
+ }
200
+
201
+ var params = {filename:div.id, node:this.currentNode.id, store:this.storeId};
202
+
203
+ new Ajax.Request(this.onBackupUrl, {
204
+ parameters: params,
205
+ onSuccess: function(transport) {
206
+ try {
207
+ this.onAjaxSuccess(transport);
208
+ alert(transport.responseText);
209
+ } catch (e) {
210
+ alert(e.message);
211
+ }
212
+ }.bind(this)
213
+ });
214
+
215
+ this.selectFolder(this.currentNode);
216
+ },
217
+
218
+ insert: function(event) {
219
+ var div;
220
+ if (event != undefined) {
221
+ div = Event.findElement(event, 'DIV');
222
+ } else {
223
+ $$('div.selected').each(function (e) {
224
+ div = $(e.id);
225
+ });
226
+ }
227
+ if ($(div.id) == undefined) {
228
+ return false;
229
+ }
230
+ var targetEl = this.getTargetElement();
231
+
232
+ if(targetEl.hasClassName('onduty')) {
233
+ var confirmed = confirm('Are you sure? All unsaved Data will be overwritten.');
234
+ if(!confirmed) return false;
235
+ }
236
+
237
+ if (! targetEl) {
238
+ alert("Target element not found for content update");
239
+ Windows.close('browser_window');
240
+ return;
241
+ }
242
+
243
+ var params = {filename:div.id, node:this.currentNode.id, store:this.storeId};
244
+
245
+ if (targetEl.tagName.toLowerCase() == 'textarea') {
246
+ params.as_is = 1;
247
+ }
248
+
249
+ new Ajax.Request(this.onInsertUrl, {
250
+ parameters: params,
251
+ onSuccess: function(transport) {
252
+ try {
253
+ this.onAjaxSuccess(transport);
254
+ if (this.getMediaBrowserOpener()) {
255
+ self.blur();
256
+ }
257
+ Windows.close('browser_window');
258
+ targetEl.show();
259
+ $$('div.active').each(function (e) {
260
+ e.removeClassName('active');
261
+ });
262
+ $$('div.selected').each(function (e) {
263
+ e.addClassName('active');
264
+ });
265
+
266
+ this.showActionButtons();
267
+
268
+ if (targetEl.tagName.toLowerCase() == 'input') {
269
+
270
+ targetEl.value = transport.responseText;
271
+
272
+ } else {
273
+
274
+ targetEl.value = transport.responseText;
275
+ targetEl.addClassName('onduty');
276
+
277
+ if (varienGlobalEvents) {
278
+ varienGlobalEvents.fireEvent('tinymceChange');
279
+ }
280
+ }
281
+ } catch (e) {
282
+ alert(e.message);
283
+ }
284
+ }.bind(this)
285
+ });
286
+ },
287
+
288
+ save: function(event) {
289
+
290
+ var div;
291
+ if (event != undefined) {
292
+ div = Event.findElement(event, 'DIV');
293
+ } else {
294
+ $$('div.selected').each(function (e) {
295
+ div = $(e.id);
296
+ });
297
+ }
298
+ if ($(div.id) == undefined) {
299
+ return false;
300
+ }
301
+
302
+ var targetEl = this.getTargetElement();
303
+
304
+ if (! targetEl) {
305
+ alert("Source element not found for content save");
306
+ Windows.close('browser_window');
307
+ return;
308
+ }
309
+
310
+ if(targetEl.hasClassName('onduty')) {
311
+
312
+ var params = {filename:div.id, node:this.currentNode.id, store:this.storeId, content:targetEl.value};
313
+
314
+ if (targetEl.tagName.toLowerCase() == 'textarea') {
315
+ params.as_is = 1;
316
+ }
317
+
318
+ new Ajax.Request(this.onSaveUrl, {
319
+ parameters: params,
320
+ onSuccess: function(transport) {
321
+ try {
322
+ this.onAjaxSuccess(transport);
323
+ if (this.getMediaBrowserOpener()) {
324
+ self.blur();
325
+ }
326
+ Windows.close('browser_window');
327
+ targetEl.show();
328
+
329
+ this.showActionButtons();
330
+
331
+ alert(transport.responseText);
332
+
333
+ } catch (e) {
334
+ alert(e.message);
335
+ }
336
+ }.bind(this)
337
+ });
338
+ }
339
+ },
340
+
341
+ /**
342
+ * Find document target element in next order:
343
+ * in acive file browser opener:
344
+ * - input field with ID: "src" in opener window
345
+ * - input field with ID: "href" in opener window
346
+ * in document:
347
+ * - element with target ID
348
+ *
349
+ * return HTMLelement | null
350
+ */
351
+ getTargetElement: function() {
352
+ if (typeof(tinyMCE) != 'undefined' && tinyMCE.get(this.targetElementId)) {
353
+ if ((opener = this.getMediaBrowserOpener())) {
354
+ var targetElementId = tinyMceEditors.get(this.targetElementId).getMediaBrowserTargetElementId();
355
+ return opener.document.getElementById(targetElementId);
356
+ } else {
357
+ return null;
358
+ }
359
+ } else {
360
+ return document.getElementById(this.targetElementId);
361
+ }
362
+ },
363
+
364
+ /**
365
+ * Return opener Window object if it exists, not closed and editor is active
366
+ *
367
+ * return object | null
368
+ */
369
+ getMediaBrowserOpener: function() {
370
+ if (typeof(tinyMCE) != 'undefined'
371
+ && tinyMCE.get(this.targetElementId)
372
+ && typeof(tinyMceEditors) != 'undefined'
373
+ && ! tinyMceEditors.get(this.targetElementId).getMediaBrowserOpener().closed) {
374
+ return tinyMceEditors.get(this.targetElementId).getMediaBrowserOpener();
375
+ } else {
376
+ return null;
377
+ }
378
+ },
379
+
380
+ newFolder: function() {
381
+ var folderName = prompt(this.newFolderPrompt);
382
+ if (!folderName) {
383
+ return false;
384
+ }
385
+ new Ajax.Request(this.newFolderUrl, {
386
+ parameters: {name: folderName},
387
+ onSuccess: function(transport) {
388
+ try {
389
+ this.onAjaxSuccess(transport);
390
+ if (transport.responseText.isJSON()) {
391
+ var response = transport.responseText.evalJSON()
392
+ var newNode = new Ext.tree.AsyncTreeNode({
393
+ text: response.short_name,
394
+ draggable:false,
395
+ id:response.id,
396
+ expanded: true
397
+ });
398
+ var child = this.currentNode.appendChild(newNode);
399
+ this.tree.expandPath(child.getPath(), '', function(success, node) {
400
+ this.selectFolder(node);
401
+ }.bind(this));
402
+ }
403
+ } catch (e) {
404
+ alert(e.message);
405
+ }
406
+ }.bind(this)
407
+ })
408
+ },
409
+
410
+ deleteFolder: function() {
411
+ if (!confirm(this.deleteFolderConfirmationMessage)) {
412
+ return false;
413
+ }
414
+ new Ajax.Request(this.deleteFolderUrl, {
415
+ onSuccess: function(transport) {
416
+ try {
417
+ this.onAjaxSuccess(transport);
418
+ var parent = this.currentNode.parentNode;
419
+ //parent.removeChild(this.currentNode);
420
+ this.selectFolder(parent);
421
+ alert(transport.responseText);
422
+ }
423
+ catch (e) {
424
+ alert(e.message);
425
+ }
426
+ }.bind(this)
427
+ })
428
+ },
429
+
430
+ createFile: function() {
431
+ var fileName = prompt(this.newFilePrompt);
432
+ if (!fileName) {
433
+ return false;
434
+ }
435
+
436
+ var params = {name:fileName, node:this.currentNode.id, store:this.storeId};
437
+
438
+ new Ajax.Request(this.newFileUrl, {
439
+ parameters: params,
440
+ onSuccess: function(transport) {
441
+ try {
442
+ this.onAjaxSuccess(transport);
443
+ this.selectFolder(this.currentNode);
444
+ alert(transport.responseText);
445
+ } catch (e) {
446
+ alert(e.message);
447
+ }
448
+ }.bind(this)
449
+ })
450
+ },
451
+
452
+ deleteFiles: function() {
453
+ if (!confirm(this.deleteFileConfirmationMessage)) {
454
+ return false;
455
+ }
456
+ var ids = [];
457
+ var i = 0;
458
+ $$('div.selected').each(function (e) {
459
+ ids[i] = e.id;
460
+ i++;
461
+ });
462
+
463
+ var params = {files: Object.toJSON(ids), node:this.currentNode.id, store:this.storeId};
464
+
465
+ new Ajax.Request(this.deleteFilesUrl, {
466
+ parameters: params,
467
+ onSuccess: function(transport) {
468
+ try {
469
+ this.onAjaxSuccess(transport);
470
+ this.selectFolder(this.currentNode);
471
+ alert(transport.responseText);
472
+ } catch(e) {
473
+ alert(e.message);
474
+ }
475
+ }.bind(this)
476
+ });
477
+ },
478
+
479
+ drawBreadcrumbs: function(node) {
480
+ if ($('breadcrumbs') != undefined) {
481
+ $('breadcrumbs').remove();
482
+ }
483
+ if (node.id == 'root') {
484
+ return;
485
+ }
486
+ var path = node.getPath().split('/');
487
+ var breadcrumbs = '';
488
+ for(var i = 0, length = path.length; i < length; i++) {
489
+ if (path[i] == '') {
490
+ continue;
491
+ }
492
+ var currNode = this.tree.getNodeById(path[i]);
493
+ if (currNode.id) {
494
+ breadcrumbs += '<li>';
495
+ breadcrumbs += '<a href="#" onclick="MediabrowserInstance.selectFolderById(\'' + currNode.id + '\');">' + currNode.text + '</a>';
496
+ if(i < (length - 1)) {
497
+ breadcrumbs += ' <span>/</span>';
498
+ }
499
+ breadcrumbs += '</li>';
500
+ }
501
+ }
502
+
503
+ if (breadcrumbs != '') {
504
+ breadcrumbs = '<ul class="breadcrumbs" id="breadcrumbs">' + breadcrumbs + '</ul>';
505
+ $('content_header').insert({after: breadcrumbs});
506
+ }
507
+ },
508
+
509
+ updateHeader: function(node) {
510
+ var header = (node.id == 'root' ? this.headerText : node.text);
511
+ if ($('content_header_text') != undefined) {
512
+ $('content_header_text').innerHTML = header;
513
+ }
514
+ },
515
+
516
+ activateBlock: function(id) {
517
+ //$$('div [id^=contents]').each(this.hideElement);
518
+ this.showElement(id);
519
+ },
520
+
521
+ hideElement: function(id) {
522
+ if ($(id) != undefined) {
523
+ $(id).addClassName('no-display');
524
+ $(id).hide();
525
+ }
526
+ },
527
+
528
+ showElement: function(id) {
529
+ if ($(id) != undefined) {
530
+ $(id).removeClassName('no-display');
531
+ $(id).show();
532
+ }
533
+ },
534
+
535
+ onAjaxSuccess: function(transport) {
536
+ if (transport.responseText.isJSON()) {
537
+ var response = transport.responseText.evalJSON()
538
+ if (response.error) {
539
+ throw response;
540
+ } else if (response.ajaxExpired && response.ajaxRedirect) {
541
+ setLocation(response.ajaxRedirect);
542
+ }
543
+ }
544
+ }
545
+ }
package.xml ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>hankeme_chameleon</name>
4
+ <version>0.1.0</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://opensource.org/licenses/osl-3.0.php">Open Software License (OSL 3.0)</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>HANKEME CHAMELEON &#x2013; SKIN &amp; TEMPLATE EDITOR lets you edit Skin-, Template- and Layout-Files directly via the Magento Backend.</summary>
10
+ <description>CHAMELEON &#x2013; SKIN &amp; TEMPLATE EDITOR&#xD;
11
+ &#xD;
12
+ HANKEME CHAMELEON &#x2013; SKIN &amp; TEMPLATE EDITOR allows you to edit skin-, template- and layout-files directy via the Magento backend. Thus it is not necessary any more to work on the webserver using FTP or SSH to adapt the design of your Magento frontend. Simply select the desired file in the backend editor, make your changes and hit the Save button. &#xD;
13
+ After installing the extension you will see an additional menu entry in the Magento backend menu named &#x201E;Template Editor&#x201C;. From here you can reach the file browsers for &#x201E;Skin Files&#x201C; and &#x201E;Template &amp; Layout Files&#x201C;. By browsing the Magento folder structure you can simply select the desired files and edit their contents by clicking the "Edit File" button. Additionally you can create new files and create backup copies of existing ones.&#xD;
14
+ &#xD;
15
+ HANKEME CHAMELEON &#x2013; SKIN &amp; TEMPLATE EDITOR is especially suitable for smaller web design tasks and template adaptions. It is inspired by a popular functionality known from WordPress.&#xD;
16
+ &#xD;
17
+ Please note: the HANKEME CHAMELEON &#x2013; SKIN &amp; TEMPLATE EDITOR is not supposed to replace a professional development environment. This extension should only be used by experienced users, as ist makes it at least theoretically possible to overwrite Magento core files or delete files that are inevitably necessary for a proper functioning of your website. Additionally your whole Magento installation might under circumstances be destroyed, for example by the use of inappropriate PHP-Code in template files.&#xD;
18
+ &#xD;
19
+ We strongy advise you to follow these security instructions:&#xD;
20
+ - Always do changes of your files in a development environment first. Test them thoroughly before releasing them to the live store.&#xD;
21
+ - Be sure to grant access to the extensions functions only to trusted users who are skilled in web design or web development.</description>
22
+ <notes>initial release</notes>
23
+ <authors><author><name>Jan Strohmeier</name><user>hankeme_de</user><email>jan.strohmeier@hanke.me</email></author></authors>
24
+ <date>2015-05-21</date>
25
+ <time>12:36:22</time>
26
+ <contents><target name="magecommunity"><dir name="Hankeme"><dir name="Chameleon"><dir name="Block"><dir name="Adminhtml"><dir name="Design"><dir name="Edit"><file name="Files.php" hash="0a6f8cefff79154816f67c28d80aec24"/></dir><file name="Edit.php" hash="7f2948b4b4a264277a738a15ae879c73"/><file name="Tree.php" hash="a3b51c1bb2c2d39cab92911a41a1e0a4"/></dir><dir name="Skin"><dir name="Edit"><file name="Files.php" hash="769dda67e249eb004d84210d3b47a841"/></dir><file name="Edit.php" hash="7506f923df8e5ab3183e6a19c9b4ae2c"/><file name="Tree.php" hash="30a9603a8ba59378cf2a65276adb72ae"/></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="0631ed5382625c5cc4fd41fb02610a62"/><file name="Design.php" hash="6081b755740c7e9afbef9072b2a33464"/></dir><dir name="Model"><dir name="Design"><dir name="Storage"><file name="Collection.php" hash="3861c6c1f8bff6281859b0ea9a629c7b"/></dir><file name="Storage.php" hash="2bd8cac0c5d68e0a4298bd30586edd9b"/></dir><dir name="Skin"><dir name="Storage"><file name="Collection.php" hash="2ddecdee18dba618596b673ffa5b00ab"/></dir><file name="Storage.php" hash="4600f9cfc3cb7d292ac99274839f4767"/></dir></dir><dir name="controllers"><dir name="Adminhtml"><dir name="Chameleon"><file name="DesignController.php" hash="cd172721764d77e20925830a78ee7850"/><file name="SkinController.php" hash="71769cb3c307a6d7a93717b6309030f1"/></dir><file name="ChameleonController.php" hash="f1dc20476e2ac42a7b852460e085208f"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="5350c41df22b6c4e55d690920ad79f26"/><file name="config.xml" hash="6011564f25a9578a2361545809e50667"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Hankeme_Chameleon.xml" hash="be1789228501d98fbddc4ec69e846647"/></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="hankeme"><dir name="chameleon"><dir name="design"><dir name="edit"><file name="files.phtml" hash="570096e4f65b50d2590cad518ea978a0"/></dir><file name="edit.phtml" hash="f3a362ace8fc6038b5366ec97ca5240f"/><file name="tree.phtml" hash="eaa8da3ca033ee6b23c6f5306492f2d8"/></dir><dir name="skin"><dir name="edit"><file name="files.phtml" hash="570096e4f65b50d2590cad518ea978a0"/></dir><file name="edit.phtml" hash="f3a362ace8fc6038b5366ec97ca5240f"/><file name="tree.phtml" hash="eaa8da3ca033ee6b23c6f5306492f2d8"/></dir></dir></dir></dir><dir name="layout"><file name="hankeme_chameleon.xml" hash="e78c26f52c60e69f9532b2da0fc1bee3"/></dir></dir></dir></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="hankeme"><file name="chameleon.css" hash="c1c38e92d921339f0f8b79c5201df11d"/><dir name="images"><file name="chameleon_compressed.png" hash="0a65365170b3f3cd533d2cac7a5b25ab"/><file name="chameleon_css.png" hash="4d80dbe4e673a5ba3c47ed0d0edaeaf0"/><file name="chameleon_file.png" hash="4d0149be03252f7c3b130ad0974a06ae"/><file name="chameleon_html.png" hash="7c728bb60a583d22824777b2dce55b78"/><file name="chameleon_image.png" hash="49d89bc5f4267cbfdbd1e223d2a3193a"/><file name="chameleon_js.png" hash="75d1886d60fc6b8a3878f154cab33a6b"/><file name="chameleon_movie.png" hash="7748a69a9eff1f417256ae158c249d50"/><file name="chameleon_music.png" hash="1fd44d584387d1fce13224c9cec95acd"/><file name="chameleon_phtml.png" hash="62266ce611fc7f8c7b0156e257cb5889"/><file name="chameleon_text.png" hash="04d66a50573d56f451d90a44b4bdadf3"/><file name="chameleon_xml.png" hash="6c7b9a7e3970a1f13434ddde2aecde03"/></dir></dir></dir></dir></dir></target><target name="mageweb"><dir name="js"><dir name="hankeme"><dir name="chameleon"><file name="chameleon.js" hash="f412c1716d713f86d0a5bf19ff5212ea"/></dir></dir></dir></target></contents>
27
+ <compatible/>
28
+ <dependencies><required><php><min>5.2.0</min><max>5.6.0</max></php></required></dependencies>
29
+ </package>
skin/adminhtml/default/default/hankeme/chameleon.css ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * HANKEME
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is exclusively published under the Open Software License (OSL 3.0)
7
+ * See http://opensource.org/licenses/osl-3.0.php for Details
8
+ * In case of questions regarding the use of this source file please
9
+ refer to the contact below.
10
+ *
11
+ * @project: [HANKEME Chameleon]
12
+ * @contact: info@hankeme.de
13
+ * @collaborators: [strohmeier]
14
+ */
15
+ .chameleon_content_list .filecnt,
16
+ .chameleon_content_list .fileslist li {
17
+ display: inline-block;
18
+ width: 125px;
19
+ vertical-align:top;
20
+ margin:0 10px;
21
+ }
22
+
23
+ /* background images courtesy of http://filetypeicons.com */
24
+ .chameleon_content_list .filecnt {
25
+ height: 110px;
26
+ width:85px;
27
+ border: none;
28
+ margin: 10px;
29
+ padding:10px;
30
+ cursor: pointer;
31
+ background-position:center top;
32
+ background-repeat: no-repeat;
33
+ background-image: url(images/chameleon_file.png);
34
+ background-color: transparent;
35
+ position:relative;
36
+ }
37
+ .chameleon_content_list .filecnt.chameleon-type-css {
38
+ background-image: url(images/chameleon_css.png);
39
+ }
40
+
41
+ .chameleon_content_list .filecnt.chameleon-type-js {
42
+ background-image: url(images/chameleon_js.png);
43
+ }
44
+
45
+ .chameleon_content_list .filecnt.chameleon-type-txt {
46
+ background-image: url(images/chameleon_text.png);
47
+ }
48
+
49
+ .chameleon_content_list .filecnt.chameleon-type-ico,
50
+ .chameleon_content_list .filecnt.chameleon-type-jpg,
51
+ .chameleon_content_list .filecnt.chameleon-type-jpeg,
52
+ .chameleon_content_list .filecnt.chameleon-type-gif,
53
+ .chameleon_content_list .filecnt.chameleon-type-png {
54
+ background-image: url(images/chameleon_image.png);
55
+ }
56
+
57
+ .chameleon_content_list .filecnt.chameleon-type-html,
58
+ .chameleon_content_list .filecnt.chameleon-type-htm {
59
+ background-image: url(images/chameleon_html.png);
60
+ }
61
+
62
+ .chameleon_content_list .filecnt.chameleon-type-phtml {
63
+ background-image: url(images/chameleon_phtml.png);
64
+ }
65
+
66
+ .chameleon_content_list .filecnt.chameleon-type-xml {
67
+ background-image: url(images/chameleon_xml.png);
68
+ }
69
+
70
+ .chameleon_content_list .filecnt.selected,
71
+ .chameleon_content_list .filecnt.selected + small {
72
+ font-weight: bold;
73
+ }
74
+ .chameleon_content_list .filecnt.active {
75
+ border: 3px solid #a6a6a6;
76
+ }
77
+
78
+ .chameleon_content_list li small {
79
+ display: block;
80
+ margin:0 0 0 0;
81
+ width:100%;
82
+ left:0;
83
+ text-align:center;
84
+ word-wrap: break-word;
85
+ background:transparent;
86
+ }
87
+
88
+ .chameleon_content_stage {
89
+ width:96%;
90
+ min-height:200px;
91
+ padding: 2%;
92
+ }
93
+
94
+ #chameleon_action_buttons {
95
+ display:block;
96
+ height: 30px;
97
+ width: 100%;
98
+ }
99
+
100
+ .chameleon_hint {
101
+ text-align: center;
102
+ color: #666e73;
103
+ }
skin/adminhtml/default/default/hankeme/images/chameleon_compressed.png ADDED
Binary file
skin/adminhtml/default/default/hankeme/images/chameleon_css.png ADDED
Binary file
skin/adminhtml/default/default/hankeme/images/chameleon_file.png ADDED
Binary file
skin/adminhtml/default/default/hankeme/images/chameleon_html.png ADDED
Binary file
skin/adminhtml/default/default/hankeme/images/chameleon_image.png ADDED
Binary file
skin/adminhtml/default/default/hankeme/images/chameleon_js.png ADDED
Binary file
skin/adminhtml/default/default/hankeme/images/chameleon_movie.png ADDED
Binary file
skin/adminhtml/default/default/hankeme/images/chameleon_music.png ADDED
Binary file
skin/adminhtml/default/default/hankeme/images/chameleon_phtml.png ADDED
Binary file
skin/adminhtml/default/default/hankeme/images/chameleon_text.png ADDED
Binary file
skin/adminhtml/default/default/hankeme/images/chameleon_xml.png ADDED
Binary file