id; } /** * Get the user who registered this organisation */ public function registrant() { /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; return $this->hasOne($classMapper->getClassMapping('user'), 'id', 'registrant_id'); } /** * Get a list of members within this organisation. */ public function members() { /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; return $this ->belongsToMany($classMapper->getClassMapping('user'), 'organisation_members', 'organisation_id', 'user_id') ->where('flag_admin', false); } /** * Get a list of administrators within this organisation. */ public function administrators() { /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; return $this ->belongsToMany($classMapper->getClassMapping('user'), 'organisation_members', 'organisation_id', 'user_id') ->where('flag_admin', true); } /** * Delete this organisation from the database, along with any linked objects. * * @param bool $hardDelete Set to true to completely remove the organisation and all associated objects. * * @return bool true if the deletion was successful, false otherwise. */ public function delete($hardDelete = false) { /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; if ($hardDelete) { static::$ci->get('organisation.beforeDelete')($this); // Remove all organisation tokens $classMapper->getClassMapping('organisation_approval')::where('owner_id', $this->id)->delete(); // Remove all member associations $this->members()->detach(); // Delete the organisation $result = $this->forceDelete(); } else { // Soft delete the organisation, leaving all associated records alone $result = parent::delete(); } return $result; } /** * Performs tasks to be done before an organisation is merged * * By default, adds a new sign-in activity and updates any legacy hash. * * @param mixed[] $params Optional array of parameters used for this event handler. * * @todo Transition to Laravel Event dispatcher to handle this */ public function beforeMerge($target, $params = []) { /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = static::$ci->authenticator->user(); /** @var \UserFrosting\Sprinkle\???? $activityLogger */ $activityLogger = static::$ci->userActivityLogger; $logEntry = function($activityLogger, $currentUser, $user, $target) { $activityLogger->info("User {$currentUser->user_name} moved user {$user->user_name} from organisation {$this->name} into {$target->name}.", [ 'type' => 'organisation_merge', 'user_id' => $currentUser->id, ]); $activityLogger->info("User {$user->user_name} was removed from the organisation {$this->name} by {$currentUser->user_name} during an organisation merge.", [ 'type' => 'group_leave', 'user_id' => $user->id, ]); $activityLogger->info("User {$user->user_name} was added to the organisation {$target->name} by {$currentUser->user_name} during an organisation merge.", [ 'type' => 'group_join', 'user_id' => $user->id, ]); }; // Move all the users from this organisation to the target $this->administrators()->each(function ($user) use ($target, $activityLogger, $currentUser, $logEntry) { $this->administrators()->detach($user); // NOTE: Should this record be retained? Or is the activity log enough of an audit? if (!$target->administrators()->find($user->id) && !$target->members()->find($user->id)) { $target->administrators()->attach($user, ['flag_admin' => true]); } $logEntry($activityLogger, $currentUser, $user, $target); }); $this->members()->each(function ($user) use ($target, $activityLogger, $currentUser, $logEntry) { $this->members()->detach($user); // NOTE: Should this record be retained? Or is the activity log enough of an audit? if (!$target->administrators()->find($user->id) && !$target->members()->find($user->id)) { $target->members()->attach($user, ['flag_admin' => false]); } $logEntry($activityLogger, $currentUser, $user, $target); }); $this->save(); $target->save(); return $this; } /** * Joins the organisation's member count, so we can do things like sort, search, paginate, etc. * * @param Builder $query * * @return Builder */ public function scopeJoinMemberCounts($query) { $memberCountsInner = DB::table('organisation_members') ->selectRaw('organisation_id, COUNT(*) AS member_count') ->where('flag_admin', false) ->groupBy('organisation_id'); $memberCounts = DB::table('organisations') ->leftJoinSub($memberCountsInner, 'member_counts_inner', function ($join) { $join->on('member_counts_inner.organisation_id', '=', 'organisations.id'); }) ->select('id AS organisation_id') ->selectRaw('COALESCE(member_count, 0) AS member_count'); $adminCountsInner = DB::table('organisation_members') ->selectRaw('organisation_id, COUNT(*) AS admin_count') ->where('flag_admin', true) ->groupBy('organisation_id'); $adminCounts = DB::table('organisations') ->leftJoinSub($adminCountsInner, 'admin_counts_inner', function ($join) { $join->on('admin_counts_inner.organisation_id', '=', 'organisations.id'); }) ->select('id AS organisation_id') ->selectRaw('COALESCE(admin_count, 0) AS admin_count'); return $query ->leftJoinSub($memberCounts, 'member_counts', function ($join) { $join->on('member_counts.organisation_id', '=', 'organisations.id'); }) ->leftJoinSub($adminCounts, 'admin_counts', function ($join) { $join->on('admin_counts.organisation_id', '=', 'organisations.id'); }); } /** * Query scope to get all organisations a specific user is a member of. * * @param Builder $query * @param int $userId * * @return Builder */ public function scopeForUser($query, $userId) { return $query->join('organisation_members', function ($join) use ($userId) { $join->on('organisation_members.organisation_id', 'organisations.id') ->where('user_id', $userId); }); } /** * Query scope to get all organisations but indicate which the specified user is a member of. * * @param Builder $query * @param int $userId * * @return Builder */ public function scopeWithUser($query, $userId) { $membersInner = DB::table('organisation_members') ->selectRaw('organisation_id, 1 AS is_member, flag_admin AS is_admin') ->where('user_id', $userId); return $query ->leftJoinSub($membersInner, 'user_orgs', function ($join) { $join->on('user_orgs.organisation_id', '=', 'organisations.id'); }); } }