Created
November 21, 2010 14:13
-
-
Save fprochazka/708764 to your computer and use it in GitHub Desktop.
Presenters Generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$gen = new Kdyby\Generator\Presenters; | |
$gen->structure = json_decode(file_get_contents(APP_DIR . '/structure.json')); | |
$gen->deploy(APP_DIR); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Kdyby\Generator; | |
use Nette; | |
use Kdyby; | |
/** | |
* @author Filip Procházka <hosiplan@kdyby.org> | |
*/ | |
class Presenters extends\Nette\Object | |
{ | |
/** @var object */ | |
private $structure; | |
/** @var path to module */ | |
private $cursor; | |
/** @var string */ | |
private $appDir; | |
/** | |
* @param string $appDir | |
*/ | |
public function deploy($appDir) | |
{ | |
$this->appDir = $appDir; | |
foreach ($this->structure->modules as $module) { | |
$this->renderModule($module); | |
} | |
} | |
/** | |
* @param object $module | |
* @param array $parent | |
*/ | |
private function renderModule($module, array $parent = NULL) | |
{ | |
$parent = $parent ? $parent : array(); | |
$modulePath = array_merge($parent, (array)$module->name); | |
$dirs = $this->prepareModule($module, $modulePath); | |
if (isset($module->presenters)) { | |
foreach ($module->presenters as $presenter) { | |
$render = $this->renderPresenter($presenter, $modulePath); | |
$this->writePresenter($render, $presenter, $dirs); | |
} | |
} | |
if (isset($module->modules)) { | |
foreach ($module->modules as $submodule) { | |
$this->renderModule($submodule, $modulePath); | |
} | |
} | |
} | |
/** | |
* @param array $render | |
* @param object $presenter | |
* @param array $dirs | |
*/ | |
private function writePresenter($render, $presenter, $dirs) | |
{ | |
$file = $dirs['presenters'].'/'.$presenter->name.'Presenter.php'; | |
if (!file_exists($file)) { dump($file); | |
file_put_contents($file, implode("\n", $render)); | |
@chmod($file, 0775); | |
} // TODO: if file exists, use reflection and add content | |
foreach ($this->renderViews($presenter) as $view => $render) { | |
$file = $dirs['templates'].'/'.ucfirst($presenter->name).'.'.lcfirst($view).'.latte'; | |
if (!file_exists($file)) { dump($file); | |
file_put_contents($file, $render); | |
@chmod($file, 0775); | |
} | |
} | |
} | |
/** | |
* @param object $presenter | |
* @return array | |
*/ | |
private function renderViews($presenter) | |
{ | |
$views = array(); | |
if (isset($presenter->actions)) { | |
foreach ($presenter->actions as $action) { | |
$template = $this->getSettings($action, 'template'); | |
$views[$action->name] = $template['default']; | |
} | |
} | |
return $views; | |
} | |
/** | |
* @param object $module | |
* @param array $modulePath | |
* @return array | |
*/ | |
private function prepareModule($module, $modulePath) | |
{ | |
$this->cursor = $modulePath; | |
$dir = $this->appDir . '/' . implode('Module/', $modulePath)."Module"; | |
$dirs = array( | |
$dir, | |
'presenters' => $dir.'/presenters', | |
'templates' => $dir.'/templates' | |
); | |
foreach ($dirs as $d) { | |
@mkdir($d); | |
@chmod($d, 0775); | |
} | |
$presenterNames = array_map(function($presenter) { | |
return Nette\String::lower($presenter->name); | |
}, $module->presenters); | |
if (isset($module->presenters)) { | |
if (!in_array('base', $presenterNames)) { | |
$basePresenter = (object)array( | |
'name' => 'Base', | |
'abstract' => TRUE, | |
'parent' => (count($this->cursor)>1 ? "../Base" : "Nette\\Application\\Presenter") | |
); | |
$render = $this->renderPresenter($basePresenter, $modulePath); | |
$this->writePresenter($render, $basePresenter, $dirs); | |
} | |
foreach ($module->presenters as $presenter) { | |
if (!isset($presenter->parent)) { | |
$presenter->parent = 'Base'; | |
} | |
} | |
} | |
return array( | |
'presenters' => $dir.'/presenters', | |
'templates' => $dir.'/templates' | |
); | |
} | |
/** | |
* @param array $ns | |
* @return string | |
*/ | |
private function nameModule($ns) | |
{ | |
return ($ns ? implode("Module\\", $ns)."Module" : NULL); | |
} | |
/** | |
* @param object $presenter | |
* @param array $ns | |
* @return array | |
*/ | |
private function renderPresenter($presenter, $ns) | |
{ | |
$render['php'] = '<'."?php\n"; | |
$namespace = $this->nameModule($ns); | |
$render['namespace'] = ($namespace ? "namespace ".$namespace.";" : NULL); | |
if ($use = $this->getSettings($presenter, 'use')) { | |
$render['use'] = "\nuse ".implode(";\nuse ", $use).";"; | |
} | |
$render[] = "\n\n"; | |
if ($classDoc = $this->getSettings($presenter, 'annotations')) { | |
$render['classDoc'] = "/**\n"; | |
foreach ($classDoc as $name => $definition) { | |
$render['classDoc'] .= " * @".$name." ".$definition."\n"; | |
} | |
$render['classDoc'] .= " */"; | |
} | |
$abstract = (isset($presenter->abstract) && $presenter->abstract) ? "abstract " : NULL; | |
$parent = $this->searchPresenter($presenter->parent); | |
$render['start'] = $abstract."class ".$presenter->name."Presenter extends ".$parent. " \n{"; | |
if (isset($presenter->params)) { | |
$this->renderProperties($render, $presenter->params); | |
$render[] = "\n\n"; | |
} | |
if (isset($presenter->actions)) { | |
$this->renderActions($render, $presenter->actions); | |
} | |
$render['end'] = "}"; | |
return $render; | |
} | |
/** | |
* @param string $presenter | |
* @return string | |
*/ | |
private function searchPresenter($presenter) | |
{ | |
if (strpos($presenter, "\\") !== FALSE) { | |
return $presenter; | |
} | |
if (strpos($presenter, '/') === FALSE) { | |
return $presenter . 'Presenter'; | |
} | |
$ns = $this->cursor; | |
do { | |
array_pop($ns); | |
$presenter = substr($presenter, 3); | |
} while (substr($presenter, 0, 3) == '../'); | |
$relativePath = Nette\String::split($presenter, '~:~'); | |
$presenter = array_pop($relativePath); | |
$ns = array_merge((array)$ns, $relativePath); | |
$module = ($ns ? "\\". implode("Module\\", $ns).'Module' : NULL); | |
return $module . "\\" . $presenter . 'Presenter'; | |
} | |
/** | |
* @param object $object | |
* @param string $var | |
* @return array | |
*/ | |
private function getSettings($object, $var) | |
{ | |
$settings = array(); | |
if (isset($this->structure->global) && isset($this->structure->global->{$var})) { | |
$settings = array_merge($settings, (array)$this->structure->global->{$var}); | |
} | |
if (isset($object->{$var})) { | |
$settings = array_merge($settings, (array)$object->{$var}); | |
} | |
return $settings; | |
} | |
/** | |
* @param array &$render | |
* @param array $params | |
*/ | |
private function renderProperties(&$render, $params) | |
{ | |
foreach ($params as $param) { | |
$render['param'.$param->name] = ""; | |
if (isset($param->persistent) && $param->persistent) { | |
$render['param'.$param->name] .= " /** @persistent */\n"; | |
} | |
$default = isset($param->default) ? $this->renderVariable($param->default) : NULL; | |
$render['param'.$param->name] .= " public \$".$param->name.($default ? ' = '.$default : NULL).";\n"; | |
} | |
} | |
/** | |
* @param mixed $variable | |
* @return string | |
*/ | |
private function renderVariable($variable) | |
{ | |
$type = isset($variable->type) ? $variable->type : 'string'; | |
return $this->convertLitteral($variable, $type); | |
} | |
/** | |
* @param array &$render | |
* @param array $actions | |
*/ | |
private function renderActions(&$render, $actions) | |
{ | |
foreach ($actions as $action) { | |
$params = isset($action->params) ? $action->params : array(); | |
$render[] = "\n /******************** ".$action->name." ********************/\n\n"; | |
$render['action'.$action->name] = $this->createMethod('action' . ucfirst($action->name), $params); | |
$render[] = "\n\n"; | |
$render['render'.$action->name] = $this->createMethod('render' . ucfirst($action->name), $params)."\n"; | |
} | |
} | |
/** | |
* @param string $name | |
* @param array $params | |
* @return string | |
*/ | |
private function createMethod($name, $params = array()) | |
{ | |
$defaults = array(); | |
foreach ($params as $param) { | |
$default = NULL; | |
if (isset($param->default)) { | |
$type = isset($variable->type) ? $variable->type : NULL; | |
$default = $this->convertLitteral($variable, $type); | |
} | |
$defaults[] = '$'. $param->name . ($default ? ' = '.$default : NULL); | |
} | |
$method = array(' public function '. $name. '('. implode(', ', $defaults).')'); | |
$method[] = ' {'; | |
$method[] = ''; | |
$method[] = ' }'; | |
return implode("\n", $method); | |
} | |
/** | |
* @param object $structure | |
*/ | |
public function setStructure($structure) | |
{ | |
$this->structure = $structure; | |
} | |
/** | |
* @return object | |
*/ | |
public function getStructure() | |
{ | |
return $this->structure; | |
} | |
/** | |
* @param mixed $value | |
* @param string $type | |
* @return string | |
*/ | |
protected function convertLitteral($value, $type) | |
{ | |
if ($value === NULL) { | |
return 'NULL'; | |
} | |
switch ($type) { | |
case 'string': | |
return '"'.addslashes($value).'"'; | |
case 'int': | |
return (int) $value; | |
case 'float': | |
return (float) $value; | |
case 'bool': | |
return ((bool) $value) ? "TRUE" : "FALSE"; | |
case 'array': | |
return var_export((array)$value, TRUE); | |
default: | |
return $value; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"global":{ | |
"annotations":{ | |
"author":"Filip Procházka <hosiplan@gmail.com>" | |
}, | |
"use":[ | |
"Nette", | |
"Kdyby" | |
], | |
"template":{ | |
"default":"{block mainContent}\n<h2>hello kitty</h2>\n\n{/block}" | |
} | |
}, | |
"modules":[ | |
{ | |
"name":"Forum", | |
"presenters":[ | |
{ | |
"name":"Category", | |
"actions":[ | |
{ | |
"name":"default", | |
"params":[ | |
] | |
} | |
] | |
} | |
], | |
"modules":[ | |
{ | |
"name":"Topic", | |
"presenters":[ | |
{ | |
"name":"Search", | |
"params":[ | |
{ | |
"name":"q", | |
"persistent":"1" | |
} | |
], | |
"actions":[ | |
{ | |
"name":"default", | |
"params":[ | |
] | |
} | |
] | |
}, | |
{ | |
"name":"List", | |
"actions":[ | |
{ | |
"name":"default", | |
"params":[ | |
] | |
} | |
] | |
}, | |
{ | |
"name":"Create", | |
"actions":[ | |
{ | |
"name":"default", | |
"params":[ | |
] | |
} | |
] | |
} | |
] | |
}, | |
{ | |
"name":"Post", | |
"presenters":[ | |
{ | |
"name":"List", | |
"actions":[ | |
{ | |
"name":"default", | |
"params":[ | |
] | |
} | |
] | |
}, | |
{ | |
"name":"Create", | |
"actions":[ | |
{ | |
"name":"default", | |
"params":[ | |
] | |
} | |
] | |
}, | |
{ | |
"name":"Edit", | |
"parent":"Create", | |
"params":[ | |
{ | |
"name":"id", | |
"persistent":"1" | |
} | |
], | |
"actions":[ | |
{ | |
"name":"default", | |
"params":[ | |
] | |
} | |
] | |
} | |
] | |
} | |
] | |
}, | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment