beyondcode / herd-community

86 stars 1 forks source link

[Feature Request]: Ability to change default public path for parked sites #232

Closed jannisborgers closed 1 year ago

jannisborgers commented 1 year ago

Feature Description

Hi! I’ve been using Valet for a couple of years and love working with it. I installed Herd today for the additional performance and for the GUI (I used PHP Monitor before). So far so nice! 👌

I don’t actually work a lot with Laravel, but use Valet mainly for CraftCMS development. Valet/Herd automatically assumes /public to be the web root for any project, while in Craft, it’s /web, or even a subfolder like /cms/web. In Valet, I usually cd into that folder and use valet link [site handle] for every new site manually.

When I want to park my local ~/Websites folder with Valet/Herd, I can’t find anything in the docs about changing the web root path. As the park command would be a time saver, I figured it would be cool to be able to change the default public path in Valet/Herd.

Is this feature valuable for other users as well and why?

This would expand the usage of Herd, Valet, and the park command to non-Laravel users.

mpociot commented 1 year ago

Hey Jannis,

this is exactly what custom drivers allow you to do in Valet/Herd. Valet and Herd both come with a CraftCMD driver out of the box, but depending on your project setup it might need some customization.

Adding custom drivers to Herd works just like Valet. Either place a LocalValetDriver.php file in the root of your project, or add a global custom driver to ~/Library/Application Support/Herd/config/valet/Drivers

You can read more about custom drivers here: https://laravel.com/docs/10.x/valet#custom-valet-drivers

Here's the code of the CraftCMS driver that Valet and Herd uses: https://github.com/laravel/valet/blob/master/cli/Valet/Drivers/Specific/CraftValetDriver.php

jannisborgers commented 1 year ago

@mpociot That was the quickest response I ever got on GitHub. Thank you very much!

jannisborgers commented 1 year ago

Sorry @mpociot but I can’t get this to work properly.

For most of my projects, the CraftValetDriver Herd ships with (located in /Applications/Herd.app/Contents/Resources/valet/cli/Valet/Drivers/Specific/CraftValetDriver.php) works fine.

For some projects, Craft’s entry script is in /cms/web/index.php instead of /web/index.php though. I think it’s easy enough to modify the existing driver to look either for a cms/web or /web directory by modifying the custom class like this:


//

public function serves(string $sitePath, string $siteName, string $uri): bool
    {
        return file_exists($sitePath.'/cms/craft') || file_exists($sitePath.'/craft');
    }

//

public function frontControllerDirectory($sitePath): string
    {
        $dirs = ['cms/web', 'web'];

//

This works, but only as LocalValetDriver.php inside the project root and when I remove the namespace Valet\Drivers\Specific. I get a warning that isActualFile() is an undefined method, though, indicating that something’s not right.

I would really like this to be a global custom driver for Craft, to avoid having to add the file locally. I tried adding the following file inside ~/Library/Application Support/Herd/config/valet/Drivers:

<?php

namespace Valet\Drivers\Specific;

use Valet\Drivers\ValetDriver;

class CustomValetDriver extends ValetDriver
{
    /**
     * Determine if the driver serves the request.
     */
    public function serves(string $sitePath, string $siteName, string $uri): bool
    {
        return file_exists($sitePath.'/cms/craft') || file_exists($sitePath.'/craft');
    }

    /**
     * Determine the name of the directory where the front controller lives.
     */
    public function frontControllerDirectory($sitePath): string
    {
        $dirs = ['cms/web', 'web'];

        foreach ($dirs as $dir) {
            if (is_dir($sitePath.'/'.$dir)) {
                return $dir;
            }
        }

        // Give up, and just return the default
        return 'web';
    }

    /**
     * Determine if the incoming request is for a static file.
     */
    public function isStaticFile(string $sitePath, string $siteName, string $uri)/*: string|false */
    {
        $frontControllerDirectory = $this->frontControllerDirectory($sitePath);

        if ($this->isActualFile($staticFilePath = $sitePath.'/'.$frontControllerDirectory.$uri)) {
            return $staticFilePath;
        }

        return false;
    }

    /**
     * Get the fully resolved path to the application's front controller.
     */
    public function frontControllerPath(string $sitePath, string $siteName, string $uri): ?string
    {
        $frontControllerDirectory = $this->frontControllerDirectory($sitePath);

        // Default index path
        $indexPath = $sitePath.'/'.$frontControllerDirectory.'/index.php';

        return $indexPath;
    }
}

When I add it as CraftValetDriver.php (also naming the class like that), I get the following error:

Fatal error: Cannot declare class Valet\Drivers\Specific\CraftValetDriver, because the name is already in use in /Users/ABC/Library/Application Support/Herd/config/valet/Drivers/CraftValetDriver.php on line 7

When I rename it to CustomValetDriver (or anything else, again, filename and class name), I get the following error:

 Fatal error: Uncaught Error: Class 'Valet\Drivers\Custom\CustomValetDriver' not found in /Applications/Herd.app/Contents/Resources/valet/cli/Valet/Drivers/ValetDriver.php:58 Stack trace: #0 /Applications/Herd.app/Contents/Resources/valet/server.php(54): Valet\Drivers\ValetDriver::assign('/Users/…', 'project', '/') #1 {main} thrown in /Applications/Herd.app/Contents/Resources/valet/cli/Valet/Drivers/ValetDriver.php on line 58