Skip to content

Commit 9ce826b

Browse files
committed
Make phpstan work without db connection
- do not include/run Mage class - provide helper class for loading Magento and Modules XML configuration - introduce new configuration parameter "magentoRootPath"
1 parent 060a5b4 commit 9ce826b

File tree

8 files changed

+655
-28
lines changed

8 files changed

+655
-28
lines changed

README.md

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# PHPStan Extension for Magento 1
1+
# PHPStan Extension for Magento 1 / OpenMage MageLTS
22

33
Extension for [PHPStan](https://github.com/phpstan/phpstan) to allow analysis of Magento 1 code.
4+
It doesn't require db connection to run.
45

5-
Currently it assumes Magento is installed in the `htdocs/` directory of the project root. Further work is needed in phpstan itself to allow more intellegence for extensions to be more customised whilst working with both phpstan/phpstan and phpstan/phpstan-shim.
66

77
## Usage
88

@@ -12,32 +12,47 @@ Make sure it has
1212

1313
```neon
1414
includes:
15-
- vendor/vianetz/phpstan-magento1/extension.neon
15+
- vendor/macopedia/phpstan-magento1/extension.neon
1616
```
1717

1818
Then run
1919

2020
```bash
21-
composer require inviqa/phpstan-magento1 phpstan/phpstan
21+
composer require --dev macopedia/phpstan-magento1
2222
```
2323

2424
## Alternative Magento path
2525

2626
By default this extension assumes the Magento directory is `%currentWorkingDirectory%/htdocs`.
27-
27+
You can adapt the path by changing the `magentoRootPath` parameter in the phpstan.neon file.
2828
Add to the project's phpstan.neon:
2929

3030
```neon
3131
parameters:
32+
magentoRootPath: %currentWorkingDirectory%/htdocs
33+
34+
```
35+
36+
## Example configuration file for analysing Magento Module
37+
38+
```neon
39+
parameters:
40+
magentoRootPath: %currentWorkingDirectory%/htdocs
3241
paths:
3342
- %currentWorkingDirectory%/path/to/magento/app/code/local
3443
autoload_files:
3544
- %currentWorkingDirectory%/path/to/magento/app/Mage.php
45+
paths:
46+
#lets start small with just our extensions
47+
- %currentWorkingDirectory%/app/code/local/VendorName/ModuleName
48+
excludePaths:
49+
- */Vendor/ModuleName/SomePathToExclude/*
50+
level: 0
3651
```
3752

3853
# Known Issues
3954

40-
## Data/SQL scripts can't be tested
55+
## Data/SQL scripts can't be tested
4156

4257
Since these scripts use a presumed $this variable due to being included from a setup class, work is needed to:
4358

composer.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
{
2-
"name": "vianetz/phpstan-magento1",
2+
"name": "macopedia/phpstan-magento1",
33
"description": "Extension for PHPStan to allow analysis of Magento 1 code.",
44
"type": "library",
55
"require": {
6-
"phpstan/phpstan": "^0.11|^0.12",
6+
"phpstan/phpstan": "^0.12",
77
"php": ">= 7.2"
88
},
99
"replace": {
10-
"inviqa/phpstan-magento1": "0.1.5"
10+
"inviqa/phpstan-magento1": "0.1.5",
11+
"vianetz/phpstan-magento1": "0.1.5"
1112
},
1213
"autoload": {
1314
"psr-4": {

extension.neon

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
1+
parametersSchema:
2+
magentoRootPath: string()
13
parameters:
2-
excludes_analyse:
4+
magentoRootPath: %currentWorkingDirectory%/htdocs
5+
excludePaths:
36
- */app/code/local/*/*/data/*
47
- */app/code/local/*/*/sql/*
58
bootstrapFiles:
6-
- %currentWorkingDirectory%/htdocs/app/Mage.php
79
- phpstan-bootstrap.php
10+
scanFiles:
11+
- %magentoRootPath%/app/Mage.php
12+
- %magentoRootPath%/app/code/core/Mage/Core/functions.php
13+
scanDirectories:
14+
#for static reflection, so we don't have to call autoloader
15+
- %magentoRootPath%/lib/
16+
- %magentoRootPath%/app/code/local/
17+
- %magentoRootPath%/app/code/community/
18+
- %magentoRootPath%/app/code/core/
819
typeAliases:
920
Mage_Catalog_Model_Entity_Product_Collection: 'Mage_Catalog_Model_Resource_Product_Collection'
1021
callback: 'callable'
@@ -37,4 +48,4 @@ services:
3748
-
3849
class: PHPStanMagento1\Type\Mage\Helper
3950
tags:
40-
- phpstan.broker.dynamicStaticMethodReturnTypeExtension
51+
- phpstan.broker.dynamicStaticMethodReturnTypeExtension

phpstan-bootstrap.php

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,48 @@
33

44
use PHPStanMagento1\Autoload\Magento\ModuleControllerAutoloader;
55

6+
if (!defined('DS')) {
7+
define('DS', DIRECTORY_SEPARATOR);
8+
}
9+
if (!defined('PS')) {
10+
define('PS', PATH_SEPARATOR);
11+
}
12+
13+
/**
14+
* @var $container \PHPStan\DependencyInjection\MemoizingContainer
15+
*/
16+
$magentoRootPath = $container->getParameter('magentoRootPath');
17+
if (empty($magentoRootPath)) {
18+
throw new \Exception('Please set "magentoRootPath" in your phpstan.neon.');
19+
}
20+
21+
if (!defined('BP')) {
22+
define('BP', $magentoRootPath);
23+
}
24+
25+
/**
26+
* Set include path
27+
*/
28+
$paths = [];
29+
$paths[] = BP . DS . 'app' . DS . 'code' . DS . 'local';
30+
$paths[] = BP . DS . 'app' . DS . 'code' . DS . 'community';
31+
$paths[] = BP . DS . 'app' . DS . 'code' . DS . 'core';
32+
$paths[] = BP . DS . 'lib';
33+
34+
$appPath = implode(PS, $paths);
35+
set_include_path($appPath . PS . get_include_path());
36+
include_once "Mage/Core/functions.php";
37+
638
(new ModuleControllerAutoloader('local'))->register();
739
(new ModuleControllerAutoloader('core'))->register();
840
(new ModuleControllerAutoloader('community'))->register();
941

1042
/**
11-
* We replace the original Varien_Autoload autoloader with a custom one.
43+
* Custom autoloader compatible with Varien_Autoload
44+
* Autoloading is needed only for the PHPStanMagento1\Config\MagentoCore which inherits from some magento classes.
45+
* PHPStan uses static analysis, so doesn't require autoloading.
1246
*/
1347
spl_autoload_register(static function($className) {
14-
spl_autoload_unregister([Varien_Autoload::instance(), 'autoload']);
1548

1649
$classFile = str_replace(' ', DIRECTORY_SEPARATOR, ucwords(str_replace('_', ' ', $className)));
1750
$classFile .= '.php';
@@ -22,5 +55,3 @@
2255
}
2356
}
2457
}, true, true);
25-
26-
Mage::app();

src/Autoload/Magento/ModuleControllerAutoloader.php

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,7 @@ final class ModuleControllerAutoloader
1717
public function __construct(string $codePool, $magentoRoot = null)
1818
{
1919
if (empty($magentoRoot)) {
20-
$mageClass = new ReflectionClass(Mage::class);
21-
if ($mageClass->getFileName() !== false) {
22-
$magentoRoot = \dirname($mageClass->getFileName(), 2);
23-
} else {
24-
throw new \RuntimeException('Could not find path to Mage class');
25-
}
20+
$magentoRoot = \dirname(BP, 2);
2621
}
2722
$this->codePool = $codePool;
2823
$this->magentoRoot = $magentoRoot;

0 commit comments

Comments
 (0)