<?php namespace BookStack\Actions;
+use BookStack\Interfaces\Viewable;
use BookStack\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;
+/**
+ * Class View
+ * Views are stored per-item per-person within the database.
+ * They can be used to find popular items or recently viewed items
+ * at a per-person level. They do not record every view instance as an
+ * activity. Only the latest and original view times could be recognised.
+ *
+ * @property int $views
+ * @property int $user_id
+ */
class View extends Model
{
{
return $this->morphTo();
}
+
+ /**
+ * Increment the current user's view count for the given viewable model.
+ */
+ public static function incrementFor(Viewable $viewable): int
+ {
+ $user = user();
+ if (is_null($user) || $user->isDefault()) {
+ return 0;
+ }
+
+ /** @var View $view */
+ $view = $viewable->views()->firstOrNew([
+ 'user_id' => $user->id,
+ ], ['views' => 0]);
+
+ $view->save(['views' => $view->views + 1]);
+
+ return $view->views;
+ }
+
+ /**
+ * Clear all views from the system.
+ */
+ public static function clearAll()
+ {
+ static::query()->truncate();
+ }
}
<?php namespace BookStack\Actions;
use BookStack\Auth\Permissions\PermissionService;
-use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Entity;
use BookStack\Entities\EntityProvider;
use DB;
$this->entityProvider = $entityProvider;
}
- /**
- * Add a view to the given entity.
- * @param \BookStack\Entities\Models\Entity $entity
- * @return int
- */
- public function add(Entity $entity)
- {
- $user = user();
- if ($user === null || $user->isDefault()) {
- return 0;
- }
- $view = $entity->views()->where('user_id', '=', $user->id)->first();
- // Add view if model exists
- if ($view) {
- $view->increment('views');
- return $view->views;
- }
-
- // Otherwise create new view count
- $entity->views()->save($this->view->newInstance([
- 'user_id' => $user->id,
- 'views' => 1
- ]));
-
- return 1;
- }
-
/**
* Get the entities with the most views.
* @param int $count
return $all->sortByDesc('last_viewed_at')->slice(0, $count);
}
-
- /**
- * Reset all view counts by deleting all views.
- */
- public function resetAll()
- {
- $this->view->truncate();
- }
}
namespace BookStack\Console\Commands;
+use BookStack\Actions\View;
use Illuminate\Console\Command;
class ClearViews extends Command
*/
public function handle()
{
- \Views::resetAll();
+ View::clearAll();
$this->comment('Views cleared');
}
}
use BookStack\Facades\Permissions;
use BookStack\Interfaces\Favouritable;
use BookStack\Interfaces\Sluggable;
+use BookStack\Interfaces\Viewable;
use BookStack\Model;
use BookStack\Traits\HasCreatorAndUpdater;
use BookStack\Traits\HasOwner;
* @method static Builder withLastView()
* @method static Builder withViewCount()
*/
-abstract class Entity extends Model implements Sluggable, Favouritable
+abstract class Entity extends Model implements Sluggable, Favouritable, Viewable
{
use SoftDeletes;
use HasCreatorAndUpdater;
use Activity;
use BookStack\Actions\ActivityType;
+use BookStack\Actions\View;
use BookStack\Entities\Tools\BookContents;
use BookStack\Entities\Models\Bookshelf;
use BookStack\Entities\Tools\PermissionsUpdater;
$bookChildren = (new BookContents($book))->getTree(true);
$bookParentShelves = $book->shelves()->visible()->get();
- Views::add($book);
+ View::incrementFor($book);
if ($request->has('shelf')) {
$this->entityContextManager->setShelfContext(intval($request->get('shelf')));
}
<?php namespace BookStack\Http\Controllers;
use Activity;
+use BookStack\Actions\View;
use BookStack\Entities\Models\Book;
use BookStack\Entities\Tools\PermissionsUpdater;
use BookStack\Entities\Tools\ShelfContext;
->values()
->all();
- Views::add($shelf);
+ View::incrementFor($shelf);
$this->entityContextManager->setShelfContext($shelf->id);
$view = setting()->getForCurrentUser('bookshelf_view_type');
<?php namespace BookStack\Http\Controllers;
+use BookStack\Actions\View;
use BookStack\Entities\Models\Book;
use BookStack\Entities\Tools\BookContents;
use BookStack\Entities\Repos\ChapterRepo;
$sidebarTree = (new BookContents($chapter->book))->getTree();
$pages = $chapter->getVisiblePages();
- Views::add($chapter);
+ View::incrementFor($chapter);
$this->setPageTitle($chapter->getShortName());
return view('chapters.show', [
<?php namespace BookStack\Http\Controllers;
+use BookStack\Actions\View;
use BookStack\Entities\Tools\BookContents;
use BookStack\Entities\Tools\PageContent;
use BookStack\Entities\Tools\PageEditActivity;
$page->load(['comments.createdBy']);
}
- Views::add($page);
+ View::incrementFor($page);
$this->setPageTitle($page->getShortName());
return view('pages.show', [
'page' => $page,
--- /dev/null
+<?php namespace BookStack\Interfaces;
+
+use Illuminate\Database\Eloquent\Relations\MorphMany;
+
+interface Viewable
+{
+ /**
+ * Get all view instances for this viewable model.
+ */
+ public function views(): MorphMany;
+}
\ No newline at end of file