Passed
Push — main ( f48de4...0f5604 )
by Michael
03:18
created

FormatterServiceProvider::getFormatterName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace MichaelRubel\Formatters;
6
7
use Illuminate\Support\Str;
8
use MichaelRubel\Formatters\Exceptions\ShouldImplementInterfaceException;
9
use MichaelRubel\Formatters\Exceptions\ShouldNotUseCamelCaseException;
10
use Spatie\LaravelPackageTools\Package;
11
use Spatie\LaravelPackageTools\PackageServiceProvider;
12
use Symfony\Component\Finder\SplFileInfo;
13
14
class FormatterServiceProvider extends PackageServiceProvider
15
{
16
    /**
17
     * Internal constants.
18
     *
19
     * @const
20
     */
21
    public const PACKAGE_FOLDER  = 'Collection';
22
    public const PACKAGE_CLASS   = 'Formatter';
23
    public const BINDING_POSTFIX = '_formatter';
24
    public const CLASS_SEPARATOR = '\\';
25
26
    /**
27
     * Configure the package.
28
     *
29
     * @param Package $package
30
     *
31
     * @return void
32
     */
33 18
    public function configurePackage(Package $package): void
34
    {
35
        $package
36 18
            ->name('laravel-formatters')
37 18
            ->hasConfigFile();
38 18
    }
39
40
    /**
41
     * Register any package services.
42
     *
43
     * @return void
44
     */
45 18
    public function packageRegistered(): void
46
    {
47
        /** @var string */
48 18
        $app_folder = config('formatters.folder')
49 1
            ?? 'app' . DIRECTORY_SEPARATOR . 'Formatters';
50
51
        /** @var string */
52 18
        $bindings_case = config('formatters.bindings_case')
53 1
            ?? 'kebab';
54
55 18
        $filesystem = app('files');
56
57 18
        $appFormatters = $filesystem->isDirectory(base_path($app_folder))
58 1
            ? collect($filesystem->allFiles(base_path($app_folder)))
59 18
            : collect();
60
61 18
        $packageFormatters = collect(
62 18
            $filesystem->allFiles(
63 18
                $this->getPackageBaseDir()
64 18
                . DIRECTORY_SEPARATOR
65 18
                . self::PACKAGE_FOLDER
66
            )
67
        );
68
69
        $packageFormatters
70 18
            ->merge($appFormatters)
71 18
            ->each(function ($file) use ($app_folder, $bindings_case) {
72 18
                $filename = $file->getFilenameWithoutExtension();
73 18
                $name     = $this->getFormatterName($bindings_case, $filename);
74 18
                $class    = $this->getFormatterClass($file, $filename, $app_folder);
75
76 18
                $this->app->bind($name, $class);
77 18
            });
78 18
    }
79
80
    /**
81
     * Returns formatter name for string binding.
82
     *
83
     * @param string $bindings_case
84
     * @param string $filename
85
     *
86
     * @return string
87
     */
88 18
    public function getFormatterName(string $bindings_case, string $filename): string
89
    {
90 18
        $name = str_replace('Formatter', '', $filename);
91
92 18
        return Str::{$bindings_case}($name . self::BINDING_POSTFIX);
93
    }
94
95
    /**
96
     * Determines the formatter class namespace.
97
     *
98
     * @param SplFileInfo $file
99
     * @param string      $filename
100
     * @param string      $app_folder
101
     *
102
     * @return string
103
     */
104 18
    private function getFormatterClass(SplFileInfo $file, string $filename, string $app_folder): string
105
    {
106 18
        $path = str_contains($file->getPathName(), $app_folder)
107 1
            ? Str::ucfirst(str_replace(DIRECTORY_SEPARATOR, self::CLASS_SEPARATOR, $app_folder))
108 1
              . self::CLASS_SEPARATOR
109 18
            : (new \ReflectionClass(static::class))->getNamespaceName()
110 18
              . self::CLASS_SEPARATOR
111 18
              . self::PACKAGE_FOLDER
112 18
              . self::CLASS_SEPARATOR;
113
114 18
        return sprintf('%s%s', $path, $filename);
115
    }
116
117
    /**
118
     * Ensures all the formatters will implement the same interface.
119
     *
120
     * @param object $formatter
121
     */
122 16
    public static function ensureFormatterImplementsInterface(object $formatter): void
123
    {
124 16
        if (! $formatter instanceof Formatter) {
125 2
            if (config('formatters.bindings_case') === 'camel') {
126 1
                throw new ShouldNotUseCamelCaseException();
127
            }
128
129 1
            throw new ShouldImplementInterfaceException();
130
        }
131 14
    }
132
}
133