Dotclear


Ignore:
Files:
6 added
10 edited

Legend:

Unmodified
Added
Removed
  • admin/blog_theme.php

    r2166 r2175  
    1515dcPage::check('admin'); 
    1616 
    17 # Loading themes 
     17# -------------------------------------------------- 
     18# @todo Add settings to Dotclear update features 
     19if ($core->blog->settings->system->repository_theme_url === null) { 
     20     $core->blog->settings->system->put( 
     21          'repository_theme_url', 'http://update.dotaddict.org/dc2/themes.xml', 'string', 'Themes XML feed location', true, true 
     22     ); 
     23} 
     24# -------------------------------------------------- 
     25 
     26# -- Loading themes -- 
    1827$core->themes = new dcThemes($core); 
    19 $core->themes->loadModules($core->blog->themes_path,null); 
    20  
    21 # Theme screenshot 
     28$core->themes->loadModules($core->blog->themes_path, null); 
     29 
     30# -- Repository helper -- 
     31$repository = new dcRepository( 
     32     $core->themes,  
     33     $core->blog->settings->system->repository_theme_url 
     34); 
     35$repository->check(); 
     36 
     37# -- Page helper -- 
     38$list = new adminThemesList( 
     39     $core,  
     40     $core->blog->themes_path, 
     41     false 
     42); 
     43 
     44# -- Theme screenshot -- 
    2245if (!empty($_GET['shot']) && $core->themes->moduleExists($_GET['shot'])) 
    2346{ 
     
    4366} 
    4467 
    45 $can_install = $core->auth->isSuperAdmin(); 
    46 $is_writable = is_dir($core->blog->themes_path) && is_writable($core->blog->themes_path); 
    47 $default_tab = 'themes-list'; 
    48  
    49 # Selecting theme 
    50 if (!empty($_POST['theme']) && !empty($_POST['select']) && empty($_REQUEST['conf'])) 
    51 { 
    52      $core->blog->settings->addNamespace('system'); 
    53      $core->blog->settings->system->put('theme',$_POST['theme']); 
    54      $core->blog->triggerBlog(); 
    55      http::redirect('blog_theme.php?upd=1'); 
    56 } 
    57  
    58 if ($can_install && !empty($_POST['theme']) && !empty($_POST['remove']) && empty($_REQUEST['conf'])) 
    59 { 
    60      try 
    61      { 
    62           if ($_POST['theme'] == 'default') { 
    63                throw new Exception(__('You can\'t remove default theme.')); 
    64           } 
    65            
    66           if (!$core->themes->moduleExists($_POST['theme'])) { 
    67                throw new Exception(__('Theme does not exist.')); 
    68           } 
    69            
    70           $theme = $core->themes->getModules($_POST['theme']); 
    71            
    72           # --BEHAVIOR-- themeBeforeDelete 
    73           $core->callBehavior('themeBeforeDelete',$theme); 
    74            
    75           $core->themes->deleteModule($_POST['theme']); 
    76            
    77           # --BEHAVIOR-- themeAfterDelete 
    78           $core->callBehavior('themeAfterDelete',$theme); 
    79            
    80           http::redirect('blog_theme.php?del=1'); 
    81      } 
    82      catch (Exception $e) 
    83      { 
     68# -- Check for module configuration -- 
     69$conf_file = false; 
     70if (!empty($_REQUEST['conf']) && !empty($_REQUEST['module'])) { 
     71     if (!$core->themes->moduleExists($_REQUEST['module'])) { 
     72          $core->error->add(__('Unknow module ID')); 
     73     } 
     74     else { 
     75          $module = $core->themes->getModules($_REQUEST['module']); 
     76          $module = adminModulesList::parseModuleInfo($_REQUEST['module'], $module); 
     77 
     78          if (!file_exists(path::real($module['root'].'/_config.php'))) { 
     79               $core->error->add(__('This module has no configuration file.')); 
     80          } 
     81          else { 
     82               $conf_file = path::real($module['root'].'/_config.php'); 
     83          } 
     84     } 
     85} 
     86 
     87# -- Display module configuration page -- 
     88if ($conf_file) { 
     89     dcPage::open(__('Blog appearance'), 
     90 
     91          # --BEHAVIOR-- themesToolsHeaders 
     92          $core->callBehavior('themesToolsHeaders', $core, $module['id']), 
     93 
     94          dcPage::breadcrumb( 
     95               array( 
     96                    html::escapeHTML($core->blog->name) => '', 
     97                    __('Blog appearance') => 'blog_theme.php', 
     98                    '<span class="page-title">'.__('Theme configuration').'</span>' => '' 
     99               )) 
     100     ); 
     101 
     102     if (!empty($_GET['done'])){ 
     103          dcPage::success(__('Theme successfully configured.')); 
     104     } 
     105 
     106     try { 
     107          if (!$module['standalone_config']) { 
     108               echo 
     109               '<form id="module_config" action="'.$list->getPageURL('conf=1').'" method="post" enctype="multipart/form-data">'. 
     110               '<h3>'.sprintf(__('Configure theme "%s"'), html::escapeHTML($module['name'])).'</h3>'. 
     111               '<p><a class="back" href="'.$list->getPageURL().'#themes">'.__('Back').'</a></p>'; 
     112          } 
     113          define('DC_CONTEXT_THEME', true); 
     114 
     115          include $conf_file; 
     116 
     117          if (!$module['standalone_config']) { 
     118               echo 
     119               '<p class="clear"><input type="submit" name="save" value="'.__('Save').'" />'. 
     120               form::hidden('module', $module['id']). 
     121               $core->formNonce().'</p>'. 
     122               '</form>'; 
     123          } 
     124     } 
     125     catch (Exception $e) { 
     126          echo '<div class="error"><p>'.$e->getMessage().'</p></div>'; 
     127     } 
     128 
     129     dcPage::close(); 
     130 
     131     # Stop reading code here 
     132     return; 
     133} 
     134 
     135# -- Execute actions -- 
     136if (!empty($_POST) && empty($_REQUEST['conf']) && $core->auth->isSuperAdmin() && $list->isPathWritable()) { 
     137     try { 
     138          $list->executeAction('themes', $core->themes, $repository); 
     139     } 
     140     catch (Exception $e) { 
    84141          $core->error->add($e->getMessage()); 
    85142     } 
    86143} 
    87144 
    88 # Theme upload 
    89 if ($can_install && $is_writable && ((!empty($_POST['upload_pkg']) && !empty($_FILES['pkg_file'])) || 
    90      (!empty($_POST['fetch_pkg']) && !empty($_POST['pkg_url'])))) 
    91 { 
    92      try 
    93      { 
    94           if (empty($_POST['your_pwd']) || !$core->auth->checkPassword(crypt::hmac(DC_MASTER_KEY,$_POST['your_pwd']))) { 
    95                throw new Exception(__('Password verification failed')); 
    96           } 
    97            
    98           if (!empty($_POST['upload_pkg'])) 
    99           { 
    100                files::uploadStatus($_FILES['pkg_file']); 
    101                 
    102                $dest = $core->blog->themes_path.'/'.$_FILES['pkg_file']['name']; 
    103                if (!move_uploaded_file($_FILES['pkg_file']['tmp_name'],$dest)) { 
    104                     throw new Exception(__('Unable to move uploaded file.')); 
    105                } 
    106           } 
    107           else 
    108           { 
    109                $url = urldecode($_POST['pkg_url']); 
    110                $dest = $core->blog->themes_path.'/'.basename($url); 
    111                 
    112                try 
    113                { 
    114                     $client = netHttp::initClient($url,$path); 
    115                     $client->setUserAgent('Dotclear - http://www.dotclear.org/'); 
    116                     $client->useGzip(false); 
    117                     $client->setPersistReferers(false); 
    118                     $client->setOutput($dest); 
    119                     $client->get($path); 
    120                } 
    121                catch( Exception $e) 
    122                { 
    123                     throw new Exception(__('An error occurred while downloading the file.')); 
    124                } 
    125                 
    126                unset($client); 
    127           } 
    128            
    129           $ret_code = dcModules::installPackage($dest,$core->themes); 
    130           http::redirect('blog_theme.php?added='.$ret_code); 
    131      } 
    132      catch (Exception $e) 
    133      { 
    134           $core->error->add($e->getMessage()); 
    135           $default_tab = 'add-theme'; 
    136      } 
    137 } 
    138  
    139 $theme_conf_mode = false; 
    140 if (!empty($_REQUEST['conf'])) 
    141 { 
    142      $theme_conf_file = path::real($core->blog->themes_path.'/'.$core->blog->settings->system->theme).'/_config.php'; 
    143      if (file_exists($theme_conf_file)) { 
    144           $theme_conf_mode = true; 
    145      } 
    146 } 
    147  
    148 function display_theme_details($id,$details,$current) 
    149 { 
    150      global $core; 
    151       
    152      $screenshot = 'images/noscreenshot.png'; 
    153      if (file_exists($core->blog->themes_path.'/'.$id.'/screenshot.jpg')) { 
    154           $screenshot = 'blog_theme.php?shot='.rawurlencode($id); 
    155      } 
    156       
    157      $radio_id = 'theme_'.html::escapeHTML($id); 
    158      if (preg_match('#^http(s)?://#',$core->blog->settings->system->themes_url)) { 
    159           $theme_url = http::concatURL($core->blog->settings->system->themes_url,'/'.$id); 
    160      } else { 
    161           $theme_url = http::concatURL($core->blog->url,$core->blog->settings->system->themes_url.'/'.$id); 
    162      } 
    163      $has_conf = file_exists(path::real($core->blog->themes_path.'/'.$id).'/_config.php'); 
    164      $has_css = file_exists(path::real($core->blog->themes_path.'/'.$id).'/style.css'); 
    165      $parent = $core->themes->moduleInfo($id,'parent'); 
    166      $has_parent = (boolean)$parent; 
    167      if ($has_parent) { 
    168           $is_parent_present = $core->themes->moduleExists($parent); 
    169      } 
    170       
    171      $res = 
    172      '<div class="theme-details'.($current ? ' current-theme' : '').'">'. 
    173      '<div class="theme-shot"><img src="'.$screenshot.'" alt="" /></div>'. 
    174      '<div class="theme-info">'. 
    175           '<h4>'.form::radio(array('theme',$radio_id),html::escapeHTML($id),$current,'','',($has_parent && !$is_parent_present)).' '. 
    176           '<label class="classic" for="'.$radio_id.'">'. 
    177           html::escapeHTML($details['name']).'</label></h4>'. 
    178           '<p><span class="theme-desc">'.html::escapeHTML($details['desc']).'</span> '. 
    179           '<span class="theme-author">'.sprintf(__('by %s'),html::escapeHTML($details['author'])).'</span> '. 
    180           '<span class="theme-version">'.sprintf(__('version %s'),html::escapeHTML($details['version'])).'</span> '; 
    181           if ($has_parent) { 
    182                if ($is_parent_present) { 
    183                     $res .= '<span class="theme-parent-ok">'.sprintf(__('(built on "%s")'),html::escapeHTML($parent)).'</span> '; 
    184                } else { 
    185                     $res .= '<span class="theme-parent-missing">'.sprintf(__('(requires "%s")'),html::escapeHTML($parent)).'</span> '; 
    186                } 
    187           } 
    188           if ($has_css) { 
    189                $res .= '<span class="theme-css"><a href="'.$theme_url.'/style.css">'.__('Stylesheet').'</a></span>'; 
    190           } 
    191           $res .= '</p>'; 
    192      $res .= 
    193      '</div>'. 
    194      '<div class="theme-actions">'; 
    195           if ($current && $has_conf) { 
    196                $res .= '<p><a href="blog_theme.php?conf=1" class="button">'.__('Configure theme').'</a></p>'; 
    197           } 
    198           if ($current) { 
    199                # --BEHAVIOR-- adminCurrentThemeDetails 
    200                $res .= $core->callBehavior('adminCurrentThemeDetails',$core,$id,$details); 
    201           } 
    202      $res .= 
    203      '</div>'. 
    204      '</div>'; 
    205       
    206      return $res; 
    207 } 
    208  
    209 if (!$theme_conf_mode) 
    210 { 
    211      $breadcrumb = dcPage::breadcrumb( 
     145# -- Page header -- 
     146dcPage::open(__('Themes management'), 
     147//   (!$conf_file ? dcPage::jsLoad('js/_blog_theme.js') : ''). 
     148     dcPage::jsPageTabs(). 
     149     dcPage::jsColorPicker(), 
     150 
     151     # --BEHAVIOR-- themesToolsHeaders 
     152     $core->callBehavior('themesToolsHeaders', $core, false), 
     153 
     154     dcPage::breadcrumb( 
    212155          array( 
    213156               html::escapeHTML($core->blog->name) => '', 
    214                __('Blog appearance') => '' 
    215           )); 
    216 } else { 
    217      $breadcrumb = dcPage::breadcrumb( 
    218           array( 
    219                html::escapeHTML($core->blog->name) => '', 
    220                __('Blog appearance') => 'blog_theme.php', 
    221                __('Theme configuration') => '' 
    222           )); 
    223 } 
    224  
    225 dcPage::open(__('Blog appearance'), 
    226      (!$theme_conf_mode ? dcPage::jsLoad('js/_blog_theme.js') : ''). 
    227      dcPage::jsPageTabs($default_tab). 
    228      dcPage::jsColorPicker(), 
    229      $breadcrumb 
     157               '<span class="page-title">'.__('Blog appearance').'</span>' => '' 
     158          )) 
    230159); 
    231160 
    232 if (!$theme_conf_mode) 
    233 { 
    234      if (!empty($_GET['upd'])) { 
    235           dcPage::success(__('Theme has been successfully changed.')); 
    236      } 
    237       
    238      if (!empty($_GET['added'])) { 
    239           dcPage::success(($_GET['added'] == 2 ? __('Theme has been successfully upgraded') : __('Theme has been successfully installed.'))); 
    240      } 
    241       
    242      if (!empty($_GET['del'])) { 
    243           dcPage::success(__('Theme has been successfully deleted.')); 
    244      } 
    245       
    246      # Themes list 
    247      echo '<div class="multi-part" id="themes-list" title="'.__('Themes').'">'. 
    248      '<h3>'.__('Available themes in your installation').'</h3>'; 
    249       
    250      $themes = $core->themes->getModules(); 
    251      if (isset($themes[$core->blog->settings->system->theme])) { 
    252           echo '<p>'.sprintf(__('You are currently using <strong>%s</strong>'),$themes[$core->blog->settings->system->theme]['name']).'.</p>'; 
    253      } 
    254       
    255      echo 
    256      '<form action="blog_theme.php" method="post" id="themes-form">'. 
    257      '<div id="themes">'; 
    258       
    259      if (isset($themes[$core->blog->settings->system->theme])) { 
    260           echo display_theme_details($core->blog->settings->system->theme,$themes[$core->blog->settings->system->theme],true); 
    261      } 
    262       
    263      foreach ($themes as $k => $v) 
    264      { 
    265           if ($core->blog->settings->system->theme == $k) { // Current theme 
    266                continue; 
    267           } 
    268           echo display_theme_details($k,$v,false); 
    269      } 
    270       
    271      echo '</div>'; 
    272       
    273      echo 
    274      '<div id="themes-actions">'. 
    275       
    276      '<p>'.$core->formNonce().'<input type="submit" name="select" value="'.__('Use selected theme').'" /> ';   
    277      if ($can_install) { 
    278           echo ' <input type="submit" class="delete" name="remove" value="'.__('Delete selected theme').'" />'; 
    279      } 
    280      echo '</p>'. 
    281       
    282      '</div>'. 
    283      '</form>'. 
     161# -- Succes messages -- 
     162if (!empty($_GET['msg'])) { 
     163     $list->displayMessage($_GET['msg']); 
     164} 
     165 
     166# -- Display modules lists -- 
     167if ($core->auth->isSuperAdmin() && $list->isPathWritable()) { 
     168 
     169     # Updated modules from repo 
     170     $modules = $repository->get(true); 
     171     if (!empty($modules)) { 
     172          echo  
     173          '<div class="multi-part" id="update" title="'.html::escapeHTML(__('Update themes')).'">'. 
     174          '<h3>'.html::escapeHTML(__('Update themes')).'</h3>'. 
     175          '<p>'.sprintf( 
     176               __('There is one theme to update available from %2$s.', 'There are %s themes to update available from %s.', count($modules)), 
     177               count($modules), 
     178               '<a href="http://dotaddict.org/dc2/themes">Dotaddict</a>' 
     179          ).'</p>'; 
     180 
     181          $list 
     182               ->newList('theme-update') 
     183               ->setModules($modules) 
     184               ->setPageTab('update') 
     185               ->displayModulesList( 
     186                    /*cols */      array('sshot', 'name', 'desc', 'author', 'version', 'current_version', 'parent'), 
     187                    /* actions */  array('update') 
     188               ); 
     189 
     190          echo 
     191          '</div>'; 
     192     } 
     193} 
     194 
     195# List all active plugins 
     196echo 
     197'<div class="multi-part" id="themes" title="'.__('Installed themes').'">'; 
     198 
     199$modules = $core->themes->getModules(); 
     200if (!empty($modules)) { 
     201 
     202     echo 
     203     '<h3>'.__('Activated themes').'</h3>'. 
     204     '<p>'.__('Manage installed themes from this list.').'</p>'; 
     205 
     206     $list 
     207          ->newList('theme-activate') 
     208          ->setModules($modules) 
     209          ->setPageTab('themes') 
     210          ->displayModulesList( 
     211               /* cols */          array('sshot', 'name', 'config', 'desc', 'author', 'version', 'parent'), 
     212               /* actions */  array('deactivate', 'delete') 
     213          ); 
     214} 
     215 
     216echo  
     217'</div>'; 
     218 
     219if ($core->auth->isSuperAdmin() && $list->isPathWritable()) { 
     220 
     221     # New modules from repo 
     222     $search = $list->getSearchQuery(); 
     223     $modules = $search ? $repository->search($search) : $repository->get(); 
     224 
     225     echo 
     226     '<div class="multi-part" id="new" title="'.__('Add themes from Dotaddict').'">'. 
     227     '<h3>'.__('Add themes from Dotaddict repository').'</h3>'; 
     228 
     229     $list 
     230          ->newList('theme-new') 
     231          ->setModules($modules) 
     232          ->setPageTab('new') 
     233          ->displaySearchForm() 
     234          ->displayNavMenu() 
     235          ->displayModulesList( 
     236               /* cols */          array('expander', 'sshot', 'name', 'config', 'desc', 'author', 'version', 'parent'), 
     237               /* actions */  array('install'), 
     238               /* nav limit */     true 
     239          ); 
     240 
     241     echo 
     242     '<p class="info vertical-separator">'.sprintf( 
     243          __("Visit %s repository, the resources center for Dotclear."), 
     244          '<a href="http://dotaddict.org/dc2/themes">Dotaddict</a>' 
     245          ). 
     246     '</p>'. 
     247 
    284248     '</div>'; 
    285       
    286      # Add a new theme 
    287      if ($can_install) 
    288      { 
    289           echo 
    290           '<div class="multi-part clear" id="add-theme" title="'.__('Install or upgrade a theme').'">'. 
    291           '<h3>'.__('Add themes to your installation').'</h3>'. 
    292           '<p class="form-note info">'.sprintf(__('You can find additional themes for your blog on %s.'), 
    293           '<a href="http://themes.dotaddict.org/galerie-dc2/">Dotaddict</a>').'</p>'; 
    294            
    295           if ($is_writable) 
    296           { 
    297                echo '<p>'.__('You can also install themes by uploading or downloading zip files.').'</p>'; 
    298                 
    299                # 'Upload theme' form 
    300                echo 
    301                '<form method="post" action="blog_theme.php" id="uploadpkg" enctype="multipart/form-data" class="fieldset">'. 
    302                '<h4>'.__('Upload a zip file').'</h4>'. 
    303                '<p class="field"><label for="pkg_file" class="classic required"><abbr title="'.__('Required field').'">*</abbr> '.__('Theme zip file:').'</label> '. 
    304                '<input type="file" name="pkg_file" id="pkg_file" /></p>'. 
    305                '<p class="field"><label for="your_pwd1" class="classic required"><abbr title="'.__('Required field').'">*</abbr> '.__('Your password:').'</label> '. 
    306                form::password(array('your_pwd','your_pwd1'),20,255).'</p>'. 
    307                '<p><input type="submit" name="upload_pkg" value="'.__('Upload theme').'" />'. 
    308                $core->formNonce().'</p>'. 
    309                '</form>'; 
    310                 
    311                # 'Fetch theme' form 
    312                echo 
    313                '<form method="post" action="blog_theme.php" id="fetchpkg" class="fieldset">'. 
    314                '<h4>'.__('Download a zip file').'</h4>'. 
    315                '<p class="field"><label for="pkg_url" class="classic required"><abbr title="'.__('Required field').'">*</abbr> '.__('Theme zip file URL:').'</label> '. 
    316                form::field(array('pkg_url','pkg_url'),40,255).'</p>'. 
    317                '<p class="field"><label for="your_pwd2" class="classic required"><abbr title="'.__('Required field').'">*</abbr> '.__('Your password:').'</label> '. 
    318                form::password(array('your_pwd','your_pwd2'),20,255).'</p>'. 
    319                '<p><input type="submit" name="fetch_pkg" value="'.__('Download theme').'" />'. 
    320                $core->formNonce().'</p>'. 
    321                '</form>'; 
    322           } 
    323           else 
    324           { 
    325                echo 
    326                '<p class="static-msg">'. 
    327                __('To enable this function, please give write access to your themes directory.'). 
    328                '</p>'; 
    329           } 
    330           echo '</div>'; 
    331      } 
    332 } 
    333 else 
    334 { 
    335      $theme_name = $core->themes->moduleInfo($core->blog->settings->system->theme,'name'); 
    336      $core->themes->loadModuleL10Nresources($core->blog->settings->system->theme,$_lang); 
    337  
    338      echo 
    339      '<p><a class="back" href="blog_theme.php">'.__('Back to Blog appearance').'</a></p>'; 
    340       
    341      try 
    342      { 
    343           # Let theme configuration set their own form(s) if required 
    344           $standalone_config = (boolean) $core->themes->moduleInfo($core->blog->settings->system->theme,'standalone_config'); 
    345  
    346           if (!$standalone_config) 
    347                echo '<form id="theme_config" action="blog_theme.php?conf=1" method="post" enctype="multipart/form-data">'; 
    348  
    349           include $theme_conf_file; 
    350  
    351           if (!$standalone_config) 
    352                echo 
    353                '<p class="clear"><input type="submit" value="'.__('Save').'" />'. 
    354                $core->formNonce().'</p>'. 
    355                '</form>'; 
    356  
    357      } 
    358      catch (Exception $e) 
    359      { 
    360           echo '<div class="error"><p>'.$e->getMessage().'</p></div>'; 
    361      } 
     249 
     250     # Add a new plugin 
     251     echo 
     252     '<div class="multi-part" id="addtheme" title="'.__('Install or upgrade manually').'">'; 
     253 
     254     echo '<p>'.__('You can install themes by uploading or downloading zip files.').'</p>'; 
     255      
     256     $list->displayManualForm(); 
     257 
     258     echo 
     259     '</div>'; 
    362260} 
    363261 
  • admin/index.php

    r2166 r2175  
    123123     } 
    124124     $__dashboard_icons['prefs'] = new ArrayObject(array(__('My preferences'),'preferences.php','images/menu/user-pref-b.png')); 
     125} 
     126 
     127# Check plugins and themes update from repository 
     128function dc_check_repository_update($mod, $url, $img, $icon) 
     129{ 
     130     $repo = new dcRepository($mod, $url); 
     131     $repo->check(); 
     132     $upd = $repo->get(true); 
     133     if (!empty($upd)) { 
     134          $icon[0] .= '<br />'.sprintf(__('An update is available', '%s updates are available.', count($upd)),count($upd)); 
     135          $icon[1] .= '#update'; 
     136          $icon[2] = 'images/menu/'.$img.'-b-update.png'; 
     137     } 
     138} 
     139if (isset($__dashboard_icons['plugins'])) { 
     140     dc_check_repository_update($core->plugins, $core->blog->settings->system->repository_plugin_url, 'plugins', $__dashboard_icons['plugins']); 
     141} 
     142if (isset($__dashboard_icons['blog_theme'])) { 
     143     $themes = new dcThemes($core); 
     144     $themes->loadModules($core->blog->themes_path, null); 
     145     dc_check_repository_update($themes, $core->blog->settings->system->repository_theme_url, 'blog-theme', $__dashboard_icons['blog_theme']); 
    125146} 
    126147 
  • admin/js/_plugins.js

    r0 r2171  
     1dotclear.moduleExpander = function(line) { 
     2        var td = line.firstChild; 
     3         
     4        var img = document.createElement('img'); 
     5        img.src = dotclear.img_plus_src; 
     6        img.alt = dotclear.img_plus_alt; 
     7        img.className = 'expand'; 
     8        $(img).css('cursor','pointer'); 
     9        img.line = line; 
     10        img.onclick = function() { dotclear.viewModuleContent(this,this.line); }; 
     11         
     12        td.insertBefore(img,td.firstChild); 
     13}; 
     14 
     15dotclear.modulesExpander = function(line,lines) { 
     16        var td = line.firstChild; 
     17 
     18        var img = document.createElement('img'); 
     19        img.src = dotclear.img_plus_src; 
     20        img.alt = dotclear.img_plus_alt; 
     21        img.className = 'expand'; 
     22        $(img).css('cursor','pointer'); 
     23        img.lines = lines; 
     24        img.onclick = function() { dotclear.viewModulesContent(this,this.lines); }; 
     25 
     26        td.insertBefore(img,td.firstChild); 
     27}; 
     28 
     29dotclear.viewModulesContent = function(img,lines) { 
     30         
     31        action = 'toggle'; 
     32 
     33        if (img.alt == dotclear.img_plus_alt) { 
     34                img.src = dotclear.img_minus_src; 
     35                img.alt = dotclear.img_minus_alt; 
     36                action = 'open'; 
     37        } else { 
     38                img.src = dotclear.img_plus_src; 
     39                img.alt = dotclear.img_plus_alt; 
     40                action = 'close'; 
     41        } 
     42         
     43        lines.each(function() { 
     44                var td = this.firstChild; 
     45                dotclear.viewModuleContent(td.firstChild,td.firstChild.line,action); 
     46        }); 
     47}; 
     48 
     49dotclear.viewModuleContent = function(img,line,action) { 
     50 
     51        var action = action || 'toggle'; 
     52          var cols = $('td',$(line)).length 
     53        var sp = line.id.split('_m_'); 
     54          var listId=sp[0]; 
     55          var moduleId= sp[1]; 
     56 
     57        var tr = document.getElementById('pe'+moduleId); 
     58         
     59          if ( !tr && ( action == 'toggle' || action == 'open' ) ) { 
     60                tr = document.createElement('tr'); 
     61                tr.id = 'pe'+moduleId; 
     62 
     63                var td = document.createElement('td'); 
     64                td.colSpan = cols; 
     65                td.className = 'expand'; 
     66                tr.appendChild(td); 
     67                 
     68                img.src = dotclear.img_minus_src; 
     69                img.alt = dotclear.img_minus_alt; 
     70                 
     71                // Get post content 
     72                $.get('services.php',{f:'getModuleById', id: moduleId, list: listId},function(data) { 
     73                        var rsp = $(data).children('rsp')[0]; 
     74                         
     75                        if (rsp.attributes[0].value == 'ok') { 
     76                                var author = $(rsp).find('author').text(); 
     77                                var details = $(rsp).find('details').text(); 
     78                                var support = $(rsp).find('support').text(); 
     79                                        var box = document.createElement('div'); 
     80                                var dl = document.createElement('ul'); 
     81                                dl.className = "mod-more"; 
     82                                 
     83                                if (author) { 
     84                                        $(dl).append($('<li class="module-author">'+dotclear.msg.module_author+' '+author+'</li>')); 
     85                                } 
     86                                if (details) { 
     87                                        var dd = ''; 
     88                                        dd += '<a class="module-details" href="'+details+'">'+dotclear.msg.module_details+'</a>'; 
     89                                        if (support) { 
     90                                                dd += ' - '; 
     91                                                dd += '<a class="module-support" href="'+support+'">'+dotclear.msg.module_support+'</a>'; 
     92                                        } 
     93                                        $(dl).append($('<li>'+dotclear.msg.module_help+' '+dd+'</li>')); 
     94                                } 
     95 
     96                                $(td).append($(box).addClass('two-boxes').append(dl)); 
     97                                 
     98                                var section = $(rsp).find('section').text(); 
     99                                var tags = $(rsp).find('tags').text(); 
     100                                 
     101                                        var boxb = document.createElement('div'); 
     102                                var dlb = document.createElement('ul'); 
     103                                dlb.className = "mod-more"; 
     104                                 
     105                                if (section) { 
     106                                        $(dlb).append($('<li class="module-section">'+dotclear.msg.module_section+' '+section+'</li>')); 
     107                                } 
     108                                if (tags) { 
     109                                        $(dlb).append($('<li class="module-tags">'+dotclear.msg.module_tags+' '+tags+'</li>')); 
     110                                } 
     111                                $(td).append($(boxb).addClass('two-boxes').append(dlb)); 
     112                        } else { 
     113                                alert($(rsp).find('message').text()); 
     114                        } 
     115                }); 
     116                 
     117                $(line).addClass('expand'); 
     118                line.parentNode.insertBefore(tr,line.nextSibling); 
     119        } 
     120        else if (tr && tr.style.display == 'none' && ( action == 'toggle' || action == 'open' ) ) 
     121        { 
     122                $(tr).css('display', 'table-row'); 
     123                $(line).addClass('expand'); 
     124                img.src = dotclear.img_minus_src; 
     125                img.alt = dotclear.img_minus_alt; 
     126        } 
     127        else if (tr && tr.style.display != 'none' && ( action == 'toggle' || action == 'close' ) ) 
     128        { 
     129                $(tr).css('display', 'none'); 
     130                $(line).removeClass('expand'); 
     131                img.src = dotclear.img_plus_src; 
     132                img.alt = dotclear.img_plus_alt; 
     133        } 
     134         
     135        parentTable = $(line).parents('table'); 
     136        if( parentTable.find('tr.expand').length == parentTable.find('tr.line').length ) { 
     137                img = parentTable.find('tr:not(.line) th:first img'); 
     138                img.attr('src',dotclear.img_minus_src); 
     139                img.attr('alt',dotclear.img_minus_alt); 
     140        } 
     141         
     142        if( parentTable.find('tr.expand').length == 0 ) { 
     143                img = parentTable.find('tr:not(.line) th:first img'); 
     144                img.attr('src',dotclear.img_plus_src); 
     145                img.attr('alt',dotclear.img_plus_alt); 
     146        } 
     147         
     148}; 
     149 
     150 
    1151$(function() { 
    2      $('table.plugins form input[type=submit][name=delete]').click(function() { 
    3           var p_name = $('input[name=plugin_id]',$(this).parent()).val(); 
    4           return window.confirm(dotclear.msg.confirm_delete_plugin.replace('%s',p_name)); 
    5      }); 
     152        $('table.modules.expandable tr:not(.line)').each(function() { 
     153                dotclear.modulesExpander(this,$('table.modules tr.line')); 
     154        }); 
     155        $('table.modules.expandable tr.line').each(function() { 
     156                dotclear.moduleExpander(this); 
     157        }); 
    6158}); 
  • admin/plugins.php

    r2166 r2175  
    1313require dirname(__FILE__).'/../inc/admin/prepend.php'; 
    1414 
    15 dcPage::checkSuper(); 
    16  
    17 $default_tab = !empty($_REQUEST['tab']) ? html::escapeHTML($_REQUEST['tab']) : 'plugins'; 
    18  
    19 $p_paths = explode(PATH_SEPARATOR, DC_PLUGINS_ROOT); 
    20 $p_path = array_pop($p_paths); 
    21 unset($p_paths); 
    22  
    23 $is_writable = false; 
    24 if (is_dir($p_path) && is_writeable($p_path)) { 
    25      $is_writable = true; 
    26      $p_path_pat = preg_quote($p_path,'!'); 
    27 } 
    28  
    29 $plugin_id = !empty($_POST['plugin_id']) ? $_POST['plugin_id'] : null; 
    30  
    31 if ($is_writable) 
    32 { 
    33      # Delete plugin 
    34      if ($plugin_id && !empty($_POST['delete'])) 
    35      { 
    36           try 
    37           { 
    38                if (empty($_POST['deactivated'])) 
    39                { 
    40                     if (!$core->plugins->moduleExists($plugin_id)) { 
    41                          throw new Exception(__('No such plugin.')); 
    42                     } 
    43                      
    44                     $plugin = $core->plugins->getModules($plugin_id); 
    45                     $plugin['id'] = $plugin_id; 
    46                      
    47                     if (!preg_match('!^'.$p_path_pat.'!', $plugin['root'])) { 
    48                          throw new Exception(__('You don\'t have permissions to delete this plugin.')); 
    49                     } 
    50                      
    51                     # --BEHAVIOR-- pluginBeforeDelete 
    52                     $core->callBehavior('pluginsBeforeDelete', $plugin); 
    53                      
    54                     $core->plugins->deleteModule($plugin_id); 
    55                      
    56                     # --BEHAVIOR-- pluginAfterDelete 
    57                     $core->callBehavior('pluginsAfterDelete', $plugin); 
    58                } 
    59                else 
    60                { 
    61                     $core->plugins->deleteModule($plugin_id,true); 
    62                } 
    63                 
    64                http::redirect('plugins.php?removed=1'); 
     15dcPage::check('admin'); 
     16 
     17# -------------------------------------------------- 
     18# @todo Add settings to Dotclear update features 
     19if ($core->blog->settings->system->plugins_allow_multi_install === null) { 
     20     $core->blog->settings->system->put( 
     21          'plugins_allow_multi_install', false, 'boolean', 'Allow multi-installation for plugins', true, true 
     22     ); 
     23} 
     24if ($core->blog->settings->system->repository_plugin_url === null) { 
     25     $core->blog->settings->system->put( 
     26          'repository_plugin_url', 'http://update.dotaddict.org/dc2/plugins.xml', 'string', 'Plugins XML feed location', true, true 
     27     ); 
     28} 
     29# -------------------------------------------------- 
     30 
     31# -- Repository helper -- 
     32$repository = new dcRepository( 
     33     $core->plugins,  
     34     $core->blog->settings->system->repository_plugin_url 
     35); 
     36$repository->check(); 
     37 
     38# -- Page helper -- 
     39$list = new adminModulesList( 
     40     $core,  
     41     DC_PLUGINS_ROOT, 
     42     $core->blog->settings->system->plugins_allow_multi_install 
     43); 
     44 
     45$list::setDistributedModules(array( 
     46     'aboutConfig', 
     47     'akismet', 
     48     'antispam', 
     49     'attachments', 
     50     'blogroll', 
     51     'blowupConfig', 
     52     'daInstaller', 
     53     'fairTrackbacks', 
     54     'importExport', 
     55     'maintenance', 
     56     'pages', 
     57     'pings', 
     58     'simpleMenu', 
     59     'tags', 
     60     'themeEditor', 
     61     'userPref', 
     62     'widgets' 
     63)); 
     64 
     65# -- Check for module configuration -- 
     66$conf_file = false; 
     67if (!empty($_REQUEST['conf']) && !empty($_REQUEST['module'])) { 
     68     if (!$core->plugins->moduleExists($_REQUEST['module'])) { 
     69          $core->error->add(__('Unknow module ID')); 
     70     } 
     71     else { 
     72          $module = $core->plugins->getModules($_REQUEST['module']); 
     73          $module = adminModulesList::parseModuleInfo($_REQUEST['module'], $module); 
     74 
     75          if (!file_exists(path::real($module['root'].'/_config.php'))) { 
     76               $core->error->add(__('This module has no configuration file.')); 
    6577          } 
    66           catch (Exception $e) 
    67           { 
    68                $core->error->add($e->getMessage()); 
     78          else { 
     79               $conf_file = path::real($module['root'].'/_config.php'); 
    6980          } 
    7081     } 
    71      # Deactivate plugin 
    72      elseif ($plugin_id && !empty($_POST['deactivate'])) 
    73      { 
    74           try 
    75           { 
    76                if (!$core->plugins->moduleExists($plugin_id)) { 
    77                     throw new Exception(__('No such plugin.')); 
    78                } 
    79                 
    80                $plugin = $core->plugins->getModules($plugin_id); 
    81                $plugin['id'] = $plugin_id; 
    82                 
    83                if (!$plugin['root_writable']) { 
    84                     throw new Exception(__('You don\'t have permissions to deactivate this plugin.')); 
    85                } 
    86                 
    87                # --BEHAVIOR-- pluginBeforeDeactivate 
    88                $core->callBehavior('pluginsBeforeDeactivate', $plugin); 
    89                      
    90                $core->plugins->deactivateModule($plugin_id); 
    91  
    92                # --BEHAVIOR-- pluginAfterDeactivate 
    93                $core->callBehavior('pluginsAfterDeactivate', $plugin); 
    94                      
    95                http::redirect('plugins.php'); 
     82} 
     83 
     84# -- Display module configuration page -- 
     85if ($conf_file) { 
     86     dcPage::open(__('Plugins management'), 
     87 
     88          # --BEHAVIOR-- pluginsToolsHeaders 
     89          $core->callBehavior('pluginsToolsHeaders', $core, $module['id']), 
     90 
     91          dcPage::breadcrumb( 
     92               array( 
     93                    html::escapeHTML($core->blog->name) => '', 
     94                    '<a href="'.$list->getPageURL().'">'.__('Plugins management').'</a>' => '', 
     95                    '<span class="page-title">'.__('Plugin configuration').'</span>' => '' 
     96               )) 
     97     ); 
     98 
     99     if (!empty($_GET['done'])){ 
     100          dcPage::success(__('Plugin successfully configured.')); 
     101     } 
     102 
     103     try { 
     104          if (!$module['standalone_config']) { 
     105               echo 
     106               '<form id="module_config" action="'.$list->getPageURL('conf=1').'" method="post" enctype="multipart/form-data">'. 
     107               '<h3>'.sprintf(__('Configure plugin "%s"'), html::escapeHTML($module['name'])).'</h3>'. 
     108               '<p><a class="back" href="'.$list->getPageURL().'#plugins">'.__('Back').'</a></p>'; 
    96109          } 
    97           catch (Exception $e) 
    98           { 
    99                $core->error->add($e->getMessage()); 
     110          define('DC_CONTEXT_PLUGIN', true); 
     111 
     112          include $conf_file; 
     113 
     114          if (!$module['standalone_config']) { 
     115               echo 
     116               '<p class="clear"><input type="submit" name="save" value="'.__('Save').'" />'. 
     117               form::hidden('module', $module['id']). 
     118               $core->formNonce().'</p>'. 
     119               '</form>'; 
    100120          } 
    101121     } 
    102      # Activate plugin 
    103      elseif ($plugin_id && !empty($_POST['activate'])) 
    104      { 
    105           try 
    106           { 
    107                $p = $core->plugins->getDisabledModules(); 
    108                if (!isset($p[$plugin_id])) { 
    109                     throw new Exception(__('No such plugin.')); 
    110                } 
    111  
    112                # --BEHAVIOR-- pluginBeforeActivate 
    113                $core->callBehavior('pluginsBeforeActivate', $plugin_id); 
    114                 
    115                $core->plugins->activateModule($plugin_id); 
    116  
    117                # --BEHAVIOR-- pluginAfterActivate 
    118                $core->callBehavior('pluginsAfterActivate', $plugin_id); 
    119                 
    120                http::redirect('plugins.php'); 
    121           } 
    122           catch (Exception $e) 
    123           { 
    124                $core->error->add($e->getMessage()); 
    125           } 
    126      } 
    127      # Plugin upload 
    128      elseif ((!empty($_POST['upload_pkg']) && !empty($_FILES['pkg_file'])) || 
    129           (!empty($_POST['fetch_pkg']) && !empty($_POST['pkg_url']))) 
    130      { 
    131           try 
    132           { 
    133                if (empty($_POST['your_pwd']) || !$core->auth->checkPassword(crypt::hmac(DC_MASTER_KEY,$_POST['your_pwd']))) { 
    134                     throw new Exception(__('Password verification failed')); 
    135                } 
    136                 
    137                if (!empty($_POST['upload_pkg'])) 
    138                { 
    139                     files::uploadStatus($_FILES['pkg_file']); 
    140                      
    141                     $dest = $p_path.'/'.$_FILES['pkg_file']['name']; 
    142                     if (!move_uploaded_file($_FILES['pkg_file']['tmp_name'],$dest)) { 
    143                          throw new Exception(__('Unable to move uploaded file.')); 
    144                     } 
    145                } 
    146                else 
    147                { 
    148                     $url = urldecode($_POST['pkg_url']); 
    149                     $dest = $p_path.'/'.basename($url); 
    150                      
    151                     try 
    152                     { 
    153                          $client = netHttp::initClient($url,$path); 
    154                          $client->setUserAgent('Dotclear - http://www.dotclear.org/'); 
    155                          $client->useGzip(false); 
    156                          $client->setPersistReferers(false); 
    157                          $client->setOutput($dest); 
    158                          $client->get($path); 
    159                     } 
    160                     catch( Exception $e) 
    161                     { 
    162                          throw new Exception(__('An error occurred while downloading the file.')); 
    163                     } 
    164                      
    165                     unset($client); 
    166                } 
    167  
    168                # --BEHAVIOR-- pluginBeforeAdd 
    169                $core->callBehavior('pluginsBeforeAdd', $plugin_id); 
    170                                
    171                $ret_code = $core->plugins->installPackage($dest,$core->plugins); 
    172  
    173                # --BEHAVIOR-- pluginAfterAdd 
    174                $core->callBehavior('pluginsAfterAdd', $plugin_id); 
    175                 
    176                http::redirect('plugins.php?added='.$ret_code); 
    177           } 
    178           catch (Exception $e) 
    179           { 
    180                $core->error->add($e->getMessage()); 
    181                $default_tab = 'addplugin'; 
    182           } 
    183      } 
    184 } 
    185  
    186 # Plugin install 
    187 $plugins_install = $core->plugins->installModules(); 
    188  
    189 /* DISPLAY Main page 
    190 -------------------------------------------------------- */ 
     122     catch (Exception $e) { 
     123          echo '<div class="error"><p>'.$e->getMessage().'</p></div>'; 
     124     } 
     125 
     126     dcPage::close(); 
     127 
     128     # Stop reading code here 
     129     return; 
     130} 
     131 
     132# -- Execute actions -- 
     133if (!empty($_POST) && empty($_REQUEST['conf']) && $core->auth->isSuperAdmin() && $list->isPathWritable()) { 
     134     try { 
     135          $list->executeAction('plugins', $core->plugins, $repository); 
     136     } 
     137     catch (Exception $e) { 
     138          $core->error->add($e->getMessage()); 
     139     } 
     140} 
     141 
     142# -- Plugin install -- 
     143$plugins_install = null; 
     144if (!$core->error->flag()) { 
     145     $plugins_install = $core->plugins->installModules(); 
     146} 
     147 
     148# -- Page header -- 
    191149dcPage::open(__('Plugins management'), 
    192150     dcPage::jsLoad('js/_plugins.js'). 
    193      dcPage::jsPageTabs($default_tab), 
     151     dcPage::jsPageTabs(). 
     152 
     153     # --BEHAVIOR-- pluginsToolsHeaders 
     154     $core->callBehavior('pluginsToolsHeaders', $core, false), 
     155 
    194156     dcPage::breadcrumb( 
    195157          array( 
     
    199161); 
    200162 
    201 if (!empty($_GET['removed'])) { 
    202      dcPage::success(__('Plugin has been successfully deleted.')); 
    203 } 
    204 if (!empty($_GET['added'])) { 
    205      dcPage::success(($_GET['added'] == 2 ? __('Plugin has been successfully upgraded') : __('Plugin has been successfully installed.'))); 
    206 } 
    207  
    208 # Plugins install messages 
    209 if (!empty($plugins_install['success'])) 
    210 { 
    211      echo '<div class="static-msg">'.__('Following plugins have been installed:').'<ul>'; 
     163# -- Succes messages -- 
     164if (!empty($_GET['msg'])) { 
     165     $list->displayMessage($_GET['msg']); 
     166} 
     167 
     168# -- Plugins install messages -- 
     169if (!empty($plugins_install['success'])) { 
     170     echo  
     171     '<div class="static-msg">'.__('Following plugins have been installed:').'<ul>'; 
    212172     foreach ($plugins_install['success'] as $k => $v) { 
    213           echo '<li>'.$k.'</li>'; 
    214      } 
    215      echo '</ul></div>'; 
    216 } 
    217 if (!empty($plugins_install['failure'])) 
    218 { 
    219      echo '<div class="error">'.__('Following plugins have not been installed:').'<ul>'; 
     173          echo  
     174          '<li>'.$k.'</li>'; 
     175     } 
     176     echo  
     177     '</ul></div>'; 
     178} 
     179if (!empty($plugins_install['failure'])) { 
     180     echo  
     181     '<div class="error">'.__('Following plugins have not been installed:').'<ul>'; 
    220182     foreach ($plugins_install['failure'] as $k => $v) { 
    221           echo '<li>'.$k.' ('.$v.')</li>'; 
    222      } 
    223      echo '</ul></div>'; 
     183          echo  
     184          '<li>'.$k.' ('.$v.')</li>'; 
     185     } 
     186     echo  
     187     '</ul></div>'; 
     188} 
     189 
     190# -- Display modules lists -- 
     191if ($core->auth->isSuperAdmin() && $list->isPathWritable()) { 
     192 
     193     # Updated modules from repo 
     194     $modules = $repository->get(true); 
     195     if (!empty($modules)) { 
     196          echo  
     197          '<div class="multi-part" id="update" title="'.html::escapeHTML(__('Update plugins')).'">'. 
     198          '<h3>'.html::escapeHTML(__('Update plugins')).'</h3>'. 
     199          '<p>'.sprintf( 
     200               __('There is one plugin to update available from %2$s.', 'There are %s plugins to update available from %s.', count($modules)), 
     201               count($modules), 
     202               '<a href="http://dotaddict.org/dc2/plugins">Dotaddict</a>' 
     203          ).'</p>'; 
     204 
     205          $list 
     206               ->newList('plugin-update') 
     207               ->setModules($modules) 
     208               ->setPageTab('update') 
     209               ->displayModulesList( 
     210                    /*cols */      array('icon', 'name', 'version', 'current_version', 'desc'), 
     211                    /* actions */  array('update') 
     212               ); 
     213 
     214          echo 
     215          '</div>'; 
     216     } 
    224217} 
    225218 
    226219# List all active plugins 
    227 echo '<p>'.__('Plugins add new functionalities to Dotclear. '. 
    228 'Here you can activate or deactivate installed plugins.').'</p>'; 
    229  
    230 echo (!$core->plugins->moduleExists('daInstaller') ? 
    231      sprintf('<p><strong>'.__('You can find additional plugins for your blog on %s.').'</strong></p>', 
    232           '<a href="http://plugins.dotaddict.org/dc2/">Dotaddict</a>') : 
    233      sprintf('<p><strong>'.__('You can find additional plugins for your blog on %s or using the %s.').'</strong></p>', 
    234           '<a href="http://plugins.dotaddict.org/dc2/">Dotaddict</a>', 
    235           '<a href="plugin.php?p=daInstaller">'.__('DotAddict.org Installer').'</a>')); 
    236  
    237 if ($is_writable) { 
    238      echo '<p>'.__('To install or upgrade a plugin you generally just need to upload it '. 
    239      'in "Install or upgrade a plugin" section.'); 
    240 } else { 
    241      echo '<p>'.__('To install or upgrade a plugin you just need to extract it in your plugins directory.'); 
    242 } 
    243 echo '</p>'; 
    244  
    245220echo 
    246 '<div class="multi-part" id="plugins" title="'.__('Plugins').'">'; 
    247  
    248 $p_available = $core->plugins->getModules(); 
    249 uasort($p_available,create_function('$a,$b','return strcasecmp($a["name"],$b["name"]);')); 
    250 if (!empty($p_available))  
    251 { 
     221'<div class="multi-part" id="plugins" title="'.__('Installed plugins').'">'; 
     222 
     223$modules = $core->plugins->getModules(); 
     224if (!empty($modules)) { 
     225 
    252226     echo 
    253227     '<h3>'.__('Activated plugins').'</h3>'. 
    254      '<div class="table-outer clear">'. 
    255      '<table class="plugins"><tr>'. 
    256      '<th>'.__('Plugin').'</th>'. 
    257      '<th class="nowrap">'.__('Version').'</th>'. 
    258      '<th class="nowrap">'.__('Details').'</th>'. 
    259      '<th class="nowrap">'.__('Action').'</th>'. 
    260      '</tr>'; 
    261       
    262      $distrib_plugins = array('aboutConfig','akismet','antispam','attachments','blogroll','blowupConfig','daInstaller', 
    263           'fairTrackbacks','importExport','maintenance','pages','pings','simpleMenu','tags','themeEditor','userPref','widgets'); 
    264      $distrib_img = '<img src="images/dotclear_pw.png"'. 
    265           ' alt="'.__('Plugin from official distribution').'" title="'.__('Plugin from official distribution').'" />'; 
    266  
    267      foreach ($p_available as $k => $v) 
    268      { 
    269           $is_deletable = $is_writable && preg_match('!^'.$p_path_pat.'!',$v['root']); 
    270           $is_deactivable = $v['root_writable']; 
    271           $is_distrib = in_array($k, $distrib_plugins); 
    272            
    273           echo 
    274           '<tr class="line wide">'. 
    275           '<td class="minimal nowrap"><strong>'.html::escapeHTML($k).'</strong></td>'. 
    276           '<td class="minimal">'.html::escapeHTML($v['version']).'</td>'. 
    277           '<td class="maximal'.($is_distrib ? ' distrib' : '').'"><strong>'.html::escapeHTML(__($v['name'])).'</strong> '. 
    278           '<br />'.html::escapeHTML(__($v['desc'])).($is_distrib ? ' '.$distrib_img : '').'</td>'. 
    279           '<td class="nowrap action">'; 
    280            
    281           if ($is_deletable || $is_deactivable) 
    282           { 
    283                echo 
    284                '<form action="plugins.php" method="post">'. 
    285                '<div>'. 
    286                $core->formNonce(). 
    287                form::hidden(array('plugin_id'),html::escapeHTML($k)). 
    288                ($is_deactivable ? '<input type="submit" name="deactivate" value="'.__('Deactivate').'" /> ' : ''). 
    289                ($is_deletable ? '<input type="submit" class="delete" name="delete" value="'.__('Delete').'" /> ' : ''). 
    290                '</div>'. 
    291                '</form>'; 
    292           } 
    293            
    294           echo 
    295           '</td>'. 
    296           '</tr>'; 
    297      } 
    298      echo 
    299      '</table></div>'; 
    300 } 
    301  
    302 $p_disabled = $core->plugins->getDisabledModules(); 
    303 uksort($p_disabled,create_function('$a,$b','return strcasecmp($a,$b);')); 
    304 if (!empty($p_disabled)) 
    305 { 
     228     '<p>'.__('Manage installed plugins from this list.').'</p>'; 
     229 
     230     $list 
     231          ->newList('plugin-activate') 
     232          ->setModules($modules) 
     233          ->setPageTab('plugins') 
     234          ->displayModulesList( 
     235               /* cols */          array('expander', 'icon', 'name', 'config', 'version', 'desc', 'distrib'), 
     236               /* actions */  array('deactivate', 'delete') 
     237          ); 
     238} 
     239 
     240# Deactivated modules 
     241$modules = $core->plugins->getDisabledModules(); 
     242if (!empty($modules)) { 
     243 
    306244     echo 
    307245     '<h3>'.__('Deactivated plugins').'</h3>'. 
    308      '<div class="clear table-outer">'. 
    309      '<table class="plugins"><tr>'. 
    310      '<th>'.__('Plugin').'</th>'. 
    311      '<th class="nowrap">'.__('Action').'</th>'. 
    312      '</tr>'; 
    313       
    314      foreach ($p_disabled as $k => $v) 
    315      { 
    316           $is_deletable = $is_writable && preg_match('!^'.$p_path_pat.'!',$v['root']); 
    317           $is_activable = $v['root_writable']; 
    318            
    319           echo 
    320           '<tr class="line wide">'. 
    321           '<td class="maximal nowrap"><strong>'.html::escapeHTML($k).'</strong></td>'. 
    322           '<td class="nowrap action">'; 
    323            
    324           if ($is_deletable || $is_activable) 
    325           { 
    326                echo 
    327                '<form action="plugins.php" method="post">'. 
    328                '<div>'. 
    329                $core->formNonce(). 
    330                form::hidden(array('plugin_id'),html::escapeHTML($k)). 
    331                form::hidden(array('deactivated'),1). 
    332                ($is_activable ? '<input type="submit" name="activate" value="'.__('Activate').'" /> ' : ''). 
    333                ($is_deletable ? '<input type="submit" class="delete" name="delete" value="'.__('Delete').'" /> ' : ''). 
    334                '</div>'. 
    335                '</form>'; 
    336           } 
    337            
    338           echo 
    339           '</td>'. 
    340           '</tr>'; 
    341      } 
    342      echo 
    343      '</table></div>'; 
    344 } 
    345  
    346 echo '</div>'; 
    347  
    348 # Add a new plugin 
    349 echo 
    350 '<div class="multi-part" id="addplugin" title="'.__('Install or upgrade a plugin').'">'; 
    351  
    352 if ($is_writable) 
    353 { 
     246     '<p>'.__('Deactivated plugins are installed but not usable. You can activate them from here.').'</p>'; 
     247 
     248     $list 
     249          ->newList('plugin-deactivate') 
     250          ->setModules($modules) 
     251          ->setPageTab('plugins') 
     252          ->displayModulesList( 
     253               /* cols */          array('icon', 'name', 'distrib'), 
     254               /* actions */  array('activate', 'delete') 
     255          ); 
     256} 
     257 
     258echo  
     259'</div>'; 
     260 
     261if ($core->auth->isSuperAdmin() && $list->isPathWritable()) { 
     262 
     263     # New modules from repo 
     264     $search = $list->getSearchQuery(); 
     265     $modules = $search ? $repository->search($search) : $repository->get(); 
     266 
     267     echo 
     268     '<div class="multi-part" id="new" title="'.__('Add plugins from Dotaddict').'">'. 
     269     '<h3>'.__('Add plugins from Dotaddict repository').'</h3>'; 
     270 
     271     $list 
     272          ->newList('plugin-new') 
     273          ->setModules($modules) 
     274          ->setPageTab('new') 
     275          ->displaySearchForm() 
     276          ->displayNavMenu() 
     277          ->displayModulesList( 
     278               /* cols */          array('expander', 'name', 'version', 'desc'), 
     279               /* actions */  array('install'), 
     280               /* nav limit */     true 
     281          ); 
     282 
     283     echo 
     284     '<p class="info vertical-separator">'.sprintf( 
     285          __("Visit %s repository, the resources center for Dotclear."), 
     286          '<a href="http://dotaddict.org/dc2/plugins">Dotaddict</a>' 
     287          ). 
     288     '</p>'. 
     289 
     290     '</div>'; 
     291 
     292     # Add a new plugin 
     293     echo 
     294     '<div class="multi-part" id="addplugin" title="'.__('Install or upgrade manually').'">'; 
     295 
    354296     echo '<p>'.__('You can install plugins by uploading or downloading zip files.').'</p>'; 
    355297      
    356      # 'Upload plugin' form 
    357      echo 
    358      '<form method="post" action="plugins.php" id="uploadpkg" enctype="multipart/form-data" class="fieldset">'. 
    359      '<h3>'.__('Upload a zip file').'</h3>'. 
    360      '<p class="field"><label for="pkg_file" class="classic required"><abbr title="'.__('Required field').'">*</abbr> '.__('Plugin zip file:').'</label> '. 
    361      '<input type="file" id="pkg_file" name="pkg_file" /></p>'. 
    362      '<p class="field"><label for="your_pwd1" class="classic required"><abbr title="'.__('Required field').'">*</abbr> '.__('Your password:').'</label> '. 
    363      form::password(array('your_pwd','your_pwd1'),20,255).'</p>'. 
    364      '<p><input type="submit" name="upload_pkg" value="'.__('Upload plugin').'" />'. 
    365      $core->formNonce(). 
    366      '</p>'. 
    367      '</form>'; 
    368       
    369      # 'Fetch plugin' form 
    370      echo 
    371      '<form method="post" action="plugins.php" id="fetchpkg" class="fieldset">'. 
    372      '<h3>'.__('Download a zip file').'</h3>'. 
    373      '<p class="field"><label for="pkg_url" class="classic required"><abbr title="'.__('Required field').'">*</abbr> '.__('Plugin zip file URL:').'</label> '. 
    374      form::field(array('pkg_url','pkg_url'),40,255).'</p>'. 
    375      '<p class="field"><label for="your_pwd2" class="classic required"><abbr title="'.__('Required field').'">*</abbr> '.__('Your password:').'</label> '. 
    376      form::password(array('your_pwd','your_pwd2'),20,255).'</p>'. 
    377      '<p><input type="submit" name="fetch_pkg" value="'.__('Download plugin').'" />'. 
    378      $core->formNonce().'</p>'. 
    379      '</form>'; 
    380 } 
    381 else 
    382 { 
    383      echo 
    384      '<p class="static-msg">'. 
    385      __('To enable this function, please give write access to your plugins directory.'). 
    386      '</p>'; 
    387 } 
    388 echo '</div>'; 
     298     $list->displayManualForm(); 
     299 
     300     echo 
     301     '</div>'; 
     302} 
    389303 
    390304# --BEHAVIOR-- pluginsToolsTabs 
    391 $core->callBehavior('pluginsToolsTabs',$core); 
     305$core->callBehavior('pluginsToolsTabs', $core); 
     306 
     307# -- Notice for super admin -- 
     308if ($core->auth->isSuperAdmin() && !$list->isPathWritable()) { 
     309     echo  
     310     '<p class="warning">'.__('Some functions are disabled, please give write access to your plugins directory to enable them.').'</p>'; 
     311} 
    392312 
    393313dcPage::close(); 
  • admin/services.php

    r1699 r2174  
    2727$core->rest->addFunction('searchMeta',array('dcRestMethods','searchMeta')); 
    2828$core->rest->addFunction('setSectionFold',array('dcRestMethods','setSectionFold')); 
     29$core->rest->addFunction('getModuleById',array('dcRestMethods','getModuleById')); 
    2930 
    3031$core->rest->serve(); 
     
    442443          return true; 
    443444     } 
    444            
    445       
     445      
     446     public static function getModuleById($core, $get, $post) 
     447     { 
     448          if (empty($get['id'])) { 
     449                    throw new Exception('No module ID'); 
     450          } 
     451          if (empty($get['list'])) { 
     452                    throw new Exception('No list ID'); 
     453          } 
     454 
     455          $id = $get['id']; 
     456          $list = $get['list']; 
     457          $module = array(); 
     458 
     459          if ($list == 'plugin-activate') { 
     460               $modules = $core->plugins->getModules(); 
     461               if (empty($modules) || !isset($modules[$id])) { 
     462                    throw new Exception('Unknow module ID'); 
     463               } 
     464               $module = $modules[$id]; 
     465          } 
     466          elseif ($list == 'plugin-new') { 
     467               $repository = new dcRepository( 
     468                    $core->plugins,  
     469                    $core->blog->settings->system->repository_plugin_url 
     470               ); 
     471               $repository->check(); 
     472 
     473               $modules = $repository->get(); 
     474               if (empty($modules) || !isset($modules[$id])) { 
     475                    throw new Exception('Unknow module ID'); 
     476               } 
     477               $module = $modules[$id]; 
     478          } 
     479          else { 
     480               // behavior not implemented yet 
     481          } 
     482 
     483          if (empty($module)) { 
     484                    throw new Exception('Unknow module ID'); 
     485          } 
     486 
     487          $module = adminModulesList::parseModuleInfo($id, $module); 
     488 
     489          $rsp = new xmlTag('module'); 
     490          $rsp->id = $id; 
     491           
     492          foreach($module as $k => $v) { 
     493               $rsp->{$k}((string) $v); 
     494          } 
     495 
     496          return $rsp; 
     497     } 
    446498} 
    447499?> 
  • admin/style/default.css

    r2152 r2171  
    15321532                    } 
    15331533/* ------------------------------------------------------------------- blog_theme.php */ 
     1534/* 
    15341535#themes { 
    15351536     margin: 0; 
     
    15681569          margin-bottom: 3em; 
    15691570          } 
     1571*/ 
    15701572/* Themes list, JS version */ 
     1573/* 
    15711574#themes-wrapper { 
    15721575     display: table; 
     
    16431646          background: #bee74b; 
    16441647          } 
     1648*/ 
    16451649/* ------------------------------------------------------------------ categories.php */ 
    16461650#categories { 
     
    19471951          } 
    19481952/* -------------------------------------------------------------------- plugins.php */ 
    1949 #plugins td.action { 
     1953.modules td.module-actions, .modules td.module-icon { 
    19501954     vertical-align: middle; 
    19511955     } 
    1952 .distrib img { 
     1956.modules td.module-icon img:last-child { 
     1957     width: 16px; 
     1958     height: 16px; 
     1959     } 
     1960.modules td.module-icon img.expand { 
     1961     margin-bottom: 3px; 
     1962     } 
     1963.modules td.module-distrib img { 
    19531964     display: block; 
    19541965     float: right; 
    1955      margin-top: -1em; 
     1966     } 
     1967.modules dt { 
     1968     font-weight: bold; 
     1969     } 
     1970.modules a.module-details { 
     1971     background: transparent url(search.png) no-repeat 2px 2px; 
     1972     padding: 4px 4px 0 20px; 
     1973     } 
     1974.modules a.module-support { 
     1975     background: transparent url(../images/page_help.png) no-repeat 2px 2px; 
     1976     padding: 4px 4px 0 20px; 
     1977     } 
     1978#m_search {     
     1979     background: transparent url(search.png) no-repeat 4px center; 
     1980     padding-left: 20px; 
     1981     } 
     1982.modules tr.expand, .modules td.expand { 
     1983     background: #f7f7f7; 
     1984     border-color: #bee74b; 
     1985     } 
     1986.modules tr.expand td:first-child { 
     1987     font-weight: bold; 
     1988     background: #DFE5E7; 
     1989     } 
     1990.modules td.expand { 
     1991     padding: 0; 
     1992     } 
     1993.mod-more, .mod-more li { 
     1994     margin: .25em 0 0 1em; 
     1995     padding: 0; 
     1996     list-style-type: none; 
     1997     } 
     1998.mod-more { 
     1999     padding-top: .5em; 
    19562000     } 
    19572001/* ---------------------------------------------------------- post.php, page.php */ 
  • inc/admin/lib.dc.page.php

    r2167 r2175  
    611611          self::jsVar('dotclear.msg.load_enhanced_uploader', 
    612612               __('Loading enhanced uploader, please wait.')). 
     613 
     614          self::jsVar('dotclear.msg.module_author', 
     615               __('Author:')). 
     616          self::jsVar('dotclear.msg.module_details', 
     617               __('Details')). 
     618          self::jsVar('dotclear.msg.module_support', 
     619               __('Support')). 
     620          self::jsVar('dotclear.msg.module_help', 
     621               __('Help:')). 
     622          self::jsVar('dotclear.msg.module_section', 
     623               __('Section:')). 
     624          self::jsVar('dotclear.msg.module_tags', 
     625               __('Tags:')). 
    613626               "\n//]]>\n". 
    614627          "</script>\n"; 
  • inc/prepend.php

    r1999 r2147  
    4646$__autoload['dcWorkspace']              = dirname(__FILE__).'/core/class.dc.workspace.php'; 
    4747$__autoload['dcPrefs']                  = dirname(__FILE__).'/core/class.dc.prefs.php'; 
     48$__autoload['dcRepository']             = dirname(__FILE__).'/core/class.dc.repository.php'; 
     49$__autoload['dcRepositoryReader']       = dirname(__FILE__).'/core/class.dc.repository.reader.php'; 
     50$__autoload['dcRepositoryParser']       = dirname(__FILE__).'/core/class.dc.repository.parser.php'; 
    4851 
    4952$__autoload['rsExtPost']                = dirname(__FILE__).'/core/class.dc.rs.extensions.php'; 
     
    6164$__autoload['dcPager']        = dirname(__FILE__).'/admin/lib.pager.php'; 
    6265$__autoload['dcAdminCombos']            = dirname(__FILE__).'/admin/lib.admincombos.php'; 
     66$__autoload['adminModulesList']              = dirname(__FILE__).'/admin/lib.moduleslist.php'; 
     67$__autoload['adminThemesList']               = dirname(__FILE__).'/admin/lib.moduleslist.php'; 
    6368 
    6469$__autoload['dcTemplate']               = dirname(__FILE__).'/public/class.dc.template.php'; 
  • plugins/maintenance/_admin.php

    r2116 r2163  
    2929$core->addBehavior('adminAfterDashboardOptionsUpdate', array('dcMaintenanceAdmin',   'adminAfterDashboardOptionsUpdate')); 
    3030$core->addBehavior('adminPageHelpBlock',     array('dcMaintenanceAdmin',   'adminPageHelpBlock')); 
     31$core->addBehavior('pluginsToolsHeaders',    array('dcMaintenanceAdmin',   'pluginsToolsHeaders')); 
    3132 
    3233/** 
     
    222223          $core->auth->user_prefs->maintenance->put('dashboard_item', !empty($_POST['maintenance_dashboard_item']), 'boolean'); 
    223224     } 
    224  
    225225 
    226226     /** 
     
    293293          } 
    294294     } 
     295 
     296     /** 
     297      * Add javascript for plugin configuration. 
     298      * 
     299      * @param $core     <b>dcCore</b>  dcCore instance 
     300      * @param $module   <b>mixed</b>   Module ID or false if none 
     301      * @return     <b>string</b>  Header code for js inclusion 
     302      */ 
     303     public static function pluginsToolsHeaders($core, $module) 
     304     { 
     305          if ($module == 'maintenance') { 
     306               return dcPage::jsLoad('index.php?pf=maintenance/js/settings.js'); 
     307          } 
     308     } 
    295309} 
  • plugins/maintenance/index.php

    r2166 r2175  
    2727$code = empty($_POST['code']) ? null : (integer) $_POST['code']; 
    2828$tab = empty($_REQUEST['tab']) ? '' : $_REQUEST['tab']; 
    29  
    30 // Save settings 
    31  
    32 if (!empty($_POST['settings'])) { 
    33  
    34      try { 
    35           $core->blog->settings->maintenance->put( 
    36                'plugin_message',  
    37                !empty($_POST['settings_plugin_message']),  
    38                'boolean',  
    39                'Display alert message of late tasks on plugin page',  
    40                true,  
    41                true 
    42           ); 
    43  
    44           foreach($tasks as $t) { 
    45                if (!empty($_POST['settings_recall_type']) && $_POST['settings_recall_type'] == 'all') { 
    46                     $ts = $_POST['settings_recall_time']; 
    47                } 
    48                else { 
    49                     $ts = empty($_POST['settings_ts_'.$t->id()]) ? 0 : $_POST['settings_ts_'.$t->id()]; 
    50                } 
    51                $core->blog->settings->maintenance->put( 
    52                     'ts_'.$t->id(),  
    53                     abs((integer) $ts),  
    54                     'integer',  
    55                     sprintf('Recall time for task %s', $t->id()),  
    56                     true,  
    57                     $t->blog() 
    58                ); 
    59           } 
    60            
    61           http::redirect($p_url.'&done=1&tab='.$tab.'#'.$tab); 
    62      } 
    63      catch(Exception $e) { 
    64           $core->error->add($e->getMessage()); 
    65      } 
    66 } 
    6729 
    6830// Get task object 
     
    287249          '</div>'; 
    288250     } 
    289  
    290      // Settings 
    291  
    292      echo  
    293      '<div id="settings" class="multi-part" title="'.__('Alert settings').'">'. 
    294      '<h3>'.__('Alert settings').'</h3>'. 
    295      '<form action="'.$p_url.'" method="post">'. 
    296  
    297      '<h4 class="pretty-title">'.__('Activation').'</h4>'. 
    298      '<p><label for="settings_plugin_message" class="classic">'. 
    299      form::checkbox('settings_plugin_message', 1, $core->blog->settings->maintenance->plugin_message). 
    300      __('Display alert messages on late tasks').'</label></p>'. 
    301  
    302      '<p class="info">'.sprintf( 
    303           __('You can place list of late tasks on your %s.'), 
    304           '<a href="preferences.php#user-favorites">'.__('Dashboard').'</a>' 
    305      ).'</p>'. 
    306  
    307      '<h4 class="pretty-title vertical-separator">'.__('Frequency').'</h4>'. 
    308  
    309      '<p class="vertical-separator">'.form::radio(array('settings_recall_type', 'settings_recall_all'), 'all').' '. 
    310      '<label class="classic" for="settings_recall_all">'. 
    311      '<strong>'.__('Use one recall time for all tasks').'</strong></label>'. 
    312  
    313      '<p class="field wide vertical-separator"><label for="settings_recall_time">'.__('Recall time for all tasks:').'</label>'. 
    314      form::combo('settings_recall_time', $combo_ts, 'seperate', 'recall-for-all'). 
    315      '</p>'. 
    316  
    317      '<p class="vertical-separator">'.form::radio(array('settings_recall_type', 'settings_recall_separate'), 'separate', 1).' '. 
    318      '<label class="classic" for="settings_recall_separate">'. 
    319      '<strong>'.__('Use one recall time per task').'</strong></label>'; 
    320  
    321      foreach($tasks as $t) 
    322      { 
    323           echo 
    324           '<div class="two-boxes">'. 
    325  
    326           '<p class="field wide"><label for="settings_ts_'.$t->id().'">'.$t->task().'</label>'. 
    327           form::combo('settings_ts_'.$t->id(), $combo_ts, $t->ts(), 'recall-per-task'). 
    328           '</p>'. 
    329  
    330           '</div>'; 
    331      } 
    332  
    333      echo  
    334      '<p class="field wide"><input type="submit" value="'.__('Save this settings').'" /> '. 
    335      form::hidden(array('tab'), 'settings'). 
    336      form::hidden(array('settings'), 1). 
    337      $core->formNonce().'</p>'. 
    338      '</form>'. 
    339      '</div>'; 
    340251} 
    341252 
Note: See TracChangeset for help on using the changeset viewer.

Sites map