Skip to content

Instantly share code, notes, and snippets.

@alganet
Created February 11, 2013 18:33
Show Gist options
  • Save alganet/4756490 to your computer and use it in GitHub Desktop.
Save alganet/4756490 to your computer and use it in GitHub Desktop.
One crazy generated class and it's main generator. This was reflected from a database schema and by accident wasn't in our blacklist. This table comes from an external ERP and we never used this code, it was a mutant offspring of our code generation automation. Indeed, it was a fantastic achievement and I've learned a lot of things about automat…
<?php
require_once 'Cube/Loader.php';
Cube_Loader::singleton('.');
class Gerador
{
protected $declaredClasses;
protected $nomeMapa;
protected $caminho;
public function __construct($nomeMapa, $caminho)
{
$this->nomeMapa = $nomeMapa;
$this->caminho = realpath($caminho);
$this->atualizarClassesDeclaradas();
foreach(self::obterIteratorDeArquivosRecursivo($caminho) as $nome => $arquivo) {
if (!self::identificarDiretorioOculto($nome)) {
include_once $arquivo;
foreach ($this->obterClassesNovas() as $novaClasse) {
$reflexaoDaClasse = $this->obterReflexao($novaClasse);
if ($this->classePertenceAoCaminho($reflexaoDaClasse)) {
$this->gerarMapa($reflexaoDaClasse);
}
}
}
}
}
public function classePertenceAoCaminho(ReflectionClass $reflexaoDaClasse)
{
return strpos($reflexaoDaClasse->getFileName(), $this->caminho) === 0;
}
public function obterReflexao($nomeDaClasse)
{
return new ReflectionClass($nomeDaClasse);
}
public function gerarMapa($reflexaoDaClasse)
{
$mapa = $this->gerarExtensaoDeMapa($reflexaoDaClasse);
$this->gravarArquivo($mapa);
}
public function gravarArquivo($mapa)
{
$arquivo = new Zend_CodeGenerator_Php_File();
$arquivo->setClass($mapa);
$arquivo->setFilename($this->obterNomeDeArquivo($mapa->getName()));
$this->prepararDiretorios($arquivo->getFilename());
if (/*/true ||/**/!file_exists($arquivo->getFilename())) {
$arquivo->write();
}
}
public function obterNomeDeExtensao($nomeDaClasse)
{
return $this->nomeMapa.'_'.$nomeDaClasse;
}
public function gerarExtensaoDeMapa(ReflectionClass $reflexaoDaClasse)
{
$extensao = new Zend_CodeGenerator_Php_Class;
$extensao->setName($this->obterNomeDeExtensao($reflexaoDaClasse->getName()));
$extensao->setExtendedClass($reflexaoDaClasse->getName());
$extensao->setImplementedInterfaces(array('Cube_Mapeador'));
$x = new Zend_CodeGenerator_Php_Method();
$x = $x->getDocblock();
$extensao->setMethods(array(
array(
'name' => 'importar',
'visibility' => 'public',
'parameters' => array(
array(
'name' => 'data',
'type' => 'array'
)
)
),
array(
'name' => 'exportar',
'visibility' => 'public'
),
array(
'name' => 'extrair',
'visibility' => 'public'
),
array(
'name' => 'completar',
'visibility' => 'public',
'body' => '$this->importar($this->extrair()->toArray());'
),
array(
'name' => 'salvar',
'visibility' => 'public'
)
));
return $extensao;
}
public function prepararDiretorios($nomeDeArquivo)
{
if (!file_exists(dirname($nomeDeArquivo))) {
mkdir(dirname($nomeDeArquivo),0777,true);
}
}
public function obterNomeDeArquivo($nomeDeClasse)
{
return str_replace('_','/',$nomeDeClasse).'.php';
}
public function obterClassesNovas()
{
$novasClasses = array_diff(get_declared_classes(),$this->declaredClasses);
$this->atualizarClassesDeclaradas();
return $novasClasses;
}
public function atualizarClassesDeclaradas()
{
$this->declaredClasses = get_declared_classes();
}
public static function identificarDiretorioOculto($caminho)
{
return strpos($caminho,'/.') !== false;
}
public static function obterIteratorDeArquivosRecursivo($caminho)
{
return new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($caminho)
);
}
}
new Gerador('Acme','./GR/');
new Gerador('Acme','./Localidade/');
<?php
/**
* Arquivo da classe Acme_Dbo_Erp_Relacionamento
*
* PHP version 5
*
* @category CakeLab2
* @package Database
* @author Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
* @copyright 2008-2009 Acme Projetos e Serviços
* @license http://sistemas.Acme.com.br/l.txt AcmeL
* @version SVN: $Id: Importador.php 322 2009-07-31 01:04:24Z webdesenv $
* @link http://example.com
*/
/**
* Classe para instâncias da tabela Acme_Dbo_Erp_Relacionamento
*
* @category CakeLab2
* @package Database
* @author Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
* @copyright 2008-2009 Acme Projetos e Serviços
* @license http://sistemas.Acme.com.br/l.txt AcmeL
* @version Release: @package_version@
* @link http://example.com
*/
class Acme_Dbo_Erp_Relacionamento extends Cube_Db_Table
{
protected $_rowClass = 'Acme_Dbo_Erp_RelacionamentoRow';
protected $_schema = 'dbCakeLab2.dbo';
protected $_name = 'ERP_Relacionamento';
protected $_primary = array (
0 => 'Rel_codigo',
1 => 'Tab_Codigo',
);
protected $_sequence = false;
protected $_dependentTables = array (
);
protected $_referenceMap = array (
'ERPTabela' =>
array (
'columns' =>
array (
0 => 'Tab_Codigo',
),
'refTableClass' => 'Acme_Dbo_Erp_Tabela',
'refColumns' =>
array (
0 => 'Tab_Codigo',
),
),
);
/**
* @var Acme_Dbo_Erp_Relacionamento
*/
public static $instance;
/**
* @return Acme_Dbo_Erp_Relacionamento
*/
public static function getInstance()
{
if (!isset(self::$instance)) {
self::$instance = new self;
}
return self::$instance;
}
}
<?php
abstract class Cube_Db_Table extends Zend_Db_Table_Abstract
{
public function __call($method, array $args)
{
/**
* Find Rows By Column Values
* fetchRowBy<Column>(value)
* Use the non-greedy pattern repeat modifier e.g. \w+?
*/
if (preg_match('/^fetchRowBy(\w+?)?$/', $method, $matches)) {
$column = $matches[1];
return $this->fetchRow(
$this->select()->where($column.' = ?',$args[0])
);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment