Skip to content

Commit

Permalink
Merge branch 'plugins-manager'
Browse files Browse the repository at this point in the history
  • Loading branch information
yosymfony committed Jun 26, 2014
2 parents 515a15f + e17c8f2 commit 3d89aa2
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 54 deletions.
22 changes: 14 additions & 8 deletions src/Yosymfony/Spress/Application.php
Expand Up @@ -37,15 +37,15 @@ public function __construct(array $values = array())
$templatesPath = $this->getTemplatesPath($spressPath);

// Paths and filenames standard
$this['spress.paths'] = array(
$this['spress.paths'] = [
'root' => $spressPath,
'config' => $spressPath . '/app/config',
'config.file' => 'config.yml',
'config.file_env' => 'config_:env.yml',
'templates' => $templatesPath,
'web' => $spressPath . '/web',
'web.index' => $spressPath . '/web/index.php',
);
];
$this['spress.version'] = self::VERSION;

if(false == isset($this['spress.io']))
Expand Down Expand Up @@ -78,19 +78,25 @@ public function __construct(array $values = array())
]);
});

$this['spress.cms.plugin'] = $this->share(function($app){
return new PluginManager(
$app['spress.content_locator'],
$app['spress.cms.plugin.classLoader']);
});

$this['spress.cms.plugin.classLoader'] = function()
{
$autoloaders = spl_autoload_functions();

return $autoloaders[0][0];
};

$this['spress.cms.plugin.options'] = [
'vendors_dir' => 'vendors',
'composer_filename' => 'composer.json',
];

$this['spress.cms.plugin'] = $this->share(function($app){
return new PluginManager(
$app['spress.content_locator'],
$app['spress.cms.plugin.classLoader'],
$app['spress.cms.plugin.options']);
});

$this['spress.cms.renderizer'] = $this->share(function($app){
return new Renderizer(
$app['spress.twig_factory'],
Expand Down
Expand Up @@ -12,11 +12,11 @@
namespace Yosymfony\Spress\Plugin;

/**
* Configuration data of a plugin.
* Wrapper for Composer data of a plugin
*
* @author Victor Puertas <vpgugr@gmail.com>
*/
class PluginConfigData
class PluginComposerData
{
private $data;

Expand Down Expand Up @@ -48,7 +48,7 @@ public function getSpressName()
}

/**
* Get the Spress plugin entry point
* Get the Spress plugin entry-point
*
* @return string
*/
Expand All @@ -63,14 +63,4 @@ public function getSpressClass()

return $result;
}

/**
* Is a valid plugin?
*
* @return boolean
*/
public function isValidPlugin()
{
return isset($this->data['extra']['spress_class']);
}
}
5 changes: 5 additions & 0 deletions src/Yosymfony/Spress/Plugin/PluginItem.php
Expand Up @@ -63,4 +63,9 @@ public function getAuthor()
{
return $this->metas && isset($this->metas['author']) ? $this->metas['author'] : '';
}

public function __toString()
{
return $this->getName();
}
}
118 changes: 85 additions & 33 deletions src/Yosymfony/Spress/Plugin/PluginManager.php
Expand Up @@ -20,15 +20,13 @@
use Yosymfony\Spress\ContentLocator\ContentLocator;

/**
* Plugin manager
* Plugins manager
*
* @author Victor Puertas <vpgugr@gmail.com>
*/
class PluginManager
{
const VENDORS_DIR = "vendors";
const COMPOSER_FILENAME = "composer.json";

private $options = [];
private $contentLocator;
private $classLoader;
private $dispatcher;
Expand All @@ -40,10 +38,12 @@ class PluginManager
* Constructor
*
* @param ContentLocator $contentLocator
* @param $classLoader
* @param ClassLoader $classLoader
* @param array $options
*/
public function __construct(ContentLocator $contentLocator, ClassLoader $classLoader)
public function __construct(ContentLocator $contentLocator, ClassLoader $classLoader, array $options)
{
$this->options = $options;
$this->contentLocator = $contentLocator;
$this->classLoader = $classLoader;
$this->dispatcher = new EventDispatcher();
Expand All @@ -52,9 +52,13 @@ public function __construct(ContentLocator $contentLocator, ClassLoader $classLo

/**
* Start the life clycle
*
* @expectedException \RuntimeException If not there mandatory options
*/
public function initialize()
{
$this->checkOptions($this->options);

$this->eventsDispatched = [];

$this->updateClassLoader();
Expand All @@ -80,40 +84,23 @@ public function dispatchEvent($eventName, Event $event = null)
}

/**
* Get plugins available
* Get plugins availables
*
* @return array Array of PluginItem
*/
public function getPlugins()
{
$result = [];
$plugins = [];
$composerPlugins = [];
$dir = $this->contentLocator->getPluginDir();

if($dir)
{
$finder = new Finder();
$finder->files()
->in($dir)
->exclude(self::VENDORS_DIR)
->name(self::COMPOSER_FILENAME);

foreach($finder as $file)
{
$pluginConf = $this->getPluginConfigData($file);

if($pluginConf->isValidPlugin())
{
$className = $pluginConf->getSpressClass();

if($this->isValidClassName($className))
{
$result[] = new PluginItem(new $className);
}
}
}
$plugins = $this->getNotNamespacePlugins($dir);
$composerPlugins = $this->getComposerPlugins($dir);
}

return $result;
return array_merge($plugins, $composerPlugins);
}

/**
Expand All @@ -136,10 +123,62 @@ public function getDispatcherShortcut()
return $this->dispatcherShortcut;
}

private function getNotNamespacePlugins($dir)
{
$plugins = [];

$finder = new Finder();
$finder->files()
->in($dir)
->exclude($this->options['vendors_dir'])
->name('*.php');

foreach($finder as $file)
{
$className = $file->getBasename('.php');
include_once($file->getRealPath());

if($this->isValidClassName($className))
{
$plugins[$className] = new PluginItem(new $className);
}
}

return $plugins;
}

private function getComposerPlugins($dir)
{
$plugins = [];

$finder = new Finder();
$finder->files()
->in($dir)
->exclude($this->options['vendors_dir'])
->name($this->options['composer_filename']);

foreach($finder as $file)
{
$pluginConf = $this->getPluginComposerData($file);

$className = $pluginConf->getSpressClass();

if($className)
{
if($this->isValidClassName($className))
{
$plugins[$className] = new PluginItem(new $className);
}
}
}

return $plugins;
}

private function updateClassLoader()
{
$baseDir = $this->contentLocator->getPluginDir();
$vendorDir = $baseDir . '/' . self::VENDORS_DIR;
$vendorDir = $baseDir . '/' . $this->options['vendors_dir'];

if(false == file_exists($vendorDir))
{
Expand All @@ -152,7 +191,7 @@ private function updateClassLoader()
);

$embeddedComposer = $embeddedComposerBuilder
->setComposerFilename(self::COMPOSER_FILENAME)
->setComposerFilename($this->options['composer_filename'])
->setVendorDirectory($vendorDir)
->build();

Expand Down Expand Up @@ -201,11 +240,24 @@ private function isValidClassName($name)
return $result;
}

private function getPluginConfigData(SplFileInfo $item)
private function getPluginComposerData(SplFileInfo $item)
{
$json = $item->getContents();
$data = json_decode($json, true);

return new PluginConfigData($data);
return new PluginComposerData($data);
}

private function checkOptions(array $options)
{
if(false == isset($options['vendors_dir']))
{
throw new \RuntimeException('vendors_dir option is necessary for Plugin Manager');
}

if(false == isset($options['composer_filename']))
{
throw new \RuntimeException('composer_filename option is necessary for Plugin Manager');
}
}
}
66 changes: 66 additions & 0 deletions tests/fixtures/project/_plugins/TestPlugin.php
@@ -0,0 +1,66 @@
<?php

use Yosymfony\Spress\Plugin\Event;
use Yosymfony\Spress\Plugin\Plugin;
use Yosymfony\Spress\Plugin\EventSubscriber;

class TestPlugin extends Plugin
{
public function initialize(EventSubscriber $subscriber)
{
$subscriber->addEventListener('spress.start', 'onStart');
$subscriber->addEventListener('spress.before_convert', 'onBefore_convert');
$subscriber->addEventListener('spress.after_convert', 'onAfter_convert');
$subscriber->addEventListener('spress.after_convert_posts', 'onAfter_convert_posts');
$subscriber->addEventListener('spress.before_render', 'onBefore_render');
$subscriber->addEventListener('spress.after_render', 'onAfter_render');
$subscriber->addEventListener('spress.before_render_pagination', 'onBefore_render_pagination');
$subscriber->addEventListener('spress.after_render_pagination', 'onAfter_render_pagination');
$subscriber->addEventListener('spress.finish', 'onFinish');
}

public function onStart(Event\EnvironmentEvent $event)
{

}

public function onBefore_convert(Event\ConvertEvent $event)
{

}

public function onAfter_convert(Event\ConvertEvent $event)
{

}

public function onAfter_convert_posts(Event\AfterConvertPostsEvent $event)
{

}

public function onBefore_render(Event\RenderEvent $event)
{

}

public function onAfter_render(Event\RenderEvent $event)
{

}

public function onBefore_render_pagination(Event\RenderEvent $event)
{

}

public function onAfter_render_pagination(Event\RenderEvent $event)
{

}

public function onFinish(Event\FinishEvent $event)
{

}
}

1 comment on commit 3d89aa2

@yosymfony
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related with issue #11

Please sign in to comment.