├── Api
├── ConfigRecordRepositoryInterface.php
└── Data
│ ├── ConfigRecordInterface.php
│ └── ConfigRecordSearchResultsInterface.php
├── COPYING.txt
├── Controller
└── Adminhtml
│ ├── ConfigRecord.php
│ └── ConfigRecord
│ ├── Index.php
│ └── Revert.php
├── LICENSE
├── Logger
├── Handler.php
└── Logger.php
├── Model
├── ConfigRecord.php
├── ConfigRecord
│ └── DataProvider.php
├── ConfigRecordRepository.php
└── ResourceModel
│ ├── ConfigRecord.php
│ └── ConfigRecord
│ └── Collection.php
├── Plugin
└── App
│ └── Config
│ └── Value.php
├── README.md
├── Service
├── Cache.php
└── System
│ └── Config
│ └── Record.php
├── Ui
└── Component
│ └── Listing
│ └── Column
│ └── ConfigRecordActions.php
├── composer.json
├── etc
├── acl.xml
├── adminhtml
│ ├── di.xml
│ ├── menu.xml
│ └── routes.xml
├── db_schema.xml
├── di.xml
└── module.xml
├── registration.php
└── view
└── adminhtml
├── layout
└── configrecord_configrecord_index.xml
├── ui_component
└── ronangr1_systemconfigwhodidthislogger_configrecord_listing.xml
└── web
└── css
└── source
└── _module.less
/Api/ConfigRecordRepositoryInterface.php:
--------------------------------------------------------------------------------
1 | setActiveMenu(self::ADMIN_RESOURCE)
19 | ->addBreadcrumb(__('Config'), __('Config'))
20 | ->addBreadcrumb(__('Record'), __('Record'));
21 | return $resultPage;
22 | }
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/ConfigRecord/Index.php:
--------------------------------------------------------------------------------
1 | resultPageFactory->create();
27 | $resultPage->getConfig()->getTitle()->prepend(__("Config Records"));
28 | return $resultPage;
29 | }
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/ConfigRecord/Revert.php:
--------------------------------------------------------------------------------
1 | resultRedirectFactory->create();
33 | $id = $this->getRequest()->getParam('entity_id');
34 | if ($id) {
35 | try {
36 | $configRecord = $this->configRecordRepository->get($id);
37 | if($configRecord->getEntityId()) {
38 | $this->writer->save($configRecord->getPath(), $configRecord->getOldValue(), $configRecord->getScope());
39 | $this->configRecordRepository->delete($configRecord);
40 | $this->cache->clean();
41 | $this->messageManager->addSuccessMessage(__('You reverted the record.'));
42 | }
43 | return $resultRedirect->setPath('*/*/');
44 | } catch (\Exception $e) {
45 | $this->messageManager->addErrorMessage($e->getMessage());
46 | return $resultRedirect->setPath('*/*/edit', ['entity_id' => $id]);
47 | }
48 | }
49 | $this->messageManager->addErrorMessage(__('We can\'t find a record to revert.'));
50 | return $resultRedirect->setPath('*/*/');
51 | }
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright © 2022-present
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
--------------------------------------------------------------------------------
/Logger/Handler.php:
--------------------------------------------------------------------------------
1 | _init(ResourceModel\ConfigRecord::class);
19 | }
20 |
21 | public function getEntityId(): string
22 | {
23 | return $this->getData(self::ENTITY_ID);
24 | }
25 |
26 | /**
27 | * @param string|int $entityId
28 | * @return \Ronangr1\SystemConfigWhoDidThisLogger\Api\Data\ConfigRecordInterface
29 | */
30 | public function setEntityId($entityId): ConfigRecordInterface
31 | {
32 | return $this->setData(self::ENTITY_ID, $entityId);
33 | }
34 |
35 | public function getAuthor(): ?string
36 | {
37 | return $this->getData(self::AUTHOR);
38 | }
39 |
40 | public function setAuthor(string $author): ConfigRecordInterface
41 | {
42 | return $this->setData(self::AUTHOR, $author);
43 | }
44 |
45 | public function getPath(): ?string
46 | {
47 | return $this->getData(self::PATH);
48 | }
49 |
50 | public function setPath(string $path): ConfigRecordInterface
51 | {
52 | return $this->setData(self::PATH, $path);
53 | }
54 |
55 | public function getOldValue(): ?string
56 | {
57 | return $this->getData(self::OLD_VALUE);
58 | }
59 |
60 | public function setOldValue(string $oldValue): ConfigRecordInterface
61 | {
62 | return $this->setData(self::OLD_VALUE, $oldValue);
63 | }
64 |
65 | public function getNewValue(): ?string
66 | {
67 | return $this->getData(self::NEW_VALUE);
68 | }
69 |
70 | public function setNewValue(string $newValue): ConfigRecordInterface
71 | {
72 | return $this->setData(self::NEW_VALUE, $newValue);
73 | }
74 |
75 | public function getScope(): string
76 | {
77 | return $this->getData(self::SCOPE);
78 | }
79 |
80 | public function setScope(string $scope): ConfigRecordInterface
81 | {
82 | return $this->setData(self::SCOPE, $scope);
83 | }
84 |
85 | public function getRecordedAt(): ?string
86 | {
87 | return $this->getData(self::RECORDED_AT);
88 | }
89 |
90 | public function setRecordedAt(string $recordAt): ConfigRecordInterface
91 | {
92 | return $this->setData(self::RECORDED_AT, $recordAt);
93 | }
94 | }
95 |
96 |
--------------------------------------------------------------------------------
/Model/ConfigRecord/DataProvider.php:
--------------------------------------------------------------------------------
1 | collection = $collectionFactory->create();
32 | $this->dataPersistor = $dataPersistor;
33 | parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data);
34 | }
35 |
36 | public function getData(): ?array
37 | {
38 | if (isset($this->loadedData)) {
39 | return $this->loadedData;
40 | }
41 | $items = $this->collection->getItems();
42 | foreach ($items as $model) {
43 | $this->loadedData[$model->getId()] = $model->getData();
44 | }
45 | $data = $this->dataPersistor->get('ronangr1_systemconfigwhodidthislogger_configrecord');
46 |
47 | if (!empty($data)) {
48 | $model = $this->collection->getNewEmptyItem();
49 | $model->setData($data);
50 | $this->loadedData[$model->getId()] = $model->getData();
51 | $this->dataPersistor->clear('ronangr1_systemconfigwhodidthislogger_configrecord');
52 | }
53 |
54 | return $this->loadedData;
55 | }
56 | }
57 |
58 |
--------------------------------------------------------------------------------
/Model/ConfigRecordRepository.php:
--------------------------------------------------------------------------------
1 | resource->save($configRecord);
42 | } catch (\Exception $exception) {
43 | throw new CouldNotSaveException(__(
44 | 'Could not save the Config Record : %1',
45 | $exception->getMessage()
46 | ));
47 | }
48 | return $configRecord;
49 | }
50 |
51 | public function get(string $entityId): ConfigRecordInterface
52 | {
53 | $configRecord = $this->configRecordFactory->create();
54 | $this->resource->load($configRecord, $entityId);
55 | if (!$configRecord->getId()) {
56 | throw new NoSuchEntityException(__('Config Record with id "%1" does not exist.', $entityId));
57 | }
58 | return $configRecord;
59 | }
60 |
61 | public function getList(
62 | SearchCriteriaInterface $criteria
63 | ): ConfigRecordSearchResultsInterface
64 | {
65 | $collection = $this->configRecordCollectionFactory->create();
66 |
67 | $this->collectionProcessor->process($criteria, $collection);
68 |
69 | $searchResults = $this->searchResultsFactory->create();
70 | $searchResults->setSearchCriteria($criteria);
71 |
72 | $items = [];
73 | foreach ($collection as $model) {
74 | $items[] = $model;
75 | }
76 |
77 | $searchResults->setItems($items);
78 | $searchResults->setTotalCount($collection->getSize());
79 | return $searchResults;
80 | }
81 |
82 | /**
83 | * @throws \Magento\Framework\Exception\CouldNotDeleteException
84 | */
85 | public function delete(ConfigRecordInterface $configRecord): bool
86 | {
87 | try {
88 | $configRecordModel = $this->configRecordFactory->create();
89 | $this->resource->load($configRecordModel, $configRecord->getEntityId());
90 | $this->resource->delete($configRecordModel);
91 | } catch (\Exception $exception) {
92 | throw new CouldNotDeleteException(__(
93 | 'Could not delete the Config Record: %1',
94 | $exception->getMessage()
95 | ));
96 | }
97 | return true;
98 | }
99 |
100 | public function deleteById(string $entityId): bool
101 | {
102 | return $this->delete($this->get($entityId));
103 | }
104 | }
105 |
106 |
--------------------------------------------------------------------------------
/Model/ResourceModel/ConfigRecord.php:
--------------------------------------------------------------------------------
1 | _init(self::TABLE_NAME, 'entity_id');
19 | }
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/Model/ResourceModel/ConfigRecord/Collection.php:
--------------------------------------------------------------------------------
1 | _init(
21 | ConfigRecord::class,
22 | ConfigRecordResourceModel::class
23 | );
24 | }
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/Plugin/App/Config/Value.php:
--------------------------------------------------------------------------------
1 | authSession->getUser();
29 | if ($user->getId()) {
30 | if ($subject->getOldValue()) {
31 | $this->recordService->record([
32 | "author" => sprintf("%s (%s)", $user->getName(), $user->getEmail()),
33 | "path" => $subject->getPath(),
34 | "scope" => $subject->getScope(),
35 | "old_value" => $subject->getOldValue(),
36 | "new_value" => $subject->getValue()
37 | ]);
38 | }
39 | }
40 | } catch (\Exception $e) {
41 | $this->logger->debug($e->getMessage());
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Module for Magento 2
2 |
3 | [](https://packagist.org/packages/ronangr1/module-systemconfigwhodidthislogger)
4 | [](./LICENSE)
5 | [](https://packagist.org/packages/ronangr1/module-systemconfigwhodidthislogger/stats)
6 | [](https://packagist.org/packages/ronangr1/module-systemconfigwhodidthislogger/stats)
7 |
8 | This module allows you to record any changes made to the configuration of your Magento 2 application
9 |
10 | - [Setup](#setup)
11 | - [Composer installation](#composer-installation)
12 | - [Setup the module](#setup-the-module)
13 | - [Documentation](#documentation)
14 | - [Support](#support)
15 | - [Authors](#authors)
16 | - [License](#license)
17 |
18 | ## Setup
19 |
20 | Magento 2 Open Source or Commerce edition is required.
21 |
22 | ### Composer installation
23 |
24 | Run the following composer command:
25 |
26 | ```
27 | composer require ronangr1/module-systemconfigwhodidthislogger
28 | ```
29 |
30 | ### Setup the module
31 |
32 | Run the following magento command:
33 |
34 | ```
35 | bin/magento setup:upgrade
36 | ```
37 |
38 | **If you are in production mode, do not forget to recompile and redeploy the static resources.**
39 |
40 | ## Documentation
41 |
42 | Go to `Store > Config Records` to see who the fuck changed the configuration values.
43 |
44 | ## Support
45 |
46 | Raise a new [request](https://github.com/ronangr1/M2-SystemConfigWhoDidThisLogger/issues) to the issue tracker.
47 |
48 | ## Authors
49 |
50 | - **ronangr1** - *Maintainer* - [](https://github.com/ronangr1)
51 | - **Contributors** - *Contributor* - [](https://github.com/ronangr1/M2-SystemConfigWhoDidThisLogger/graphs/contributors)
52 |
53 | ## License
54 |
55 | This project is licensed under the MIT License - see the [LICENSE](./LICENSE) details.
56 |
57 | ***That's all folks!***
58 |
--------------------------------------------------------------------------------
/Service/Cache.php:
--------------------------------------------------------------------------------
1 | cacheTypes;
27 | foreach ($types as $type) {
28 | $this->cacheTypeList->cleanType($type);
29 | }
30 | foreach ($this->cacheFrontendPool as $cacheFrontend) {
31 | $cacheFrontend->getBackend()->clean();
32 | }
33 | } catch (\Exception) {
34 | return false;
35 | }
36 | return true;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Service/System/Config/Record.php:
--------------------------------------------------------------------------------
1 | configRecordFactory->create();
33 | $record->setData($data);
34 | $this->configRecordRepository->save($record);
35 | } catch (\Exception) {
36 | return false;
37 | }
38 | return true;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Ui/Component/Listing/Column/ConfigRecordActions.php:
--------------------------------------------------------------------------------
1 | urlBuilder = $urlBuilder;
29 | parent::__construct($context, $uiComponentFactory, $components, $data);
30 | }
31 |
32 | public function prepareDataSource(array $dataSource): array
33 | {
34 | if (isset($dataSource['data']['items'])) {
35 | foreach ($dataSource['data']['items'] as & $item) {
36 | if (isset($item['entity_id'])) {
37 | $item[$this->getData('name')] = [
38 | 'revert' => [
39 | 'href' => $this->urlBuilder->getUrl(
40 | static::URL_PATH_REVERT,
41 | [
42 | 'entity_id' => $item['entity_id']
43 | ]
44 | ),
45 | 'label' => __('Revert'),
46 | 'confirm' => [
47 | 'title' => __('Revert'),
48 | 'message' => __('Are you sure you wan\'t to revert this record?')
49 | ]
50 | ]
51 | ];
52 | }
53 | }
54 | }
55 |
56 | return $dataSource;
57 | }
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ronangr1/module-systemconfigwhodidthislogger",
3 | "description": "This module allows you to record any changes made to the configuration of your Magento 2 application\n\n",
4 | "type": "magento2-module",
5 | "license": "MIT",
6 | "authors": [
7 | {
8 | "name": "ronangr1",
9 | "email": "guerin.ronan@proton.me"
10 | }
11 | ],
12 | "minimum-stability": "dev",
13 | "require": {
14 | "php": ">=8.0"
15 | },
16 | "autoload": {
17 | "files": [
18 | "registration.php"
19 | ],
20 | "psr-4": {
21 | "Ronangr1\\SystemConfigWhoDidThisLogger\\": ""
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/etc/acl.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
10 |
21 |