Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Sign in
Toggle navigation
D
drupal
Project overview
Project overview
Details
Activity
Releases
Cycle Analytics
Insights
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Locked Files
Drupal.org issue queue
Drupal.org issue queue
Security & Compliance
Security & Compliance
Dependency List
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
project
drupal
Commits
e559eaa9
Commit
e559eaa9
authored
Feb 25, 2016
by
catch
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue
#2671034
by alexpott, damiankloip: Create plugin per file YAML discovery
parent
f7c02dfe
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
477 additions
and
0 deletions
+477
-0
core/lib/Drupal/Component/Discovery/DiscoverableInterface.php
.../lib/Drupal/Component/Discovery/DiscoverableInterface.php
+3
-0
core/lib/Drupal/Component/Discovery/DiscoveryException.php
core/lib/Drupal/Component/Discovery/DiscoveryException.php
+14
-0
core/lib/Drupal/Component/Discovery/YamlDirectoryDiscovery.php
...lib/Drupal/Component/Discovery/YamlDirectoryDiscovery.php
+164
-0
core/lib/Drupal/Core/Plugin/Discovery/YamlDirectoryDiscovery.php
...b/Drupal/Core/Plugin/Discovery/YamlDirectoryDiscovery.php
+37
-0
core/tests/Drupal/Tests/Component/Discovery/YamlDirectoryDiscoveryTest.php
.../Tests/Component/Discovery/YamlDirectoryDiscoveryTest.php
+157
-0
core/tests/Drupal/Tests/Core/Plugin/Discovery/YamlDirectoryDiscoveryTest.php
...ests/Core/Plugin/Discovery/YamlDirectoryDiscoveryTest.php
+102
-0
No files found.
core/lib/Drupal/Component/Discovery/DiscoverableInterface.php
View file @
e559eaa9
...
...
@@ -17,6 +17,9 @@ interface DiscoverableInterface {
*
* @return array
* An array of discovered data keyed by provider.
*
* @throws \Drupal\Component\Discovery\DiscoveryException
* Exception thrown if there is a problem during discovery.
*/
public
function
findAll
();
...
...
core/lib/Drupal/Component/Discovery/DiscoveryException.php
0 → 100644
View file @
e559eaa9
<?php
/**
* @file
* Contains \Drupal\Component\Discovery\DiscoveryException.
*/
namespace
Drupal\Component\Discovery
;
/**
* Exception thrown during discovery if the data is invalid.
*/
class
DiscoveryException
extends
\RuntimeException
{
}
core/lib/Drupal/Component/Discovery/YamlDirectoryDiscovery.php
0 → 100644
View file @
e559eaa9
<?php
/**
* @file
* Contains \Drupal\Component\Discovery\YamlDirectoryDiscovery.
*/
namespace
Drupal\Component\Discovery
;
use
Drupal\Component\FileSystem\RegexDirectoryIterator
;
use
Drupal\Component\Serialization\Exception\InvalidDataTypeException
;
use
Drupal\Component\Serialization\Yaml
;
use
Drupal\Component\FileCache\FileCacheFactory
;
/**
* Discovers multiple YAML files in a set of directories.
*/
class
YamlDirectoryDiscovery
implements
DiscoverableInterface
{
/**
* Defines the key in the discovered data where the file path is stored.
*/
const
FILE_KEY
=
'_discovered_file_path'
;
/**
* An array of directories to scan, keyed by the provider.
*
* The value can either be a string or an array of strings. The string values
* should be the path of a directory to scan.
*
* @var array
*/
protected
$directories
=
[];
/**
* The suffix for the file cache key.
*
* @var string
*/
protected
$fileCacheKeySuffix
;
/**
* The key contained in the discovered data that identifies it.
*
* @var string
*/
protected
$idKey
;
/**
* Constructs a YamlDirectoryDiscovery object.
*
* @param array $directories
* An array of directories to scan, keyed by the provider. The value can
* either be a string or an array of strings. The string values should be
* the path of a directory to scan.
* @param string $file_cache_key_suffix
* The file cache key suffix. This should be unique for each type of
* discovery.
* @param string $key
* (optional) The key contained in the discovered data that identifies it.
* Defaults to 'id'.
*/
public
function
__construct
(
array
$directories
,
$file_cache_key_suffix
,
$key
=
'id'
)
{
$this
->
directories
=
$directories
;
$this
->
fileCacheKeySuffix
=
$file_cache_key_suffix
;
$this
->
idKey
=
$key
;
}
/**
* {@inheritdoc}
*/
public
function
findAll
()
{
$all
=
array
();
$files
=
$this
->
findFiles
();
$file_cache
=
FileCacheFactory
::
get
(
'yaml_discovery:'
.
$this
->
fileCacheKeySuffix
);
// Try to load from the file cache first.
foreach
(
$file_cache
->
getMultiple
(
array_keys
(
$files
))
as
$file
=>
$data
)
{
$all
[
$files
[
$file
]][
$this
->
getIdentifier
(
$file
,
$data
)]
=
$data
;
unset
(
$files
[
$file
]);
}
// If there are files left that were not returned from the cache, load and
// parse them now. This list was flipped above and is keyed by filename.
if
(
$files
)
{
foreach
(
$files
as
$file
=>
$provider
)
{
// If a file is empty or its contents are commented out, return an empty
// array instead of NULL for type consistency.
try
{
$data
=
Yaml
::
decode
(
file_get_contents
(
$file
))
?:
[];
}
catch
(
InvalidDataTypeException
$e
)
{
throw
new
DiscoveryException
(
"The
$file
contains invalid YAML"
,
0
,
$e
);
}
$data
[
static
::
FILE_KEY
]
=
$file
;
$all
[
$provider
][
$this
->
getIdentifier
(
$file
,
$data
)]
=
$data
;
$file_cache
->
set
(
$file
,
$data
);
}
}
return
$all
;
}
/**
* Gets the identifier from the data.
*
* @param string $file
* The filename.
* @param array $data
* The data from the YAML file.
*
* @return string
* The identifier from the data.
*/
protected
function
getIdentifier
(
$file
,
array
$data
)
{
if
(
!
isset
(
$data
[
$this
->
idKey
]))
{
throw
new
DiscoveryException
(
"The
$file
contains no data in the identifier key '
{
$this
->
idKey
}
'"
);
}
return
$data
[
$this
->
idKey
];
}
/**
* Returns an array of providers keyed by file path.
*
* @return array
* An array of providers keyed by file path.
*/
protected
function
findFiles
()
{
$file_list
=
[];
foreach
(
$this
->
directories
as
$provider
=>
$directories
)
{
$directories
=
(
array
)
$directories
;
foreach
(
$directories
as
$directory
)
{
if
(
is_dir
(
$directory
))
{
/** @var \SplFileInfo $fileInfo */
foreach
(
$this
->
getDirectoryIterator
(
$directory
)
as
$fileInfo
)
{
$file_list
[
$fileInfo
->
getPathname
()]
=
$provider
;
}
}
}
}
return
$file_list
;
}
/**
* Gets an iterator to loop over the files in the provided directory.
*
* This method exists so that it is easy to replace this functionality in a
* class that extends this one. For example, it could be used to make the scan
* recursive.
*
* @param string $directory
* The directory to scan.
*
* @return \Traversable
* An \Traversable object or array where the values are \SplFileInfo
* objects.
*/
protected
function
getDirectoryIterator
(
$directory
)
{
return
new
RegexDirectoryIterator
(
$directory
,
'/\.yml$/i'
);
}
}
core/lib/Drupal/Core/Plugin/Discovery/YamlDirectoryDiscovery.php
0 → 100644
View file @
e559eaa9
<?php
/**
* @file
* Contains \Drupal\Core\Plugin\Discovery\YamlDiscovery.
*/
namespace
Drupal\Core\Plugin\Discovery
;
use
Drupal\Component\Discovery\YamlDirectoryDiscovery
as
ComponentYamlDirectoryDiscovery
;
/**
* Allows multiple YAML files per directory to define plugin definitions.
*/
class
YamlDirectoryDiscovery
extends
YamlDiscovery
{
/**
* Constructs a YamlDirectoryDiscovery object.
*
* @param array $directories
* An array of directories to scan, keyed by the provider. The value can
* either be a string or an array of strings. The string values should be
* the path of a directory to scan.
* @param string $file_cache_key_suffix
* The file cache key suffix. This should be unique for each type of
* discovery.
* @param string $key
* (optional) The key contained in the discovered data that identifies it.
* Defaults to 'id'.
*/
public
function
__construct
(
array
$directories
,
$file_cache_key_suffix
,
$key
=
'id'
)
{
// Intentionally does not call parent constructor as this class uses a
// different YAML discovery.
$this
->
discovery
=
new
ComponentYamlDirectoryDiscovery
(
$directories
,
$file_cache_key_suffix
,
$key
);
}
}
core/tests/Drupal/Tests/Component/Discovery/YamlDirectoryDiscoveryTest.php
0 → 100644
View file @
e559eaa9
<?php
/**
* @file
* Contains \Drupal\Tests\Component\Discovery\YamlDiscoveryTest.
*/
namespace
Drupal\Tests\Component\Discovery
;
use
Drupal\Component\Discovery\DiscoveryException
;
use
Drupal\Component\Discovery\YamlDirectoryDiscovery
;
use
Drupal\Tests\UnitTestCase
;
use
org\bovigo\vfs\vfsStream
;
/**
* YamlDirectoryDiscoveryTest component unit tests.
*
* @coversDefaultClass \Drupal\Component\Discovery\YamlDirectoryDiscovery
*
* @group Discovery
*/
class
YamlDirectoryDiscoveryTest
extends
UnitTestCase
{
/**
* Tests YAML directory discovery.
*
* @covers ::findAll
*/
public
function
testDiscovery
()
{
vfsStream
::
setup
(
'modules'
,
NULL
,
[
'test_1'
=>
[
'subdir1'
=>
[
'item_1.test.yml'
=>
"id: item1
\n
name: 'test1 item 1'"
,
],
'subdir2'
=>
[
'item_2.test.yml'
=>
"id: item2
\n
name: 'test1 item 2'"
,
],
],
'test_2'
=>
[
'subdir1'
=>
[
'item_3.test.yml'
=>
"id: item3
\n
name: 'test2 item 3'"
,
],
'subdir2'
=>
[],
],
'test_3'
=>
[],
'test_4'
=>
[
'subdir1'
=>
[
'item_4.test.yml'
=>
"id: item4
\n
name: 'test4 item 4'"
,
'item_5.test.yml'
=>
"id: item5
\n
name: 'test4 item 5'"
,
'item_6.test.yml'
=>
"id: item6
\n
name: 'test4 item 6'"
,
],
],
]);
// Set up the directories to search.
$directories
=
[
// Multiple directories both with valid items.
'test_1'
=>
[
vfsStream
::
url
(
'modules/test_1/subdir1'
),
vfsStream
::
url
(
'modules/test_1/subdir2'
),
],
// The subdir2 directory is empty.
'test_2'
=>
[
vfsStream
::
url
(
'modules/test_2/subdir1'
),
vfsStream
::
url
(
'modules/test_2/subdir2'
),
],
// Directories that do not exist.
'test_3'
=>
[
vfsStream
::
url
(
'modules/test_3/subdir1'
),
vfsStream
::
url
(
'modules/test_3/subdir2'
),
],
// A single directory.
'test_4'
=>
vfsStream
::
url
(
'modules/test_4/subdir1'
),
];
$discovery
=
new
YamlDirectoryDiscovery
(
$directories
,
'test'
);
$data
=
$discovery
->
findAll
();
$this
->
assertSame
([
'id'
=>
'item1'
,
'name'
=>
'test1 item 1'
,
YamlDirectoryDiscovery
::
FILE_KEY
=>
'vfs://modules/test_1/subdir1/item_1.test.yml'
],
$data
[
'test_1'
][
'item1'
]);
$this
->
assertSame
([
'id'
=>
'item2'
,
'name'
=>
'test1 item 2'
,
YamlDirectoryDiscovery
::
FILE_KEY
=>
'vfs://modules/test_1/subdir2/item_2.test.yml'
],
$data
[
'test_1'
][
'item2'
]);
$this
->
assertCount
(
2
,
$data
[
'test_1'
]);
$this
->
assertSame
([
'id'
=>
'item3'
,
'name'
=>
'test2 item 3'
,
YamlDirectoryDiscovery
::
FILE_KEY
=>
'vfs://modules/test_2/subdir1/item_3.test.yml'
],
$data
[
'test_2'
][
'item3'
]);
$this
->
assertCount
(
1
,
$data
[
'test_2'
]);
$this
->
assertTrue
(
empty
(
$data
[
'test_3'
]),
'test_3 provides 0 items'
);
$this
->
assertSame
([
'id'
=>
'item4'
,
'name'
=>
'test4 item 4'
,
YamlDirectoryDiscovery
::
FILE_KEY
=>
'vfs://modules/test_4/subdir1/item_4.test.yml'
],
$data
[
'test_4'
][
'item4'
]);
$this
->
assertSame
([
'id'
=>
'item5'
,
'name'
=>
'test4 item 5'
,
YamlDirectoryDiscovery
::
FILE_KEY
=>
'vfs://modules/test_4/subdir1/item_5.test.yml'
],
$data
[
'test_4'
][
'item5'
]);
$this
->
assertSame
([
'id'
=>
'item6'
,
'name'
=>
'test4 item 6'
,
YamlDirectoryDiscovery
::
FILE_KEY
=>
'vfs://modules/test_4/subdir1/item_6.test.yml'
],
$data
[
'test_4'
][
'item6'
]);
$this
->
assertCount
(
3
,
$data
[
'test_4'
]);
}
/**
* Tests YAML directory discovery with an alternate ID key.
*
* @covers ::findAll
*/
public
function
testDiscoveryAlternateId
()
{
vfsStream
::
setup
(
'modules'
,
NULL
,
[
'test_1'
=>
[
'item_1.test.yml'
=>
"alt_id: item1
\n
id: ignored"
,
],
]);
// Set up the directories to search.
$directories
=
[
'test_1'
=>
vfsStream
::
url
(
'modules/test_1'
)];
$discovery
=
new
YamlDirectoryDiscovery
(
$directories
,
'test'
,
'alt_id'
);
$data
=
$discovery
->
findAll
();
$this
->
assertSame
([
'alt_id'
=>
'item1'
,
'id'
=>
'ignored'
,
YamlDirectoryDiscovery
::
FILE_KEY
=>
'vfs://modules/test_1/item_1.test.yml'
],
$data
[
'test_1'
][
'item1'
]);
$this
->
assertCount
(
1
,
$data
[
'test_1'
]);
}
/**
* Tests YAML directory discovery with a missing ID key.
*
* @covers ::findAll
* @covers ::getIdentifier
*/
public
function
testDiscoveryNoIdException
()
{
$this
->
setExpectedException
(
DiscoveryException
::
class
,
'The vfs://modules/test_1/item_1.test.yml contains no data in the identifier key \'id\''
);
vfsStream
::
setup
(
'modules'
,
NULL
,
[
'test_1'
=>
[
'item_1.test.yml'
=>
""
,
],
]);
// Set up the directories to search.
$directories
=
[
'test_1'
=>
vfsStream
::
url
(
'modules/test_1'
)];
$discovery
=
new
YamlDirectoryDiscovery
(
$directories
,
'test'
);
$discovery
->
findAll
();
}
/**
* Tests YAML directory discovery with invalid YAML.
*
* @covers ::findAll
*/
public
function
testDiscoveryInvalidYamlException
()
{
$this
->
setExpectedException
(
DiscoveryException
::
class
,
'The vfs://modules/test_1/item_1.test.yml contains invalid YAML'
);
vfsStream
::
setup
(
'modules'
,
NULL
,
[
'test_1'
=>
[
'item_1.test.yml'
=>
"id: invalid
\n
foo : [bar}"
,
],
]);
// Set up the directories to search.
$directories
=
[
'test_1'
=>
vfsStream
::
url
(
'modules/test_1'
)];
$discovery
=
new
YamlDirectoryDiscovery
(
$directories
,
'test'
);
$discovery
->
findAll
();
}
}
core/tests/Drupal/Tests/Core/Plugin/Discovery/YamlDirectoryDiscoveryTest.php
0 → 100644
View file @
e559eaa9
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Plugin\Discovery\YamlDiscoveryTest.
*/
namespace
Drupal\Tests\Core\Plugin\Discovery
;
use
Drupal\Component\Discovery\YamlDirectoryDiscovery
as
ComponentYamlDirectoryDiscovery
;
use
Drupal\Core\StringTranslation\TranslatableMarkup
;
use
Drupal\Tests\UnitTestCase
;
use
Drupal\Core\Plugin\Discovery\YamlDirectoryDiscovery
;
use
org\bovigo\vfs\vfsStream
;
/**
* @coversDefaultClass \Drupal\Core\Plugin\Discovery\YamlDirectoryDiscovery
*
* @group Plugin
*/
class
YamlDirectoryDiscoveryTest
extends
UnitTestCase
{
/**
* @covers ::getDefinitions
*/
public
function
testGetDefinitions
()
{
vfsStream
::
setup
(
'modules'
,
NULL
,
[
'module_a'
=>
[
'subdir1'
=>
[
'plugin1.yml'
=>
"id: plugin1
\n
test_provider: module_a"
,
'plugin2.yml'
=>
"id: plugin2
\n
test_provider: module_a"
,
],
'subdir2'
=>
[
'plugin3.yml'
=>
"id: plugin3
\n
test_provider: module_a"
,
],
'subdir3'
=>
[
]
],
'module_b'
=>
[
'subdir1'
=>
[
'plugin4.yml'
=>
"id: plugin4
\n
test_provider: module_b"
,
],
],
]);
$directories
=
[
'module_a'
=>
[
vfsStream
::
url
(
'modules/module_a/subdir1'
),
vfsStream
::
url
(
'modules/module_a/subdir2'
),
// Empty directory.
vfsStream
::
url
(
'modules/module_a/subdir3'
),
// Directory does not exist.
vfsStream
::
url
(
'modules/module_a/subdir4'
),
],
'module_b'
=>
vfsStream
::
url
(
'modules/module_b/subdir1'
),
];
$discovery
=
new
YamlDirectoryDiscovery
(
$directories
,
'test'
);
$definitions
=
$discovery
->
getDefinitions
();
$this
->
assertInternalType
(
'array'
,
$definitions
);
$this
->
assertCount
(
4
,
$definitions
);
foreach
(
$definitions
as
$id
=>
$definition
)
{
foreach
(
array
(
'id'
,
'provider'
,
ComponentYamlDirectoryDiscovery
::
FILE_KEY
)
as
$key
)
{
$this
->
assertArrayHasKey
(
$key
,
$definition
);
}
$this
->
assertEquals
(
$id
,
$definition
[
'id'
]);
$this
->
assertEquals
(
$definition
[
'test_provider'
],
$definition
[
'provider'
]);
}
}
/**
* @covers ::getDefinitions
*/
public
function
testGetDefinitionsWithTranslatableDefinitions
()
{
vfsStream
::
setup
(
'modules'
,
NULL
,
[
'module_a'
=>
[
'subdir1'
=>
[
'plugin1.yml'
=>
"id: plugin1
\n
test_provider: module_a
\n
title: 'test title'"
,
'plugin2.yml'
=>
"id: plugin2
\n
test_provider: module_a
\n
title: 'test title'
\n
title_context: test-context"
,
],
],
]);
$directories
=
[
'module_a'
=>
vfsStream
::
url
(
'modules/module_a/subdir1'
),
];
$discovery
=
new
YamlDirectoryDiscovery
(
$directories
,
'test'
);
$discovery
->
addTranslatableProperty
(
'title'
,
'title_context'
);
$definitions
=
$discovery
->
getDefinitions
();
$this
->
assertCount
(
2
,
$definitions
);
$plugin_1
=
$definitions
[
'plugin1'
];
$plugin_2
=
$definitions
[
'plugin2'
];
$this
->
assertInstanceOf
(
TranslatableMarkup
::
class
,
$plugin_1
[
'title'
]);
$this
->
assertEquals
([],
$plugin_1
[
'title'
]
->
getOptions
());
$this
->
assertInstanceOf
(
TranslatableMarkup
::
class
,
$plugin_2
[
'title'
]);
$this
->
assertEquals
([
'context'
=>
'test-context'
],
$plugin_2
[
'title'
]
->
getOptions
());
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment