Changeset 1440

Show
Ignore:
Timestamp:
03/07/08 02:00:16 (16 months ago)
Author:
freakerz
Message:

Merging r1439.

There are no changes yet in this branch as we made the merge into trunk early on.

This branch will be used to work Atom and APP validation/separation.

/me pokes michaeltwofish

Location:
branches/111307-atom
Files:
1 removed
78 modified
1 copied

Legend:

Unmodified
Added
Removed
  • branches/111307-atom/doc/manual/index.html

    r1291 r1440  
    734734        { 
    735735                if ( $plugin_id == $this->plugin_id() ) { 
    736                         $actions[] = _('Configure'); 
     736                        $actions[] = _t('Configure'); 
    737737                } 
    738738                return $actions; 
    739739        }</pre> 
    740 The _() function translates the string into the language used by the site.  For English-language blogs, the output would be "Configure", while for Spanish-language blogs, for example, the output might be "Configurar". 
     740The _t() function translates the string into the language used by the site.  For English-language blogs, the output would be "Configure", while for Spanish-language blogs, for example, the output might be "Configurar". 
     741The _e() function echoes a translated string for display. 
    741742<pre>public function action_plugin_ui( $plugin_id, $action ) 
    742743        { 
    743744                if ( $plugin_id == $this->plugin_id() ) { 
    744745                        switch ( $action ) { 
    745                                 case _('Configure') : 
     746                                case _t('Configure') : 
    746747                                        $ui = new FormUI( strtolower( get_class( $this ) ) ); 
    747                                         $customvalue= $ui->add( 'text', 'customvalue', _('Your custom value:') ); 
     748                                        $customvalue= $ui->add( 'text', 'customvalue', _t('Your custom value:') ); 
    748749                                        $ui->on_success( array( $this, 'updated_config' ) ); 
    749750                                        $ui->out(); 
  • branches/111307-atom/index.php

    r1291 r1440  
    2323 * The path to the root of this Habari installation. 
    2424 */ 
    25 define( 'HABARI_PATH', dirname( __FILE__ ) ); 
     25if( ! defined( 'HABARI_PATH' ) ) { 
     26    define( 'HABARI_PATH', dirname( __FILE__ ) ); 
     27} 
    2628 
    2729// We start up output buffering in order to take advantage of output compression, 
     
    153155} 
    154156 
     157// If we're doing unit testing, stop here 
     158if( defined( 'UNIT_TEST' ) ) { 
     159    return; 
     160} 
     161 
    155162// Send the Content-Type HTTP header. 
    156163// @todo Find a better place to put this. 
     
    188195// Flush (send) the output buffer. 
    189196ob_flush(); 
     197 
    190198?> 
  • branches/111307-atom/system/admin/admin.js

    r1291 r1440  
    33        $(this).hover( 
    44            function() { $(this).addClass(c);  }, 
    5             function() { $(this).removeClass(c); } 
     5            function() { $(this).removeClass(c); $('.menu-list').hide();} 
    66        ); 
    77    }); 
    88}; 
     9 
     10$.fn.resizeable = function(){ 
     11 
     12    this.each(function() { 
     13        var textarea = $(this); 
     14        var offset = null; 
     15        var grip = $('<div class="grip"></div>').mousedown(function(ev){ 
     16            offset = textarea.height() - (ev.clientY + document.documentElement.scrollTop) 
     17            $(document).mousemove(doDrag).mouseup(endDrag); 
     18        }).mouseup(endDrag); 
     19        var resizer = $('<div class="resizer"></div>').css('margin-bottom',$(this).css('margin-bottom')); 
     20        $(this).css('margin-bottom', '0px').wrap(resizer).parent().append(grip); 
     21 
     22        function doDrag(ev){ 
     23            textarea.height(Math.max(offset + ev.clientY + document.documentElement.scrollTop, 60) + 'px'); 
     24            return false; 
     25        } 
     26 
     27        function endDrag(ev){ 
     28            $(document).unbind('mousemove', doDrag).unbind('mouseup', endDrag); 
     29            textarea.css('opacity', 1.0); 
     30        } 
     31 
     32    }); 
     33} 
     34 
    935 
    1036String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); } 
     
    1945    }); 
    2046 
    21     $("#menu .menu-item").hover( 
     47    $("#oldmenu .menu-item").hover( 
    2248        function(){ $("ul", this).fadeIn("fast"); }, 
    2349        function() { } 
     
    2551 
    2652    if (document.all) { 
    27         $("#menu .menu-item").hoverClass("sfHover"); 
     53        $("#oldmenu .menu-item").hoverClass("iehover"); 
    2854    } 
    2955 
     
    6692    }); 
    6793 
    68     /* Resizable Textareas */ 
    69     $('textarea.resizable').each(function() { 
    70         var textarea = $(this); 
    71         var offset = null; 
    72         var grip = $('<div class="grip"></div>').mousedown(function(ev){ 
    73             offset = textarea.height() - (ev.clientY + document.documentElement.scrollTop) 
    74             $(document).mousemove(doDrag).mouseup(endDrag); 
    75         }).mouseup(endDrag); 
    76         var resizer = $('<div class="resizer"></div>').css('margin-bottom',$(this).css('margin-bottom')); 
    77         $(this).css('margin-bottom', '0px').wrap(resizer).parent().append(grip); 
    78  
    79         function doDrag(ev){ 
    80             textarea.height(Math.max(offset + ev.clientY + document.documentElement.scrollTop, 60) + 'px'); 
    81             return false; 
    82         } 
    83  
    84         function endDrag(ev){ 
    85             $(document).unbind('mousemove', doDrag).unbind('mouseup', endDrag); 
    86             textarea.css('opacity', 1.0); 
    87         } 
    88  
    89     }); 
     94    /* Make Textareas Resizable */ 
     95    $('.resizable').resizeable(); 
    9096 
    9197    /* Tabs, using jQuery UI Tabs */ 
     
    164170habari.editor = { 
    165171    insertSelection: function(value) { 
     172        if($('#content').filter('.islabeled').size() > 0) { 
     173            $('#content').filter('.islabeled') 
     174                .removeClass('islabeled') 
     175                .val(value); 
     176        } 
     177        else { 
     178            var contentel = $('#content')[0]; 
     179            if('selectionStart' in contentel) { 
     180                var content = $('#content').val(); 
     181                $('#content').val(content.substr(0, contentel.selectionStart) + value + contentel.value.substr(contentel.selectionEnd, content.length)); 
     182            } 
     183            else if(document.selection) { 
     184                contentel.focus(); 
     185                document.selection.createRange().text = value; 
     186            } 
     187            else { 
     188                $('#content').filter('.islabeled') 
     189                    .removeClass('islabeled') 
     190                    .val(value); 
     191            } 
     192        } 
     193    }, 
     194    getContents: function() { 
     195        return $('#content').val(); 
     196    }, 
     197    setContents: function(contents) { 
    166198        $('#content').filter('.islabeled') 
    167199            .val('') 
    168200            .removeClass('islabeled'); 
    169         $("#content").val($("#content").val() + value); 
     201        $('#content').val(contents) 
     202    }, 
     203    getSelection: function(contents) { 
     204        if($('#content').filter('.islabeled').size() > 0) { 
     205            return ''; 
     206        } 
     207        else { 
     208            var contentel = $('#content')[0]; 
     209            if('selectionStart' in contentel) { 
     210                return $('#content').val().substr(contentel.selectionStart, contentel.selectionEnd - contentel.selectionStart); 
     211            } 
     212            else if(document.selection) { 
     213                contentel.focus(); 
     214                var range = document.selection.createRange(); 
     215                if (range == null) { 
     216                    return ''; 
     217                } 
     218                return range.text; 
     219            } 
     220            else { 
     221                return $("#content").val(); 
     222            } 
     223        } 
    170224    } 
    171225}; 
  • branches/111307-atom/system/admin/css/admin.css

    r1291 r1440  
    9696    width: 105px; 
    9797    padding: 0 0 0 15px; 
    98     background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAGlJREFUeNpinD59+mcGBgYeBtzgCxOQ6GPAD/pgit7hUPAOpugjHtNA4h+ZoJyJQPwCTcELqDgDTNEXIO5AU9QBFYcrAoHpQPwUyn4K5TOgK/oFxE1A/AhK/4JJsKBZsQCqaB+yIECAAQB0mBnahYs+3AAAAABJRU5ErkJggg==) 100px center no-repeat; /* png is dropdown arrow */ 
     98    /* background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAGlJREFUeNpinD59+mcGBgYeBtzgCxOQ6GPAD/pgit7hUPAOpugjHtNA4h+ZoJyJQPwCTcELqDgDTNEXIO5AU9QBFYcrAoHpQPwUyn4K5TOgK/oFxE1A/AhK/4JJsKBZsQCqaB+yIECAAQB0mBnahYs+3AAAAABJRU5ErkJggg==) 100px center no-repeat; /* png is dropdown arrow */ 
     99    background: url(../images/bar-back-drop.png) 100px center no-repeat; 
    99100    } 
    100101 
     
    110111    } 
    111112 
    112 #oldmenu li.menu-item:hover ul { 
     113#oldmenu li.menu-item:hover ul, #oldmenu li.menu-item.iehover ul { 
    113114    top: 22px; 
    114115    } 
     
    123124    } 
    124125 
    125 #oldmenu li.menu-item:hover .menu-list a:hover { 
     126#oldmenu li.menu-item:hover .menu-list a:hover, #oldmenu li.menu-item.iehover .menu-list a:hover { 
    126127    color: white; 
    127128    background: #333; 
    128129    } 
    129  
    130  
    131  
    132 /* The NEW HOTNESS Menu */ 
    133  
    134 #menu { 
    135     position: fixed; 
    136     top: 0; 
    137     height: 32px; 
    138     padding: 0 0px; 
    139     width: 100%; 
    140     font-size: 1.2em; 
    141     background: #242424 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAICAIAAAC3eAIWAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABhJREFUeNpikpOTY2JgYABjRkZGdAwQYAAMYgB6RRurTwAAAABJRU5ErkJggg==) repeat-x top; /* Top dropshadow */ 
    142     } 
    143  
    144 #menu li { 
    145     display: inline; 
    146     } 
    147  
    148 #menu li#site-name { 
    149     float: right; 
    150     margin-right: 10px; 
    151     } 
    152  
    153 #menu li#site-name a { 
    154     padding: 0 20px 0 20px; 
    155     border: none; 
    156     } 
    157  
    158 #menu > li > a { 
    159     font-family: 'HelveticaNeue-Light', 'Helvetica Neue', Helvetica, Arial, Sans-Serif; 
    160     } 
    161  
    162 #menu li a { 
    163     color: white; 
    164     line-height: 32px; 
    165     text-decoration:none; 
    166     display: block; 
    167     } 
    168  
    169 #menu li.menu-item:hover a, #menu li#site-name a:hover { 
    170     background-color: #424242; 
    171     } 
    172  
    173 #menu > .menu-item { 
    174     float: left; 
    175     } 
    176  
    177 #menu #contentmenu { 
    178     border-left: 1px solid #131313; 
    179     margin-left: 10px; 
    180     } 
    181  
    182 #menu #adminmenu { 
    183     border-left: 1px solid #131313; 
    184     border-right: 1px solid #131313; 
    185     } 
    186  
    187 #menu > .menu-item > a { 
    188     width: 105px; 
    189     padding: 0 0 0 15px; 
    190     background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAGlJREFUeNpinD59+mcGBgYeBtzgCxOQ6GPAD/pgit7hUPAOpugjHtNA4h+ZoJyJQPwCTcELqDgDTNEXIO5AU9QBFYcrAoHpQPwUyn4K5TOgK/oFxE1A/AhK/4JJsKBZsQCqaB+yIECAAQB0mBnahYs+3AAAAABJRU5ErkJggg==) 100px center no-repeat; /* png is dropdown arrow */ 
    191     } 
    192  
    193 #menu li.menu-item > ul { 
    194     position: absolute; 
    195     top: -10000px; 
    196     min-width: 120px; 
    197     max-width: 250px; 
    198     margin: 10px 0 0 -1px; 
    199     } 
    200  
    201 .menu-list { 
    202     background: #e1e1e1; 
    203     border: 1px solid #b0b0b0; 
    204     border-top: none; 
    205     padding: 5px 0; 
    206     } 
    207  
    208 #menu li.menu-item:hover ul { 
    209     top: 22px; 
    210     } 
    211  
    212 #menu li.menu-item .menu-list a { 
    213     width: auto; 
    214     font-size: .8em; 
    215     line-height: 1.6em; 
    216     color: #333; 
    217     padding: 3px 15px; 
    218     background: none; 
    219     } 
    220  
    221 #menu .submenuitems { 
    222     margin: 0; 
    223     } 
    224  
    225 #menu .submenuitems a { 
    226     font-size: .75em !important; 
    227     padding-left: 25px !important; 
    228     color: #777 !important; 
    229     } 
    230  
    231 #menu .menu-list li { 
    232     display: block; 
    233     } 
    234  
    235 #menu #createpagelink { 
    236     padding-bottom: 5px; 
    237     border-bottom: 1px solid #bbb; 
    238     } 
    239  
    240 #menu #managecontentlink { 
    241     padding-top: 5px; 
    242     } 
    243  
    244 #menu li.menu-item:hover .menu-list a:hover { 
    245     color: white !important; 
    246     background: #333; 
    247     } 
    248  
    249  
    250130 
    251131/* Page Splitter Tabs */ 
     
    464344/* BluePrint Overrides */ 
    465345 
    466 #plugin_options { 
    467     background: #3A3A3A; 
     346#plugin_options, #theme_options { 
     347    background: #333333 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAVCAYAAACHUoQEAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEBJREFUeNpiYGBgSGICEowg4i+I+AMnfoGI33ACzP0FxAxmIMIARGiBCBUQIQciJEGECIjgAxFcIIINRDADBBgAlsIJb8O3yoQAAAAASUVORK5CYII=) top repeat-x; /* Drop shadow */ 
    468348    border-top: 1px solid #C0C0C0; 
    469349    border-bottom: 1px solid #C0C0C0; 
     
    473353} 
    474354 
    475 #plugin_options h2 { 
     355#plugin_options h2, #theme_options h2 { 
    476356    color: white; 
    477357} 
  • branches/111307-atom/system/admin/dashboard.php

    r1291 r1440  
    207207  </div> 
    208208  <hr> 
    209   <div class="column prepend-7 span-16 first"> 
     209  <div class="column prepend-8 span-15 first"> 
    210210    <h3>Drafts (<a href="<?php URL::out( 'admin', 'page=content' ); ?>#drafts" title="View Your Drafts">more</a> &raquo;)</h3> 
    211211    <?php 
  • branches/111307-atom/system/admin/groups.php

    r1291 r1440  
    1515<ul> 
    1616<?php 
    17 foreach ( $groups as $id => $name ) 
    18 { 
    19         echo '<li>'; 
    20         echo '<form method="post" action=""><input type="hidden" name="group" value="' . $id . '"><input type="submit" name="delete_group" value="Delete"> '; 
     17foreach ( $groups as $group ) { 
     18    echo '<li>'; 
     19    echo '<form method="post" action=""><input type="hidden" name="group" value="' . $group->name . '"><input type="submit" name="delete_group" value="Delete"> '; 
    2120    echo '<input type="submit" name="edit_group" value="Edit"> '; 
    22     echo $name . '</form>'; 
    23         echo '</li>'; 
     21    echo $group->name . '</form>'; 
     22    echo '</li>'; 
    2423} 
    2524?> 
     
    2928<p>Members</p> 
    3029<?php 
    31 if ( isset( $group ) ) { 
     30if ( isset( $group_edit ) ) { 
    3231    if ( isset( $users) && ( ! empty( $users ) ) ) { 
     32        echo '<p>Editing members of ' . $group_edit->name . '</p>'; 
    3333        echo '<form method="post" action="">'; 
    34         echo '<input type="hidden" name="group" value="' . $group . '">'; 
    35         echo Utils::html_select( 'add_user', $users ); 
    36         echo ' <input type="submit" value="Add"></form>'; 
    37     } 
    38     if ( ! empty($group_members) ) { 
    39             echo '<ul>'; 
    40             foreach ( $group_members as $member ) { 
    41                     $user= User::get_by_id($member); 
    42                     echo '<li><form method="post" action=""><input type="hidden" name="remove_user" value="' . $user->id . '">'; 
    43             echo '<input type="hidden" name="user_group" value="' . $group . '"><input type="submit" value="Remove"></form> ' . $user->username . '</li>'; 
    44             } 
    45             echo '</ul>'; 
     34        echo '<input type="hidden" name="group" value="' . $group_edit->name . '">'; 
     35        foreach ( $users as $user ) { 
     36            echo '<input type="checkbox" name="user_id[]" value="' . $user->id . '"'; 
     37            if ( in_array( $user->id, $group_edit->members ) ) { 
     38                echo ' checked'; 
     39            } 
     40            echo '"> ' . $user->username . '<br>'; 
     41        } 
     42        echo '<input type="submit" name="users" value="Submit"></form>'; 
    4643    } else { 
    4744        echo '<p>No members.</p>'; 
     
    5249<div class="column span-8 last"> 
    5350<p>Permissions</p> 
     51<?php 
     52if ( isset( $group_edit ) ) { 
     53    if ( isset( $permissions) && ( ! empty( $permissions ) ) ) { 
     54        echo '<p>Editing Permissions of ' . $group_edit->name . '</p>'; 
     55        echo '<form method="post" action="">'; 
     56        echo '<input type="hidden" name="group" value="' . $group_edit->name . '">'; 
     57        echo '<table><tr><th>Granted</th><th>Permission</th><th>Denied</th></tr>'; 
     58        foreach( $permissions as $perm ) { 
     59            echo '<tr>'; 
     60            if(  isset( $permissions_granted[ $perm->id ] ) ) { 
     61                // indicate that this permission is granted 
     62            } elseif ( isset( $permissions_denied[ $perm->id ] ) ) { 
     63                // indicate that this permission is denied 
     64            } 
     65            echo "<td><input type='checkbox' name='grant[]' value='{$perm->id}'"; 
     66            if ( in_array( $perm->id, $permissions_granted ) ) { 
     67                echo ' checked'; 
     68            } 
     69            echo "></td><td> {$perm->description} </td><td>"; 
     70            echo "<input type='checkbox' name='deny[]' value='{$perm->id}'"; 
     71            if ( in_array( $perm->id, $permissions_denied ) ) { 
     72                echo ' checked'; 
     73            } 
     74            echo '></td></tr>'; 
     75        } 
     76        echo '<tr><td colspan="3"><input type="submit" name="permissions" value="' . _t('Submit') . '"></td>'; 
     77        echo '</table></form>'; 
     78    } else { 
     79        echo '<p>No permissions.</p>'; 
     80    } 
     81} 
     82?> 
    5483</div> 
    5584</div> 
  • branches/111307-atom/system/admin/header.php

    r1291 r1440  
    33<head> 
    44    <title>Habari Administration</title> 
    5  
     5    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
    66    <link rel="stylesheet" href="<?php Site::out_url('habari'); ?>/3rdparty/blueprint/screen.css" type="text/css" media="screen, projection"> 
    77    <link rel="stylesheet" href="<?php Site::out_url('habari'); ?>/3rdparty/blueprint/print.css" type="text/css" media="print"> 
  • branches/111307-atom/system/admin/login.php

    r1291 r1440  
    2525        } 
    2626 
    27         #databasesetup { 
     27        #loginform { 
    2828            margin:0 auto; 
    2929        } 
     
    3737            margin-bottom: 50px; 
    3838        } 
     39        .notice, .error { 
     40            margin-left:auto; 
     41            margin-right:auto; 
     42            width:552px; 
     43        } 
    3944 
    4045        </style> 
    4146</head> 
    4247<body> 
    43 <ul id="menu"> 
     48<ul id="oldmenu"> 
    4449    <li id="site-name"> 
    4550        <a href="<?php Site::out_url('habari'); ?>" title="<?php Options::out('title'); ?>"><?php Options::out('title'); ?></a> 
    4651    </li> 
    47  
    4852</ul> 
    4953 
     54<div style="min-height:45px;"> 
     55<?php 
     56if ( Session::has_errors( 'expired_session' ) ) { 
     57    echo '<div class="error">' . Session::get_error( 'expired_session', false ) . '</div>'; 
     58} 
     59if ( Session::has_errors( 'expired_form_submission' ) ) { 
     60    echo '<div class="notice">' . Session::get_error( 'expired_form_submission', false ) . '</div>'; 
     61} 
     62?> 
     63</div> 
     64 
    5065<div id="wrapper"> 
    51 <div id="masthead"> 
    52     <h1>Habari</h1> 
    53 </div> 
    5466<form method="post" action="<?php URL::out( 'user', array( 'page' => 'login' ) ); ?>"> 
    55 <div class="installstep ready done" id="databasesetup"> 
    56     <h2>Login to <?php Options::out( 'title' ); ?></h2> 
     67<div class="installstep ready done" id="loginform"> 
     68    <h2>Login to Habari</h2> 
    5769    <div class="options"> 
    5870        <div class="inputfield"> 
     
    6577                <input type="password" size="25" name="habari_password" id="habari_password"> 
    6678            </p> 
    67             <p> 
    68                 <input class="submit" type="submit" value="GO!"> 
     79            <p class="center"> 
     80                <input class="submit" type="submit" value="Let's go!"> 
    6981            </p> 
    7082        </div> 
     
    7486</form> 
    7587 
    76 <div id="footer"> 
     88<div> 
    7789    <p class="left"><a href="<?php Site::out_url( 'habari' ); ?>/manual/index.html" onclick="popUp(this.href); return false;" title="Read the user manual">Manual</a> - 
    7890        <a href="http://wiki.habariproject.org/" title="Read the Habari wiki">Wiki</a> - 
    7991        <a href="http://groups.google.com/group/habari-users" title="Ask the community">Mailing List</a> 
    8092    </p> 
    81  
    82  
    8393</div> 
    8494 
  • branches/111307-atom/system/admin/logs.php

    r1291 r1440  
    6161             <input type="submit" name="do_delete" value="<?php _e('Delete'); ?>"> 
    6262        </table> 
     63        </form> 
    6364    </div> 
    6465</div> 
  • branches/111307-atom/system/admin/media.js

    r1291 r1440  
    3535                    output = '<table><tr>'; 
    3636                    var first = ' first'; 
     37                    habari.media.assets = result.files; 
    3738                    for(var file in result.files) { 
    3839                        stats = ''; 
    39                         output += '<td><div class="media' + first + '"><div class="mediatitle">' + result.files[file].title + '</div><img src="' + result.files[file].thumbnail_url + '"><div class="mediastats"> ' + stats + '</div><div class="foroutput"><img src="' + result.files[file].url + '"></div></div></td>'; 
     40                        output += '<td><div class="media' + first + '"><span class="foroutput">' + file + '</span>'; 
     41 
     42                        if(result.files[file].filetype && habari.media.preview[result.files[file].filetype]) { 
     43                            output += habari.media.preview[result.files[file].filetype](file, result.files[file]); 
     44                        } 
     45                        else { 
     46                            output += habari.media.preview.image(file, result.files[file]); 
     47                        } 
     48 
     49                        output += '</div></td>'; 
    4050                        first = ''; 
    4151                    } 
     
    4353                    $('.mediaphotos', container).html(output); 
    4454                    $('.media').dblclick(function(){ 
    45                         habari.editor.insertSelection($('.foroutput', this).html()); 
     55                        habari.media.insertAsset(this); 
    4656                    }); 
    4757                    $('.media_controls ul li:first', container).nextAll().remove(); 
     
    8797        container = $('.mediasplitter:visible'); 
    8898        $('.pathstore', container).addClass('toload'); 
     99    }, 
     100 
     101    preview: { 
     102        image: function(fileindex, fileobj) { 
     103            var stats = ''; 
     104            return '<div class="mediatitle">' + fileobj.title + '</div><img src="' + fileobj.thumbnail_url + '"><div class="mediastats"> ' + stats + '</div>'; 
     105        } 
     106    }, 
     107 
     108    output: { 
     109        image: function(fileindex, fileobj) { 
     110            habari.editor.insertSelection('<img src="' + fileobj.url + '">'); 
     111        } 
     112    }, 
     113 
     114    submitPanel: function(form) { 
     115        var query = $(form).serialize(); 
     116    }, 
     117 
     118    insertAsset: function(asset) { 
     119        var id = $('.foroutput', asset).html(); 
     120        if(this.assets[id].filetype && habari.media.output[this.assets[id].filetype]) { 
     121            habari.media.output[this.assets[id].filetype](id, this.assets[id]); 
     122        } 
     123        else { 
     124            habari.media.output.image(id, this.assets[id]); 
     125        } 
    89126    } 
    90127 
  • branches/111307-atom/system/admin/moderate.php

    r1291 r1440  
    3232                <label>URL <input type="checkbox" name="search_fields[]" class="search_field" value="url"<?php echo in_array('url', $search_fields) ? ' checked' : ''; ?>></label> 
    3333                <?php echo Utils::html_select('search_status', $statuses, $search_status, array( 'class'=>'longselect')); ?> 
    34                 <?php echo Utils::html_select('search_type', $types, $type, array( 'class'=>'longselect')); ?> 
     34                <?php echo Utils::html_select('search_type', $types, $search_type, array( 'class'=>'longselect')); ?> 
    3535            </p> 
    3636            </form> 
  • branches/111307-atom/system/admin/plugins.php

    r1291 r1440  
    33<hr> 
    44  <?php if(Session::has_messages()) {Session::messages_out();} ?> 
    5     <div class="column prepend-1 span-22 append-1" id="welcome"> 
    6         <h2>Currently Available Plugins</h2> 
    7         <p>Activate, deactivate and remove plugins through this interface.</p> 
     5    <div class="column prepend-2 span-20 append-2" id="welcome"> 
     6        <h2 class="center">Currently Available Plugins</h2> 
     7        <p class="center">Activate, deactivate and configure plugins through this interface.</p> 
    88    </div> 
    9     <div class="column prepend-1 span-22 append-1"> 
     9    <div class="column prepend-2 span-20 append-2"> 
     10        <h3>Active Plugins</h3> 
    1011        <table cellspacing="0" width="100%"> 
    1112            <thead> 
     
    2021            <tbody> 
    2122            <?php 
    22             foreach($plugins as $plugin) { 
     23            foreach($active_plugins as $plugin) { 
     24 
    2325                if($plugin['debug']) { 
    2426                ?> 
     
    6870                    </tbody></table></div></div> 
    6971                    <div id="plugin_options"><div class="container"><div class="column prepend-1 span-22 append-1"> 
    70                         <h2><?php echo $plugins[$configure]['info']->name; ?> : <?php echo $action; ?></h2> 
     72                        <h2><?php echo $active_plugins[$configure]['info']->name; ?> : <?php echo $action; ?></h2> 
    7173                        <?php 
    7274                            Plugins::act( 'plugin_ui', $configure, $action ); 
    7375                        ?> 
     76                        <a class="link_as_button" href="<?php URL::out( 'admin', 'page=plugins' ); ?>"><?php echo 'close' ?></a> 
    7477                    </div></div></div> 
    7578                    <div class="wrapper"> 
    7679                    <div class="container"> 
    77                     <div class="column prepend-1 span-22 append-1"> 
     80                    <div class="column prepend-2 span-20 append-2"> 
    7881                    <table cellspacing="0" width="100%"><tbody> 
    7982                    <?php } ?> 
     
    8285            </tbody> 
    8386        </table> 
     87        <h3>Inactive Plugins</h3> 
     88        <table cellspacing="0" width="100%"> 
     89            <thead> 
     90                <tr> 
     91                    <th align="left">Plugin Name</th> 
     92                    <th align="left">Author Name</th> 
     93                    <th align="left">Version</th> 
     94                    <th align="left">Description</th> 
     95                    <th>Action</th> 
     96                </tr> 
     97            </thead> 
     98            <tbody> 
     99            <?php 
     100            foreach($inactive_plugins as $plugin) { 
     101                 
     102                if($plugin['debug']) { 
     103                ?>   
     104                    <tr> 
     105                        <td colspan="3" class="error"><p>The plugin file '<?php echo $plugin['file']; ?>' had syntax errors and could not load.</p> 
     106                        <div style="display:none;" id="error_<?php echo $plugin['plugin_id']; ?>"><?php echo $plugin['error']; ?></div> 
     107                        </td> 
     108                        <td><button onclick="$('#error_<?php echo $plugin['plugin_id']; ?>').show();">Show Error</button></td> 
     109                    </tr> 
     110                <?php 
     111                }    
     112                else { 
     113                ?>   
     114                    <tr id="plugin_<?php echo $plugin['plugin_id']; ?>"> 
     115                        <td><?php echo '<a href="' . $plugin['info']->url . '">' . $plugin['info']->name . '</a>'; ?> 
     116                        </td> 
     117                        <td><?php echo empty( $plugin['info']->authorurl ) ? $plugin['info']->author : '<a href="' . $plugin['info']->authorurl . '">' . $plugin['info']->author . '</a>'; ?></td>          
     118                        <td><?php echo $plugin['info']->version; ?></td> 
     119                        <td><?php echo $plugin['info']->description; ?></td> 
     120                        <td> 
     121                        <form method='POST' action='<?php URL::out( 'admin', 'page=plugin_toggle' ); ?>'> 
     122                        <p><input type='hidden' name='plugin' value='<?php echo $plugin['file']; ?>'> 
     123                        <input type='hidden' name='action' value='Activate'> 
     124                        <button name='submit' type='submit'><?php echo $plugin['verb']; ?></button> 
     125                        </p> 
     126                        </form> 
     127                        </td> 
     128                    </tr> 
     129                    <?php if ( isset( $this->engine_vars['configure'] ) && ( $configure == $plugin['plugin_id'] ) ) { ?> 
     130                    </tbody></table></div></div> 
     131                    <div class="wrapper"> 
     132                    <div class="container"> 
     133                    <div class="column prepend-1 span-22 append-1"> 
     134                    <table cellspacing="0" width="100%"><tbody> 
     135                    <?php } ?> 
     136                <?php } ?> 
     137            <?php } ?> 
     138            </tbody> 
     139        </table> 
     140 
     141 
    84142    </div> 
    85143</div> 
  • branches/111307-atom/system/admin/publish.php

    r1291 r1440  
    9292        <?php endforeach; ?> 
    9393    </div> 
    94  
     94    <div style="display:none;" id="hiddenfields"> 
     95    <input type="hidden" name="content_type" value="<?php echo $content_type; ?>"> 
     96    <?php if ( $post->slug != '' ) { ?> 
     97    <input type="hidden" name="slug" id="slug" value="<?php echo $post->slug; ?>"> 
     98    <?php } ?> 
     99    </div> 
    95100 
    96101    <div id="formbuttons" class="container"> 
  • branches/111307-atom/system/admin/publish_settings.php

    r1291 r1440  
    1                 <input type="hidden" name="content_type" value="<?php echo $content_type; ?>"> 
    21                <div class="container"> 
    32                    <p class="column span-5"><?php _e('Content State'); ?></p> 
     
    1312                <div class="container"><p class="column span-5"><?php _e('Content Address'); ?></p>     <p class="column span-14 last"><input type="text" name="newslug" id="newslug" class="styledformelement" value="<?php echo $post->slug; ?>"></p></div> 
    1413 
    15                 <?php if ( $post->slug != '' ) { ?> 
    16                 <p><input type="hidden" name="slug" id="slug" value="<?php echo $post->slug; ?>"></p> 
    17                 <?php } ?> 
  • branches/111307-atom/system/admin/themes.php

    r1291 r1440  
    44    <?php if(Session::has_messages()) {Session::messages_out();} ?> 
    55    <div class="column prepend-1 span-22 append-1"> 
    6         <h2>Currently Available Themes</h2> 
    7         <p>Activate, deactivate and remove themes through this interface.</p> 
     6        <h2 class="center">Currently Available Themes</h2> 
     7        <p class="center">Activate, deactivate, configure and remove themes through this interface.</p> 
    88    </div> 
     9        <?php 
     10        if ( isset( $this->engine_vars['configure'] ) ): ?> 
     11            </div> 
     12                <div id="theme_options"><div class="container"><div class="column prepend-1 span-22 append-1"> 
     13                    <h2><?php echo $active_theme_name ?> : Configure</h2> 
     14                    <?php Plugins::act( 'theme_ui', $active_theme ); ?> 
     15                    <a class="link_as_button" href="<?php URL::out( 'admin', 'page=themes' ); ?>"><?php echo 'close' ?></a> 
     16                </div></div></div> 
     17            <div class="container"> 
     18        <?php endif; ?> 
    919    <div class="column prepend-1 span-22 append-1"> 
    1020        <?php foreach( $all_themes as $theme ) : ?> 
     
    1424                 by <a href="<?php echo $theme['info']->url; ?>"><?php echo $theme['info']->author; ?></a> 
    1525 
    16                 <?php if ( $theme['dir'] != $active_theme ) { ?> 
     26                <?php if ( $theme['dir'] != $active_theme_dir ) { ?> 
    1727                <form method='post' action='<?php URL::out('admin', 'page=activate_theme'); ?>'> 
    1828                <input type='hidden' name='theme_name' value='<?php echo $theme['info']->name; ?>'> 
    1929                <input type='hidden' name='theme_dir' value='<?php echo $theme['dir']; ?>'> 
    2030                <input type='submit' name='submit' value='activate'> 
    21                 </form>  
     31                </form> 
    2232                <?php } else { 
    23                     echo "<br><strong>Currently Active Theme</strong><br><br>"; 
     33                        echo "<br><strong>Currently Active Theme</strong><br><br>"; 
     34                        if ( $configurable ) { 
     35                        ?> 
     36                            <a class="link_as_button" href="<?php URL::out( 'admin', 'page=themes&configure=' . $theme['dir'] ); ?>">Configure</a> 
     37                        <?php 
     38                        } 
    2439                  } 
    2540                 ?> 
    26                  
     41 
    2742            </div> 
    2843        <?php endforeach; ?> 
  • branches/111307-atom/system/admin/user.php

    r1291 r1440  
    4040        <p><label>Username:</label></p> 
    4141        <p><input type="text" name="username" value="<?php echo $user->username; ?>"></p> 
     42                <p><label>Display Name:</label></p> 
     43                <p><input type="text" name="displayname" value="<?php echo $user->info->displayname; ?>"></p> 
    4244        <p><label>Email address:</label></p> 
    4345        <p><input type="text" name="email" value="<?php echo $user->email; ?>"></p> 
  • branches/111307-atom/system/classes/acl.php

    r745 r1440  
    11<?php 
    22 
    3 /**  
     3/** 
    44 * Access Control List class 
    5  *   
     5 * 
    66 * The default Habari ACL class implements groups, and group permissions 
    77 * Users are assigned to one or more groups. 
     
    1111 * that permission denies the user that permission, even if another group 
    1212 * grants that permission. 
    13  *      
     13 * 
    1414 * @package Habari 
    1515 **/ 
    16   
     16 
    1717class ACL { 
    18     /** 
    19      * An array of users assigned to a specific group id. 
    20      * Both the group and the user are id integers, not string values. 
    21      * The user arrays have both the key and the value set to the user_id.        
    22      * For example: 
    23      * <code> 
    24      * self::$groups= array( 
    25      *  1 => array(1 => 1), 
    26      *  2 => array(1 => 1, 2 => 2), 
    27      * ); 
    28      * </code> 
    29      **/      
    30     private static $groups= array(); 
    31  
    32     /** 
    33      * An array of group IDs with group names. 
    34      * For example: 
    35      * <code> 
    36      * self::$group_names= array( 
    37      *  1 => 'administrators', 
    38      *  2 => 'guests', 
    39      * ); 
    40      * </code>    
    41      **/          
    42     private static $group_names= array(); 
    43  
    44     /** 
    45      * An array of permssions assigned to a group. 
    46      * The group and permission are both id integers, not string values. 
    47      * The key of each permission array is the permission id.   
    48      * The value of the permission id is boolean on whether to grant or deny that permission. 
    49      * For example: 
    50      * <code> 
    51      * self::$group_permissions= array( 
    52      *  1 => array( 1 => true, 2 => true), 
    53      *  2 => array( 2 => false), 
    54      * ); 
    55      * </code> 
    56      **/                                             
    57     private static $group_permissions= array(); 
    58  
    59     /** 
    60      * An array in which specific user permissions are cached as they are built from the other structures. 
    61      **/             
    62     private static $user_permissions= array(); 
    63      
    64     /** 
    65      * An array of permissions, with the permission id as the key and the string value as the value. 
    66      **/         
    67     private static $permissions= array(); 
    68      
    6918    /** 
    7019     * How to handle a permission request for a permission that is not in the permission list. 
     
    7221     * It's true at the moment because that allows access to all features for upgrading users. 
    7322     * @todo Decide if this is a setting we need or want to change, or perhaps it should be an option. 
    74      **/                     
     23     **/ 
    7524    const ACCESS_NONEXISTANT_PERMISSION = true; 
    7625 
    7726    /** 
    78      * Load all group and permission data from the DB 
    79      * __static() class members are called by __autoload()    
    80     **/ 
    81     public static function __static() 
    82     { 
    83         $results= DB::get_results( 'SELECT * FROM ' . DB::table('groups') ); 
    84         foreach ($results as $group) { 
    85             self::$group_names[$group->id]= $group->name; 
    86         } 
    87         $results= DB::get_results( 'SELECT * FROM ' . DB::table('permissions')); 
    88         foreach ( $results as $permission ) { 
    89             self::$permissions[$permission->id] = $permission->name; 
    90         } 
    91         $results= DB::get_results( 'SELECT * FROM ' . DB::table('users_groups') ); 
    92         foreach ( $results as $group ) { 
    93             self::$groups[$group->group_id][$group->user_id]= $group->user_id; 
    94         } 
    95         $results= DB::get_results( 'SELECT * FROM ' . DB::table('groups_permissions')); 
    96         foreach ( $results as $permission ) { 
    97             self::$group_permissions[$permission->group_id][$permission->permission_id]= !$permission->denied; 
    98         } 
     27     * Create a new permission, and save it to the Permissions table 
     28     * @param string The name of the permission 
     29     * @param string The description of the permission 
     30     * @return mixed the ID of the newly created permission, or boolean FALSE 
     31    **/ 
     32    public static function create_permission( $name, $description ) 
     33    { 
     34        $name= self::normalize_permission( $name ); 
     35        // first, make sure this isn't a duplicate 
     36        if ( ACL::permission_exists( $name ) ) { 
     37            return false; 
     38        } 
     39        $allow= true; 
     40        // Plugins have the opportunity to prevent adding this permission 
     41        $allow= Plugins::filter('permission_create_allow', $allow, $name, $description ); 
     42        if ( ! $allow ) { 
     43            return false; 
     44        } 
     45        Plugins::act('permission_create_before', $name, $description); 
     46        $result= DB::query('INSERT INTO {permissions} (name, description) VALUES (?, ?)', array( $name, $description) ); 
     47        if ( ! $result ) { 
     48            // if it didn't work, don't bother trying to log it 
     49            return false; 
     50        } 
     51        EventLog::log('New permission created: ' . $name, 'info', 'default', 'habari'); 
     52        Plugins::act('permission_create_after', $name, $description ); 
     53        return $result; 
     54    } 
     55 
     56    /** 
     57     * Remove a permission, and any assignments of it 
     58     * @param mixed a permission ID or name 
     59     * @return bool whether the permission was deleted or not 
     60    **/ 
     61    public static function destroy_permission( $permission ) 
     62    { 
     63        // make sure the permission exists, first 
     64        if ( ! ACL::permission_exists( $permission ) ) { 
     65            return false; 
     66        } 
     67 
     68        // Use ids internall for permissions 
     69        $permission= ACL::permission_id( $permission ); 
     70 
     71        $allow= true; 
     72        // plugins have the opportunity to prevent deletion 
     73        $allow= Plugins::filter('permission_destroy_allow', $allow, $permission); 
     74        if ( ! $allow ) { 
     75            return false; 
     76        } 
     77        Plugins::act('permission_destroy_before', $permission ); 
     78        // capture the permission name 
     79        $name= DB::get_value( 'SELECT name FROM {permissions} WHERE id=?', array( $permission ) ); 
     80        // remove all references to this permissions 
     81        $result= DB::query( 'DELETE FROM {groups_permissions} WHERE permission_id=?', array( $permission ) ); 
     82        // remove this permission 
     83        $result= DB::query( 'DELETE FROM {permissions} WHERE permissions_id=?', array( $permission ) ); 
     84        if ( ! $result ) { 
     85            // if it didn't work, don't bother trying to log it 
     86            return false; 
     87        } 
     88        EventLog::log('Permission deleted: ' . $name, 'info', 'default', 'habari'); 
     89        Plugins::act('permission_destroy_after', $permission ); 
     90        return $result; 
     91    } 
     92 
     93    /** 
     94     * Get an array of QueryRecord objects containing all permissions 
     95     * @param string the order in which to sort the returning array 
     96     * @return array an array of QueryRecord objects containing all permissions 
     97    **/ 
     98    public static function all_permissions( $order= 'id' ) 
     99    { 
     100        $order= strtolower( $order ); 
     101        if ( ( 'id' != $order ) && ( 'name' != $order ) && ( 'description' != $order ) ) { 
     102            $order= 'id'; 
     103        } 
     104        $permissions= DB::get_results( 'SELECT id, name, description FROM {permissions} ORDER BY ' . $order ); 
     105        return $permissions ? $permissions : array(); 
     106    } 
     107 
     108    /** 
     109     * Get a permission's name by its ID 
     110     * @param int a permission ID 
     111     * @return string the name of the permission, or boolean FALSE 
     112    **/ 
     113    public static function permission_name( $id ) 
     114    { 
     115        if ( ! is_int( $id ) ) { 
     116            return false; 
     117        } else { 
     118            return DB::get_value( 'SELECT name FROM {permissions} WHERE id=?', array( $id ) ); 
     119        } 
     120    } 
     121 
     122    /** 
     123     * Get a permission's ID by its name 
     124     * @param string the name of the permission 
     125     * @return int the permission's ID 
     126    **/ 
     127    public static function permission_id( $name ) 
     128    { 
     129        if( is_integer($name) ) { 
     130            return $name; 
     131        } 
     132        $name= self::normalize_permission( $name ); 
     133        return DB::get_value( 'SELECT id FROM {permissions} WHERE name=?', array( $name ) ); 
     134    } 
     135 
     136    /** 
     137     * Fetch a permission description from the DB 
     138     * @param mixed a permission name or ID 
     139     * @return string the description of the permission 
     140    **/ 
     141    public static function permission_description( $permission ) 
     142    { 
     143        if ( is_int( $permission) ) { 
     144            $query= 'id'; 
     145        } else { 
     146            $query= 'name'; 
     147            $permission= self::normalize_permission( $permission ); 
     148        } 
     149        return DB::get_value( "SELECT description FROM {permissions} WHERE $query=?", array( $permission ) ); 
     150    } 
     151 
     152    /** 
     153     * Determine whether a permission exists 
     154     * @param mixed a permission name or ID 
     155     * @return bool whether the permission exists or not 
     156    **/ 
     157    public static function permission_exists( $permission ) 
     158    { 
     159        if ( is_int( $permission ) ) { 
     160            $query= 'id'; 
     161        } 
     162        else { 
     163            $query= 'name'; 
     164            $permission= self::normalize_permission( $permission ); 
     165        } 
     166        return ( DB::get_value( "SELECT COUNT(id) FROM {permissions} WHERE $query=?", array( $permission ) ) > 0 ); 
    99167    } 
    100168 
    101169    /** 
    102170     * Determine whether the specified user is a member of the specified group 
    103      * @param int A user  ID 
    104      * @param int A group ID 
     171     * @param mixed A user  ID or name 
     172     * @param mixed A group ID or name 
    105173     * @return bool True if the user is in the group, otherwise false 
    106174    **/ 
    107175    public static function user_in_group( $user_id, $group_id ) 
    108176    { 
    109         return isset(self::$groups[self::group_id( $group_id )][$user_id]); 
    110     } 
    111  
    112     /** 
    113      * Return an array of the groups to which this user belongs 
    114      * @param int A user ID 
    115      * @return array An array of group IDs 
    116     **/ 
    117     public static function user_group_list( $user_id ) 
    118     { 
    119         $user_id= intval($user_id); 
    120         return array_keys( array_filter( self::$groups, create_function('$a', 'return isset($a[' . $user_id . ']);') ) ); 
     177        if ( ! is_int( $user_id ) ) { 
     178            $user= User::get( $user_id ); 
     179            $user_id= $user->id; 
     180        } 
     181        if ( ! is_int( $group_id ) ) { 
     182            $group_id= UserGroup::id( $group_id ); 
     183        } 
     184        $group= DB::get_value( 'SELECT id FROM {users_groups} WHERE user_id=? AND group_id=?', array( $user_id, $group_id ) ); 
     185        if ( $group ) { 
     186            return true; 
     187        } 
     188        return false; 
    121189    } 
    122190 
    123191    /** 
    124192     * Determine whether a group can perform a specific action 
    125      * @param int A group ID 
    126      * @param string An action 
     193     * @param mixed $group A group ID or name 
     194     * @param mixed $permission An action ID or name 
    127195     * @return bool Whether the group can perform the action 
    128196    **/ 
    129     public static function group_can( $group_id, $action ) 
    130     { 
    131         return isset(self::$group_permissions[self::group_id( $group_id )][$action]) && self::$group_permissions[self::group_id( $group_id )][$action]; 
    132     } 
    133      
    134     /** 
    135      * Return the id of a group, provided the name 
    136      * @param string $group_id The name of the group 
    137      * @return int The group id 
    138      **/ 
    139     public static function group_id( $group_id ) 
    140     { 
    141         if(!is_numeric($group_id)) { 
    142             $group_id = array_search($group_id, self::$group_names); 
    143         } 
    144         return $group_id; 
    145     }                
     197    public static function group_can( $group, $permission ) 
     198    { 
     199        // Use only numeric ids internally 
     200        $group= UserGroup::id( $group ); 
     201        $permission= ACL::permission_id( $permission ); 
     202        $result= DB::get_value( 'SELECT denied FROM {groups_permissions} WHERE permission_id=? AND group_id=?', array( $permission, $group ) ); 
     203        if ( 0 === intval($result) ) { 
     204            // the permission has been granted to this group 
     205            return true; 
     206        } 
     207        // either the permission hasn't been granted, or it's been 
     208        // explicitly denied. 
     209        return false; 
     210    } 
    146211 
    147212    /** 
    148213     * Determine whether a user can perform a specific action 
    149      * @param int A user ID 
    150      * @param string An action 
     214     * @param mixed $user A user object, user ID or a username 
     215     * @param mixed $permission A permission ID or name 
    151216     * @return bool Whether the user can perform the action 
    152217    **/ 
    153     public static function user_can( $user_id, $action ) 
    154     { 
    155         if(($permission_id = array_search($action, self::$permissions)) === false) { 
    156             return ACL::ACCESS_NONEXISTANT_PERMISSION; 
    157         } 
    158         if(!isset(self::$user_permissions[$user_id])) { 
    159             self::$user_permissions[$user_id] = array(); 
    160             foreach( self::user_group_list( $user_id ) as $group_id )   { 
    161                 foreach( self::$group_permissions[$group_id] as $action => $grant ) { 
    162                     if(isset(self::$user_permissions[$user_id][$permission_id])) { 
    163                         self::$user_permissions[$user_id][$permission_id]= self::$user_permissions[$user_id][$permission_id] && $grant; 
    164                     } 
    165                     else { 
    166                         self::$user_permissions[$user_id][$permission_id]= $grant; 
    167                     } 
    168                 } 
     218    public static function user_can( $user, $permission ) 
     219    { 
     220        // Use only numeric ids internally 
     221        $permission= ACL::permission_id( $permission ); 
     222        // if we were given a user ID, use that to fetch the group membership from the DB 
     223        if ( is_int( $user) ) { 
     224            $user_id= $user; 
     225        } else { 
     226            // otherwise, make sure we have a User object, and get 
     227            // the groups from that 
     228            if ( ! $user instanceof User ) { 
     229                $user= User::get( $user ); 
    169230            } 
    170         } 
    171         return isset(self::$user_permissions[$user_id][$permission_id]) && self::$user_permissions[$user_id][$permission_id]; 
     231            $user_id= $user->id; 
     232        } 
     233 
     234        // we select the "denied" value from all the permissions 
     235        // assigned to all the groups to which this user is a member. 
     236        // array_unique() should consolidate this down to, at most, 
     237        // two values: 0 and 1. 
     238        $permissions= DB::get_column('SELECT gp.denied from {groups_permissions} gp, {users_groups} g where gp.group_id = g.group_id and g.user_id=? and permission_id=?', array( $user_id, $permission ) ); 
     239 
     240        // if any group is explicitly denied access to this permission, 
     241        // this user is denied access to that permission 
     242        if ( in_array( 1, $permissions ) ) { 
     243            return false; 
     244        } 
     245        // if the permission is not explicitly denied, make sure it's 
     246        // explicitly granted.  If it is, the user can do this. 
     247        if ( in_array( 0, $permissions, true ) ) { 
     248            return true; 
     249        } 
     250        // if the permission is neither denied nor granted, they're not 
     251        // allowed to do it. 
     252        return self::ACCESS_NONEXISTANT_PERMISSION; 
     253        return false; 
     254    } 
     255 
     256    /** 
     257     * Convert a permission name into a valid format 
     258     * 
     259     * @param string $name The name of a permission 
     260     * @return string The permission with spaces converted to underscores and all lowercase 
     261     */ 
     262    public static function normalize_permission( $name ) 
     263    { 
     264        return strtolower( preg_replace( '/\s+/', '_', trim($name) ) ); 
    172265    } 
    173266} 
  • branches/111307-atom/system/classes/adminhandler.php

    r1291 r1440  
    1818        $user= User::identify(); 
    1919        if ( !$user ) { 
     20            Session::error( _t('Your session expired.'), 'expired_session' ); 
    2021            Session::add_to_set( 'login', $_SERVER['REQUEST_URI'], 'original' ); 
     22            if ( !empty( $_POST ) ) { 
     23                Session::add_to_set( 'last_form_data', $_POST, 'post' ); 
     24                Session::error( _t('We saved the last form you posted. Log back in to continue its submission.'), 'expired_form_submission' ); 
     25            } 
     26            if ( !empty( $_GET ) ) { 
     27                Session::add_to_set( 'last_form_data', $_GET, 'get' ); 
     28                Session::error( _t('We saved the last form you posted. Log back in to continue its submission.'), 'expired_form_submission' ); 
     29            } 
    2130            Utils::redirect( URL::get( 'user', array( 'page' => 'login' ) ) ); 
    2231            exit; 
     
    2534            die( _t( 'Permission denied.' ) ); 
    2635        } 
     36        $last_form_data= Session::get_set( 'last_form_data' ); // This was saved in the "if ( !$user )" above, UserHandler transferred it properly. 
     37        /* At this point, Controller has not created handler_vars, so we have to modify $_POST/$_GET. */ 
     38        if ( isset( $last_form_data['post'] ) ) { 
     39            $_POST= array_merge( $_POST, $last_form_data['post'] ); 
     40            $_SERVER['REQUEST_METHOD']= 'POST'; // This will trigger the proper act_admin switches. 
     41            Session::remove_error( 'expired_form_submission' ); 
     42        } 
     43        if ( isset( $last_form_data['get'] ) ) { 
     44            $_GET= array_merge( $_GET, $last_form_data['get'] ); 
     45            Session::remove_error( 'expired_form_submission' ); 
     46            // No need to change REQUEST_METHOD since GET is the default. 
     47        } 
    2748        $user->remember(); 
    2849    } 
     
    3455    { 
    3556        $page= ( isset( $this->handler_vars['page'] ) && !empty( $this->handler_vars['page'] ) ) ? $this->handler_vars['page'] : 'dashboard'; 
    36         $this->theme= Themes::create( 'admin', 'RawPHPEngine', Site::get_dir( 'admin_theme', TRUE ) ); 
     57        $theme_dir = Plugins::filter( 'admin_theme_dir', Site::get_dir( 'admin_theme', TRUE ) ); 
     58        $this->theme= Themes::create( 'admin', 'RawPHPEngine', $theme_dir ); 
    3759        $this->set_admin_template_vars( $this->theme ); 
     60        $this->theme->admin_page = $page; 
    3861        switch( $_SERVER['REQUEST_METHOD'] ) { 
    3962            case 'POST': 
     63                // Let plugins try to handle the page 
     64                Plugins::act('admin_theme_post_' . $page, $this, $this->theme); 
    4065                // Handle POSTs to the admin pages 
    4166                $fn= 'post_' . $page; 
     
    5075                break; 
    5176            default: 
     77                // Let plugins try to handle the page 
     78                Plugins::act('admin_theme_get_' . $page, $this, $this->theme); 
    5279                // Handle GETs of the admin pages 
    5380                $fn= 'get_' . $page; 
     
    5784                } 
    5885                // If a get_ function doesn't exist, just load the template and display it 
    59                 $files= Utils::glob( Site::get_dir( 'admin_theme', TRUE ) . '*.php' ); 
    60                 $filekeys= array_map( create_function( '$a', 'return basename( $a, \'.php\' );' ), $files ); 
    61                 $map= array_combine( $filekeys, $files ); 
    62                 if ( isset( $map[$page] ) ) { 
     86                if ( $this->theme->template_exists( $page ) ) { 
    6387                    $this->display( $page ); 
    6488                } 
     
    120144 
    121145    /** 
     146     * Handles get requests for the dashboard 
     147     */ 
     148    public function get_dashboard() 
     149    { 
     150        // Not sure how best to determine this yet, maybe set an option on install, maybe do this: 
     151        $firstpostdate = strtotime(DB::get_value('SELECT min(pubdate) FROM {posts} WHERE status = ?', array(Post::status('published')))); 
     152        $firstpostdate = time() - $firstpostdate; 
     153        $this->theme->active_time = array( 
     154            'years' => floor($firstpostdate / 31536000), 
     155            'months' => floor(($firstpostdate % 31536000) / 2678400), 
     156            'days' => round(($firstpostdate % 2678400) / 86400), 
     157        ); 
     158 
     159        $this->theme->stats = array( 
     160            'author_count' => DB::get_value('SELECT count(*) FROM {posts} GROUP BY user_id;'), 
     161            'page_count' => DB::get_value('SELECT count(pubdate) FROM {posts} WHERE content_type = ? and status = ?', array(Post::type('page'), Post::status('published'))), 
     162            'entry_count' => DB::get_value('SELECT count(pubdate) FROM {posts} WHERE content_type = ? and status = ?', array(Post::type('entry'), Post::status('published'))), 
     163            'comment_count' => DB::get_value('SELECT min(pubdate) FROM {posts} WHERE content_type = ?', array(Post::type('page'))), 
     164            'tag_count' => DB::get_value('SELECT count(*) FROM {tags}'), 
     165            'page_draft_count' => DB::get_value('SELECT min(pubdate) FROM {posts} WHERE content_type = ? and status = ?', array(Post::type('page'), Post::status('draft'))), 
     166            'entry_draft_count' => DB::get_value('SELECT min(pubdate) FROM {posts} WHERE content_type = ? and status = ?', array(Post::type('entry'), Post::status('draft'))), 
     167            'unapproved_comment_count' => Comments::count_total( Comment::STATUS_UNAPPROVED ), 
     168        ); 
     169 
     170        $this->theme->recent_posts = Posts::get( array( 'status' => 'published', 'limit' => 8 ) ); 
     171        $this->theme->recent_comments = Comments::get( array( 'status' => 'approved', 'limit' => 5 ) ); 
     172 
     173        $this->display( 'dashboard' ); 
     174    } 
     175 
     176    /** 
    122177     * Handles post requests from the publish page. 
    123178     */ 
     
    128183            $post= Post::get( array( 'slug' => $slug, 'status' => Post::status( 'any' ) ) ); 
    129184            $post->title= $title; 
    130             $post->slug= $newslug; 
     185            if ( ( $newslug != '' ) && ( $newslug != $slug ) ) { 
     186                $post->slug= $newslug; 
     187            } 
    131188            $post->tags= $tags; 
    132189            $post->content= $content; 
     
    248305        $user= $currentuser; 
    249306        extract( $this->handler_vars ); 
    250         $fields= array( 'user_id' => 'id', 'delete' => NULL, 'username' => 'username', 'email' => 'email', 'imageurl' => 'imageurl', 'pass1' => NULL ); 
     307        $fields= array( 'user_id' => 'id', 'delete' => NULL, 'username' => 'username', 'displayname' => 'displayname', 'email' => 'email', 'imageurl' => 'imageurl', 'pass1' => NULL ); 
    251308        $fields= Plugins::filter( 'adminhandler_post_user_fields', $fields ); 
    252309 
     
    264321                        if ( isset( $user_id ) && ( $currentuser->id != intval( $user_id ) ) ) { 
    265322                            $username= $user->username; 
    266                             $posts= Posts::get( array( 'user_id' => $user_id ) ); 
     323                            $posts= Posts::get( array( 'user_id' => $user_id, 'nolimit' => 1 ) ); 
    267324                            if ( isset( $reassign ) && ( 1 === intval( $reassign ) ) ) { 
    268325                                // we're going to re-assign all of this user's posts 
    269326                                $newauthor= isset( $author ) ? intval( $author ) : 1; 
    270                                 foreach ( $posts as $post ) { 
    271                                     $post->user_id= $newauthor; 
    272                                     $post->update(); 
    273                                 } 
    274                             } else { 
     327                                Posts::reassign( $newauthor, $posts ); 
     328                            } 
     329                            else { 
    275330                                // delete posts 
    276331                                foreach ( $posts as $post ) { 
     
    392447    } 
    393448 
     449    /** 
     450     * A POST handler for the admin themes page that simply passes those options through. 
     451     */ 
     452    public function post_themes() 
     453    { 
     454        return $this->get_themes(); 
     455    } 
     456 
     457    /** 
     458     * Handles GET requests for the theme listing 
     459     */ 
    394460    function get_themes() 
    395461    { 
    396         $this->theme->active_theme= Options::get( 'theme_dir' ); 
    397         $this->theme->all_themes= Themes::get_all_data(); 
     462 
     463        $all_themes= Themes::get_all_data(); 
     464        $this->theme->all_themes= $all_themes; 
     465 
     466        $active_theme_dir= Options::get( 'theme_dir' ); 
     467        $this->theme->active_theme_dir= $active_theme_dir; 
     468        $this->theme->active_theme= $all_themes[$active_theme_dir]; 
     469 
     470        // instantiate the active theme to see if it's configurable 
     471        $active_theme= Themes::create(); 
     472        $this->theme->active_theme_name= $all_themes[$active_theme_dir]['info']->name; 
     473        $this->theme->configurable= Plugins::filter( 'theme_config', false, $active_theme); 
    398474 
    399475        $this->theme->display( 'themes' ); 
     
    470546            // Delete all comments that have the spam status. 
    471547            Comments::delete_by_status( Comment::STATUS_SPAM ); 
     548            // let's optimize the table 
     549            $result= DB::query('OPTIMIZE TABLE {comments}'); 
    472550            Session::notice( _t( 'Deleted all spam comments' ) ); 
    473551            Utils::redirect(); 
     
    514592                        // This comment was marked as spam 
    515593                        $comment= Comment::get( $comment->id ); 
    516                         $modstatus['Marked %d comments as spam'] += $comment->status != Comment::STATUS_SPAM; 
     594                        $modstatus['Marked %d comments as spam']+= $comment->status != Comment::STATUS_SPAM; 
    517595                        $comment->status= Comment::STATUS_SPAM; 
    518596                        $comment->update(); 
     
    521599                        // This comment was marked for approval 
    522600                        $comment= Comment::get( $comment->id ); 
    523                         $modstatus['Approved %d comments'] += $comment->status != Comment::STATUS_APPROVED; 
     601                        $modstatus['Approved %d comments']+= $comment->status != Comment::STATUS_APPROVED; 
     602                        $modstatus['Approved comments on these posts: %s'] = (isset($modstatus['Approved comments on these posts: %s'])? $modstatus['Approved comments on these posts: %s'] . ' &middot; ' : '') . '<a href="' . $comment->post->permalink . '">' . $comment->post->title . '</a> '; 
    524603                        $comment->status= Comment::STATUS_APPROVED; 
    525604                        $comment->update(); 
     
    528607                        // This comment was marked for unapproval 
    529608                        $comment= Comment::get( $comment->id ); 
    530                         $modstatus['Unapproved %d comments'] += $comment->status != Comment::STATUS_UNAPPROVED; 
     609                        $modstatus['Unapproved %d comments']+= $comment->status != Comment::STATUS_UNAPPROVED; 
    531610                        $comment->status= Comment::STATUS_UNAPPROVED; 
    532611                        $comment->update(); 
     
    612691        $this->theme->default_radio= $default_radio; 
    613692 
     693        if($search_type != 'All') { 
     694            $arguments['type']= intval( $search_type ); 
     695        } 
     696 
    614697        if ( '' != $search ) { 
    615698            $arguments['criteria']= $search; 
    616699            $arguments['criteria_fields']= $search_fields; 
    617             if ( $search_status == 'All' ) { 
    618                 unset( $arguments['status'] ); 
    619             } 
    620             if ( $search_type == 'All' ) { 
    621                 unset( $arguments['type'] ); 
    622             } 
     700        } 
     701        if ( $search_status == 'All' ) { 
     702            unset( $arguments['status'] ); 
     703        } 
     704        if ( $search_type == 'All' ) { 
     705            unset( $arguments['type'] ); 
    623706        } 
    624707        $this->theme->comments= Comments::get( $arguments ); 
     
    655738        $active_plugins= Plugins::get_active(); 
    656739 
    657         $plugins= array(); 
     740        $sort_active_plugins= array(); 
     741        $sort_inactive_plugins= array(); 
     742 
    658743        foreach ( $all_plugins as $file ) { 
    659744            $plugin= array(); 
     
    676761                    // in order to get its info() 
    677762                    include_once( $file ); 
    678                     $pluginobj= Plugins::load( $file ); 
     763                    $pluginobj= Plugins::load( $file, false ); 
    679764                    $plugin['active']= false; 
    680765                    $plugin['verb']= _t( 'Activate' ); 
     
    686771                $plugin['debug']= true; 
    687772                $plugin['error']= $error; 
    688             } 
    689             $plugins[$plugin_id]= $plugin; 
    690         } 
    691  
    692         $this->theme->plugins= $plugins; 
     773                $plugin['active']= false; 
     774            } 
     775            if ($plugin['active']) { 
     776                $sort_active_plugins[$plugin_id]= $plugin; 
     777            } else { 
     778                $sort_inactive_plugins[$plugin_id]= $plugin; 
     779            } 
     780        } 
     781 
     782        //$this->theme->plugins= array_merge($sort_active_plugins, $sort_inactive_plugins); 
     783        $this->theme->active_plugins= $sort_active_plugins; 
     784        $this->theme->inactive_plugins= $sort_inactive_plugins; 
    693785 
    694786        $this->display( 'plugins' ); 
     
    767859 
    768860        // Set up Authors select box 
    769         $authors_temp= DB::get_results( 'SELECT username, user_id FROM ' . DB::table( 'users' ) . ' JOIN ' . DB::table( 'posts' ) . ' ON ' . DB::table( 'users' ) . '.id=' . DB::table( 'posts' ) . '.user_id GROUP BY user_id ORDER BY username ASC' ); 
     861        $authors_temp= DB::get_results( 'SELECT username, user_id FROM {users} JOIN {posts} ON {users}.id={posts}.user_id GROUP BY user_id ORDER BY username ASC' ); 
    770862        array_unshift( $authors_temp, new QueryRecord( array( 'username' => 'All', 'user_id' => 0 ) ) ); 
    771863        $authors= array(); 
     
    831923    { 
    832924        $locals= array( 
    833             'do_update' => false, 
     925            'do_delete' => false, 
    834926            'log_ids' => null, 
    835927            'nonce' => '', 
     
    852944            $this->theme->{$varname}= $$varname; 
    853945        } 
     946        if ( $do_delete && isset( $log_ids ) ) { 
     947            $okay= true; 
     948            if ( empty( $nonce ) || empty( $timestamp ) ||  empty( $PasswordDigest ) ) { 
     949                $okay= false; 
     950            } 
     951            // Ensure the request was submitted less than five minutes ago 
     952            if ( ( time() - strtotime( $timestamp ) ) > 300 ) { 
     953                $okay= false; 
     954            } 
     955            $wsse= Utils::WSSE( $nonce, $timestamp ); 
     956            if ( $PasswordDigest != $wsse['digest'] ) { 
     957                $okay= false; 
     958            } 
     959            if ( $okay ) { 
     960                foreach ( $log_ids as $id ) { 
     961                    $ids[]= array( 'id' => $id ); 
     962                } 
     963                $to_delete= EventLog::get( array( 'where' => $ids, 'nolimit' => 1 ) ); 
     964                $logstatus= array( 'Deleted %d logs' => 0 ); 
     965                foreach ( $to_delete as $log ) { 
     966                    $log->delete(); 
     967                    $logstatus['Deleted %d logs']+= 1; 
     968                } 
     969                foreach ( $logstatus as $key => $value ) { 
     970                    if ( $value ) { 
     971                        Session::notice( sprintf( _t( $key ), $value ) ); 
     972                    } 
     973                } 
     974            } 
     975            Utils::redirect(); 
     976            die(); 
     977        } 
    854978        $this->theme->severities= LogEntry::list_severities(); 
    855979        $any= array( '0' => 'Any' ); 
     
    9561080    public function post_groups() 
    9571081    { 
    958         $this->theme->groups= UserGroup::all_groups(); 
     1082        $this->theme->groups= UserGroups::get_all(); 
    9591083        if ( isset( $this->handler_vars['add_group'] ) ) { 
    960             if ( UserGroup::add_group( $this->handler_vars['add_group'] ) ) { 
    961                 Session::notice( sprintf(_t( 'Added group %s'), $this->handler_vars['add_group'] ) ); 
    962                 $this->theme->groups= UserGroup::all_groups(); 
     1084            $name= $this->handler_vars['add_group']; 
     1085            if ( UserGroup::exists($name) ) { 
     1086                Session::notice( sprintf(_t( 'The group %s already exists'), $name ) ); 
     1087            } 
     1088            else { 
     1089                $groupdata= array( 
     1090                    'name' => $name 
     1091                ); 
     1092                $group= UserGroup::create($groupdata); 
     1093                Session::notice( sprintf(_t( 'Added group %s'), $name ) ); 
     1094                // reload the groups 
     1095                $this->theme->groups= UserGroups::get_all(); 
    9631096            } 
    9641097        } 
    9651098 
    9661099        if ( isset( $this->handler_vars['delete_group'] ) ) { 
    967             // capture the group name before we delete it 
    968             $group_name=  $this->theme->groups[$this->handler_vars['group']]; 
    969             if ( UserGroup::remove_group( intval($this->handler_vars['group'] ) ) ) { 
    970                 Session::notice( sprintf( _t('Removed group %s'), $group_name ) ); 
     1100            $name= $this->handler_vars['group']; 
     1101            if ( !UserGroup::exists($name) ) { 
     1102                Session::notice( sprintf(_t( 'The group %s does not exist'), $name ) ); 
     1103            } 
     1104            else { 
     1105                $group= UserGroup::get($name); 
     1106                $group->delete(); 
     1107                Session::notice( sprintf( _t( 'Removed group %s' ), $name ) ); 
    9711108                // reload the groups 
    972                 $this->theme->groups= UserGroup::all_groups(); 
    973             } 
    974         } 
    975  
    976         if ( isset( $this->handler_vars['add_user'] ) ) { 
    977             UserGroup::add_user( $this->handler_vars['group'], $this->handler_vars['add_user'] ); 
    978             $this->theme->groups= UserGroup::all_groups(); 
    979         } 
    980  
    981         if ( isset( $this->handler_vars['remove_user'] ) ) { 
    982             UserGroup::remove_user( $this->handler_vars['user_group'], $this->handler_vars['remove_user'] ); 
    983             $this->theme->groups= UserGroup::all_groups(); 
     1109                $this->theme->groups= UserGroups::get_all(); 
     1110            } 
    9841111        } 
    9851112 
    9861113        if ( isset( $this->handler_vars['edit_group'] ) ) { 
    987             $this->theme->group= $this->handler_vars['group']; 
    988             $this->theme->group_members= UserGroup::members( $this->theme->group ); 
    989             $all_users= Users::get_all(); 
    990             $users= array(); 
    991             foreach ($all_users as $user) { 
    992                 if ( ! in_array( $user->id,  $this->theme->group_members ) ) { 
    993                     $users[$user->id]= $user->username; 
    994                 } 
    995             } 
    996             $this->theme->users= $users; 
    997         } 
     1114            $name= $this->handler_vars['group']; 
     1115            if ( !UserGroup::exists($name) ) { 
     1116                Session::notice( sprintf(_t( 'The group %s does not exist'), $name ) ); 
     1117            } 
     1118            else { 
     1119                $group= UserGroup::get($name); 
     1120                $this->theme->group_edit= $group; 
     1121                $this->theme->members= $group->members; 
     1122                $this->theme->users= Users::get_all(); 
     1123                $this->theme->permissions= ACL::all_permissions( 'description' ); 
     1124                $this->theme->permissions_granted= $group->granted; 
     1125                $this->theme->permissions_denied= $group->denied; 
     1126            } 
     1127        } 
     1128 
     1129        if ( isset( $this->handler_vars['users'] ) ) { 
     1130            $name= $this->handler_vars['group']; 
     1131            if ( ! UserGroup::exists($name) ) { 
     1132                Session::notice( sprintf(_t( 'The group %s does not exist'), $name ) ); 
     1133            } 
     1134            else { 
     1135                $group= UserGroup::get($name); 
     1136                $add_users= array(); 
     1137                $remove_users= array(); 
     1138                $form_users= array(); 
     1139                if ( isset( $this->handler_vars['user_id'] ) ) { 
     1140                    $form_users= $this->handler_vars['user_id']; 
     1141                } 
     1142                foreach ( Users::get_all() as $user ) { 
     1143                    if ( in_array( $user->id, $form_users ) ) { 
     1144                        $add_users[]= (int) $user->id; 
     1145                    } else { 
     1146                        $remove_users[]= (int) $user->id; 
     1147                    } 
     1148                } 
     1149                if ( ! empty( $add_users ) ) { 
     1150                    $group->add( $add_users ); 
     1151                } 
     1152                if ( ! empty( $remove_users ) ) { 
     1153                    $group->remove( $remove_users ); 
     1154                } 
     1155                $group->update(); 
     1156                Session::notice( sprintf(_t( 'Modified membership of group %s'), $name ) ); 
     1157                // reload the groups 
     1158                $this->theme->groups= UserGroups::get_all(); 
     1159            } 
     1160        } 
     1161 
     1162        if ( isset( $this->handler_vars['permissions'] ) ) { 
     1163            $group_name= $this->handler_vars['group']; 
     1164            if ( !UserGroup::exists( $group_name ) ) { 
     1165                Session::notice( sprintf(_t( 'The group %s does not exist'), $name ) ); 
     1166            } 
     1167            else { 
     1168                $grant= array(); 
     1169                $deny= array(); 
     1170                $revoke= array(); 
     1171                if ( isset( $this->handler_vars['grant'] ) ) { 
     1172                    $form_grant= $this->handler_vars['grant']; 
     1173                } 
     1174                else { 
     1175                    $form_grant= array(); 
     1176                } 
     1177                if ( isset( $this->handler_vars['deny'] ) ) { 
     1178                    $form_deny= $this->handler_vars['deny']; 
     1179                } 
     1180                else { 
     1181                    $form_deny= array(); 
     1182                } 
     1183                $group= UserGroup::get( $group_name ); 
     1184                foreach( ACL::all_permissions() as $permission ) { 
     1185                    if ( in_array( $permission->id, $form_grant ) ) { 
     1186                        $grant[]= (int) $permission->id; 
     1187                    } 
     1188                    elseif ( in_array( $permission->id, $form_deny ) ) { 
     1189                        $deny[]= (int) $permission->id; 
     1190                    } 
     1191                    else { 
     1192                        $revoke[]= (int) $permission->id; 
     1193                    } 
     1194                } 
     1195                if ( ! empty( $grant ) ){ 
     1196                    $group->grant( $grant ); 
     1197                } 
     1198                if ( ! empty( $deny ) ) { 
     1199                    $group->deny( $deny ); 
     1200                } 
     1201                if ( ! empty( $revoke ) ) { 
     1202                    $group->revoke( $revoke ); 
     1203                } 
     1204                $group->update(); 
     1205                Session::notice( sprintf(_t( 'Granted the permission to group %s'), $group_name ) ); 
     1206                // reload the groups 
     1207                $this->theme->groups= UserGroups::get_all(); 
     1208            } 
     1209        } 
     1210 
    9981211        $this->display( 'groups' ); 
    9991212    } 
     
    10781291    public function ajax_media( $handler_vars ) 
    10791292    { 
    1080         $path = $handler_vars['path']; 
    1081         $rpath = $path; 
    1082         $silo = Media::get_silo($rpath, true);  // get_silo sets $rpath by reference to the path inside the silo 
    1083         $assets = Media::dir($path); 
    1084         $output = array( 
     1293        $path= $handler_vars['path']; 
     1294        $rpath= $path; 
     1295        $silo= Media::get_silo( $rpath, true );  // get_silo sets $rpath by reference to the path inside the silo 
     1296        $assets= Media::dir( $path ); 
     1297        $output= array( 
    10851298            'ok' => 1, 
    10861299            'dirs' => array(), 
     
    10881301            'path' => $path, 
    10891302        ); 
    1090         foreach($assets as $asset) { 
    1091             if($asset->is_dir) { 
    1092                 $output['dirs'][$asset->basename] = $asset->get_props(); 
     1303        foreach ( $assets as $asset ) { 
     1304            if ( $asset->is_dir ) { 
     1305                $output['dirs'][$asset->basename]= $asset->get_props(); 
    10931306            } 
    10941307            else { 
    1095                 $output['files'][$asset->basename] = $asset->get_props(); 
    1096             } 
    1097         } 
    1098         $controls = array(); 
    1099         $controls = Plugins::filter('media_controls', $controls, $silo, $rpath, ''); 
    1100         $output['controls'] = '<li>' . implode('</li><li>', $controls) . '</li>'; 
    1101  
    1102         echo json_encode($output); 
     1308                $output['files'][$asset->basename]= $asset->get_props(); 
     1309            } 
     1310        } 
     1311        $controls= array(); 
     1312        $controls= Plugins::filter( 'media_controls', $controls, $silo, $rpath, '' ); 
     1313        $output['controls']= '<li>' . implode( '</li><li>', $controls ) . '</li>'; 
     1314 
     1315        echo json_encode( $output ); 
    11031316    } 
    11041317 
    11051318    public function ajax_media_panel( $handler_vars ) 
    11061319    { 
    1107         $path = $handler_vars['path']; 
    1108         $panelname = $handler_vars['panel']; 
    1109         $rpath = $path; 
    1110         $silo = Media::get_silo($rpath, true);  // get_silo sets $rpath by reference to the path inside the silo 
    1111  
    1112         $panel = ''; 
    1113         $panel = Plugins::filter('media_panels', $panel, $silo, $rpath, $panelname); 
    1114         $controls = array(); 
    1115         $controls = Plugins::filter('media_controls', $controls, $silo, $rpath, $panelname); 
    1116         $controls = '<li>' . implode('</li><li>', $controls) . '</li>'; 
    1117         $output = array( 
     1320        $path= $handler_vars['path']; 
     1321        $panelname= $handler_vars['panel']; 
     1322        $rpath= $path; 
     1323        $silo= Media::get_silo( $rpath, true );  // get_silo sets $rpath by reference to the path inside the silo 
     1324 
     1325        $panel= ''; 
     1326        $panel= Plugins::filter( 'media_panels', $panel, $silo, $rpath, $panelname ); 
     1327        $controls= array(); 
     1328        $controls= Plugins::filter( 'media_controls', $controls, $silo, $rpath, $panelname ); 
     1329        $controls= '<li>' . implode( '</li><li>', $controls ) . '</li>'; 
     1330        $output= array( 
    11181331            'controls' => $controls, 
    11191332            'panel' => $panel, 
    11201333        ); 
    11211334 
    1122         header('content-type:text/javascript'); 
    1123         echo json_encode($output); 
     1335        header( 'content-type:text/javascript' ); 
     1336        echo json_encode( $output ); 
    11241337    } 
    11251338 
  • branches/111307-atom/system/classes/atomhandler.php

    r1292 r1440  
    11<?php 
    22/** 
    3     * Habari AtomHandler class 
    4     * Produces Atom feeds and accepts Atom Publishing Protocol input     
    5     *  
    6     * @package Habari 
    7     * @todo Apply system error handling      
    8     */ 
    9      
     3 * Habari AtomHandler class 
     4 * Produces Atom feeds and accepts Atom Publishing Protocol input 
     5 * 
     6 * @package Habari 
     7 * @todo Apply system error handling 
     8 */ 
     9 
    1010class AtomHandler extends ActionHandler 
    1111{ 
    12      
     12 
    1313    public $user= NULL; // Cache the username 
    1414 
     
    1919    public function __construct() 
    2020    { 
    21         Plugins::act('init_atom'); 
     21        Plugins::act( 'init_atom' ); 
    2222        /** 
    2323        * The following Format::apply calls should be moved into a plugin that is 
     
    3333        */ 
    3434        if ( !$this->is_auth() ) { 
    35             Format::apply('autop', 'post_content_atom'); 
    36         } 
    37     } 
    38      
    39     /** 
    40         * Check if a user is authenticated for Atom editing 
    41         *  
    42         * @todo This entire funciton should be put into the User class somehow. 
    43         * @todo X-WSSE 
    44         * @param bool $force Force authorization? If so, basic HTTP_AUTH is displayed if not authed 
    45         * @return User The logged-in user 
    46         */ 
     35            Format::apply( 'autop', 'post_content_atom' ); 
     36        } 
     37    } 
     38 
     39    /** 
     40     * Check if a user is authenticated for Atom editing 
     41     * 
     42     * @todo This entire function should be put into the User class somehow. 
     43     * @todo X-WSSE 
     44     * @param bool $force Force authorization? If so, basic HTTP_AUTH is displayed if not authed 
     45     * @return User The logged-in user 
     46     */ 
    4747    function is_auth( $force= FALSE ) 
    4848    { 
    49         try { 
    50             if ( ( $this->user == NULL ) || ( $force != FALSE ) ) {          
    51                 // If running PHP as CGI, extract/decode the credentials from $_GET['HTTP_AUTHORIZATION'] 
    52                 // During installation, we add a special rule to pass the credentials via a GET request. 
    53                 if ( isset( $_GET['HTTP_AUTHORIZATION'] ) ) { 
    54                     list( $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'] )= explode( ':', base64_decode( substr( $_GET['HTTP_AUTHORIZATION'], 6 ) ) ); 
    55                 } 
    56                  
    57                 if ( isset( $_SERVER['PHP_AUTH_USER'] ) ) { 
    58                     User::authenticate( $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'] ); 
    59                 } 
    60                  
    61                 if ( ( $force != FALSE ) && ( !$this->user = User::identify() ) ) { 
    62                     header( 'HTTP/1.1 401 Unauthorized' ); 
    63                     header( 'Status: 401 Unauthorized' ); 
    64                     header( 'WWW-Authenticate: Basic realm="Habari"' ); 
    65                     die(); 
    66                 } 
    67             } 
    68              
    69             return $this->user; 
    70         } 
    71         catch (Exception $e) { 
    72         print 'Caught exception: ' .  $e->getMessage() . "\n"; 
    73         } 
    74     } 
    75      
    76     /** 
    77         * Handle incoming requests for Atom entry collections 
    78         */ 
     49        if ( ( $this->user == NULL ) || ( $force != FALSE ) ) { 
     50            if ( isset( $_SERVER['PHP_AUTH_USER'] ) ) { 
     51                User::authenticate( $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'] ); 
     52            } 
     53 
     54            if ( ( $force != FALSE ) && ( !$this->user= User::identify() ) ) { 
     55                header( 'HTTP/1.1 401 Unauthorized' ); 
     56                header( 'Status: 401 Unauthorized' ); 
     57                header( 'WWW-Authenticate: Basic realm="Habari"' ); 
     58                die(); 
     59            } 
     60        } 
     61 
     62        return $this->user; 
     63    } 
     64 
     65    /** 
     66     * Handle incoming requests for Atom entry collections 
     67     */ 
    7968    public function act_collection() 
    8069    { 
     
    9079 
    9180    /** 
    92         * function act_entry 
    93         * 'index' should be 'slug' 
    94         */ 
     81     * function act_entry 
     82     * 'index' should be 'slug' 
     83     */ 
    9584    public function act_entry() 
    9685    { 
     
    10796        } 
    10897    } 
    109          
    110     /** 
    111         * Handle incoming requests for RSD 
    112         *  
    113         * @todo Move the internal list of supported feeds into options to allow dynamic editing of capabilities                  
    114         */ 
     98 
     99    /** 
     100     * Handle incoming requests for RSD 
     101     * 
     102     * @todo Move the internal list of supported feeds into options to allow dynamic editing of capabilities 
     103     */ 
    115104    public function act_rsd() 
    116105    { 
    117         try { 
    118             /** 
    119                 * List of APIs supported by the RSD 
    120                 * Refer to namespace for required elements/attributes. 
    121                 */ 
    122             $apis_list= array( 
    123                 'Atom' => array( 
    124                     'preferred' => 'true', 
    125                     'apiLink' => URL::get( 'collection', 'index=1' ), // This should be the XML-RPC url 
    126                     'blogID' => '', 
    127                 ), 
    128             ); 
    129              
    130             $apis_list= Plugins::filter('rsd_api_list', $apis_list); 
    131                      
     106        /** 
     107         * List of APIs supported by the RSD 
     108         * Refer to namespace for required elements/attributes. 
     109         */ 
     110        $apis_list= array( 
     111            'Atom' => array( 
     112                'preferred' => 'true', 
     113                'apiLink' => URL::get( 'atom_feed', 'index=1' ), // This should be the XML-RPC url 
     114                'blogID' => '', 
     115            ), 
     116        ); 
     117 
     118        $apis_list= Plugins::filter( 'rsd_api_list', $apis_list ); 
     119 
     120        if ( Cache::has( 'atom:rsd:apis' ) ) { 
     121            $cache_apis= Cache::get( 'atom:rsd:apis' ); 
     122            if ( ( $cache_apis === $apis_list ) && Cache::has( 'atom:rsd:xml' ) ) { 
     123                $cache_xml= Cache::get( 'atom:rsd:xml' ); 
     124                $cache_xml= simplexml_load_string( $cache_xml ); 
     125            } 
     126        } 
     127        else { 
     128            Cache::set( 'atom:rsd:apis', $apis_list ); 
     129        } 
     130 
     131        if ( $cache_xml instanceOf SimpleXMLElement ) { 
     132            $xml= $cache_xml; 
     133        } 
     134        else { 
    132135            $xml= new SimpleXMLElement( '<rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd"></rsd>' ); 
    133              
     136 
    134137            $rsd_service= $xml->addChild( 'service' ); 
    135138            $service_engineName= $rsd_service->addChild( 'engineName', 'Habari' ); 
    136139            $service_engineLink= $rsd_service->addChild( 'engineLink', 'http://www.habariproject.org/' ); 
    137             $service_homePageLink= $rsd_service->addChild( 'homePageLink', Site::get_url('habari') ); 
     140            $service_homePageLink= $rsd_service->addChild( 'homePageLink', Site::get_url( 'habari' ) ); 
    138141            $service_apis= $rsd_service->addChild( 'apis' ); 
    139              
     142 
    140143            if ( !isset( $apis_list ) || ( count( $apis_list ) < 1 ) ) { 
    141144                return false; 
    142145            } 
    143              
     146 
    144147            foreach ( $apis_list as $apiName => $atts ) { 
    145148                if ( !isset( $atts['preferred'], $atts['apiLink'], $atts['blogID'] ) ) { 
    146149                    continue; 
    147150                } 
    148                  
     151 
    149152                $apis_api= $service_apis->addChild( 'api' ); 
    150153                $apis_api->addAttribute( 'name', $apiName ); 
     
    152155                $apis_api->addAttribute( 'apiLink', $atts['apiLink'] ); 
    153156                $apis_api->addAttribute( 'blogID', $atts['blogID'] ); 
    154                              
     157 
    155158                if ( !isset( $atts['settings'] ) || ( count( $atts['settings'] ) < 1 ) ) { 
    156159                    continue; 
    157160                } 
    158                              
     161 
    159162                $api_settings= $apis_api->addChild( 'settings' ); 
    160      
     163 
    161164                foreach ( $atts['settings'] as $settingName => $settingValue ) { 
    162165                    switch ( $settingName ) { 
     
    171174                            } 
    172175                            break; 
    173                     }                        
     176                    } 
    174177                } 
    175             }  
    176              
    177             $xml= Plugins::filter( 'rsd', $xml, $this->handler_vars ); 
    178             $xml= $xml->asXML(); 
    179              
    180             ob_clean(); 
    181             header( 'Content-Type: application/rsd+xml' ); 
    182             print $xml; 
    183         } 
    184         catch (Exception $e) { 
    185         print 'Caught exception: ' .  $e->getMessage() . "\n"; 
    186         } 
    187     } 
    188      
    189     /** 
    190         * Handle incoming requests for the introspection document 
    191         */ 
     178            } 
     179 
     180            Cache::set( 'atom:rsd:xml', $xml->asXML() ); 
     181        } 
     182 
     183        $xml= Plugins::filter( 'rsd', $xml, $this->handler_vars ); 
     184        $xml= $xml->asXML(); 
     185 
     186        ob_clean(); 
     187        header( 'Content-Type: application/rsd+xml' ); 
     188        print $xml; 
     189    } 
     190 
     191    /** 
     192     * Handle incoming requests for the introspection document 
     193     */ 
    192194    public function act_introspection() 
    193195    { 
    194         try { 
     196        if ( Cache::has( 'atom:introspection:xml' ) ) { 
     197            $cache_xml= Cache::get( 'atom:introspection:xml' ); 
     198            $cache_xml= simplexml_load_string( $cache_xml ); 
     199        } 
     200 
     201        if ( $cache_xml instanceOf SimpleXMLElement ) { 
     202            $xml= $cache_xml; 
     203        } 
     204        else { 
    195205            $xml= new SimpleXMLElement( '<service xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom"></service>' ); 
    196              
     206 
    197207            $service_workspace= $xml->addChild( 'workspace' ); 
    198              
    199             $workspace_title= $service_workspace->addChild( 'atom:title', Options::get( 'title' ), 'http://www.w3.org/2005/Atom' ); 
    200              
     208 
     209            $workspace_title= $service_workspace->addChild( 'atom:title', htmlspecialchars( Options::get( 'title' ) ), 'http://www.w3.org/2005/Atom' ); 
     210 
    201211            $workspace_collection= $service_workspace->addChild( 'collection' ); 
    202             $workspace_collection->addAttribute( 'href', URL::get( 'collection', 'index=1' ) ); 
    203              
     212            $workspace_collection->addAttribute( 'href', URL::get( 'atom_feed', 'index=1' ) ); 
     213 
    204214            $collection_title= $workspace_collection->addChild( 'atom:title', 'Blog Entries', 'http://www.w3.org/2005/Atom' ); 
    205215            $collection_accept= $workspace_collection->addChild( 'accept', 'application/atom+xml;type=entry' ); 
    206              
    207             $xml= Plugins::filter( 'atom_introspection', $xml, $this->handler_vars ); 
     216 
     217            Cache::set( 'atom:introspection:xml', $xml->asXML() ); 
     218        } 
     219 
     220        $xml= Plugins::filter( 'atom_introspection', $xml, $this->handler_vars ); 
     221        $xml= $xml->asXML(); 
     222 
     223        ob_clean(); 
     224        header( 'Content-Type: application/atomsvc+xml' ); 
     225        print $xml; 
     226    } 
     227 
     228    /** 
     229     * Handle incoming requests for the Atom entry collection for a specific tag 
     230     */ 
     231    public function act_tag_collection() 
     232    { 
     233        $this->get_collection(); 
     234    } 
     235 
     236    /** 
     237     * Handle incoming requests for the Atom entry collection for all comments 
     238     */ 
     239    function act_comments( $params= array() ) 
     240    { 
     241        $this->get_comments( $params ); 
     242    } 
     243 
     244    /** 
     245     * Handle incoming requests for the Atom entry collection for comments on an entry 
     246     */ 
     247    function act_entry_comments() 
     248    { 
     249        if ( isset( $this->handler_vars['slug'] ) ) { 
     250            $this->act_comments( array( 'slug' => $this->handler_vars['slug'] ) ); 
     251        } 
     252        else { 
     253            $this->act_comments( array( 'id' => $this->handler_vars['id'] ) ); 
     254        } 
     255    } 
     256 
     257    /** 
     258     * Output an Atom collection of comments based on the supplied parameters. 
     259     * 
     260     * @param array $params An array of parameters passed to Comments::get() to retrieve comments 
     261     */ 
     262    function get_comments( $params= array() ) 
     263    { 
     264        $params['status']= Post::status( 'published' ); 
     265 
     266        $xml= new SimpleXMLElement( '<feed xmlns="http://www.w3.org/2005/Atom"></feed>' ); 
     267 
     268        $feed_title= $xml->addChild( 'title', htmlspecialchars( Options::get( 'title' ) ) ); 
     269 
     270        if ( $tagline= Options::get( 'tagline' ) ) { 
     271            $feed_subtitle= $xml->addChild( 'subtitle', htmlspecialchars( $tagline ) ); 
     272        } 
     273 
     274        $feed_updated= $xml->addChild( 'updated', date( 'c', time() ) ); 
     275 
     276        $feed_link= $xml->addChild( 'link' ); 
     277        $feed_link->addAttribute( 'rel', 'alternate' ); 
     278        $feed_link->addAttribute( 'href', URL::get( 'atom_feed_comments' ) ); 
     279 
     280        $feed_link= $xml->addChild( 'link' ); 
     281        $feed_link->addAttribute( 'rel', 'self' ); 
     282 
     283        if ( isset( $params['slug'] ) ) { 
     284            $feed_link->addAttribute( 'href', URL::get( 'atom_feed_entry_comments', 'slug=' . $params['slug'] ) ); 
     285        } 
     286        else { 
     287            $feed_link->addAttribute( 'href', URL::get( 'atom_feed_comments' ) ); 
     288        } 
     289 
     290        $feed_generator= $xml->addChild( 'generator', 'Habari' ); 
     291        $feed_generator->addAttribute( 'uri', 'http://www.habariproject.org/' ); 
     292        $feed_generator->addAttribute( 'version', Version::get_habariversion() ); 
     293 
     294        $feed_id= $xml->addChild( 'id', 'tag:' . Site::get_url( 'hostname' ) . ',' . date( "Y-m-d" ) . ':' . ( ( isset( $params['slug'] ) ) ? $params['slug'] : 'atom_comments' ) . '/' . Options::get( 'GUID' ) ); 
     295 
     296        foreach ( Posts::get( $params ) as $post ) { 
     297 
     298            foreach ( $post->comments->approved as $comment ) { 
     299                $user= User::get_by_id( $post->user_id ); 
     300                $title= ( $this->is_auth() ) ? htmlspecialchars( $post->title ) : htmlspecialchars( $post->title_atom ); 
     301                $content= ( $this->is_auth() ) ? htmlspecialchars( $comment->content ) : htmlspecialchars( $comment->content_atom ); 
     302 
     303                $feed_entry= $xml->addChild( 'entry' ); 
     304                $entry_title= $feed_entry->addChild( 'title', 'Comment on ' . $title . ' by ' . $comment->name ); 
     305 
     306                $entry_link= $feed_entry->addChild( 'link' ); 
     307                $entry_link->addAttribute( 'rel', 'alternate' ); 
     308                $entry_link->addAttribute( 'href', $post->permalink . '#comment-' . $comment->id ); 
     309 
     310                $entry_author= $feed_entry->addChild( 'author' ); 
     311                $author_name= $entry_author->addChild( 'name', $comment->name ); 
     312 
     313                $entry_id= $feed_entry->addChild( 'id', $post->guid . '/' . $comment->id ); 
     314 
     315                $entry_updated= $feed_entry->addChild( 'updated', date( 'c', strtotime( $comment->date ) ) ); 
     316 
     317                $entry_content= $feed_entry->addChild( 'content', $content ); 
     318                $entry_content->addAttribute( 'type', 'html' ); 
     319            } 
     320        } 
     321 
     322        $xml= Plugins::filter( 'atom_get_comments', $xml, $params, $this->handler_vars ); 
     323        $xml= $xml->asXML(); 
     324 
     325        ob_clean(); 
     326        header( 'Content-Type: application/atom+xml' ); 
     327        print $xml; 
     328    } 
     329 
     330    /** 
     331     * Output the Atom entry for a specific slug 
     332     * 
     333     * @param string $slug The slug to get the entry for 
     334     */ 
     335    public function get_entry( $slug ) 
     336    { 
     337        $params['slug']= $slug; 
     338        $params['status']= Post::status( 'published' ); 
     339 
     340        if ( $post= Post::get( $params ) ) { 
     341            $user= User::get_by_id( $post->user_id ); 
     342            $title= ( $this->is_auth() ) ? htmlspecialchars( $post->title ) : htmlspecialchars( $post->title_atom ); 
     343            $content= ( $this->is_auth() ) ? htmlspecialchars( $post->content ) : htmlspecialchars( $post->content_atom ); 
     344 
     345            $xml= new SimpleXMLElement( '<entry xmlns="http://www.w3.org/2005/Atom"></entry>' ); 
     346            $entry_title= $xml->addChild( 'title', $title ); 
     347 
     348            $entry_author= $xml->addChild( 'author' ); 
     349            $author_name= $entry_author->addChild( 'name', $user->username ); 
     350 
     351            $entry_link= $xml->addChild( 'link' ); 
     352            $entry_link->addAttribute( 'rel', 'alternate' ); 
     353            $entry_link->addAttribute( 'href', $post->permalink ); 
     354 
     355            $entry_link= $xml->addChild( 'link' ); 
     356            $entry_link->addAttribute( 'rel', 'edit' ); 
     357            $entry_link->addAttribute( 'href', URL::get( 'atom_entry', "slug={$post->slug}" ) ); 
     358 
     359            $entry_id= $xml->addChild( 'id', $post->guid ); 
     360            $entry_updated= $xml->addChild( 'updated', date( 'c', strtotime( $post->updated ) ) ); 
     361            $entry_published= $xml->addChild( 'published', date( 'c', strtotime( $post->pubdate ) ) ); 
     362 
     363            $entry_content= $xml->addChild( 'content', $content ); 
     364            $entry_content->addAttribute( 'type', 'html' ); 
     365 
     366            $xml= Plugins::filter( 'atom_get_entry', $xml, $slug, $this->handler_vars ); 
    208367            $xml= $xml->asXML(); 
    209              
    210             ob_clean(); 
    211             header( 'Content-Type: application/atomsvc+xml' ); 
    212             print $xml; 
    213         } 
    214         catch (Exception $e) { 
    215         print 'Caught exception: ' .  $e->getMessage() . "\n"; 
    216         } 
    217     } 
    218      
    219     /** 
    220         * Handle incoming requests for the Atom entry collection for a specific tag 
    221         */   
    222     public function act_tag_collection() 
    223     { 
    224         $this->get_collection(); 
    225     } 
    226      
    227     /** 
    228         * Handle incoming requests for the Atom entry collection for all comments 
    229         */ 
    230     function act_comments( $params= array() ) 
    231     { 
    232         $this->get_comments( $params ); 
    233     } 
    234      
    235     /** 
    236         * Handle incoming requests for the Atom entry collection for comments on an entry 
    237         */ 
    238     function act_entry_comments() 
    239     { 
    240         $this->act_comments( array( 'slug' => $this->handler_vars['slug'] ) ); 
    241     } 
    242      
    243     /** 
    244         * Output an Atom collection of comments based on the supplied parameters. 
    245         *  
    246         * @param array $params An array of parameters passed to Comments::get() to retrieve comments                 
    247         */ 
    248     function get_comments( $params= array() ) 
    249     { 
    250         try { 
    251             $params['status'] = Post::status('published'); 
    252  
    253             $xml= new SimpleXMLElement( '<feed xmlns="http://www.w3.org/2005/Atom"></feed>' ); 
    254              
    255             $feed_title= $xml->addChild( 'title', Options::get( 'title' ) ); 
    256              
    257             if ( $tagline= Options::get( 'tagline' ) ) 
    258             { 
    259                 $feed_subtitle= $xml->addChild( 'subtitle', $tagline ); 
    260             } 
    261              
    262             $feed_updated= $xml->addChild( 'updated', date( 'c', time() ) ); 
    263              
    264             $feed_link= $xml->addChild( 'link' ); 
    265             $feed_link->addAttribute( 'rel', 'alternate' ); 
    266             $feed_link->addAttribute( 'href', URL::get( 'comments' ) ); 
    267              
    268             $feed_link= $xml->addChild( 'link' ); 
    269             $feed_link->addAttribute( 'rel', 'self' ); 
    270              
    271             if ( isset( $params['slug'] ) ) { 
    272                 $feed_link->addAttribute( 'href', URL::get( 'entry_comments', 'slug=' . $params['slug'] ) ); 
    273             } 
    274             else { 
    275                 $feed_link->addAttribute( 'href', URL::get( 'comments' ) ); 
    276             } 
    277                  
    278             $feed_generator= $xml->addChild( 'generator', 'Habari' ); 
    279             $feed_generator->addAttribute( 'uri', 'http://www.habariproject.org/' ); 
    280             $feed_generator->addAttribute( 'version', Options::get( 'version' ) ); 
    281              
    282             $feed_id= $xml->addChild( 'id', 'tag:' . Site::get_url('hostname') . ',' . date("Y-m-d") . ':' . ( ( isset( $params['slug'] ) ) ? $params['slug'] : 'atom_comments' ) . '/' . Options::get( 'GUID' ) ); 
    283  
    284             foreach ( Posts::get( $params ) as $post ) { 
    285                  
    286                 foreach ( $post->comments->approved as $comment ) { 
    287                     $user= User::get_by_id( $post->user_id ); 
    288                     $title= ( $this->is_auth() ) ? htmlspecialchars( $post->title ) : htmlspecialchars( $post->title_atom ); 
    289                     $content= ( $this->is_auth() ) ? htmlspecialchars( $comment->content ) : htmlspecialchars( $comment->content_atom ); 
    290                  
    291                     $feed_entry= $xml->addChild( 'entry' ); 
    292                     $entry_title= $feed_entry->addChild( 'title', 'Comment on ' . $title . ' by ' . $comment->name ); 
    293                      
    294                     $entry_link= $feed_entry->addChild( 'link' ); 
    295                     $entry_link->addAttribute( 'rel', 'alternate' ); 
    296                     $entry_link->addAttribute( 'href', $post->permalink . '#comment-' . $comment->id ); 
    297                          
    298                     $entry_author= $feed_entry->addChild( 'author' ); 
    299                     $author_name= $entry_author->addChild( 'name', $comment->name ); 
    300                      
    301                     $entry_id= $feed_entry->addChild( 'id', $post->guid . '/' . $comment->id ); 
    302                      
    303                     $entry_updated= $feed_entry->addChild( 'updated', date( 'c', strtotime( $comment->date ) ) ); 
    304                      
    305                     $entry_content= $feed_entry->addChild( 'content', $content ); 
    306                     $entry_content->addAttribute( 'type', 'html' ); 
    307                 } 
    308             } 
    309              
    310             $xml= Plugins::filter( 'atom_get_comments', $xml, $params, $this->handler_vars ); 
    311             $xml= $xml->asXML(); 
    312      
     368 
    313369            ob_clean(); 
    314370            header( 'Content-Type: application/atom+xml' ); 
    315371            print $xml; 
    316372        } 
    317         catch (Exception $e) { 
    318         print 'Caught exception: ' .  $e->getMessage() . "\n"; 
    319         } 
    320     } 
    321              
    322     /** 
    323         * Output the Atom entry for a specific slug 
    324         *  
    325         * @param string $slug The slug to get the entry for                  
    326         */ 
    327     public function get_entry( $slug ) 
    328     { 
    329         try 
    330         { 
    331             $params['slug']= $slug; 
    332             $params['status'] = Post::status('published'); 
    333              
    334             if ( $post = Post::get($params) ) { 
    335                 $user= User::get_by_id( $post->user_id ); 
    336                 $title= ( $this->is_auth() ) ? htmlspecialchars( $post->title ) : htmlspecialchars( $post->title_atom ); 
    337                 $content= ( $this->is_auth() ) ? htmlspecialchars( $post->content ) : htmlspecialchars( $post->content_atom ); 
    338                  
    339                 $xml= new SimpleXMLElement( '<entry xmlns="http://www.w3.org/2005/Atom"></entry>' ); 
    340                 $entry_title= $xml->addChild( 'title', $title ); 
    341                  
    342                 $entry_author= $xml->addChild( 'author' ); 
    343                 $author_name= $entry_author->addChild( 'name', $user->username ); 
    344                  
    345                 $entry_link= $xml->addChild( 'link' ); 
    346                 $entry_link->addAttribute( 'rel', 'alternate' ); 
    347                 $entry_link->addAttribute( 'href', $post->permalink ); 
    348                  
    349                 $entry_link= $xml->addChild( 'link' ); 
    350                 $entry_link->addAttribute( 'rel', 'edit' ); 
    351                 $entry_link->addAttribute( 'href', URL::get( 'entry', "slug={$post->slug}" ) ); 
    352                  
    353                 $entry_id= $xml->addChild( 'id', $post->guid ); 
    354                 $entry_updated= $xml->addChild( 'updated', date( 'c', strtotime( $post->updated ) ) ); 
    355                 $entry_published= $xml->addChild( 'published', date( 'c', strtotime( $post->pubdate ) ) ); 
    356                  
    357                 foreach ( $post->tags as $tag ) { 
    358                     $entry_category= $xml->addChild( 'category' ); 
    359                     $entry_category->addAttribute( 'term', $tag ); 
    360                 } 
    361                  
    362                 $entry_content= $xml->addChild( 'content', $content ); 
    363                 $entry_content->addAttribute( 'type', 'html' ); 
    364                  
    365                 $xml= Plugins::filter( 'atom_get_entry', $xml, $slug, $this->handler_vars ); 
    366                 $xml= $xml->asXML(); 
    367      
    368                 ob_clean(); 
    369                 header( 'Content-Type: application/atom+xml' ); 
    370                 print $xml; 
    371             } 
    372         } 
    373         catch (Exception $e) { 
    374         print 'Caught exception: ' .  $e->getMessage() . "\n"; 
    375         } 
    376     } 
    377      
    378     /** 
    379         * Updates (editing) a post entry that is sent via APP. 
    380         *  
    381         * @param string $slug The slug of the entry to save              
    382         */ 
     373    } 
     374 
     375    /** 
     376     * Updates (editing) a post entry that is sent via APP. 
     377     * 
     378     * @param string $slug The slug of the entry to save 
     379     */ 
    383380    public function put_entry( $slug ) 
    384381    { 
    385         try { 
    386             $params= array(); 
    387      
    388             $user= $this->is_auth( TRUE ); 
    389             $bxml= file_get_contents( 'php://input' ); 
    390              
    391             $params['slug']= $slug; 
    392             $params['status'] = Post::status('published'); 
    393             if ( $post = Post::get($params) ) { 
    394                 $xml = new SimpleXMLElement( $bxml ); 
    395                  
    396                 preg_match( '/<content type=[\'|"]\w*[\'|"]>(.*)<\/content>/is', $xml->content->asXML(), $content ); 
    397                 $xml->content= $content[1]; 
    398                 $xml= Plugins::filter( 'atom_put_entry', $xml, $slug, $this->handler_vars ); 
    399              
    400                 if ( (string) $xml->title != '' ) { 
    401                     $post->title= $xml->title; 
    402                 } 
    403                  
    404                 if ( (string) $xml->id != '' ) { 
    405                     $post->guid= $xml->id; 
    406                 } 
    407                  
    408                 if ( (string) $xml->content != '' ) { 
    409                     $post->content= (string) $xml->content; 
    410                 } 
    411                  
    412                 if ( (string) $xml->pubdate != '' ) { 
    413                     $post->pubdate= (string) $xml->pubdate; 
    414                 } 
    415                  
    416                 if ( isset( $_SERVER['HTTP_SLUG'] ) ) { 
    417                     $post->slug= $_SERVER['HTTP_SLUG']; 
    418                 } 
    419              
    420                 $post->status= Post::status('published'); 
    421                 $post->user_id= $user->id; 
    422                 $post->update(); 
    423             } 
    424         } 
    425         catch (Exception $e) { 
    426             print 'Caught exception: ' .  $e->getMessage() . "\n"; 
    427         } 
    428     } 
    429      
    430     /** 
    431         * Delete a post based on the HTTP DELETE request via Atom 
    432         *  
    433         * @param string $slug The post slug to delete                
    434         */ 
    435     public function delete_entry( $slug ) 
    436     { 
    437         try { 
    438             $params = array(); 
    439              
    440             $this->is_auth(); 
    441              
    442             $params['slug']= $slug; 
    443             $params['status'] = Post::status('published'); 
    444             if ( $post= Post::get($params) ) { 
    445                 $post->delete(); 
    446             } 
    447         } 
    448         catch (Exception $e) { 
    449             print 'Caught exception: ' .  $e->getMessage() . "\n"; 
    450         } 
    451     } 
    452      
    453     /** 
    454         *   Output a post collection based on the provided parameters. 
    455         *    
    456         * @param array $params An array of parameters as passed to Posts::get() to retrieve posts.               
    457         */ 
    458     public function get_collection( $params = array() ) 
    459     {    
    460         try { 
    461             // Assign alternate links based on the matched rule. 
    462             $alternate_rules= array(