Skip to content

Instantly share code, notes, and snippets.

@thrashr888
Created August 9, 2010 21:35
Show Gist options
  • Select an option

  • Save thrashr888/516169 to your computer and use it in GitHub Desktop.

Select an option

Save thrashr888/516169 to your computer and use it in GitHub Desktop.
<?php
/**
* a feature enabling class
*
* This class has a few methods for enabling or disabling chunks of code.
* It also provides enabling based on user buckets. Most methods are just static.
*
* @author Paul Thrasher
*
*/
class features
{
protected static $enabled = array(); // just holds the enabled features
/**
* set the chunk of enabled features for testing later
* this can get grabbed from the db
* @param array $enabled
*/
public static function setEnabled(Array $enabled)
{
self::$enabled = $enabled;
}
/**
* checks if a feature is enabled
* @param $feature
*/
public static function enabled($feature = 'default')
{
return isset(self::$enabled[$feature]) ? (bool) self::$enabled[$feature] : false;
}
/**
* enable a feature
* @param $feature
*/
public static function enable($feature = 'default')
{
self::$enabled[$feature] = true;
}
/**
* disable a feature
* @param $feature
*/
public static function disable($feature = 'default')
{
unset(self::$enabled[$feature]);
}
/**
* bucket test a percentage of users.
* @example features::users('20', 2) // true for 20-40 of 100
* @param $percent how many users you want (1-100)
* @param $bucket_number which bucket you want (>0)
*/
public static function users($percent, $bucket_number = 1)
{
if(self::userSegment() > ($percent * $bucket_number -1) // start
&& self::userSegment() < ($percent * $bucket_number)) // end
{
return true;
}
return false;
}
/**
* splits users into buckets
* @example features::bucket('4', 3) // true for 50-75 of 100
* @param int $bucket_count how many buckets you want
* @param int $bucket_number which bucket you want
*/
public static function bucket($bucket_count = 2, $bucket_number = 1)
{
return self::users(100/$bucket_count, $bucket_number);
}
/**
* @param int $bucket_count
* @return a bucket number corresponding to the user
*/
public static function number($bucket_count = 2)
{
return (self::userSegment() / 100) * $bucket_count;
}
/**
* bucket users between an arbitrary amount of values
* @param mixed an arbitrary amount of values
* @return mixed one of the passed arguments
*/
public static function values()
{
$values = func_get_args();
return $values[self::number(func_num_args())];
}
/**
* rollout
* this resolves to true across the time period of 1 day, according to user_id. by end of day, all users will resolve true.
* @param string $date_of_rollout
* @return boolean
*/
public static function rollout($date_of_rollout)
{
if(new DateTime() >= new DateTime($date_of_rollout) || floor(date('H') / 24 * 100) <= self::userSegment()) return true;
return false;
}
/**
* breaks up users into segments of 1-100 in 0.1 increments
* we use user_id for unique user login
* it gets translated to user_segment
* if not logged in, we make one up
* @return int (1-100)
*/
public static function userSegment()
{
if(!isset($_SESSION['user_id'])){
$_SESSION['user_segment'] = mt_rand(1, 1000)/10;
}
if(isset($_SESSION['user_id']) && !isset($_SESSION['user_segment'])){
$_SESSION['user_segment'] = (substr($_SESSION['user_id'], -3) + 1)/10;
}
return $_SESSION['user_segment'];
}
/**
* time duration
* @param string $start date
* @param string $end date
*/
public static function between($start_date, $end_date)
{
$now = new DateTime();
$start_date = new DateTime($start_date);
$end_date = new DateTime($end_date);
if($start_date < $now && $now < $end_date) return true;
return false;
}
/**
* time duration. returns true *before* passed date.
* @param string $end
*/
public static function before($end_date)
{
$now = new DateTime();
$end_date = new DateTime($end_date);
if($now < $end_date) return true;
return false;
}
/**
* time duration. returns true *after( passed date.
* @param string $start
*/
public static function after($start_date)
{
$now = new DateTime();
$start_date = new DateTime($start_date);
if($start_date < $now) return true;
return false;
}
public static function url($url_pattern)
{
if(preg_match($url_pattern, $_SERVER['REQUEST_URI']))
{
return true;
}
return false;
}
}
/**
* tests/examples for features class
*/
/*
// setup features to test for later
features::setEnabled(array(
'testing' => true,
'admin' => true,
'special-group' => true,
'howard the duck' => false,
'beta' => false,
));
if(features::enabled('testing')){
// we're testing
debug('testing enabled');
}
if(!features::enabled('beta')){
// we're testing
debug('beta off');
}
if(features::users(10)){
// we're in the 10% of segmented users
debug('lucky 1-10');
}
if(features::users(50, 2)){
// we're in the 50% of segmented users
debug('lucky 50-100');
}
if(features::bucket(10, 2)){
// we grabbed 10% of users
debug('lucky 10-20');
}
if(features::bucket(40, 4)){
// we grabbed 2.5% of users
debug('lucky 10-12.5');
}
if(features::rollout('8/5/10')){
// this will roll out a feature to all users over the course of 1 day,
// based on the hour and their user_id
debug('rollin out!');
}
if(features::date('05/05/2010', '08/04/10')){
// only on certain dates
debug('it is time!');
}
if(features::after('04/29/2010')){
// only after a date
debug('easter time!');
}
if(features::before('12/25/2010')){
// only before a date
debug('not yet christmas');
}
if(features::before('12/25/2009')){
// this date has passed, no debug
debug('not yet christmas');
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment