imanghafoori1 / laravel-microscope

Fearless refactoring, it does a lot of smart checks to find certain errors.
MIT License
1.48k stars 96 forks source link

file_get_contents(): Read of 8192 bytes failed with errno=21 Is a directory #133

Closed Eixix closed 3 years ago

Eixix commented 3 years ago

Hi, first of all thanks for you awesome work!

It seems that all namespace-related commands throw this error, namely:

I guess this happens, as there are additional folders in my app folder. Simply put unexpected directories.

Cheers

imanghafoori1 commented 3 years ago

Please mention your exact version of: microscope PHP laravel OS

Thanks

Eixix commented 3 years ago

Sorry for not mentioning it in the first place:

Stack trace is:

file(): Read of 8192 bytes failed with errno=21 Is a directory

  at vendor/imanghafoori/laravel-microscope/src/Commands/CheckPsr4.php:63
     59▕     }
     60▕ 
     61▕     private function fixRefs($_path, $olds, $news)
     62▕     {
  ➜  63▕         $lines = file($_path);
     64▕         $changed = [];
     65▕         $olds = $this->deriveVariants($olds);
     66▕         $news = $this->deriveVariants($news);
     67▕         foreach ($lines as $i => $line) {

      +27 vendor frames
  28  artisan:37
      Illuminate\Foundation\Console\Kernel::handle()
imanghafoori1 commented 3 years ago

Do you have a file and folder with the same name side by side?

Eixix commented 3 years ago

So the problem still persists with the latest version 1.0.174

The code you provided to discover the faulty directory just logs the root folder of my laravel installation, which is weird...

Many thanks for you efforts!

imanghafoori1 commented 3 years ago

Nice clue. Thanks

imanghafoori1 commented 3 years ago

it would be a big help if you open CheckPsr4.php file and comment out these, one by one to see which one is causing the problem.

image

Eixix commented 3 years ago

Ah a fellow PHPStorm connaisseur. It is line 93!

imanghafoori1 commented 3 years ago

The latest patch version should solve the issue.

Eixix commented 3 years ago

Is it already released? Because the problem is still there with the dev-master version

imanghafoori1 commented 3 years ago

Yeah, it is released on the latest version. At least I think the problem is now from somewhere else. Please redo the debug steps I just told you, to see if the problem is still from the RoutePaths::get()

Eixix commented 3 years ago

Ok, even when commenting out every content, the error still persists with the current version (dev-master)

imanghafoori1 commented 3 years ago

It is strange, is the error exactly the same?

Eixix commented 3 years ago

It is the same error message but it does not happen for the check:psr4 but rather the check:imports

imanghafoori1 commented 3 years ago

So please comment out these, one by one.

image

Eixix commented 3 years ago

The corresponding line that provokes the error is 34 $this->checkFilePaths(RoutePaths::get())

imanghafoori1 commented 3 years ago

I am curious to see what this dd will produce in your app. I guess you have a Route::group([...], 'someWrongPath'); in your project.

image

Eixix commented 3 years ago

It will output this (shortened the absolute paths, it is just my project folder and all path prefixes are the same):

Checking imports...
array:4 [
  0 => "/routes/admin.php"
  1 => "/routes/auth.php"
  2 => "/routes/web.php"
  3 => "/routes/api.php"
]
array:4 [
  0 => "/routes/admin.php"
  1 => "/routes/auth.php"
  2 => "/routes/web.php"
  3 => "/routes/api.php"
]
imanghafoori1 commented 3 years ago

What about this?? image

Eixix commented 3 years ago

This appears to be the problem right?

array:5 [
  0 => "/project/routes/admin.php"
  1 => "/project/routes/auth.php"
  2 => "/project/routes/web.php"
  3 => "/project/routes/api.php"
  4 => "/project"
]
imanghafoori1 commented 3 years ago

I think if you change the code this way, it will work. Also I want to know how you have loaded an extra route file by calling loadRoutesFrom method in your service provider.

image

Eixix commented 3 years ago

Now i think I found another issue, but the initial one is gone 😨 and yes I use this method

Checking imports...
"==========================================================="
"was not able to properly parse the: /project/app/Extensions/Auth/Backend/Native/AuthenticatesIdpUsers.php file."
"Please open up an issue on the github repo"
"https://github.com/imanghafoori1/laravel-microscope/issues"
"and also send the content of the file to fix the issue."
"========================== Thanks =========================="

   ErrorException 

  foreach() argument must be of type array|object, null given

  at vendor/imanghafoori/laravel-microscope/src/CheckClassReferencesAreValid.php:176
    172▕ 
    173▕         $printer = app(ErrorPrinter::class);
    174▕ 
    175▕         loopStart:
  ➜ 176▕         foreach ($nonImportedClasses as $nonImportedClass) {
    177▕             $class = $nonImportedClass['class'];
    178▕             $line = $nonImportedClass['line'];
    179▕ 
    180▕             if (! self::isAbsent($class) || \function_exists($class)) {

      +18 vendor frames
  19  artisan:37
      Illuminate\Foundation\Console\Kernel::handle()

Sorry for causing so much trouble

imanghafoori1 commented 3 years ago

The problem is with my code, not your side. I want to know how you have called the loadRoutesFrom and what you have passed to it?

imanghafoori1 commented 3 years ago

also the contents of this file is needed: /project/app/Extensions/Auth/Backend/Native/AuthenticatesIdpUsers.php

Eixix commented 3 years ago

We have our own service provider, where we call this method like this:

$path = app_path('Extensions/Shibalike/routes/routes.php');
$this->loadRoutesFrom($path);

Here you have the contents of AuthenticatesIdpUsers.php:

<?php

namespace App\Extensions\Auth\Backend\Embedded;

use App\Extensions\Auth\Backend\Native\AuthenticatesIdpUsers as NativeAuthenticatesIdpUsers;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Http\Request;

trait AuthenticatesIdpUsers
{
    /*
    |--------------------------------------------------------------------------
    | Authenticates Idp Users Trait
    |--------------------------------------------------------------------------
    |
    | This trait extends the native Authenticates Idp Users Trait with an
    | embedded mode returning authentication tokens. In order to disable
    | embedded usage, just use the native trait instead of this one.
    |
    */

    use NativeAuthenticatesIdpUsers, Concerns\EmbedsAuthentication;

    /**
     * The user has been authenticated.
     *
     * @param Request $request
     * @param  mixed  $user
     * @return mixed
     */
    protected function authenticated(Request $request, $user)
    {
        return $this->succeeded();
    }

    /**
     * Get the guard to be used during authentication.
     *
     * @return Guard
     */
    protected function guard()
    {
        return $this->authenticator();
    }
}
imanghafoori1 commented 3 years ago

@Eixix I think this file is not the one causing the error. it seems you have another class with the same name in the Native folder (not Embedded folder).

The microscope has no problem with the one you just sent.

Eixix commented 3 years ago

Oh yeah sorry my bad. Here you can find the class:

<?php

namespace App\Extensions\Auth\Backend\Native;

use App\Extensions\Auth\Backend\Native\IdpHandlers\Contracts\Handler;
use Illuminate\Contracts\Auth\StatefulGuard;
use Illuminate\Foundation\Auth\RedirectsUsers;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Validator;
use Illuminate\SUpport\Str;

trait AuthenticatesIdpUsers
{
    use RedirectsUsers;

    /**
     * Send the user away to the Idp for authentication.
     *
     * @param  string  $idp
     * @param  string  $target
     * @return RedirectResponse
     */
    protected function login(string $idp, string $target)
    {
        return $this->handler()->login($idp, $target);
    }

    /**
     * Setup authentication based on returned data from the IdP.
     *
     * @param Request $request
     * @return RedirectResponse|\Illuminate\Http\Response|JsonResponse
     *
     * @throws HttpResponseException
     */
    public function idpAuth(Request $request)
    {
        $data = $this->validateRequest();
        $user = $this->updateOrCreate($data);

        return $this->loginAndRespond($request, $user);
    }

    /**
     * Validate authorization and data of an incoming request of the Idp.
     *
     * @return array
     *
     * @throws HttpResponseException
     */
    protected function validateRequest()
    {
        $data = $this->data();

        if (! $this->isAuthorized()) {
            $this->back(trans('auth.forbidden'));
        }
        if (! $this->isValid($data)) {
            $this->back(trans('auth.invalid'));
        }

        return $data;
    }

    /**
     * Send the response after the user was authenticated and logged in.
     *
     * @param Request $request
     * @param  mixed  $user
     * @return RedirectResponse|\Illuminate\Http\Response
     */
    protected function loginAndRespond(Request $request, $user)
    {
        $this->guard()->login($user);
        $request->session()->regenerate();

        if ($response = $this->authenticated($request, $user)) {
            return $response;
        }

        return $request->wantsJson()
            ? Response::noContent()
            : Redirect::intended($this->redirectPath());
    }

    /**
     * The user has been authenticated.
     *
     * @param Request $request
     * @param  mixed  $user
     * @return mixed
     */
    protected function authenticated(Request $request, $user)
    {
        //
    }

    /**
     * Get all required server variables.
     *
     * @return array
     */
    protected function data()
    {
        $handler = $this->handler();

        foreach ($this->rules() as $key => $rule) {
            $data[$key] = $handler->variable($key);
        }

        return $data ?? [];
    }

    /**
     * Check if the authenticated user has any of the given entitlements.
     *
     * @param  string|array $entitlements
     * @return bool
     */
    protected function isEntitled($entitlements)
    {
        $affiliations = $this->handler()->variable('affiliation');

        return Str::contains($affiliations, $entitlements);
    }

    /**
     * Determine if the data of an incoming authentication request is valid.
     *
     * @param  array  $data
     * @return bool
     */
    protected function isValid(array $data)
    {
        return Validator::make($data, $this->rules())->passes();
    }

    /**
     * Send the user back to the login page and show them a message.
     *
     * @param  string  $message
     * @return void
     *
     * @throws HttpResponseException
     */
    protected function back(string $message)
    {
        abort(Redirect::route('home')->with(['status' => 'info', 'message' => $message]));
    }

    /**
     * Get the guard to be used during authentication.
     *
     * @return StatefulGuard
     */
    protected function guard()
    {
        return Auth::guard();
    }

    /**
     * Get the idp handler to be used during authentication.
     *
     * @return Handler
     */
    protected function handler()
    {
        return config('auth.emulate_idp')
            ? new IdpHandlers\Shibalike
            : new IdpHandlers\Shibboleth;
    }
}
imanghafoori1 commented 3 years ago

try out the latest patch and it would be fine for you.

Eixix commented 3 years ago

Everything is working now, thanks a lot for your work and effort! :)