Changeset 534


Ignore:
Timestamp:
Jul 27, 2015 7:56:08 AM (9 years ago)
Author:
anonymous
Message:

Improved module maker validation output. Allow disabling cache at run time for ACL. Added ACL getList() method. Improved ACL CLI listing. Fixed app boomerang array initialization. Now retaining identical boomerang URLs if the key is different. Added a maximum boomerang time. Added a way to disable cache per request through a query string. Added validator isDecimal() method. Added disableSelectOptions() HTML method. Added getGravatarURL() method. Change how navigation page array is managed. Updated navigation currentPage() method to test an array of URLs.

Location:
trunk
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/bin/acl.cli.php

    r533 r534  
    4444require_once CODEBASE_PATH . '/lib/ACL.inc.php';
    4545$acl =& ACL::getInstance();
    46 $acl->setParam(array('create_table' => false));
     46$acl->setParam(array(
     47    'create_table' => false,
     48    'enable_cache' => false,
     49));
    4750
    4851
     
    6568    case 'aco' :
    6669    case 'axo' :
    67         listObjects('root', $type);
     70        listObjects($type);
    6871        break;
    6972    case 'all' :
    70         listObjects('root', 'aro');
    71         listObjects('root', 'aco');
    72         listObjects('root', 'axo');
     73        listObjects('aro');
     74        listObjects('aco');
     75        listObjects('axo');
    7376        break;
    7477    case 'perms' :
     
    244247*
    245248* @access   public
     249* @param    string $type Table to call, one of: aro, aco, or axo.
    246250* @param    string $root Root node from which to begin calculating.
    247 * @param    string $type Table to call, one of: aro, aco, or axo.
    248251* @return   bool Returns false on error.
    249252* @author   Quinn Comendant <quinn@strangecode.com>
     
    251254* @since    17 Jun 2006 23:41:22
    252255*/
    253 function listObjects($root, $type)
     256function listObjects($type, $root=null)
    254257{
     258    global $acl;
     259
    255260    $app =& App::getInstance();
    256261    $db =& DB::getInstance();
    257262
    258     echo "\n";
    259 
    260263    switch ($type) {
    261264    case 'aro' :
    262         $tbl = 'aro_tbl';
    263         printf("%-45s %s\n", 'Request objects', 'Added');
     265        printf("\n%-45s %s\n", 'Request objects', 'Added');
    264266        break;
    265267    case 'aco' :
    266         $tbl = 'aco_tbl';
    267         printf("%-45s %s\n", 'Control objects', 'Added');
     268        printf("\n%-45s %s\n", 'Control objects', 'Added');
    268269        break;
    269270    case 'axo' :
    270         $tbl = 'axo_tbl';
    271         printf("%-45s %s\n", 'Xtra objects', 'Added');
     271        printf("\n%-45s %s\n", 'Xtra objects', 'Added');
    272272        break;
    273273    default :
    274274        $app->logMsg(sprintf('Invalid access object type: %s', $type), LOG_ERR, __FILE__, __LINE__);
    275275        return false;
    276         break;
    277276    }
    278277
    279278    echo "---------------------------------------------------------------------\n";
    280279
    281     // Retrieve the left and right value of the $root node.
    282     $qid = $db->query("SELECT lft, rgt FROM $tbl WHERE name = '" . $db->escapeString($root) . "'");
    283     list($lft, $rgt) = mysql_fetch_row($qid);
    284 
    285     $depth = array();
    286 
    287     // Retrieve all descendants of the root node
    288     $qid = $db->query("SELECT name, lft, rgt, added_datetime FROM $tbl WHERE lft BETWEEN $lft AND $rgt ORDER BY lft ASC");
    289     while (list($name, $lft, $rgt, $added_datetime) = mysql_fetch_row($qid)) {
    290         // If the last element of $depth is less than the current rgt it means we finished with a set of children nodes.
    291         while (sizeof($depth) > 0 && end($depth) < $rgt) {
    292             array_pop($depth);
    293         }
    294 
     280    foreach ($acl->getList($type, $root) as $o) {
    295281        // Display indented node title.
    296         printf("%-45s %s\n", str_repeat('    ', sizeof($depth)) . $name, date($app->getParam('date_format') . ' ' . $app->getParam('time_format'), strtotime($added_datetime)));
    297 
    298         // Add this node to the stack.
    299         $depth[] = $rgt;
    300     }
     282        printf("%-45s %s\n", str_repeat('    ', $o['depth']) . $o['name'], date($app->getParam('date_format') . ' ' . $app->getParam('time_format'), strtotime($o['added_datetime'])));
     283    }
     284
     285    echo "\n";
    301286}
    302287
  • trunk/bin/module_maker/validation.cli.php

    r533 r534  
    7373        $field = $col[0];
    7474        $title = ucfirst(str_replace('_', ' ', $field));
    75         $type = preg_replace('/^(\w+).*$/', '\\1', $col[1]);
     75        $type = preg_replace('/^(\w+).*$/', '$1', $col[1]);
     76        $max_dig = preg_replace('/^\w+\((\d+)(?:,\d+)?\).*$/', '$1', $col[1]);
     77        $max_dec = preg_replace('/^\w+\((?:\d+)(?:,(\d+))?\).*$/', '$1', $col[1]);
    7678        $is_primary_key = ('PRI' == $col[3]);
    7779        $unsigned = preg_match('/\s+unsigned\s*$/i', $col[1]);
     
    110112        case 'varchar' :
    111113            $len_type = 'string';
    112             $max_length = 255;
     114            $max_length = '' != $max_dig ? $max_dig : 255;
    113115            break;
    114116
     
    131133            break;
    132134
     135        case 'bit' :
     136            $len_type = 'num';
     137            $min = 0;
     138            $max = '' != $max_dig ? $max_dig : 64;
     139            break;
     140
    133141        case 'tinyint' :
    134         case 'bit' :
    135142        case 'bool' :
    136143            $len_type = 'num';
     
    191198        case 'float' :
    192199            $len_type = 'num';
    193             $min = -3.40282E+38;
    194             $max = 3.40282E+38;
     200            if ($unsigned) {
     201                $min = 0;
     202                $max = 3.40282E+38;
     203            } else {
     204                $min = -3.40282E+38;
     205                $max = 3.40282E+38;
     206            }
    195207            break;
    196208
    197209        case 'double' :
    198210        case 'double precision' :
     211            $len_type = 'num';
     212            if ($unsigned) {
     213                $min = 0;
     214                $max = 1.7976931348623157E+308;
     215            } else {
     216                $min = -1.7976931348623157E+308;
     217                $max = 1.7976931348623157E+308;
     218            }
     219            break;
     220
    199221        case 'real' :
    200222        case 'decimal' :
    201223        case 'dec' :
    202224        case 'numeric' :
    203             $len_type = 'num';
    204             $min = -1.79769E+308;
    205             $max = 1.79769E+308;
     225        case 'fixed' :
     226            $len_type = 'decimal'; // This doesn't match anything, on purpose.
    206227            break;
    207228
     
    255276
    256277        case 'float' :
    257         case 'float' :
    258278        case 'double' :
    259         case 'double' :
     279            $negative_ok = $unsigned ? '' : ', true';
     280            $o[] = "\$fv->isFloat('$field', sprintf(_(\"%s must be a valid number.\"), _(\"$title\"))$negative_ok);";
     281            break;
     282
    260283        case 'real' :
    261284        case 'decimal' :
    262285        case 'dec' :
    263286        case 'numeric' :
    264             $negative_ok = $unsigned ? '' : ', true';
    265             $o[] = "\$fv->isFloat('$field', sprintf(_(\"%s must be a valid number.\"), _(\"$title\"))$negative_ok);";
     287        case 'float' :
     288            $max = str_repeat('9', $max_dig - $max_dec);
     289            if ($max_dec > 0) {
     290                $max .= '.' . str_repeat('9', $max_dec);
     291            }
     292            if ($unsigned) {
     293                $negative_ok = 'false';
     294                $min = 0;
     295            } else {
     296                $negative_ok = 'true';
     297                $min = -$max;
     298            }
     299            $negative_ok = $unsigned ? 'false' : 'true';
     300            $o[] = "\$fv->isDecimal('$field', sprintf(_(\"%s must be a number between %d and %d.\"), _(\"$title\"), $min, $max), $negative_ok, $max_dig, $max_dec);";
    266301            break;
    267302
  • trunk/lib/ACL.inc.php

    r506 r534  
    6565        // Configure the cache object.
    6666        $this->cache = new Cache('acl');
    67         $this->cache->setParam(array('enabled' => true));
    6867
    6968        // Get create tables config from global context.
     
    101100
    102101        if (isset($params) && is_array($params)) {
     102            // Some params require special processing. Catch those in a loop and process individually.
     103            foreach ($params as $key => $val) {
     104                switch ($key) {
     105                case 'enable_cache':
     106                    $this->cache->setParam(array('enabled' => $val));
     107                    break;
     108                }
     109
     110            }
     111            unset($key, $value);
     112
    103113            // Merge new parameters with old overriding only those passed.
    104114            $this->_params = array_merge($this->_params, $params);
     
    675685
    676686        $cache_hash = $aro . '|' . $aco . '|' . $axo;
    677         if ($this->cache->exists($cache_hash) && true === $this->getParam('enable_cache')) {
     687        if (true === $this->getParam('enable_cache') && $this->cache->exists($cache_hash)) {
    678688            // Access value is cached.
    679689            $access = $this->cache->get($cache_hash);
     
    694704            if (!list($access) = mysql_fetch_row($qid)) {
    695705                $this->cache->set($cache_hash, 'deny');
    696                 $app->logMsg(sprintf('Access denied: %s -> %s -> %s (no records found).', $aro, $aco, $axo), LOG_DEBUG, __FILE__, __LINE__);
     706                $app->logMsg(sprintf('Access denied: %s -> %s -> %s (no records found).', $aro, $aco, $axo), LOG_WARNING, __FILE__, __LINE__);
    697707                return false;
    698708            }
     
    704714            return true;
    705715        } else {
    706             $app->logMsg(sprintf('Access denied: %s -> %s -> %s', $aro, $aco, $axo), LOG_DEBUG, __FILE__, __LINE__);
     716            $app->logMsg(sprintf('Access denied: %s -> %s -> %s', $aro, $aco, $axo), LOG_NOTICE, __FILE__, __LINE__);
    707717            return false;
    708718        }
     
    736746    }
    737747
     748    /*
     749    * Returns an array of the specified object type starting specified root.
     750    *
     751    * @access   public
     752    * @param    string $type Table to list, one of: aro, aco, or axo.
     753    * @param    string $root Root node from which to begin from.
     754    * @return   mixed        Returns a multidimensional array of objects, or false on error.
     755    * @author   Quinn Comendant <quinn@strangecode.com>
     756    * @version  1.0
     757    * @since    17 Jun 2006 23:41:22
     758    */
     759    function getList($type, $root=null)
     760    {
     761        $app =& App::getInstance();
     762        $db =& DB::getInstance();
     763
     764        switch ($type) {
     765        case 'aro' :
     766            $tbl = 'aro_tbl';
     767            break;
     768        case 'aco' :
     769            $tbl = 'aco_tbl';
     770            break;
     771        case 'axo' :
     772            $tbl = 'axo_tbl';
     773            break;
     774        default :
     775            $app->logMsg(sprintf('Invalid access object type: %s', $type), LOG_ERR, __FILE__, __LINE__);
     776            return false;
     777        }
     778
     779        // By default start with the 'root' node.
     780        $root = !isset($root) ? 'root' : $root;
     781
     782        // Retrieve the left and right value of the $root node.
     783        $qid = $db->query("SELECT lft, rgt FROM $tbl WHERE name = '" . $db->escapeString($root) . "'");
     784        list($lft, $rgt) = mysql_fetch_row($qid);
     785
     786        $results = array();
     787        $depth = array();
     788
     789        // Retrieve all descendants of the root node
     790        $qid = $db->query("SELECT name, lft, rgt, added_datetime FROM $tbl WHERE lft BETWEEN $lft AND $rgt ORDER BY lft ASC");
     791        while (list($name, $lft, $rgt, $added_datetime) = mysql_fetch_row($qid)) {
     792            // If the last element of $depth is less than the current rgt it means we finished with a set of children nodes.
     793            while (sizeof($depth) > 0 && end($depth) < $rgt) {
     794                array_pop($depth);
     795            }
     796
     797            $results[] = array(
     798                'name' => $name,
     799                'added_datetime' => $added_datetime,
     800                'depth' => sizeof($depth),
     801            );
     802
     803            // Add this node to the stack.
     804            $depth[] = $rgt;
     805        }
     806
     807        return $results;
     808    }
     809
    738810} // End class.
  • trunk/lib/App.inc.php

    r532 r534  
    416416                $_SESSION['_app'][$this->_ns] = array(
    417417                    'messages' => array(),
    418                     'boomerang' => array('url'),
     418                    'boomerang' => array('url' => array()),
    419419                );
    420420            }
     
    539539
    540540        if (!$this->running) {
    541             $this->logMsg(sprintf('Canceled method call %s, application not running.', __FUNCTION__), LOG_NOTICE, __FILE__, __LINE__);
     541            $this->logMsg(sprintf('Canceled %s, application not running.', __METHOD__), LOG_NOTICE, __FILE__, __LINE__);
    542542            return false;
    543543        }
    544544
    545545        if (!$this->getParam('enable_session')) {
    546             $this->logMsg(sprintf('Canceled method call %s, session not enabled.', __FUNCTION__), LOG_NOTICE, __FILE__, __LINE__);
     546            $this->logMsg(sprintf('Canceled %s, session not enabled.', ≠), LOG_NOTICE, __FILE__, __LINE__);
    547547            return false;
    548548        }
     
    609609    {
    610610        if (!$this->running) {
    611             $this->logMsg(sprintf('Canceled method call %s, application not running.', __FUNCTION__), LOG_NOTICE, __FILE__, __LINE__);
     611            $this->logMsg(sprintf('Canceled %s, application not running.', __METHOD__), LOG_NOTICE, __FILE__, __LINE__);
    612612            return false;
    613613        }
     
    625625    {
    626626        if (!$this->running) {
    627             $this->logMsg(sprintf('Canceled method call %s, application not running.', __FUNCTION__), LOG_NOTICE, __FILE__, __LINE__);
     627            $this->logMsg(sprintf('Canceled %s, application not running.', __METHOD__), LOG_NOTICE, __FILE__, __LINE__);
    628628            return false;
    629629        }
     
    647647
    648648        if (!$this->running) {
    649             $this->logMsg(sprintf('Canceled method call %s, application not running.', __FUNCTION__), LOG_NOTICE, __FILE__, __LINE__);
     649            $this->logMsg(sprintf('Canceled %s, application not running.', __METHOD__), LOG_NOTICE, __FILE__, __LINE__);
    650650            return false;
    651651        }
     
    968968    {
    969969        if (!$this->running) {
    970             $this->logMsg(sprintf('Canceled method call %s, application not running.', __FUNCTION__), LOG_NOTICE, __FILE__, __LINE__);
     970            $this->logMsg(sprintf('Canceled %s, application not running.', __METHOD__), LOG_NOTICE, __FILE__, __LINE__);
    971971            return false;
    972972        }
     
    10951095    {
    10961096        if (!$this->running) {
    1097             $this->logMsg(sprintf('Canceled method call %s, application not running.', __FUNCTION__), LOG_NOTICE, __FILE__, __LINE__);
     1097            $this->logMsg(sprintf('Canceled %s, application not running.', __METHOD__), LOG_NOTICE, __FILE__, __LINE__);
    10981098            return false;
    10991099        }
     
    12031203    *
    12041204    * @access   public
     1205    * @param    string  $user_submitted_csrf_token The user-submitted token to compare with the session token.
    12051206    * @param    string  $csrf_token     The token to compare with the session token.
    12061207    * @return   bool    True if the tokens match, false otherwise.
     
    12131214
    12141215        if (!$this->getParam('csrf_token_enabled')) {
    1215             $this->logMsg(sprintf('%s method called, but csrf_token_enabled=false', __FUNCTION__), LOG_ERR, __FILE__, __LINE__);
     1216            $this->logMsg(sprintf('%s called, but csrf_token_enabled=false', __METHOD__), LOG_ERR, __FILE__, __LINE__);
    12161217            return true;
    12171218        }
     
    12381239    *
    12391240    * @access   public
    1240     * @param    string  $user_submitted_csrf_token The user-submitted token to compare with the session token.
    12411241    * @param    string  $message    Optional message to display to the user (otherwise default message will display). Set to an empty string to display no message.
    12421242    * @param    int    $type    The type of message: MSG_NOTICE,
     
    12741274    {
    12751275        if (!$this->running) {
    1276             $this->logMsg(sprintf('Canceled method call %s, application not running.', __FUNCTION__), LOG_NOTICE, __FILE__, __LINE__);
     1276            $this->logMsg(sprintf('Canceled %s, application not running.', __METHOD__), LOG_NOTICE, __FILE__, __LINE__);
    12771277            return false;
    12781278        }
     
    13271327    {
    13281328        if (!$this->running) {
    1329             $this->logMsg(sprintf('Canceled method call %s, application not running.', __FUNCTION__), LOG_NOTICE, __FILE__, __LINE__);
     1329            $this->logMsg(sprintf('Canceled %s, application not running.', __METHOD__), LOG_NOTICE, __FILE__, __LINE__);
    13301330            return false;
    13311331        }
     
    13691369    {
    13701370        if (!$this->running) {
    1371             $this->logMsg(sprintf('Canceled method call %s, application not running.', __FUNCTION__), LOG_NOTICE, __FILE__, __LINE__);
     1371            $this->logMsg(sprintf('Canceled %s, application not running.', __METHOD__), LOG_NOTICE, __FILE__, __LINE__);
    13721372            return false;
    13731373        }
     
    13771377        if ('' != $url && is_string($url)) {
    13781378            // Delete any boomerang request keys in the query string (along with any trailing delimiters after the deletion).
    1379             $url = preg_replace(array('/([&?])boomerang=\w+[&?]?/', '/[&?]$/'), array('$1', ''), $url);
     1379            $url = preg_replace(array('/([&?])boomerang=[^&?]+[&?]?/', '/[&?]$/'), array('$1', ''), $url);
    13801380
    13811381            if (isset($_SESSION['_app'][$this->_ns]['boomerang']['url']) && is_array($_SESSION['_app'][$this->_ns]['boomerang']['url']) && !empty($_SESSION['_app'][$this->_ns]['boomerang']['url'])) {
    1382                 // If the URL currently exists in the boomerang array, delete.
    1383                 while ($existing_key = array_search($url, $_SESSION['_app'][$this->_ns]['boomerang']['url'])) {
    1384                     unset($_SESSION['_app'][$this->_ns]['boomerang']['url'][$existing_key]);
     1382                // If the ID=>URL pair currently exists in the boomerang array, delete.
     1383                foreach (array_keys($_SESSION['_app'][$this->_ns]['boomerang']['url'], $url) as $existing_key) {
     1384                    if ($existing_key == $id) {
     1385                        $this->logMsg(sprintf('Found and deleting existing ID=>URL pair: %s=>%s', $id, $url), LOG_DEBUG, __FILE__, __LINE__);
     1386                        unset($_SESSION['_app'][$this->_ns]['boomerang']['url'][$existing_key]);
     1387                    }
    13851388                }
    13861389            }
     
    14071410    {
    14081411        if (!$this->running) {
    1409             $this->logMsg(sprintf('Canceled method call %s, application not running.', __FUNCTION__), LOG_NOTICE, __FILE__, __LINE__);
     1412            $this->logMsg(sprintf('Canceled %s, application not running.', __METHOD__), LOG_NOTICE, __FILE__, __LINE__);
    14101413            return false;
    14111414        }
     
    14321435    {
    14331436        if (!$this->running) {
    1434             $this->logMsg(sprintf('Canceled method call %s, application not running.', __FUNCTION__), LOG_NOTICE, __FILE__, __LINE__);
     1437            $this->logMsg(sprintf('Canceled %s, application not running.', __METHOD__), LOG_NOTICE, __FILE__, __LINE__);
    14351438            return false;
    14361439        }
     
    14541457    {
    14551458        if (!$this->running) {
    1456             $this->logMsg(sprintf('Canceled method call %s, application not running.', __FUNCTION__), LOG_NOTICE, __FILE__, __LINE__);
     1459            $this->logMsg(sprintf('Canceled %s, application not running.', __METHOD__), LOG_NOTICE, __FILE__, __LINE__);
    14571460            return false;
    14581461        }
     
    14901493            // Last boomerang direction was less than 2 seconds ago.
    14911494            $this->logMsg(sprintf('validBoomerangURL(%s) not valid, boomerang_time too short: %s seconds', $id, time() - $boomerang_time), LOG_DEBUG, __FILE__, __LINE__);
     1495            return false;
     1496        }
     1497        if ($boomerang_time < (time() - 72000)) {
     1498            // Last boomerang direction was more than 20 minutes ago.
     1499            $this->logMsg(sprintf('validBoomerangURL(%s) not valid, boomerang_time too long: %s seconds', $id, time() - $boomerang_time), LOG_DEBUG, __FILE__, __LINE__);
    14921500            return false;
    14931501        }
  • trunk/lib/Cache.inc.php

    r523 r534  
    2626 * Provides an API for storing a limited amount of data
    2727 * intended to have a short lifetime in a user's session.
     28 *
     29 * Disable cache per-request by adding '_disable_cache=1' to a GET or POST parameter.
    2830 *
    2931 * @author  Quinn Comendant <quinn@strangecode.com>
     
    8082        if (true !== $app->getParam('enable_session')) {
    8183            // Force disable the cache because there is no session to save to.
    82             $app->logMsg('Cache disabled, enable_session is false.', LOG_DEBUG, __FILE__, __LINE__);
     84            $app->logMsg('Cache disabled, enable_session != true.', LOG_DEBUG, __FILE__, __LINE__);
    8385            $this->setParam(array('enabled' => false));
    8486        } else if (!isset($_SESSION['_cache'][$this->_ns])) {
     
    154156        $app =& App::getInstance();
    155157
    156         if (true !== $this->getParam('enabled')) {
     158        if (true !== $this->getParam('enabled') || getFormData('_disable_cache')) {
    157159            $app->logMsg(sprintf('Cache disabled, not saving data.', null), LOG_DEBUG, __FILE__, __LINE__);
    158160            return false;
     
    207209        $app =& App::getInstance();
    208210
    209         if (true !== $this->getParam('enabled')) {
     211        if (true !== $this->getParam('enabled') || getFormData('_disable_cache')) {
    210212            $app->logMsg(sprintf('Cache disabled, not getting data.', null), LOG_DEBUG, __FILE__, __LINE__);
    211213            return false;
     
    236238        $app =& App::getInstance();
    237239
    238         if (true !== $this->getParam('enabled')) {
     240        if (true !== $this->getParam('enabled') || getFormData('_disable_cache')) {
    239241            $app->logMsg(sprintf('Cache disabled on exist assertion.', null), LOG_DEBUG, __FILE__, __LINE__);
    240242            return false;
     
    254256        $app =& App::getInstance();
    255257
    256         if (true !== $this->getParam('enabled')) {
     258        if (true !== $this->getParam('enabled') || getFormData('_disable_cache')) {
    257259            $app->logMsg(sprintf('Cache disabled, skipping delete of %s', $key), LOG_DEBUG, __FILE__, __LINE__);
    258260            return false;
  • trunk/lib/FormValidator.inc.php

    r502 r534  
    384384
    385385    /**
     386     * Check whether input is a Decimal or Fixed type. Check values to be stored in mysql decimal, numeric, num, or fixed types.
     387     * Note: some integers and floats will also pass this test.
     388     * https://dev.mysql.com/doc/refman/5.5/en/fixed-point-types.html
     389     *
     390     * @param  string $form_name the name of the incoming form variable
     391     * @param  string $msg       the message to display on error
     392     * @param  string $val The input data to validate.
     393     * @param  bool $negative_ok  If the value can be unsigned.
     394     * @param  int  $max    Total max number of digits.
     395     * @param  int  $dec    Total max number of digits after the decimal place.
     396     * @return bool   true if value is a float
     397     */
     398    public function isDecimal($form_name, $msg='', $negative_ok=false, $max=10, $dec=2)
     399    {
     400        if (Validator::isDecimal(getFormData($form_name), $negative_ok, $max, $dec)) {
     401            return true;
     402        } else {
     403            $this->addError($form_name, $msg);
     404            return false;
     405        }
     406    }
     407
     408    /**
    386409     * Check whether input is an array.
    387410     *
  • trunk/lib/HTML.inc.php

    r502 r534  
    154154    }
    155155
     156    /*
     157    *
     158    *
     159    * @access   public
     160    * @param    array   $options    Array of options, with keys: value, selected, text
     161    * @param    array   $deselected Array of values to disable in options.
     162    * @return   array               Same options, but those with a value matching an element in $deselected will have a 'disabled' element of true.
     163    * @author   Quinn Comendant <quinn@strangecode.com>
     164    * @version  1.0
     165    * @since    24 Jul 2015 01:41:33
     166    */
     167    static public function disableSelectOptions($options, $deselected)
     168    {
     169        $app =& App::getInstance();
     170        $n = sizeof($options);
     171        for ($i=0; $i < $n; $i++) {
     172            $app->logMsg(sprintf('Disable check: %s == %s', $options[$i]['value'], getDump($deselected)), LOG_DEBUG, __FILE__, __LINE__);
     173            $options[$i]['disabled'] = in_array($options[$i]['value'], $deselected);
     174        }
     175        return $options;
     176    }
     177
    156178    /**
    157179     * Prints option fields for a select form. Works only with enum or set
     
    219241
    220242        foreach ($options as $o) {
    221             printf('<option value="%s"%s>%s</option>',
     243            printf('<option value="%s"%s%s>%s</option>',
    222244                oTxt($o['value']),
    223                 ($o['selected'] ? ' selected' : ''),
     245                (isset($o['selected']) && $o['selected'] ? ' selected' : ''),
     246                (isset($o['disabled']) && $o['disabled'] ? ' disabled' : ''),
    224247                oTxt($o['text'])
    225248            );
    226249        }
    227250    }
     251
     252    /**
     253     * Get a Gravatar URL for a specified email address.
     254     *
     255     * @param string $email The email address
     256     * @param string $size Size in pixels, defaults to 80px [ 1 - 2048 ]
     257     * @param string $d Default imageset to use [ 404 | mm | identicon | monsterid | wavatar ]
     258     * @param string $r Maximum rating (inclusive) [ g | pg | r | x ]
     259     * @return String containing a URL to a gravatar image.
     260     * @source http://gravatar.com/site/implement/images/php/
     261     */
     262    static public function getGravatarURL($email, $size=80, $defset='mm', $rating='g') {
     263        return sprintf('https://www.gravatar.com/avatar/%s?s=%s&d=%s&r=%s',
     264            md5(strtolower(trim($email))),
     265            $size,
     266            $defset,
     267            $rating
     268        );
     269    }
    228270}
  • trunk/lib/Navigation.inc.php

    r523 r534  
    4848        'path_delimiter' => ' / ',
    4949        'last_crumb_format' => '%s',
     50        'current_page_url' => null, // This should be set at runtime using, e.g., $_SERVER['REQUEST_URI']
    5051    );
    5152    public $pages = array();
     
    5758    {
    5859        $app =& App::getInstance();
     60
     61        // Define current_page_url here because _SERVER, not a static scalar, cannot be defined in the defaults above.
     62        // Using PHP_SELF for legacy compatability, but it might make sense to override this with REQUEST_URI.
     63        // This could be overwritten by passed params.
     64        $this->_params['current_page_url'] = $_SERVER['PHP_SELF'];
    5965
    6066        if (isset($params) && is_array($params)) {
     
    7278     * @access  public
    7379     * @param   string  $title      The title of the page.
    74      * @param   string  $url        The URL to the page. Set to null to use PHP_SELF.
     80     * @param   string  $url        The URL to the page. Set to null to use REQUEST_URI.
    7581     * @param   array   $vars       Additional page variables.
    7682     */
     
    8187            'head_title' => $title,
    8288            'body_title' => $title,
    83             'url' => is_null($url) ? $_SERVER['PHP_SELF'] : $url,
     89            'url' => is_null($url) ? $this->_params['current_page_url'] : $url,
    8490        );
    85         $this->pages[] = array_merge($page, $vars);
     91        // An "unformed page element" has settings applied (via ->set()) but no page added (via ->add()).
     92        if (empty($this->pages) || isset(end($this->pages)['title'])) {
     93            // There are no unformed page elements; add a whole new page.
     94            $this->pages[] = array_merge($page, $vars);
     95        } else {
     96            // Append the new page to the unformed page element.
     97            $curr_page =& $this->pages[key($this->pages)];
     98            $curr_page = array_merge($curr_page, $page, $vars);
     99        }
    86100    }
    87101
     
    143157    {
    144158        // Set params of current page.
    145         $curr_page =& $this->pages[sizeof($this->pages) - 1];
     159        if (empty($this->pages)) {
     160            // If we're setting a value on an empty pages array, we need to add one "unformed" element first.
     161            $this->pages[] = array();
     162        }
     163        end($this->pages);
     164        $curr_page =& $this->pages[key($this->pages)];
    146165        $curr_page[$key] = $val;
    147166    }
     
    157176    public function get($key, $default='')
    158177    {
    159         $curr_page =& $this->pages[sizeof($this->pages) - 1];
     178        end($this->pages);
     179        $curr_page =& $this->pages[key($this->pages)];
    160180
    161181        switch ($key) {
     
    375395     * @access  public
    376396     *
    377      * @param   string  $test_uri       A URI to test against the current page.
     397     * @param   mixed   $test_uri       A URI, or an array of URIs, to test against the current page.
    378398     * @param   mixed   $true_return    The value to return if the current page matches the test URI.
    379399     * @param   mixed   $false_return   The value to return if the current page does not match the test URI.
     
    387407    {
    388408        $app =& App::getInstance();
     409
     410        // If given an array, test each URI recursively returning TRUE on a first match, or FALSE if none match.
     411        if (is_array($test_uri)) {
     412            foreach ($test_uri as $uri) {
     413                if ($this->currentPage($uri, $true_return, $false_return, $include_query)) {
     414                    return true;
     415                }
     416            }
     417            return false;
     418        }
    389419
    390420        $actual_uri = $include_query ? $_SERVER['REQUEST_URI'] : strtok($_SERVER['REQUEST_URI'], '?');
  • trunk/lib/Utilities.inc.php

    r532 r534  
    275275 * @return string  A hexadecimal html color.
    276276 */
    277 function getTextColor($text, $method=1)
     277function getTextColor($text, $method=1, $n=0.87)
    278278{
    279279    $hash = md5($text);
     
    291291    default :
    292292        // Reduce all hex values slightly to avoid all white.
    293         array_walk($rgb, create_function('&$v', '$v = dechex(round(hexdec($v) * 0.87));'));
     293        array_walk($rgb, create_function('&$v', "\$v = dechex(round(hexdec(\$v) * $n));"));
    294294        break;
    295295    case 2 :
  • trunk/lib/Validator.inc.php

    r523 r534  
    120120     *
    121121     * @param  string $val The input data to validate.
     122     * @param  bool $negative_ok  If the value can be unsigned.
    122123     * @return bool   true if value is a float
    123124     */
     
    126127        $pattern = $negative_ok ? '/^-?[[:digit:]]*(?:\.?[[:digit:]]+)$/' : '/^[[:digit:]]*(?:\.?[[:digit:]]+)$/';
    127128        return '' == trim((string)$val) || (is_numeric($val) && preg_match($pattern, $val));
     129    }
     130
     131    /**
     132     * Check whether input is a Decimal or Fixed type. Check values to be stored in mysql decimal, numeric, num, or fixed types.
     133     * Note: some integers and floats will also pass this test.
     134     * https://dev.mysql.com/doc/refman/5.5/en/fixed-point-types.html
     135     *
     136     * @param  string $val The input data to validate.
     137     * @param  bool $negative_ok  If the value can be unsigned.
     138     * @param  int  $max    Total max number of digits (for mysql max is 65).
     139     * @param  int  $dec    Total max number of digits after the decimal place (for mysql max is 30).
     140     * @return bool   true if value is a float
     141     */
     142    static public function isDecimal($val, $negative_ok=false, $max=10, $dec=2)
     143    {
     144        if ('' == trim((string)$val)) {
     145            return true;
     146        }
     147        if (!$negative_ok && is_numeric($val) && $val < 0) {
     148            return false;
     149        }
     150        // Get the length of the part after any decimal point, or zero.
     151        $num_parts = explode('.', $val);
     152        $dec_count = sizeof($num_parts) <= 1 ? 0 : mb_strlen(end($num_parts));
     153        // Must be numeric, total digits <= $max, dec digits <= $dec.
     154        return is_numeric($val) && mb_strlen(str_replace(['-', '.'], '', $val)) <= $max && $dec_count <= $dec;
    128155    }
    129156
  • trunk/services/templates/lock.ihtml

    r497 r534  
    2323                ); ?>
    2424                </p>
    25                 <?php if ($lock->getSecondsElapsed() >= $lock->getParam('timeout')) { ?>
    26                     <p class="sc-msg-notice"><?php printf(_("You can forcibly unlock the record if you believe the editing session has expired. You might want to confirm with %s before doing this."), $lock->getEditor()) ?></p>
    27                     <div class="sc-msg-notice">
    28                         <?php
    29                         HTML::printButtons(array(
    30                             array('name' => 'unlock', 'value' => _("Unlock"), 'class' => 'small button alert', 'accesskey' => 'u'),
    31                             array('name' => 'cancel', 'value' => _("Cancel"), 'class' => 'small button secondary', 'accesskey' => 'c'),
    32                         ));
    33                         ?>
    34                     </div>
    35                 <?php } else { ?>
    36                     <div class="sc-msg-notice">
    37                         <?php
    38                         HTML::printButtons(array(
    39                             array('name' => 'cancel', 'value' => _("Cancel"), 'class' => 'small button secondary', 'accesskey' => 'c'),
    40                         ));
    41                         ?>
    42                     </div>
    43                 <?php } ?>
    4425            </div>
    4526        </div>
     27        <?php if ($lock->getSecondsElapsed() >= $lock->getParam('timeout')) { ?>
     28            <div id="sc-msg" class="sc-msg row">
     29                <div class="large-12 columns">
     30                    <p class="sc-msg-notice"><?php printf(_("You can forcibly unlock the record if you believe the editing session has expired. You might want to confirm with %s before doing this."), $lock->getEditor()) ?></p>
     31                </div>
     32            </div>
     33            <div class="row sc-submit-buttons">
     34                <div class="large-12 columns">
     35                    <?php
     36                    HTML::printButtons(array(
     37                        array('name' => 'unlock', 'value' => _("Unlock"), 'class' => 'small button alert', 'accesskey' => 'u'),
     38                        array('name' => 'cancel', 'value' => _("Cancel"), 'class' => 'small button secondary', 'accesskey' => 'c'),
     39                    ));
     40                    ?>
     41                </div>
     42            </div>
     43        <?php } else { ?>
     44            <div class="row sc-submit-buttons">
     45                <div class="large-12 columns">
     46                    <?php
     47                    HTML::printButtons(array(
     48                        array('name' => 'cancel', 'value' => _("Cancel"), 'class' => 'small button secondary', 'accesskey' => 'c'),
     49                    ));
     50                    ?>
     51                </div>
     52            </div>
     53        <?php } ?>
    4654    </form>
    4755</main>
Note: See TracChangeset for help on using the changeset viewer.