Created
August 9, 2010 21:35
-
-
Save thrashr888/516169 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?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