Dotclear

source: inc/admin/lib.moduleslist.php @ 2182:eaaf345b04f3

Revision 2182:eaaf345b04f3, 25.5 KB checked in by Denis Jean-Chirstian <contact@…>, 12 years ago (diff)

Enable complex loop (get, post, redirect) in themes and plugins configuration files

Line 
1<?php
2
3class adminModulesList
4{
5     public $core;
6     public $modules;
7
8     public static  $allow_multi_install;
9     public static $distributed_modules = array();
10
11     protected $list_id = 'unknow';
12
13     protected $config_module = '';
14     protected $config_file = '';
15     protected $config_content = '';
16
17     protected $path = false;
18     protected $path_writable = false;
19     protected $path_pattern = false;
20
21     protected $page_url = 'plugins.php';
22     protected $page_qs = '?';
23     protected $page_tab = '';
24
25     public static $nav_indexes = 'abcdefghijklmnopqrstuvwxyz0123456789';
26     protected $nav_list = array();
27     protected $nav_special = 'other';
28
29     protected $sort_field = 'sname';
30     protected $sort_asc = true;
31
32     public function __construct($core, $root, $allow_multi_install=false)
33     {
34          $this->core = $core;
35          self::$allow_multi_install = (boolean) $allow_multi_install;
36          $this->setPathInfo($root);
37          $this->setNavSpecial(__('other'));
38
39          $this->init();
40     }
41
42     protected function init()
43     {
44          return null;
45     }
46
47     public function newList($list_id)
48     {
49          $this->modules = array();
50          $this->page_tab = '';
51          $this->list_id = $list_id;
52
53          return $this;
54     }
55
56     protected function setPathInfo($root)
57     {
58          $paths = explode(PATH_SEPARATOR, $root);
59          $path = array_pop($paths);
60          unset($paths);
61
62          $this->path = $path;
63          if (is_dir($path) && is_writeable($path)) {
64               $this->path_writable = true;
65               $this->path_pattern = preg_quote($path,'!');
66          }
67
68          return $this;
69     }
70
71     public function getPath()
72     {
73          return $this->path;
74     }
75
76     public function isPathWritable()
77     {
78          return $this->path_writable;
79     }
80
81     public function isPathDeletable($root)
82     {
83          return $this->path_writable 
84               && preg_match('!^'.$this->path_pattern.'!', $root) 
85               && $this->core->auth->isSuperAdmin();
86     }
87
88     public function setPageURL($url)
89     {
90          $this->page_qs = strpos('?', $url) ? '&' : '?';
91          $this->page_url = $url;
92
93          return $this;
94     }
95
96     public function getPageURL($queries='', $with_tab=true)
97     {
98          return $this->page_url.
99               (!empty($queries) ? $this->page_qs : '').
100               (is_array($queries) ? http_build_query($queries) : $queries).
101               ($with_tab && !empty($this->page_tab) ? '#'.$this->page_tab : '');
102     }
103
104     public function setPageTab($tab)
105     {
106          $this->page_tab = $tab;
107
108          return $this;
109     }
110
111     public function getPageTab()
112     {
113          return $this->page_tab;
114     }
115
116     public function getSearchQuery()
117     {
118          $query = !empty($_REQUEST['m_search']) ? trim($_REQUEST['m_search']) : null;
119          return strlen($query) > 1 ? $query : null;
120     }
121
122     public function displaySearchForm()
123     {
124          $query = $this->getSearchQuery();
125
126          if (empty($this->modules) && $query === null) {
127               return $this;
128          }
129
130          echo 
131          '<form action="'.$this->getPageURL().'" method="get" class="fieldset">'.
132          '<p><label for="m_search" class="classic">'.__('Search in repository:').'&nbsp;</label><br />'.
133          form::field(array('m_search','m_search'), 30, 255, html::escapeHTML($query)).
134          '<input type="submit" value="'.__('Search').'" /> ';
135          if ($query) { echo ' <a href="'.$this->getPageURL().'" class="button">'.__('Reset search').'</a>'; }
136          echo '</p>'.
137          '</form>';
138
139          if ($query) {
140               echo 
141               '<p class="message">'.sprintf(
142                    __('Found %d result for search "%s":', 'Found %d results for search "%s":', count($this->modules)), 
143                    count($this->modules), html::escapeHTML($query)
144                    ).
145               '</p>';
146          }
147          return $this;
148     }
149
150     public function setNavSpecial($str)
151     {
152          $this->nav_special = (string) $str;
153          $this->nav_list = array_merge(str_split(self::$nav_indexes), array($this->nav_special));
154
155          return $this;
156     }
157
158     public function getNavQuery()
159     {
160          return isset($_REQUEST['m_nav']) && in_array($_REQUEST['m_nav'], $this->nav_list) ? $_REQUEST['m_nav'] : $this->nav_list[0];
161     }
162
163     public function displayNavMenu()
164     {
165          if (empty($this->modules) || $this->getSearchQuery() !== null) {
166               return $this;
167          }
168
169          # Fetch modules required field
170          $indexes = array();
171          foreach ($this->modules as $id => $module) {
172               if (!isset($module[$this->sort_field])) {
173                    continue;
174               }
175               $char = substr($module[$this->sort_field], 0, 1);
176               if (!in_array($char, $this->nav_list)) {
177                    $char = $this->nav_special;
178               }
179               if (!isset($indexes[$char])) {
180                    $indexes[$char] = 0;
181               }
182               $indexes[$char]++;
183          }
184
185          $buttons = array();
186          foreach($this->nav_list as $char) {
187               # Selected letter
188               if ($this->getNavQuery() == $char) {
189                    $buttons[] = '<li class="active" title="'.__('current selection').'"><strong> '.$char.' </strong></li>';
190               }
191               # Letter having modules
192               elseif (!empty($indexes[$char])) {
193                    $title = sprintf(__('%d module', '%d modules', $indexes[$char]), $indexes[$char]);
194                    $buttons[] = '<li class="btn" title="'.$title.'"><a href="'.$this->getPageURL('m_nav='.$char).'" title="'.$title.'"> '.$char.' </a></li>';
195               }
196               # Letter without modules
197               else {
198                    $buttons[] = '<li class="btn no-link" title="'.__('no module').'"> '.$char.' </li>';
199               }
200          }
201          # Parse navigation menu
202          echo '<div class="pager">'.__('Browse index:').' <ul>'.implode('',$buttons).'</ul></div>';
203
204          return $this;
205     }
206
207     public function setSortField($field, $asc=true)
208     {
209          $this->sort_field = $field;
210          $this->sort_asc = (boolean) $asc;
211
212          return $this;
213     }
214
215     public function getSortQuery()
216     {
217          return !empty($_REQUEST['m_sort']) ? $_REQUEST['m_sort'] : $this->sort_field;
218     }
219
220     public function displaySortForm()
221     {
222          //not yet implemented
223     }
224
225     public function displayMessage($action)
226     {
227          switch($action) {
228               case 'activate': 
229                    $str = __('Module successfully activated.'); break;
230               case 'deactivate': 
231                    $str = __('Module successfully deactivated.'); break;
232               case 'delete': 
233                    $str = __('Module successfully deleted.'); break;
234               case 'install': 
235                    $str = __('Module successfully installed.'); break;
236               case 'update': 
237                    $str = __('Module successfully updated.'); break;
238               default:
239                    $str = ''; break;
240          }
241          if (!empty($str)) {
242               dcPage::success($str);
243          }
244     }
245
246     public function setModules($modules)
247     {
248          $this->modules = array();
249          if (!empty($modules) && is_array($modules)) {
250               foreach($modules as $id => $module) {
251                    $this->modules[$id] = self::parseModuleInfo($id, $module);
252               }
253          }
254          return $this;
255     }
256
257     public function getModules()
258     {
259          return $this->modules;
260     }
261
262     public static function parseModuleInfo($id, $module)
263     {
264          $label = empty($module['label']) ? $id : $module['label'];
265          $name = __(empty($module['name']) ? $label : $module['name']);
266         
267          return array_merge(
268               # Default values
269               array(
270                    'desc'                   => '',
271                    'author'            => '',
272                    'version'                => 0,
273                    'current_version'   => 0,
274                    'root'                   => '',
275                    'root_writable'     => false,
276                    'permissions'       => null,
277                    'parent'            => null,
278                    'priority'               => 1000,
279                    'standalone_config' => false,
280                    'support'                => '',
281                    'section'                => '',
282                    'tags'                   => '',
283                    'details'                => '',
284                    'sshot'             => ''
285               ),
286               # Module's values
287               $module,
288               # Clean up values
289               array(
290                    'id'                     => $id,
291                    'sid'                    => self::sanitizeString($id),
292                    'label'             => $label,
293                    'name'                   => $name,
294                    'sname'             => self::sanitizeString($name)
295               )
296          );
297     }
298
299     public static function setDistributedModules($modules)
300     {
301          self::$distributed_modules = $modules;
302     }
303
304     public static function isDistributedModule($module)
305     {
306          $distributed_modules = self::$distributed_modules;
307
308          return is_array($distributed_modules) && in_array($module, $distributed_modules);
309     }
310
311     public static function sortModules($modules, $field, $asc=true)
312     {
313          $sorter = array();
314          foreach($modules as $id => $module) {
315               $sorter[$id] = isset($module[$field]) ? $module[$field] : $field;
316          }
317          array_multisort($sorter, $asc ? SORT_ASC : SORT_DESC, $modules);
318
319          return $modules;
320     }
321
322     public function displayModulesList($cols=array('name', 'config', 'version', 'desc'), $actions=array(), $nav_limit=false)
323     {
324          echo 
325          '<div class="table-outer">'.
326          '<table id="'.html::escapeHTML($this->list_id).'" class="modules'.(in_array('expander', $cols) ? ' expandable' : '').'">'.
327          '<caption class="hidden">'.html::escapeHTML(__('Modules list')).'</caption><tr>';
328
329          if (in_array('name', $cols)) {
330               echo 
331               '<th class="first nowrap"'.(in_array('icon', $cols) ? ' colspan="2"' : '').'>'.__('Name').'</th>';
332          }
333
334          if (in_array('version', $cols)) {
335               echo 
336               '<th class="nowrap count" scope="col">'.__('Version').'</th>';
337          }
338
339          if (in_array('current_version', $cols)) {
340               echo 
341               '<th class="nowrap count" scope="col">'.__('Current version').'</th>';
342          }
343
344          if (in_array('desc', $cols)) {
345               echo 
346               '<th class="nowrap" scope="col">'.__('Details').'</th>';
347          }
348
349          if (in_array('distrib', $cols)) {
350               echo '<th'.(in_array('desc', $cols) ? '' : ' class="maximal"').'></th>';
351          }
352
353          if (!empty($actions) && $this->core->auth->isSuperAdmin()) {
354               echo 
355               '<th class="minimal nowrap">'.__('Action').'</th>';
356          }
357
358          echo 
359          '</tr>';
360
361          $sort_field = $this->getSortQuery();
362
363          # Sort modules by id
364          $modules = $this->getSearchQuery() === null ?
365               self::sortModules($this->modules, $sort_field, $this->sort_asc) :
366               $this->modules;
367
368          $count = 0;
369          foreach ($modules as $id => $module)
370          {
371               # Show only requested modules
372               if ($nav_limit && $this->getSearchQuery() === null) {
373                    $char = substr($module[$sort_field], 0, 1);
374                    if (!in_array($char, $this->nav_list)) {
375                         $char = $this->nav_special;
376                    }
377                    if ($this->getNavQuery() != $char) {
378                         continue;
379                    }
380               }
381
382               echo 
383               '<tr class="line" id="'.html::escapeHTML($this->list_id).'_m_'.html::escapeHTML($id).'">';
384
385               if (in_array('icon', $cols)) {
386                    echo 
387                    '<td class="module-icon nowrap">'.sprintf(
388                         '<img alt="%1$s" title="%1$s" src="%2$s" />', 
389                         html::escapeHTML($id), file_exists($module['root'].'/icon.png') ? 'index.php?pf='.$id.'/icon.png' : 'images/module.png'
390                    ).'</td>';
391               }
392
393               # Link to config file
394               $config = in_array('config', $cols) && !empty($module['root']) && file_exists(path::real($module['root'].'/_config.php'));
395
396               echo 
397               '<td class="module-name nowrap" scope="row">'.($config ? 
398                    '<a href="'.$this->getPageURL('module='.$id.'&conf=1').'" title"'.sprintf(__('Configure module "%s"'), html::escapeHTML($module['name'])).'">'.html::escapeHTML($module['name']).'</a>' : 
399                    html::escapeHTML($module['name'])
400               ).'</td>';
401
402               if (in_array('version', $cols)) {
403                    echo 
404                    '<td class="module-version nowrap count">'.html::escapeHTML($module['version']).'</td>';
405               }
406
407               if (in_array('current_version', $cols)) {
408                    echo 
409                    '<td class="module-current-version nowrap count">'.html::escapeHTML($module['current_version']).'</td>';
410               }
411
412               if (in_array('desc', $cols)) {
413                    echo 
414                    '<td class="module-desc maximal">'.html::escapeHTML($module['desc']).'</td>';
415               }
416
417               if (in_array('distrib', $cols)) {
418                    echo 
419                    '<td class="module-distrib">'.(self::isDistributedModule($id) ? 
420                         '<img src="images/dotclear_pw.png" alt="'.
421                         __('Module from official distribution').'" title="'.
422                         __('module from official distribution').'" />' 
423                    : '').'</td>';
424               }
425
426               if (!empty($actions) && $this->core->auth->isSuperAdmin()) {
427                    echo 
428                    '<td class="module-actions nowrap">';
429
430                    $this->displayLineActions($id, $module, $actions);
431
432                    echo
433                    '</td>';
434               }
435
436               echo 
437               '</tr>';
438
439               $count++;
440          }
441          echo 
442          '</table></div>';
443
444          if(!$count) {
445               echo 
446               '<p class="message">'.__('No module matches your search.').'</p>';
447          }
448     }
449
450     protected function displayLineActions($id, $module, $actions, $echo=true)
451     {
452          $submits = array();
453
454          # Activate
455          if (in_array('deactivate', $actions) && $module['root_writable']) {
456               $submits[] = '<input type="submit" name="deactivate" value="'.__('Deactivate').'" />';
457          }
458
459          # Deactivate
460          if (in_array('activate', $actions) && $module['root_writable']) {
461               $submits[] = '<input type="submit" name="activate" value="'.__('Activate').'" />';
462          }
463
464          # Delete
465          if (in_array('delete', $actions) && $this->isPathDeletable($module['root'])) {
466               $submits[] = '<input type="submit" class="delete" name="delete" value="'.__('Delete').'" />';
467          }
468
469          # Install (form repository)
470          if (in_array('install', $actions) && $this->path_writable) {
471               $submits[] = '<input type="submit" name="install" value="'.__('Install').'" />';
472          }
473
474          # Update (from repository)
475          if (in_array('update', $actions) && $this->path_writable) {
476               $submits[] = '<input type="submit" name="update" value="'.__('Update').'" />';
477          }
478
479          # Select (from repository)
480          if (in_array('choose', $actions) && $this->path_writable) {
481               $submits[] = '<input type="submit" name="choose" value="'.__('Choose').'" />';
482          }
483
484          # Parse form
485          if (!empty($submits)) {
486               $res = 
487               '<form action="'.$this->getPageURL().'" method="post">'.
488               '<div>'.
489               $this->core->formNonce().
490               form::hidden(array('module'), html::escapeHTML($id)).
491               form::hidden(array('tab'), $this->page_tab).
492               implode(' ', $submits).
493               '</div>'.
494               '</form>';
495
496               if (!$echo) {
497                    return $res;
498               }
499               echo $res;
500          }
501     }
502
503     public function executeAction($prefix, dcModules $modules, dcRepository $repository)
504     {
505          if (!$this->core->auth->isSuperAdmin() || !$this->isPathWritable()) {
506               return null;
507          }
508
509          # List actions
510          if (!empty($_POST['module'])) {
511
512               $id = $_POST['module'];
513
514               if (!empty($_POST['activate'])) {
515
516                    $enabled = $modules->getDisabledModules();
517                    if (!isset($enabled[$id])) {
518                         throw new Exception(__('No such module.'));
519                    }
520
521                    # --BEHAVIOR-- moduleBeforeActivate
522                    $this->core->callBehavior($type.'BeforeActivate', $id);
523
524                    $modules->activateModule($id);
525
526                    # --BEHAVIOR-- moduleAfterActivate
527                    $this->core->callBehavior($type.'AfterActivate', $id);
528
529                    http::redirect($this->getPageURL('msg=activate'));
530               }
531
532               if (!empty($_POST['deactivate'])) {
533
534                    if (!$modules->moduleExists($id)) {
535                         throw new Exception(__('No such module.'));
536                    }
537
538                    $module = $modules->getModules($id);
539                    $module['id'] = $id;
540
541                    if (!$module['root_writable']) {
542                         throw new Exception(__('You don\'t have permissions to deactivate this module.'));
543                    }
544
545                    # --BEHAVIOR-- moduleBeforeDeactivate
546                    $this->core->callBehavior($prefix.'BeforeDeactivate', $module);
547
548                    $modules->deactivateModule($id);
549
550                    # --BEHAVIOR-- moduleAfterDeactivate
551                    $this->core->callBehavior($prefix.'AfterDeactivate', $module);
552
553                    http::redirect($this->getPageURL('msg=deactivate'));
554               }
555
556               if (!empty($_POST['delete'])) {
557
558                    $disabled = $modules->getDisabledModules();
559                    if (!isset($disabled[$id])) {
560
561                         if (!$modules->moduleExists($id)) {
562                              throw new Exception(__('No such module.'));
563                         }
564
565                         $module = $modules->getModules($id);
566                         $module['id'] = $id;
567
568                         if (!$this->isPathDeletable($module['root'])) {
569                              throw new Exception(__("You don't have permissions to delete this module."));
570                         }
571
572                         # --BEHAVIOR-- moduleBeforeDelete
573                         $this->core->callBehavior($prefix.'BeforeDelete', $module);
574
575                         $modules->deleteModule($id);
576
577                         # --BEHAVIOR-- moduleAfterDelete
578                         $this->core->callBehavior($prefix.'AfterDelete', $module);
579                    }
580                    else {
581                         $modules->deleteModule($id, true);
582                    }
583
584                    http::redirect($this->getPageURL('msg=delete'));
585               }
586
587               if (!empty($_POST['update'])) {
588
589                    $updated = $repository->get();
590                    if (!isset($updated[$id])) {
591                         throw new Exception(__('No such module.'));
592                    }
593
594                    if (!$modules->moduleExists($id)) {
595                         throw new Exception(__('No such module.'));
596                    }
597
598                    $module = $updated[$id];
599                    $module['id'] = $id;
600               
601                    if (!self::$allow_multi_install) {
602                         $dest = $module['root'].'/../'.basename($module['file']);
603                    }
604                    else {
605                         $dest = $this->getPath().'/'.basename($module['file']);
606                         if ($module['root'] != $dest) {
607                              @file_put_contents($module['root'].'/_disabled', '');
608                         }
609                    }
610
611                    # --BEHAVIOR-- moduleBeforeUpdate
612                    $this->core->callBehavior($type.'BeforeUpdate', $module);
613
614                    $repository->process($module['file'], $dest);
615
616                    # --BEHAVIOR-- moduleAfterUpdate
617                    $this->core->callBehavior($type.'AfterUpdate', $module);
618
619                    http::redirect($this->getPageURL('msg=upadte'));
620               }
621
622               if (!empty($_POST['install'])) {
623
624                    $updated = $repository->get();
625                    if (!isset($updated[$id])) {
626                         throw new Exception(__('No such module.'));
627                    }
628
629                    $module = $updated[$id];
630                    $module['id'] = $id;
631
632                    $dest = $this->getPath().'/'.basename($module['file']);
633
634                    # --BEHAVIOR-- moduleBeforeAdd
635                    $this->core->callBehavior($type.'BeforeAdd', $module);
636
637                    $ret_code = $repository->process($module['file'], $dest);
638
639                    # --BEHAVIOR-- moduleAfterAdd
640                    $this->core->callBehavior($type.'AfterAdd', $module);
641
642                    http::redirect($this->getPageURL('msg='.($ret_code == 2 ? 'update' : 'install')));
643               }
644          }
645          # Manual actions
646          elseif (!empty($_POST['upload_pkg']) && !empty($_FILES['pkg_file']) 
647               || !empty($_POST['fetch_pkg']) && !empty($_POST['pkg_url']))
648          {
649               if (empty($_POST['your_pwd']) || !$this->core->auth->checkPassword(crypt::hmac(DC_MASTER_KEY, $_POST['your_pwd']))) {
650                    throw new Exception(__('Password verification failed'));
651               }
652
653               if (!empty($_POST['upload_pkg'])) {
654                    files::uploadStatus($_FILES['pkg_file']);
655                   
656                    $dest = $this->getPath().'/'.$_FILES['pkg_file']['name'];
657                    if (!move_uploaded_file($_FILES['pkg_file']['tmp_name'], $dest)) {
658                         throw new Exception(__('Unable to move uploaded file.'));
659                    }
660               }
661               else {
662                    $url = urldecode($_POST['pkg_url']);
663                    $dest = $this->getPath().'/'.basename($url);
664                    $repository->download($url, $dest);
665               }
666
667               # --BEHAVIOR-- moduleBeforeAdd
668               $this->core->callBehavior($prefix.'BeforeAdd', null);
669
670               $ret_code = $repository->install($dest);
671
672               # --BEHAVIOR-- moduleAfterAdd
673               $this->core->callBehavior($prefix.'AfterAdd', null);
674
675               http::redirect($this->getPageURL('msg='.($ret_code == 2 ? 'update' : 'install')).'#'.$prefix);
676          }
677          return null;
678     }
679
680     public function displayManualForm()
681     {
682          if (!$this->core->auth->isSuperAdmin() || !$this->isPathWritable()) {
683               return null;
684          }
685
686          # 'Upload module' form
687          echo
688          '<form method="post" action="'.$this->getPageURL().'" id="uploadpkg" enctype="multipart/form-data" class="fieldset">'.
689          '<h4>'.__('Upload a zip file').'</h4>'.
690          '<p class="field"><label for="pkg_file" class="classic required"><abbr title="'.__('Required field').'">*</abbr> '.__('Zip file path:').'</label> '.
691          '<input type="file" name="pkg_file" id="pkg_file" /></p>'.
692          '<p class="field"><label for="your_pwd1" class="classic required"><abbr title="'.__('Required field').'">*</abbr> '.__('Your password:').'</label> '.
693          form::password(array('your_pwd','your_pwd1'),20,255).'</p>'.
694          '<p><input type="submit" name="upload_pkg" value="'.__('Upload').'" />'.
695          form::hidden(array('tab'), $this->getPageTab()).
696          $this->core->formNonce().'</p>'.
697          '</form>';
698         
699          # 'Fetch module' form
700          echo
701          '<form method="post" action="'.$this->getPageURL().'" id="fetchpkg" class="fieldset">'.
702          '<h4>'.__('Download a zip file').'</h4>'.
703          '<p class="field"><label for="pkg_url" class="classic required"><abbr title="'.__('Required field').'">*</abbr> '.__('Zip file URL:').'</label> '.
704          form::field(array('pkg_url','pkg_url'),40,255).'</p>'.
705          '<p class="field"><label for="your_pwd2" class="classic required"><abbr title="'.__('Required field').'">*</abbr> '.__('Your password:').'</label> '.
706          form::password(array('your_pwd','your_pwd2'),20,255).'</p>'.
707          '<p><input type="submit" name="fetch_pkg" value="'.__('Download').'" />'.
708          form::hidden(array('tab'), $this->getPageTab()).
709          $this->core->formNonce().'</p>'.
710          '</form>';
711     }
712
713     /**
714      *
715      * We need to get configuration content in three steps
716      * and out of this class to keep backward compatibility.
717      *
718      * if ($xxx->setConfigurationFile()) {
719      *   include $xxx->getConfigurationFile();
720      * }
721      * $xxx->setConfigurationContent();
722      * ... [put here page headers and other stuff]
723      * $xxx->getConfigurationContent();
724      *
725      */
726     public function setConfigurationFile(dcModules $modules, $id=null)
727     {
728          if (empty($_REQUEST['conf']) || empty($_REQUEST['module']) && !$id) {
729               return false;
730          }
731         
732          if (!empty($_REQUEST['module']) && empty($id)) {
733               $id = $_REQUEST['module'];
734          }
735
736          if (!$modules->moduleExists($id)) {
737               $core->error->add(__('Unknow module ID'));
738               return false;
739          }
740
741          $module = $modules->getModules($id);
742          $module = self::parseModuleInfo($id, $module);
743          $file = path::real($module['root'].'/_config.php');
744
745          if (!file_exists($file)) {
746               $core->error->add(__('This module has no configuration file.'));
747               return false;
748          }
749
750          $this->config_module = $module;
751          $this->config_file = $file;
752          $this->config_content = '';
753
754          if (!defined('DC_CONTEXT_MODULE')) {
755               define('DC_CONTEXT_MODULE', true);
756          }
757
758          return true;
759     }
760
761     public function getConfigurationFile()
762     {
763          if (!$this->config_file) {
764               return null;
765          }
766
767          ob_start();
768
769          return $this->config_file;
770     }
771
772     public function setConfigurationContent()
773     {
774          if ($this->config_file) {
775               $this->config_content = ob_get_contents();
776          }
777
778          ob_end_clean();
779
780          return !empty($this->file_content);
781     }
782
783     public function getConfigurationContent()
784     {
785          if (!$this->config_file) {
786               return null;
787          }
788
789          if (!$this->config_module['standalone_config']) {
790               echo
791               '<form id="module_config" action="'.$this->getPageURL('conf=1').'" method="post" enctype="multipart/form-data">'.
792               '<h3>'.sprintf(__('Configure plugin "%s"'), html::escapeHTML($this->config_module['name'])).'</h3>'.
793               '<p><a class="back" href="'.$this->getPageURL().'#plugins">'.__('Back').'</a></p>';
794          }
795
796          echo $this->config_content;
797
798          if (!$this->config_module['standalone_config']) {
799               echo
800               '<p class="clear"><input type="submit" name="save" value="'.__('Save').'" />'.
801               form::hidden('module', $this->config_module['id']).
802               $this->core->formNonce().'</p>'.
803               '</form>';
804          }
805
806          return true;
807     }
808
809     public static function sanitizeString($str)
810     {
811          return preg_replace('/[^A-Za-z0-9\@\#+_-]/', '', strtolower($str));
812     }
813}
814
815class adminThemesList extends adminModulesList
816{
817     protected $page_url = 'blog_theme.php';
818
819     public function displayModulesList($cols=array('name', 'config', 'version', 'desc'), $actions=array(), $nav_limit=false)
820     {
821          echo 
822          '<div id="'.html::escapeHTML($this->list_id).'" class="modules'.(in_array('expander', $cols) ? ' expandable' : '').' one-box">';
823
824          $sort_field = $this->getSortQuery();
825
826          # Sort modules by id
827          $modules = $this->getSearchQuery() === null ?
828               self::sortModules($this->modules, $sort_field, $this->sort_asc) :
829               $this->modules;
830
831          $res = '';
832          $count = 0;
833          foreach ($modules as $id => $module)
834          {
835               # Show only requested modules
836               if ($nav_limit && $this->getSearchQuery() === null) {
837                    $char = substr($module[$sort_field], 0, 1);
838                    if (!in_array($char, $this->nav_list)) {
839                         $char = $this->nav_special;
840                    }
841                    if ($this->getNavQuery() != $char) {
842                         continue;
843                    }
844               }
845
846               $current = $this->core->blog->settings->system->theme == $id;
847
848               if (preg_match('#^http(s)?://#', $this->core->blog->settings->system->themes_url)) {
849                    $theme_url = http::concatURL($this->core->blog->settings->system->themes_url, '/'.$id);
850               } else {
851                    $theme_url = http::concatURL($this->core->blog->url, $this->core->blog->settings->system->themes_url.'/'.$id);
852               }
853
854               $has_conf = file_exists(path::real($this->core->blog->themes_path.'/'.$id).'/_config.php');
855               $has_css = file_exists(path::real($this->core->blog->themes_path.'/'.$id).'/style.css');
856               $parent = $module['parent'];
857               $has_parent = !empty($module['parent']);
858               if ($has_parent) {
859                    $is_parent_present = $this->core->themes->moduleExists($parent);
860               }
861
862               $line = 
863               '<div class="box small '.($current ? 'current-theme' : 'theme').'">';
864
865               if (in_array('sshot', $cols)) {
866                    # Screenshot from url
867                    if (preg_match('#^http(s)?://#', $module['sshot'])) {
868                         $sshot = $module['sshot'];
869                    }
870                    # Screenshot from installed module
871                    elseif (file_exists($this->core->blog->themes_path.'/'.$id.'/screenshot.jpg')) {
872                         $sshot = $this->getPageURL('shot='.rawurlencode($id));
873                    }
874                    # Default screenshot
875                    else {
876                         $sshot = 'images/noscreenshot.png';
877                    }
878
879                    $line .= 
880                    '<div class="module-sshot"><img src="'.$sshot.'" alt="'.__('screenshot.').'" /></div>';
881               }
882
883               if (in_array('name', $cols)) {
884                    $line .= 
885                    '<h4 class="module-name">'.html::escapeHTML($module['name']).'</h4>';
886               }
887
888               $line .= 
889               '<div class="module-infos">'.
890               '<p>';
891
892               if (in_array('desc', $cols)) {
893                    $line .= 
894                    '<span class="module-desc">'.html::escapeHTML($module['desc']).'</span> ';
895               }
896
897               if (in_array('author', $cols)) {
898                    $line .= 
899                    '<span class="module-author">'.sprintf(__('by %s'),html::escapeHTML($module['author'])).'</span> ';
900               }
901
902               if (in_array('version', $cols)) {
903                    $line .= 
904                    '<span class="module-version">'.sprintf(__('version %s'),html::escapeHTML($module['version'])).'</span> ';
905               }
906
907               if (in_array('parent', $cols) && $has_parent) {
908                    if ($is_parent_present) {
909                         $line .= 
910                         '<span class="module-parent-ok">'.sprintf(__('(built on "%s")'),html::escapeHTML($parent)).'</span> ';
911                    }
912                    else {
913                         $line .= 
914                         '<span class="module-parent-missing">'.sprintf(__('(requires "%s")'),html::escapeHTML($parent)).'</span> ';
915                    }
916               }
917
918               $line .= 
919               '</p>'.
920               '</div>';
921
922               $line .= 
923               '<div class="modules-actions">';
924               
925               # _GET actions
926               $line .= 
927               '<p>';
928
929               if ($current && $has_css) {
930                    $line .= 
931                    '<a href="'.$theme_url.'/style.css" class="button">'.__('View stylesheet').'</a> ';
932               }
933               if ($current && $has_conf) {
934                    $line .= 
935                    '<a href="'.$this->getPageURL('module='.$id.'&conf=1', false).'" class="button">'.__('Configure theme').'</a> ';
936               }
937               $line .= 
938               '</p>';
939
940               # Plugins actions
941               if ($current) {
942                    # --BEHAVIOR-- adminCurrentThemeDetails
943                    $line .= 
944                    $this->core->callBehavior('adminCurrentThemeDetails', $this->core, $id, $module);
945               }
946
947               # _POST actions
948               if (!empty($actions) && $this->core->auth->isSuperAdmin()) {
949                    $line .=
950                    $this->displayLineActions($id, $module, $actions, false);
951               }
952
953               $line .= 
954               '</div>';
955
956               $line .=
957               '</div>';
958
959               $count++;
960
961               $res = $current ? $line.$res : $res.$line;
962          }
963          echo 
964          $res.
965          '</div>';
966
967          if(!$count) {
968               echo 
969               '<p class="message">'.__('No module matches your search.').'</p>';
970          }
971     }
972}
Note: See TracBrowser for help on using the repository browser.

Sites map