/** * Add activity metadata * * @param User $user * @param Activity $activity * @param array $data key-value pair data to store * @param array $exclude When given exclude keys to be stored in the database */ public static function addUserActivity(User $user, Activity $activity, array $data, array $exclude = []) { $rows = []; $exclude = array_map('strtolower', $exclude); // Create a session_id. // Session_id is use for easily identify groups of metadata $hashids = new Hashids('dma.activity.metadata', 6); $user_id = $user->getKey(); $activity_id = $activity->getKey(); // Add unixtime and microseconds to avoid session_id collisions $micro = microtime(true); $unixtime = floor($micro); $milseconds = floor(($micro - $unixtime) * pow(10, 8)); // Create session_id $session_id = $hashids->encode($user_id, $activity_id, $unixtime, $milseconds); // Current date and time $now = date('Y-m-d H:i:s'); foreach ($data as $key => $value) { $key = strtolower($key); if (!in_array($key, $exclude)) { $row = ['session_id' => $session_id, 'user_id' => $user_id, 'activity_id' => $activity_id, 'key' => $key, 'value' => $value, 'created_at' => $now, 'updated_at' => $now]; $rows[] = $row; } } if (count($row) > 0) { static::insert($rows); } }
/** * Take an activity and apply it to any badges and steps that apply * * @param User $user * A user model * @param Activity $activity * An activity model */ public static function applyActivityToBadges(User $user, Activity $activity) { $steps = $activity->steps()->get(); foreach ($steps as $step) { // user has not completed the step $isStepCompletable = self::checkUserActivities($user, $activity, $step); if ($isStepCompletable) { // Find badge associated with steps self::completeBadge($step, $user); } } }
/** * {%inheritDoc} */ public static function process(User $user, $params = []) { if (!isset($params['code']) || empty($params['code'])) { return false; } if ($activity = Activity::findActivityType('LikeWorkOfArt')->first()) { $code = $params['code']; if ($data = self::isAssessionNumber($code)) { // Skip activity process if user has already like this work of art $likeCount = ActivityMetadata::hasMetadataValue($user, $activity, 'object_id', $data['object_id'])->count(); if ($likeCount == 0) { // User haven't like this artwork yet if ($ret = parent::process($user, ['activity' => $activity])) { // TODO: Find a better way to pass this data $activity->objectData = $data; // Save user metada activity ActivityMetadata::addUserActivity($user, $activity, $data, ['object_title']); FriendsLog::artwork(['user' => $user, 'artwork_id' => $params['code']]); } return $ret; } else { Session::put('activityError', Lang::get('dma.friends::lang.activities.alreadyLikeWorkArtError', ['code' => $params['code']])); } } else { // Verify if user try to enter an Object number // Regex expression to match object number format $re = "/((([a-zA-Z0-9_\\-]+\\.){1,})([a-zA-Z0-9_\\-]+))/"; $isObjectNumber = preg_match_all($re, str_replace(' ', '', $code)) > 0; if ($isObjectNumber) { Session::put('activityError', Lang::get('dma.friends::lang.activities.likeWorkArtCodeError', ['code' => $params['code']])); } } } return false; }
public function testTimeRestrictionsAreSerialized() { $activity = FactoryMuffin::create('DMA\\Friends\\Models\\Activity'); $timeRestrictionData = ['start_time' => '11:00AM', 'end_time' => '12:00PM', 'days' => [1 => true, 2 => false, 3 => true, 4 => false, 5 => true, 6 => false]]; $activity->time_restriction_data = $timeRestrictionData; $activity->save(); // Load a new reference to the model $newActivity = Activity::find($activity->id); // Compare time_restriction_data to ensure that attributes are serialized/unserialized properly $this->assertEquals($newActivity->time_restriction_data, $timeRestrictionData); }
/** * {@inheritDoc} */ public static function process(User $user, $params = []) { $activities = Activity::where('activity_type', '=', 'Registration')->get(); if (!$activities) { return; } foreach ($activities as $activity) { parent::process($user, ['activity' => $activity]); } return true; }
/** * @see \DMA\Friends\Classes\ActivityTypeBase * * Process and determine if an award can be isued * based on a provided activity code * * @param User $user * A user model for which the activity should act upon * * @param array $params * An array of parameters for validating activities * * @return boolean * returns true if the process was successful */ public static function process(User $user, $params = []) { if (!isset($params['code']) || empty($params['code'])) { return false; } if ($activity = Activity::findCode($params['code'])->first()) { return parent::process($user, ['activity' => $activity]); } Session::put('activityError', Lang::get('dma.friends::lang.activities.codeError', ['code' => $params['code']])); return false; }
/** * Run the migrations. * * @return void */ public function up() { Activity::chunk(200, function ($activities) { foreach ($activities as $activity) { if ($activity->date_begin && $activity->date_end) { $activity->time_restriction = Activity::TIME_RESTRICT_DAYS; } elseif (!empty($activity->time_restriction_data)) { $activity->time_restriction = Activity::TIME_RESTRICT_HOURS; } else { $activity->time_restriction = Activity::TIME_RESTRICT_NONE; } $activity->save(); } }); }
/** * Produce a collection of Activities based on recommendations and filters */ private function getResults($filterstr = null) { $perpage = 12; if ($filterstr && $filterstr != 'all') { $filters = json_decode($filterstr, true); if ($filters && is_array($filters['categories'])) { $results = Activity::isActive()->byCategory($filters['categories'])->paginate($perpage); } else { $results = Activity::isActive()->paginate($perpage); } } else { $results = Activity::isActive()->paginate($perpage); } $this->page['activities'] = $results; $this->page['hasLinks'] = $results->hasMorePages() || $results->currentPage() > 1; $this->page['links'] = $results->render(); }
/** * @see \DMA\Friends\Classes\ActivityTypeBase * * Process and determine if an award can be isued * based on a provided activity code * * @param User $user * A user model for which the activity should act upon * * @param array $params * An array of parameters for validating activities * * @return boolean * returns true if the process was successful */ public static function process(User $user, $params = []) { static $is_running = false; if (!$is_running) { $is_running = true; $activities = Activity::findActivityType('Points')->get(); foreach ($activities as $activity) { if ($user->activities->contains($activity->id)) { continue; } if ($user->points >= $activity->points) { parent::process($user, ['activity' => $activity]); } } $is_running = false; } return true; }
/** * {@inheritDoc} */ public function boot() { // Extend Activity model to support extra fields & ratings Activity::extend(function ($model) { $model->hasOne['activity_fields'] = ['DenverArt\\ActivityFields\\Models\\ExtraFields']; $model->hasMany['ratings'] = ['DenverArt\\ActivityFields\\Models\\Rating']; $model->addDynamicMethod('scopeNotIgnored', function ($query, $user) { $query = $query->whereHas('ratings', function ($q) use($user) { $q->where('user_id', $user->getKey())->where('rating', 0); }, '<', 1); }); $model->addDynamicMethod('scopeIgnored', function ($query, $user) { $query = $query->whereHas('ratings', function ($q) use($user) { $q->where('user_id', $user->getKey())->where('rating', 0); }); }); $model->addDynamicMethod('scopeNotComplete', function ($query, $user) { $query = $query->whereHas('users', function ($q) use($user) { $q->where('user_id', $user->getKey()); }, '<', 1); }); $model->addDynamicMethod('scopeComplete', function ($query, $user) { $query = $query->whereHas('users', function ($q) use($user) { $q->where('user_id', $user->getKey()); }); }); }); // Extend User model to support ratings User::extend(function ($model) { $model->hasMany['ratings'] = ['DenverArt\\ActivityFields\\Models\\Rating']; }); // Extend Activity fields $context = $this; Event::listen('backend.form.extendFields', function ($widget) use($context) { $context->extendedActivityFields($widget); }); // Extend Activity admin listing table columns Event::listen('backend.list.extendColumns', function ($widget) { if (!$widget->getController() instanceof \DMA\Friends\Controllers\Activities) { return; } $widget->addColumns(['duration' => ['label' => 'Duration', 'relation' => 'activity_fields', 'sortable' => true, 'select' => '@duration', 'searchable' => true], 'location' => ['label' => 'Location', 'relation' => 'activity_fields', 'sortable' => true, 'select' => '@location', 'searchable' => true]]); }); }
public function afterSave() { $activity = Activity::find($this->getKey()); $activity->touch(); }
public function onUndoHide() { // Get submit data $activity_id = (int) post('activity'); // Validate $activity = Activity::find($activity_id); if ($activity) { // Get User $user = Auth::getUser(); Rating::where('activity_id', $activity_id)->where('user_id', $user->id)->delete(); Flash::success('Okay. That activity will be available in your recommendations now.'); } else { Flash::error('That activity does not exist.'); } // return flash message return ['#flashMessages' => $this->renderPartial('@flashMessages')]; }
/** * Determine if an activity is capable of being completed * * @param Activity * An activity model * * @return boolean * returns true if an activity can be completed by the user */ public static function canComplete(Activity $activity, User $user) { if (!$activity->isActive()) { return false; } // Check activity lockout if ($activity->activity_lockout && ($pivot = $user->activities()->where('activity_id', $activity->id)->first())) { $time = Carbon::now(); $lastTime = $pivot->pivot->created_at; if ($time->diffInMinutes($lastTime) < $activity->activity_lockout) { $x = $time->diffInMinutes($lastTime->addMinutes($activity->activity_lockout)); $message = self::convertToHoursMins($x, '%d hours and %02d minutes'); Session::put('activityError', Lang::get('dma.friends::lang.activities.lockout', ['x' => $message])); return false; } } switch ($activity->time_restriction) { case Activity::TIME_RESTRICT_NONE: return true; case Activity::TIME_RESTRICT_HOURS: if ($activity->time_restriction_data) { $now = Carbon::now(); $start = self::convertTime($activity->time_restriction_data['start_time']); $end = self::convertTime($activity->time_restriction_data['end_time']); $start_time = Carbon::now(); $start_time->setTime($start['hour'], $start['minutes']); $end_time = Carbon::now(); $end_time->setTime($end['hour'], $start['minutes']); $day = date('w'); // Sunday is on the end of the week and date sets sunday as 0 if ($day == 0) { $day = 7; } if ($activity->time_restriction_data['days'][$day] !== false && $now->gte($start_time) && $now->lte($end_time)) { return true; } else { Session::put('activityError', Lang::get('dma.friends::lang.activities.notAvailable')); } } break; case Activity::TIME_RESTRICT_DAYS: $now = new DateTime('now'); if ($now >= $activity->date_begin && $now <= $activity->date_end) { return true; } else { Session::put('activityError', Lang::get('dma.friends::lang.activities.notAvailable')); } break; } return false; }
/** * Produce a collection of Activities based on recommendations and filters */ private function getResults($filterstr = null) { $user = Auth::getUser(); $perpage = 12; $dayNames = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']; $restrictions = []; if ($filterstr && $filterstr != 'all') { $filters = json_decode($filterstr, true); if ($filters && is_array($filters['categories'])) { $results = Activity::isActive()->ignored($user)->byCategory($filters['categories'])->paginate($perpage); } else { $results = Activity::isActive()->ignored($user)->paginate($perpage); } } else { $results = Activity::isActive()->ignored($user)->paginate($perpage); } foreach ($results as $index => $result) { $string = ''; $type = $result->time_restriction; $time = $result->time_restriction_data; if ($type == 1) { $days = []; foreach ($time['days'] as $key => $value) { if ($value > 0) { $days[] .= $dayNames[$key - 1]; } } $len = count($days); switch ($len) { case 0: break; case 1: $string = $days[0]; break; case 2: $string = implode(' and ', $days); break; default: $last = array_pop($days); $string = implode(', ', $days) . ' and ' . $last; } $string .= ' at '; $string .= strtolower($time['start_time'] . '–' . $time['end_time']); } elseif ($type == 2) { $start = date('M j, Y', strtotime($result->date_begin)); $end = date('M j, Y', strtotime($result->date_end)); if ($start == $end) { $start = date('M j, Y g:i a', strtotime($result->date_begin)); $end = date('M j, Y g:i a', strtotime($result->date_end)); if ($start == $end) { $string = $start; } else { $end = date('g:i a', strtotime($result->date_end)); } } if (!$string) { $string = $start . ' to ' . $end; } } $restrictions[$index] = $string; } $this->page['activities'] = $results; $this->page['activity_count'] = $results->count(); $this->page['restrictions'] = $restrictions; $this->page['hasLinks'] = $results->hasMorePages() || $results->currentPage() > 1; $this->page['links'] = $results->render(); }
/** * Execute the console command. * @return void */ public function fire() { // Taxonomy terms $termRelations = $this->db->table('wp_term_relationships')->get(); foreach ($termRelations as $relation) { $activity = Activity::findWordpress($relation->object_id)->first(); if ($activity) { if (!$activity->categories->contains($relation->term_taxonomy_id)) { $category = Category::find($relation->term_taxonomy_id); if ($category) { $activity->categories()->save($category); } } } } // p2p connections $p2ps = $this->db->table('wp_p2p')->get(); foreach ($p2ps as $p2p) { list($from, $t, $to) = explode('-', $p2p->p2p_type); switch ($from) { case 'activity': $from = Activity::findWordpress($p2p->p2p_from)->first(); $from_table = 'activity'; break; case 'badge': $from = Badge::findWordpress($p2p->p2p_from)->first(); $from_table = 'badge'; break; case 'dma-location': $from = Location::findWordpress($p2p->p2p_from)->first(); $from_table = 'location'; break; case 'step': $from = Step::findWordpress($p2p->p2p_from)->first(); $from_table = 'step'; break; default: $from = false; } switch ($to) { case 'activity': $to = Activity::findWordpress($p2p->p2p_to)->first(); $to_table = 'activity'; break; case 'badge': $to = Badge::findWordpress($p2p->p2p_to)->first(); $to_table = 'badge'; break; case 'dma-location': $to = Location::findWordpress($p2p->p2p_to)->first(); $to_table = 'location'; break; case 'step': $to = Step::findWordpress($p2p->p2p_to)->first(); $to_table = 'step'; break; default: $to = false; } if ($from && $to) { $table = 'dma_friends_' . $from_table . '_' . $to_table; switch ($table) { case 'dma_friends_activity_step': $from->steps()->save($to); $this->info('activity: ' . $from->title . ' --> step: ' . $to->title); break; case 'dma_friends_step_badge': $to->steps()->save($from); $this->info('step: ' . $from->title . ' --> badge: ' . $to->title); break; default: $values = [$from_table . '_id' => $from->id, $to_table . '_id' => $to->id]; if (Schema::hasTable($table)) { DB::table($table)->insert($values); $this->info('from: ' . $from->title . ' ----- ' . $to->title); } else { $this->error('table doesnt exist: ' . $table); } } } } // User achievements $achievements = $this->db->table('wp_usermeta')->where('meta_key', '_badgeos_achievements')->get(); $post = new Post(); $this->info('Sync Achievements'); foreach ($achievements as $achievement) { $user = User::find($achievement->user_id); if (empty($user)) { continue; } // Flush existing records DB::table($this->userStepTable)->where('user_id', $user->id)->delete(); DB::table($this->userBadgeTable)->where('user_id', $user->id)->delete(); $data = unserialize($achievement->meta_value); // wtf we don't need arrays in our arrays if we want to array $data = array_pop($data); foreach ($data as $d) { $link = ['user_id' => $user->id, 'created_at' => $post->epochToTimestamp($d->date_earned)]; // About half way thru the data for the location key changes. // so lets deal with that if (isset($d->location)) { $location_id = $d->location; } elseif (isset($d->location_earned)) { $location_id = $d->location_earned; } else { $location_id = null; } $location = Location::findWordpress($location_id)->first(); if (isset($location->id)) { $link['location_id'] = $location->id; } if ($d->post_type == 'step') { $step = Step::findWordpress($d->ID)->first(); if ($step) { $link['step_id'] = $step->id; DB::table($this->userStepTable)->insert($link); } } elseif ($d->post_type == 'badge') { $badge = Badge::findWordpress($d->ID)->first(); if ($badge) { $link['badge_id'] = $badge->id; DB::table($this->userBadgeTable)->insert($link); } } } } // Syncronize activities and users $this->info('Importing Activity/User relations'); $table = 'dma_friends_activity_user'; DB::table($table)->delete(); ActivityLog::where('action', '=', 'activity')->chunk(100, function ($activityLogs) use($table) { foreach ($activityLogs as $activityLog) { if ($activityLog->object_id) { echo '.'; $pivotTable = ['user_id' => $activityLog->user_id, 'activity_id' => $activityLog->object_id, 'created_at' => $activityLog->timestamp, 'updated_at' => $activityLog->timestamp]; DB::table($table)->insert($pivotTable); } } }); // Syncronize rewards and users $this->info('Importing Reward/User relations'); $table = 'dma_friends_reward_user'; //DB::table($table)->delete(); ActivityLog::where('action', '=', 'reward')->where('timestamp', '<', '2015-02-02 12:10:35')->chunk(100, function ($activityLogs) use($table) { foreach ($activityLogs as $activityLog) { if ($activityLog->object_id) { echo '.'; if (Reward::find($activityLog->object_id) && User::find($activityLog->user_id)) { $pivotTable = ['user_id' => $activityLog->user_id, 'reward_id' => $activityLog->object_id, 'created_at' => $activityLog->timestamp, 'updated_at' => $activityLog->timestamp]; DB::table($table)->insert($pivotTable); } } } }); $this->info('Sync complete'); }
/** * Import user accounts from wordpress * * @param int $limit * The amount of records to import at one time */ public function import($limit = 0) { $count = 0; $table = $this->model->table; $id = (int) DB::table($table)->max('id'); $wordpressLogs = $this->db->table('wp_badgeos_logs')->where('id', '>', $id)->orderBy('id', 'asc')->limit($limit)->get(); // Use dummy model to get action types $l = new $this->model(); foreach ($wordpressLogs as $wlog) { if (!in_array($wlog->action, $l->actionTypes)) { continue; } $object = false; $log = new $this->model(); $log->id = $wlog->id; $log->user_id = $wlog->user_id; $log->action = $wlog->action; $log->message = $wlog->message; $log->points_earned = $wlog->points_earned; $log->total_points = $wlog->total_points; $log->timestamp = $wlog->timestamp; $log->timezone = $wlog->timezone; if ($wlog->action == 'artwork') { $log->artwork_id = $wlog->object_id; $object = OctoberActivity::where('activity_type', '=', 'LikeWorkOfArt')->first(); } else { // Get the wordpress post type $post_type = $this->db->table('wp_posts')->select('post_type')->where('ID', $wlog->object_id)->first(); if (isset($post_type->post_type)) { // Convert the post type to a usable object model switch ($post_type->post_type) { case 'activity': $object = OctoberActivity::findWordpress($wlog->object_id); break; case 'badge': $object = OctoberBadge::findWordpress($wlog->object_id); break; case 'badgeos-rewards': $object = OctoberReward::findWordpress($wlog->object_id); break; case 'dma-location': $object = OctoberLocation::findWordpress($wlog->object_id); break; case 'step': $object = OctoberStep::findWordpress($wlog->object_id); break; default: continue; } } else { continue; } } try { if ($log->save()) { // If the log is related to an object, save that relation if ($object) { $object = $object->first(); // Ugly hack to get sync working for now if (get_class($object) == 'DMA\\Friends\\Wordpress\\ActivityLog') { continue; } $object->activityLogs()->save($log); } $count++; } } catch (Exception $e) { echo "Failed to import log entry id: " . $log->id . "\n"; echo $e->getMessage() . "\n"; } } return $count; }
/** * Query scope to filter activity metadata by the given key and value * @param mixed $query * @param RainLab\User\Models\User $user * @param DMA\Friends\Models\Activity $activity * @param string $key * @param string $value */ public function scopeHasMetadataValue($query, $user, $activity, $key, $value) { return self::where('user_id', $user->getKey())->where('activity_id', $activity->getKey())->where('key', $key)->where('value', $value); }