Passed
Push — master ( bce62f...f8ebd8 )
by Tom
03:09
created

RouteBuilder::getUrlGenerator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace TomHart\Routing;
4
5
use Illuminate\Database\Eloquent\Model;
6
use Illuminate\Routing\Router;
7
use Illuminate\Routing\UrlGenerator;
8
use Symfony\Component\Routing\Exception\RouteNotFoundException;
9
use TomHart\Utilities\ArrayUtil;
10
11
class RouteBuilder
12
{
13
14
    public function __construct()
15
    {
16
    }
17
18
    /**
19
     * Get the router instance.
20
     *
21
     * @return Router
22
     */
23
    private function getRouter(): Router
24
    {
25
        return app('router');
26
    }
27
28
    /**
29
     * Get the UrlGenerator.
30
     *
31
     * @return UrlGenerator
32
     */
33
    private function getUrlGenerator(): UrlGenerator
34
    {
35
        return app('url');
36
    }
37
38
    /**
39
     * This allows a route to be dynamically built just from a Model instance.
40
     * Imagine a route called "test":
41
     *      '/test/{name}/{id}'
42
     * Calling:
43
     *      routeFromModel('test', Site::find(8));
44
     * will successfully build the route, as "name" and "id" are both attributes on the Site model.
45
     *
46
     * Further more, once using routeFromModel, the route can be changed. Without changing the call:
47
     *      routeFromModel('test', Site::find(8));
48
     * You can change the route to be:
49
     *      '/test/{name}/{id}/{parent->relationship->value}/{slug}/{otherParent->value}'
50
     * And the route will successfully change, as all the extra parts can be extracted from the Model.
51
     * Relationships can be called and/or chained with "->" (Imagine Model is a Order):
52
     *      {customer->address->postcode}
53
     * Would get the postcode of the customer who owns the order.
54
     *
55
     * @param string $routeName The route you want to build
56
     * @param Model $model The model to pull the data from
57
     * @param mixed[] $data Data to build into the route when it doesn't exist on the model
58
     *
59
     * @return string The built URL.
60
     */
61
    public function routeFromModel(string $routeName, Model $model, array $data = [])
62
    {
63
        $router = $this->getRouter();
64
        $urlGen = $this->getUrlGenerator();
65
        $route = $router->getRoutes()->getByName($routeName);
66
67
        if (!$route) {
68
            throw new RouteNotFoundException("Route $routeName not found");
69
        }
70
71
        $params = $route->parameterNames();
72
73
        $data = ArrayUtil::populateArrayFromObject($params, $model, $data);
74
75
        return rtrim($urlGen->route($routeName, $data), '?');
76
    }
77
}
78