├── tests
├── .gitkeep
└── ActivityLogSupervisorTest.php
├── .gitignore
├── scrutinizer.yml
├── .travis.yml
├── src
├── Spatie
│ └── Activitylog
│ │ ├── LogsActivityInterface.php
│ │ ├── ActivitylogFacade.php
│ │ ├── Handlers
│ │ ├── BeforeHandlerInterface.php
│ │ ├── ActivitylogHandlerInterface.php
│ │ ├── DefaultLaravelHandler.php
│ │ └── EloquentHandler.php
│ │ ├── LogsActivity.php
│ │ ├── Models
│ │ └── Activity.php
│ │ ├── ActivitylogServiceProvider.php
│ │ └── ActivitylogSupervisor.php
├── migrations
│ └── create_activity_log_table.stub
└── config
│ └── activitylog.php
├── phpunit.xml
├── CHANGELOG.md
├── composer.json
├── LICENSE
├── CONTRIBUTING.md
└── README.md
/tests/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor
2 | composer.phar
3 | composer.lock
4 |
5 |
--------------------------------------------------------------------------------
/scrutinizer.yml:
--------------------------------------------------------------------------------
1 | tools:
2 | external_code_coverage: false
3 | checks:
4 | php:
5 | code_rating: true
6 | duplication: true
7 |
8 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 5.4
5 | - 5.5
6 | - 5.6
7 | - hhvm
8 | - 7
9 |
10 | before_script:
11 | - travis_retry composer self-update
12 | - travis_retry composer install --prefer-source --no-interaction --dev
13 |
14 | script: vendor/bin/phpunit
15 |
--------------------------------------------------------------------------------
/src/Spatie/Activitylog/LogsActivityInterface.php:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 | ./tests/
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/Spatie/Activitylog/Handlers/ActivitylogHandlerInterface.php:
--------------------------------------------------------------------------------
1 | increments('id');
15 | $table->integer('user_id')->nullable();
16 | $table->string('text');
17 | $table->string('ip_address', 64);
18 | $table->timestamps();
19 | });
20 | }
21 |
22 | /**
23 | * Reverse the migrations.
24 | */
25 | public function down()
26 | {
27 | Schema::drop('activity_log');
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "spatie/activitylog",
3 | "description": "A very simple activity logger to monitor the users of your website or application",
4 | "homepage": "https://github.com/spatie/activitylog",
5 | "abandoned" : "This package has been replaced by spatie/laravel-activitylog",
6 | "keywords":
7 | [
8 | "log",
9 | "user",
10 | "activity",
11 | "laravel"
12 | ],
13 | "authors": [
14 | {
15 | "name": "Freek Van der Herten",
16 | "email": "freek@spatie.be"
17 | }
18 | ],
19 | "require": {
20 | "php": ">=5.4.0",
21 | "illuminate/support": "5.*"
22 |
23 | },
24 | "require-dev": {
25 | "phpunit/phpunit": "~4.0",
26 | "mockery/mockery": "0.9.*"
27 | },
28 | "autoload": {
29 | "classmap": [
30 | "src/migrations"
31 | ],
32 | "psr-0": {
33 | "Spatie\\Activitylog\\": "src/"
34 | }
35 | },
36 | "license": "MIT"
37 | }
38 |
--------------------------------------------------------------------------------
/src/Spatie/Activitylog/Handlers/DefaultLaravelHandler.php:
--------------------------------------------------------------------------------
1 | getActivityDescriptionForEvent($eventName);
15 |
16 | if ($message != '') {
17 | Activity::log($message);
18 | }
19 | });
20 | }
21 | }
22 |
23 | /**
24 | * Set the default events to be recorded if the $recordEvents
25 | * property does not exist on the model.
26 | *
27 | * @return array
28 | */
29 | protected static function getRecordActivityEvents()
30 | {
31 | if (isset(static::$recordEvents)) {
32 | return static::$recordEvents;
33 | }
34 |
35 | return [
36 | 'created', 'updated', 'deleting', 'deleted',
37 | ];
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Freek Van der Herten
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/Spatie/Activitylog/Handlers/EloquentHandler.php:
--------------------------------------------------------------------------------
1 | $text,
24 | 'user_id' => ($userId == '' ? null : $userId),
25 | 'ip_address' => $attributes['ipAddress'],
26 | ]
27 | );
28 |
29 | return true;
30 | }
31 |
32 | /**
33 | * Clean old log records.
34 | *
35 | * @param int $maxAgeInMonths
36 | *
37 | * @return bool
38 | */
39 | public function cleanLog($maxAgeInMonths)
40 | {
41 | $minimumDate = Carbon::now()->subMonths($maxAgeInMonths);
42 | Activity::where('created_at', '<=', $minimumDate)->delete();
43 |
44 | return true;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/Spatie/Activitylog/Models/Activity.php:
--------------------------------------------------------------------------------
1 | belongsTo($this->getAuthModelName(), 'user_id');
26 | }
27 |
28 | public function getAuthModelName()
29 | {
30 | if (config('activitylog.userModel')) {
31 | return config('activitylog.userModel');
32 | }
33 |
34 | //laravel 5.0 - 5.1
35 | if (! is_null(config('auth.model'))) {
36 | return config('auth.model');
37 | }
38 |
39 | //laravel 5.2
40 | if (! is_null(config('auth.providers.users.model'))) {
41 | return config('auth.providers.users.model');
42 | }
43 |
44 | throw new Exception('could not determine the model name for users');
45 | }
46 |
47 | protected $guarded = ['id'];
48 | }
49 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Contributions are **welcome** and will be fully **credited**.
4 |
5 | We accept contributions via Pull Requests on [Github](https://github.com/thephpleague/laravel-backup).
6 |
7 |
8 | ## Pull Requests
9 |
10 | - **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer).
11 |
12 | - **Add tests!** - Your patch won't be accepted if it doesn't have tests.
13 |
14 | - **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date.
15 |
16 | - **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option.
17 |
18 | - **Create feature branches** - Don't ask us to pull from your master branch.
19 |
20 | - **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
21 |
22 | - **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting.
23 |
24 |
25 | ## Running Tests
26 |
27 | ``` bash
28 | vendor/bin/phpunit
29 | ```
30 |
31 |
32 | **Happy coding**!
33 |
--------------------------------------------------------------------------------
/tests/ActivityLogSupervisorTest.php:
--------------------------------------------------------------------------------
1 | logHandler = Mockery::mock('\Spatie\Activitylog\Handlers\EloquentHandler');
15 | $this->config = Mockery::mock('\Illuminate\Config\Repository');
16 | $this->auth = Mockery::mock('Illuminate\Contracts\Auth\Guard');
17 |
18 | $this->config->shouldReceive('get')->andReturn(false);
19 | $this->activityLogSupervisor = new ActivitylogSupervisor($this->logHandler, $this->config, $this->auth);
20 | }
21 |
22 | /**
23 | * @test
24 | */
25 | public function it_normalizes_an_empty_user_id_when_noone_is_logged_in()
26 | {
27 | $this->auth->shouldReceive('check')->andReturn(false);
28 |
29 | $normalizedUserId = $this->activityLogSupervisor->normalizeUserId('');
30 |
31 | $this->assertSame('', $normalizedUserId);
32 | }
33 |
34 | /**
35 | * @test
36 | */
37 | public function it_normalizes_an_empty_user_id_when_someone_is_logged_in()
38 | {
39 | $user = json_decode(json_encode(['id' => 123]), false);
40 |
41 | $this->auth->shouldReceive('check')->andReturn(true);
42 | $this->auth->shouldReceive('user')->andReturn($user);
43 |
44 | $normalizedUserId = $this->activityLogSupervisor->normalizeUserId('');
45 |
46 | $this->assertSame(123, $normalizedUserId);
47 | }
48 |
49 | /**
50 | * @test
51 | */
52 | public function it_normalizes_a_numeric_user_id()
53 | {
54 | $normalizedUserId = $this->activityLogSupervisor->normalizeUserId(123);
55 |
56 | $this->assertSame(123, $normalizedUserId);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/Spatie/Activitylog/ActivitylogServiceProvider.php:
--------------------------------------------------------------------------------
1 | publishes([
23 | __DIR__ . '/../../config/activitylog.php' => config_path('activitylog.php'),
24 | ], 'config');
25 |
26 | if (!$this->migrationHasAlreadyBeenPublished()) {
27 | // Publish migration
28 | $timestamp = date('Y_m_d_His', time());
29 |
30 | $this->publishes([
31 | __DIR__ . "/../../migrations/create_activity_log_table.stub" => database_path("/migrations/{$timestamp}_create_activity_log_table.php"),
32 | ], 'migrations');
33 | }
34 | }
35 |
36 | /**
37 | * Register the service provider.
38 | */
39 | public function register()
40 | {
41 | $this->app->bind(
42 | 'activity',
43 | 'Spatie\Activitylog\ActivitylogSupervisor'
44 | );
45 |
46 | $this->app->bind(
47 | 'Spatie\Activitylog\Handlers\ActivitylogHandlerInterface',
48 | 'Spatie\Activitylog\Handlers\EloquentHandler'
49 | );
50 | }
51 |
52 | /**
53 | * Get the services provided by the provider.
54 | *
55 | * @return array
56 | */
57 | public function provides()
58 | {
59 | return [];
60 | }
61 |
62 | /**
63 | * @return bool
64 | */
65 | protected function migrationHasAlreadyBeenPublished()
66 | {
67 | $files = glob(database_path('/migrations/*_create_activity_log_table.php'));
68 |
69 | return count($files) > 0;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/config/activitylog.php:
--------------------------------------------------------------------------------
1 | true,
15 |
16 | /*
17 | |--------------------------------------------------------------------------
18 | | Max age in months for log records
19 | |--------------------------------------------------------------------------
20 | |
21 | | When running the cleanLog-command all recorder older than the number of months
22 | | specified here will be deleted
23 | |
24 | */
25 | 'deleteRecordsOlderThanMonths' => 2,
26 |
27 | /*
28 | |--------------------------------------------------------------------------
29 | | Fallback user id if no user is logged in
30 | |--------------------------------------------------------------------------
31 | |
32 | | If you don't specify a user id when logging some activity and no
33 | | user is logged in, this id will be used.
34 | |
35 | */
36 | 'defaultUserId' => '',
37 |
38 | /*
39 | |--------------------------------------------------------------------------
40 | | Handler that is called before logging is done
41 | |--------------------------------------------------------------------------
42 | |
43 | | If you want to disable logging based on some custom conditions, create
44 | | a handler class that implements the BeforeHandlerInterface and
45 | | reference it here.
46 | |
47 | */
48 | 'beforeHandler' => null,
49 |
50 | /*
51 | |--------------------------------------------------------------------------
52 | | The class name for the related user model
53 | |--------------------------------------------------------------------------
54 | |
55 | | This can be a class name or null. If null the model will be determined
56 | | from Laravel's auth configuration.
57 | |
58 | */
59 | 'userModel' => null,
60 | ];
61 |
--------------------------------------------------------------------------------
/src/Spatie/Activitylog/ActivitylogSupervisor.php:
--------------------------------------------------------------------------------
1 | config = $config;
34 |
35 | $this->logHandlers[] = $logHandler;
36 |
37 | if ($this->config->get('activitylog.alsoLogInDefaultLog')) {
38 | $this->logHandlers[] = new DefaultLaravelHandler();
39 | }
40 |
41 | $this->auth = $auth;
42 | }
43 |
44 | /**
45 | * Log some activity to all registered log handlers.
46 | *
47 | * @param $text
48 | * @param string $userId
49 | *
50 | * @return bool
51 | */
52 | public function log($text, $userId = '')
53 | {
54 | $userId = $this->normalizeUserId($userId);
55 |
56 | if (! $this->shouldLogCall($text, $userId)) {
57 | return false;
58 | }
59 |
60 | $ipAddress = Request::getClientIp();
61 |
62 | foreach ($this->logHandlers as $logHandler) {
63 | $logHandler->log($text, $userId, compact('ipAddress'));
64 | }
65 |
66 | return true;
67 | }
68 |
69 | /**
70 | * Clean out old entries in the log.
71 | *
72 | * @return bool
73 | */
74 | public function cleanLog()
75 | {
76 | foreach ($this->logHandlers as $logHandler) {
77 | $logHandler->cleanLog(Config::get('activitylog.deleteRecordsOlderThanMonths'));
78 | }
79 |
80 | return true;
81 | }
82 |
83 | /**
84 | * Normalize the user id.
85 | *
86 | * @param object|int $userId
87 | *
88 | * @return int
89 | */
90 | public function normalizeUserId($userId)
91 | {
92 | if (is_numeric($userId)) {
93 | return $userId;
94 | }
95 |
96 | if (is_object($userId)) {
97 | return $userId->id;
98 | }
99 |
100 | if ($this->auth->check()) {
101 | return $this->auth->user()->id;
102 | }
103 |
104 | if (is_numeric($this->config->get('activitylog.defaultUserId'))) {
105 | return $this->config->get('activitylog.defaultUserId');
106 | };
107 |
108 | return '';
109 | }
110 |
111 | /**
112 | * Determine if this call should be logged.
113 | *
114 | * @param $text
115 | * @param $userId
116 | *
117 | * @return bool
118 | */
119 | protected function shouldLogCall($text, $userId)
120 | {
121 | $beforeHandler = $this->config->get('activitylog.beforeHandler');
122 |
123 | if (is_null($beforeHandler) || $beforeHandler == '') {
124 | return true;
125 | }
126 |
127 | return app($beforeHandler)->shouldLog($text, $userId);
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Log the activity of your users
2 |
3 | [](https://github.com/spatie/activitylog/releases)
4 | [](LICENSE.md)
5 | [](https://travis-ci.org/spatie/activitylog)
6 | [](https://insight.sensiolabs.com/projects/c48809c7-cdb3-4e86-974b-ad9c6282bc3c)
7 | [](https://packagist.org/packages/spatie/activitylog)
8 |
9 | ## EOL-warning
10 |
11 | This package has been abandoned on 2016-06-28. Please use [laravel-activitylog](https://github.com/spatie/laravel-activitylog) instead.
12 |
13 | ## Description
14 |
15 | This Laravel 5 package provides a very easy to use solution to log the activities of the users of your Laravel 5 app. All the activities will be logged in a db-table. Optionally the activities can also be logged against the default Laravel Log Handler.
16 |
17 | Spatie is a webdesign agency in Antwerp, Belgium. You'll find an overview of all our open source projects [on our website](https://spatie.be/opensource).
18 |
19 | ### Note:
20 |
21 | If you're using Laravel 4, take a look at version 0.3.0 of this package.
22 |
23 | ## Postcardware
24 |
25 | You're free to use this package (it's [MIT-licensed](LICENSE.md)), but if it makes it to your production environment you are required to send us a postcard from your hometown, mentioning which of our package(s) you are using.
26 |
27 | Our address is: Spatie, Samberstraat 69D, 2060 Antwerp, Belgium.
28 |
29 | The best postcards will get published on the open source page on our website.
30 |
31 | ## Installation
32 |
33 | This package can be installed through Composer.
34 | ```bash
35 | composer require spatie/activitylog
36 | ```
37 |
38 |
39 | This service provider must be registered.
40 | ```php
41 | // config/app.php
42 |
43 | 'providers' => [
44 | '...',
45 | 'Spatie\Activitylog\ActivitylogServiceProvider',
46 | ];
47 | ```
48 |
49 |
50 | You'll also need to publish and run the migration in order to create the db-table.
51 | ```
52 | php artisan vendor:publish --provider="Spatie\Activitylog\ActivitylogServiceProvider" --tag="migrations"
53 | php artisan migrate
54 | ```
55 |
56 |
57 | Activitylog also comes with a facade, which provides an easy way to call it.
58 | ```php
59 | // config/app.php
60 |
61 | 'aliases' => [
62 | ...
63 | 'Activity' => 'Spatie\Activitylog\ActivitylogFacade',
64 | ];
65 | ```
66 |
67 |
68 | Optionally you can publish the config file of this package.
69 | ```
70 | php artisan vendor:publish --provider="Spatie\Activitylog\ActivitylogServiceProvider" --tag="config"
71 | ```
72 | The configuration will be written to ```config/activitylog.php```. The options provided are self explanatory.
73 |
74 |
75 | ## Usage
76 |
77 | ### Manual logging
78 |
79 | Logging some activity is very simple.
80 | ```php
81 | //at the top of your file you should import the facade.
82 | use Activity;
83 | ...
84 | /*
85 | The log-function takes two parameters:
86 | - $text: the activity you wish to log.
87 | - $user: optional can be an user id or a user object.
88 | if not proved the id of Auth::user() will be used
89 |
90 | */
91 | Activity::log('Some activity that you wish to log');
92 | ```
93 | The string you pass to function gets written in a db-table together with a timestamp, the ip address and the user agent of the user.
94 |
95 | ### Log model events
96 | This package can log the events from your models. To do so your model must use the `LogsActivity`-trait and implement `LogsActivityInterface`.
97 |
98 | ```php
99 | use Spatie\Activitylog\LogsActivityInterface;
100 | use Spatie\Activitylog\LogsActivity;
101 |
102 | class Article implements LogsActivityInterface {
103 |
104 | use LogsActivity;
105 | ...
106 | ```
107 |
108 | The interface expects you to implement the `getActivityDescriptionForEvent`-function.
109 |
110 | Here's an example of a possible implementation.
111 |
112 | ```php
113 | /**
114 | * Get the message that needs to be logged for the given event name.
115 | *
116 | * @param string $eventName
117 | * @return string
118 | */
119 | public function getActivityDescriptionForEvent($eventName)
120 | {
121 | if ($eventName == 'created')
122 | {
123 | return 'Article "' . $this->name . '" was created';
124 | }
125 |
126 | if ($eventName == 'updated')
127 | {
128 | return 'Article "' . $this->name . '" was updated';
129 | }
130 |
131 | if ($eventName == 'deleted')
132 | {
133 | return 'Article "' . $this->name . '" was deleted';
134 | }
135 |
136 | return '';
137 | }
138 | ```
139 | The result of this function will be logged, unless the result is an empty string.
140 |
141 | ### Using a before handler.
142 | If you want to disable logging under certain conditions,
143 | such as for a specific user, create a class in your application
144 | namespace that implements the `Spatie\Activitylog\Handlers\BeforeHandlerInterface`.
145 |
146 | This interface defines an `shouldLog()` method in which you can code any custom logic to determine
147 | whether logging should be ignored or not. You must return `true` the call should be logged.
148 |
149 | To en the namespaced class nameto the `beforeHandler` field in the configuration file:
150 | ```php
151 | 'beforeHandler' => '\App\Handlers\BeforeHandler',
152 | ```
153 |
154 | For example, this callback class could look like this to disable
155 | logging a user with id of 1:
156 | ```php
157 | latest()->limit(100)->get();
181 | ```
182 |
183 | ### Cleaning up the log
184 |
185 | Over time your log will grow. To clean up the database table you can run this command:
186 | ```php
187 | Activity::cleanLog();
188 | ```
189 | By default records older than 2 months will be deleted. The number of months can be modified in the config-file of the package.
190 |
191 | ## Contributing
192 |
193 | Please see [CONTRIBUTING](CONTRIBUTING.md) for details.
194 |
195 | ## Security
196 |
197 | If you discover any security related issues, please email freek@spatie.be instead of using the issue tracker.
198 |
199 | ## Credits
200 |
201 | - [Freek Van der Herten](https://github.com/freekmurze)
202 | - [All Contributors](../../contributors)
203 |
204 | ## About Spatie
205 | Spatie is a webdesign agency in Antwerp, Belgium. You'll find an overview of all our open source projects [on our website](https://spatie.be/opensource).
206 |
207 | ## License
208 |
209 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
210 |
--------------------------------------------------------------------------------