Dotclear

Changeset 2609:c26642f775e2 for admin


Ignore:
Timestamp:
12/10/13 09:00:09 (12 years ago)
Author:
Dsls
Branch:
twig
Parents:
2468:d7fda5a0bd39 (diff), 2608:3365c9df16a6 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge with default

Location:
admin
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • admin/auth.php

    r2566 r2593  
    44# This file is part of Dotclear 2. 
    55# 
    6 # Copyright (c) 2003-2013 Olivier Meunier & Association Dotclear 
     6# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear 
    77# Licensed under the GPL version 2.0 license. 
    88# See LICENSE file or 
     
    1414 
    1515# If we have a session cookie, go to index.php 
    16 if (isset($_SESSION['sess_user_id'])) 
    17 { 
     16if (isset($_SESSION['sess_user_id'])) { 
    1817     http::redirect('index.php'); 
    1918} 
     
    2322$dlang = http::getAcceptLanguage(); 
    2423$dlang = ($dlang == '' ? 'en' : $dlang); 
    25 if ($dlang != 'en' && preg_match('/^[a-z]{2}(-[a-z]{2})?$/',$dlang)) 
    26 { 
    27      l10n::lang($dlang); 
     24if ($dlang != 'en' && preg_match('/^[a-z]{2}(-[a-z]{2})?$/',$dlang)) { 
    2825     l10n::set(dirname(__FILE__).'/../locales/'.$dlang.'/main'); 
    2926} 
    30  
    31 $page_url = http::getHost().$_SERVER['REQUEST_URI']; 
    32  
    33 $change_pwd = $core->auth->allowPassChange() && isset($_POST['new_pwd']) && isset($_POST['new_pwd_c']) && isset($_POST['login_data']); 
    34 $login_data = !empty($_POST['login_data']) ? html::escapeHTML($_POST['login_data']) : null; 
    35 $recover = $core->auth->allowPassChange() && !empty($_REQUEST['recover']); 
    36 $safe_mode = !empty($_REQUEST['safe_mode']); 
    37 $akey = $core->auth->allowPassChange() && !empty($_GET['akey']) ? $_GET['akey'] : null; 
    38 $user_id = $user_pwd = $user_key = $user_email = null; 
    39 $err = $msg = null; 
    4027 
    4128# Auto upgrade 
     
    4431     try { 
    4532          if (($changes = dotclearUpgrade($core)) !== false) { 
    46                $msg = __('Dotclear has been upgraded.').'<!-- '.$changes.' -->'; 
    47           } 
    48      } catch (Exception $e) { 
    49           $err = $e->getMessage(); 
    50      } 
    51 } 
    52  
    53 # If we have POST login informations, go throug auth process 
    54 if (!empty($_POST['user_id']) && !empty($_POST['user_pwd'])) 
     33               $_ctx->setAlert(__('Dotclear has been upgraded.').'<!-- '.$changes.' -->'); 
     34          } 
     35     } 
     36     catch (Exception $e) { 
     37          $_ctx->addError($e->getMessage()); 
     38     } 
     39} 
     40 
     41/** 
     42Actions for authentication on admin pages 
     43*/ 
     44class adminPageAuth 
    5545{ 
    56      $user_id = !empty($_POST['user_id']) ? $_POST['user_id'] : null; 
    57      $user_pwd = !empty($_POST['user_pwd']) ? $_POST['user_pwd'] : null; 
    58 } 
    59 # If we have COOKIE login informations, go throug auth process 
    60 elseif (isset($_COOKIE['dc_admin']) && strlen($_COOKIE['dc_admin']) == 104) 
    61 { 
     46     # Send new password from recover email 
     47     public static function send($akey) 
     48     { 
     49          global $core, $_ctx; 
     50           
     51          $_ctx->akey = true; 
     52           
     53          try  { 
     54               $recover_res = $core->auth->recoverUserPassword($akey); 
     55                
     56               $subject = mb_encode_mimeheader('DotClear '.__('Your new password'),'UTF-8','B'); 
     57               $message = 
     58               __('Username:').' '.$recover_res['user_id']."\n". 
     59               __('Password:').' '.$recover_res['new_pass']."\n\n". 
     60               preg_replace('/\?(.*)$/','',http::getHost().$_SERVER['REQUEST_URI']); 
     61                
     62               $headers[] = 'From: dotclear@'.$_SERVER['HTTP_HOST']; 
     63               $headers[] = 'Content-Type: text/plain; charset=UTF-8;'; 
     64                
     65               mail::sendMail($recover_res['user_email'],$subject,$message,$headers); 
     66               $_ctx->setAlert(__('Your new password is in your mailbox.')); 
     67          } 
     68          catch (Exception $e) { 
     69               $_ctx->addError($e->getMessage()); 
     70          } 
     71     } 
     72      
     73     # Authentication process 
     74     public static function process($form,$user_id,$user_pwd,$user_key=null) 
     75     { 
     76          global $core, $_ctx; 
     77           
     78          # We check the user 
     79          $check_user = $core->auth->checkUser($user_id,$user_pwd,$user_key) === true; 
     80           
     81          $cookie_admin = http::browserUID(DC_MASTER_KEY.$user_id. 
     82               crypt::hmac(DC_MASTER_KEY,$user_pwd)).bin2hex(pack('a32',$user_id)); 
     83           
     84          if ($check_user && $core->auth->mustChangePassword()) 
     85          { 
     86               $form->login_data = join('/',array( 
     87                    base64_encode($user_id), 
     88                    $cookie_admin, 
     89                    $form->user_remember == '' ? '0' : '1' 
     90               )); 
     91                
     92               if (!$core->auth->allowPassChange()) { 
     93                    $_ctx->addError(__('You have to change your password before you can login.')); 
     94               } else { 
     95                    $_ctx->addError(__('In order to login, you have to change your password now.')); 
     96                    $_ctx->change_pwd = true; 
     97               } 
     98          } 
     99          elseif ($check_user && $form->safe_mode != '' && !$core->auth->isSuperAdmin())  
     100          { 
     101               $_ctx->addError(__('Safe Mode can only be used for super administrators.')); 
     102          } 
     103          elseif ($check_user) 
     104          { 
     105               $core->session->start(); 
     106               $_SESSION['sess_user_id'] = $user_id; 
     107               $_SESSION['sess_browser_uid'] = http::browserUID(DC_MASTER_KEY); 
     108                
     109               if ($form->blog != '') { 
     110                    $_SESSION['sess_blog_id'] = $form->blog; 
     111               } 
     112                
     113               if ($form->safe_mode != '' && $core->auth->isSuperAdmin()) { 
     114                    $_SESSION['sess_safe_mode'] = true; 
     115               } 
     116                
     117               if ($form->user_remember != '') { 
     118                    setcookie('dc_admin',$cookie_admin,strtotime('+15 days'),'','',DC_ADMIN_SSL); 
     119               } 
     120                
     121               http::redirect('index.php'); 
     122          } 
     123          else 
     124          { 
     125               if (isset($_COOKIE['dc_admin'])) { 
     126                    unset($_COOKIE['dc_admin']); 
     127                    setcookie('dc_admin',false,-600,'','',DC_ADMIN_SSL); 
     128               } 
     129               $_ctx->addError(__('Wrong username or password')); 
     130          } 
     131     } 
     132      
     133     # Login form action 
     134     public static function login($form) 
     135     { 
     136          global $_ctx; 
     137           
     138          if ($form->user_id != '' && $form->user_pwd != '') { 
     139               self::process($form,$form->user_id,$form->user_pwd); 
     140          } 
     141           
     142          # Send post values to form 
     143          $form->user_id = $form->user_id; 
     144     } 
     145 
     146     # Recover password form action 
     147     public static function recover($form) 
     148     { 
     149          global $core, $_ctx; 
     150           
     151          if ($form->user_id == '' || $form->user_email == '') { 
     152               return; 
     153          } 
     154           
     155          $user_id = $form->user_id; 
     156          $user_email = $form->user_email; 
     157          $page_url = http::getHost().$_SERVER['REQUEST_URI']; 
     158           
     159          try { 
     160               $recover_key = $core->auth->setRecoverKey($user_id,$user_email); 
     161                
     162               $subject = mail::B64Header('DotClear '.__('Password reset')); 
     163               $message = 
     164               __('Someone has requested to reset the password for the following site and username.')."\n\n". 
     165               $page_url."\n".__('Username:').' '.$user_id."\n\n". 
     166               __('To reset your password visit the following address, otherwise just ignore this email and nothing will happen.')."\n". 
     167               $page_url.'?akey='.$recover_key; 
     168                
     169               $headers[] = 'From: '.(defined('DC_ADMIN_MAILFROM') && DC_ADMIN_MAILFROM ? DC_ADMIN_MAILFROM : 'dotclear@local'); 
     170               $headers[] = 'Content-Type: text/plain; charset=UTF-8;'; 
     171                
     172               mail::sendMail($user_email,$subject,$message,$headers); 
     173               $_ctx->setAlert(sprintf(__('The e-mail was sent successfully to %s.'),$user_email)); 
     174          } 
     175          catch (Exception $e) { 
     176               $_ctx->addError($e->getMessage()); 
     177          } 
     178           
     179          # Send post values to form 
     180          $form->user_id = $form->user_id; 
     181          $form->user_email = $form->user_email; 
     182     } 
     183 
     184     # Change password form action 
     185     public static function change($form) 
     186     { 
     187          global $core, $_ctx; 
     188           
     189          if ($form->login_data) { 
     190               return; 
     191          } 
     192          $_ctx->change_pwd = true; 
     193           
     194          $new_pwd = (string) $form->new_pwd; 
     195          $new_pwd_c = (string) $form->new_pwd_c; 
     196           
     197          try { 
     198               $tmp_data = explode('/',$form->login_data); 
     199               if (count($tmp_data) != 3) { 
     200                    throw new Exception(); 
     201               } 
     202               $data = array( 
     203                    'user_id'=>base64_decode($tmp_data[0]), 
     204                    'cookie_admin'=>$tmp_data[1], 
     205                    'user_remember'=>$tmp_data[2]=='1' 
     206               ); 
     207               if ($data['user_id'] === false) { 
     208                    throw new Exception(); 
     209               } 
     210                
     211               # Check login informations 
     212               $check_user = false; 
     213               if (isset($data['cookie_admin']) && strlen($data['cookie_admin']) == 104) 
     214               { 
     215                    $user_id = substr($data['cookie_admin'],40); 
     216                    $user_id = @unpack('a32',@pack('H*',$user_id)); 
     217                    if (is_array($user_id)) 
     218                    { 
     219                         $user_id = $user_id[1]; 
     220                         $user_key = substr($data['cookie_admin'],0,40); 
     221                         $check_user = $core->auth->checkUser($user_id,null,$user_key) === true; 
     222                    } 
     223               } 
     224                
     225               if (!$core->auth->allowPassChange() || !$check_user) { 
     226                    $_ctx->change_pwd = false; 
     227                    throw new Exception(); 
     228               } 
     229                
     230               if ($new_pwd != $new_pwd_c) { 
     231                    throw new Exception(__("Passwords don't match")); 
     232               } 
     233                
     234               if ($core->auth->checkUser($user_id,$new_pwd) === true) { 
     235                    throw new Exception(__("You didn't change your password.")); 
     236               } 
     237                
     238               $cur = $core->con->openCursor($core->prefix.'user'); 
     239               $cur->user_change_pwd = 0; 
     240               $cur->user_pwd = $new_pwd; 
     241               $core->updUser($core->auth->userID(),$cur); 
     242                
     243               $core->session->start(); 
     244               $_SESSION['sess_user_id'] = $user_id; 
     245               $_SESSION['sess_browser_uid'] = http::browserUID(DC_MASTER_KEY); 
     246                
     247               if ($data['user_remember']) { 
     248                    setcookie('dc_admin',$data['cookie_admin'],strtotime('+15 days'),'','',DC_ADMIN_SSL); 
     249               } 
     250                
     251               http::redirect('index.php'); 
     252          } 
     253          catch (Exception $e) { 
     254               $_ctx->addError($e->getMessage()); 
     255          } 
     256           
     257          # Send post values to form 
     258          $form->login_data = $form->login_data; 
     259     } 
     260} 
     261 
     262# Form fields 
     263$form = new dcForm($core,'auth','auth.php'); 
     264$form 
     265     ->addField( 
     266          new dcFieldText('user_id','',array( 
     267               "label" => __('Username:'), 
     268               "maxlength" => 32))) 
     269     ->addField( 
     270          new dcFieldPassword('user_pwd','',array( 
     271               "label" => __('Password:')))) 
     272     ->addField( 
     273          new dcFieldText('user_email','',array( 
     274               "label" => __('Email:')))) 
     275     ->addField( 
     276          new dcFieldPassword('new_pwd','',array( 
     277               "label" => __('New password:')))) 
     278     ->addField( 
     279          new dcFieldPassword('new_pwd_c','',array( 
     280               "label" => __('Confirm password:')))) 
     281     ->addField( 
     282          new dcFieldCheckbox ('user_remember',1,array( 
     283               "label" => __('Remember my ID on this computer')))) 
     284     ->addField( 
     285          new dcFieldSubmit('auth_login',__('log in'),array( 
     286               'action' => array('adminPageAuth','login')))) 
     287     ->addField( 
     288          new dcFieldSubmit('auth_recover',__('recover'),array( 
     289               'action' => array('adminPageAuth','recover')))) 
     290     ->addField( 
     291          new dcFieldSubmit('auth_change',__('change'),array( 
     292               'action' => array('adminPageAuth','change')))) 
     293     ->addField( 
     294          new dcFieldHidden ('safe_mode','0')) 
     295     ->addField( 
     296          new dcFieldHidden ('recover','0')) 
     297     ->addField( 
     298          new dcFieldHidden ('login_data','')) 
     299     ->addField( 
     300          new dcFieldHidden ('blog','')); 
     301 
     302# Context variables 
     303$_ctx->allow_pass_change = $core->auth->allowPassChange(); 
     304$_ctx->change_pwd = $core->auth->allowPassChange() && $form->new_pwd != '' && $form->new_pwd_c != '' && $form->login_data != ''; 
     305$_ctx->recover = $form->recover = $core->auth->allowPassChange() && !empty($_REQUEST['recover']); 
     306$_ctx->setSafeMode(!empty($_REQUEST['safe_mode']));  
     307$form->safe_mode = !empty($_REQUEST['safe_mode']); 
     308$_ctx->akey = false; 
     309$_ctx->dlang = $dlang; 
     310 
     311# If we have no POST login informations and have COOKIE login informations, go throug auth process 
     312if ($form->user_id == '' && $form->user_pwd == ''  
     313 && isset($_COOKIE['dc_admin']) && strlen($_COOKIE['dc_admin']) == 104) { 
     314 
    62315     # If we have a remember cookie, go through auth process with user_key 
    63316     $user_id = substr($_COOKIE['dc_admin'],40); 
    64317     $user_id = @unpack('a32',@pack('H*',$user_id)); 
    65      if (is_array($user_id)) 
    66      { 
     318      
     319     if (is_array($user_id)) { 
    67320          $user_id = $user_id[1]; 
    68321          $user_key = substr($_COOKIE['dc_admin'],0,40); 
    69           $user_pwd = null; 
    70      } 
    71      else 
    72      { 
    73           $user_id = null; 
    74      } 
    75 } 
    76  
    77 # Recover password 
    78 if ($recover && !empty($_POST['user_id']) && !empty($_POST['user_email'])) 
    79 { 
    80      $user_id = !empty($_POST['user_id']) ? $_POST['user_id'] : null; 
    81      $user_email = !empty($_POST['user_email']) ? $_POST['user_email'] : ''; 
    82      try 
    83      { 
    84           $recover_key = $core->auth->setRecoverKey($user_id,$user_email); 
    85  
    86           $subject = mail::B64Header('DotClear '.__('Password reset')); 
    87           $message = 
    88           __('Someone has requested to reset the password for the following site and username.')."\n\n". 
    89           $page_url."\n".__('Username:').' '.$user_id."\n\n". 
    90           __('To reset your password visit the following address, otherwise just ignore this email and nothing will happen.')."\n". 
    91           $page_url.'?akey='.$recover_key; 
    92  
    93           $headers[] = 'From: '.(defined('DC_ADMIN_MAILFROM') && DC_ADMIN_MAILFROM ? DC_ADMIN_MAILFROM : 'dotclear@local'); 
    94           $headers[] = 'Content-Type: text/plain; charset=UTF-8;'; 
    95  
    96           mail::sendMail($user_email,$subject,$message,$headers); 
    97           $msg = sprintf(__('The e-mail was sent successfully to %s.'),$user_email); 
    98      } 
    99      catch (Exception $e) 
    100      { 
    101           $err = $e->getMessage(); 
    102      } 
    103 } 
    104 # Send new password 
    105 elseif ($akey) 
    106 { 
    107      try 
    108      { 
    109           $recover_res = $core->auth->recoverUserPassword($akey); 
    110  
    111           $subject = mb_encode_mimeheader('DotClear '.__('Your new password'),'UTF-8','B'); 
    112           $message = 
    113           __('Username:').' '.$recover_res['user_id']."\n". 
    114           __('Password:').' '.$recover_res['new_pass']."\n\n". 
    115           preg_replace('/\?(.*)$/','',$page_url); 
    116  
    117           $headers[] = 'From: dotclear@'.$_SERVER['HTTP_HOST']; 
    118           $headers[] = 'Content-Type: text/plain; charset=UTF-8;'; 
    119  
    120           mail::sendMail($recover_res['user_email'],$subject,$message,$headers); 
    121           $msg = __('Your new password is in your mailbox.'); 
    122      } 
    123      catch (Exception $e) 
    124      { 
    125           $err = $e->getMessage(); 
    126      } 
    127 } 
    128 # Change password and retry to log 
    129 elseif ($change_pwd) 
    130 { 
    131      try 
    132      { 
    133           $tmp_data = explode('/',$_POST['login_data']); 
    134           if (count($tmp_data) != 3) { 
    135                throw new Exception(); 
    136           } 
    137           $data = array( 
    138                'user_id'=>base64_decode($tmp_data[0]), 
    139                'cookie_admin'=>$tmp_data[1], 
    140                'user_remember'=>$tmp_data[2]=='1' 
    141           ); 
    142           if ($data['user_id'] === false) { 
    143                throw new Exception(); 
    144           } 
    145  
    146      # Check login informations 
    147      $check_user = false; 
    148      if (isset($data['cookie_admin']) && strlen($data['cookie_admin']) == 104) 
    149      { 
    150           $user_id = substr($data['cookie_admin'],40); 
    151           $user_id = @unpack('a32',@pack('H*',$user_id)); 
    152           if (is_array($user_id)) 
    153           { 
    154                $user_id = $user_id[1]; 
    155                $user_key = substr($data['cookie_admin'],0,40); 
    156                $check_user = $core->auth->checkUser($user_id,null,$user_key) === true; 
    157           } 
    158      } 
    159  
    160           if (!$core->auth->allowPassChange() || !$check_user) { 
    161                $change_pwd = false; 
    162                throw new Exception(); 
    163           } 
    164  
    165           if ($_POST['new_pwd'] != $_POST['new_pwd_c']) { 
    166                throw new Exception(__("Passwords don't match")); 
    167           } 
    168  
    169           if ($core->auth->checkUser($user_id,$_POST['new_pwd']) === true) { 
    170                throw new Exception(__("You didn't change your password.")); 
    171           } 
    172  
    173           $cur = $core->con->openCursor($core->prefix.'user'); 
    174           $cur->user_change_pwd = 0; 
    175           $cur->user_pwd = $_POST['new_pwd']; 
    176           $core->updUser($core->auth->userID(),$cur); 
    177  
    178           $core->session->start(); 
    179           $_SESSION['sess_user_id'] = $user_id; 
    180           $_SESSION['sess_browser_uid'] = http::browserUID(DC_MASTER_KEY); 
    181  
    182           if ($data['user_remember']) 
    183           { 
    184                setcookie('dc_admin',$data['cookie_admin'],strtotime('+15 days'),'','',DC_ADMIN_SSL); 
    185           } 
    186  
    187           http::redirect('index.php'); 
    188      } 
    189      catch (Exception $e) 
    190      { 
    191           $err = $e->getMessage(); 
    192      } 
    193 } 
    194 # Try to log 
    195 elseif ($user_id !== null && ($user_pwd !== null || $user_key !== null)) 
    196 { 
    197      # We check the user 
    198      $check_user = $core->auth->checkUser($user_id,$user_pwd,$user_key,false) === true; 
    199      if ($check_user) { 
    200           $check_perms = $core->auth->findUserBlog() !== false; 
    201      } else { 
    202           $check_perms = false; 
    203      } 
    204  
    205      $cookie_admin = http::browserUID(DC_MASTER_KEY.$user_id. 
    206           crypt::hmac(DC_MASTER_KEY,$user_pwd)).bin2hex(pack('a32',$user_id)); 
    207  
    208      if ($check_perms && $core->auth->mustChangePassword()) 
    209      { 
    210           $login_data = join('/',array( 
    211                base64_encode($user_id), 
    212                $cookie_admin, 
    213                empty($_POST['user_remember'])?'0':'1' 
    214           )); 
    215  
    216           if (!$core->auth->allowPassChange()) { 
    217                $err = __('You have to change your password before you can login.'); 
    218           } else { 
    219                $err = __('In order to login, you have to change your password now.'); 
    220                $change_pwd = true; 
    221           } 
    222      } 
    223      elseif ($check_perms && !empty($_POST['safe_mode']) && !$core->auth->isSuperAdmin()) 
    224      { 
    225           $err = __('Safe Mode can only be used for super administrators.'); 
    226      } 
    227      elseif ($check_perms) 
    228      { 
    229           $core->session->start(); 
    230           $_SESSION['sess_user_id'] = $user_id; 
    231           $_SESSION['sess_browser_uid'] = http::browserUID(DC_MASTER_KEY); 
    232  
    233           if (!empty($_POST['blog'])) { 
    234                $_SESSION['sess_blog_id'] = $_POST['blog']; 
    235           } 
    236  
    237           if (!empty($_POST['safe_mode']) && $core->auth->isSuperAdmin()) { 
    238                $_SESSION['sess_safe_mode'] = true; 
    239           } 
    240  
    241           if (!empty($_POST['user_remember'])) { 
    242                setcookie('dc_admin',$cookie_admin,strtotime('+15 days'),'','',DC_ADMIN_SSL); 
    243           } 
    244  
    245           http::redirect('index.php'); 
    246      } 
    247      else 
    248      { 
    249           if (isset($_COOKIE['dc_admin'])) { 
    250                unset($_COOKIE['dc_admin']); 
    251                setcookie('dc_admin',false,-600,'','',DC_ADMIN_SSL); 
    252           } 
    253           if ($check_user) { 
    254                $err = __('Insufficient permissions'); 
    255           } else { 
    256                $err = __('Wrong username or password'); 
    257           } 
    258      } 
     322          $user_pwd = ''; 
     323           
     324          adminPageAuth::process($form,$user_id,$user_pwd,$user_key); 
     325     } 
     326} 
     327# If we have an akey, go throug send password process 
     328elseif ($core->auth->allowPassChange() && !empty($_GET['akey'])) { 
     329     adminPageAuth::send($_GET['akey']); 
    259330} 
    260331 
    261332if (isset($_GET['user'])) { 
    262      $user_id = $_GET['user']; 
    263 } 
    264  
    265 header('Content-Type: text/html; charset=UTF-8'); 
     333     $form->user_id = $_GET['user']; 
     334} 
     335 
     336$form->setup(); 
     337 
     338$core->tpl->display('auth.html.twig'); 
    266339?> 
    267 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
    268 <html xmlns="http://www.w3.org/1999/xhtml" 
    269 xml:lang="<?php echo $dlang; ?>" lang="<?php echo $dlang; ?>"> 
    270 <head> 
    271   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
    272   <meta http-equiv="Content-Script-Type" content="text/javascript" /> 
    273   <meta http-equiv="Content-Style-Type" content="text/css" /> 
    274   <meta http-equiv="Content-Language" content="<?php echo $dlang; ?>" /> 
    275   <meta name="ROBOTS" content="NOARCHIVE,NOINDEX,NOFOLLOW" /> 
    276   <meta name="GOOGLEBOT" content="NOSNIPPET" /> 
    277   <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 
    278   <title><?php echo html::escapeHTML(DC_VENDOR_NAME); ?></title> 
    279   <link rel="icon" type="image/png" href="images/favicon96-logout.png" /> 
    280   <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" /> 
    281  
    282  
    283 <?php 
    284 echo dcPage::jsLoadIE7(); 
    285 echo dcPage::jsCommon(); 
    286 ?> 
    287  
    288      <link rel="stylesheet" href="style/default.css" type="text/css" media="screen" /> 
    289  
    290   <?php 
    291   # --BEHAVIOR-- loginPageHTMLHead 
    292   $core->callBehavior('loginPageHTMLHead'); 
    293   ?> 
    294  
    295   <script type="text/javascript"> 
    296   //<![CDATA[ 
    297   $(window).load(function() { 
    298     var uid = $('input[name=user_id]'); 
    299     var upw = $('input[name=user_pwd]'); 
    300     uid.focus(); 
    301  
    302     if (upw.length == 0) { return; } 
    303  
    304     uid.keypress(processKey); 
    305  
    306     function processKey(evt) { 
    307       if (evt.which == 13 && upw.val() == '') { 
    308          upw.focus(); 
    309          return false; 
    310       } 
    311       return true; 
    312     }; 
    313     $.cookie('dc_admin_test_cookie',true); 
    314     if ($.cookie('dc_admin_test_cookie')) { 
    315       $('#cookie_help').hide(); 
    316       $.cookie('dc_admin_test_cookie', '', {'expires': -1}); 
    317     } else { 
    318       $('#cookie_help').show(); 
    319     } 
    320     $('#issue #more').toggleWithLegend($('#issue').children().not('#more')); 
    321   }); 
    322   //]]> 
    323   </script> 
    324 </head> 
    325  
    326 <body id="dotclear-admin" class="auth"> 
    327  
    328 <form action="auth.php" method="post" id="login-screen"> 
    329 <h1><?php echo html::escapeHTML(DC_VENDOR_NAME); ?></h1> 
    330  
    331 <?php 
    332 if ($err) { 
    333      echo '<div class="error">'.$err.'</div>'; 
    334 } 
    335 if ($msg) { 
    336      echo '<p class="success">'.$msg.'</p>'; 
    337 } 
    338  
    339 if ($akey) 
    340 { 
    341      echo '<p><a href="auth.php">'.__('Back to login screen').'</a></p>'; 
    342 } 
    343 elseif ($recover) 
    344 { 
    345      echo 
    346      '<div class="fieldset"><h2>'.__('Request a new password').'</h2>'. 
    347      '<p><label for="user_id">'.__('Username:').'</label> '. 
    348      form::field(array('user_id','user_id'),20,32,html::escapeHTML($user_id)).'</p>'. 
    349  
    350      '<p><label for="user_email">'.__('Email:').'</label> '. 
    351      form::field(array('user_email','user_email'),20,255,html::escapeHTML($user_email)).'</p>'. 
    352  
    353      '<p><input type="submit" value="'.__('recover').'" />'. 
    354      form::hidden(array('recover'),1).'</p>'. 
    355      '</div>'. 
    356  
    357      '<div id="issue">'. 
    358      '<p><a href="auth.php">'.__('Back to login screen').'</a></p>'. 
    359      '</div>'; 
    360 } 
    361 elseif ($change_pwd) 
    362 { 
    363      echo 
    364      '<div class="fieldset"><h2>'.__('Change your password').'</h2>'. 
    365      '<p><label for="new_pwd">'.__('New password:').'</label> '. 
    366      form::password(array('new_pwd','new_pwd'),20,255).'</p>'. 
    367  
    368      '<p><label for="new_pwd_c">'.__('Confirm password:').'</label> '. 
    369      form::password(array('new_pwd_c','new_pwd_c'),20,255).'</p>'. 
    370      '</div>'. 
    371  
    372      '<p><input type="submit" value="'.__('change').'" />'. 
    373      form::hidden('login_data',$login_data).'</p>'; 
    374 } 
    375 else 
    376 { 
    377      if (is_callable(array($core->auth,'authForm'))) 
    378      { 
    379           echo $core->auth->authForm($user_id); 
    380      } 
    381      else 
    382      { 
    383           if ($safe_mode) { 
    384                echo '<div class="fieldset">'; 
    385                echo '<h2>'.__('Safe mode login').'</h2>'; 
    386                echo 
    387                     '<p class="form-note">'. 
    388                     __('This mode allows you to login without activating any of your plugins. This may be useful to solve compatibility problems').'&nbsp;</p>'. 
    389                     '<p class="form-note">'.__('Disable or delete any plugin suspected to cause trouble, then log out and log back in normally.'). 
    390                     '</p>'; 
    391           } 
    392           else { 
    393                echo '<div class="fieldset">'; 
    394           } 
    395  
    396           echo 
    397           '<p><label for="user_id">'.__('Username:').'</label> '. 
    398           form::field(array('user_id','user_id'),20,32,html::escapeHTML($user_id)).'</p>'. 
    399  
    400           '<p><label for="user_pwd">'.__('Password:').'</label> '. 
    401           form::password(array('user_pwd','user_pwd'),20,255).'</p>'. 
    402  
    403           '<p>'. 
    404           form::checkbox(array('user_remember','user_remember'),1). 
    405           '<label for="user_remember" class="classic">'. 
    406           __('Remember my ID on this computer').'</label></p>'. 
    407  
    408           '<p><input type="submit" value="'.__('log in').'" class="login" /></p>'; 
    409  
    410           if (!empty($_REQUEST['blog'])) { 
    411                echo form::hidden('blog',html::escapeHTML($_REQUEST['blog'])); 
    412           } 
    413           if($safe_mode) { 
    414                echo 
    415                form::hidden('safe_mode',1). 
    416                '</div>'; 
    417           } 
    418           else { 
    419                echo '</div>'; 
    420           } 
    421           echo 
    422           '<p id="cookie_help" class="error">'.__('You must accept cookies in order to use the private area.').'</p>'; 
    423  
    424           echo '<div id="issue">'; 
    425  
    426           if ($safe_mode) { 
    427                echo 
    428                '<p><a href="auth.php" id="normal_mode_link">'.__('Get back to normal authentication').'</a></p>'; 
    429           } else { 
    430                echo '<p id="more"><strong>'.__('Connection issue?').'</strong></p>'; 
    431                if ($core->auth->allowPassChange()) { 
    432                     echo '<p><a href="auth.php?recover=1">'.__('I forgot my password').'</a></p>'; 
    433                } 
    434                echo '<p><a href="auth.php?safe_mode=1" id="safe_mode_link">'.__('I want to log in in safe mode').'</a></p>'; 
    435           } 
    436  
    437           echo '</div>'; 
    438      } 
    439 } 
    440 ?> 
    441 </form> 
    442 </body> 
    443 </html> 
  • admin/index.php

    r2566 r2593  
    1515     exit; 
    1616} 
     17if (!empty($_GET['tf'])) { 
     18     define('DC_CONTEXT_ADMIN',true); 
     19     require dirname(__FILE__).'/../inc/load_theme_file.php'; 
     20     exit; 
     21} 
    1722 
    1823require dirname(__FILE__).'/../inc/admin/prepend.php'; 
     
    4348$plugins_install = $core->plugins->installModules(); 
    4449 
     50# Send plugins install messages to templates 
     51if (!empty($plugins_install['success'])) { 
     52     $_ctx->addMessagesList(__('Following plugins have been installed:'),$plugins_install['success']); 
     53} 
     54if (!empty($plugins_install['failure'])) { 
     55     $_ctx->addMessagesList(__('Following plugins have not been installed:'),$plugins_install['failure']); 
     56} 
     57 
     58# Send plugins errors messages to templates 
     59$_ctx->modules_errors = $core->auth->isSuperAdmin() ? $core->plugins->getErrors() : array(); 
     60 
     61# Send Dotclear updates notifications to tempaltes 
     62$_ctx->updater = array(); 
     63if ($core->auth->isSuperAdmin() && is_readable(DC_DIGESTS)) { 
     64 
     65     $updater = new dcUpdate(DC_UPDATE_URL,'dotclear',DC_UPDATE_VERSION,DC_TPL_CACHE.'/versions'); 
     66     $new_v = $updater->check(DC_VERSION); 
     67     $version_info = $new_v ? $updater->getInfoURL() : ''; 
     68      
     69     if ($updater->getNotify() && $new_v) { 
     70          $_ctx->updater = array( 
     71               'new_version'  => $new_v, 
     72               'version_info' => $version_info 
     73          ); 
     74     } 
     75} 
     76 
    4577# Check dashboard module prefs 
    4678$ws = $core->auth->user_prefs->addWorkspace('dashboard'); 
     79 
     80# Doclinks prefs 
    4781if (!$core->auth->user_prefs->dashboard->prefExists('doclinks')) { 
    4882     if (!$core->auth->user_prefs->dashboard->prefExists('doclinks',true)) { 
     
    5185     $core->auth->user_prefs->dashboard->put('doclinks',true,'boolean'); 
    5286} 
     87 
     88# Send doclinks to templates 
     89$_ctx->dashboard_doclinks = array(); 
     90if ($core->auth->user_prefs->dashboard->doclinks && !empty($__resources['doc'])) { 
     91     $_ctx->dashboard_doclinks = $__resources['doc']; 
     92} 
     93 
     94# Dcnews prefs 
    5395if (!$core->auth->user_prefs->dashboard->prefExists('dcnews')) { 
    5496     if (!$core->auth->user_prefs->dashboard->prefExists('dcnews',true)) { 
     
    5799     $core->auth->user_prefs->dashboard->put('dcnews',true,'boolean'); 
    58100} 
    59 if (!$core->auth->user_prefs->dashboard->prefExists('quickentry')) { 
    60      if (!$core->auth->user_prefs->dashboard->prefExists('quickentry',true)) { 
    61           $core->auth->user_prefs->dashboard->put('quickentry',false,'boolean','',null,true); 
    62      } 
    63      $core->auth->user_prefs->dashboard->put('quickentry',false,'boolean'); 
    64 } 
    65  
    66 // Handle folded/unfolded sections in admin from user preferences 
    67 $ws = $core->auth->user_prefs->addWorkspace('toggles'); 
    68 if (!$core->auth->user_prefs->toggles->prefExists('unfolded_sections')) { 
    69      $core->auth->user_prefs->toggles->put('unfolded_sections','','string','Folded sections in admin',null,true); 
    70 } 
    71  
    72  
    73 # Dashboard icons 
    74 $__dashboard_icons = new ArrayObject(); 
    75  
    76 $favs = $core->favs->getUserFavorites(); 
    77 $core->favs->appendDashboardIcons($__dashboard_icons); 
    78  
    79 # Check plugins and themes update from repository 
    80 function dc_check_store_update($mod, $url, $img, $icon) 
    81 { 
    82      $repo = new dcStore($mod, $url); 
    83      $upd = $repo->get(true); 
    84      if (!empty($upd)) { 
    85           $icon[0] .= '<br />'.sprintf(__('An update is available', '%s updates are available.', count($upd)),count($upd)); 
    86           $icon[1] .= '#update'; 
    87           $icon[2] = 'images/menu/'.$img.'-b-update.png'; 
    88      } 
    89 } 
    90 if (isset($__dashboard_icons['plugins'])) { 
    91      dc_check_store_update($core->plugins, $core->blog->settings->system->store_plugin_url, 'plugins', $__dashboard_icons['plugins']); 
    92 } 
    93 if (isset($__dashboard_icons['blog_theme'])) { 
    94      $themes = new dcThemes($core); 
    95      $themes->loadModules($core->blog->themes_path, null); 
    96      dc_check_store_update($themes, $core->blog->settings->system->store_theme_url, 'blog-theme', $__dashboard_icons['blog_theme']); 
    97 } 
    98  
    99 # Latest news for dashboard 
    100 $__dashboard_items = new ArrayObject(array(new ArrayObject(),new ArrayObject())); 
    101  
    102 $dashboardItem = 0; 
    103  
    104 if ($core->auth->user_prefs->dashboard->dcnews) { 
     101 
     102# Send dcnews to templates 
     103$_ctx->dashboard_dcnews = array(); 
     104if ($core->auth->user_prefs->dashboard->dcnews && !empty($__resources['rss_news'])) { 
    105105     try 
    106106     { 
    107           if (empty($__resources['rss_news'])) { 
    108                throw new Exception(); 
    109           } 
    110  
    111107          $feed_reader = new feedReader; 
    112108          $feed_reader->setCacheDir(DC_TPL_CACHE); 
     
    114110          $feed_reader->setUserAgent('Dotclear - http://www.dotclear.org/'); 
    115111          $feed = $feed_reader->parse($__resources['rss_news']); 
    116           if ($feed) 
    117           { 
    118                $latest_news = '<div class="box medium dc-box"><h3>'.__('Dotclear news').'</h3><dl id="news">'; 
     112          if ($feed) { 
     113               $items = array(); 
    119114               $i = 1; 
    120                foreach ($feed->items as $item) 
    121                { 
    122                     $dt = isset($item->link) ? '<a href="'.$item->link.'" class="outgoing" title="'.$item->title.'">'. 
    123                          $item->title.' <img src="images/outgoing-blue.png" alt="" /></a>' : $item->title; 
    124  
    125                     if ($i < 3) { 
    126                          $latest_news .= 
    127                          '<dt>'.$dt.'</dt>'. 
    128                          '<dd><p><strong>'.dt::dt2str(__('%d %B %Y:'),$item->pubdate,'Europe/Paris').'</strong> '. 
    129                          '<em>'.text::cutString(html::clean($item->content),120).'...</em></p></dd>'; 
    130                     } else { 
    131                          $latest_news .= 
    132                          '<dt>'.$dt.'</dt>'. 
    133                          '<dd>'.dt::dt2str(__('%d %B %Y:'),$item->pubdate,'Europe/Paris').'</dd>'; 
    134                     } 
     115               foreach ($feed->items as $item) { 
     116                    $items[] = array( 
     117                         'title' => $item->title, 
     118                         'link' => isset($item->link) ? $item->link : '', 
     119                         'date' => dt::dt2str(__('%d %B %Y'),$item->pubdate,'Europe/Paris'), 
     120                         'content' => html::clean($item->content) 
     121                    ); 
    135122                    $i++; 
    136                     if ($i > 2) { break; } 
     123                    if ($i > 3) { break; } 
    137124               } 
    138                $latest_news .= '</dl></div>'; 
    139                $__dashboard_items[$dashboardItem][] = $latest_news; 
    140                $dashboardItem++; 
     125               $_ctx->dashboard_dcnews = $items; 
    141126          } 
    142127     } 
     
    144129} 
    145130 
    146 # Documentation links 
    147 if ($core->auth->user_prefs->dashboard->doclinks) { 
    148      if (!empty($__resources['doc'])) 
    149      { 
    150           $doc_links = '<div class="box small dc-box"><h3>'.__('Documentation and support').'</h3><ul>'; 
    151  
    152           foreach ($__resources['doc'] as $k => $v) { 
    153                $doc_links .= '<li><a class="outgoing" href="'.$v.'" title="'.$k.'">'.$k. 
    154                ' <img src="images/outgoing-blue.png" alt="" /></a></li>'; 
    155           } 
    156  
    157           $doc_links .= '</ul></div>'; 
    158           $__dashboard_items[$dashboardItem][] = $doc_links; 
    159           $dashboardItem++; 
    160      } 
    161 } 
    162  
     131# Quick entry prefs 
     132if (!$core->auth->user_prefs->dashboard->prefExists('quickentry')) { 
     133     if (!$core->auth->user_prefs->dashboard->prefExists('quickentry',true)) { 
     134          $core->auth->user_prefs->dashboard->put('quickentry',true,'boolean','',null,true); 
     135     } 
     136     $core->auth->user_prefs->dashboard->put('quickentry',true,'boolean'); 
     137} 
     138 
     139# Send quick entry to templates 
     140$_ctx->dashboard_quickentry = false; 
     141if ($core->auth->user_prefs->dashboard->quickentry &&$core->auth->check('usage,contentadmin',$core->blog->id)) 
     142{ 
     143     $categories_combo = array('&nbsp;' => ''); 
     144     try { 
     145          $categories = $core->blog->getCategories(array('post_type'=>'post')); 
     146          while ($categories->fetch()) { 
     147               $categories_combo[$categories->cat_id] =  
     148                    str_repeat('&nbsp;&nbsp;',$categories->level-1). 
     149                    ($categories->level-1 == 0 ? '' : '&bull; '). 
     150                    html::escapeHTML($categories->cat_title); 
     151          } 
     152     } catch (Exception $e) { } 
     153      
     154     $form = new dcForm($core,array('quickentry','quick-entry'),'post.php'); 
     155     $form 
     156          ->addField( 
     157               new dcFieldText('post_title','', array( 
     158                    'size'         => 20, 
     159                    'required'     => true, 
     160                    'label'        => __('Title')))) 
     161          ->addField( 
     162               new dcFieldTextArea('post_content','', array( 
     163                    'required'     => true, 
     164                    'label'        => __("Content:")))) 
     165          ->addField( 
     166               new dcFieldCombo('cat_id','',$categories_combo,array( 
     167                    "label" => __('Category:')))) 
     168          ->addField( 
     169               new dcFieldSubmit('save',__('Save'),array( 
     170                    'action' => 'savePost'))) 
     171          ->addField( 
     172               new dcFieldHidden ('post_status',-2)) 
     173          ->addField( 
     174               new dcFieldHidden ('post_format',$core->auth->getOption('post_format'))) 
     175          ->addField( 
     176               new dcFieldHidden ('post_excerpt','')) 
     177          ->addField( 
     178               new dcFieldHidden ('post_lang',$core->auth->getInfo('user_lang'))) 
     179          ->addField( 
     180               new dcFieldHidden ('post_notes','')) 
     181     ; 
     182     if ($core->auth->check('publish',$core->blog->id)) { 
     183          $form->addField( 
     184               new dcFieldHidden ('save-publish',__('Save and publish'))); 
     185     } 
     186      
     187     $_ctx->dashboard_quickentry = true; 
     188} 
     189 
     190# Dashboard icons 
     191$__dashboard_icons = new ArrayObject(); 
     192 
     193# Dashboard favorites 
     194$post_count = $core->blog->getPosts(array(),true)->f(0); 
     195$str_entries = ($post_count > 1) ? __('%d entries') : __('%d entry'); 
     196 
     197$comment_count = $core->blog->getComments(array(),true)->f(0); 
     198$str_comments = ($comment_count > 1) ? __('%d comments') : __('%d comment'); 
     199 
     200$ws = $core->auth->user_prefs->addWorkspace('favorites'); 
     201$count = 0; 
     202foreach ($ws->dumpPrefs() as $k => $v) { 
     203     // User favorites only 
     204     if (!$v['global']) { 
     205          $fav = unserialize($v['value']); 
     206          if (($fav['permissions'] == '*') || $core->auth->check($fav['permissions'],$core->blog->id)) { 
     207               if (dc_valid_fav($fav['url'])) { 
     208                    $count++; 
     209                    $title = ($fav['name'] == 'posts' ? sprintf($str_entries,$post_count) :  
     210                         ($fav['name'] == 'comments' ? sprintf($str_comments,$comment_count) : $fav['title'])); 
     211                    $__dashboard_icons[$fav['name']] = new ArrayObject(array(__($title),$fav['url'],$fav['large-icon'])); 
     212 
     213                    # Let plugins set their own title for favorite on dashboard 
     214                    $core->callBehavior('adminDashboardFavsIcon',$core,$fav['name'],$__dashboard_icons[$fav['name']]); 
     215               } 
     216          } 
     217     } 
     218}     
     219if (!$count) { 
     220     // Global favorites if any 
     221     foreach ($ws->dumpPrefs() as $k => $v) { 
     222          $fav = unserialize($v['value']); 
     223          if (($fav['permissions'] == '*') || $core->auth->check($fav['permissions'],$core->blog->id)) { 
     224               if (dc_valid_fav($fav['url'])) { 
     225                    $count++; 
     226                    $title = ($fav['name'] == 'posts' ? sprintf($str_entries,$post_count) :  
     227                         ($fav['name'] == 'comments' ? sprintf($str_comments,$comment_count) : $fav['title'])); 
     228                    $__dashboard_icons[$fav['name']] = new ArrayObject(array(__($title),$fav['url'],$fav['large-icon'])); 
     229 
     230                    # Let plugins set their own title for favorite on dashboard 
     231                    $core->callBehavior('adminDashboardFavsIcon',$core,$fav['name'],$__dashboard_icons[$fav['name']]); 
     232               } 
     233          } 
     234     } 
     235} 
     236if (!$count) { 
     237     // No user or global favorites, add "user pref" and "new entry" fav 
     238     if ($core->auth->check('usage,contentadmin',$core->blog->id)) { 
     239          $__dashboard_icons['new_post'] = new ArrayObject(array(__('New entry'),'post.php','images/menu/edit-b.png')); 
     240     } 
     241     $__dashboard_icons['prefs'] = new ArrayObject(array(__('My preferences'),'preferences.php','images/menu/user-pref-b.png')); 
     242} 
     243 
     244# Send dashboard icons to templates 
     245$icons = array(); 
     246foreach ($__dashboard_icons as $i) { 
     247     $icons[] = array( 
     248          'title'   => $i[0], 
     249          'url'     => $i[1], 
     250          'img'     => dc_admin_icon_url($i[2]) 
     251     ); 
     252} 
     253$_ctx->dashboard_icons = $icons; 
     254 
     255# Dashboard items 
     256$__dashboard_items = new ArrayObject(array(new ArrayObject,new ArrayObject)); 
    163257$core->callBehavior('adminDashboardItems', $core, $__dashboard_items); 
    164258 
     259# Send dashboard items to templates 
     260$items = array(); 
     261foreach ($__dashboard_items as $i) {     
     262     if ($i->count() > 0) { 
     263          foreach ($i as $v) { 
     264               $items[] = $v; 
     265          } 
     266     } 
     267} 
     268$_ctx->dashboard_items = $items; 
     269 
    165270# Dashboard content 
    166 $dashboardContents = ''; 
    167271$__dashboard_contents = new ArrayObject(array(new ArrayObject,new ArrayObject)); 
    168272$core->callBehavior('adminDashboardContents', $core, $__dashboard_contents); 
    169273 
    170 /* DISPLAY 
    171 -------------------------------------------------------- */ 
    172 dcPage::open(__('Dashboard'), 
    173      dcPage::jsToolBar(). 
    174      dcPage::jsLoad('js/_index.js'). 
    175      # --BEHAVIOR-- adminDashboardHeaders 
    176      $core->callBehavior('adminDashboardHeaders'), 
    177      dcPage::breadcrumb( 
    178           array( 
    179           __('Dashboard').' : '.html::escapeHTML($core->blog->name) => '' 
    180           ), 
    181           array('home_link' =>false) 
    182      ) 
    183 ); 
    184  
    185 # Dotclear updates notifications 
    186 if ($core->auth->isSuperAdmin() && is_readable(DC_DIGESTS)) 
    187 { 
    188      $updater = new dcUpdate(DC_UPDATE_URL,'dotclear',DC_UPDATE_VERSION,DC_TPL_CACHE.'/versions'); 
    189      $new_v = $updater->check(DC_VERSION); 
    190      $version_info = $new_v ? $updater->getInfoURL() : ''; 
    191  
    192      if ($updater->getNotify() && $new_v) { 
    193           echo 
    194           '<div class="dc-update"><h3>'.sprintf(__('Dotclear %s is available!'),$new_v).'</h3> '. 
    195           '<p><a class="button submit" href="update.php">'.sprintf(__('Upgrade now'),$new_v).'</a> '. 
    196           '<a class="button" href="update.php?hide_msg=1">'.__('Remind me later').'</a>'. 
    197           ($version_info ? ' </p>'. 
    198           '<p class="updt-info"><a href="'.$version_info.'">'.__('Information about this version').'</a>' : '').'</p>'. 
    199           '</div>'; 
    200      } 
    201 } 
    202  
    203 if ($core->auth->getInfo('user_default_blog') != $core->blog->id && $core->auth->getBlogCount() > 1) { 
    204      echo 
    205      '<p><a href="index.php?default_blog=1" class="button">'.__('Make this blog my default blog').'</a></p>'; 
    206 } 
    207  
     274# Send dashboard contents to templates 
     275$contents = array(); 
     276foreach ($__dashboard_contents as $i) {  
     277     if ($i->count() > 0) { 
     278          foreach ($i as $v) { 
     279               $contents[] = $v; 
     280          } 
     281     } 
     282} 
     283$_ctx->dashboard_contents = $contents; 
     284 
     285# Blog status message 
    208286if ($core->blog->status == 0) { 
    209      echo '<p class="static-msg">'.__('This blog is offline').'.</p>'; 
     287     $_ctx->addMessageStatic(__('This blog is offline')); 
    210288} elseif ($core->blog->status == -1) { 
    211      echo '<p class="static-msg">'.__('This blog is removed').'.</p>'; 
    212 } 
    213  
     289     $_ctx->addMessageStatic(__('This blog is removed')); 
     290} 
     291 
     292# Config errors messages 
    214293if (!defined('DC_ADMIN_URL') || !DC_ADMIN_URL) { 
    215      echo 
    216      '<p class="static-msg">'. 
    217      sprintf(__('%s is not defined, you should edit your configuration file.'),'DC_ADMIN_URL'). 
    218      ' '.__('See <a href="http://dotclear.org/documentation/2.0/admin/config">documentation</a> for more information.'). 
    219      '</p>'; 
    220 } 
    221  
     294     $_ctx->addMessageStatic( 
     295          sprintf(__('%s is not defined, you should edit your configuration file.'),'DC_ADMIN_URL').' '. 
     296          __('See <a href="http://dotclear.org/documentation/2.0/admin/config">documentation</a> for more information.') 
     297     ); 
     298} 
    222299if (!defined('DC_ADMIN_MAILFROM') || !DC_ADMIN_MAILFROM) { 
    223      echo 
    224      '<p class="static-msg">'. 
    225      sprintf(__('%s is not defined, you should edit your configuration file.'),'DC_ADMIN_MAILFROM'). 
    226      ' '.__('See <a href="http://dotclear.org/documentation/2.0/admin/config">documentation</a> for more information.'). 
    227      '</p>'; 
    228 } 
    229  
    230 $err = array(); 
    231  
    232 # Check cache directory 
    233 if ( $core->auth->isSuperAdmin() ) { 
    234      if (!is_dir(DC_TPL_CACHE) || !is_writable(DC_TPL_CACHE)) { 
    235           $err[] = '<p>'.__("The cache directory does not exist or is not writable. You must create this directory with sufficient rights and affect this location to \"DC_TPL_CACHE\" in inc/config.php file.").'</p>'; 
    236      } 
    237 } else { 
    238      if (!is_dir(DC_TPL_CACHE) || !is_writable(DC_TPL_CACHE)) { 
    239           $err[] = '<p>'.__("The cache directory does not exist or is not writable. You should contact your administrator.").'</p>'; 
    240      } 
    241 } 
    242  
    243 # Check public directory 
    244 if ( $core->auth->isSuperAdmin() ) { 
    245      if (!is_dir($core->blog->public_path) || !is_writable($core->blog->public_path)) { 
    246           $err[] = '<p>'.__("There is no writable directory /public/ at the location set in about:config \"public_path\". You must create this directory with sufficient rights (or change this setting).").'</p>'; 
    247      } 
    248 } else { 
    249      if (!is_dir($core->blog->public_path) || !is_writable($core->blog->public_path)) { 
    250           $err[] = '<p>'.__("There is no writable root directory for the media manager. You should contact your administrator.").'</p>'; 
    251      } 
    252 } 
    253  
    254 # Error list 
    255 if (count($err) > 0) { 
    256      echo '<div class="error"><p><strong>'.__('Error:').'</strong></p>'. 
    257      '<ul><li>'.implode("</li><li>",$err).'</li></ul></div>'; 
    258 } 
    259  
    260 # Plugins install messages 
    261 if (!empty($plugins_install['success'])) 
    262 { 
    263      echo '<div class="success">'.__('Following plugins have been installed:').'<ul>'; 
    264      foreach ($plugins_install['success'] as $k => $v) { 
    265           echo '<li>'.$k.'</li>'; 
    266      } 
    267      echo '</ul></div>'; 
    268 } 
    269 if (!empty($plugins_install['failure'])) 
    270 { 
    271      echo '<div class="error">'.__('Following plugins have not been installed:').'<ul>'; 
    272      foreach ($plugins_install['failure'] as $k => $v) { 
    273           echo '<li>'.$k.' ('.$v.')</li>'; 
    274      } 
    275      echo '</ul></div>'; 
    276 } 
    277 # Errors modules notifications 
    278 if ($core->auth->isSuperAdmin()) 
    279 { 
    280      $list = $core->plugins->getErrors(); 
    281      if (!empty($list)) { 
    282           echo 
    283           '<div class="error" id="module-errors" class="error"><p>'.__('Errors have occured with following plugins:').'</p> '. 
    284           '<ul><li>'.implode("</li>\n<li>", $list).'</li></ul></div>'; 
    285      } 
    286 } 
    287  
    288 # Dashboard columns (processed first, as we need to know the result before displaying the icons.) 
    289 $dashboardItems = ''; 
    290  
    291 foreach ($__dashboard_items as $i) 
    292 { 
    293      if ($i->count() > 0) 
    294      { 
    295           $dashboardItems .= ''; 
    296           foreach ($i as $v) { 
    297                $dashboardItems .= $v; 
    298           } 
    299           $dashboardItems .= ''; 
    300      } 
    301 } 
    302  
    303 # Dashboard elements 
    304 echo '<div id="dashboard-main">'; 
    305  
    306 # Dashboard icons 
    307 echo '<div id="icons">'; 
    308 foreach ($__dashboard_icons as $i) 
    309 { 
    310      echo 
    311      '<p><a href="'.$i[1].'"><img src="'.dc_admin_icon_url($i[2]).'" alt="" />'. 
    312      '<br /><span>'.$i[0].'</span></a></p>'; 
    313 } 
    314 echo '</div>'; 
    315  
    316 if ($core->auth->user_prefs->dashboard->quickentry) { 
    317      if ($core->auth->check('usage,contentadmin',$core->blog->id)) 
    318      { 
    319           # Getting categories 
    320           $categories_combo = dcAdminCombos::getCategoriesCombo( 
    321                $core->blog->getCategories(array('post_type'=>'post')) 
    322           ); 
    323  
    324           echo 
    325           '<div id="quick">'. 
    326           '<h3>'.__('Quick entry').'</h3>'. 
    327           '<form id="quick-entry" action="post.php" method="post" class="fieldset">'. 
    328           '<h4>'.__('New entry').'</h4>'. 
    329           '<p class="col"><label for="post_title" class="required"><abbr title="'.__('Required field').'">*</abbr> '.__('Title:').'</label>'. 
    330           form::field('post_title',20,255,'','maximal'). 
    331           '</p>'. 
    332           '<p class="area"><label class="required" '. 
    333           'for="post_content"><abbr title="'.__('Required field').'">*</abbr> '.__('Content:').'</label> '. 
    334           form::textarea('post_content',50,10). 
    335           '</p>'. 
    336           '<p><label for="cat_id" class="classic">'.__('Category:').'</label> '. 
    337           form::combo('cat_id',$categories_combo).'</p>'. 
    338           ($core->auth->check('categories', $core->blog->id) 
    339                ? '<div>'. 
    340                '<p id="new_cat" class="q-cat">'.__('Add a new category').'</p>'. 
    341                '<p class="q-cat"><label for="new_cat_title">'.__('Title:').'</label> '. 
    342                form::field('new_cat_title',30,255,'','').'</p>'. 
    343                '<p class="q-cat"><label for="new_cat_parent">'.__('Parent:').'</label> '. 
    344                form::combo('new_cat_parent',$categories_combo,'',''). 
    345                '</p>'. 
    346                '<p class="form-note info clear">'.__('This category will be created when you will save your post.').'</p>'. 
    347                '</div>' 
    348                : ''). 
    349           '<p><input type="submit" value="'.__('Save').'" name="save" /> '. 
    350           ($core->auth->check('publish',$core->blog->id) 
    351                ? '<input type="hidden" value="'.__('Save and publish').'" name="save-publish" />' 
    352                : ''). 
    353           $core->formNonce(). 
    354           form::hidden('post_status',-2). 
    355           form::hidden('post_format',$core->auth->getOption('post_format')). 
    356           form::hidden('post_excerpt',''). 
    357           form::hidden('post_lang',$core->auth->getInfo('user_lang')). 
    358           form::hidden('post_notes',''). 
    359           '</p>'. 
    360           '</form>'. 
    361           '</div>'; 
    362      } 
    363 } 
    364  
    365 foreach ($__dashboard_contents as $i) 
    366 { 
    367      if ($i->count() > 0) 
    368      { 
    369           $dashboardContents .= ''; 
    370           foreach ($i as $v) { 
    371                $dashboardContents .= $v; 
    372           } 
    373           $dashboardContents .= ''; 
    374      } 
    375 } 
    376  
    377 if ($dashboardContents != '' || $dashboardItems != '') { 
    378      echo 
    379      '<div id="dashboard-boxes">'. 
    380      '<div class="db-items">'.$dashboardItems.$dashboardContents.'</div>'. 
    381      '</div>'; 
    382 } 
    383  
    384 echo '</div>'; #end dashboard-main 
    385 dcPage::helpBlock('core_dashboard'); 
    386 dcPage::close(); 
     300     $_ctx->addMessageStatic( 
     301          sprintf(__('%s is not defined, you should edit your configuration file.'),'DC_ADMIN_MAILFROM').' '. 
     302          __('See <a href="http://dotclear.org/documentation/2.0/admin/config">documentation</a> for more information.') 
     303     ); 
     304} 
     305 
     306$_ctx->setBreadCrumb(__('Dashboard').' : '.html::escapeHTML($core->blog->name), false); 
     307$core->tpl->display('index.html.twig'); 
     308?> 
  • admin/js/_post.js

    r2313 r2593  
    1 dotclear.commentExpander = 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.viewCommentContent(this,this.line); }; 
    11  
    12      td.insertBefore(img,td.firstChild); 
    13 }; 
    14  
    15 dotclear.viewCommentContent = function(img,line) { 
    16      var commentId = line.id.substr(1); 
    17  
     1dotclear.viewCommentContent = function(line,action) { 
     2     var commentId = $(line).attr('id').substr(1); 
    183     var tr = document.getElementById('ce'+commentId); 
    194 
     
    2611          tr.appendChild(td); 
    2712 
    28           img.src = dotclear.img_minus_src; 
    29           img.alt = dotclear.img_minus_alt; 
    30  
    3113          // Get comment content 
    3214          $.get('services.php',{f:'getCommentById',id: commentId},function(data) { 
     
    6042          $(tr).toggle(); 
    6143          $(line).toggleClass('expand'); 
    62           img.src = dotclear.img_minus_src; 
    63           img.alt = dotclear.img_minus_alt; 
    6444     } 
    6545     else 
     
    6747          $(tr).toggle(); 
    6848          $(line).toggleClass('expand'); 
    69           img.src = dotclear.img_plus_src; 
    70           img.alt = dotclear.img_plus_alt; 
    7149     } 
    7250}; 
     
    9068                    $(this).val(last_post_format); 
    9169               } 
    92                 
     70 
    9371               $('.format_control > *').addClass('hide'); 
    9472               $('.format_control:not(.control_no_'+$(this).val()+') > *').removeClass('hide'); 
     
    10280     if (document.getElementById('comment_content')) { 
    10381          var commentTb = new jsToolBar(document.getElementById('comment_content')); 
     82          commentTb.draw('xhtml'); 
    10483     } 
    10584 
     
    128107          a.className = 'button '; 
    129108          $(a).click(function() { 
    130                 
     109 
    131110               excerpt_content = $('#post_excerpt').css('display') != 'none' ? $('#post_excerpt').val() : $('#excerpt-area iframe').contents().find('body').html(); 
    132                post_content    = $('#post_content').css('display') != 'none' ? $('#post_content').val() : $('#content-area iframe').contents().find('body').html(); 
    133                 
     111               post_content   = $('#post_content').css('display') != 'none' ? $('#post_content').val() : $('#content-area iframe').contents().find('body').html(); 
     112 
    134113               var params = { 
    135114                    xd_check: dotclear.nonce, 
     
    146125                         return false; 
    147126                    } 
    148                           
     127 
    149128                    $('.message, .success, .error, .warning-msg').remove(); 
    150129 
     
    152131                         var p = document.createElement('p'); 
    153132                         p.id = 'markup-validator'; 
    154                           
     133 
    155134                         $(p).addClass('success'); 
    156135                         $(p).text(dotclear.msg.xhtml_valid); 
     
    162141                         var div = document.createElement('div'); 
    163142                         div.id = 'markup-validator'; 
    164                           
     143 
    165144                         $(div).addClass('error'); 
    166145                         $(div).html('<p><strong>' + dotclear.msg.xhtml_not_valid + '</strong></p>' + $(data).find('errors').text()); 
     
    185164 
    186165          a.appendChild(document.createTextNode(dotclear.msg.xhtml_validator)); 
    187            
     166 
    188167          $('.format_control > *').addClass('hide'); 
    189168          $('.format_control:not(.control_no_'+last_post_format+') > *').removeClass('hide'); 
     
    266245 
    267246     $('#comments').onetabload(function() { 
    268           $('#form-comments .comments-list tr.line').each(function() { 
    269                dotclear.commentExpander(this); 
     247          $.expandContent({ 
     248               lines:$('#form-comments .comments-list tr.line'), 
     249               callback:dotclear.viewCommentContent 
    270250          }); 
    271251          $('#form-comments .checkboxes-helpers').each(function() { 
     
    277257 
    278258     $('#trackbacks').onetabload(function() { 
    279           $('#form-trackbacks .comments-list tr.line').each(function() { 
    280                dotclear.commentExpander(this); 
     259          $.expandContent({ 
     260               lines:$('#form-trackbacks .comments-list tr.line'), 
     261               callback:dotclear.viewCommentContent 
    281262          }); 
    282263          $('#form-trackbacks .checkboxes-helpers').each(function() { 
  • admin/plugin.php

    r2566 r2593  
    44# This file is part of Dotclear 2. 
    55# 
    6 # Copyright (c) 2003-2013 Olivier Meunier & Association Dotclear 
     6# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear 
    77# Licensed under the GPL version 2.0 license. 
    88# See LICENSE file or 
     
    1515dcPage::check('usage,contentadmin'); 
    1616 
     17$has_content = false; 
    1718$p_file = ''; 
    1819$p = !empty($_REQUEST['p']) ? $_REQUEST['p'] : null; 
    19 $popup = (integer) !empty($_REQUEST['popup']); 
    20  
    21 if ($popup) { 
    22      $open_f = array('dcPage','openPopup'); 
    23      $close_f = array('dcPage','closePopup'); 
    24 } else { 
    25      $open_f = array('dcPage','open'); 
    26      $close_f = array('dcPage','close'); 
    27 } 
     20$popup = $_ctx->popup = (integer) !empty($_REQUEST['popup']); 
    2821 
    2922if ($core->plugins->moduleExists($p)) { 
    3023     $p_file = $core->plugins->moduleRoot($p).'/index.php'; 
    3124} 
     25if (file_exists($p_file)) { 
    3226 
    33 if (file_exists($p_file)) 
    34 { 
    35      # Loading plugin 
     27//* Keep this for old style plugins using dcPage 
     28     if ($popup) { 
     29          $open_f = array('dcPage','openPopup'); 
     30          $close_f = array('dcPage','closePopup'); 
     31     } else { 
     32          $open_f = array('dcPage','open'); 
     33          $close_f = array('dcPage','close'); 
     34     } 
     35      
    3636     $p_info = $core->plugins->getModules($p); 
    37  
    3837     $p_url = 'plugin.php?p='.$p; 
    39  
    40      $p_title = 'no content - plugin'; 
    41      $p_head = ''; 
    42      $p_content = '<p>'.__('No content found on this plugin.').'</p>'; 
    43  
     38     $p_title = $p_head = $p_content = ''; 
     39//*/  
     40     # Get page content 
    4441     ob_start(); 
    4542     include $p_file; 
     
    4744     ob_end_clean(); 
    4845 
    49      if (preg_match('|<head>(.*?)</head|ms',$res,$m)) { 
    50           if (preg_match('|<title>(.*?)</title>|ms',$m[1],$mt)) { 
    51                $p_title = $mt[1]; 
    52           } 
    53  
    54           if (preg_match_all('|(<script.*?>.*?</script>)|ms',$m[1],$ms)) { 
    55                foreach ($ms[1] as $v) { 
    56                     $p_head .= $v."\n"; 
     46     # Check context and display 
     47     if ($_ctx->hasPageTitle() && !empty($res)) { 
     48          $has_content = true; 
     49          echo $res; 
     50     } 
     51//* Keep this for old style plugins using dcPage 
     52     elseif (!$_ctx->hasPageTitle()) { 
     53           
     54          if (preg_match('|<head>(.*?)</head|ms',$res,$m)) { 
     55               if (preg_match('|<title>(.*?)</title>|ms',$m[1],$mt)) { 
     56                    $p_title = $mt[1]; 
     57               } 
     58                
     59               if (preg_match_all('|(<script.*?>.*?</script>)|ms',$m[1],$ms)) { 
     60                    foreach ($ms[1] as $v) { 
     61                         $p_head .= $v."\n"; 
     62                    } 
     63               } 
     64                
     65               if (preg_match_all('|(<style.*?>.*?</style>)|ms',$m[1],$ms)) { 
     66                    foreach ($ms[1] as $v) { 
     67                         $p_head .= $v."\n"; 
     68                    } 
     69               } 
     70                
     71               if (preg_match_all('|(<link.*?/>)|ms',$m[1],$ms)) { 
     72                    foreach ($ms[1] as $v) { 
     73                         $p_head .= $v."\n"; 
     74                    } 
    5775               } 
    5876          } 
    59  
    60           if (preg_match_all('|(<style.*?>.*?</style>)|ms',$m[1],$ms)) { 
    61                foreach ($ms[1] as $v) { 
    62                     $p_head .= $v."\n"; 
    63                } 
    64           } 
    65  
    66           if (preg_match_all('|(<link.*?/>)|ms',$m[1],$ms)) { 
    67                foreach ($ms[1] as $v) { 
    68                     $p_head .= $v."\n"; 
    69                } 
     77           
     78          if (preg_match('|<body.*?>(.+)</body>|ms',$res,$m)) { 
     79               $p_content = $m[1]; 
     80                
     81               call_user_func($open_f,$p_title,$p_head); 
     82               echo $p_content; 
     83               call_user_func($close_f); 
     84                
     85               $has_content = true; 
    7086          } 
    7187     } 
    72  
    73      if (preg_match('|<body.*?>(.+)</body>|ms',$res,$m)) { 
    74           $p_content = $m[1]; 
    75      } 
    76  
    77      call_user_func($open_f,$p_title,$p_head); 
    78      echo $p_content; 
    79      call_user_func($close_f); 
     88//*/ 
    8089} 
    81 else 
    82 { 
    83      call_user_func($open_f,__('Plugin not found'),'', 
    84           dcPage::breadcrumb( 
    85                array( 
    86                     __('System') => '', 
    87                     __('Plugin not found') => '' 
    88                )) 
    89      ); 
    90  
    91      echo '<p>'.__('The plugin you reached does not exist or does not have an admin page.').'</p>'; 
    92  
    93      call_user_func($close_f); 
     90# No plugin or content found 
     91if (!$has_content) { 
     92     $_ctx->setBreadcrumb(__('Plugin not found')); 
     93     $_ctx->addError(__('The plugin you reached does not exist or does not have an admin page.')); 
     94     $core->tpl->display('plugin.html.twig'); 
    9495} 
     96?> 
  • admin/post.php

    r2566 r2593  
    1515dcPage::check('usage,contentadmin'); 
    1616 
    17 $post_id = ''; 
    18 $cat_id = ''; 
    19 $post_dt = ''; 
    20 $post_format = $core->auth->getOption('post_format'); 
    21 $post_password = ''; 
    22 $post_url = ''; 
    23 $post_lang = $core->auth->getInfo('user_lang'); 
    24 $post_title = ''; 
    25 $post_excerpt = ''; 
    26 $post_excerpt_xhtml = ''; 
    27 $post_content = ''; 
    28 $post_content_xhtml = ''; 
    29 $post_notes = ''; 
    30 $post_status = $core->auth->getInfo('user_post_status'); 
    31 $post_selected = false; 
    32 $post_open_comment = $core->blog->settings->system->allow_comments; 
    33 $post_open_tb = $core->blog->settings->system->allow_trackbacks; 
     17class PostActions  
     18{ 
     19     public static function savePost($form) { 
     20          global $_ctx, $core; 
     21          if (!$form->can_edit_post) { 
     22               return; 
     23          } 
     24          try { 
     25               $form->check($_ctx); 
     26               $form->cat_id = (integer) $form->cat_id; 
     27      
     28               if (!empty($form->post_dt)) { 
     29                    try 
     30                    { 
     31                         $post_dt = strtotime($form->post_dt); 
     32                         if ($post_dt == false || $post_dt == -1) { 
     33                              $bad_dt = true; 
     34                              throw new Exception(__('Invalid publication date')); 
     35                         } 
     36                         $form->post_dt = date('Y-m-d H:i',$post_dt); 
     37                    } 
     38                    catch (Exception $e) 
     39                    { 
     40                         $core->error->add($e->getMessage()); 
     41                    } 
     42               } 
     43               $post_excerpt = $form->post_excerpt; 
     44               $post_content = $form->post_content; 
     45               $post_excerpt_xhtml = ''; 
     46               $post_content_xhtml = ''; 
     47               $core->blog->setPostContent( 
     48                    $form->id,$form->post_format,$form->post_lang, 
     49                    $post_excerpt,$post_excerpt_xhtml,$post_content,$post_content_xhtml 
     50               ); 
     51               $form->post_excerpt = $post_excerpt; 
     52               $form->post_content = $post_content; 
     53               $form->post_excerpt_xhtml = $post_excerpt_xhtml; 
     54               $form->post_content_xhtml = $post_content_xhtml; 
     55                
     56               $cur = $core->con->openCursor($core->prefix.'post'); 
     57      
     58               $cur->post_title = $form->post_title; 
     59               $cur->cat_id = $form->cat_id ? $form->cat_id : null; 
     60               $cur->post_dt = $form->post_dt ? date('Y-m-d H:i:00',strtotime($form->post_dt)) : ''; 
     61               $cur->post_format = $form->post_format; 
     62               $cur->post_password = $form->post_password; 
     63               $cur->post_lang = $form->post_lang; 
     64               $cur->post_title = $form->post_title; 
     65               $cur->post_excerpt = $form->post_excerpt; 
     66               $cur->post_excerpt_xhtml = $form->post_excerpt_xhtml; 
     67               $cur->post_content = $form->post_content; 
     68               $cur->post_content_xhtml = $form->post_content_xhtml; 
     69               $cur->post_notes = $form->post_notes; 
     70               $cur->post_status = $form->post_status; 
     71               $cur->post_selected = (integer) $form->post_selected; 
     72               $cur->post_open_comment = (integer) $form->post_open_comment; 
     73               $cur->post_open_tb = (integer) $form->post_open_tb; 
     74      
     75               if (!empty($form->post_url)) { 
     76                    $cur->post_url = $form->post_url; 
     77               } 
     78      
     79               # Update post 
     80               if ($form->id) 
     81               { 
     82                    # --BEHAVIOR-- adminBeforePostUpdate 
     83                    $core->callBehavior('adminBeforePostUpdate',$cur,$form->id); 
     84                     
     85                    $core->blog->updPost($form->id,$cur); 
     86                     
     87                    # --BEHAVIOR-- adminAfterPostUpdate 
     88                    $core->callBehavior('adminAfterPostUpdate',$cur,$form->id); 
     89                    http::redirect('post.php?id='.$form->id.'&upd=1'); 
     90               } 
     91               else 
     92               { 
     93                    $cur->user_id = $core->auth->userID(); 
     94                                        # --BEHAVIOR-- adminBeforePostCreate 
     95                    $core->callBehavior('adminBeforePostCreate',$cur); 
     96                     
     97                    $return_id = $core->blog->addPost($cur); 
     98                     
     99                    # --BEHAVIOR-- adminAfterPostCreate 
     100                    $core->callBehavior('adminAfterPostCreate',$cur,$return_id); 
     101                     
     102                    http::redirect('post.php?id='.$return_id.'&crea=1'); 
     103               } 
     104 
     105          } catch (Exception $e) { 
     106               $_ctx->addError($e->getMessage()); 
     107          } 
     108     } 
     109     public static function deletePost($form) { 
     110          global $core,$_ctx; 
     111          if ($form->can_delete) { 
     112               try { 
     113                    $post_id = $form->id; 
     114                    $core->callBehavior('adminBeforePostDelete',$post_id); 
     115                    $core->blog->delPost($post_id); 
     116                    http::redirect('posts.php'); 
     117                    exit; 
     118               } catch (Exception $e) { 
     119                    $_ctx->addError($e->getMessage()); 
     120               } 
     121          } 
     122     } 
     123} 
    34124 
    35125$page_title = __('New entry'); 
    36  
     126$post_id=''; 
    37127$can_view_page = true; 
    38128$can_edit_post = $core->auth->check('usage,contentadmin',$core->blog->id); 
     
    47137# If user can't publish 
    48138if (!$can_publish) { 
    49      $post_status = -2; 
     139     $form->post_status = -2; 
    50140} 
    51141 
    52142# Getting categories 
    53 $categories_combo = dcAdminCombos::getCategoriesCombo( 
    54      $core->blog->getCategories(array('post_type'=>'post')) 
    55 ); 
    56  
    57 $status_combo = dcAdminCombos::getPostStatusesCombo(); 
    58  
    59 $img_status_pattern = '<img class="img_select_option" alt="%1$s" title="%1$s" src="images/%2$s" />'; 
     143$categories_combo = array('&nbsp;' => ''); 
     144try { 
     145     $categories = $core->blog->getCategories(array('post_type'=>'post')); 
     146     while ($categories->fetch()) { 
     147          $categories_combo[$categories->cat_id] =  
     148               str_repeat('&nbsp;&nbsp;',$categories->level-1). 
     149               ($categories->level-1 == 0 ? '' : '&bull; '). 
     150               html::escapeHTML($categories->cat_title); 
     151     } 
     152} catch (Exception $e) { } 
     153 
     154# Status combo 
     155foreach ($core->blog->getAllPostStatus() as $k => $v) { 
     156     $status_combo[$k] = $v; 
     157} 
    60158 
    61159# Formaters combo 
    62 $formaters_combo = dcAdminCombos::getFormatersCombo(); 
     160foreach ($core->getFormaters() as $v) { 
     161     $formaters_combo[$v] = $v; 
     162} 
    63163 
    64164# Languages combo 
    65165$rs = $core->blog->getLangs(array('order'=>'asc')); 
    66 $lang_combo = dcAdminCombos::getLangsCombo($rs,true); 
    67  
    68 # Validation flag 
    69 $bad_dt = false; 
    70  
    71 # Trackbacks 
    72 $TB = new dcTrackback($core); 
    73 $tb_urls = $tb_excerpt = ''; 
    74  
     166$all_langs = l10n::getISOcodes(0,1); 
     167$lang_combo = array('' => '', __('Most used') => array(), __('Available') => l10n::getISOcodes(0,1)); 
     168while ($rs->fetch()) { 
     169     if (isset($all_langs[$rs->post_lang])) { 
     170          $lang_combo[__('Most used')][$rs->post_lang] = $all_langs[$rs->post_lang]; 
     171          unset($lang_combo[__('Available')][$rs->post_lang]); 
     172     } else { 
     173          $lang_combo[__('Most used')][$rs->post_lang] = $all_langs[$rs->post_lang]; 
     174     } 
     175} 
     176unset($all_langs); 
     177unset($rs); 
     178 
     179$form = new dcForm($core,'post','post.php'); 
     180$form 
     181     ->addField( 
     182          new dcFieldText('post_title','', array( 
     183               'maxlength'         => 255, 
     184               'required'     => true, 
     185               'label'        => __('Title:')))) 
     186     ->addField( 
     187          new dcFieldTextArea('post_excerpt','', array( 
     188               'cols'         => 50, 
     189               'rows'         => 5, 
     190               'label'        => __("Excerpt:").'<span class="form-note">'. 
     191               __('Add an introduction to the post.').'</span>'))) 
     192     ->addField( 
     193          new dcFieldTextArea('post_content','', array( 
     194               'required'     => true, 
     195               'label'        => __("Content:")))) 
     196     ->addField( 
     197          new dcFieldTextArea('post_notes','', array( 
     198               'label'        => __("Notes")))) 
     199     ->addField( 
     200          new dcFieldSubmit('save',__('Save'),array( 
     201               'action' => array('PostActions','savePost')))) 
     202     ->addField( 
     203          new dcFieldSubmit('delete',__('Delete'),array( 
     204               'action' => array('PostActions','deletePost')))) 
     205     ->addField( 
     206          new dcFieldCombo('post_status',$core->auth->getInfo('user_post_status'),$status_combo,array( 
     207               'disabled' => !$can_publish, 
     208               'label' => __('Entry status')))) 
     209     ->addField( 
     210          new dcFieldCombo('cat_id','',$categories_combo,array( 
     211               "label" => __('Category')))) 
     212     ->addField( 
     213          new dcFieldCombo('new_cat_parent','',$categories_combo,array( 
     214               "label" => __('Parent:')))) 
     215     ->addField( 
     216          new dcFieldText('new_cat_title','', array( 
     217               'maxlength'         => 255, 
     218               'label'        => __('Title')))) 
     219           
     220     ->addField( 
     221          new dcFieldText('post_dt','',array( 
     222               "label" => __('Publication date and hour')))) 
     223     ->addField( 
     224          new dcFieldCombo('post_format',$core->auth->getOption('post_format'),$formaters_combo,array( 
     225               "label" => __('Text formating')))) 
     226     ->addField( 
     227          new dcFieldCheckbox ('post_open_comment',$core->blog->settings->system->allow_comments,array( 
     228               "label" => __('Accept comments')))) 
     229     ->addField( 
     230          new dcFieldCheckbox ('post_open_tb',$core->blog->settings->system->allow_trackbacks,array( 
     231               "label" => __('Accept trackbacks')))) 
     232     ->addField( 
     233          new dcFieldCheckbox ('post_selected',array(1=>false),array( 
     234               "label" => __('Selected entry')))) 
     235     ->addField( 
     236          new dcFieldCombo ('post_lang',$core->auth->getInfo('user_lang'),$lang_combo, array( 
     237               "label" => __('Entry lang:')))) 
     238     ->addField( 
     239          new dcFieldText('post_password','',array( 
     240               "maxlength" => 32, 
     241               "label" => __('Entry password:')))) 
     242     ->addField( 
     243          new dcFieldText('post_url','',array( 
     244               "maxlength" => 255, 
     245               "label" => __('Basename:')))) 
     246     ->addField( 
     247          new dcFieldHidden ('id','')) 
     248; 
    75249# Get entry informations 
    76250if (!empty($_REQUEST['id'])) 
    77251{ 
    78      $page_title = __('Edit entry'); 
    79  
    80252     $params['post_id'] = $_REQUEST['id']; 
    81  
     253      
    82254     $post = $core->blog->getPosts($params); 
    83  
     255      
    84256     if ($post->isEmpty()) 
    85257     { 
     
    89261     else 
    90262     { 
    91           $post_id = $post->post_id; 
    92           $cat_id = $post->cat_id; 
    93           $post_dt = date('Y-m-d H:i',strtotime($post->post_dt)); 
    94           $post_format = $post->post_format; 
    95           $post_password = $post->post_password; 
    96           $post_url = $post->post_url; 
    97           $post_lang = $post->post_lang; 
    98           $post_title = $post->post_title; 
    99           $post_excerpt = $post->post_excerpt; 
    100           $post_excerpt_xhtml = $post->post_excerpt_xhtml; 
    101           $post_content = $post->post_content; 
    102           $post_content_xhtml = $post->post_content_xhtml; 
    103           $post_notes = $post->post_notes; 
    104           $post_status = $post->post_status; 
    105           $post_selected = (boolean) $post->post_selected; 
    106           $post_open_comment = (boolean) $post->post_open_comment; 
    107           $post_open_tb = (boolean) $post->post_open_tb; 
    108  
    109           $can_edit_post = $post->isEditable(); 
    110           $can_delete= $post->isDeletable(); 
    111  
     263          $form->id = $post_id = $post->post_id; 
     264          $form->cat_id = $post->cat_id; 
     265          $form->post_dt = date('Y-m-d H:i',strtotime($post->post_dt)); 
     266          $form->post_format = $post->post_format; 
     267          $form->post_password = $post->post_password; 
     268          $form->post_url = $post->post_url; 
     269          $form->post_lang = $post->post_lang; 
     270          $form->post_title = $post->post_title; 
     271          $form->post_excerpt = $post->post_excerpt; 
     272          $form->post_excerpt_xhtml = $post->post_excerpt_xhtml; 
     273          $form->post_content = $post->post_content; 
     274          $form->post_content_xhtml = $post->post_content_xhtml; 
     275          $form->post_notes = $post->post_notes; 
     276          $form->post_status = $post->post_status; 
     277          $form->post_selected = (boolean) $post->post_selected; 
     278          $form->post_open_comment = (boolean) $post->post_open_comment; 
     279          $form->post_open_tb = (boolean) $post->post_open_tb; 
     280          $form->can_edit_post = $post->isEditable(); 
     281          $form->can_delete= $post->isDeletable(); 
    112282          $next_rs = $core->blog->getNextPost($post,1); 
    113283          $prev_rs = $core->blog->getNextPost($post,-1); 
    114  
     284           
    115285          if ($next_rs !== null) { 
    116                $next_link = sprintf($post_link,$next_rs->post_id, 
    117                     html::escapeHTML($next_rs->post_title),__('Next entry').'&nbsp;&#187;'); 
    118                $next_headlink = sprintf($post_headlink,'next', 
    119                     html::escapeHTML($next_rs->post_title),$next_rs->post_id); 
    120           } 
    121  
     286               $_ctx->next_post = array('id' => $next_rs->post_id,'title' => $next_rs->post_title); 
     287          } 
    122288          if ($prev_rs !== null) { 
    123                $prev_link = sprintf($post_link,$prev_rs->post_id, 
    124                     html::escapeHTML($prev_rs->post_title),'&#171;&nbsp;'.__('Previous entry')); 
    125                $prev_headlink = sprintf($post_headlink,'previous', 
    126                     html::escapeHTML($prev_rs->post_title),$prev_rs->post_id); 
    127           } 
    128  
    129           try { 
    130                $core->media = new dcMedia($core); 
    131           } catch (Exception $e) { 
    132                $core->error->add($e->getMessage()); 
    133           } 
    134  
    135           # Sanitize trackbacks excerpt 
    136           $tb_excerpt = empty($_POST['tb_excerpt']) ? 
    137                $post_excerpt_xhtml.' '.$post_content_xhtml : 
    138                $_POST['tb_excerpt']; 
    139           $tb_excerpt = html::decodeEntities(html::clean($tb_excerpt)); 
    140           $tb_excerpt = text::cutString(html::escapeHTML($tb_excerpt), 255); 
    141           $tb_excerpt = preg_replace('/\s+/ms', ' ', $tb_excerpt); 
    142      } 
    143 } 
    144 if (isset($_REQUEST['section']) && $_REQUEST['section']=='trackbacks') { 
    145      $anchor = 'trackbacks'; 
    146 } else { 
    147      $anchor = 'comments'; 
    148 } 
    149  
    150 $comments_actions_page = new dcCommentsActionsPage($core,'post.php',array('id' => $post_id, '_ANCHOR'=>$anchor,'section' => $anchor)); 
    151  
    152 if ($comments_actions_page->process()) { 
    153      return; 
    154 } 
    155  
    156 # Ping blogs 
    157 if (!empty($_POST['ping'])) 
    158 { 
    159      if (!empty($_POST['tb_urls']) && $post_id && $post_status == 1 && $can_edit_post) 
    160      { 
    161           $tb_urls = $_POST['tb_urls']; 
    162           $tb_urls = str_replace("\r", '', $tb_urls); 
    163           $tb_post_title = html::escapeHTML(trim(html::clean($post_title))); 
    164           $tb_post_url = $post->getURL(); 
    165  
    166           foreach (explode("\n", $tb_urls) as $tb_url) 
    167           { 
    168                try { 
    169                     $TB->ping($tb_url, $post_id, $tb_post_title, $tb_excerpt, $tb_post_url); 
    170                } catch (Exception $e) { 
    171                     $core->error->add($e->getMessage()); 
    172                } 
    173           } 
    174  
    175           if (!$core->error->flag()) { 
    176                dcPage::addSuccessNotice(__('All pings sent.')); 
    177                http::redirect('post.php?id='.$post_id.'&tb=1'); 
    178           } 
    179      } 
    180 } 
    181  
    182 # Format excerpt and content 
    183 elseif (!empty($_POST) && $can_edit_post) 
    184 { 
    185      $post_format = $_POST['post_format']; 
    186      $post_excerpt = $_POST['post_excerpt']; 
    187      $post_content = $_POST['post_content']; 
    188  
    189      $post_title = $_POST['post_title']; 
    190  
    191      $cat_id = (integer) $_POST['cat_id']; 
    192  
    193      if (isset($_POST['post_status'])) { 
    194           $post_status = (integer) $_POST['post_status']; 
    195      } 
    196  
    197      if (empty($_POST['post_dt'])) { 
    198           $post_dt = ''; 
    199      } else { 
    200           try 
    201           { 
    202                $post_dt = strtotime($_POST['post_dt']); 
    203                if ($post_dt == false || $post_dt == -1) { 
    204                     $bad_dt = true; 
    205                     throw new Exception(__('Invalid publication date')); 
    206                } 
    207                $post_dt = date('Y-m-d H:i',$post_dt); 
    208           } 
    209           catch (Exception $e) 
    210           { 
    211                $core->error->add($e->getMessage()); 
    212           } 
    213      } 
    214  
    215      $post_open_comment = !empty($_POST['post_open_comment']); 
    216      $post_open_tb = !empty($_POST['post_open_tb']); 
    217      $post_selected = !empty($_POST['post_selected']); 
    218      $post_lang = $_POST['post_lang']; 
    219      $post_password = !empty($_POST['post_password']) ? $_POST['post_password'] : null; 
    220  
    221      $post_notes = $_POST['post_notes']; 
    222  
    223      if (isset($_POST['post_url'])) { 
    224           $post_url = $_POST['post_url']; 
    225      } 
    226  
    227      $core->blog->setPostContent( 
    228           $post_id,$post_format,$post_lang, 
    229           $post_excerpt,$post_excerpt_xhtml,$post_content,$post_content_xhtml 
    230      ); 
    231 } 
    232  
    233 # Delete post 
    234 if (!empty($_POST['delete']) && $can_delete) 
    235 { 
    236      try { 
    237           # --BEHAVIOR-- adminBeforePostDelete 
    238           $core->callBehavior('adminBeforePostDelete',$post_id); 
    239           $core->blog->delPost($post_id); 
    240           http::redirect('posts.php'); 
    241      } catch (Exception $e) { 
    242           $core->error->add($e->getMessage()); 
    243      } 
    244 } 
    245  
    246 # Create or update post 
    247 if (!empty($_POST) && !empty($_POST['save']) && $can_edit_post && !$bad_dt) 
    248 { 
    249      # Create category 
    250      if (!empty($_POST['new_cat_title']) && $core->auth->check('categories', $core->blog->id)) { 
    251  
    252           $cur_cat = $core->con->openCursor($core->prefix.'category'); 
    253           $cur_cat->cat_title = $_POST['new_cat_title']; 
    254           $cur_cat->cat_url = ''; 
    255  
    256           $parent_cat = !empty($_POST['new_cat_parent']) ? $_POST['new_cat_parent'] : ''; 
    257  
    258           # --BEHAVIOR-- adminBeforeCategoryCreate 
    259           $core->callBehavior('adminBeforeCategoryCreate', $cur_cat); 
    260  
    261           $cat_id = $core->blog->addCategory($cur_cat, (integer) $parent_cat); 
    262  
    263           # --BEHAVIOR-- adminAfterCategoryCreate 
    264           $core->callBehavior('adminAfterCategoryCreate', $cur_cat, $cat_id); 
    265      } 
    266  
    267      $cur = $core->con->openCursor($core->prefix.'post'); 
    268  
    269      $cur->post_title = $post_title; 
    270      $cur->cat_id = ($cat_id ? $cat_id : null); 
    271      $cur->post_dt = $post_dt ? date('Y-m-d H:i:00',strtotime($post_dt)) : ''; 
    272      $cur->post_format = $post_format; 
    273      $cur->post_password = $post_password; 
    274      $cur->post_lang = $post_lang; 
    275      $cur->post_title = $post_title; 
    276      $cur->post_excerpt = $post_excerpt; 
    277      $cur->post_excerpt_xhtml = $post_excerpt_xhtml; 
    278      $cur->post_content = $post_content; 
    279      $cur->post_content_xhtml = $post_content_xhtml; 
    280      $cur->post_notes = $post_notes; 
    281      $cur->post_status = $post_status; 
    282      $cur->post_selected = (integer) $post_selected; 
    283      $cur->post_open_comment = (integer) $post_open_comment; 
    284      $cur->post_open_tb = (integer) $post_open_tb; 
    285  
    286      if (isset($_POST['post_url'])) { 
    287           $cur->post_url = $post_url; 
    288      } 
    289  
    290      # Update post 
    291      if ($post_id) 
    292      { 
    293           try 
    294           { 
    295                # --BEHAVIOR-- adminBeforePostUpdate 
    296                $core->callBehavior('adminBeforePostUpdate',$cur,$post_id); 
    297  
    298                $core->blog->updPost($post_id,$cur); 
    299  
    300                # --BEHAVIOR-- adminAfterPostUpdate 
    301                $core->callBehavior('adminAfterPostUpdate',$cur,$post_id); 
    302                dcPage::addSuccessNotice (sprintf(__('The post "%s" has been successfully updated'),html::escapeHTML($cur->post_title))); 
    303                http::redirect('post.php?id='.$post_id); 
    304           } 
    305           catch (Exception $e) 
    306           { 
    307                $core->error->add($e->getMessage()); 
    308           } 
    309      } 
    310      else 
    311      { 
    312           $cur->user_id = $core->auth->userID(); 
    313  
    314           try 
    315           { 
    316                # --BEHAVIOR-- adminBeforePostCreate 
    317                $core->callBehavior('adminBeforePostCreate',$cur); 
    318  
    319                $return_id = $core->blog->addPost($cur); 
    320  
    321                # --BEHAVIOR-- adminAfterPostCreate 
    322                $core->callBehavior('adminAfterPostCreate',$cur,$return_id); 
    323  
    324                dcPage::addSuccessNotice(__('Entry has been successfully created.')); 
    325                http::redirect('post.php?id='.$return_id); 
    326           } 
    327           catch (Exception $e) 
    328           { 
    329                $core->error->add($e->getMessage()); 
    330           } 
    331      } 
    332 } 
    333  
    334 # Getting categories 
    335 $categories_combo = dcAdminCombos::getCategoriesCombo( 
    336      $core->blog->getCategories(array('post_type'=>'post')) 
    337 ); 
     289               $_ctx->prev_post = array('id' => $prev_rs->post_id,'title' => $prev_rs->post_title); 
     290          } 
     291          $page_title = __('Edit entry'); 
     292 
     293     } 
     294} 
     295if ($post_id) { 
     296     $_ctx->post_id = $post->post_id; 
     297 
     298     $_ctx->preview_url = 
     299          $core->blog->url.$core->url->getURLFor('preview',$core->auth->userID().'/'. 
     300          http::browserUID(DC_MASTER_KEY.$core->auth->userID().$core->auth->getInfo('user_pwd')). 
     301          '/'.$post->post_url); 
     302           
     303      
     304     $form_comment = new dcForm($core,'add-comment','comment.php'); 
     305     $form_comment 
     306          ->addField( 
     307               new dcFieldText('comment_author','', array( 
     308                    'maxlength'         => 255, 
     309                    'required'     => true, 
     310                    'label'        => __('Name:')))) 
     311          ->addField( 
     312               new dcFieldText('comment_email','', array( 
     313                    'maxlength'         => 255, 
     314                    'required'     => true, 
     315                    'label'        => __('Email:')))) 
     316          ->addField( 
     317               new dcFieldText('comment_site','', array( 
     318                    'maxlength'         => 255, 
     319                    'label'        => __('Web site:')))) 
     320          ->addField( 
     321               new dcFieldTextArea('comment_content','', array( 
     322                    'required'     => true, 
     323                    'label'        => __('Comment:')))) 
     324          ->addField( 
     325               new dcFieldHidden('post_id',$post_id)) 
     326          ->addField( 
     327               new dcFieldSubmit('add',__('Save'),array( 
     328                    'action' => 'addComment'))) 
     329          ; 
     330 
     331      
     332} 
     333 
     334$form->setup(); 
     335 
     336$sidebar_blocks = new ArrayObject(array( 
     337     'status-box' => array( 
     338          'title' => __('Status'), 
     339          'items' => array('post_status','post_dt','post_lang','post_format')), 
     340     'metas-box' => array( 
     341          'title' => __('Ordering'), 
     342          'items' => array('post_selected','cat_id')), 
     343     'options-box' => array( 
     344          'title' => __('Options'), 
     345          'items' => array('post_open_comment','post_open_tb','post_password','post_url')) 
     346)); 
     347 
     348$main_blocks = new ArrayObject(array( 
     349     "post_title","post_excerpt","post_content","post_notes" 
     350)); 
     351 
     352 
     353$_ctx->sidebar_blocks = $sidebar_blocks; 
     354$_ctx->main_blocks = $main_blocks; 
     355 
    338356/* DISPLAY 
    339357-------------------------------------------------------- */ 
     
    345363     $default_tab = 'comments'; 
    346364} 
    347 elseif (!empty($_GET['tb'])) { 
    348      $default_tab = 'trackbacks'; 
    349 } 
    350  
    351 if ($post_id) { 
    352      switch ($post_status) { 
    353           case 1: 
    354                $img_status = sprintf($img_status_pattern,__('Published'),'check-on.png'); 
    355                break; 
    356           case 0: 
    357                $img_status = sprintf($img_status_pattern,__('Unpublished'),'check-off.png'); 
    358                break; 
    359           case -1: 
    360                $img_status = sprintf($img_status_pattern,__('Scheduled'),'scheduled.png'); 
    361                break; 
    362           case -2: 
    363                $img_status = sprintf($img_status_pattern,__('Pending'),'check-wrn.png'); 
    364                break; 
    365           default: 
    366                $img_status = ''; 
    367      } 
    368      $edit_entry_str = __('&ldquo;%s&rdquo;'); 
    369      $page_title_edit = sprintf($edit_entry_str, html::escapeHTML($post_title)).' '.$img_status; 
    370 } else { 
    371      $img_status = ''; 
    372 } 
    373  
    374  
    375 dcPage::open($page_title.' - '.__('Entries'), 
    376      dcPage::jsDatePicker(). 
    377      dcPage::jsToolBar(). 
    378      dcPage::jsModal(). 
    379      dcPage::jsMetaEditor(). 
    380      dcPage::jsLoad('js/_post.js'). 
    381      dcPage::jsConfirmClose('entry-form','comment-form'). 
    382      # --BEHAVIOR-- adminPostHeaders 
    383      $core->callBehavior('adminPostHeaders'). 
    384      dcPage::jsPageTabs($default_tab). 
    385      $next_headlink."\n".$prev_headlink, 
    386      dcPage::breadcrumb( 
     365$page_title_edit = __('Edit entry'); 
     366$_ctx 
     367     ->setBreadCrumb( 
    387368          array( 
    388369               html::escapeHTML($core->blog->name) => '', 
    389370               __('Entries') => 'posts.php', 
    390371               ($post_id ? $page_title_edit : $page_title) => '' 
    391           )) 
    392 ); 
     372     )) 
     373     ->default_tab = $default_tab; 
     374$_ctx->post_status = $form->post_status; 
     375$_ctx->post_title = $form->post_title; 
     376if ($form->post_status == 1) { 
     377     $_ctx->post_url = $post->getURL(); 
     378} 
    393379 
    394380if (!empty($_GET['upd'])) { 
    395      dcPage::success(__('Entry has been successfully updated.')); 
     381     $_ctx->setAlert(__('Entry has been successfully updated.')); 
    396382} 
    397383elseif (!empty($_GET['crea'])) { 
    398      dcPage::success(__('Entry has been successfully created.')); 
     384     $_ctx->setAlert(__('Entry has been successfully created.')); 
    399385} 
    400386elseif (!empty($_GET['attached'])) { 
    401      dcPage::success(__('File has been successfully attached.')); 
     387     $_ctx->setAlert(__('File has been successfully attached.')); 
    402388} 
    403389elseif (!empty($_GET['rmattach'])) { 
    404      dcPage::success(__('Attachment has been successfully removed.')); 
    405 } 
    406  
     390     $_ctx->setAlert(__('Attachment has been successfully removed.')); 
     391} 
    407392if (!empty($_GET['creaco'])) { 
    408      dcPage::success(__('Comment has been successfully created.')); 
    409 } 
    410 if (!empty($_GET['tbsent'])) { 
    411      dcPage::success(__('All pings sent.')); 
    412 } 
    413  
    414 # XHTML conversion 
    415 if (!empty($_GET['xconv'])) 
    416 { 
    417      $post_excerpt = $post_excerpt_xhtml; 
    418      $post_content = $post_content_xhtml; 
    419      $post_format = 'xhtml'; 
    420  
    421      dcPage::message(__('Don\'t forget to validate your XHTML conversion by saving your post.')); 
    422 } 
    423  
    424 if ($post_id && $post->post_status == 1) { 
    425      echo '<p><a class="onblog_link outgoing" href="'.$post->getURL().'" title="'.$post_title.'">'.__('Go to this entry on the site').' <img src="images/outgoing-blue.png" alt="" /></a></p>'; 
    426 } 
    427 if ($post_id) 
    428 { 
    429      echo '<p class="nav_prevnext">'; 
    430      if ($prev_link) { echo $prev_link; } 
    431      if ($next_link && $prev_link) { echo ' | '; } 
    432      if ($next_link) { echo $next_link; } 
    433  
    434      # --BEHAVIOR-- adminPostNavLinks 
    435      $core->callBehavior('adminPostNavLinks',isset($post) ? $post : null); 
    436  
    437      echo '</p>'; 
    438 } 
    439  
    440 # Exit if we cannot view page 
    441 if (!$can_view_page) { 
    442      dcPage::helpBlock('core_post'); 
    443      dcPage::close(); 
    444      exit; 
    445 } 
    446 /* Post form if we can edit post 
    447 -------------------------------------------------------- */ 
    448 if ($can_edit_post) 
    449 { 
    450      $sidebar_items = new ArrayObject(array( 
    451           'status-box' => array( 
    452                'title' => __('Status'), 
    453                'items' => array( 
    454                     'post_status' => 
    455                          '<p class="entry-status"><label for="post_status">'.__('Entry status').' '.$img_status.'</label>'. 
    456                          form::combo('post_status',$status_combo,$post_status,'maximal','',!$can_publish). 
    457                          '</p>', 
    458                     'post_dt' => 
    459                          '<p><label for="post_dt">'.__('Publication date and hour').'</label>'. 
    460                          form::field('post_dt',16,16,$post_dt,($bad_dt ? 'invalid' : '')). 
    461                          '</p>', 
    462                     'post_lang' => 
    463                          '<p><label for="post_lang">'.__('Entry language').'</label>'. 
    464                          form::combo('post_lang',$lang_combo,$post_lang). 
    465                          '</p>', 
    466                     'post_format' => 
    467                          '<div>'. 
    468                          '<h5 id="label_format"><label for="post_format" class="classic">'.__('Text formatting').'</label></h5>'. 
    469                          '<p>'.form::combo('post_format',$formaters_combo,$post_format,'maximal'). 
    470                          '</p>'. 
    471                          '<p class="format_control control_no_xhtml">'. 
    472                          '<a id="convert-xhtml" class="button'.($post_id && $post_format != 'wiki' ? ' hide' : '').'" href="post.php?id='.$post_id.'&amp;xconv=1">'. 
    473                          __('Convert to XHTML').'</a></p></div>')), 
    474           'metas-box' => array( 
    475                'title' => __('Filing'), 
    476                'items' => array( 
    477                     'post_selected' => 
    478                          '<p><label for="post_selected" class="classic">'. 
    479                          form::checkbox('post_selected',1,$post_selected).' '. 
    480                          __('Selected entry').'</label></p>', 
    481                     'cat_id' => 
    482                          '<div>'. 
    483                          '<h5 id="label_cat_id">'.__('Category').'</h5>'. 
    484                          '<p><label for="cat_id">'.__('Category:').'</label>'. 
    485                          form::combo('cat_id',$categories_combo,$cat_id,'maximal'). 
    486                          '</p>'. 
    487                          ($core->auth->check('categories', $core->blog->id) ? 
    488                               '<div>'. 
    489                               '<h5 id="create_cat">'.__('Add a new category').'</h5>'. 
    490                               '<p><label for="new_cat_title">'.__('Title:').' '. 
    491                               form::field('new_cat_title',30,255,'','maximal').'</label></p>'. 
    492                               '<p><label for="new_cat_parent">'.__('Parent:').' '. 
    493                               form::combo('new_cat_parent',$categories_combo,'','maximal'). 
    494                               '</label></p>'. 
    495                               '</div>' 
    496                          : ''). 
    497                          '</div>')), 
    498           'options-box' => array( 
    499                'title' => __('Options'), 
    500                'items' => array( 
    501                     'post_open_comment_tb' => 
    502                          '<div>'. 
    503                          '<h5 id="label_comment_tb">'.__('Comments and trackbacks list').'</h5>'. 
    504                          '<p><label for="post_open_comment" class="classic">'. 
    505                          form::checkbox('post_open_comment',1,$post_open_comment).' '. 
    506                          __('Accept comments').'</label></p>'. 
    507                          ($core->blog->settings->system->allow_comments ? 
    508                               (isContributionAllowed($post_id,strtotime($post_dt),true) ? 
    509                                    '' : 
    510                                    '<p class="form-note warn">'. 
    511                                    __('Warning: Comments are not more accepted for this entry.').'</p>') : 
    512                               '<p class="form-note warn">'. 
    513                               __('Comments are not accepted on this blog so far.').'</p>'). 
    514                          '<p><label for="post_open_tb" class="classic">'. 
    515                          form::checkbox('post_open_tb',1,$post_open_tb).' '. 
    516                          __('Accept trackbacks').'</label></p>'. 
    517                          ($core->blog->settings->system->allow_trackbacks ? 
    518                               (isContributionAllowed($post_id,strtotime($post_dt),false) ? 
    519                                    '' : 
    520                                    '<p class="form-note warn">'. 
    521                                    __('Warning: Trackbacks are not more accepted for this entry.').'</p>') : 
    522                               '<p class="form-note warn">'.__('Trackbacks are not accepted on this blog so far.').'</p>'). 
    523                          '</div>', 
    524                     'post_password' => 
    525                          '<p><label for="post_password">'.__('Password').'</label>'. 
    526                          form::field('post_password',10,32,html::escapeHTML($post_password),'maximal'). 
    527                          '</p>', 
    528                     'post_url' => 
    529                          '<div class="lockable">'. 
    530                          '<p><label for="post_url">'.__('Edit basename').'</label>'. 
    531                          form::field('post_url',10,255,html::escapeHTML($post_url),'maximal'). 
    532                          '</p>'. 
    533                          '<p class="form-note warn">'. 
    534                          __('Warning: If you set the URL manually, it may conflict with another entry.'). 
    535                          '</p></div>' 
    536      )))); 
    537  
    538      $main_items = new ArrayObject(array( 
    539           "post_title" => 
    540                '<p class="col">'. 
    541                '<label class="required no-margin bold"><abbr title="'.__('Required field').'">*</abbr> '.__('Title:').'</label>'. 
    542                form::field('post_title',20,255,html::escapeHTML($post_title),'maximal'). 
    543                '</p>', 
    544  
    545           "post_excerpt" => 
    546                '<p class="area" id="excerpt-area"><label for="post_excerpt" class="bold">'.__('Excerpt:').' <span class="form-note">'. 
    547                __('Introduction to the post.').'</span></label> '. 
    548                form::textarea('post_excerpt',50,5,html::escapeHTML($post_excerpt)). 
    549                '</p>', 
    550  
    551           "post_content" => 
    552                '<p class="area" id="content-area"><label class="required bold" '. 
    553                'for="post_content"><abbr title="'.__('Required field').'">*</abbr> '.__('Content:').'</label> '. 
    554                form::textarea('post_content',50,$core->auth->getOption('edit_size'),html::escapeHTML($post_content)). 
    555                '</p>', 
    556  
    557           "post_notes" => 
    558                '<p class="area" id="notes-area"><label for="post_notes" class="bold">'.__('Personal notes:').' <span class="form-note">'. 
    559                __('Unpublished notes.').'</span></label>'. 
    560                form::textarea('post_notes',50,5,html::escapeHTML($post_notes)). 
    561                '</p>' 
    562           ) 
    563      ); 
    564  
    565      # --BEHAVIOR-- adminPostFormItems 
    566      $core->callBehavior('adminPostFormItems',$main_items,$sidebar_items, isset($post) ? $post : null); 
    567  
    568      echo '<div class="multi-part" title="'.($post_id ? __('Edit entry') : __('New entry')).'" id="edit-entry">'; 
    569      echo '<form action="post.php" method="post" id="entry-form">'; 
    570      echo '<div id="entry-wrapper">'; 
    571      echo '<div id="entry-content"><div class="constrained">'; 
    572  
    573      echo '<h3 class="out-of-screen-if-js">'.__('Edit post').'</h3>'; 
    574  
    575      foreach ($main_items as $id => $item) { 
    576           echo $item; 
    577      } 
    578  
    579      # --BEHAVIOR-- adminPostForm (may be deprecated) 
    580      $core->callBehavior('adminPostForm',isset($post) ? $post : null); 
    581  
    582      echo 
    583      '<p class="border-top">'. 
    584      ($post_id ? form::hidden('id',$post_id) : ''). 
    585      '<input type="submit" value="'.__('Save').' (s)" '. 
    586      'accesskey="s" name="save" /> '; 
    587      if ($post_id) { 
    588           $preview_url = 
    589           $core->blog->url.$core->url->getURLFor('preview',$core->auth->userID().'/'. 
    590           http::browserUID(DC_MASTER_KEY.$core->auth->userID().$core->auth->getInfo('user_pwd')). 
    591           '/'.$post->post_url); 
    592           echo '<a id="post-preview" href="'.$preview_url.'" class="button modal" accesskey="p">'.__('Preview').' (p)'.'</a> '; 
    593      } else { 
    594           echo 
    595           '<a id="post-cancel" href="index.php" class="button" accesskey="c">'.__('Cancel').' (c)</a>'; 
    596      } 
    597  
    598      echo 
    599      ($can_delete ? '<input type="submit" class="delete" value="'.__('Delete').'" name="delete" />' : ''). 
    600      $core->formNonce(). 
    601      '</p>'; 
    602  
    603      echo '</div></div>';          // End #entry-content 
    604      echo '</div>';      // End #entry-wrapper 
    605  
    606      echo '<div id="entry-sidebar">'; 
    607  
    608      foreach ($sidebar_items as $id => $c) { 
    609           echo '<div id="'.$id.'" class="sb-box">'. 
    610                '<h4>'.$c['title'].'</h4>'; 
    611           foreach ($c['items'] as $e_name=>$e_content) { 
    612                echo $e_content; 
    613           } 
    614           echo '</div>'; 
    615      } 
    616  
    617  
    618      # --BEHAVIOR-- adminPostFormSidebar (may be deprecated) 
    619      $core->callBehavior('adminPostFormSidebar',isset($post) ? $post : null); 
    620      echo '</div>';      // End #entry-sidebar 
    621  
    622      echo '</form>'; 
    623  
    624      # --BEHAVIOR-- adminPostForm 
    625      $core->callBehavior('adminPostAfterForm',isset($post) ? $post : null); 
    626  
    627      echo '</div>'; 
    628 } 
    629  
    630 if ($post_id) 
    631 { 
    632      /* Comments 
    633      -------------------------------------------------------- */ 
    634  
    635      $params = array('post_id' => $post_id, 'order' => 'comment_dt ASC'); 
    636  
    637      $comments = $core->blog->getComments(array_merge($params,array('comment_trackback'=>0))); 
    638  
    639      echo 
    640      '<div id="comments" class="clear multi-part" title="'.__('Comments').'">'; 
    641      $combo_action = $comments_actions_page->getCombo(); 
    642      $has_action = !empty($combo_action) && !$comments->isEmpty(); 
    643      echo 
    644      '<p class="top-add"><a class="button add" href="#comment-form">'.__('Add a comment').'</a></p>'; 
    645  
    646      if ($has_action) { 
    647           echo '<form action="post.php" id="form-comments" method="post">'; 
    648      } 
    649  
    650      echo '<h3>'.__('Comments').'</h3>'; 
    651      if (!$comments->isEmpty()) { 
    652           showComments($comments,$has_action); 
    653      } else { 
    654           echo '<p>'.__('No comment').'</p>'; 
    655      } 
    656  
    657      if ($has_action) { 
    658           echo 
    659           '<div class="two-cols">'. 
    660           '<p class="col checkboxes-helpers"></p>'. 
    661  
    662           '<p class="col right"><label for="action" class="classic">'.__('Selected comments action:').'</label> '. 
    663           form::combo('action',$combo_action). 
    664           form::hidden(array('section'),'comments'). 
    665           form::hidden(array('id'),$post_id). 
    666           $core->formNonce(). 
    667           '<input type="submit" value="'.__('ok').'" /></p>'. 
    668           '</div>'. 
    669           '</form>'; 
    670      } 
    671      /* Add a comment 
    672      -------------------------------------------------------- */ 
    673  
    674      echo 
    675      '<div class="fieldset clear">'. 
    676      '<h3>'.__('Add a comment').'</h3>'. 
    677  
    678      '<form action="comment.php" method="post" id="comment-form">'. 
    679      '<div class="constrained">'. 
    680      '<p><label for="comment_author" class="required"><abbr title="'.__('Required field').'">*</abbr> '.__('Name:').'</label>'. 
    681      form::field('comment_author',30,255,html::escapeHTML($core->auth->getInfo('user_cn'))). 
    682      '</p>'. 
    683  
    684      '<p><label for="comment_email">'.__('Email:').'</label>'. 
    685      form::field('comment_email',30,255,html::escapeHTML($core->auth->getInfo('user_email'))). 
    686      '</p>'. 
    687  
    688      '<p><label for="comment_site">'.__('Web site:').'</label>'. 
    689      form::field('comment_site',30,255,html::escapeHTML($core->auth->getInfo('user_url'))). 
    690      '</p>'. 
    691  
    692      '<p class="area"><label for="comment_content" class="required"><abbr title="'.__('Required field').'">*</abbr> '. 
    693      __('Comment:').'</label> '. 
    694      form::textarea('comment_content',50,8,html::escapeHTML('')). 
    695      '</p>'. 
    696  
    697      '<p>'. 
    698      form::hidden('post_id',$post_id). 
    699      $core->formNonce(). 
    700      '<input type="submit" name="add" value="'.__('Save').'" /></p>'. 
    701      '</div>'. #constrained 
    702  
    703      '</form>'. 
    704      '</div>'. #add comment 
    705      '</div>'; #comments 
    706 } 
    707  
    708 if ($post_id && $post_status == 1) 
    709 { 
    710      /* Trackbacks 
    711      -------------------------------------------------------- */ 
    712  
    713      $params = array('post_id' => $post_id, 'order' => 'comment_dt ASC'); 
    714      $trackbacks = $core->blog->getComments(array_merge($params, array('comment_trackback' => 1))); 
    715  
    716      # Actions combo box 
    717      $combo_action = $comments_actions_page->getCombo(); 
    718      $has_action = !empty($combo_action) && !$trackbacks->isEmpty(); 
    719  
    720      if (!empty($_GET['tb_auto'])) { 
    721           $tb_urls = implode("\n", $TB->discover($post_excerpt_xhtml.' '.$post_content_xhtml)); 
    722      } 
    723  
    724      # Display tab 
    725      echo 
    726      '<div id="trackbacks" class="clear multi-part" title="'.__('Trackbacks').'">'; 
    727  
    728      # tracbacks actions 
    729      if ($has_action) { 
    730           echo '<form action="post.php" id="form-trackbacks" method="post">'; 
    731      } 
    732  
    733      echo '<h3>'.__('Trackbacks received').'</h3>'; 
    734  
    735      if (!$trackbacks->isEmpty()) { 
    736           showComments($trackbacks, $has_action, true); 
    737      } else { 
    738           echo '<p>'.__('No trackback').'</p>'; 
    739      } 
    740  
    741      if ($has_action) { 
    742           echo 
    743           '<div class="two-cols">'. 
    744           '<p class="col checkboxes-helpers"></p>'. 
    745  
    746           '<p class="col right"><label for="action" class="classic">'.__('Selected trackbacks action:').'</label> '. 
    747           form::combo('action', $combo_action). 
    748           form::hidden('id',$post_id). 
    749           form::hidden(array('section'),'trackbacks'). 
    750           $core->formNonce(). 
    751           '<input type="submit" value="'.__('ok').'" /></p>'. 
    752           '</div>'. 
    753           '</form>'; 
    754      } 
    755  
    756      /* Add trackbacks 
    757      -------------------------------------------------------- */ 
    758      if ($can_edit_post && $post->post_status) { 
    759           echo 
    760           '<div class="fieldset clear">'; 
    761  
    762           echo 
    763           '<h3>'.__('Ping blogs').'</h3>'. 
    764           '<form action="post.php?id='.$post_id.'" id="trackback-form" method="post">'. 
    765           '<p><label for="tb_urls" class="area">'.__('URLs to ping:').'</label>'. 
    766           form::textarea('tb_urls', 60, 5, $tb_urls). 
    767           '</p>'. 
    768  
    769           '<p><label for="tb_excerpt" class="area">'.__('Excerpt to send:').'</label>'. 
    770           form::textarea('tb_excerpt', 60, 5, $tb_excerpt).'</p>'. 
    771  
    772           '<p>'. 
    773           $core->formNonce(). 
    774           '<input type="submit" name="ping" value="'.__('Ping blogs').'" />'. 
    775           (empty($_GET['tb_auto']) ? 
    776                '&nbsp;&nbsp;<a class="button" href="'. 
    777                'post.php?id='.$post_id.'&amp;tb_auto=1&amp;tb=1'. 
    778                '">'.__('Auto discover ping URLs').'</a>' 
    779           : ''). 
    780           '</p>'. 
    781           '</form>'; 
    782  
    783           $pings = $TB->getPostPings($post_id); 
    784  
    785           if (!$pings->isEmpty()) 
    786           { 
    787                echo '<h3>'.__('Previously sent pings').'</h3>'; 
    788  
    789                echo '<ul class="nice">'; 
    790                while ($pings->fetch()) { 
    791                     echo 
    792                     '<li>'.dt::dt2str(__('%Y-%m-%d %H:%M'), $pings->ping_dt).' - '. 
    793                     $pings->ping_url.'</li>'; 
    794                } 
    795                echo '</ul>'; 
    796           } 
    797  
    798           echo '</div>'; 
    799      } 
    800  
    801      echo '</div>'; #trackbacks 
    802 } 
    803  
    804 # Controls comments or trakbacks capabilities 
    805 function isContributionAllowed($id,$dt,$com=true) 
    806 { 
    807      global $core; 
    808  
    809      if (!$id) { 
    810           return true; 
    811      } 
    812      if ($com) { 
    813           if (($core->blog->settings->system->comments_ttl == 0) || 
    814                (time() - $core->blog->settings->system->comments_ttl*86400 < $dt)) { 
    815                return true; 
    816           } 
    817      } else { 
    818           if (($core->blog->settings->system->trackbacks_ttl == 0) || 
    819                (time() - $core->blog->settings->system->trackbacks_ttl*86400 < $dt)) { 
    820                return true; 
    821           } 
    822      } 
    823      return false; 
    824 } 
    825  
    826 # Show comments or trackbacks 
    827 function showComments($rs,$has_action,$tb=false) 
    828 { 
    829      echo 
    830      '<div class="table-outer">'. 
    831      '<table class="comments-list"><tr>'. 
    832      '<th colspan="2" class="first">'.__('Author').'</th>'. 
    833      '<th>'.__('Date').'</th>'. 
    834      '<th class="nowrap">'.__('IP address').'</th>'. 
    835      '<th>'.__('Status').'</th>'. 
    836      '<th>'.__('Edit').'</th>'. 
    837      '</tr>'; 
    838      $comments = array(); 
    839      if (isset($_REQUEST['comments'])) { 
    840           foreach ($_REQUEST['comments'] as $v) { 
    841                $comments[(integer)$v]=true; 
    842           } 
    843      } 
    844  
    845      while($rs->fetch()) 
    846      { 
    847           $comment_url = 'comment.php?id='.$rs->comment_id; 
    848  
    849           $img = '<img alt="%1$s" title="%1$s" src="images/%2$s" />'; 
    850           switch ($rs->comment_status) { 
    851                case 1: 
    852                     $img_status = sprintf($img,__('Published'),'check-on.png'); 
    853                     break; 
    854                case 0: 
    855                     $img_status = sprintf($img,__('Unpublished'),'check-off.png'); 
    856                     break; 
    857                case -1: 
    858                     $img_status = sprintf($img,__('Pending'),'check-wrn.png'); 
    859                     break; 
    860                case -2: 
    861                     $img_status = sprintf($img,__('Junk'),'junk.png'); 
    862                     break; 
    863           } 
    864  
    865           echo 
    866           '<tr class="line'.($rs->comment_status != 1 ? ' offline' : '').'"'. 
    867           ' id="c'.$rs->comment_id.'">'. 
    868  
    869           '<td class="nowrap">'. 
    870           ($has_action ? form::checkbox(array('comments[]'),$rs->comment_id,isset($comments[$rs->comment_id]),'','',0,'title="'.($tb ? __('select this trackback') : __('select this comment')).'"') : '').'</td>'. 
    871           '<td class="maximal">'.html::escapeHTML($rs->comment_author).'</td>'. 
    872           '<td class="nowrap">'.dt::dt2str(__('%Y-%m-%d %H:%M'),$rs->comment_dt).'</td>'. 
    873           '<td class="nowrap"><a href="comments.php?ip='.$rs->comment_ip.'">'.$rs->comment_ip.'</a></td>'. 
    874           '<td class="nowrap status">'.$img_status.'</td>'. 
    875           '<td class="nowrap status"><a href="'.$comment_url.'">'. 
    876           '<img src="images/edit-mini.png" alt="" title="'.__('Edit this comment').'" /> '.__('Edit').'</a></td>'. 
    877  
    878           '</tr>'; 
    879      } 
    880  
    881      echo '</table></div>'; 
    882 } 
    883  
    884 dcPage::helpBlock('core_post','core_trackbacks','core_wiki'); 
    885 dcPage::close(); 
     393     $_ctx->setAlert(__('Comment has been successfully created.')); 
     394}     
     395      
     396$core->tpl->display('post.html.twig'); 
     397?> 
  • admin/posts.php

    r2566 r2593  
    44# This file is part of Dotclear 2. 
    55# 
    6 # Copyright (c) 2003-2013 Olivier Meunier & Association Dotclear 
     6# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear 
    77# Licensed under the GPL version 2.0 license. 
    88# See LICENSE file or 
     
    1212 
    1313require dirname(__FILE__).'/../inc/admin/prepend.php'; 
    14  
     14global $_ctx; 
    1515dcPage::check('usage,contentadmin'); 
    1616 
     
    4747{ 
    4848     # Filter form we'll put in html_block 
    49      $users_combo = array_merge( 
    50           array('-' => ''), 
    51           dcAdminCombos::getUsersCombo($users) 
     49     $users_combo = $categories_combo = array(); 
     50     while ($users->fetch()) 
     51     { 
     52          $user_cn = dcUtils::getUserCN($users->user_id,$users->user_name, 
     53          $users->user_firstname,$users->user_displayname); 
     54           
     55          if ($user_cn != $users->user_id) { 
     56               $user_cn .= ' ('.$users->user_id.')'; 
     57          } 
     58           
     59          $users_combo[$user_cn] = $users->user_id;  
     60     } 
     61      
     62 
     63# Getting categories 
     64$categories_combo = array(); 
     65try { 
     66     $categories = $core->blog->getCategories(array('post_type'=>'post')); 
     67     while ($categories->fetch()) { 
     68          $categories_combo[$categories->cat_id] =  
     69               str_repeat('&nbsp;&nbsp;',$categories->level-1). 
     70               ($categories->level-1 == 0 ? '' : '&bull; '). 
     71               html::escapeHTML($categories->cat_title); 
     72     } 
     73} catch (Exception $e) { } 
     74     $status_combo = array( 
    5275     ); 
     76     foreach ($core->blog->getAllPostStatus() as $k => $v) { 
     77          $status_combo[(string) $k] = (string)$v; 
     78     } 
     79      
     80     $selected_combo = array( 
     81     '1' => __('is selected'), 
     82     '0' => __('is not selected') 
     83     ); 
     84      
     85     # Months array 
     86     while ($dates->fetch()) { 
     87          $dt_m_combo[$dates->year().$dates->month()] = dt::str('%B %Y',$dates->ts()); 
     88     } 
     89      
     90     while ($langs->fetch()) { 
     91          $lang_combo[$langs->post_lang] = $langs->post_lang; 
     92     } 
     93} 
     94$form = new dcForm($core,'post','post.php'); 
    5395 
    54      $categories_combo = array_merge( 
    55           array( 
    56                new formSelectOption('-',''), 
    57                new formSelectOption(__('(No cat)'),'NULL')), 
    58           dcAdminCombos::getCategoriesCombo($categories,false) 
     96 
     97# Actions combo box 
     98$combo_action = array(); 
     99if ($core->auth->check('publish,contentadmin',$core->blog->id)) 
     100{ 
     101     $combo_action[__('Status')] = array( 
     102          __('Publish') => 'publish', 
     103          __('Unpublish') => 'unpublish', 
     104          __('Schedule') => 'schedule', 
     105          __('Mark as pending') => 'pending' 
    59106     ); 
    60      $categories_values = array(); 
    61      foreach ($categories_combo as $cat) { 
    62           if (isset($cat->value)) { 
    63                $categories_values[$cat->value]=true; 
    64           } 
     107} 
     108$combo_action[__('Mark')] = array( 
     109     __('Mark as selected') => 'selected', 
     110     __('Mark as unselected') => 'unselected' 
     111); 
     112$combo_action[__('Change')] = array( 
     113     __('Change category') => 'category', 
     114     __('Change language') => 'lang'); 
     115if ($core->auth->check('admin',$core->blog->id)) 
     116{ 
     117     $combo_action[__('Change')] = array_merge($combo_action[__('Change')], 
     118          array(__('Change author') => 'author')); 
     119} 
     120if ($core->auth->check('delete,contentadmin',$core->blog->id)) 
     121{ 
     122     $combo_action[__('Delete')] = array(__('Delete') => 'delete'); 
     123} 
     124 
     125# --BEHAVIOR-- adminPostsActionsCombo 
     126$core->callBehavior('adminPostsActionsCombo',array(&$combo_action)); 
     127 
     128 
     129 
     130class monthdcFilterCombo extends dcFilterCombo { 
     131     public function applyFilter($params) { 
     132          $month=$this->avalues['values'][0]; 
     133          $params['post_month'] = substr($month,4,2); 
     134          $params['post_year'] = substr($month,0,4); 
     135     } 
     136} 
     137 
     138class PostsFetcher extends dcListFetcher { 
     139 
     140     public function getEntries($params,$offset,$limit) { 
     141          $params['limit'] = array($offset,$limit); 
     142          return $this->core->blog->getPosts($params); 
    65143     } 
    66144 
    67      $status_combo = array_merge( 
    68           array('-' => ''), 
    69           dcAdminCombos::getPostStatusesCombo() 
    70      ); 
    71  
    72      $selected_combo = array( 
    73      '-' => '', 
    74      __('Selected') => '1', 
    75      __('Not selected') => '0' 
    76      ); 
    77  
    78      $attachment_combo = array( 
    79      '-' => '', 
    80      __('With attachments') => '1', 
    81      __('Without attachments') => '0' 
    82      ); 
    83  
    84      # Months array 
    85      $dt_m_combo = array_merge( 
    86           array('-' => ''), 
    87           dcAdminCombos::getDatesCombo($dates) 
    88      ); 
    89  
    90      $lang_combo = array_merge( 
    91           array('-' => ''), 
    92           dcAdminCombos::getLangsCombo($langs,false) 
    93      ); 
    94  
    95      $sortby_combo = array( 
    96      __('Date') => 'post_dt', 
    97      __('Title') => 'post_title', 
    98      __('Category') => 'cat_title', 
    99      __('Author') => 'user_id', 
    100      __('Status') => 'post_status', 
    101      __('Selected') => 'post_selected', 
    102      __('Number of comments') => 'nb_comment', 
    103      __('Number of trackbacks') => 'nb_trackback' 
    104      ); 
    105  
    106      $order_combo = array( 
    107      __('Descending') => 'desc', 
    108      __('Ascending') => 'asc' 
    109      ); 
    110 } 
    111  
    112 # Actions combo box 
    113  
    114 $posts_actions_page = new dcPostsActionsPage($core,'posts.php'); 
    115  
    116 if ($posts_actions_page->process()) { 
    117      return; 
    118 } 
    119  
    120 /* Get posts 
    121 -------------------------------------------------------- */ 
    122 $user_id = !empty($_GET['user_id']) ?   $_GET['user_id'] : ''; 
    123 $cat_id = !empty($_GET['cat_id']) ?     $_GET['cat_id'] : ''; 
    124 $status = isset($_GET['status']) ? $_GET['status'] : ''; 
    125 $selected = isset($_GET['selected']) ?  $_GET['selected'] : ''; 
    126 $attachment = isset($_GET['attachment']) ?   $_GET['attachment'] : ''; 
    127 $month = !empty($_GET['month']) ?       $_GET['month'] : ''; 
    128 $lang = !empty($_GET['lang']) ?         $_GET['lang'] : ''; 
    129 $sortby = !empty($_GET['sortby']) ?     $_GET['sortby'] : 'post_dt'; 
    130 $order = !empty($_GET['order']) ?       $_GET['order'] : 'desc'; 
    131  
    132 $show_filters = false; 
    133  
    134 $page = !empty($_GET['page']) ? max(1,(integer) $_GET['page']) : 1; 
    135 $nb_per_page =  30; 
    136  
    137 if (!empty($_GET['nb']) && (integer) $_GET['nb'] > 0) { 
    138      if ($nb_per_page != $_GET['nb']) { 
    139           $show_filters = true; 
     145     public function getEntriesCount($params) { 
     146          $count = $this->core->blog->getPosts($params,true); 
     147          return $count->f(0); 
    140148     } 
    141      $nb_per_page = (integer) $_GET['nb']; 
    142 } 
    143  
    144 $params['limit'] = array((($page-1)*$nb_per_page),$nb_per_page); 
    145 $params['no_content'] = true; 
    146  
    147 # - User filter 
    148 if ($user_id !== '' && in_array($user_id,$users_combo)) { 
    149      $params['user_id'] = $user_id; 
    150      $show_filters = true; 
    151 } else { 
    152      $user_id=''; 
    153 } 
    154  
    155 # - Categories filter 
    156 if ($cat_id !== '' && isset($categories_values[$cat_id])) { 
    157      $params['cat_id'] = $cat_id; 
    158      $show_filters = true; 
    159 } else { 
    160      $cat_id=''; 
    161 } 
    162  
    163 # - Status filter 
    164 if ($status !== '' && in_array($status,$status_combo)) { 
    165      $params['post_status'] = $status; 
    166      $show_filters = true; 
    167 } else { 
    168      $status=''; 
    169 } 
    170  
    171 # - Selected filter 
    172 if ($selected !== '' && in_array($selected,$selected_combo)) { 
    173      $params['post_selected'] = $selected; 
    174      $show_filters = true; 
    175 } else { 
    176      $selected=''; 
    177 } 
    178  
    179 # - Selected filter 
    180 if ($attachment !== '' && in_array($attachment,$attachment_combo)) { 
    181      $params['media'] = $attachment; 
    182      $params['link_type'] = 'attachment'; 
    183      $show_filters = true; 
    184 } else { 
    185      $attachment=''; 
    186 } 
    187  
    188 # - Month filter 
    189 if ($month !== '' && in_array($month,$dt_m_combo)) { 
    190      $params['post_month'] = substr($month,4,2); 
    191      $params['post_year'] = substr($month,0,4); 
    192      $show_filters = true; 
    193 } else { 
    194      $month=''; 
    195 } 
    196  
    197 # - Lang filter 
    198 if ($lang !== '' && in_array($lang,$lang_combo)) { 
    199      $params['post_lang'] = $lang; 
    200      $show_filters = true; 
    201 } else { 
    202      $lang=''; 
    203 } 
    204  
    205 # - Sortby and order filter 
    206 if ($sortby !== '' && in_array($sortby,$sortby_combo)) { 
    207      if ($order !== '' && in_array($order,$order_combo)) { 
    208           $params['order'] = $sortby.' '.$order; 
    209      } else { 
    210           $order='desc'; 
    211      } 
    212  
    213      if ($sortby != 'post_dt' || $order != 'desc') { 
    214           $show_filters = true; 
    215      } 
    216 } else { 
    217      $sortby='post_dt'; 
    218      $order='desc'; 
    219 } 
    220  
    221 # Get posts 
    222 try { 
    223      $posts = $core->blog->getPosts($params); 
    224      $counter = $core->blog->getPosts($params,true); 
    225      $post_list = new adminPostList($core,$posts,$counter->f(0)); 
    226 } catch (Exception $e) { 
    227      $core->error->add($e->getMessage()); 
    228149} 
    229150 
    230151/* DISPLAY 
    231152-------------------------------------------------------- */ 
     153$filterSet = new dcFilterSet($core,'fposts','posts.php'); 
    232154 
    233 $form_filter_title = __('Show filters and display options'); 
    234 $starting_script  = dcPage::jsLoad('js/_posts_list.js'); 
    235 $starting_script .= dcPage::jsLoad('js/filter-controls.js'); 
    236 $starting_script .= 
    237      '<script type="text/javascript">'."\n". 
    238      "//<![CDATA["."\n". 
    239      dcPage::jsVar('dotclear.msg.show_filters', $show_filters ? 'true':'false')."\n". 
    240      dcPage::jsVar('dotclear.msg.filter_posts_list',$form_filter_title)."\n". 
    241      dcPage::jsVar('dotclear.msg.cancel_the_filter',__('Cancel filters and display options'))."\n". 
    242      "//]]>". 
    243      "</script>"; 
     155$filterSet 
     156     ->addFilter(new dcFilterRichCombo( 
     157          'users',__('Author'), __('Author'), 'user_id', $users_combo,array( 
     158               'multiple' => true))) 
     159     ->addFilter(new dcFilterRichCombo( 
     160          'category',__('Category'), __('Category'), 'cat_id', $categories_combo,array( 
     161               'multiple' => true))) 
     162     ->addFilter(new dcFilterRichCombo( 
     163          'post_status',__('Status'), __('Status'), 'post_status', $status_combo)) 
     164     ->addFilter(new dcFilterRichCombo( 
     165          'lang',__('Lang'), __('Lang'), 'post_lang', $lang_combo)) 
     166     ->addFilter(new dcFilterCombo( 
     167          'selected',__('Selected'), __('The post : '),'post_selected', $selected_combo)) 
     168     ->addFilter(new monthdcFilterCombo( 
     169          'month',__('Month'),__('Month'), 'post_month', $dt_m_combo,array('singleval' => 1))) 
     170     ->addFilter(new dcFilterText( 
     171          'search',__('Contains'),__('The entry contains'), 'search',20,255)); 
    244172 
    245 dcPage::open(__('Entries'),$starting_script, 
    246      dcPage::breadcrumb( 
    247           array( 
    248                html::escapeHTML($core->blog->name) => '', 
    249                __('Entries') => '' 
    250           )) 
    251 ); 
    252 if (!empty($_GET['upd'])) { 
    253      dcPage::success(__('Selected entries have been successfully updated.')); 
    254 } elseif (!empty($_GET['del'])) { 
    255      dcPage::success(__('Selected entries have been successfully deleted.')); 
    256 } 
    257 if (!$core->error->flag()) 
    258 { 
    259      echo 
    260      '<p class="top-add"><a class="button add" href="post.php">'.__('New entry').'</a></p>'. 
    261      '<form action="posts.php" method="get" id="filters-form">'. 
    262      '<h3 class="out-of-screen-if-js">'.$form_filter_title.'</h3>'. 
    263173 
    264      '<div class="table">'. 
    265      '<div class="cell">'. 
    266      '<h4>'.__('Filters').'</h4>'. 
    267      '<p><label for="user_id" class="ib">'.__('Author:').'</label> '. 
    268      form::combo('user_id',$users_combo,$user_id).'</p>'. 
    269      '<p><label for="cat_id" class="ib">'.__('Category:').'</label> '. 
    270      form::combo('cat_id',$categories_combo,$cat_id).'</p>'. 
    271      '<p><label for="status" class="ib">'.__('Status:').'</label> ' . 
    272      form::combo('status',$status_combo,$status).'</p> '. 
    273      '</div>'. 
     174$lfetcher = new PostsFetcher($core); 
     175$lposts = new dcItemList ($core,array('lposts','form-entries'),$lfetcher,'posts_actions.php'); 
     176$lposts->setFilterSet($filterSet); 
     177$lposts->addTemplate('posts_cols.html.twig'); 
    274178 
    275      '<div class="cell filters-sibling-cell">'. 
    276      '<p><label for="selected" class="ib">'.__('Selected:').'</label> '. 
    277      form::combo('selected',$selected_combo,$selected).'</p>'. 
    278      '<p><label for="attachment" class="ib">'.__('Attachments:').'</label> '. 
    279      form::combo('attachment',$attachment_combo,$attachment).'</p>'. 
    280      '<p><label for="month" class="ib">'.__('Month:').'</label> '. 
    281      form::combo('month',$dt_m_combo,$month).'</p>'. 
    282      '<p><label for="lang" class="ib">'.__('Lang:').'</label> '. 
    283      form::combo('lang',$lang_combo,$lang).'</p> '. 
    284      '</div>'. 
     179$lposts 
     180     ->addColumn(new dcColumn('title',__('Title'),'post_title')) 
     181     ->addColumn(new dcColumn('cat',__('Category'),'cat_title')) 
     182     ->addColumn(new dcColumn('date',__('Date'),'post_date')) 
     183     ->addColumn(new dcColumn('datetime',__('Date and Time'),'post_dt')) 
     184     ->addColumn(new dcColumn('author',__('Author'),'user_id')) 
     185     ->addColumn(new dcColumn('status',__('Status'),'post_status')); 
    285186 
    286      '<div class="cell filters-options">'. 
    287      '<h4>'.__('Display options').'</h4>'. 
    288      '<p><label for="sortby" class="ib">'.__('Order by:').'</label> '. 
    289      form::combo('sortby',$sortby_combo,$sortby).'</p>'. 
    290      '<p><label for="order" class="ib">'.__('Sort:').'</label> '. 
    291      form::combo('order',$order_combo,$order).'</p>'. 
    292      '<p><span class="label ib">'.__('Show').'</span> <label for="nb" class="classic">'. 
    293      form::field('nb',3,3,$nb_per_page).' '. 
    294      __('entries per page').'</label></p>'. 
    295      '</div>'. 
    296      '</div>'. 
    297187 
    298      '<p><input type="submit" value="'.__('Apply filters and display options').'" />'. 
    299      '<br class="clear" /></p>'. //Opera sucks 
    300      '</form>'; 
     188$lposts->setup(); 
    301189 
    302      # Show posts 
    303      $post_list->display($page,$nb_per_page, 
    304      '<form action="posts.php" method="post" id="form-entries">'. 
     190$_ctx 
     191     ->setBreadCrumb(array(__('Entries') => 'posts.php')); 
    305192 
    306      '%s'. 
    307193 
    308      '<div class="two-cols">'. 
    309      '<p class="col checkboxes-helpers"></p>'. 
     194$core->tpl->display('posts.html.twig'); 
    310195 
    311      '<p class="col right"><label for="action" class="classic">'.__('Selected entries action:').'</label> '. 
    312      form::combo('action',$posts_actions_page->getCombo()). 
    313      '<input type="submit" value="'.__('ok').'" /></p>'. 
    314      form::hidden(array('user_id'),$user_id). 
    315      form::hidden(array('cat_id'),$cat_id). 
    316      form::hidden(array('status'),$status). 
    317      form::hidden(array('selected'),$selected). 
    318      form::hidden(array('attachment'),$attachment). 
    319      form::hidden(array('month'),$month). 
    320      form::hidden(array('lang'),$lang). 
    321      form::hidden(array('sortby'),$sortby). 
    322      form::hidden(array('order'),$order). 
    323      form::hidden(array('page'),$page). 
    324      form::hidden(array('nb'),$nb_per_page). 
    325      $core->formNonce(). 
    326      '</div>'. 
    327      '</form>', 
    328      $show_filters 
    329      ); 
    330 } 
    331196 
    332 dcPage::helpBlock('core_posts'); 
    333 dcPage::close(); 
     197?> 
  • admin/style/default.css

    r2468 r2593  
    442442     text-decoration: none; 
    443443     border-bottom: 1px dotted #999; 
    444      } 
    445 a:hover, a:active, a:focus { 
     444     background-color: inherit; 
     445     outline: 0; 
     446     } 
     447a:hover, a:active { 
    446448     border-bottom-style: solid; 
    447449     } 
    448450a img, a:link img, a:visited img { 
    449451     border: none; 
     452     background: inherit; 
    450453     } 
    451454h1 a:link, h1 a:visited { 
     
    455458     color: #333; 
    456459     } 
     460a:link { 
     461  transition: .5s; 
     462} 
     463a:focus, a:focus img { 
     464  outline: 2px solid #bee74b; 
     465  border-bottom: none; 
     466  text-decoration: none; 
     467} 
    457468/* ---------------------------------------------------------------------------- 
    458469                                                                                     FORMULAIRES 
    459470---------------------------------------------------------------------------- */ 
    460 input[type=text], input[type=password], input[type=submit],  
     471input[type=text], input[type=password], input[type=submit], 
    461472input[type=button], input[type=reset], a.button, button, textarea, select, legend { 
    462      border-radius: 3px;  
     473     border-radius: 3px; 
    463474     max-width: 100%; 
    464475     } 
     
    488499     margin-bottom: 0.5em; 
    489500     } 
    490 label .maximal, textarea.maximal, input.maximal { 
     501label .maximal, textarea.maximal, input.maximal, select.maximal { 
    491502     width: 99%; 
    492503     } 
     
    686697/* suppression, reset, "neutres" fond gris */ 
    687698button, input[type=button], input.button, 
    688 input[type=reset], input[type=submit].reset, input.reset,  
     699input[type=reset], input[type=submit].reset, input.reset, 
    689700input[type=submit].delete, input.delete, 
    690701 a.button, a.button.delete, a.button.reset { 
     
    699710button:hover, input[type=button]:hover, input.button:hover, 
    700711     button:focus, input[type=button]:focus, input.button:focus, 
    701      input[type=reset]:hover, input[type=submit].reset:hover, input.reset:hover,  
    702      input[type=reset]:focus, input[type=submit].reset:focus, input.reset:focus,  
     712     input[type=reset]:hover, input[type=submit].reset:hover, input.reset:hover, 
     713     input[type=reset]:focus, input[type=submit].reset:focus, input.reset:focus, 
    703714     input[type=submit].delete:hover, input.delete:hover, 
    704715     input[type=submit].delete:focus, input.delete:focus, 
     
    930941     color: #fff; 
    931942     background: transparent url(dc_logos/b-dotclear120.png) no-repeat 0 6px; 
     943     transition: none; 
    932944     } 
    933945h1 a:hover, h1 a:focus { 
    934946     background-position: 0 -94px; 
     947     background-color: transparent; 
     948     transition: none; 
    935949     } 
    936950/* top-info-blog */ 
     
    12771291     padding-right: 1.5em; 
    12781292     } 
    1279 th.first img { 
     1293th.first input { 
    12801294     padding-right: 34px; 
    12811295     } 
     
    14231437     background: #fff; 
    14241438     margin-bottom: 0; 
     1439     margin-top: 1em; 
    14251440     } 
    14261441#login-screen input[type=text], #login-screen input[type=password], #login-screen input[type=submit], 
     
    14851500#icons a:focus img, #icons a:hover img { 
    14861501     background: #bee74b; 
    1487      } 
    1488 #icons a:focus span, #icons a:hover span { 
     1502     outline: 0; 
     1503     border-color: #dadada; 
     1504     } 
     1505#icons a:focus { 
     1506     outline: 0; 
     1507     border-color: #fff; 
     1508     } 
     1509#icons a:hover span, #icons a:focus span { 
    14891510     border-bottom-style: solid; 
     1511     } 
     1512#icons a:focus span { 
     1513     border: 2px solid #bee74b; 
    14901514     } 
    14911515/* billet rapide */ 
     
    16111635/* ------------------------------------------------------------------- blog_theme.php */ 
    16121636/* pour les alignements verticaux */ 
    1613 #theme-new, #theme-activate, #theme-deactivate { 
     1637#theme-new, #theme-activate, #theme-deactivate, #theme-update { 
    16141638     margin-left: -10px; 
    16151639     margin-right: -10px; 
     
    16241648     background: #ecf0f1 url(texture.png); 
    16251649     } 
    1626 .module-name { 
     1650.module-name, .module-name label { 
    16271651     margin-bottom: .5em; 
     1652     color: #676e78; 
    16281653     } 
    16291654.module-sshot { 
     
    16621687     margin-bottom: 1em; 
    16631688     } 
     1689.module-name input[type="checkbox"] { 
     1690     margin-bottom: 0; 
     1691     } 
    16641692/** 
    16651693Les screenshots des thèmes ont deux tailles possibles : 
    16661694- dans Ajouter des thèmes : 240px (+ 10 padding image + 20 padding boîte + 6 bordure + 2 ombrage = 278) 
    16671695- dans Thèmes installés : 280px (+ 10 padding-image + 20 padding-boîte + 2 ombrage = 318) 
    1668 On adapte largeur et hauteur en fonction  
     1696On adapte largeur et hauteur en fonction 
    16691697*/ 
    1670 #theme-new .box.theme { /* Ajouter un thème */ 
     1698#theme-new .box.theme, #theme-update .box.theme { /* Ajouter un thème */ 
    16711699     width: 278px; 
    16721700     min-height: 275px; 
     
    19091937     } 
    19101938/* upload multiple */ 
    1911 .enhanced_uploader .choose_files, .enhanced_uploader .cancel,  
     1939.enhanced_uploader .choose_files, .enhanced_uploader .cancel, 
    19121940.enhanced_uploader .clean, .enhanced_uploader .start { 
    19131941     margin-right: .4em; 
     
    20712099     } 
    20722100.modules a.module-config { 
    2073      /* todo: add icon here */ 
    2074      padding: 4px 4px 0 20px; 
     2101     background: transparent url(settings.png) no-repeat 2px 6px; 
     2102     padding: 4px 4px 0 18px; 
    20752103     } 
    20762104#m_search { 
     
    21022130.mod-more { 
    21032131     padding-top: .5em; 
     2132     } 
     2133#plugin-update td { 
     2134     vertical-align: baseline; 
    21042135     } 
    21052136/* ---------------------------------------------------------- post.php, page.php */ 
     
    23392370     } 
    23402371.nav_prevnext a, a.back { 
     2372     color: #2373A8; 
    23412373     border: 1px solid #dfdfdf; 
    23422374     padding: 2px 1.5em; 
     
    25672599     border-color: #ffd478; 
    25682600     } 
    2569 /* ---------------------------------------------- Couleurs ajoutées via javascript    
     2601/* ---------------------------------------------- Couleurs ajoutées via javascript 
    25702602/* color-picker.js */ 
    2571 .color-color-picker {  
     2603.color-color-picker { 
    25722604     border: 1px solid #000; 
    2573      width: 195px;  
    2574      background: #fff;  
     2605     width: 195px; 
     2606     background: #fff; 
    25752607     } 
    25762608/* _media_item.js */ 
    2577 .color-div {  
     2609.color-div { 
    25782610     border: 1px solid #ccc; 
    25792611     } 
    25802612/* fadings ('color' est utilisé comme variable, pas comme text color) */ 
    2581 .colorBeginPassword,  
    2582 .colorBeginValidatorErr,  
     2613.colorBeginPassword, 
     2614.colorBeginValidatorErr, 
    25832615.colorBeginUserMail           { color: #fff; } 
    2584 .colorEndPassword,  
    2585 .colorEndError,  
    2586 .colorEndValidatorErr,  
     2616.colorEndPassword, 
     2617.colorEndError, 
     2618.colorEndValidatorErr, 
    25872619.colorEndUserMail             { color: #ffbaba; } 
    25882620.colorBeginMessage            { color: #ccc; } 
    2589 .colorEndMessage,  
     2621.colorEndMessage, 
    25902622.colorBeginValidatorMsg  { color: #676e78; } 
    25912623.colorBeginError              { color: #fefacd; } 
     
    25962628                                                                           UN POIL DE MEDIA QUERIES 
    25972629------------------------------------------------------------------------------------ */ 
    2598 @media screen and (min-width: 117em) { 
    2599 body { 
    2600      border: 1px solid #ccc; 
    2601      border-top-width: 0; 
    2602      } 
    2603 } 
    26042630@media screen and (min-width: 80em) { 
    2605 html { 
    2606      background: #fff; 
    2607      } 
    2608 body { 
    2609      max-width: 140em; 
    2610      margin: 0 auto; 
    2611      } 
    26122631#wrapper { 
    26132632     background: #F7F7F7 url(bg_wrapper.png) repeat-y 18em; 
     
    27692788     vertical-align: bottom; 
    27702789     } 
     2790.pseudo-tabs li { 
     2791     display: block; 
     2792     float: left; 
     2793     width: 50%; 
     2794     border-top: 1px solid #ddd; 
     2795     padding: .25em; 
     2796     } 
     2797.pseudo-tabs li:first-child, .pseudo-tabs li:nth-of-type(2) { 
     2798     border-top: none; 
     2799     } 
    27712800} 
    27722801@media screen and (max-width: 26.5em) { 
     
    28372866     padding: 0.3em 1em 0.3em 0; 
    28382867     } 
     2868.pseudo-tabs li { 
     2869     display: block; 
     2870     width: 100%; 
     2871     float: none; 
     2872     border-top: 1px solid #ddd !important; 
     2873     } 
     2874.pseudo-tabs li:first-child { 
     2875     border-top: none; 
     2876     } 
    28392877} 
Note: See TracChangeset for help on using the changeset viewer.

Sites map