├── .github
├── require-dev-install.sh
└── workflows
│ ├── coding-standard.yml
│ ├── integration.yml
│ ├── mess-detector.yml
│ └── phpstan.yml
├── README.md
├── composer.json
├── docs
├── admin_menu_entry.png
└── extension_dashboard.png
├── src
├── Api
│ └── ReleaseProviderInterface.php
├── Controller
│ └── Adminhtml
│ │ └── Extensionlist
│ │ └── Index.php
├── ExtensionRelease
│ └── ExtensionRelease.php
├── Model
│ ├── ExtensionDocument.php
│ ├── ExtensionReleaseDb.php
│ └── Grid
│ │ ├── Collection.php
│ │ └── EmptyFilterPool.php
├── ReleaseProvider
│ ├── ComposerFeedReleaseProvider.php
│ ├── CsvReleaseProvider.php
│ ├── ReleaseProviderListing.php
│ └── ThirdParty
│ │ ├── FoomanReleaseProvider.php
│ │ └── YireoCommercialReleaseProvider.php
├── composer.json
├── data
│ └── all-releases.csv
├── etc
│ ├── acl.xml
│ ├── adminhtml
│ │ ├── menu.xml
│ │ └── routes.xml
│ ├── di.xml
│ └── module.xml
├── registration.php
└── view
│ └── adminhtml
│ ├── layout
│ └── extdndashboard_extensionlist_index.xml
│ └── ui_component
│ └── extdndashboard_extensionlist_grid.xml
└── tests
└── integration
└── testsuite
└── Extdn
└── ExtensionDashboard
└── Controller
└── Adminhtml
└── ExtensionListTest.php
/.github/require-dev-install.sh:
--------------------------------------------------------------------------------
1 | composer require fooman/magento2-phpunit-bridge --no-update
2 |
--------------------------------------------------------------------------------
/.github/workflows/coding-standard.yml:
--------------------------------------------------------------------------------
1 | name: ExtDN M2 Coding Standard
2 | on: [push, pull_request]
3 |
4 | jobs:
5 | static:
6 | name: M2 Coding Standard
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v2
10 | - uses: extdn/github-actions-m2/magento-coding-standard@master
11 |
--------------------------------------------------------------------------------
/.github/workflows/integration.yml:
--------------------------------------------------------------------------------
1 | name: ExtDN M2 Integration Tests
2 | on: [push, pull_request]
3 |
4 | jobs:
5 | integration-tests-2-3-mid:
6 | name: Magento 2.3.4 Integration Tests
7 | runs-on: ubuntu-latest
8 | services:
9 | mysql:
10 | image: mysql:5.7
11 | env:
12 | MYSQL_ROOT_PASSWORD: root
13 | ports:
14 | - 3306:3306
15 | options: --tmpfs /tmp:rw --tmpfs /var/lib/mysql:rw --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
16 | steps:
17 | - uses: actions/checkout@v2
18 | - name: M2 Integration Tests with Magento 2 (Php7.2)
19 | uses: extdn/github-actions-m2/magento-integration-tests/7.2@master
20 | with:
21 | module_name: Extdn_ExtensionDashboard
22 | composer_name: extdn/extension-dashboard-m2
23 | ce_version: '2.3.4'
24 | magento_pre_install_script: './.github/require-dev-install.sh'
25 | integration-tests-2-3-5:
26 | name: Magento 2.3.5 Integration Tests
27 | runs-on: ubuntu-latest
28 | services:
29 | mysql:
30 | image: mysql:5.7
31 | env:
32 | MYSQL_ROOT_PASSWORD: root
33 | ports:
34 | - 3306:3306
35 | options: --tmpfs /tmp:rw --tmpfs /var/lib/mysql:rw --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
36 | steps:
37 | - uses: actions/checkout@v2
38 | - name: M2 Integration Tests with Magento 2 (Php7.2)
39 | uses: extdn/github-actions-m2/magento-integration-tests/7.2@master
40 | with:
41 | module_name: Extdn_ExtensionDashboard
42 | composer_name: extdn/extension-dashboard-m2
43 | ce_version: '2.3.5'
44 | magento_pre_install_script: './.github/require-dev-install.sh'
45 | integration-tests-2-3-latest:
46 | name: Magento 2.3 Latest Integration Tests
47 | runs-on: ubuntu-latest
48 | services:
49 | mysql:
50 | image: mysql:5.7
51 | env:
52 | MYSQL_ROOT_PASSWORD: root
53 | ports:
54 | - 3306:3306
55 | options: --tmpfs /tmp:rw --tmpfs /var/lib/mysql:rw --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
56 | steps:
57 | - uses: actions/checkout@v2
58 | - name: M2 Integration Tests with Magento 2 (Php7.3)
59 | uses: extdn/github-actions-m2/magento-integration-tests/7.3@master
60 | with:
61 | module_name: Extdn_ExtensionDashboard
62 | composer_name: extdn/extension-dashboard-m2
63 | ce_version: '2.3.6'
64 | magento_pre_install_script: './.github/require-dev-install.sh'
65 | integration-tests-2-4-low:
66 | name: Magento 2.4.0 Integration Tests
67 | runs-on: ubuntu-latest
68 | services:
69 | mysql:
70 | image: mysql:5.7
71 | env:
72 | MYSQL_ROOT_PASSWORD: root
73 | ports:
74 | - 3306:3306
75 | options: --tmpfs /tmp:rw --tmpfs /var/lib/mysql:rw --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
76 | es:
77 | image: docker.io/wardenenv/elasticsearch:7.8
78 | ports:
79 | - 9200:9200
80 | env:
81 | 'discovery.type': single-node
82 | 'xpack.security.enabled': false
83 | ES_JAVA_OPTS: "-Xms64m -Xmx512m"
84 | options: --health-cmd="curl localhost:9200/_cluster/health?wait_for_status=yellow&timeout=60s" --health-interval=10s --health-timeout=5s --health-retries=3
85 | steps:
86 | - uses: actions/checkout@v2
87 | - name: M2 Integration Tests with Magento 2 (Php7.3)
88 | uses: extdn/github-actions-m2/magento-integration-tests/7.3@master
89 | with:
90 | module_name: Extdn_ExtensionDashboard
91 | composer_name: extdn/extension-dashboard-m2
92 | ce_version: '2.4.0'
93 | magento_pre_install_script: './.github/require-dev-install.sh'
94 | integration-tests-2-4-latest:
95 | name: Magento 2.4 Latest Integration Tests
96 | runs-on: ubuntu-latest
97 | services:
98 | mysql:
99 | image: mysql:5.7
100 | env:
101 | MYSQL_ROOT_PASSWORD: root
102 | ports:
103 | - 3306:3306
104 | options: --tmpfs /tmp:rw --tmpfs /var/lib/mysql:rw --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
105 | es:
106 | image: docker.io/wardenenv/elasticsearch:7.8
107 | ports:
108 | - 9200:9200
109 | env:
110 | 'discovery.type': single-node
111 | 'xpack.security.enabled': false
112 | ES_JAVA_OPTS: "-Xms64m -Xmx512m"
113 | options: --health-cmd="curl localhost:9200/_cluster/health?wait_for_status=yellow&timeout=60s" --health-interval=10s --health-timeout=5s --health-retries=3
114 | steps:
115 | - uses: actions/checkout@v2
116 | - name: M2 Integration Tests with Magento 2 (Php7.4)
117 | uses: extdn/github-actions-m2/magento-integration-tests/7.4@master
118 | with:
119 | module_name: Extdn_ExtensionDashboard
120 | composer_name: extdn/extension-dashboard-m2
121 | ce_version: '2.4.1'
122 | magento_pre_install_script: './.github/require-dev-install.sh'
123 |
--------------------------------------------------------------------------------
/.github/workflows/mess-detector.yml:
--------------------------------------------------------------------------------
1 | name: ExtDN M2 Mess Detector
2 | on: [push, pull_request]
3 |
4 | jobs:
5 | phpmd:
6 | name: M2 Mess Detector
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v2
10 | - uses: extdn/github-actions-m2/magento-mess-detector@master
11 |
--------------------------------------------------------------------------------
/.github/workflows/phpstan.yml:
--------------------------------------------------------------------------------
1 | name: ExtDN M2 PhpStan
2 | on: [push, pull_request]
3 |
4 | jobs:
5 | phpstan:
6 | name: M2 PhpStan
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v2
10 | - uses: extdn/github-actions-m2/magento-phpstan@master
11 | with:
12 | composer_name: extdn/extension-dashboard-m2
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Extension Dashboard for Magento 2
2 | This module adds a dashboard to review all installed extensions in the Magento admin (Magento 2.3.0+ for now only).
3 |
4 | ## Screenshots
5 | 
6 |
7 | 
8 |
9 | ## Installation
10 | We strongly recommend to always make changes to a Magento 2 site through a development environment that runs in the Developer Mode:
11 | ```bash
12 | bin/magento deploy:mode:set developer
13 | ```
14 |
15 | Add this Git repository to composer and then install the composer package:
16 | ```bash
17 | composer config repositories.extdndash git https://github.com/extdn/extension-dashboard-m2.git
18 | composer require extdn/extension-dashboard-m2:dev-master
19 | ```
20 |
21 | Next, enable the module:
22 | ```bash
23 | bin/magento module:enable Extdn_ExtensionDashboard
24 | bin/magento setup:upgrade
25 | ```
26 |
27 | Next, follow the usual procedure to push changes from the development environment to production (for example with `bin/magento deploy:mode:set production`).
28 |
29 | ## Extension feeds
30 | This dashboard is being fed through feeds: Either a CSV-file or a remote resource that allows you to define version-information. Currently, the following is supported:
31 |
32 | - Define a new DI VirtualType (see `di.xml`) to use the `ComposerFeedProvider` to load information from Packagist.
33 | - Use the `CsvFeedProvider` to load information from a local CSV file.
34 | - Add a custom provider to the listing of providers.
35 |
36 | ## Todo
37 | - Move extension feeds to different submodules?
38 | - Automatically fetch information from Packagist on existing extensions, if available.
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "extdn/extension-dashboard-m2",
3 | "license": "OSL-3.0",
4 | "description": "",
5 | "version": "0.0.1",
6 | "type": "magento2-module",
7 | "require": {
8 | "php": "~7.1.0|~7.2.0|~7.3.0|~7.4.0",
9 | "magento/framework": "^102.0|^103.0",
10 | "magento/module-backend": "^100.1|^101.0|^102.0",
11 | "league/csv": "^9.1"
12 | },
13 | "autoload": {
14 | "psr-4": {
15 | "Extdn\\ExtensionDashboard\\": "src/"
16 | },
17 | "files": [
18 | "src/registration.php"
19 | ]
20 | },
21 | "prefer-stable": true,
22 | "require-dev": {
23 | "fooman/magento2-phpunit-bridge": "^0.7.1| ^0.9.0",
24 | "magento/magento-coding-standard": "*"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/docs/admin_menu_entry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/extdn/extension-dashboard-m2/22afc1cb82f58426dd6a2c65e211c800ef18c190/docs/admin_menu_entry.png
--------------------------------------------------------------------------------
/docs/extension_dashboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/extdn/extension-dashboard-m2/22afc1cb82f58426dd6a2c65e211c800ef18c190/docs/extension_dashboard.png
--------------------------------------------------------------------------------
/src/Api/ReleaseProviderInterface.php:
--------------------------------------------------------------------------------
1 | _view->loadLayout();
18 | $this->_setActiveMenu('Extdn_ExtensionDashboard::index');
19 | $this->_view->getPage()->getConfig()->getTitle()->prepend(__('Extension Dashboard'));
20 | $this->_addBreadcrumb(__('Extension Dashboard'), __('Extension Dashboard'));
21 | $this->_view->renderLayout();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/ExtensionRelease/ExtensionRelease.php:
--------------------------------------------------------------------------------
1 | setModuleName((string)$data['module_name']);
20 | $this->setVersion((string)$data['version']);
21 | $this->setDate((string)$data['date']);
22 | $this->setSecurityRelease((bool)$data['security_release']);
23 | $this->setContent((string)$data['content']);
24 | }
25 |
26 | /**
27 | * @return string
28 | */
29 | public function getModuleName(): string
30 | {
31 | return (string) $this->getData('module_name');
32 | }
33 |
34 | /**
35 | * @param string $moduleName
36 | */
37 | private function setModuleName(string $moduleName): void
38 | {
39 | $this->setData('module_name', $moduleName);
40 | }
41 |
42 | /**
43 | * @return string
44 | */
45 | public function getVersion(): string
46 | {
47 | return (string) $this->getData('version');
48 | }
49 |
50 | /**
51 | * @param string $version
52 | */
53 | private function setVersion(string $version): void
54 | {
55 | $this->setData('version', $version);
56 | }
57 |
58 | /**
59 | * @return string
60 | */
61 | public function getDate(): string
62 | {
63 | return (string) $this->getData('date');
64 | }
65 |
66 | /**
67 | * @param string $date
68 | */
69 | private function setDate(string $date): void
70 | {
71 | $this->setData('date', $date);
72 | }
73 |
74 | /**
75 | * @return bool
76 | */
77 | public function isSecurityRelease(): bool
78 | {
79 | return (bool) $this->getData('security');
80 | }
81 |
82 | /**
83 | * @param bool $securityRelease
84 | */
85 | private function setSecurityRelease(bool $securityRelease): void
86 | {
87 | $this->setData('security', $securityRelease);
88 | }
89 |
90 | /**
91 | * @return string
92 | */
93 | public function getContent(): string
94 | {
95 | return (string) $this->getData('content');
96 | }
97 |
98 | /**
99 | * @param string $content
100 | */
101 | private function setContent(string $content): void
102 | {
103 | $this->setData('content', $content);
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/Model/ExtensionDocument.php:
--------------------------------------------------------------------------------
1 | extensionReleaseFactory = $extensionReleaseFactory;
39 | $this->releaseProviderListing = $releaseProviderListing;
40 | }
41 |
42 | /**
43 | * @param bool $printQuery
44 | * @param bool $logQuery
45 | * @return FrameworkDataCollection|void
46 | * @throws Exception
47 | */
48 | public function loadData($printQuery = false, $logQuery = false)
49 | {
50 | if (!$this->isLoaded()) {
51 | $releaseProviders = $this->releaseProviderListing->getList();
52 | foreach ($releaseProviders as $releaseProvider) {
53 | foreach ($releaseProvider->getExtensionReleases() as $extensionRelease) {
54 | $this->addItem($extensionRelease);
55 | }
56 | }
57 |
58 | $this->_setIsLoaded(true);
59 | }
60 | }
61 |
62 | /**
63 | * @param string $name
64 | * @return bool|Phrase
65 | */
66 | public function getLatestReleaseForModule(string $name)
67 | {
68 | $latest = false;
69 | foreach ($this->getItems() as $item) {
70 | /** @var ExtensionRelease $item */
71 | if ($item->getModuleName() === $name) {
72 | if (!$latest) {
73 | $latest = $item->getVersion();
74 | } elseif (version_compare($item->getVersion(), $latest, '>')) {
75 | $latest = $item->getVersion();
76 | }
77 | }
78 | }
79 |
80 | if ($latest) {
81 | return (string)$latest;
82 | }
83 |
84 | //TODO: Link this back to github repo to invite contributions
85 | return (string)__('No release data found in DB');
86 | }
87 |
88 | /**
89 | * @param string $name
90 | * @param string $installedVersion
91 | * @return string
92 | */
93 | public function getIsSecure(string $name, string $installedVersion): string
94 | {
95 | $found = false;
96 | $missing = [];
97 | foreach ($this->getItems() as $item) {
98 | /** @var ExtensionRelease $item */
99 | if ($item->getModuleName() === $name) {
100 | $found = true;
101 | if (version_compare($item->getVersion(), $installedVersion, '>')
102 | && $item->isSecurityRelease()) {
103 | $missing[] = $item->getVersion();
104 | }
105 | }
106 | }
107 |
108 | // @todo: Either return true or throw an Exception?
109 | if (!$found) {
110 | return (string)__('No release data found in DB');
111 | }
112 |
113 | // @todo: Make the display a bit nicer, warn with colour
114 | if (empty($missing)) {
115 | return (string)__('All applied');
116 | }
117 |
118 | return __('WARNING missing') . ': ' . implode(',', $missing);
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/src/Model/Grid/Collection.php:
--------------------------------------------------------------------------------
1 | moduleList = $moduleList;
71 | $this->moduleListActive = $moduleListActive;
72 | $this->extensionDocumentFactory = $extensionDocumentFactory;
73 | $this->packageInfo = $packageInfo;
74 | $this->extensionReleaseDb = $extensionReleaseDb;
75 | }
76 |
77 | /**
78 | * @return DocumentInterface[]
79 | */
80 | public function getItems()
81 | {
82 | if (empty($this->extensions)) {
83 | $allModules = $this->moduleList->getAll();
84 | foreach ($allModules as $module) {
85 | if ($this->isMagentoModule($module['name'])) {
86 | continue;
87 | }
88 |
89 | $this->extensions[] = $this->getDocFromModule($module);
90 | }
91 | }
92 |
93 | return $this->extensions;
94 | }
95 |
96 | /**
97 | * @param array $module
98 | * @return ExtensionDocument
99 | */
100 | private function getDocFromModule(array $module): ExtensionDocument
101 | {
102 | $packageName = $this->packageInfo->getPackageName($module['name']);
103 | $version = $this->packageInfo->getVersion($module['name']);
104 | $active = $this->moduleListActive->has($module['name']);
105 |
106 | $doc = $this->extensionDocumentFactory->create();
107 | $doc->setCustomAttribute('module_name', $module['name']);
108 | $doc->setCustomAttribute('setup_version', $module['setup_version']);
109 | $doc->setCustomAttribute('package_name', $packageName);
110 | $doc->setCustomAttribute('version', $version);
111 | $doc->setCustomAttribute('latest_version', $this->getLatestVersion((string)$module['name']));
112 | $doc->setCustomAttribute('is_secure', $this->isSecure($module['name'], $version));
113 | $doc->setCustomAttribute('active', $active ? __('Enabled') : __('Disabled'));
114 |
115 | return $doc;
116 | }
117 |
118 | /**
119 | * @param string $moduleName
120 | * @return bool|\Magento\Framework\Phrase
121 | */
122 | private function getLatestVersion(string $moduleName)
123 | {
124 | return $this->extensionReleaseDb->getLatestReleaseForModule($moduleName);
125 | }
126 |
127 | /**
128 | * @param string $moduleName
129 | * @param string $installedVersion
130 | * @return string
131 | */
132 | private function isSecure(string $moduleName, string $installedVersion)
133 | {
134 | // @todo: Refactor return value of underlying call
135 | return $this->extensionReleaseDb->getIsSecure($moduleName, $installedVersion);
136 | }
137 |
138 | /**
139 | * @param string $moduleName
140 | * @return bool
141 | */
142 | private function isMagentoModule(string $moduleName)
143 | {
144 | return substr($moduleName, 0, strlen(self::MAGENTO_VENDOR_NAME)) === self::MAGENTO_VENDOR_NAME;
145 | }
146 |
147 | /**
148 | * Get total count.
149 | *
150 | * @return int
151 | */
152 | public function getTotalCount(): int
153 | {
154 | return count($this->extensions);
155 | }
156 |
157 | /**
158 | * Set items list.
159 | *
160 | * @param \Magento\Framework\Api\ExtensibleDataInterface[] $items
161 | *
162 | * @return $this
163 | */
164 | public function setItems(?array $items = null)
165 | {
166 | $this->extensions = $items;
167 | return $this;
168 | }
169 |
170 | /**
171 | * Get search criteria.
172 | *
173 | * @return void
174 | */
175 | // phpcs:ignore Magento2.CodeAnalysis.EmptyBlock.DetectedFunction -- currently not used
176 | public function getSearchCriteria()
177 | {
178 | // TODO: Implement getSearchCriteria() method.
179 | }
180 |
181 | /**
182 | * Set search criteria.
183 | *
184 | * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria
185 | *
186 | * @return $this
187 | */
188 | public function setSearchCriteria(SearchCriteriaInterface $searchCriteria)
189 | {
190 | // TODO: Implement setSearchCriteria() method.
191 | return $this;
192 | }
193 |
194 | /**
195 | * Set total count.
196 | *
197 | * @param int $totalCount
198 | *
199 | * @return $this
200 | */
201 | public function setTotalCount($totalCount)
202 | {
203 | // TODO: Implement setTotalCount() method.
204 | return $this;
205 | }
206 |
207 | /**
208 | * @return \Magento\Framework\Api\Search\AggregationInterface
209 | */
210 | // phpcs:ignore Magento2.CodeAnalysis.EmptyBlock.DetectedFunction -- currently not used
211 | public function getAggregations()
212 | {
213 | // TODO: Implement getAggregations() method.
214 | }
215 |
216 | /**
217 | * @param \Magento\Framework\Api\Search\AggregationInterface $aggregations
218 | *
219 | * @return $this
220 | */
221 | public function setAggregations($aggregations)
222 | {
223 | // TODO: Implement setAggregations() method.
224 | return $this;
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/src/Model/Grid/EmptyFilterPool.php:
--------------------------------------------------------------------------------
1 | extensionReleaseFactory = $extensionReleaseFactory;
42 | $this->client = $client;
43 | $this->urls = $urls;
44 | }
45 |
46 | /**
47 | * @return ExtensionRelease[]
48 | */
49 | public function getExtensionReleases(): array
50 | {
51 | $items = [];
52 |
53 | foreach ($this->urls as $moduleName => $url) {
54 | try {
55 | $data = $this->getDataFromUrl($url);
56 | } catch (Exception $e) {
57 | continue;
58 | }
59 |
60 | foreach ($data['packages'] as $versions) {
61 | foreach ($versions as $version => $versionData) {
62 | $data = $this->getDataFromPackage($moduleName, $version, $versionData);
63 | $items[] = $this->extensionReleaseFactory->create(['data' => $data]);
64 | }
65 | }
66 | }
67 |
68 | return $items;
69 | }
70 |
71 | /**
72 | * @param string $moduleName
73 | * @param array $package
74 | * @return array
75 | */
76 | protected function getDataFromPackage(string $moduleName, string $version, array $package): array
77 | {
78 | return [
79 | 'module_name' => $moduleName,
80 | 'version' => $version,
81 | 'date' => date('Y-m-d', strtotime($package['time'])),
82 | 'security_release' => 0,
83 | 'content' => '',
84 | ];
85 | }
86 |
87 | /**
88 | * @param string $url
89 | * @return array
90 | * @throws RuntimeException
91 | */
92 | protected function getDataFromUrl(string $url): array
93 | {
94 | $response = $this->client->get($url);
95 | if (!$response) {
96 | throw new RuntimeException('Invalid response from URL ' . $url);
97 | }
98 |
99 | $contents = $response->getBody()->getContents();
100 | if (!$contents) {
101 | throw new RuntimeException('Empty response from URL ' . $url);
102 | }
103 |
104 | $data = json_decode($contents, true);
105 | if (!$data) {
106 | throw new RuntimeException('Empty data from URL ' . $url);
107 | }
108 |
109 | return $data;
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/ReleaseProvider/CsvReleaseProvider.php:
--------------------------------------------------------------------------------
1 | extensionReleaseFactory = $extensionReleaseFactory;
33 | $this->csvFile = $csvFile;
34 | }
35 |
36 | /**
37 | * @return ExtensionRelease[]
38 | */
39 | public function getExtensionReleases(): array
40 | {
41 | $csv = Reader::createFromPath($this->csvFile, 'r');
42 | $csv->setHeaderOffset(0);
43 | $records = $csv->getRecords();
44 |
45 | $items = [];
46 | foreach ($records as $record) {
47 | $record['module_name'] = $record['extension'];
48 | $record['security_release'] = $record['security'];
49 | $items[] = $this->extensionReleaseFactory->create(['data' => $record]);
50 | }
51 |
52 | return $items;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/ReleaseProvider/ReleaseProviderListing.php:
--------------------------------------------------------------------------------
1 | releaseProviders = $releaseProviders;
23 | }
24 |
25 | /**
26 | * @param ReleaseProviderInterface $releaseProvider
27 | */
28 | public function add(ReleaseProviderInterface $releaseProvider)
29 | {
30 | $this->releaseProviders[] = $releaseProvider;
31 | }
32 |
33 | /**
34 | * @return ReleaseProviderInterface[]
35 | */
36 | public function getList()
37 | {
38 | return $this->releaseProviders;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/ReleaseProvider/ThirdParty/FoomanReleaseProvider.php:
--------------------------------------------------------------------------------
1 | getPath('module', 'Extdn_ExtensionDashboard');
22 | $csvFile = $basePath . '/data/all-releases.csv';
23 |
24 | parent::__construct($extensionReleaseFactory, $csvFile);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/ReleaseProvider/ThirdParty/YireoCommercialReleaseProvider.php:
--------------------------------------------------------------------------------
1 | urls = [
40 | 'Yireo_TaxRatesManager2' => 'https://api.yireo.com/resource,packages/request,Yireo_TaxRatesManager2/',
41 | 'Yireo_EmailTester2' => 'https://api.yireo.com/resource,packages/request,Yireo_EmailTester2/',
42 | ];
43 |
44 | $this->extensionReleaseFactory = $extensionReleaseFactory;
45 | $this->client = $client;
46 | }
47 |
48 | /**
49 | * @return array
50 | * @throws Exception
51 | */
52 | public function getExtensionReleases(): array
53 | {
54 | $items = [];
55 | foreach ($this->urls as $moduleName => $url) {
56 | try {
57 | $data = $this->getDataFromUrl($url);
58 | } catch (Exception $e) {
59 | continue;
60 | }
61 |
62 | foreach ($data['packages'] as $package) {
63 | $data = $this->getDataFromPackage($moduleName, $package);
64 | $items[] = $this->extensionReleaseFactory->create(['data' => $data]);
65 | }
66 | }
67 |
68 | return $items;
69 | }
70 |
71 | /**
72 | * @param string $moduleName
73 | * @param array $package
74 | * @return array
75 | */
76 | private function getDataFromPackage(string $moduleName, array $package): array
77 | {
78 | return [
79 | 'module_name' => $moduleName,
80 | 'version' => $package['version'],
81 | 'date' => $package['version'] ?? '',
82 | 'security_release' => $package['security_release'] ?? 0,
83 | 'content' => $package['content'] ?? '',
84 | ];
85 | }
86 |
87 | /**
88 | * @param string $url
89 | * @return array
90 | * @throws RuntimeException
91 | */
92 | private function getDataFromUrl(string $url): array
93 | {
94 | $response = $this->client->get($url);
95 | if (!$response) {
96 | throw new RuntimeException('Invalid response from URL ' . $url);
97 | }
98 |
99 | $contents = $response->getBody()->getContents();
100 | if (!$contents) {
101 | throw new RuntimeException('Empty response from URL ' . $url);
102 | }
103 |
104 | $data = json_decode($contents, true);
105 | if (!$data) {
106 | throw new RuntimeException('Empty data from URL ' . $url);
107 | }
108 |
109 | return $data;
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "extdn/extension-dashboard-m2",
3 | "license": "OSL-3.0",
4 | "description": "",
5 | "version": "0.0.1",
6 | "type": "magento2-module",
7 | "require": {
8 | "php": "~7.1.0|~7.2.0",
9 | "magento/framework": "^102.0.0",
10 | "magento/module-backend": "^100.1.0 | ^101.0.0"
11 | },
12 | "autoload": {
13 | "psr-4": {
14 | "Extdn\\ExtensionDashboard\\": ""
15 | },
16 | "files": [
17 | "registration.php"
18 | ]
19 | },
20 | "prefer-stable": true
21 | }
--------------------------------------------------------------------------------
/src/data/all-releases.csv:
--------------------------------------------------------------------------------
1 | extension,version,date,security,content
2 | Fooman_PrintOrderPdf,103.1.0,2018-11-27,0,"ADDED:\nSupport for Magento 2.3"
3 | Fooman_PrintOrderPdf,103.0.3,2018-07-23,0,"CHANGED:\nReorganise unit and integration tests"
4 | Fooman_PrintOrderPdf,103.0.2,2018-07-19,0,"FIXED:\nAdjust integration test for 2.2.5"
5 | Fooman_PrintOrderPdf,103.0.1,2018-05-08,0,"ADDED:\nAbility to translate more terms (thanks @gediminaskv)\nFIXED:\nMinor code style issue"
6 | Fooman_PrintOrderPdf,103.0.0,2018-05-07,0,"CHANGED:\nPackage name renamed to fooman/printorderpdf-implementation-m2, installation should be via metapackage fooman/printorderpdf-m2\nIncreased version number by 100 to differentiate from metapackage\nFIXED:\nChange setTemplate workaround, use area emulation insteadConstructor change in Plugin\PaymentInfoBlockPlugin, removes copied template files"
7 | Fooman_PrintOrderPdf,2.2.2,2017-09-11,0,"CHANGED:\nAllow for different pdf versions in test"
8 | Fooman_PrintOrderPdf,2.2.1,2017-08-30,0,"CHANGED:\nAdded preprocessing of tests to run across 2.1/2.2"
9 | Fooman_PrintOrderPdf,2.2.0,2017-08-25,0,"FIXED:\nEmpty payment details by providing frontend pdf template for known template files\nADDED:\nAdded support for PHP 7.1"
10 | Fooman_PrintOrderPdf,2.1.0,2017-03-01,0,"ADDED:\nSupport for bundled products"
11 | Fooman_PrintOrderPdf,2.0.3,2016-06-29,0,"CHANGED:\nCompatibility with Magento 2.1, for Magento 2.0 use earlier versions"
12 | Fooman_PrintOrderPdf,2.0.2,2016-03-30,0,"CHANGED:\nTest improvements"
13 | Fooman_PrintOrderPdf,2.0.0,2015-12-09,0,"CHANGED:\nChange folder structure to src/ and tests/"
14 | Fooman_PrintOrderPdf,1.1.0,2015-11-29,0,"ADDED:\nProvide a Pdf Renderer so that Fooman Email Attachments M2 (separate extension) can attach a pdf to outgoing order confirmation emails\nTranslations"
15 | Fooman_PrintOrderPdf,1.0.2,2015-11-15,0,"CHANGED:\nPSR-2\nUse Magento repositories and factory\nUse Magento massaction\nUpdate code to stay compatible with latest Magento development branch"
16 | Fooman_PrintOrderPdf,1.0.1,2015-09-07,0,"CHANGED:\nUpdate code to stay compatible with latest Magento development branch"
17 | Fooman_PrintOrderPdf,1.0.0,2015-08-02,0,"ADDED:\nInitial release for Magento 2"
18 | Fooman_EmailAttachments,105.0.2,2018-12-11,0,"CHANGED:\nReverse 7.1 features as Magento Marketplace does not yet support it"
19 | Fooman_EmailAttachments,105.0.1,2018-11-27,0,"CHANGED:\nUse newer php features (minimum 7.1)"
20 | Fooman_EmailAttachments,105.0.0,2018-11-26,0,"CHANGED:\nAdd compatibility with Magento 2.3.0 and handle upgrade of Zend_Mail, for earlier versions of Magento useprevious versionsConstructor change in Model\EmailEventDispatcher\nexplicitly state Zend\Mime dependency"
21 | Fooman_EmailAttachments,104.0.4,2018-09-28,0,"ADDED:\nAbility to customise affect the final filename"
22 | Fooman_EmailAttachments,104.0.3,2018-07-23,0,"CHANGED:\nReorganised unit tests"
23 | Fooman_EmailAttachments,104.0.2,2018-07-15,0,"CHANGED:\nCode Quality improvement - use class constants"
24 | Fooman_EmailAttachments,104.0.1,2018-07-10,0,"CHANGED:\nFixed integration tests"
25 | Fooman_EmailAttachments,104.0.0,2018-06-25,0,"CHANGED:\nMajor rewrite - removed all preferences, use plugins on TransportBuilder and TransportFactory instead"
26 | Fooman_EmailAttachments,103.0.1,2018-03-20,0,"CHANGED:\nAdjusted tests to provide for Pdf Customiser transforming T&Cs to Pdfs"
27 | Fooman_EmailAttachments,103.0.0,2018-03-15,0,"CHANGED:\nPackage name renamed to fooman/emailattachments-implementation-m2, installation should be via metapackage fooman/emailattachments-m2\nIncreased version number by 100 to differentiate from metapackage\nMoved attachment code into separate classConstructor change Observer\AbstractObserver\nAttachments are also added to emails sent separately"
28 | Fooman_EmailAttachments,2.1.0,2017-09-01,0,"ADDED:\nSupport for PHP 7.1\nSupport for Magento 2.2.0"
29 | Fooman_EmailAttachments,2.0.8,2017-06-02,0,"FIXED:\nMake CheckoutAgreements dependency explicit"
30 | Fooman_EmailAttachments,2.0.7,2017-02-28,0,"ADDED:\nAbility for integration test to check for attachment name"
31 | Fooman_EmailAttachments,2.0.6,2017-02-26,0,"FIXED:\nTranslations of file names (thanks Manuel)"
32 | Fooman_EmailAttachments,2.0.5,2016-09-22,0,"ADDED:\nAdd note to ""Attach Order as Pdf"" that it requires the Print Order Pdf extension"
33 | Fooman_EmailAttachments,2.0.4,2016-06-15,0,"CHANGED:\nWiden dependencies in preparation for Magento 2.1.0"
34 | Fooman_EmailAttachments,2.0.3,2016-04-03,0,"FIXED:\nAdd missing configuration setting for attaching T&Cs to shipping email"
35 | Fooman_EmailAttachments,2.0.2,2016-04-01,0,"CHANGED:\nRelease for Marketplace"
36 | Fooman_EmailAttachments,2.0.1,2016-03-25,0,"ADDED:\nIntegration tests now support Pdf Customiser supplied attachments"
37 | Fooman_EmailAttachments,2.0.0,2016-01-21,0,"CHANGED:\nChange project folder structure to src/ and tests/ (not applicable for Marketplace version)"
38 | Fooman_EmailAttachments,1.0.0,2015-11-29,0,"ADDED:\nInitial release for Magento 2"
39 | Fooman_PdfCore,14.0.0,2019-01-25,0,"ADDED:\nAbility to use currency formatting with Custom Product Attribute ColumnsConstructor Change in Fooman\PdfCore\Block\Pdf\Column\Renderer\ProductAttribute\nFIXED:\nRow Total Column should match Magento when using discounts\nCHANGED:\nRemoved ability to select Tier Price columns"
40 | Fooman_PdfCore,13.1.0,2019-01-24,0,"ADDED:\nOriginal Price column\nCHANGED:\nAllow SKU product attribute to be displayed as it can be different to the ordered SKU"
41 | Fooman_PdfCore,13.0.3,2018-12-13,0,"FIXED:\nEnsure Pdf responses are not cached"
42 | Fooman_PdfCore,13.0.2,2018-11-27,0,"CHANGED:\nBold quantity if more than 1\nFIXED:\nUndefined offset notice when printing multiple packing slips with particular pagebreaks"
43 | Fooman_PdfCore,13.0.1,2018-09-27,0,"FIXED:\nCheckbox image not loading"
44 | Fooman_PdfCore,13.0.0,2018-09-25,1,"SECURITY:\nForce update to latest Tcpdf library version\nGuard against calls to file_exists for phar stream wrappersAll Constructors using Magento\Framework\Filesystem\Io\File changed to Helper\FileOps\nCHANGED:\nReorganise unit tests\nExplicitly state all dependencies"
45 | Fooman_PdfCore,12.0.1,2018-09-13,0,"FIXED:\nImage in Footer may be get flipped due to page constraints"
46 | Fooman_PdfCore,12.0.0,2018-09-12,0,"ADDED:\nAbility to set a label row on tableupdated view/frontend/templates/pdf/table.phtml\nFIXED:\nNull values are not formatted as currency\nProperty name clash with parent see Fooman\PdfCore\Block\Pdf\Column\Renderer\Currency"
47 | Fooman_PdfCore,11.1.0,2018-09-05,0,"ADDED:\nAbility to specify column alignment"
48 | Fooman_PdfCore,11.0.1,2018-08-31,0,"FIXED:\nFilename now works for pdf types without increment numbers"
49 | Fooman_PdfCore,11.0.0,2018-08-06,0,"ADDED:\nNew Column Type: Qty Details\nBackground image can now be suppressed from the adminConstructor Change in \Fooman\PdfCore\Helper\BackgroundImage\nFIXED:\nLinebreaks in footer content - updated view/frontend/templates/pdf/footer.phtml"
50 | Fooman_PdfCore,10.0.1,2018-06-05,0,"CHANGED:\nLocation of custom fonts is now under media/downloadable/pdfcustomfonts"
51 | Fooman_PdfCore,10.0.0,2018-06-05,0,"ADDED:\nAbility to upload custom fontschanged constructor in \Fooman\PdfCore\Model\PdfRenderer"
52 | Fooman_PdfCore,9.6.8,2018-03-07,0,"FIXED:\nConsistent linebreak on logo placement\nSubtotal column values on invoice and creditmemo"
53 | Fooman_PdfCore,9.6.7,2017-12-14,0,"FIXED:\nProduct attributes can have a trailing underscore\nFooter Font and Size now follow settings"
54 | Fooman_PdfCore,9.6.6,2017-11-15,0,"FIXED:\nPrevent default array to string conversion"
55 | Fooman_PdfCore,9.6.5,2017-11-15,0,"FIXED:\nPrevent double decoding of column config"
56 | Fooman_PdfCore,9.6.4,2017-11-13,0,"FIXED:\nPrice Column can now show tax inclusive/exclusive prices simultaneously"
57 | Fooman_PdfCore,9.6.3,2017-11-13,0,"FIXED:\nBarcode Column handling of deleting products"
58 | Fooman_PdfCore,9.6.2,2017-11-11,0,"FIXED:\nColumns setting can be pre-populated with default values"
59 | Fooman_PdfCore,9.6.1,2017-11-08,0,"FIXED:\nPrice Column tax in-/exclusiveness in a multi-store environment"
60 | Fooman_PdfCore,9.6.0,2017-11-03,0,"ADDED:\nWeight Column"
61 | Fooman_PdfCore,9.5.7,2017-10-30,0,"FIXED:\nAllow linebreak tag in product attribute column"
62 | Fooman_PdfCore,9.5.6,2017-10-26,0,"FIXED:\nImage dimensions need to be without unit on php 7.1\napp:config:import with column settings"
63 | Fooman_PdfCore,9.5.5,2017-10-11,0,"ADDED:\nPdfRenderer object to fooman_pdfcore_before_write_html event"
64 | Fooman_PdfCore,9.5.4,2017-10-01,0,"FIXED:\nApp Emulation needs to force Locale in the back-end"
65 | Fooman_PdfCore,9.5.3,2017-09-17,0,"CHANGED:\nRe-organised tests"
66 | Fooman_PdfCore,9.5.2,2017-09-12,0,"CHANGED:\nTemplate processing"
67 | Fooman_PdfCore,9.5.1,2017-09-10,0,"FIXED:\nMake Footer template change backward compatible"
68 | Fooman_PdfCore,9.5.0,2017-09-07,0,"ADDED:\nMake template variables accessible in the footer\nSupport for Php 7.1"
69 | Fooman_PdfCore,9.4.0,2017-08-22,0,"ADDED:\nCommon Pdf file handler"
70 | Fooman_PdfCore,9.3.5,2017-08-02,0,"FIXED:\nEmpty template during Store Emulation"
71 | Fooman_PdfCore,9.3.4,2017-07-16,0,"CHANGED:\nBetter compatibility alignment with Magento php versions\nFurther spacing improvements"
72 | Fooman_PdfCore,9.3.3,2017-07-07,0,"FIXED:\nSpacing for barcode column"
73 | Fooman_PdfCore,9.3.2,2017-06-25,0,"CHANGED:\nAdded supported php versions"
74 | Fooman_PdfCore,9.3.1,2017-06-24,0,"CHANGED:\nImproved spacing for images\nFIXED:\nMagento template filename resolver caches too aggressively"
75 | Fooman_PdfCore,9.3.0,2017-06-20,0,"ADDED:\nLogo block and helper now accept a maxheight argument\nCHANGED:\nImplemented some MEQP2 suggestions\nFIXED:\nMagento template filename resolver caches too aggressively"
76 | Fooman_PdfCore,9.2.0,2017-05-26,0,"ADDED:\nAbility to display both order and base currencies simultaneously"
77 | Fooman_PdfCore,9.1.3,2017-05-25,0,"FIXED:\nImage file location on invoices,creditmemos and shipments"
78 | Fooman_PdfCore,9.1.2,2017-05-16,0,"CHANGED:\nTweaked positioning on integrated label"
79 | Fooman_PdfCore,9.1.1,2017-04-10,0,"CHANGED:\nTweaked Image Display"
80 | Fooman_PdfCore,9.1.0,2017-04-10,0,"CHANGED:\nConfigurable product image now displays the simple product's image\nADDED:\nNew column type: Row Total"
81 | Fooman_PdfCore,9.0.2,2017-03-11,0,"CHANGED:\nNicer formatting of tax percentage column\nRetrieve price from order item\nFIXED:\nFooter store id retrieval"
82 | Fooman_PdfCore,9.0.1,2017-03-01,0,"FIXED:\nPass through reset param for filename helper"
83 | Fooman_PdfCore,9.0.0,2017-02-27,0,"ADDED:\nEmit event in PdfRenderer"
84 | Fooman_PdfCore,8.1.0,2017-02-23,0,"ADDED:\nCheckbox Column"
85 | Fooman_PdfCore,8.0.2,2017-02-13,0,"ADDED:\nAllow filename to be reset\nFIXED:\nProduct attribute values on non order pdfs"
86 | Fooman_PdfCore,8.0.1,2017-02-06,0,"FIXED:\nAlternative approach for cron translation fix"
87 | Fooman_PdfCore,8.0.0,2017-02-04,0,"ADDED:\nAdd ability to set a row background color\nFIXED:\nExplicitly revert emulated design\nUse Image call directly to benefit from automatic scaling\nWorkaround for Magento 2 bug to ensure translation of email pdfs via cron(Changed DocumentRenderer constructor)"
88 | Fooman_PdfCore,7.0.1,2016-12-23,0,"FIXED:\nFooter block template can be themed\nCHANGED:\nAllow plugin column listing"
89 | Fooman_PdfCore,7.0.0,2016-12-20,0,"ADDED:\nNew getForcedPageOrientation() method for DocumentRendererInterface\nTax Percentage Column"
90 | Fooman_PdfCore,6.1.2,2016-11-12,0,"FIXED:\nDefault fallback for Custom column titles"
91 | Fooman_PdfCore,6.1.1,2016-11-11,0,"FIXED:\nTax column uses new currency renderer"
92 | Fooman_PdfCore,6.1.0,2016-11-06,0,"ADDED:\nCustom titles for columns\nFIXED:\nPrice column now follows Magento setting\nMagento changed currency renderer"
93 | Fooman_PdfCore,6.0.0,2016-10-19,0,"CHANGED:\nDocument Renderer now uses Template directly instead of via a Factory\nADDED:\nSubtotal excluding tax column"
94 | Fooman_PdfCore,5.0.1,2016-09-22,0,"FIXED:\nCheck to exclude some product attributes"
95 | Fooman_PdfCore,5.0.0,2016-09-15,0,"ADDED:\nBackground images\nFIXED:\nSome settings were not multistore capable\ngetStoreId() added to DocumentRendererInterface"
96 | Fooman_PdfCore,4.1.0,2016-08-26,0,"ADDED:\nSupport Product Attribute Column"
97 | Fooman_PdfCore,4.0.1,2016-08-19,0,"FIXED:\nshow column extras in templates/pdf/table.html, adjusted spacing"
98 | Fooman_PdfCore,4.0.0,2016-07-25,0,"ADDED:\nSupport for integrated labels\nAbility to restore default values\nCHANGED:\nCompatibility with Magento 2.1, for Magento 2.0 use earlier versions\nColumns setting field HtmlId is not random anymore"
99 | Fooman_PdfCore,3.0.6,2016-06-14,0,"FIXED:\nMulti store capability of footer blocks"
100 | Fooman_PdfCore,3.0.5,2016-06-09,0,"FIXED:\nVersion Number"
101 | Fooman_PdfCore,3.0.4,2016-06-09,0,"FIXED:\nAllow setting of currency for table columns\nCompatibility with Magento 2.1.0-rc1\nPage break on table rows\nConstant line height on images\nCHANGED:\nRun footer through template engine"
102 | Fooman_PdfCore,3.0.3,2016-03-25,0,"FIXED:\nComposer.json for registration and dependency declaration of core modules\nM2 code style"
103 | Fooman_PdfCore,3.0.2,2016-03-24,0,"FIXED:\nExtra second composer.json to support Magento Setup UI"
104 | Fooman_PdfCore,3.0.1,2016-03-13,0,"FIXED:\nCode Style improvements"
105 | Fooman_PdfCore,3.0.0,2016-02-22,0,"CHANGED:\nInitial Release for Magento 2"
106 | Fooman_SameOrderInvoiceNumber,3.0.0,2018-11-28,0,"CHANGED:\nPackage changed into a Metapackage - Implementation moved into fooman/sameorderinvoicenumber-implementation-m2 package\nSemantic versioning will only be applied to the implementation package\nADDED:\nSupport for Magento 2.3"
107 | Fooman_SameOrderInvoiceNumber,2.1.1,2018-07-22,0,"CHANGED:\nReorganised unit tests\nFIXED:\nShipment Integration test for Magento 2.2.5"
108 | Fooman_SameOrderInvoiceNumber,2.1.0,2017-09-27,0,"ADDED:\nSupport for PHP 7.1\nSupport for Magento 2.2.0"
109 | Fooman_SameOrderInvoiceNumber,2.0.5,2016-05-30,0,"FIXED:\nUpdate functional tests to work with 2.1.0-rc1"
110 | Fooman_SameOrderInvoiceNumber,2.0.4,2016-05-24,0,"FIXED:\nWiden Dependency Definition to work with 2.1.0"
111 | Fooman_SameOrderInvoiceNumber,2.0.3,2016-04-03,0,"CHANGED:\nMove dependencies in right location in composer.json\nAdd integration tests"
112 | Fooman_SameOrderInvoiceNumber,2.0.2,2016-02-10,0,"FIXES:\nresource_ids updated to work with new Magento Core module names"
113 | Fooman_SameOrderInvoiceNumber,2.0.1,2015-12-15,0,"FIXES:\nregistration.php was missing from autoload"
114 | Fooman_SameOrderInvoiceNumber,2.0.0,2015-12-08,0,"CHANGED:\nChange project folder structure to src/ and tests/"
115 | Fooman_SameOrderInvoiceNumber,1.0.3,2015-12-06,0,"ADDED:\nInitial release for Magento 2"
116 |
--------------------------------------------------------------------------------
/src/etc/acl.xml:
--------------------------------------------------------------------------------
1 |
2 |