diff --git a/.gitignore b/.gitignore
index f02a2f8..85d90cf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@ build
composer.lock
docs
vendor
+.idea
diff --git a/.idea/laravel-activitylog-extended.iml b/.idea/laravel-activitylog-extended.iml
index e50c58c..17b75cc 100644
--- a/.idea/laravel-activitylog-extended.iml
+++ b/.idea/laravel-activitylog-extended.iml
@@ -115,6 +115,10 @@
+
+
+
+
diff --git a/.idea/php-test-framework.xml b/.idea/php-test-framework.xml
index fc195b9..a01bbcb 100644
--- a/.idea/php-test-framework.xml
+++ b/.idea/php-test-framework.xml
@@ -6,6 +6,7 @@
+
diff --git a/.idea/php.xml b/.idea/php.xml
index 5acac42..ecde23c 100644
--- a/.idea/php.xml
+++ b/.idea/php.xml
@@ -112,9 +112,94 @@
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+ /etc/php/8.1/cli/conf.d/10-mysqlnd.ini, /etc/php/8.1/cli/conf.d/10-opcache.ini, /etc/php/8.1/cli/conf.d/10-pdo.ini, /etc/php/8.1/cli/conf.d/15-xml.ini, /etc/php/8.1/cli/conf.d/20-ast.ini, /etc/php/8.1/cli/conf.d/20-bcmath.ini, /etc/php/8.1/cli/conf.d/20-calendar.ini, /etc/php/8.1/cli/conf.d/20-ctype.ini, /etc/php/8.1/cli/conf.d/20-curl.ini, /etc/php/8.1/cli/conf.d/20-dom.ini, /etc/php/8.1/cli/conf.d/20-exif.ini, /etc/php/8.1/cli/conf.d/20-ffi.ini, /etc/php/8.1/cli/conf.d/20-fileinfo.ini, /etc/php/8.1/cli/conf.d/20-ftp.ini, /etc/php/8.1/cli/conf.d/20-gd.ini, /etc/php/8.1/cli/conf.d/20-gettext.ini, /etc/php/8.1/cli/conf.d/20-iconv.ini, /etc/php/8.1/cli/conf.d/20-igbinary.ini, /etc/php/8.1/cli/conf.d/20-intl.ini, /etc/php/8.1/cli/conf.d/20-mbstring.ini, /etc/php/8.1/cli/conf.d/20-msgpack.ini, /etc/php/8.1/cli/conf.d/20-mysqli.ini, /etc/php/8.1/cli/conf.d/20-pdo_mysql.ini, /etc/php/8.1/cli/conf.d/20-pdo_pgsql.ini, /etc/php/8.1/cli/conf.d/20-pdo_sqlite.ini, /etc/php/8.1/cli/conf.d/20-pgsql.ini, /etc/php/8.1/cli/conf.d/20-phar.ini, /etc/php/8.1/cli/conf.d/20-posix.ini, /etc/php/8.1/cli/conf.d/20-readline.ini, /etc/php/8.1/cli/conf.d/20-redis.ini, /etc/php/8.1/cli/conf.d/20-shmop.ini, /etc/php/8.1/cli/conf.d/20-simplexml.ini, /etc/php/8.1/cli/conf.d/20-soap.ini, /etc/php/8.1/cli/conf.d/20-sockets.ini, /etc/php/8.1/cli/conf.d/20-sqlite3.ini, /etc/php/8.1/cli/conf.d/20-sysvmsg.ini, /etc/php/8.1/cli/conf.d/20-sysvsem.ini, /etc/php/8.1/cli/conf.d/20-sysvshm.ini, /etc/php/8.1/cli/conf.d/20-tokenizer.ini, /etc/php/8.1/cli/conf.d/20-xmlreader.ini, /etc/php/8.1/cli/conf.d/20-xmlwriter.ini, /etc/php/8.1/cli/conf.d/20-xsl.ini, /etc/php/8.1/cli/conf.d/20-zip.ini, /etc/php/8.1/cli/conf.d/25-memcached.ini, /etc/php/8.1/cli/conf.d/xdebug.ini
+ /etc/php/8.1/cli/php.ini
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.phpunit.result.cache b/.phpunit.result.cache
index 42cba6c..3b52cb7 100644
--- a/.phpunit.result.cache
+++ b/.phpunit.result.cache
@@ -1 +1 @@
-{"version":1,"defects":{"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_activities_from_a_specific_log":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_from_multiple_logs":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_from_multiple_logs_using_an_array":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_for_a_specific_causer":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_for_a_specific_subject":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_all_log_items_related_to_subject":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_for_a_specific_morphmapped_causer":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_for_a_specific_morphmapped_subject":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_not_log_an_activity_when_the_log_is_not_enabled":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_log_an_activity_when_enabled_option_is_null":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_log_to_the_default_log_by_default":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_to_a_specific_log":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_with_a_subject":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_with_a_causer":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_with_a_causer_when_there_is_no_web_guard":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_activity_with_properties":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_activity_with_a_single_properties":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_translate_a_given_causer_id_to_an_object":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_throw_an_exception_if_it_cannot_translate_a_causer_id":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_use_the_logged_in_user_as_the_causer_by_default":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_replace_the_placeholders":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_not_replace_non_placeholders":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_returns_an_instance_of_the_activity_log_after_logging_when_using_a_custom_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CausesActivityTest::it_can_get_all_activity_for_the_causer":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CleanActivitylogCommandTest::it_can_clean_the_activity_log":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomActivityModelTest::it_can_log_activity_using_a_custom_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomActivityModelTest::it_does_not_throw_an_exception_when_model_config_is_null":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomActivityModelTest::it_throws_an_exception_when_model_doesnt_implements_activity":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomActivityModelTest::it_throws_an_exception_when_model_doesnt_extend_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomActivityModelTest::it_doesnt_conlict_with_laravel_change_tracking":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_values_when_creating_a_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_relation_values_when_creating_a_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_empty_relation_when_creating_a_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_when_updating_a_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_dirty_changes_only":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_dirty_changes_for_swapping_values":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_when_updating_a_related_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_dirty_changes_when_updating_a_related_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_will_store_no_changes_when_not_logging_attributes":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_will_store_the_values_when_deleting_the_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_will_store_the_values_when_deleting_the_model_with_softdeletes":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_of_array_casted_properties":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_nothing_as_loggable_attributes":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_text_as_loggable_attributes":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_fillable_as_loggable_attributes":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_both_fillable_and_log_attributes":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_wildcard_for_loggable_attributes":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_wildcard_with_relation":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_wildcard_when_updating_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\HasActivityTest::it_can_log_activity_on_subject_by_same_causer":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_the_creation_of_the_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_skip_logging_model_events_if_asked_to":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_switch_on_activity_logging_after_disabling_it":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_skip_logging_if_asked_to_for_update_method":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_an_update_of_the_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_the_deletion_of_a_model_without_softdeletes":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_the_deletion_of_a_model_with_softdeletes":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_the_restoring_of_a_model_with_softdeletes":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_fetch_all_activity_for_a_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_fetch_soft_deleted_models":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_log_activity_to_log_returned_from_model_method_override":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_log_activity_to_log_named_in_the_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_not_log_an_update_of_the_model_if_only_ignored_attributes_are_changed":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_not_fail_if_asked_to_replace_from_empty_attribute":4},"times":{"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_activities_from_a_specific_log":0.316,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_from_multiple_logs":0.098,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_from_multiple_logs_using_an_array":0.11,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_for_a_specific_causer":0.143,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_for_a_specific_subject":0.116,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_all_log_items_related_to_subject":0.129,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_for_a_specific_morphmapped_causer":0.118,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_for_a_specific_morphmapped_subject":0.108,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity":0.078,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_not_log_an_activity_when_the_log_is_not_enabled":0.075,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_log_an_activity_when_enabled_option_is_null":0.082,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_log_to_the_default_log_by_default":0.086,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_to_a_specific_log":0.086,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_with_a_subject":0.08,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_with_a_causer":0.08,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_with_a_causer_when_there_is_no_web_guard":0.08,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_activity_with_properties":0.081,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_activity_with_a_single_properties":0.083,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_translate_a_given_causer_id_to_an_object":0.083,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_throw_an_exception_if_it_cannot_translate_a_causer_id":0.095,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_use_the_logged_in_user_as_the_causer_by_default":0.227,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_replace_the_placeholders":0.258,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_not_replace_non_placeholders":0.16,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_returns_an_instance_of_the_activity_log_after_logging_when_using_a_custom_model":0.088,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CausesActivityTest::it_can_get_all_activity_for_the_causer":0.107,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CleanActivitylogCommandTest::it_can_clean_the_activity_log":0.573,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomActivityModelTest::it_can_log_activity_using_a_custom_model":0.108,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomActivityModelTest::it_does_not_throw_an_exception_when_model_config_is_null":0.104,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomActivityModelTest::it_throws_an_exception_when_model_doesnt_implements_activity":0.101,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomActivityModelTest::it_throws_an_exception_when_model_doesnt_extend_model":0.097,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomActivityModelTest::it_doesnt_conlict_with_laravel_change_tracking":0.102,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_values_when_creating_a_model":0.088,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_relation_values_when_creating_a_model":0.098,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_empty_relation_when_creating_a_model":0.101,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_when_updating_a_model":0.094,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_dirty_changes_only":0.095,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_dirty_changes_for_swapping_values":0.093,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_when_updating_a_related_model":0.101,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_dirty_changes_when_updating_a_related_model":0.103,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_will_store_no_changes_when_not_logging_attributes":0.089,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_will_store_the_values_when_deleting_the_model":0.23,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_will_store_the_values_when_deleting_the_model_with_softdeletes":0.315,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_of_array_casted_properties":0.243,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_nothing_as_loggable_attributes":0.084,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_text_as_loggable_attributes":0.083,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_fillable_as_loggable_attributes":0.085,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_both_fillable_and_log_attributes":0.086,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_wildcard_for_loggable_attributes":0.087,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_wildcard_with_relation":0.088,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_wildcard_when_updating_model":0.104,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\HasActivityTest::it_can_log_activity_on_subject_by_same_causer":0.084,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_the_creation_of_the_model":0.085,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_skip_logging_model_events_if_asked_to":0.081,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_switch_on_activity_logging_after_disabling_it":0.143,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_skip_logging_if_asked_to_for_update_method":0.233,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_an_update_of_the_model":0.243,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_the_deletion_of_a_model_without_softdeletes":0.09,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_the_deletion_of_a_model_with_softdeletes":0.099,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_the_restoring_of_a_model_with_softdeletes":0.105,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_fetch_all_activity_for_a_model":0.098,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_fetch_soft_deleted_models":0.105,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_log_activity_to_log_returned_from_model_method_override":0.089,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_log_activity_to_log_named_in_the_model":0.094,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_not_log_an_update_of_the_model_if_only_ignored_attributes_are_changed":0.102,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_not_fail_if_asked_to_replace_from_empty_attribute":0.098}}
\ No newline at end of file
+{"version":1,"defects":{"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_activities_from_a_specific_log":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_from_multiple_logs":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_from_multiple_logs_using_an_array":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_for_a_specific_causer":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_for_a_specific_subject":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_all_log_items_related_to_subject":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_for_a_specific_morphmapped_causer":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_for_a_specific_morphmapped_subject":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_not_log_an_activity_when_the_log_is_not_enabled":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_log_an_activity_when_enabled_option_is_null":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_log_to_the_default_log_by_default":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_to_a_specific_log":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_with_a_subject":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_with_a_causer":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_with_a_causer_when_there_is_no_web_guard":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_activity_with_properties":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_activity_with_a_single_properties":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_translate_a_given_causer_id_to_an_object":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_throw_an_exception_if_it_cannot_translate_a_causer_id":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_use_the_logged_in_user_as_the_causer_by_default":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_replace_the_placeholders":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_not_replace_non_placeholders":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_returns_an_instance_of_the_activity_log_after_logging_when_using_a_custom_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CausesActivityTest::it_can_get_all_activity_for_the_causer":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CleanActivitylogCommandTest::it_can_clean_the_activity_log":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomActivityModelTest::it_can_log_activity_using_a_custom_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomActivityModelTest::it_does_not_throw_an_exception_when_model_config_is_null":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomActivityModelTest::it_throws_an_exception_when_model_doesnt_implements_activity":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomActivityModelTest::it_throws_an_exception_when_model_doesnt_extend_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomActivityModelTest::it_doesnt_conlict_with_laravel_change_tracking":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_values_when_creating_a_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_relation_values_when_creating_a_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_empty_relation_when_creating_a_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_when_updating_a_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_dirty_changes_only":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_dirty_changes_for_swapping_values":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_when_updating_a_related_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_dirty_changes_when_updating_a_related_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_will_store_no_changes_when_not_logging_attributes":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_will_store_the_values_when_deleting_the_model":3,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_will_store_the_values_when_deleting_the_model_with_softdeletes":3,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_of_array_casted_properties":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_nothing_as_loggable_attributes":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_text_as_loggable_attributes":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_fillable_as_loggable_attributes":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_both_fillable_and_log_attributes":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_wildcard_for_loggable_attributes":3,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_wildcard_with_relation":3,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_wildcard_when_updating_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\HasActivityTest::it_can_log_activity_on_subject_by_same_causer":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_the_creation_of_the_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_skip_logging_model_events_if_asked_to":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_switch_on_activity_logging_after_disabling_it":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_skip_logging_if_asked_to_for_update_method":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_an_update_of_the_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_the_deletion_of_a_model_without_softdeletes":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_the_deletion_of_a_model_with_softdeletes":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_the_restoring_of_a_model_with_softdeletes":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_fetch_all_activity_for_a_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_fetch_soft_deleted_models":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_log_activity_to_log_returned_from_model_method_override":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_log_activity_to_log_named_in_the_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_not_log_an_update_of_the_model_if_only_ignored_attributes_are_changed":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_not_fail_if_asked_to_replace_from_empty_attribute":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_activity_when_attributes_are_changed_with_tap":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_disable_logs_for_a_callback_without_affecting_previous_state_even_with_exception":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_with_a_causer_other_than_user_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_with_a_causer_that_has_been_set_from_other_context":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_activity_using_an_anonymous_causer":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_override_the_logged_in_user_as_the_causer_when_an_anonymous_causer_is_specified":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_with_event":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_not_log_an_activity_when_the_log_is_manually_disabled":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_log_an_activity_when_the_log_is_manually_enabled":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_accepts_null_parameter_for_caused_by":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_log_a_custom_created_at_date_time":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_disable_logs_for_a_callback":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_disable_logs_for_a_callback_without_affecting_previous_state":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_disable_logs_for_a_callback_without_affecting_previous_state_even_when_already_disabled":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CauserResolverTest::it_can_resolve_current_logged_in_user":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CauserResolverTest::it_will_throw_an_exception_if_it_cannot_resolve_user_by_id":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CauserResolverTest::it_can_resloved_user_from_passed_id":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CauserResolverTest::it_will_resolve_the_provided_override_callback":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CauserResolverTest::it_will_resolve_any_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomDatabaseConnectionActivityModelTest::it_uses_the_database_connection_from_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomTableNameModelTest::uses_the_table_name_from_the_configuration":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomTableNameModelTest::uses_a_custom_table_name":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomTableNameModelTest::uses_the_table_name_from_the_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_log_activity_when_attributes_are_changed_with_tap":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_log_activity_when_description_is_changed_with_tap":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_log_activity_when_event_is_changed_with_tap":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_the_retrieval_of_the_model":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_detect_changes_for_date_inteval_attributes":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_removes_key_event_if_it_was_loggable":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_when_saving_including_multi_level_related_model":3,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_overloaded_as_loggable_attributes":4,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_detect_changes_for_null_date_inteval_attributes":3},"times":{"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_activities_from_a_specific_log":1.615,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_from_multiple_logs":0.584,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_from_multiple_logs_using_an_array":0.58,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_for_a_specific_causer":0.694,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_for_a_specific_subject":0.682,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_all_log_items_related_to_subject":0.781,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_for_a_specific_morphmapped_causer":0.682,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityModelTest::it_provides_a_scope_to_get_log_items_for_a_specific_morphmapped_subject":0.695,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity":0.453,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_not_log_an_activity_when_the_log_is_not_enabled":0.434,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_log_an_activity_when_enabled_option_is_null":0.459,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_log_to_the_default_log_by_default":0.467,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_to_a_specific_log":0.5,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_with_a_subject":0.471,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_with_a_causer":0.465,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_with_a_causer_when_there_is_no_web_guard":0.468,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_activity_with_properties":0.475,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_activity_with_a_single_properties":0.465,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_translate_a_given_causer_id_to_an_object":0.647,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_throw_an_exception_if_it_cannot_translate_a_causer_id":0.443,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_use_the_logged_in_user_as_the_causer_by_default":0.561,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_replace_the_placeholders":0.573,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_not_replace_non_placeholders":0.68,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_returns_an_instance_of_the_activity_log_after_logging_when_using_a_custom_model":0.647,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CausesActivityTest::it_can_get_all_activity_for_the_causer":0.8,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CleanActivitylogCommandTest::it_can_clean_the_activity_log":3.147,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomActivityModelTest::it_can_log_activity_using_a_custom_model":0.722,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomActivityModelTest::it_does_not_throw_an_exception_when_model_config_is_null":0.719,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomActivityModelTest::it_throws_an_exception_when_model_doesnt_implements_activity":0.688,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomActivityModelTest::it_throws_an_exception_when_model_doesnt_extend_model":0.682,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomActivityModelTest::it_doesnt_conlict_with_laravel_change_tracking":0.741,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_values_when_creating_a_model":0.594,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_relation_values_when_creating_a_model":0.8,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_empty_relation_when_creating_a_model":0.817,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_when_updating_a_model":0.749,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_dirty_changes_only":0.729,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_dirty_changes_for_swapping_values":0.909,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_when_updating_a_related_model":0.906,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_dirty_changes_when_updating_a_related_model":0.728,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_will_store_no_changes_when_not_logging_attributes":0.601,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_will_store_the_values_when_deleting_the_model":0.692,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_will_store_the_values_when_deleting_the_model_with_softdeletes":0.748,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_of_array_casted_properties":0.66,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_nothing_as_loggable_attributes":0.588,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_text_as_loggable_attributes":0.579,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_fillable_as_loggable_attributes":0.691,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_both_fillable_and_log_attributes":0.635,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_wildcard_for_loggable_attributes":0.592,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_wildcard_with_relation":0.7,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_wildcard_when_updating_model":0.9,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\HasActivityTest::it_can_log_activity_on_subject_by_same_causer":0.628,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_the_creation_of_the_model":0.77,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_skip_logging_model_events_if_asked_to":0.647,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_switch_on_activity_logging_after_disabling_it":0.744,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_skip_logging_if_asked_to_for_update_method":0.651,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_an_update_of_the_model":0.922,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_the_deletion_of_a_model_without_softdeletes":0.696,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_the_deletion_of_a_model_with_softdeletes":0.785,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_the_restoring_of_a_model_with_softdeletes":0.832,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_fetch_all_activity_for_a_model":0.674,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_fetch_soft_deleted_models":0.75,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_log_activity_to_log_returned_from_model_method_override":0.618,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_log_activity_to_log_named_in_the_model":0.575,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_not_log_an_update_of_the_model_if_only_ignored_attributes_are_changed":0.636,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_not_fail_if_asked_to_replace_from_empty_attribute":0.672,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_with_a_causer_other_than_user_model":0.46,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_with_a_causer_that_has_been_set_from_other_context":0.476,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_activity_using_an_anonymous_causer":0.52,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_override_the_logged_in_user_as_the_causer_when_an_anonymous_causer_is_specified":0.474,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_an_activity_with_event":0.94,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_not_log_an_activity_when_the_log_is_manually_disabled":0.553,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_log_an_activity_when_the_log_is_manually_enabled":0.554,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_accepts_null_parameter_for_caused_by":0.556,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_can_log_activity_when_attributes_are_changed_with_tap":0.639,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_log_a_custom_created_at_date_time":0.605,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_disable_logs_for_a_callback":0.531,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_disable_logs_for_a_callback_without_affecting_previous_state":0.659,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_disable_logs_for_a_callback_without_affecting_previous_state_even_when_already_disabled":0.602,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\ActivityloggerTest::it_will_disable_logs_for_a_callback_without_affecting_previous_state_even_with_exception":0.556,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CauserResolverTest::it_can_resolve_current_logged_in_user":0.543,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CauserResolverTest::it_will_throw_an_exception_if_it_cannot_resolve_user_by_id":0.538,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CauserResolverTest::it_can_resloved_user_from_passed_id":0.603,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CauserResolverTest::it_will_resolve_the_provided_override_callback":0.862,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CauserResolverTest::it_will_resolve_any_model":0.873,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CleanActivitylogCommandTest::it_can_accept_days_as_option_to_override_config_setting":2.854,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomDatabaseConnectionActivityModelTest::it_uses_the_database_connection_from_the_configuration":0.806,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomDatabaseConnectionActivityModelTest::it_uses_a_custom_database_connection":0.758,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomDatabaseConnectionActivityModelTest::it_uses_the_default_database_connection_when_the_one_from_configuration_is_null":0.805,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomDatabaseConnectionActivityModelTest::it_uses_the_database_connection_from_model":0.842,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomTableNameModelTest::uses_the_table_name_from_the_configuration":0.843,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomTableNameModelTest::uses_a_custom_table_name":0.783,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\CustomTableNameModelTest::uses_the_table_name_from_the_model":0.689,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogBatchTest::it_generates_uuid_after_start_and_end_batch_properely":0.701,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogBatchTest::it_returns_null_uuid_after_end_batch_properely":0.697,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogBatchTest::it_generates_a_new_uuid_after_starting_new_batch_properly":0.698,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogBatchTest::it_will_not_generate_new_uuid_if_start_already_started_batch":0.713,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogBatchTest::it_will_not_generate_uuid_if_end_batch_before_starting":0.732,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogBatchTest::it_can_set_uuid_and_start_a_batch":0.709,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogBatchTest::it_can_set_uuid_for_already_started_batch":0.728,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogBatchTest::it_will_not_return_null_uuid_if_end_batch_that_started_twice":0.697,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogBatchTest::it_will_return_null_uuid_if_end_batch_that_started_twice_properly":0.679,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::can_log_activity_on_subject_by_same_causer":0.941,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_log_activity_when_attributes_are_changed_with_tap":0.735,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_log_activity_when_description_is_changed_with_tap":0.609,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_can_log_activity_when_event_is_changed_with_tap":0.573,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_not_submit_log_when_there_is_no_changes":0.624,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_submit_a_log_with_json_changes":0.68,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_log_the_retrieval_of_the_model":0.637,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\LogsActivityTest::it_will_not_log_casted_attribute_of_the_model_if_attribute_raw_values_is_used":0.607,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_deep_diff_check_json_field":0.639,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_detect_changes_for_date_inteval_attributes":0.677,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_detect_changes_for_null_date_inteval_attributes":0.925,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_retruns_same_uuid_for_all_log_changes_under_one_batch":1.078,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_assigns_new_uuid_for_multiple_change_logs_in_different_batches":0.858,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_removes_key_event_if_it_was_loggable":0.772,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_when_updating_a_snake_case_related_model":0.711,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_when_updating_a_camel_case_related_model":0.712,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_when_updating_a_custom_case_related_model":0.881,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_when_saving_including_multi_level_related_model":0.877,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_of_collection_casted_properties":0.835,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_of_json_casted_properties":0.732,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_when_a_boolean_field_is_changed_from_false_to_null":0.806,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_ignored_attributes_while_updating":0.602,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_unguarded_as_loggable_attributes":0.578,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_will_store_no_changes_when_wildcard_guard_and_log_unguarded_attributes":0.581,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_hidden_as_loggable_attributes":0.6,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_overloaded_as_loggable_attributes":0.705,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_mutated_as_loggable_attributes":0.749,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_accessor_as_loggable_attributes":0.706,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_encrypted_as_loggable_attributes":0.779,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_casted_as_loggable_attribute":0.821,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_nullable_date_as_loggable_attributes":0.646,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_custom_date_cast_as_loggable_attributes":0.619,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_use_custom_immutable_date_cast_as_loggable_attributes":0.587,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_can_store_the_changes_of_json_attributes":0.618,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_will_not_store_changes_to_untracked_json":0.856,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_will_return_null_for_missing_json_attribute":0.728,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_will_return_an_array_for_sub_key_in_json_attribute":0.646,"Padosoft\\Laravel\\ActivitylogExtended\\Test\\DetectsChangesTest::it_will_access_further_than_level_one_json_attribute":0.657}}
\ No newline at end of file
diff --git a/composer.json b/composer.json
index 4475223..702c5d2 100644
--- a/composer.json
+++ b/composer.json
@@ -20,7 +20,7 @@
}
],
"require": {
- "spatie/laravel-activitylog": "^3.6"
+ "spatie/laravel-activitylog": "^4.0"
},
"require-dev": {
"roave/security-advisories": "dev-latest",
diff --git a/src/Models/Activity.php b/src/Models/Activity.php
index 87cbfa6..958a3eb 100644
--- a/src/Models/Activity.php
+++ b/src/Models/Activity.php
@@ -10,8 +10,40 @@
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Request;
+/**
+ * Padosoft\Laravel\ActivitylogExtended\Models\Activity.
+ *
+ * @property int $id
+ * @property string|null $log_name
+ * @property string $description
+ * @property string|null $subject_type
+ * @property int|null $subject_id
+ * @property string|null $causer_type
+ * @property int|null $causer_id
+ * @property \Illuminate\Support\Collection|null $properties
+ * @property \Carbon\Carbon|null $created_at
+ * @property \Carbon\Carbon|null $updated_at
+ * @property-read \Illuminate\Database\Eloquent\Model|\Eloquent $causer
+ * @property-read \Illuminate\Support\Collection $changes
+ * @property-read \Illuminate\Database\Eloquent\Model|\Eloquent $subject
+ *
+ * @method static \Illuminate\Database\Eloquent\Builder|\Spatie\Activitylog\Models\Activity causedBy(\Illuminate\Database\Eloquent\Model $causer)
+ * @method static \Illuminate\Database\Eloquent\Builder|\Spatie\Activitylog\Models\Activity forBatch(string $batchUuid)
+ * @method static \Illuminate\Database\Eloquent\Builder|\Spatie\Activitylog\Models\Activity forEvent(string $event)
+ * @method static \Illuminate\Database\Eloquent\Builder|\Spatie\Activitylog\Models\Activity forSubject(\Illuminate\Database\Eloquent\Model $subject)
+ * @method static \Illuminate\Database\Eloquent\Builder|\Spatie\Activitylog\Models\Activity hasBatch()
+ * @method static \Illuminate\Database\Eloquent\Builder|\Spatie\Activitylog\Models\Activity inLog($logNames)
+ * @method static \Illuminate\Database\Eloquent\Builder|\Spatie\Activitylog\Models\Activity newModelQuery()
+ * @method static \Illuminate\Database\Eloquent\Builder|\Spatie\Activitylog\Models\Activity newQuery()
+ * @method static \Illuminate\Database\Eloquent\Builder|\Spatie\Activitylog\Models\Activity query()
+ */
class Activity extends ActivityBase
{
+ public function __construct(array $attributes = [])
+ {
+ parent::__construct($attributes);
+ }
+
protected static function boot()
{
parent::boot();
@@ -22,17 +54,17 @@ protected static function boot()
});
}
- public function resolveIp()
+ public function resolveIp(): ?string
{
return Request::ip();
}
- public function resolveUserAgent()
+ public function resolveUserAgent(): array|string|null
{
return Request::header('User-Agent');
}
- public function resolveUrl()
+ public function resolveUrl(): string
{
if (!App::runningInConsole()) {
return Request::fullUrlWithQuery([]);
@@ -44,20 +76,15 @@ public function resolveUrl()
return 'console';
}
- public function __construct(array $attributes = [])
- {
- parent::__construct($attributes);
- }
-
public function scopeAllRelations(Builder $query, \Illuminate\Database\Eloquent\Model $subject): Builder
{
return $query
->where(function ($q) use ($subject) {
$q->where('subject_type', '=', $subject->getMorphClass())
- ->where('subject_id', $subject->getKey());
+ ->where('subject_id', $subject->getKey());
})->orWhere(function ($q) use ($subject) {
$q->where('causer_type', '=', $subject->getMorphClass())
- ->where('causer_id', $subject->getKey());
+ ->where('causer_id', $subject->getKey());
})->orWhere('properties', 'LIKE', '%' . $subject->getTable() . '":"' . $subject->getKey() . '"%');
}
}
diff --git a/src/Traits/LogsActivityWithRelations.php b/src/Traits/LogsActivityWithRelations.php
index e4a08a6..102caea 100644
--- a/src/Traits/LogsActivityWithRelations.php
+++ b/src/Traits/LogsActivityWithRelations.php
@@ -23,6 +23,10 @@ trait LogsActivityWithRelations
self::bootLogsActivity();
}*/
+ /**
+ * @param string $processingEvent
+ * @return array
+ */
public function attributeValuesToBeLogged(string $processingEvent): array
{
$properties = $this->attributeValuesToBeLoggedBase($processingEvent);
@@ -32,19 +36,29 @@ public function attributeValuesToBeLogged(string $processingEvent): array
return $properties;
}
+
+ /**
+ * @return mixed
+ */
public function getAllRelatedActivites()
{
$model = ActivitylogServiceProvider::getActivityModelInstance();
-
- return $model->allRelations($this)->get();
+ $subject = $this;
+ return $model->where(function ($q) use ($subject) {
+ $q->where('subject_type', '=', $subject->getMorphClass())
+ ->where('subject_id', $subject->getKey());
+ })->orWhere(function ($q) use ($subject) {
+ $q->where('causer_type', '=', $subject->getMorphClass())
+ ->where('causer_id', $subject->getKey());
+ })->orWhere('properties', 'LIKE', '%' . $subject->getTable() . '":"' . $subject->getKey() . '"%')->get();
}
/**
- * @param $properties
+ * @param array $properties
*
- * @return mixed
+ * @return array
*/
- public function setRelationsToBeLogged($properties)
+ public function setRelationsToBeLogged(array $properties): array
{
$relationships = $this->getModelRelations();
diff --git a/src/Traits/RelationshipsTrait.php b/src/Traits/RelationshipsTrait.php
index 61ecaa2..37f2a94 100644
--- a/src/Traits/RelationshipsTrait.php
+++ b/src/Traits/RelationshipsTrait.php
@@ -13,7 +13,11 @@
trait RelationshipsTrait
{
- public function getModelRelations()
+ /**
+ * @return array
+ * @throws \ReflectionException
+ */
+ public function getModelRelations(): array
{
$model = new static;
diff --git a/tests/ActivityloggerTest.php b/tests/ActivityloggerTest.php
index aeef08e..8d56344 100644
--- a/tests/ActivityloggerTest.php
+++ b/tests/ActivityloggerTest.php
@@ -3,11 +3,14 @@
namespace Padosoft\Laravel\ActivitylogExtended\Test;
use Auth;
+use Carbon\Carbon;
use Illuminate\Support\Collection;
use Padosoft\Laravel\ActivitylogExtended\Models\Activity;
use Padosoft\Laravel\ActivitylogExtended\Test\Models\User;
use Padosoft\Laravel\ActivitylogExtended\Test\Models\Article;
+use Spatie\Activitylog\Contracts\Activity as ActivityContract;
use Spatie\Activitylog\Exceptions\CouldNotLogActivity;
+use Spatie\Activitylog\Facades\CauserResolver;
class ActivityloggerTest extends TestCase
{
@@ -99,6 +102,35 @@ public function it_can_log_an_activity_with_a_causer()
$this->assertInstanceOf(User::class, $firstActivity->causer);
}
+ /** @test */
+ public function it_can_log_an_activity_with_a_causer_other_than_user_model()
+ {
+ $article = Article::first();
+ activity()
+ ->causedBy($article)
+ ->log($this->activityDescription);
+ $firstActivity = Activity::first();
+ $this->assertEquals($firstActivity->causer->id, $article->id);
+ $this->assertInstanceOf(Article::class, $firstActivity->causer);
+ }
+
+ /** @test */
+ public function it_can_log_an_activity_with_a_causer_that_has_been_set_from_other_context()
+ {
+ $causer = Article::first();
+ CauserResolver::setCauser($causer);
+
+ $article = Article::first();
+
+ activity()
+ ->log($this->activityDescription);
+
+ $firstActivity = Activity::first();
+
+ $this->assertEquals($firstActivity->causer->id, $article->id);
+ $this->assertInstanceOf(Article::class, $firstActivity->causer);
+ }
+
/** @test */
public function it_can_log_an_activity_with_a_causer_when_there_is_no_web_guard()
{
@@ -194,6 +226,29 @@ public function it_will_use_the_logged_in_user_as_the_causer_by_default()
$this->assertEquals($userId, $this->getLastActivity()->causer->id);
}
+ /** @test */
+ public function it_can_log_activity_using_an_anonymous_causer()
+ {
+ activity()
+ ->causedByAnonymous()
+ ->log('hello poetsvrouwman');
+ $this->assertNull($this->getLastActivity()->causer_id);
+ $this->assertNull($this->getLastActivity()->causer_type);
+ }
+
+ /** @test */
+ public function it_will_override_the_logged_in_user_as_the_causer_when_an_anonymous_causer_is_specified()
+ {
+ $userId = 1;
+
+ Auth::login(User::find($userId));
+ activity()
+ ->byAnonymous()
+ ->log('hello poetsvrouwman');
+ $this->assertNull($this->getLastActivity()->causer_id);
+ $this->assertNull($this->getLastActivity()->causer_type);
+ }
+
/** @test */
public function it_can_replace_the_placeholders()
{
@@ -212,6 +267,17 @@ public function it_can_replace_the_placeholders()
$this->assertEquals($expectedDescription, $this->getLastActivity()->description);
}
+ /** @test */
+ public function it_can_log_an_activity_with_event()
+ {
+ $article = Article::create(['name' => 'article name']);
+ activity()
+ ->performedOn($article)
+ ->event('create')
+ ->log('test event');
+ $this->assertEquals('create', $this->getLastActivity()->event);
+ }
+
/** @test */
public function it_will_not_replace_non_placeholders()
{
@@ -243,4 +309,138 @@ public function it_returns_an_instance_of_the_activity_log_after_logging_when_us
$this->assertInstanceOf($activityClassName, $activityModel);
}
+
+ /** @test */
+ public function it_will_not_log_an_activity_when_the_log_is_manually_disabled()
+ {
+ activity()->disableLogging();
+
+ activity()->log($this->activityDescription);
+
+ $this->assertNull($this->getLastActivity());
+ }
+
+ /** @test */
+ public function it_will_log_an_activity_when_the_log_is_manually_enabled()
+ {
+ config(['activitylog.enabled' => false]);
+
+ activity()->enableLogging();
+
+ activity()->log($this->activityDescription);
+
+ $this->assertEquals($this->getLastActivity()->description, $this->activityDescription);
+ }
+
+ /** @test */
+ public function it_accepts_null_parameter_for_caused_by()
+ {
+ activity()->causedBy(null)->log('nothing');
+
+ $this->assertTrue(true);
+ }
+
+ /** @test */
+ public function it_can_log_activity_when_attributes_are_changed_with_tap()
+ {
+ $properties = [
+ 'property' => [
+ 'subProperty' => 'value',
+ ],
+ ];
+
+ activity()
+ ->tap(function (ActivityContract $activity) use ($properties) {
+ $activity->properties = collect($properties);
+ $activity->created_at = Carbon::yesterday()->startOfDay();
+ })
+ ->log($this->activityDescription);
+
+ $firstActivity = Activity::first();
+
+
+ $this->assertInstanceOf(Collection::class, $firstActivity->properties);
+
+ $this->assertEquals($firstActivity->getExtraProperty('property.subProperty'), 'value');
+ $this->assertEquals($firstActivity->created_at->format('Y-m-d H:i:s'), Carbon::yesterday()->startOfDay()->format('Y-m-d H:i:s'));
+ }
+
+ /** @test */
+ public function it_will_log_a_custom_created_at_date_time()
+ {
+ $activityDateTime = now()->subDays(10);
+
+ activity()
+ ->createdAt($activityDateTime)
+ ->log('created');
+
+ $firstActivity = Activity::first();
+
+ $this->assertEquals($firstActivity->created_at->toAtomString(), $activityDateTime->toAtomString());
+ }
+
+ /** @test */
+ public function it_will_disable_logs_for_a_callback()
+ {
+ $result = activity()->withoutLogs(function () {
+ activity()->log('created');
+
+ return 'hello';
+ });
+
+ $this->assertNull($this->getLastActivity());
+ $this->assertEquals('hello', $result);
+ }
+
+ /** @test */
+ public function it_will_disable_logs_for_a_callback_without_affecting_previous_state()
+ {
+ activity()->withoutLogs(function () {
+ activity()->log('created');
+ });
+
+ $this->assertNull($this->getLastActivity());
+
+ activity()->log('outer');
+
+ $this->assertEquals('outer', $this->getLastActivity()->description);
+ }
+
+ /** @test */
+ public function it_will_disable_logs_for_a_callback_without_affecting_previous_state_even_when_already_disabled()
+ {
+ activity()->disableLogging();
+
+ activity()->withoutLogs(function () {
+ activity()->log('created');
+ });
+
+ $this->assertNull($this->getLastActivity());
+
+ activity()->log('outer');
+
+ $this->assertNull($this->getLastActivity());
+ }
+
+ /** @test */
+ public function it_will_disable_logs_for_a_callback_without_affecting_previous_state_even_with_exception()
+ {
+ activity()->disableLogging();
+
+ try {
+ activity()->withoutLogs(function () {
+ activity()->log('created');
+
+ throw new \Exception('OH NO');
+ });
+ } catch (\Exception $ex) {
+ //
+ }
+
+ $this->assertNull($this->getLastActivity());
+
+ activity()->log('outer');
+
+ $this->assertNull($this->getLastActivity());
+ }
}
diff --git a/tests/Casts/IntervalCasts.php b/tests/Casts/IntervalCasts.php
new file mode 100644
index 0000000..ac1c501
--- /dev/null
+++ b/tests/Casts/IntervalCasts.php
@@ -0,0 +1,29 @@
+assertInstanceOf(User::class, $causer);
+ $this->assertEquals($causer->id, $user->id);
+ }
+
+ /** @test */
+ public function it_will_throw_an_exception_if_it_cannot_resolve_user_by_id()
+ {
+ $this->expectException(CouldNotLogActivity::class);
+
+ CauserResolver::resolve(9999);
+ }
+
+ /** @test */
+ public function it_can_resloved_user_from_passed_id()
+ {
+ $causer = CauserResolver::resolve(1);
+
+ $this->assertInstanceOf(User::class, $causer);
+ $this->assertEquals(1, $causer->id);
+ }
+
+ /** @test */
+ public function it_will_resolve_the_provided_override_callback()
+ {
+ CauserResolver::resolveUsing(fn() => Article::first());
+
+ $causer = CauserResolver::resolve();
+
+ $this->assertInstanceOf(Article::class, $causer);
+ $this->assertEquals(1, $causer->id);
+ }
+
+ /** @test */
+ public function it_will_resolve_any_model()
+ {
+ $causer = CauserResolver::resolve($article = Article::first());
+
+ $this->assertInstanceOf(Article::class, $causer);
+ $this->assertEquals($article->id, $causer->id);
+ }
+}
diff --git a/tests/CleanActivitylogCommandTest.php b/tests/CleanActivitylogCommandTest.php
index 46e23f8..aa5bfff 100644
--- a/tests/CleanActivitylogCommandTest.php
+++ b/tests/CleanActivitylogCommandTest.php
@@ -37,4 +37,25 @@ public function it_can_clean_the_activity_log()
$this->assertCount(0, Activity::where('created_at', '<', $cutOffDate)->get());
}
+
+ /** @test */
+ public function it_can_accept_days_as_option_to_override_config_setting()
+ {
+ collect(range(1, 60))->each(function (int $index) {
+ Activity::create([
+ 'description' => "item {$index}",
+ 'created_at' => Carbon::now()->subDays($index)->startOfDay(),
+ ]);
+ });
+
+ $this->assertCount(60, Activity::all());
+
+ Artisan::call('activitylog:clean', ['--days' => 7]);
+
+ $this->assertCount(7, Activity::all());
+
+ $cutOffDate = Carbon::now()->subDays(7)->format('Y-m-d H:i:s');
+
+ $this->assertCount(0, Activity::where('created_at', '<', $cutOffDate)->get());
+ }
}
diff --git a/tests/CustomDatabaseConnectionActivityModelTest.php b/tests/CustomDatabaseConnectionActivityModelTest.php
new file mode 100644
index 0000000..684bccb
--- /dev/null
+++ b/tests/CustomDatabaseConnectionActivityModelTest.php
@@ -0,0 +1,58 @@
+activityDescription = 'My activity';
+ parent::setUp();
+
+ collect(range(1, 5))->each(function (int $index) {
+ $logName = "log{$index}";
+ activity($logName)->log('hello everybody');
+ });
+ }
+
+ /** @test */
+ public function it_uses_the_database_connection_from_the_configuration()
+ {
+ $model = new Activity();
+
+ $this->assertEquals(config('activitylog.database_connection'), $model->getConnectionName());
+ }
+
+ /** @test */
+ public function it_uses_a_custom_database_connection()
+ {
+ $model = new Activity();
+
+ $model->setConnection('custom_sqlite');
+
+ $this->assertNotEquals($model->getConnectionName(), config('activitylog.database_connection'));
+ $this->assertEquals('custom_sqlite', $model->getConnectionName());
+ }
+
+ /** @test */
+ public function it_uses_the_default_database_connection_when_the_one_from_configuration_is_null()
+ {
+ app()['config']->set('activitylog.database_connection', null);
+
+ $model = new Activity();
+
+ $this->assertInstanceOf('Illuminate\Database\SQLiteConnection', $model->getConnection());
+ }
+
+ /** @test */
+ public function it_uses_the_database_connection_from_model()
+ {
+ $model = new CustomDatabaseConnectionOnActivityModel();
+
+ $this->assertNotEquals($model->getConnectionName(), config('activitylog.database_connection'));
+ $this->assertEquals('custom_connection_name', $model->getConnectionName());
+ }
+}
diff --git a/tests/CustomTableNameModelTest.php b/tests/CustomTableNameModelTest.php
new file mode 100644
index 0000000..3effa34
--- /dev/null
+++ b/tests/CustomTableNameModelTest.php
@@ -0,0 +1,49 @@
+activityDescription = 'My activity';
+ parent::setUp();
+
+ collect(range(1, 5))->each(function (int $index) {
+ $logName = "log{$index}";
+ activity($logName)->log('hello everybody');
+ });
+ }
+
+ /** @test */
+ public function uses_the_table_name_from_the_configuration()
+ {
+ $model = new Activity();
+
+ $this->assertEquals(config('activitylog.table_name'), $model->getTable());
+ }
+
+ /** @test */
+ public function uses_a_custom_table_name()
+ {
+ $model = new Activity();
+ $newTableName = 'my_personal_activities';
+
+ $model->setTable($newTableName);
+
+ $this->assertNotEquals($model->getTable(), config('activitylog.table_name'));
+ $this->assertEquals($newTableName, $model->getTable());
+ }
+
+ /** @test */
+ public function uses_the_table_name_from_the_model()
+ {
+ $model = new CustomTableNameOnActivityModel();
+
+ $this->assertNotEquals($model->getTable(), config('activitylog.table_name'));
+ $this->assertEquals('custom_table_name', $model->getTable());
+ }
+}
diff --git a/tests/DetectsChangesTest.php b/tests/DetectsChangesTest.php
index 464b4ea..9e6f05d 100644
--- a/tests/DetectsChangesTest.php
+++ b/tests/DetectsChangesTest.php
@@ -3,9 +3,16 @@
namespace Padosoft\Laravel\ActivitylogExtended\Test;
use Carbon\Carbon;
+use Carbon\CarbonInterval;
+use Illuminate\Support\Arr;
use Padosoft\Laravel\ActivitylogExtended\Models\Activity;
+use Padosoft\Laravel\ActivitylogExtended\Test\Casts\IntervalCasts;
use Padosoft\Laravel\ActivitylogExtended\Test\Models\User;
use Padosoft\Laravel\ActivitylogExtended\Test\Models\Article;
+use Spatie\Activitylog\Contracts\LoggablePipe;
+use Spatie\Activitylog\EventLogBag;
+use Spatie\Activitylog\LogBatch;
+use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\LogsActivity;
use Illuminate\Database\Eloquent\SoftDeletes;
@@ -19,9 +26,13 @@ public function setUp(): void
parent::setUp();
$this->article = new class() extends Article {
- public static $logAttributes = ['name', 'text'];
use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()->logOnly(['name', 'text']);
+ }
};
$this->assertCount(0, Activity::all());
@@ -42,13 +53,124 @@ public function it_can_store_the_values_when_creating_a_model()
$this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
}
+ /** @test */
+ public function it_deep_diff_check_json_field()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ protected $casts = [
+ 'json' => 'collection',
+ ];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->dontSubmitEmptyLogs()
+ ->logOnlyDirty()
+ ->logOnly(['json->phone', 'json->details', 'json->address']);
+ }
+ };
+
+ $articleClass::addLogChange(new class() implements LoggablePipe {
+ public function handle(EventLogBag $event, \Closure $next): EventLogBag
+ {
+ if ($event->event === 'updated') {
+ $event->changes['attributes']['json'] = array_udiff_assoc(
+ $event->changes['attributes']['json'],
+ $event->changes['old']['json'],
+ function ($new, $old) {
+ if ($old === null || $new === null) {
+ return 0;
+ }
+
+ return $new <=> $old;
+ }
+ );
+
+ $event->changes['old']['json'] = collect($event->changes['old']['json'])
+ ->only(array_keys($event->changes['attributes']['json']))
+ ->all();
+ }
+
+ return $next($event);
+ }
+ });
+
+ $article = $articleClass::create([
+ 'name' => 'Hamburg',
+ 'json' => ['details' => '', 'phone' => '1231231234', 'address' => 'new address'],
+ ]);
+
+ $article->update(['json' => ['details' => 'new details']]);
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'json' => [
+ 'details' => 'new details',
+ ],
+ ],
+ 'old' => [
+ 'json' => [
+ 'details' => '',
+ ],
+ ],
+ ];
+
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+ }
+
+ /** @test */
+ public function it_detect_changes_for_date_inteval_attributes()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ protected $casts = [
+ 'interval' => IntervalCasts::class,
+ ];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['name', 'interval'])
+ ->logOnlyDirty();
+ }
+ };
+
+ $article = $articleClass::create([
+ 'name' => 'Hamburg',
+ 'interval' => CarbonInterval::minute(),
+ ]);
+
+ $article->update(['name' => 'New name', 'interval' => CarbonInterval::month()]);
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'name' => 'New name',
+ 'interval' => '1 month',
+ ],
+ 'old' => [
+ 'name' => 'Hamburg',
+ 'interval' => '1 minute',
+ ],
+ ];
+
+ // test case when intervals changing from interval to another
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+ }
+
/** @test */
public function it_can_store_the_relation_values_when_creating_a_model()
{
$articleClass = new class() extends Article {
- public static $logAttributes = ['name', 'text', 'user.name'];
use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()->logOnly(['name', 'text', 'user.name']);
+ }
};
$user = User::create([
@@ -85,9 +207,13 @@ public function it_can_store_the_relation_values_when_creating_a_model()
public function it_can_store_empty_relation_when_creating_a_model()
{
$articleClass = new class() extends Article {
- public static $logAttributes = ['name', 'text', 'user.name'];
use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()->logOnly(['name', 'text', 'user.name']);
+ }
};
$user = User::create([
@@ -195,9 +321,13 @@ public function it_can_store_dirty_changes_for_swapping_values()
public function it_can_store_the_changes_when_updating_a_related_model()
{
$articleClass = new class() extends Article {
- public static $logAttributes = ['name', 'text', 'user.name'];
use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()->logOnly(['name', 'text', 'user.name']);
+ }
};
$user = User::create([
@@ -236,11 +366,13 @@ public function it_can_store_the_changes_when_updating_a_related_model()
public function it_can_store_the_dirty_changes_when_updating_a_related_model()
{
$articleClass = new class() extends Article {
- public static $logAttributes = ['name', 'text', 'user.name'];
-
- public static $logOnlyDirty = true;
use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()->logOnly(['name', 'text', 'user.name'])->logOnlyDirty();
+ }
};
$user = User::create([
@@ -275,9 +407,13 @@ public function it_can_store_the_dirty_changes_when_updating_a_related_model()
public function it_will_store_no_changes_when_not_logging_attributes()
{
$articleClass = new class() extends Article {
- public static $logAttributes = [];
use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()->logOnly([]);
+ }
};
$article = new $articleClass();
@@ -297,7 +433,7 @@ public function it_will_store_the_values_when_deleting_the_model()
$article->delete();
$expectedChanges = collect([
- 'attributes' => [
+ 'old' => [
'name' => 'my name',
'text' => null,
],
@@ -311,9 +447,13 @@ public function it_will_store_the_values_when_deleting_the_model()
public function it_will_store_the_values_when_deleting_the_model_with_softdeletes()
{
$articleClass = new class() extends Article {
- public static $logAttributes = ['name', 'text'];
use LogsActivity, SoftDeletes;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()->logOnly(['name', 'text']);
+ }
};
$article = new $articleClass();
@@ -323,7 +463,7 @@ public function it_will_store_the_values_when_deleting_the_model_with_softdelete
$article->delete();
$expectedChanges = collect([
- 'attributes' => [
+ 'old' => [
'name' => 'my name',
'text' => null,
],
@@ -335,7 +475,7 @@ public function it_will_store_the_values_when_deleting_the_model_with_softdelete
$article->forceDelete();
$expectedChanges = collect([
- 'attributes' => [
+ 'old' => [
'name' => 'my name',
'text' => null
],
@@ -352,11 +492,15 @@ public function it_will_store_the_values_when_deleting_the_model_with_softdelete
public function it_can_store_the_changes_of_array_casted_properties()
{
$articleClass = new class() extends Article {
- public static $logAttributes = ['json'];
- public static $logOnlyDirty = true;
+
protected $casts = ['json' => 'collection'];
use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()->logOnly(['json'])->logOnlyDirty();
+ }
};
$article = $articleClass::create([
@@ -386,9 +530,14 @@ public function it_can_use_nothing_as_loggable_attributes()
{
$articleClass = new class() extends Article {
protected $fillable = ['name', 'text'];
- protected static $logFillable = false;
+
use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()->dontLogFillable();
+ }
};
$article = new $articleClass();
@@ -406,10 +555,13 @@ public function it_can_use_text_as_loggable_attributes()
{
$articleClass = new class() extends Article {
protected $fillable = ['name', 'text'];
- protected static $logAttributes = ['text'];
- protected static $logFillable = false;
use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()->logOnly(['text'])->dontLogFillable();
+ }
};
$article = new $articleClass();
@@ -431,9 +583,13 @@ public function it_can_use_fillable_as_loggable_attributes()
{
$articleClass = new class() extends Article {
protected $fillable = ['name', 'text'];
- protected static $logFillable = true;
use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()->logFillable();
+ }
};
$article = new $articleClass();
@@ -455,10 +611,13 @@ public function it_can_use_both_fillable_and_log_attributes()
{
$articleClass = new class() extends Article {
protected $fillable = ['name'];
- protected static $logAttributes = ['text'];
- protected static $logFillable = true;
use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()->logOnly(['text'])->logFillable();
+ }
};
$article = new $articleClass();
@@ -480,9 +639,13 @@ public function it_can_use_both_fillable_and_log_attributes()
public function it_can_use_wildcard_for_loggable_attributes()
{
$articleClass = new class() extends Article {
- public static $logAttributes = ['*'];
use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()->logOnly(['*']);
+ }
};
$article = new $articleClass();
@@ -499,6 +662,8 @@ public function it_can_use_wildcard_for_loggable_attributes()
'id' => $article->id,
'user_id' => null,
'json' => null,
+ 'price' => null,
+ 'interval' => null,
'created_at' => $this->isLaravel6OrLower() ? '2017-01-01 12:00:00' : '2017-01-01T12:00:00.000000Z',
'updated_at' => $this->isLaravel6OrLower() ? '2017-01-01 12:00:00' : '2017-01-01T12:00:00.000000Z',
],
@@ -511,9 +676,13 @@ public function it_can_use_wildcard_for_loggable_attributes()
public function it_can_use_wildcard_with_relation()
{
$articleClass = new class() extends Article {
- public static $logAttributes = ['*', 'user.name'];
use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()->logOnly(['*', 'user.name']);
+ }
};
$user = User::create([
@@ -536,6 +705,8 @@ public function it_can_use_wildcard_with_relation()
'deleted_at' => null,
'user_id' => $user->id,
'json' => null,
+ 'price' => null,
+ 'interval' => null,
'created_at' => $this->isLaravel6OrLower() ? '2017-01-01 12:00:00' : '2017-01-01T12:00:00.000000Z',
'updated_at' => $this->isLaravel6OrLower() ? '2017-01-01 12:00:00' : '2017-01-01T12:00:00.000000Z',
'user.name' => 'user name',
@@ -549,10 +720,13 @@ public function it_can_use_wildcard_with_relation()
public function it_can_use_wildcard_when_updating_model()
{
$articleClass = new class() extends Article {
- public static $logAttributes = ['*'];
- public static $logOnlyDirty = true;
use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()->logOnly(['*'])->logOnlyDirty();
+ }
};
$user = User::create([
@@ -573,11 +747,11 @@ public function it_can_use_wildcard_when_updating_model()
$expectedChanges = [
'attributes' => [
'name' => 'changed name',
- 'updated_at' => $this->isLaravel6OrLower() ? '2018-01-01 12:00:00':'2018-01-01T12:00:00.000000Z',
+ 'updated_at' => $this->isLaravel6OrLower() ? '2018-01-01 12:00:00' : '2018-01-01T12:00:00.000000Z',
],
'old' => [
'name' => 'article name',
- 'updated_at' => $this->isLaravel6OrLower() ? '2017-01-01 12:00:00':'2017-01-01T12:00:00.000000Z',
+ 'updated_at' => $this->isLaravel6OrLower() ? '2017-01-01 12:00:00' : '2017-01-01T12:00:00.000000Z',
],
];
@@ -596,11 +770,15 @@ protected function createArticle(): Article
protected function createDirtyArticle(): Article
{
$articleClass = new class() extends Article {
- public static $logAttributes = ['name', 'text'];
public static $logOnlyDirty = true;
use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()->logOnly(['name', 'text'])->logOnlyDirty();
+ }
};
$article = new $articleClass();
@@ -609,4 +787,1344 @@ protected function createDirtyArticle(): Article
return $article;
}
+
+ /** @test */
+ public function it_detect_changes_for_null_date_inteval_attributes()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ protected $casts = [
+ 'interval' => IntervalCasts::class,
+ ];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->dontLogIfAttributesChangedOnly(['created_at', 'updated_at', 'deleted_at'])
+ ->logOnly(['name', 'interval']);
+ }
+ };
+
+ $nullIntevalArticle = $articleClass::create([
+ 'name' => 'Hamburg',
+ ]);
+
+ $nullIntevalArticle->update(['name' => 'New name', 'interval' => CarbonInterval::month()]);
+
+ $expectedChangesForNullInterval = [
+ 'attributes' => [
+ 'name' => 'New name',
+ 'interval' => '1 month',
+ ],
+ 'old' => [
+ 'name' => 'Hamburg',
+ 'interval' => null,
+ ],
+ ];
+ $this->assertEquals($expectedChangesForNullInterval, $this->getLastActivity()->changes()->toArray());
+
+ $intervalArticle = $articleClass::create([
+ 'name' => 'Hamburg',
+ 'interval' => CarbonInterval::month(),
+ ]);
+
+ $intervalArticle->update(['name' => 'New name', 'interval' => null]);
+
+ $expectedChangesForInterval = [
+ 'attributes' => [
+ 'name' => 'New name',
+ 'interval' => null,
+ ],
+ 'old' => [
+ 'name' => 'Hamburg',
+ 'interval' => '1 month',
+ ],
+ ];
+
+ $this->assertEquals($expectedChangesForInterval, $this->getLastActivity()->changes()->toArray());
+ }
+
+
+ /** @test */
+ public function it_retruns_same_uuid_for_all_log_changes_under_one_batch()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+ use SoftDeletes;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['name', 'text']);
+ }
+ };
+
+ app(LogBatch::class)->startBatch();
+
+ $user = User::create([
+ 'name' => 'user name',
+ ]);
+
+ $article = $articleClass::create([
+ 'name' => 'original name',
+ 'text' => 'original text',
+ 'user_id' => $user->id,
+ ]);
+
+ $article->name = 'updated name';
+ $article->text = 'updated text';
+ $article->save();
+
+ $article->delete();
+ $article->forceDelete();
+
+ $batchUuid = app(LogBatch::class)->getUuid();
+
+ app(LogBatch::class)->endBatch();
+
+ $this->assertTrue(Activity::pluck('batch_uuid')->every(fn($uuid) => $uuid === $batchUuid));
+ }
+
+ /** @test */
+ public function it_assigns_new_uuid_for_multiple_change_logs_in_different_batches()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+ use SoftDeletes;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['name', 'text']);
+ }
+ };
+
+ app(LogBatch::class)->startBatch();
+
+ $uuidForCreatedEvent = app(LogBatch::class)->getUuid();
+ $user = User::create([
+ 'name' => 'user name',
+ ]);
+
+ $article = $articleClass::create([
+ 'name' => 'original name',
+ 'text' => 'original text',
+ 'user_id' => $user->id,
+ ]);
+
+ app(LogBatch::class)->endBatch();
+
+ $this->assertTrue(Activity::pluck('batch_uuid')->every(fn($uuid) => $uuid === $uuidForCreatedEvent));
+
+ app(LogBatch::class)->startBatch();
+
+ $article->name = 'updated name';
+ $article->text = 'updated text';
+ $article->save();
+ $uuidForUpdatedEvents = app(LogBatch::class)->getUuid();
+
+ app(LogBatch::class)->endBatch();
+
+ $this->assertCount(1, Activity::where('description', 'updated')->get());
+
+ $this->assertEquals($uuidForUpdatedEvents, Activity::where('description', 'updated')->first()->batch_uuid);
+
+ app(LogBatch::class)->startBatch();
+ $article->delete();
+ $article->forceDelete();
+
+ $uuidForDeletedEvents = app(LogBatch::class)->getUuid();
+
+ app(LogBatch::class)->endBatch();
+
+ $this->assertCount(2, Activity::where('batch_uuid', $uuidForDeletedEvents)->get());
+
+ $this->assertNotSame($uuidForCreatedEvent, $uuidForDeletedEvents);
+ }
+
+ /** @test */
+ public function it_can_removes_key_event_if_it_was_loggable()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['name', 'text', 'user.name']);
+ }
+ };
+
+ $user = User::create([
+ 'name' => 'user name',
+ ]);
+
+ $articleClass::addLogChange(new class() implements LoggablePipe {
+ public function handle(EventLogBag $event, \Closure $next): EventLogBag
+ {
+ Arr::forget($event->changes, ['attributes.name', 'old.name']);
+
+ return $next($event);
+ }
+ });
+
+ $article = $articleClass::create([
+ 'name' => 'original name',
+ 'text' => 'original text',
+ 'user_id' => $user->id,
+ ]);
+
+ $article->name = 'updated name';
+ $article->text = 'updated text';
+ $article->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'text' => 'updated text',
+ 'user.name' => 'user name',
+ ],
+ 'old' => [
+ 'text' => 'original text',
+ 'user.name' => 'user name',
+ ],
+ ];
+
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+ }
+
+
+ /** @test */
+ public function it_can_store_the_changes_when_updating_a_snake_case_related_model()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['name', 'text', 'snakeUser.name']);
+ }
+
+ public function snake_user()
+ {
+ return $this->belongsTo(User::class, 'user_id');
+ }
+ };
+
+ $user = User::create([
+ 'name' => 'a name',
+ ]);
+
+ $anotherUser = User::create([
+ 'name' => 'another name',
+ ]);
+
+ $article = $articleClass::create([
+ 'name' => 'name',
+ 'text' => 'text',
+ 'user_id' => $user->id,
+ ]);
+
+ $article->user()->associate($anotherUser)->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'name' => 'name',
+ 'text' => 'text',
+ 'snake_user.name' => 'another name',
+ ],
+ 'old' => [
+ 'name' => 'name',
+ 'text' => 'text',
+ 'snake_user.name' => 'a name',
+ ],
+ ];
+
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+ }
+
+
+ /** @test */
+ public function it_can_store_the_changes_when_updating_a_camel_case_related_model()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['name', 'text', 'camel_user.name']);
+ }
+
+ public function camelUser()
+ {
+ return $this->belongsTo(User::class, 'user_id');
+ }
+ };
+
+ $user = User::create([
+ 'name' => 'a name',
+ ]);
+
+ $anotherUser = User::create([
+ 'name' => 'another name',
+ ]);
+
+ $article = $articleClass::create([
+ 'name' => 'name',
+ 'text' => 'text',
+ 'user_id' => $user->id,
+ ]);
+
+ $article->user()->associate($anotherUser)->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'name' => 'name',
+ 'text' => 'text',
+ 'camelUser.name' => 'another name',
+ ],
+ 'old' => [
+ 'name' => 'name',
+ 'text' => 'text',
+ 'camelUser.name' => 'a name',
+ ],
+ ];
+
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+ }
+
+
+ /** @test */
+ public function it_can_store_the_changes_when_updating_a_custom_case_related_model()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['name', 'text', 'Custom_Case_User.name']);
+ }
+
+ public function Custom_Case_User()
+ {
+ return $this->belongsTo(User::class, 'user_id');
+ }
+ };
+
+ $user = User::create([
+ 'name' => 'a name',
+ ]);
+
+ $anotherUser = User::create([
+ 'name' => 'another name',
+ ]);
+
+ $article = $articleClass::create([
+ 'name' => 'name',
+ 'text' => 'text',
+ 'user_id' => $user->id,
+ ]);
+
+ $article->user()->associate($anotherUser)->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'name' => 'name',
+ 'text' => 'text',
+ 'Custom_Case_User.name' => 'another name',
+ ],
+ 'old' => [
+ 'name' => 'name',
+ 'text' => 'text',
+ 'Custom_Case_User.name' => 'a name',
+ ],
+ ];
+
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+ }
+
+
+ /** @test */
+ public function it_can_store_the_changes_when_saving_including_multi_level_related_model()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['name', 'text', 'user.latest_article.name'])
+ ->logOnlyDirty();
+ }
+ };
+
+ $user = User::create([
+ 'name' => 'a name',
+ ]);
+
+ $articleClass::create([
+ 'name' => 'name #1',
+ 'text' => 'text #1',
+ 'user_id' => $user->id,
+ ]);
+
+ $articleClass::create([
+ 'name' => 'name #2',
+ 'text' => 'text #2',
+ 'user_id' => $user->id,
+ ]);
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'name' => 'name #2',
+ 'text' => 'text #2',
+ 'user.latestArticle.name' => 'name #1',
+ ],
+ ];
+
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+ }
+
+
+ /** @test */
+ public function it_can_store_the_changes_of_collection_casted_properties()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ protected $casts = ['json' => 'collection'];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['json'])
+ ->logOnlyDirty();
+ }
+ };
+
+ $article = $articleClass::create([
+ 'json' => ['value' => 'original'],
+ ]);
+
+ $article->json = collect(['value' => 'updated']);
+ $article->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'json' => [
+ 'value' => 'updated',
+ ],
+ ],
+ 'old' => [
+ 'json' => [
+ 'value' => 'original',
+ ],
+ ],
+ ];
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+ }
+
+
+ /** @test */
+ public function it_can_store_the_changes_of_json_casted_properties()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ protected $casts = ['json' => 'json'];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['json'])
+ ->logOnlyDirty();
+ }
+ };
+
+ $article = $articleClass::create([
+ 'json' => ['value' => 'original'],
+ ]);
+
+ $article->json = collect(['value' => 'updated']);
+ $article->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'json' => [
+ 'value' => 'updated',
+ ],
+ ],
+ 'old' => [
+ 'json' => [
+ 'value' => 'original',
+ ],
+ ],
+ ];
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+ }
+
+
+ /** @test */
+ public function it_can_store_the_changes_when_a_boolean_field_is_changed_from_false_to_null()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ protected $casts = [
+ 'text' => 'boolean',
+ ];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logAll()
+ ->logOnlyDirty();
+ }
+ };
+
+ $user = User::create([
+ 'name' => 'user name',
+ ]);
+
+ Carbon::setTestNow(Carbon::create(2017, 1, 1, 12, 0, 0));
+ $article = $articleClass::create([
+ 'name' => 'article name',
+ 'text' => false,
+ 'user_id' => $user->id,
+ ]);
+
+ $article->text = null;
+ Carbon::setTestNow(Carbon::create(2018, 1, 1, 12, 0, 0));
+ $article->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'text' => null,
+ 'updated_at' => '2018-01-01T12:00:00.000000Z',
+
+ ],
+ 'old' => [
+ 'text' => false,
+ 'updated_at' => '2017-01-01T12:00:00.000000Z',
+ ],
+ ];
+
+ $this->assertSame($expectedChanges, $this->getLastActivity()->changes()->toArray());
+ }
+
+
+ /** @test */
+ public function it_can_use_ignored_attributes_while_updating()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logAll()
+ ->logExcept(['name', 'updated_at']);
+ }
+ };
+
+ $article = new $articleClass();
+ $article->name = 'my name';
+
+ Carbon::setTestNow(Carbon::create(2017, 1, 1, 12, 0, 0));
+ $article->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'text' => null,
+ 'deleted_at' => null,
+ 'id' => $article->id,
+ 'user_id' => null,
+ 'json' => null,
+ 'price' => null,
+ 'interval' => null,
+ 'created_at' => '2017-01-01T12:00:00.000000Z',
+ ],
+ ];
+
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+ }
+
+
+ /** @test */
+ public function it_can_use_unguarded_as_loggable_attributes()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ protected $guarded = ['text', 'json'];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logUnguarded()
+ ->logExcept(['id', 'created_at', 'updated_at', 'deleted_at']);
+ }
+ };
+
+ $article = new $articleClass();
+ $article->name = 'my name';
+ $article->text = 'my new text';
+ $article->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'name' => 'my name',
+ 'user_id' => null,
+ 'price' => null,
+ 'interval' => null,
+ ],
+ ];
+
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+ }
+
+
+ /** @test */
+ public
+ function it_will_store_no_changes_when_wildcard_guard_and_log_unguarded_attributes()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ protected $guarded = ['*'];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logUnguarded();
+ }
+ };
+
+ $article = new $articleClass();
+ $article->name = 'my name';
+ $article->text = 'my new text';
+ $article->save();
+
+ $this->assertEquals([], $this->getLastActivity()->changes()->toArray());
+ }
+
+ /** @test */
+ public
+ function it_can_use_hidden_as_loggable_attributes()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ protected $hidden = ['text'];
+ protected $fillable = ['name', 'text'];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['name', 'text']);
+ }
+ };
+
+ $article = new $articleClass();
+ $article->name = 'my name';
+ $article->text = 'my text';
+ $article->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'name' => 'my name',
+ 'text' => 'my text',
+ ],
+ ];
+
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+ }
+
+ /** @test */
+ public
+ function it_can_use_overloaded_as_loggable_attributes()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ protected $fillable = ['name', 'text'];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['name', 'text', 'description']);
+ }
+
+ public function setDescriptionAttribute($value)
+ {
+ $this->attributes['json'] = json_encode(['description' => $value]);
+ }
+
+ public function getDescriptionAttribute()
+ {
+ return Arr::get(json_decode($this->attributes['json'], true), 'description');
+ }
+ };
+
+ $article = new $articleClass();
+ $article->name = 'my name';
+ $article->text = 'my text';
+ $article->description = 'my description';
+ $article->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'name' => 'my name',
+ 'text' => 'my text',
+ 'description' => 'my description',
+ ],
+ ];
+
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+ }
+
+ /** @test */
+ public
+ function it_can_use_mutated_as_loggable_attributes()
+ {
+ $userClass = new class() extends User {
+ use LogsActivity;
+
+ protected $fillable = ['name', 'text'];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logAll();
+ }
+
+ public function setNameAttribute($value)
+ {
+ $this->attributes['name'] = strtoupper($value);
+ }
+ };
+
+ Carbon::setTestNow(Carbon::create(2017, 1, 1, 12, 0, 0));
+ $user = new $userClass();
+ $user->name = 'my name';
+ $user->text = 'my text';
+ $user->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'id' => $user->id,
+ 'name' => 'MY NAME',
+ 'text' => 'my text',
+ 'created_at' => '2017-01-01T12:00:00.000000Z',
+ 'updated_at' => '2017-01-01T12:00:00.000000Z',
+ 'deleted_at' => null,
+ ],
+ ];
+
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+
+ $user->name = 'my name 2';
+ $user->save();
+
+ $expectedChanges = [
+ 'old' => [
+ 'id' => $user->id,
+ 'name' => 'MY NAME',
+ 'text' => 'my text',
+ 'created_at' => '2017-01-01T12:00:00.000000Z',
+ 'updated_at' => '2017-01-01T12:00:00.000000Z',
+ 'deleted_at' => null,
+ ],
+ 'attributes' => [
+ 'id' => $user->id,
+ 'name' => 'MY NAME 2',
+ 'text' => 'my text',
+ 'created_at' => '2017-01-01T12:00:00.000000Z',
+ 'updated_at' => '2017-01-01T12:00:00.000000Z',
+ 'deleted_at' => null,
+ ],
+ ];
+
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+ }
+
+ /** @test */
+ public
+ function it_can_use_accessor_as_loggable_attributes()
+ {
+ $userClass = new class() extends User {
+ use LogsActivity;
+
+ protected $fillable = ['name', 'text'];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logAll();
+ }
+
+ public function getNameAttribute($value)
+ {
+ return strtoupper($value);
+ }
+ };
+
+ Carbon::setTestNow(Carbon::create(2017, 1, 1, 12, 0, 0));
+ $user = new $userClass();
+ $user->name = 'my name';
+ $user->text = 'my text';
+ $user->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'id' => $user->id,
+ 'name' => 'MY NAME',
+ 'text' => 'my text',
+ 'created_at' => '2017-01-01T12:00:00.000000Z',
+ 'updated_at' => '2017-01-01T12:00:00.000000Z',
+ 'deleted_at' => null,
+ ],
+ ];
+
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+
+ $user->name = 'my name 2';
+ $user->save();
+
+ $expectedChanges = [
+ 'old' => [
+ 'id' => $user->id,
+ 'name' => 'MY NAME',
+ 'text' => 'my text',
+ 'created_at' => '2017-01-01T12:00:00.000000Z',
+ 'updated_at' => '2017-01-01T12:00:00.000000Z',
+ 'deleted_at' => null,
+ ],
+ 'attributes' => [
+ 'id' => $user->id,
+ 'name' => 'MY NAME 2',
+ 'text' => 'my text',
+ 'created_at' => '2017-01-01T12:00:00.000000Z',
+ 'updated_at' => '2017-01-01T12:00:00.000000Z',
+ 'deleted_at' => null,
+ ],
+ ];
+
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+ }
+
+ /** @test */
+ public
+ function it_can_use_encrypted_as_loggable_attributes()
+ {
+ $userClass = new class() extends User {
+ use LogsActivity;
+
+ protected $fillable = ['name', 'text'];
+ protected $encryptable = ['name', 'text'];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['name', 'text']);
+ }
+
+ public function getAttributeValue($key)
+ {
+ $value = parent::getAttributeValue($key);
+
+ if (in_array($key, $this->encryptable)) {
+ $value = decrypt($value);
+ }
+
+ return $value;
+ }
+
+ public function setAttribute($key, $value)
+ {
+ if (in_array($key, $this->encryptable)) {
+ $value = encrypt($value);
+ }
+
+ return parent::setAttribute($key, $value);
+ }
+ };
+
+ Carbon::setTestNow(Carbon::create(2017, 1, 1, 12, 0, 0));
+ $user = new $userClass();
+ $user->name = 'my name';
+ $user->text = 'my text';
+ $user->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'name' => 'my name',
+ 'text' => 'my text',
+ ],
+ ];
+
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+
+ $user->name = 'my name 2';
+ $user->save();
+
+ $expectedChanges = [
+ 'old' => [
+ 'name' => 'my name',
+ 'text' => 'my text',
+ ],
+ 'attributes' => [
+ 'name' => 'my name 2',
+ 'text' => 'my text',
+ ],
+ ];
+
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+ }
+
+ /** @test */
+ public
+ function it_can_use_casted_as_loggable_attribute()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ protected $casts = [
+ 'price' => 'float',
+ ];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['name', 'text', 'price'])
+ ->logOnlyDirty();
+ }
+ };
+
+ $article = new $articleClass();
+ $article->name = 'my name';
+ $article->text = 'my text';
+ $article->price = '9.99';
+ $article->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'name' => 'my name',
+ 'text' => 'my text',
+ 'price' => 9.99,
+ ],
+ ];
+
+ $changes = $this->getLastActivity()->changes()->toArray();
+ $this->assertSame($expectedChanges, $changes);
+ $this->assertIsFloat($changes['attributes']['price']);
+
+ $article->price = 19.99;
+ $article->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'price' => 19.99,
+ ],
+ 'old' => [
+ 'price' => 9.99,
+ ],
+ ];
+
+ $changes = $this->getLastActivity()->changes()->toArray();
+ $this->assertSame($expectedChanges, $changes);
+ $this->assertIsFloat($changes['attributes']['price']);
+ }
+
+ /** @test */
+ public
+ function it_can_use_nullable_date_as_loggable_attributes()
+ {
+ $userClass = new class() extends User {
+ use LogsActivity;
+ use SoftDeletes;
+
+ protected $fillable = ['name', 'text'];
+
+ protected $dates = [
+ 'created_at',
+ 'updated_at',
+ 'deleted_at',
+ ];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logAll();
+ }
+ };
+
+ Carbon::setTestNow(Carbon::create(2017, 1, 1, 12, 0, 0));
+ $user = new $userClass();
+ $user->name = 'my name';
+ $user->text = 'my text';
+ $user->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'id' => $user->getKey(),
+ 'name' => 'my name',
+ 'text' => 'my text',
+ 'created_at' => '2017-01-01T12:00:00.000000Z',
+ 'updated_at' => '2017-01-01T12:00:00.000000Z',
+ 'deleted_at' => null,
+ ],
+ ];
+
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+ }
+
+ /** @test */
+ public
+ function it_can_use_custom_date_cast_as_loggable_attributes()
+ {
+ $userClass = new class() extends User {
+ use LogsActivity;
+
+ protected $fillable = ['name', 'text'];
+ protected $casts = [
+ 'created_at' => 'date:d.m.Y',
+ ];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logAll();
+ }
+ };
+
+ Carbon::setTestNow(Carbon::create(2017, 1, 1, 12, 0, 0));
+ $user = new $userClass();
+ $user->name = 'my name';
+ $user->text = 'my text';
+ $user->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'id' => $user->getKey(),
+ 'name' => 'my name',
+ 'text' => 'my text',
+ 'created_at' => '01.01.2017',
+ 'updated_at' => '2017-01-01T12:00:00.000000Z',
+ 'deleted_at' => null,
+ ],
+ ];
+
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+ }
+
+ /** @test */
+ public
+ function it_can_use_custom_immutable_date_cast_as_loggable_attributes()
+ {
+ $userClass = new class() extends User {
+ use LogsActivity;
+
+ protected $fillable = ['name', 'text'];
+ protected $casts = [
+ 'created_at' => 'immutable_date:d.m.Y',
+ ];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logAll();
+ }
+ };
+
+ Carbon::setTestNow(Carbon::create(2017, 1, 1, 12, 0, 0));
+ $user = new $userClass();
+ $user->name = 'my name';
+ $user->text = 'my text';
+ $user->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'id' => $user->getKey(),
+ 'name' => 'my name',
+ 'text' => 'my text',
+ 'created_at' => '01.01.2017',
+ 'updated_at' => '2017-01-01T12:00:00.000000Z',
+ 'deleted_at' => null,
+ ],
+ ];
+
+ $this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
+ }
+
+ /** @test */
+ public
+ function it_can_store_the_changes_of_json_attributes()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ protected $casts = [
+ 'json' => 'collection',
+ ];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['name', 'json->data'])
+ ->logOnlyDirty();
+ }
+ };
+
+ $article = new $articleClass();
+ $article->json = ['data' => 'test'];
+ $article->name = 'I am JSON';
+ $article->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'name' => 'I am JSON',
+ 'json' => [
+ 'data' => 'test',
+ ],
+ ],
+ ];
+
+ $changes = $this->getLastActivity()->changes()->toArray();
+
+ $this->assertSame($expectedChanges, $changes);
+ }
+
+ /** @test */
+ public
+ function it_will_not_store_changes_to_untracked_json()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ protected $casts = [
+ 'json' => 'collection',
+ ];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['name', 'json->data'])
+ ->logOnlyDirty();
+ }
+ };
+
+ $article = new $articleClass();
+ $article->json = ['unTracked' => 'test'];
+ $article->name = 'a name';
+ $article->save();
+
+ $article->name = 'I am JSON';
+ $article->json = ['unTracked' => 'different string'];
+ $article->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'name' => 'I am JSON',
+ ],
+ 'old' => [
+ 'name' => 'a name',
+ ],
+ ];
+
+ $changes = $this->getLastActivity()->changes()->toArray();
+
+ $this->assertSame($expectedChanges, $changes);
+ }
+
+ /** @test */
+ public
+ function it_will_return_null_for_missing_json_attribute()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ protected $casts = [
+ 'json' => 'collection',
+ ];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['name', 'json->data->missing'])
+ ->logOnlyDirty();
+ }
+ };
+
+ $jsonToStore = [];
+
+ $article = new $articleClass();
+ $article->json = $jsonToStore;
+ $article->name = 'I am JSON';
+ $article->save();
+
+ data_set($jsonToStore, 'data.missing', 'I wasn\'t here');
+
+ $article->json = $jsonToStore;
+ $article->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'json' => [
+ 'data' => [
+ 'missing' => 'I wasn\'t here',
+ ],
+ ],
+ ],
+ 'old' => [
+ 'json' => [
+ 'data' => [
+ 'missing' => null,
+ ],
+ ],
+ ],
+ ];
+
+ $changes = $this->getLastActivity()->changes()->toArray();
+
+ $this->assertSame($expectedChanges, $changes);
+ }
+
+ /** @test */
+ public
+ function it_will_return_an_array_for_sub_key_in_json_attribute()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ protected $casts = [
+ 'json' => 'collection',
+ ];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['name', 'json->data'])
+ ->logOnlyDirty();
+ }
+ };
+
+ $jsonToStore = [
+ 'data' => [
+ 'data_a' => 1,
+ 'data_b' => 2,
+ 'data_c' => 3,
+ 'data_d' => 4,
+ 'data_e' => 5,
+ ],
+ ];
+
+ $article = new $articleClass();
+ $article->json = $jsonToStore;
+ $article->name = 'I am JSON';
+ $article->save();
+
+ data_set($jsonToStore, 'data.data_c', 'I Got The Key');
+
+ $article->json = $jsonToStore;
+ $article->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'json' => [
+ 'data' => [
+ 'data_a' => 1,
+ 'data_b' => 2,
+ 'data_c' => 'I Got The Key',
+ 'data_d' => 4,
+ 'data_e' => 5,
+ ],
+ ],
+ ],
+ 'old' => [
+ 'json' => [
+ 'data' => [
+ 'data_a' => 1,
+ 'data_b' => 2,
+ 'data_c' => 3,
+ 'data_d' => 4,
+ 'data_e' => 5,
+ ],
+ ],
+ ],
+ ];
+
+ $changes = $this->getLastActivity()->changes()->toArray();
+
+ $this->assertSame($expectedChanges, $changes);
+ }
+
+ /** @test */
+ public
+ function it_will_access_further_than_level_one_json_attribute()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ protected $casts = [
+ 'json' => 'collection',
+ ];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['name', 'json->data->can->go->how->far'])
+ ->logOnlyDirty();
+ }
+ };
+
+ $jsonToStore = [];
+ // data_set($jsonToStore, 'data.can.go.how.far', 'Data');
+
+ $article = new $articleClass();
+ $article->json = $jsonToStore;
+ $article->name = 'I am JSON';
+ $article->save();
+
+ data_set($jsonToStore, 'data.can.go.how.far', 'This far');
+
+ $article->json = $jsonToStore;
+ $article->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'json' => [
+ 'data' => [
+ 'can' => [
+ 'go' => [
+ 'how' => [
+ 'far' => 'This far',
+ ],
+ ],
+ ],
+ ],
+ ],
+ ],
+ 'old' => [
+ 'json' => [
+ 'data' => [
+ 'can' => [
+ 'go' => [
+ 'how' => [
+ 'far' => null,
+ ],
+ ],
+ ],
+ ],
+ ],
+ ],
+ ];
+
+ $changes = $this->getLastActivity()->changes()->toArray();
+
+ $this->assertSame($expectedChanges, $changes);
+ }
}
diff --git a/tests/HasActivityTest.php b/tests/HasActivityTest.php
index 71c5fb7..2fc301e 100644
--- a/tests/HasActivityTest.php
+++ b/tests/HasActivityTest.php
@@ -6,6 +6,7 @@
use Padosoft\Laravel\ActivitylogExtended\Test\Models\User;
use Illuminate\Database\Eloquent\SoftDeletes;
use Padosoft\Laravel\ActivitylogExtended\Traits\LogsActivityWithRelations;
+use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\CausesActivity;
use Spatie\Activitylog\Traits\LogsActivity;
@@ -13,7 +14,7 @@ class HasActivityTest extends TestCase
{
protected $user;
- public function setUp():void
+ public function setUp(): void
{
parent::setUp();
@@ -21,6 +22,11 @@ public function setUp():void
use LogsActivity;
use CausesActivity;
use SoftDeletes;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults();
+ }
};
$this->assertCount(0, Activity::all());
diff --git a/tests/LogBatchTest.php b/tests/LogBatchTest.php
new file mode 100644
index 0000000..243d232
--- /dev/null
+++ b/tests/LogBatchTest.php
@@ -0,0 +1,160 @@
+activityDescription = 'My activity';
+ parent::setUp();
+
+ collect(range(1, 5))->each(function (int $index) {
+ $logName = "log{$index}";
+ activity($logName)->log('hello everybody');
+ });
+ }
+
+ /** @test */
+ public function it_generates_uuid_after_start_and_end_batch_properely()
+ {
+ LogBatch::startBatch();
+ $uuid = LogBatch::getUuid();
+ LogBatch::endBatch();
+
+ $this->assertFalse(LogBatch::isopen());
+
+ $this->assertIsString($uuid);
+ }
+
+ /** @test */
+ public function it_returns_null_uuid_after_end_batch_properely()
+ {
+ LogBatch::startBatch();
+ $uuid = LogBatch::getUuid();
+ LogBatch::endBatch();
+
+ $this->assertFalse(LogBatch::isopen());
+ $this->assertNotNull($uuid);
+ $this->assertNull(LogBatch::getUuid());
+ }
+
+ /** @test */
+ public function it_generates_a_new_uuid_after_starting_new_batch_properly()
+ {
+ LogBatch::startBatch();
+ $firstBatchUuid = LogBatch::getUuid();
+ LogBatch::endBatch();
+
+ LogBatch::startBatch();
+
+ LogBatch::startBatch();
+ $secondBatchUuid = LogBatch::getUuid();
+ LogBatch::endBatch();
+
+ $this->assertTrue(LogBatch::isopen());
+ $this->assertNotNull($firstBatchUuid);
+ $this->assertNotNull($secondBatchUuid);
+
+ $this->assertNotEquals($firstBatchUuid, $secondBatchUuid);
+ }
+
+ /** @test */
+ public function it_will_not_generate_new_uuid_if_start_already_started_batch()
+ {
+ LogBatch::startBatch();
+
+ $firstUuid = LogBatch::getUuid();
+
+ LogBatch::startBatch();
+
+ $secondUuid = LogBatch::getUuid();
+
+ LogBatch::endBatch();
+
+ $this->assertTrue(LogBatch::isopen());
+
+ $this->assertEquals($secondUuid, $firstUuid);
+ }
+
+ /** @test */
+ public function it_will_not_generate_uuid_if_end_batch_before_starting()
+ {
+ LogBatch::endBatch();
+ $uuid = LogBatch::getUuid();
+
+ LogBatch::startBatch();
+
+ $this->assertNull($uuid);
+ }
+
+ /** @test */
+ public function it_can_set_uuid_and_start_a_batch()
+ {
+ $uuid = Str::uuid();
+
+ LogBatch::setBatch($uuid);
+ $this->assertTrue(LogBatch::isOpen());
+ $this->assertEquals($uuid, LogBatch::getUuid());
+
+ LogBatch::endBatch();
+ $this->assertFalse(LogBatch::isOpen());
+ }
+
+ /** @test */
+ public function it_can_set_uuid_for_already_started_batch()
+ {
+ $uuid = Str::uuid();
+
+ LogBatch::startBatch();
+ $this->assertTrue(LogBatch::isOpen());
+ $this->assertNotEquals($uuid, LogBatch::getUuid());
+
+ LogBatch::setBatch($uuid);
+ $this->assertTrue(LogBatch::isOpen());
+ $this->assertEquals($uuid, LogBatch::getUuid());
+
+ LogBatch::endBatch();
+ $this->assertFalse(LogBatch::isOpen());
+ }
+
+ /** @test */
+ public function it_will_not_return_null_uuid_if_end_batch_that_started_twice()
+ {
+ LogBatch::startBatch();
+ $firstUuid = LogBatch::getUuid();
+
+ LogBatch::startBatch();
+
+ LogBatch::endBatch();
+
+ $notNullUuid = LogBatch::getUuid();
+
+ $this->assertNotNull($firstUuid);
+ $this->assertNotNull($notNullUuid);
+
+ $this->assertEquals($notNullUuid, $firstUuid);
+ }
+
+ /** @test */
+ public function it_will_return_null_uuid_if_end_batch_that_started_twice_properly()
+ {
+ LogBatch::startBatch();
+ $firstUuid = LogBatch::getUuid();
+
+ LogBatch::startBatch();
+
+ LogBatch::endBatch();
+ LogBatch::endBatch();
+
+ $nullUuid = LogBatch::getUuid();
+
+ $this->assertNotNull($firstUuid);
+ $this->assertNull($nullUuid);
+
+ $this->assertNotSame($firstUuid, $nullUuid);
+ }
+}
diff --git a/tests/LogsActivityTest.php b/tests/LogsActivityTest.php
index 45dd439..90219a2 100644
--- a/tests/LogsActivityTest.php
+++ b/tests/LogsActivityTest.php
@@ -2,8 +2,14 @@
namespace Padosoft\Laravel\ActivitylogExtended\Test;
+use Carbon\Carbon;
+use Illuminate\Support\Collection;
use Padosoft\Laravel\ActivitylogExtended\Models\Activity;
use Padosoft\Laravel\ActivitylogExtended\Test\Models\Article;
+use Padosoft\Laravel\ActivitylogExtended\Test\Models\Issue733;
+use Padosoft\Laravel\ActivitylogExtended\Test\Models\User;
+use Spatie\Activitylog\Contracts\Activity as ActivityContract;
+use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\LogsActivity;
use Illuminate\Database\Eloquent\SoftDeletes;
@@ -19,6 +25,21 @@ public function setUp(): void
$this->article = new class() extends Article {
use LogsActivity;
use SoftDeletes;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults();
+ }
+ };
+
+ $this->user = new class() extends User {
+ use LogsActivity;
+ use SoftDeletes;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults();
+ }
};
$this->assertCount(0, Activity::all());
@@ -96,6 +117,11 @@ public function it_will_log_the_deletion_of_a_model_without_softdeletes()
{
$articleClass = new class() extends Article {
use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults();
+ }
};
$article = new $articleClass();
@@ -159,6 +185,26 @@ public function it_can_fetch_all_activity_for_a_model()
$this->assertCount(2, $activities);
}
+ /** @test */
+ public function it_can_log_activity_to_log_named_in_the_model()
+ {
+ $articleClass = new class() extends Article {
+ use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->useLogName('custom_log');
+ }
+ };
+
+ $article = new $articleClass();
+ $article->name = 'my name';
+ $article->save();
+
+ $this->assertSame('custom_log', Activity::latest()->first()->log_name);
+ }
+
/** @test */
public function it_can_fetch_soft_deleted_models()
{
@@ -187,9 +233,9 @@ public function it_can_log_activity_to_log_returned_from_model_method_override()
$articleClass = new class() extends Article {
use LogsActivity;
- public function getLogNameToUse()
+ public function getActivitylogOptions(): LogOptions
{
- return 'custom_log';
+ return LogOptions::defaults()->useLogName('custom_log');
}
};
@@ -202,42 +248,258 @@ public function getLogNameToUse()
}
/** @test */
- public function it_can_log_activity_to_log_named_in_the_model()
+ public function it_will_not_log_an_update_of_the_model_if_only_ignored_attributes_are_changed()
{
$articleClass = new class() extends Article {
use LogsActivity;
- protected static $logName = 'custom_log';
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()->dontLogIfAttributesChangedOnly(['text']);
+ }
};
$article = new $articleClass();
$article->name = 'my name';
$article->save();
- $this->assertSame('custom_log', Activity::latest()->first()->log_name);
+ $article->text = 'ignore me';
+ $article->save();
+
+ $this->assertCount(1, Activity::all());
+
+ $this->assertInstanceOf(get_class($articleClass), $this->getLastActivity()->subject);
+ $this->assertEquals($article->id, $this->getLastActivity()->subject->id);
+ $this->assertEquals('created', $this->getLastActivity()->description);
}
/** @test */
- public function it_will_not_log_an_update_of_the_model_if_only_ignored_attributes_are_changed()
+ public function can_log_activity_on_subject_by_same_causer()
+ {
+ $user = $this->loginWithFakeUser();
+
+ $user->name = 'LogsActivity Name';
+ $user->save();
+
+ $this->assertCount(1, Activity::all());
+
+ $this->assertInstanceOf(get_class($this->user), $this->getLastActivity()->subject);
+ $this->assertEquals($user->id, $this->getLastActivity()->subject->id);
+ $this->assertEquals($user->id, $this->getLastActivity()->causer->id);
+ $this->assertCount(1, $user->activities);
+ $this->assertCount(1, $user->actions);
+ }
+
+ /** @test */
+ public function it_can_log_activity_when_attributes_are_changed_with_tap()
+ {
+ $model = new class() extends Article {
+ use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults();
+ }
+
+ protected $properties = [
+ 'property' => [
+ 'subProperty' => 'value',
+ ],
+ ];
+
+ public function tapActivity(ActivityContract $activity, string $eventName)
+ {
+ $properties = $this->properties;
+ $properties['event'] = $eventName;
+ $activity->properties = collect($properties);
+ $activity->created_at = Carbon::yesterday()->startOfDay();
+ }
+ };
+
+ $entity = new $model();
+ $entity->save();
+
+ $firstActivity = $entity->activities()->first();
+
+ $this->assertInstanceOf(Collection::class, $firstActivity->properties);
+ $this->assertEquals('value', $firstActivity->getExtraProperty('property.subProperty'));
+ $this->assertEquals('created', $firstActivity->description);
+ $this->assertEquals('created', $firstActivity->event);
+ $this->assertEquals(Carbon::yesterday()->startOfDay()->format('Y-m-d H:i:s'), $firstActivity->created_at->format('Y-m-d H:i:s'));
+ }
+
+ /** @test */
+ public function it_can_log_activity_when_description_is_changed_with_tap()
+ {
+ $model = new class() extends Article {
+ use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults();
+ }
+
+ public function tapActivity(ActivityContract $activity, string $eventName)
+ {
+ $activity->description = 'my custom description';
+ }
+ };
+
+ $entity = new $model();
+ $entity->save();
+
+ $firstActivity = $entity->activities()->first();
+
+ $this->assertEquals('my custom description', $firstActivity->description);
+ }
+
+ /** @test */
+ public function it_can_log_activity_when_event_is_changed_with_tap()
+ {
+ $model = new class() extends Article {
+ use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults();
+ }
+
+ public function tapActivity(ActivityContract $activity, string $eventName)
+ {
+ $activity->event = 'my custom event';
+ }
+ };
+
+ $entity = new $model();
+ $entity->save();
+
+ $firstActivity = $entity->activities()->first();
+
+ $this->assertEquals('my custom event', $firstActivity->event);
+ }
+
+ /** @test */
+ public function it_will_not_submit_log_when_there_is_no_changes()
+ {
+ $model = new class() extends Article {
+ use LogsActivity;
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['text'])
+ ->dontSubmitEmptyLogs()
+ ->logOnlyDirty();
+ }
+ };
+
+ $entity = new $model(['text' => 'test']);
+ $entity->save();
+
+ $this->assertCount(1, Activity::all());
+
+ $entity->name = 'my name';
+ $entity->save();
+
+ $this->assertCount(1, Activity::all());
+ }
+
+ /** @test */
+ public function it_will_submit_a_log_with_json_changes()
+ {
+ $model = new class() extends Article {
+ use LogsActivity;
+
+ protected $casts = [
+ 'json' => 'collection',
+ ];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->logOnly(['text', 'json->data'])
+ ->dontSubmitEmptyLogs()
+ ->logOnlyDirty();
+ }
+ };
+
+ $entity = new $model([
+ 'text' => 'test',
+ 'json' => [
+ 'data' => 'oldish',
+ ],
+ ]);
+
+ $entity->save();
+
+ $this->assertCount(1, Activity::all());
+
+ $entity->json = [
+ 'data' => 'chips',
+ 'irrelevant' => 'should not be',
+ ];
+
+ $entity->save();
+
+ $expectedChanges = [
+ 'attributes' => [
+ 'json' => [
+ 'data' => 'chips',
+ ],
+ ],
+ 'old' => [
+ 'json' => [
+ 'data' => 'oldish',
+ ],
+ ],
+ ];
+
+ $changes = $this->getLastActivity()->changes()->toArray();
+
+ $this->assertCount(2, Activity::all());
+ $this->assertSame($expectedChanges, $changes);
+ }
+
+ /** @test */
+ public function it_will_log_the_retrieval_of_the_model()
+ {
+ $article = Issue733::create(['name' => 'my name']);
+
+ $retrieved = Issue733::whereKey($article->getKey())->first();
+ $this->assertTrue($article->is($retrieved));
+
+ $activity = $this->getLastActivity();
+
+ $this->assertInstanceOf(get_class($article), $activity->subject);
+ $this->assertTrue($article->is($activity->subject));
+ $this->assertEquals('retrieved', $activity->description);
+ }
+
+ /** @test */
+ public function it_will_not_log_casted_attribute_of_the_model_if_attribute_raw_values_is_used()
{
$articleClass = new class() extends Article {
use LogsActivity;
- protected static $ignoreChangedAttributes = ['text'];
+ protected $casts = [
+ 'name' => 'encrypted',
+ ];
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()->logOnly(['name'])->useAttributeRawValues(['name']);
+ }
};
$article = new $articleClass();
$article->name = 'my name';
$article->save();
- $article->text = 'ignore me';
- $article->save();
-
- $this->assertCount(1, Activity::all());
-
$this->assertInstanceOf(get_class($articleClass), $this->getLastActivity()->subject);
$this->assertEquals($article->id, $this->getLastActivity()->subject->id);
+ $this->assertNotEquals($article->name, $this->getLastActivity()->properties['attributes']['name']);
$this->assertEquals('created', $this->getLastActivity()->description);
+ $this->assertEquals('created', $this->getLastActivity()->event);
}
/** @test */
@@ -247,10 +509,13 @@ public function it_will_not_fail_if_asked_to_replace_from_empty_attribute()
use LogsActivity;
use SoftDeletes;
- public function getDescriptionForEvent(string $eventName): string
+ public function getActivitylogOptions(): LogOptions
{
- return ":causer.name $eventName";
+ return LogOptions::defaults()->setDescriptionForEvent(function (string $eventName): string {
+ return ":causer.name $eventName";
+ });
}
+
};
$entity = new $model();
diff --git a/tests/Models/ArticleWithRelations.php b/tests/Models/ArticleWithRelations.php
index 5ff2c56..aa0e55e 100644
--- a/tests/Models/ArticleWithRelations.php
+++ b/tests/Models/ArticleWithRelations.php
@@ -3,15 +3,17 @@
namespace Padosoft\Laravel\ActivitylogExtended\Test\Models;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Facades\Log;
use Padosoft\Laravel\ActivitylogExtended\Traits\LogsActivityWithRelations;
+use Spatie\Activitylog\LogOptions;
class ArticleWithRelations extends Model
{
use LogsActivityWithRelations;
- protected static $logAttributes = ['*'];
+ protected static $logAttributes = ['*'];
protected static $ignoreChangedAttributes = ['updated_at'];
- protected static $logOnlyDirty = true;
+ protected static $logOnlyDirty = true;
protected $table = 'articles';
@@ -21,4 +23,9 @@ public function User()
{
return $this->belongsTo(User::class);
}
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults();
+ }
}
diff --git a/tests/Models/CustomActivityModel.php b/tests/Models/CustomActivityModel.php
index 81e2c0a..b67a57f 100644
--- a/tests/Models/CustomActivityModel.php
+++ b/tests/Models/CustomActivityModel.php
@@ -2,6 +2,7 @@
namespace Padosoft\Laravel\ActivitylogExtended\Test\Models;
+use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
@@ -46,14 +47,14 @@ public function causer(): MorphTo
*
* @return mixed
*/
- public function getExtraProperty(string $propertyName)
+ public function getExtraProperty(string $propertyName): mixed
{
- return array_get($this->properties->toArray(), $propertyName);
+ return Arr::get($this->properties->toArray(), $propertyName);
}
public function changes(): Collection
{
- if (! $this->properties instanceof Collection) {
+ if (!$this->properties instanceof Collection) {
return new Collection();
}
diff --git a/tests/Models/CustomDatabaseConnectionOnActivityModel.php b/tests/Models/CustomDatabaseConnectionOnActivityModel.php
new file mode 100644
index 0000000..c877fd8
--- /dev/null
+++ b/tests/Models/CustomDatabaseConnectionOnActivityModel.php
@@ -0,0 +1,10 @@
+properties->toArray(), $propertyName);
+ return Arr::get($this->properties->toArray(), $propertyName);
}
public function changes(): Collection
{
- if (! $this->properties instanceof Collection) {
+ if (!$this->properties instanceof Collection) {
return new Collection();
}
diff --git a/tests/Models/CustomTableNameOnActivityModel.php b/tests/Models/CustomTableNameOnActivityModel.php
new file mode 100644
index 0000000..0b40435
--- /dev/null
+++ b/tests/Models/CustomTableNameOnActivityModel.php
@@ -0,0 +1,10 @@
+dontSubmitEmptyLogs()
+ ->logOnly(['name']);
+ }
+}
diff --git a/tests/Models/User.php b/tests/Models/User.php
index ad5acd9..311ca4c 100644
--- a/tests/Models/User.php
+++ b/tests/Models/User.php
@@ -81,4 +81,9 @@ public function articles()
{
return $this->hasMany(Article::class);
}
+
+ public function latestArticle()
+ {
+ return $this->hasOne(Article::class)->latest()->limit(1);
+ }
}
diff --git a/tests/Models/UserWithRelations.php b/tests/Models/UserWithRelations.php
index cc3e404..6607500 100644
--- a/tests/Models/UserWithRelations.php
+++ b/tests/Models/UserWithRelations.php
@@ -4,6 +4,7 @@
use Illuminate\Database\Eloquent\Model;
use Padosoft\Laravel\ActivitylogExtended\Traits\LogsActivityWithRelations;
+use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\CausesActivity;
use Illuminate\Contracts\Auth\Authenticatable;
@@ -83,4 +84,9 @@ public function articles()
{
return $this->hasMany(Article::class);
}
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults();
+ }
}
diff --git a/tests/TestCase.php b/tests/TestCase.php
index 725a3ca..68e442d 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -2,6 +2,7 @@
namespace Padosoft\Laravel\ActivitylogExtended\Test;
+use Illuminate\Support\Arr;
use Padosoft\Laravel\ActivitylogExtended\Models\Activity;
use Padosoft\Laravel\ActivitylogExtended\Test\Models\User;
use Illuminate\Database\Schema\Blueprint;
@@ -21,10 +22,10 @@ public function setUp(): void
protected function checkRequirements()
{
- parent::checkRequirements();
+ //parent::checkRequirements();
collect($this->getAnnotations())->filter(function ($location) {
- return in_array('!Travis', array_get($location, 'requires', []));
+ return in_array('!Travis', Arr::get($location, 'requires', []));
})->each(function ($location) {
getenv('TRAVIS') && $this->markTestSkipped('Travis will not run this test.');
});
@@ -43,7 +44,7 @@ public function getEnvironmentSetUp($app)
$app['config']->set('database.connections.sqlite', [
'driver' => 'sqlite',
- 'database' => $this->getTempDirectory().'/database.sqlite',
+ 'database' => $this->getTempDirectory() . '/database.sqlite',
'prefix' => '',
]);
@@ -59,35 +60,37 @@ protected function setUpDatabase()
$this->createActivityLogTable();
$this->createTables('articles', 'users');
- $this->seedModels(User::class,Article::class);
+ $this->seedModels(User::class, Article::class);
}
protected function resetDatabase()
{
- file_put_contents($this->getTempDirectory().'/database.sqlite', null);
+ file_put_contents($this->getTempDirectory() . '/database.sqlite', null);
}
protected function createActivityLogTable()
{
- include_once '__DIR__'.'/../vendor/spatie/laravel-activitylog/migrations/create_activity_log_table.php.stub';
+ include_once __DIR__ . '/../vendor/spatie/laravel-activitylog/database/migrations/create_activity_log_table.php.stub';
(new \CreateActivityLogTable())->up();
- if (file_exists('__DIR__'.'/../vendor/spatie/laravel-activitylog/migrations/add_event_column_to_activity_log_table.php.stub')){
- include_once '__DIR__'.'/../vendor/spatie/laravel-activitylog/migrations/add_event_column_to_activity_log_table.php.stub';
+ if (file_exists(__DIR__ . '/../vendor/spatie/laravel-activitylog/database/migrations/add_event_column_to_activity_log_table.php.stub')) {
+ include_once __DIR__ . '/../vendor/spatie/laravel-activitylog/database/migrations/add_event_column_to_activity_log_table.php.stub';
(new \AddEventColumnToActivityLogTable())->up();
}
+ if (file_exists(__DIR__ . '/../vendor/spatie/laravel-activitylog/database/migrations/add_batch_uuid_column_to_activity_log_table.php.stub')) {
+ include_once __DIR__ . '/../vendor/spatie/laravel-activitylog/database/migrations/add_batch_uuid_column_to_activity_log_table.php.stub';
+ (new \AddBatchUuidColumnToActivityLogTable())->up();
+ }
-
-
- include_once '__DIR__'.'/../migrations/enhance_activity_log_table.php.stub';
+ include_once __DIR__ . '/../migrations/enhance_activity_log_table.php.stub';
(new \EnhanceActivityLogTable())->up();
}
public function getTempDirectory(): string
{
- return __DIR__.'/temp';
+ return __DIR__ . '/temp';
}
protected function createTables(...$tableNames)
@@ -104,6 +107,8 @@ protected function createTables(...$tableNames)
$table->integer('user_id')->unsigned()->nullable();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->text('json')->nullable();
+ $table->string('interval')->nullable();
+ $table->decimal('price')->nullable();
}
});
});
@@ -113,10 +118,10 @@ protected function seedModels(...$modelClasses)
{
collect($modelClasses)->each(function (string $modelClass) {
foreach (range(1, 0) as $index) {
- if ($modelClass==Article::class){
+ if ($modelClass == Article::class) {
$causer = User::first();
- $modelClass::create(['name' => "name {$index}",'user_id'=>$causer->id]);
- }else {
+ $modelClass::create(['name' => "name {$index}", 'user_id' => $causer->id]);
+ } else {
$modelClass::create(['name' => "name {$index}"]);
}
}
@@ -138,8 +143,19 @@ public function doNotMarkAsRisky()
public function isLaravel6OrLower(): bool
{
- $majorVersion = (int) substr(App::version(), 0, 1);
+ $majorVersion = (int)substr(App::version(), 0, 1);
return $majorVersion <= 6;
}
+
+ public function loginWithFakeUser()
+ {
+ $user = new $this->user();
+
+ $user::find(1);
+
+ $this->be($user);
+
+ return $user;
+ }
}