Skip to content

Commit de6635b

Browse files
authored
Merge pull request #8 from tattersoftware/vendor
Frontend Abstract Classes
2 parents 6ecabca + 6fe9920 commit de6635b

8 files changed

Lines changed: 200 additions & 21 deletions

File tree

composer.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,8 @@
2323
],
2424
"require": {
2525
"php": "^7.3 || ^8.0",
26-
"enyo/dropzone": "^5.7",
2726
"fortawesome/font-awesome": "^5.15",
2827
"league/commonmark": "^1.5",
29-
"tatter/adminlte": "^1.0 || ^2.0",
3028
"tatter/assets": "^3.0",
3129
"tatter/menus": "^1.0",
3230
"tatter/themes": "^2.0"

src/Bundles/FontAwesomeBundle.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
namespace Tatter\Frontend\Bundles;
44

5-
use Tatter\Assets\VendorBundle;
5+
use Tatter\Frontend\FrontendBundle;
66

7-
class FontAwesomeBundle extends VendorBundle
7+
class FontAwesomeBundle extends FrontendBundle
88
{
99
/**
1010
* Applies any initial inputs after the constructor.

src/FrontendBundle.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace Tatter\Frontend;
4+
5+
use Tatter\Assets\Asset;
6+
use Tatter\Assets\Bundle;
7+
8+
/**
9+
* Frontend Bundle Abstract Class
10+
*
11+
* A bundle of Assets specifically sourced from
12+
* third-party files published to the configured
13+
* "vendor" path (see Assets Config) and used in
14+
* conjunction with FrontendPublisher.
15+
*/
16+
abstract class FrontendBundle extends Bundle
17+
{
18+
/**
19+
* The base directory, i.e. Assets directory + vendor path
20+
*
21+
* @var string|null
22+
*/
23+
private static $base;
24+
25+
/**
26+
* Returns the base path according to the configurations.
27+
*/
28+
public static function base(): string
29+
{
30+
if (self::$base === null) {
31+
$config = Asset::config();
32+
self::$base = $config->directory . $config->vendor;
33+
}
34+
35+
return self::$base;
36+
}
37+
38+
/**
39+
* Adds an Asset by its vendor path, i.e. relative to base().
40+
*
41+
* @return $this
42+
*/
43+
final public function addPath(string $path)
44+
{
45+
$this->add(Asset::createFromPath(Asset::config()->vendor . trim($path, DIRECTORY_SEPARATOR)));
46+
47+
return $this;
48+
}
49+
}

src/FrontendPublisher.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace Tatter\Frontend;
4+
5+
use CodeIgniter\Publisher\Publisher;
6+
use DomainException;
7+
8+
/**
9+
* Frontend Publisher Abstract Class
10+
*
11+
* A Publisher wrapper for Assets sourced from
12+
* third-party files to be published to the configured
13+
* "vendor" path (see Assets Config) and used in
14+
* conjunction with FrontendBundle.
15+
*/
16+
abstract class FrontendPublisher extends Publisher
17+
{
18+
/**
19+
* Destination path relative to AssetsConfig::directory.
20+
* Must be set by child classes.
21+
*
22+
* @var string
23+
*/
24+
protected $path;
25+
26+
/**
27+
* Set the real destination.
28+
*/
29+
public function __construct(?string $source = null, ?string $destination = null)
30+
{
31+
if (! is_string($this->path)) {
32+
throw new DomainException('Invalid relative destination $path.');
33+
}
34+
35+
$this->destination = FrontendBundle::base() . ltrim($this->path, '\\/');
36+
37+
if (! is_dir($this->destination)) {
38+
mkdir($this->destination, 0775, true);
39+
}
40+
41+
parent::__construct($source, $destination);
42+
}
43+
}

src/Publishers/FontAwesomePublisher.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
namespace Tatter\Frontend\Publishers;
44

5-
use Tatter\Assets\VendorPublisher;
5+
use Tatter\Frontend\FrontendPublisher;
66

7-
class FontAwesomePublisher extends VendorPublisher
7+
class FontAwesomePublisher extends FrontendPublisher
88
{
99
/**
1010
* @var string

tests/FontAwesomeTest.php

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*/
1010
final class FontAwesomeTest extends TestCase
1111
{
12-
public function testFontAwesome()
12+
public function testPublisher()
1313
{
1414
// Partial list of expected files to be published
1515
$expected = [
@@ -19,19 +19,17 @@ public function testFontAwesome()
1919
'font-awesome/webfonts/fa-solid-900.woff2',
2020
];
2121

22-
$publisher = new FontAwesomePublisher();
23-
$publisher->publish();
24-
25-
$this->assertSame([], $publisher->getErrors());
26-
$this->assertNotSame([], $publisher->getPublished());
27-
28-
foreach ($expected as $path) {
29-
$file = $this->config->directory . $this->config->vendor . $path;
30-
$this->assertFileExists($file);
31-
}
22+
$this->assertPublishesFiles(FontAwesomePublisher::class, $expected);
23+
}
3224

33-
$bundle = new FontAwesomeBundle();
25+
public function testBundle()
26+
{
27+
// Partial lists of expected files to be bundled
28+
$head = [
29+
'all.min.css',
30+
];
31+
$body = [];
3432

35-
$this->assertStringContainsString('all.min.css', $bundle->head());
33+
$this->assertBundlesFiles(FontAwesomeBundle::class, $head, $body);
3634
}
3735
}

tests/FrontendPublisherTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
use Tatter\Frontend\FrontendPublisher;
4+
use Tests\Support\TestCase;
5+
6+
/**
7+
* @internal
8+
*/
9+
final class FrontendPublisherTest extends TestCase
10+
{
11+
public function testPublisherThrowsWithoutPath()
12+
{
13+
$this->expectException('DomainException');
14+
$this->expectExceptionMessage('Invalid relative destination $path');
15+
16+
$publisher = new class () extends FrontendPublisher {
17+
};
18+
}
19+
20+
public function testPublisherSetsDestination()
21+
{
22+
// Allow publishing to the test folder
23+
config('Publisher')->restrictions[SUPPORTPATH] = '*';
24+
25+
$publisher = new class () extends FrontendPublisher {
26+
protected $path = 'foobar';
27+
};
28+
29+
$this->assertSame($this->config->directory . 'vendor/foobar/', $publisher->getDestination());
30+
}
31+
}

tests/_support/TestCase.php

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22

33
namespace Tests\Support;
44

5+
use CodeIgniter\Publisher\Publisher;
56
use CodeIgniter\Test\CIUnitTestCase;
67
use org\bovigo\vfs\vfsStream;
78
use org\bovigo\vfs\vfsStreamDirectory;
89
use Tatter\Assets\Asset;
910
use Tatter\Assets\Config\Assets as AssetsConfig;
11+
use Tatter\Frontend\FrontendBundle;
12+
use Tatter\Frontend\FrontendPublisher;
1013

1114
abstract class TestCase extends CIUnitTestCase
1215
{
@@ -31,8 +34,8 @@ protected function setUp(): void
3134

3235
$this->root = vfsStream::setup('root');
3336

34-
// Create the config (if a trait has not already)
35-
$this->config = Asset::config();
37+
// Create the config
38+
$this->config = config('Assets');
3639
$this->config->directory = $this->root->url() . DIRECTORY_SEPARATOR;
3740
$this->config->useTimestamps = false; // These make testing much harder
3841

@@ -41,4 +44,61 @@ protected function setUp(): void
4144
// Add VFS as an allowed Publisher directory
4245
config('Publisher')->restrictions[$this->config->directory] = '*';
4346
}
47+
48+
/**
49+
* Preps the config and VFS.
50+
*/
51+
protected function tearDown(): void
52+
{
53+
parent::tearDown();
54+
55+
$this->root = null; // @phpstan-ignore-line
56+
$this->resetServices();
57+
}
58+
59+
/**
60+
* @param class-string<FrontendPublisher> $class
61+
* @param string[] $expected
62+
*/
63+
public function assertPublishesFiles(string $class, array $expected): void
64+
{
65+
$publisher = new $class();
66+
$result = $publisher->publish();
67+
68+
// Verify that publication succeeded
69+
$this->assertTrue($result);
70+
$this->assertSame([], $publisher->getErrors());
71+
$this->assertNotSame([], $publisher->getPublished());
72+
73+
// Check for each of the expected files
74+
foreach ($expected as $path) {
75+
$file = $this->config->directory . $this->config->vendor . $path;
76+
$this->assertFileExists($file);
77+
}
78+
}
79+
80+
/**
81+
* @param class-string<FrontendBundle> $class
82+
* @param string[] $expectedHeadFiles
83+
* @param string[] $expectedBodyFiles
84+
*/
85+
public function assertBundlesFiles(string $class, array $expectedHeadFiles, array $expectedBodyFiles): void
86+
{
87+
// Make sure everything is published
88+
foreach (Publisher::discover() as $publisher) {
89+
$publisher->publish();
90+
}
91+
92+
$bundle = new $class();
93+
$head = $bundle->head();
94+
$body = $bundle->body();
95+
96+
foreach ($expectedHeadFiles as $file) {
97+
$this->assertStringContainsString($file, $head);
98+
}
99+
100+
foreach ($expectedBodyFiles as $file) {
101+
$this->assertStringContainsString($file, $body);
102+
}
103+
}
44104
}

0 commit comments

Comments
 (0)