コード例 #1
0
ファイル: core.YuppLoader.class.php プロジェクト: fkali/yupp
 /**
  * Carga todo el modelo de todas las aplicaciones.
  */
 public static function loadModel()
 {
     $cl = YuppLoader::getInstance();
     // Si estoy en una aplicacion que no es 'core', solo cargo el modelo de esa aplicacion.
     // Si estoy en la aplicacion 'core', carga el modelo de todas las aplicaciones.
     $ctx = YuppContext::getInstance();
     //$apps = array( $ctx->getApp() );
     $apps = array($ctx->getRealApp());
     if ($apps[0] == 'core') {
         $apps = FileSystem::getSubdirNames("./apps");
     }
     $packs = new PackageNames();
     // FIXME: que pasa si quiero cargar con refresh otras clases? p.e. MySQLDatabase se carga solo una vez porque el que la usa (DAL) es singleton.
     if (!$cl->modelLoaded) {
         // Carga: apps/theApp/model, para todos las aplicaciones
         foreach ($apps as $app) {
             $package = "{$app}.model";
             $path = YuppConventions::getModelPath($package);
             if (file_exists($path)) {
                 $cl->_loadModelRecursive($path);
             }
         }
         $cl->modelLoaded = true;
         // necesaria para mantener actualizada la session con la instance del singleton. (xq no referencia a la session xa este es un valor desserealizado...)
         YuppSession::set("_class_loader_singleton_instance", $cl);
         // actualizo la variable en la session...
     } else {
         self::refresh();
     }
 }
コード例 #2
0
 public static function getInstance()
 {
     // Deberia ser persistente asi concervo el locale entre requests...
     // pero puede haber problemas con los params, aunque los params se resetean en cada request.
     // FIXED: el locale es lo unico que se persiste entre requests.
     if (self::$instance === NULL) {
         self::$instance = new YuppContext();
     }
     return self::$instance;
 }
コード例 #3
0
 /**
  * @param appControllerFiltersInstance instancia de AppControllerFilters, puede ser NULL.
  */
 public function execute($appControllerFiltersInstance)
 {
     // TODO: se le podria pasar el context como parametro porque en el llamador ya lo tengo, ahorro tener que pedirlo aca.
     $ctx = YuppContext::getInstance();
     $app = $ctx->getApp();
     $controller = $ctx->getController();
     $action = $ctx->getAction();
     // Lo que se retorna de una accion de un controller o el command de un filtro cuando falla.
     $model_or_command = NULL;
     $command = NULL;
     // Comando que voy a retornar.
     // ===================================================
     // Before y After filters para acciones de controllers
     $beforeFilters = $appControllerFiltersInstance !== NULL ? $appControllerFiltersInstance->getBeforeFilters() : array();
     $afterFilters = $appControllerFiltersInstance !== NULL ? $appControllerFiltersInstance->getAfterFilters() : array();
     $filters = new YuppControllerFilter($beforeFilters, $afterFilters);
     // FIXME: no llamar sino hay beforeFilters
     // Ejecucion de los before filters, true si pasan o un ViewCommand si no.
     $bf_res = $filters->before_filter($app, $controller, $action, $this->params);
     // ===================================================
     // Sino pasa el beforeFilter
     // ===================================================
     if ($bf_res !== true) {
         Logger::getInstance()->log("Resultado del filter NO ES TRUE!!!");
         if (!$bf_res instanceof ViewCommand) {
             throw new Exception("After filter no retorna ViewCommand, retorna " . get_class($bf_res));
         }
         $command = $bf_res;
         return $command;
     }
     // ===================================================
     // Ejecuta accion del controllador
     YuppLoader::load('core.app', 'App');
     $app = App::getCurrent();
     $command = $app->execAction($controller, $action, $this->params);
     // FIXME: no llamar sino hay afterFilters
     // ===================================================
     // after filters
     // Ejecucion de los after filters, true si pasan o un ViewCommand si no.
     $af_res = $filters->after_filter($app, $controller, $action, $this->params, $command);
     if ($af_res !== true) {
         if (get_class($af_res) !== 'ViewCommand') {
             throw new Exception("After filter no retorna ViewCommand, retorna " . get_class($af_res));
         }
         $command = $af_res;
         // Retorna el ViewCommand del after filter.
     }
     // ===================================================
     return $command;
 }
コード例 #4
0
 public function __construct($params)
 {
     if (!is_array($params)) {
         throw new Exception("Error: 'params' debe ser un array. " . __FILE__ . " " . __LINE__);
     }
     if (isset($params['actionUrl'])) {
         $this->action_url = $params['actionUrl'];
     } else {
         // Si no vienen los params de la url, los tomo del contexto
         // http://code.google.com/p/yupp/issues/detail?id=28
         $ctx = YuppContext::getInstance();
         if (isset($params['app'])) {
             $this->app = $params['app'];
         } else {
             $this->app = $ctx->getApp();
         }
         if (isset($params['controller'])) {
             $this->controller = $params['controller'];
         } else {
             $this->controller = $ctx->getController();
         }
         if (isset($params['action'])) {
             $this->action = $params['action'];
         } else {
             $this->action = $ctx->getAction();
         }
     }
     if (isset($params['method'])) {
         $this->method = $params['method'];
     } else {
         $this->method = 'get';
     }
     if (isset($params['isAjax'])) {
         $this->isAjax = $params['isAjax'];
         $this->ajaxCallback = $params['ajaxCallback'];
         // obligatorio
         $this->ajaxBeforeSubmit = isset($params['ajaxBeforeSubmit']) ? $params['ajaxBeforeSubmit'] : NULL;
         // opcional
     }
     // Para ids autogenerados
     $c = self::$counter;
     self::$counter++;
     $this->id = "form_{$c}";
 }
コード例 #5
0
 private function __construct($po_loader)
 {
     $po_loader->setManager($this);
     // Inversion Of Control
     $this->po_loader = $po_loader;
     // Siempre viene una estrategia, getInstance se encarga de eso.
     $ctx = YuppContext::getInstance();
     $appName = $ctx->getApp();
     if ($ctx->isAnotherApp()) {
         $appName = $ctx->getRealApp();
     }
     //      Logger::getInstance()->on();
     //      Logger::struct($ctx);
     //      Logger::getInstance()->pm_log("PM::__construct appName: " . $appName);
     //      Logger::getInstance()->pm_log("PM::__construct ctx.realApp: " . $ctx->getRealApp());
     //      Logger::getInstance()->off();
     $this->dal = new DAL($appName);
     // FIXME: de donde saco el nombre de la app actual???
 }
コード例 #6
0
ファイル: core.Yupp.class.php プロジェクト: fkali/yupp
 /**
  * Retorna el modo de ejecucion actual del framework, dev, prod o test.
  */
 public function getMode()
 {
     // En YuppConfig se definen los modos posibles, p.e. YuppConfig :: MODE_DEV
     return YuppContext::getInstance()->getMode();
 }
コード例 #7
0
 /**
  * clazz es el nombre de una clase de modelo (tambien puede ser PersistentObject).
  * Devuelve una estructura multiple con los nombres de todas las clases que heredan de clazz (hijas, nietas, etc)
  */
 public static function getAllSubclassesOf($clazz)
 {
     //echo "<h1>ModelUtils.getAllSubclassesOf $clazz</h1>";
     //Logger::struct( get_declared_classes(), "Declared classes ".__FILE__." ".__LINE__ );
     // Esto en realidad se deberia hacer con getLoadedModelClasses
     // porque ModelUtils es para resolver temas de las clases del modelo.
     //$loadedClasses = YuppLoader::getLoadedClasses();
     // Como las clases cargadas dependen de la aplicacion,
     // me ancargo de cargar todas las clases de la aplicacion
     // actual para obtener correctamente las subclases.
     // Mismo codigo que getSubclassesOf.
     $ctx = YuppContext::getInstance();
     $appName = $ctx->getApp();
     if ($appName == 'core') {
         // Si no se cargaron todas las clases y no se pasa el nombre de la app, no devuelve realmente todas las subclases, solo las que estan cargadas.
         YuppLoader::loadModel();
         // Carga el modelo de todas las aplicaciones
     } else {
         // TODO: metodo para cargar todas las clases del modelo de una aplicacion.
         $classes = array();
         // FIXME: Mismo codigo que CoreController.dbStatus
         YuppLoader::load('core.app', 'App');
         // Puede no estar cargada
         $app = new App($appName);
         $modelClassFileNames = $app->getModel();
         // Logger::struct( $modelClassFileNames, "modelClassFileNames ".__FILE__." ".__LINE__ );
         $modelClassFileNames = self::array_flatten($modelClassFileNames);
         $fn = new FileNames();
         foreach ($modelClassFileNames as $classFileName) {
             $fileInfo = $fn->getFileNameInfo($classFileName);
             YuppLoader::load($fileInfo['package'], $fileInfo['name']);
         }
     }
     $loadedClasses = YuppLoader::getLoadedModelClasses();
     $res = array();
     foreach ($loadedClasses as $loadedClass) {
         if (class_exists($loadedClass) && is_subclass_of($loadedClass, $clazz)) {
             $res[] = $loadedClass;
         }
     }
     return $res;
 }
コード例 #8
0
ファイル: core.app.App.class.php プロジェクト: fkali/yupp
 static function getCurrent()
 {
     $ctx = YuppContext::getInstance();
     return new App($ctx->getApp());
 }
コード例 #9
0
 /**
  * Para ejecutar los tests de una aplicacion.
  * in: name 1..1 nombre de la aplicacion
  */
 public function testAppAction()
 {
     YuppLoader::load('core.testing', 'TestSuite');
     YuppLoader::load('core.testing', 'TestCase');
     $appName = $this->params['name'];
     $app = new App($appName);
     // Si hay tests
     if (!$app->hasTests()) {
         return $this->redirect(array('action' => 'index', 'params' => array('flash.message' => 'No hay tests para ejecutar')));
     }
     // Para que cargue la configuracion correcta de la base de datos.
     // Si no trata de ejecutar usando la configuracion de la base por defecto.
     $ctx = YuppContext::getInstance();
     $ctx->setApp($appName);
     // Cargar los casos de test en una suite y ejecutarlos
     $suite = $app->loadTests();
     $suite->run();
     //print_r( $suite->getReports() );
     $this->params['results'] = $suite->getReports();
     $this->params['app'] = $app;
 }
コード例 #10
0
 public static function doRequest()
 {
     global $_base_dir;
     // TODO: que el mostrar el tiempo de proceso sea configurable.
     //$tiempo_inicio = microtime(true);
     $timer_process = new Timer();
     $timer_process->start();
     // Establezco la url base, independiente del directorio donde este situado el script.
     // Si la uri es: http://localhost:8081/Persistent/test/usermanager/person/create?name=pepe&age=23&height=180
     // y este script esta en http://localhost:8081/Persistent/test/
     // Url sera: usermanager/person/create?name=pepe&age=23&height=180
     // ====================================================
     // ROUTING: el objetivo es devolver un $command
     $router = new Router($_SERVER['REQUEST_URI']);
     $lr = $router->getLogicalRoute();
     $ctx = YuppContext::getInstance();
     //Logger::struct( $lr, "LOGICAR ROUTE 1 " .__FILE__.' '.__LINE__ );
     // ====================================================================
     // FIXME: esto lo deberia hacer el router
     // ====================================================================
     // Verifica salida del router y setea valores que no vienen seteados.
     // TODO: OJO, luego debe pasar el verificador de si el controller
     //       y action existen, y si no, ejecutar contra core.
     // Esto dice a donde ir cuando se accede a la aplicacion YUPP,
     // esta bien que se haga aca, no es cosa del router.
     if (empty($lr['app'])) {
         $config = YuppConfig::getInstance();
         $modeDefaultMapping = $config->getModeDefaultMapping();
         $lr['app'] = $modeDefaultMapping['app'];
         $lr['controller'] = $modeDefaultMapping['controller'];
         $lr['action'] = $modeDefaultMapping['action'];
         $router->addCustomParams($modeDefaultMapping['params']);
     }
     // FIXME: esto lo deberia hacer el router
     // Si la ruta en la URL llega hasta la app,
     // se muestran los controladores de la app.
     if (empty($lr['controller'])) {
         if (!Yupp::appExists($lr['app'])) {
             // Tira 404: Not Found
             $command = ViewCommand::display('404', new ArrayObject(array('message' => 'La aplicaci&oacute;n <b>' . $lr['app'] . '</b> no existe')), new ArrayObject());
         } else {
             //Logger::getInstance()->po_log("RM: ".__FILE__ .' '.__LINE__);
             $router->addCustomParams(array('app' => $lr['app']));
             $lr['app'] = "core";
             // Le dice a core/core que muestre los controllers de la app $lr['app']
             $lr['controller'] = "core";
             $lr['action'] = "appControllers";
         }
     } else {
         // Prefiero el parametro por url "_action_nombreAccion", a la accion que viene en la URL (app/controlador/accion).
         // Esto es porque los formularios creados con YuppForm generan acciones distintas para botones de
         // submit distintos y la accion es pasada codificada en un parametros _action_nombreAcction.
         // Por si la accion viene codificada en una key de un param como '_action_laAccion', por ejemplo: esto pasa en un submit de un YuppForm.
         $actionParam = $router->getActionParam();
         if (empty($actionParam)) {
             if (!isset($lr['action']) || $lr['action'] === "") {
                 $lr['action'] = 'index';
             }
         } else {
             // FIXME: hay un problema con actionParam cuando se manda desde un form.
             // La accion que aparece en la URL es la de la action del form, pero la
             // vista que se muestra es la que renderea la acction actionParam. La URL
             // deberia ser tambien la que diga actionParam. Por eso haria un redirect
             // en lugar de un render.
             $lr['action'] = $actionParam;
         }
     }
     // Si en logicalRoute se ponen parametros ej. en el AppMapping,
     // se deben agregar al router como customParams:
     if (isset($lr['params'])) {
         $router->addCustomParams($lr['params']);
         // Deberia ser un array...
     }
     //Logger::struct( $lr, "LOGICAR ROUTE 2 " .__FILE__.' '.__LINE__ );
     // *******************************************************************************
     // FIXME: puedo tener app, controlador y accion, pero pueden ser nombres
     // errados, es decir, que no existen, por ejemplo si en la url le paso /x/y/z.
     // Aqui hay que verificar si existe antes de seguir, y si la app no existe,
     // o si existe pero el controlador no existe, o si ambos existen, si la accion
     // en el controlador no existe, deberia devolver un error y mostrarlo lindo (largar una exept).
     // Estaria bueno definir codigos estandar de errores de yupp, para poder tener una
     // lista ed todos los errores que pueden ocurrir.
     // *******************************************************************************
     // FIXME: no armar esto a mano, pedirselo a alguna clase de convensiones o la nueva clase App.
     $appPath = "apps/" . $lr['app'];
     $controllerClassName = String::firstToUpper($lr['controller']) . "Controller";
     $controllerFileName = "apps." . $lr['app'] . ".controllers." . $controllerClassName . ".class.php";
     $controllerPath = "apps/" . $lr['app'] . "/controllers/" . $controllerFileName;
     /// ACTUALIZAR CONTEXTO ///
     $ctx->setApp($lr['app']);
     $ctx->setController($lr['controller']);
     $ctx->setAction($lr['action']);
     /// ACTUALIZAR CONTEXTO ///
     //Logger::struct( $lr, "LOGICAR ROUTE 3 " .__FILE__.' '.__LINE__ );
     //echo "<hr/>PATH: $controllerPath<br/>";
     // Verifico que lo que pide existe...
     if (!file_exists($appPath)) {
         Logger::getInstance()->log("Path1 '{$appPath}' no existe");
         // Tira 404: Not Found
         $command = ViewCommand::display('404', new ArrayObject(array('message' => 'La aplicaci&oacute;n <b>' . $lr['app'] . '</b> no existe')), new ArrayObject());
     } else {
         if (!file_exists($controllerPath)) {
             Logger::getInstance()->log("Path2 '{$controllerPath}' no existe");
             // Tira 404: Not Found
             $command = ViewCommand::display('404', new ArrayObject(array('message' => 'El controlador <b>' . $lr['controller'] . '</b> no existe')), new ArrayObject());
         } else {
             // Aca deberia chekear si la clase $lr['controller'] . "Controller" tiene le metodo $lr['action'] . "Action".
             // Esto igual salta en el executer cuando intenta llamar al metodo, y salta si no existe.
             // Logger::struct($lr, "LOGICAL ROUTE 2");
             // FIXME: esto es una regla re ruteo.
             // TODO: Si accede a la app sin poner el controller, se intenta buscar un controller con el mismo nombre de la app.
             //       Si no existe, se redirige al core controller como se hace aqui.
             // Verificacion de controller filters (v0.1.6.3)
             $controllerFiltersPath = 'apps/' . $lr['app'] . '/AppControllerFilters.php';
             // Nombre y ubicacion por defecto.
             $controllerFiltersInstance = NULL;
             if (file_exists($controllerFiltersPath)) {
                 // FIXME: con la carga bajo demanda de PHP esto se haria automaticamente!
                 include_once $controllerFiltersPath;
                 // FIXME: no usa YuppLoader (nombre de archivo no sigue estandares!).
                 $controllerFiltersInstance = new AppControllerFilters();
                 // Esta clase esta definida en el archivo incluido (es una convension de Yupp).
             }
             //Logger::struct( $router->getParams(), "ROUTER PARAMS " .__FILE__.' '.__LINE__ );
             //Logger::struct( $_POST, "POST " .__FILE__.' '.__LINE__ );
             //Logger::struct( $_GET, "GET " .__FILE__.' '.__LINE__ );
             $executer = new Executer($router->getParams());
             $command = $executer->execute($controllerFiltersInstance);
             // $controllerFiltersInstance puede ser null!
         }
     }
     // /ROUTING
     // ====================================================
     // Aun mejor, si devuelvo un array, lo tomo como modelo y tomo la accion y controller para encontrar el view, si el view existe o no, lo trato luego con paginas logicas o views escaffoldeados...
     // Si no devuelve nada, hago lo mismo, y tomo como modelo un array vacio, lo que podria hacer, es si el controller tiene atributos, es usar esos atributos (los valores) como modelo (y los nombres los uso como key en el model).
     // View/Redirect
     // TODO:....
     // Si no vienen las cosas seteadas puedo adivinar por ejemplo que view mostrar en funcion de la accion y contorller, como en grails.
     // TODO: Verificar si no es null, si tiene todos los atributos necesarios para hacer o que dice el comando, etc.
     // FIXME: SI EL COMANDO ES NULL QUIERO HACER ACCIONES POR DEFECTO! como mostrar la view correspondiente al controller, y la action ejecutadas.
     if ($command === NULL || empty($command)) {
         // O le falta el command o es que la accion es de pedir un recurso estatico el que se devuelve como stream.
         // Error 500: Internal Server Error
         $command = ViewCommand::display('500', new ArrayObject(array('message' => 'Hubo un error al crear el comando')), new ArrayObject());
     }
     // ==============
     // TEST: ver si guarda el estado en la sesion
     //$test = CurrentFlows::getInstance()->getFlow( 'createUser' );
     //Logger::show( "Flow en sesion antes de hacer render: " . print_r($test->getCurrentState(), true) . ", " . __FILE__ . " " . __LINE__ );
     // ================
     // Siempre llega algun comando
     if ($command->isDisplayCommand()) {
         // Aqui llegan tambien los errores ej 500 o 404 para mostrar una vista linda.
         // FIXME: mostrar o no el tiempo de procesamiento deberia ser configurable.
         //$tiempo_final = microtime(true);
         //$tiempo_proc = $tiempo_final - $tiempo_inicio;
         $timer_process->stop();
         $tiempo_proc = $timer_process->getElapsedTime();
         //$tiempo_inicio = microtime(true);
         $timer_render = new Timer();
         $timer_render->start();
         // FIXME: en router esta toda la info, porque pasar todo?
         self::render($lr, $command, $ctx, $router);
         //$tiempo_final = microtime(true);
         //$tiempo_render = $tiempo_final - $tiempo_inicio;
         $timer_render->stop();
         $tiempo_render = $timer_render->getElapsedTime();
         // TODO: configurar si se quiere o no ver el tiempo de proceso.
         //echo "<br/><br/>Tiempo de proceso: " . $tiempo_proc . " s<br/>";
         //echo "Tiempo de render: " . $tiempo_render . " s<br/>";
         return;
     } else {
         if ($command->isStringDisplayCommand()) {
             echo $command->getString();
             return;
         } else {
             if ($command->isDisplayTemplateCommand()) {
                 $params = array();
                 // TODO: poder pasarle path al helper, asi puedo poner el template en cualquier lado.
                 $params['name'] = $command->viewName();
                 // Nombre del template
                 $params['args'] = $command->params();
                 Helpers::template($params);
                 return;
             } else {
                 // TODO: me gustaria poner todo esto en una clase "Redirect".
                 // echo "DICE QUE NO ES DISPLAY!!!!";
                 // La idea es que cmo es excecute, redirija a unc compo/controller/action/params que diga el command.
                 // Entonces es reentrante a este modulo, el problema es que no tengo el
                 // request hecho de forma que pueda llamarlo de afuera, deberia hacerlo aparte
                 // llamar a ese para la primer entrada y las posibles redirecciones que se puedan hacer.
                 //
                 // -> excecuteControllerAction
                 // Que hago con el command que tira este? tengo que revisar las llamadas recursivas...
                 //$command = self::excecuteControllerAction( $app->app(), $app->controller(), $app->action(), $urlproc->params() )
                 // FIXME: no hace nada con el model, deberia pasar lo que puede como params de GET.
                 // TODO: habria que ver como hacer un request por POST asi puedo mandar info sin que se vea en el request.
                 $model = Model::getInstance();
                 $model->addFlash($command->flash());
                 // Uso el helper para armar la url. Obs> hay funciones estandar de php que arman urls, como
                 // - http://www.php.net/manual/es/function.http-build-url.php
                 // - http://www.php.net/manual/es/function.http-build-str.php //
                 //
                 $url_params = array();
                 $url_params['app'] = $command->app();
                 $url_params['controller'] = $command->controller();
                 $url_params['action'] = $command->action();
                 $url_params['params'] = $command->params();
                 // T#63 solo pasar los params del modelo no los del request.
                 // Agrega params a la url (fix a perdida del flash en redirect)
                 foreach ($command->flash() as $key => $value) {
                     // FIXME: si en flash se ponen arrays y se hace redirect, urlencode va a fallar porque espera un string...
                     $url_params['flash_' . $key] = urlencode($value);
                     // Por ejemplo flash.message='un mensaje', url encode por si tiene simbolos.
                 }
                 //print_r( $url_params );
                 $url = Helpers::url($url_params);
                 // http://www.php.net/manual/es/function.http-redirect.php
                 // retorna false si no puede, exit si si puede.
                 //http_redirect( $url ); // [, array $params  [, bool $session = FALSE  [, int $status  ]]]] )
                 if (!headers_sent()) {
                     // No funciona si hay algun output antes, como el log prendido.
                     // http://www.php.net/header
                     //
                     header('Location: http://' . $_SERVER['HTTP_HOST'] . $url);
                     exit;
                 } else {
                     // TODO: esto deberia ser un template de redireccion automatica fallida.
                     // TODO: los mensajes deberian ser i18n.
                     $url = 'http://' . $_SERVER['HTTP_HOST'] . $url;
                     echo "<html>" . "<head></head><body>" . "Ya se han enviado los headers por lo que no se puede redirigir de forma automatica.<br/>" . "Intenta redirigir a: <a href=\"{$url}\">{$url}</a>" . "</body></html>";
                 }
                 // TODO: Puede redirigir a una pagina logica (como en el CMS) o a una pagina de scaffolding
                 // (no existe fisicamente pero se genera mediante un template y muestra la info que se le
                 // pasa de forma estandar, considerando si es un list, show, create o edit).
                 //return; // TODO
             }
         }
     }
     // NO DEBERIA LLEGAR ACA, DEBE HACERSE UN RENDER O UN REDIRECT ANTES...
 }
コード例 #11
0
 private static function display_show(PersistentObject $po)
 {
     $res = '<table>';
     $attrs = $po->getAttributeTypes();
     foreach ($attrs as $attr => $type) {
         $res .= '<tr><td>';
         $res .= $attr;
         // TODO: Habria que ver si esto es i18n, deberia haber algun "display name" asociado al nombre del campo.
         $res .= '</td><td>';
         $res .= self::field_to_html_show($attr, $type, $po->aGet($attr));
         $res .= '</td></tr>';
     }
     // Necesito el nombre de la aplicacion y no deberia ser 'core', lo obtengo de ctx o de los params.
     $ctx = YuppContext::getInstance();
     $m = Model::getInstance();
     // Muestro hasOne: http://code.google.com/p/yupp/issues/detail?id=12
     $hone = $po->getHasOne();
     foreach ($hone as $attr => $clazz) {
         // TODO: Habria que ver si esto es i18n, deberia haber algun "display name" asociado al nombre del campo.
         $res .= "<tr><td>{$attr}</td><td>";
         $relObj = $po->aGet($attr);
         if ($relObj == NULL) {
             continue;
         }
         $ctx = YuppContext::getInstance();
         $app = $m->get('app');
         if (!isset($app)) {
             $app = $ctx->getApp();
         }
         // Link a vista de scaffolding del objeto relacionado con hasOne
         $res .= h('link', array('app' => 'core', 'controller' => 'core', 'action' => 'show', 'class' => $relObj->getClass(), 'id' => $relObj->getId(), 'body' => $relObj->getClass() . ' [' . $relObj->getId() . ']', 'params' => array('app' => $app)));
         $res .= '</td></tr>';
     }
     $res .= '</table>';
     return $res;
 }
コード例 #12
0
 public function renderWithLayout($pagePath)
 {
     // TODO: utilizar $referencedJSLibs para meter en el header las librerias seleccionadas.
     // reglas:
     //  - la vista puede no tener header, si hay js y no hay header, agregar tambien el header.
     //  - se inlcuiran todos los archivos en el directorio referenciado,
     //    con el potencial problema que un js deba ser incluido antes que
     //    otro y esa informacion no la maneja el framework. Una solucion es
     //    poner los Js en directorios distintos, en ese caso el directorio que
     //    sea referenciado primero sera el primero que se incluya, porque si se
     //    mantienen el orden de inclusion de las libs en $referencedJSLibs.
     //  - ...
     //
     // ================================================================
     // FIXME: include_once ya interpreta el php, si cargo una vista que usa un helper,
     //        y el helper esta incluido en el layout, va a dar un error de que no encuentra
     //        el helper.
     //        Se deberia hacer una inclusion funcional del layout desde la vista en lugar
     //        de hacerlo con la tag layout.
     // ================================================================
     ob_start();
     // Precondicion: la pagina con esta path existe.
     // importa derecho la pagina...
     include_once $pagePath;
     $view = ob_get_clean();
     /*
     echo '<textarea style="width:600px;">';
     echo $view;
     echo '</textarea>';
     */
     //$coincidencias = explode("<head>", $view); // 0 -> html+layout, 1-> resto
     $layout = NULL;
     // Busco tag de layout... muuuyyyy lentoooo!!!!! lento con stripos...
     $pos = strpos($view, '<layout name="');
     // <layout name="papichulo" />
     if ($pos !== false) {
         $coincidencias = explode('<layout name="', $view);
         // 0-> html, 1-> " />+resto
         //echo '<textarea style="width:600px; height:400px;">';
         //print_r( $coincidencias );
         //echo '</textarea>';
         //$coincidencias = explode('" />', $coincidencias[1]); // MAL! puede haber mas /> que el que cierra el layout!
         //$layout = $coincidencias[0];
         $end_layout_pos = strpos($coincidencias[1], '" />');
         $layout = substr($view, $pos + 14, $end_layout_pos);
         //$layout = substr($view, $pos+14); // 14 es el largo de <layout name="
         //         echo '<textarea style="width:600px; height:400px;">';
         //         print_r( $coincidencias );
         //         echo '</textarea>';
         /*
         * coincidencias[0] => 
           <html>
         * coincidencias[1] => blog" />
           <head>
              <link type="text/css" rel="stylesheet" href="/Persistent/css/main.css"/>   </head>
           <body>
           ...
         */
         // substr($coincidencias[1], $end_layout_pos+4) // +4 para evitar el '" />', y cuenta a partir del " en coincidencias[1]
         $coincidencias = explode("</head>", substr($coincidencias[1], $end_layout_pos + 4));
         // 0-> head, 1->resto
         // coincidencias[0] tiene <head>
         $dirtyhead = explode("<head>", $coincidencias[0]);
         $head = $dirtyhead[1];
         // saca el <head>
         //echo '<textarea style="height:800px; width:940px;">';
         //print_r( $dirtyhead );
         //print_r( $coincidencias );
         //echo '</textarea>';
         /*
         * coincidencias[0] => 
           <head>
              <link type="text/css" rel="stylesheet" href="/Persistent/css/main.css"/>   
           coincidencias[1] => 
           <body>
              <h1>Ingreso</h1>
              ...
         */
         //         echo '<textarea style="width:600px; height:400px;">';
         //         print_r( $coincidencias );
         //         echo '</textarea>';
         // Inclusion de JS bajo demanda
         // http://code.google.com/p/yupp/issues/detail?id=32
         /* La inclusion se hace directamente en addJSLibReference
            foreach ( $this->referencedJSLibs as $path )
            {
               $head = '<script type="text/javascript" src="'. $path .'"></script>' . $head;
            }
            */
         // OJO! SI EL LAYOUT SE PONE EN EL HEAD, ESA TAG INVALIDA SE VA A MOSTRAR... TALVEZ SEA MEJOR PONERLA ARRIBA DEL TODO, ANTES DEL HTML, AUNQUE NO SEA UN XML valido...
         //         echo "LAYOUT ";
         //         echo '<textarea style="width:600px; height:400px;">';
         //         echo $layout;
         //         echo '</textarea>';
         // FIXME: si body tiene atributos, esto se rompe
         $coincidencias = explode("<body>", $coincidencias[1]);
         // 0-> nada, 1-> body, /body /html
         $coincidencias = explode("</body>", $coincidencias[1]);
         // 0-> body, 1-> /html
         $body = $coincidencias[0];
         $ctx = YuppContext::getInstance();
         $path = 'apps/' . $ctx->getApp() . '/views/' . $layout . '.layout.php';
         if (!file_exists($path)) {
             throw new Exception("El layout {$layout} no existe en la ruta: {$path} " . __FILE__ . " " . __LINE__);
         }
         include_once $path;
     } else {
         //echo "NO LAYOUT";
         //echo $view;
         // Inclusion de JS bajo demanda
         // http://code.google.com/p/yupp/issues/detail?id=32
         $partes = explode("<head>", $view);
         if (count($partes) > 1) {
             $partes[0] .= '<head>';
         }
         // explode elimina el <head>, lo agrego.
         //$head = $coincidencias[0];
         // Inclusion de JS bajo demanda
         // http://code.google.com/p/yupp/issues/detail?id=32
         /* La inclusion se hace directamente en addJSLibReference
            foreach ( $this->referencedJSLibs as $path )
            {
               $partes[0] .= '<script type="text/javascript" src="'. $path .'"></script>';
            }
            */
         // FIXME: Si la pagina no esta bien formada aqui dara un error
         // p.e. si no se tiene html/head/body
         if (isset($partes[0])) {
             echo $partes[0];
         }
         if (isset($partes[1])) {
             echo $partes[1];
         }
         //echo '<textarea style="height:800px; width:940px;">';
         //print_r( $partes );
         //echo '</textarea>';
     }
 }
 /**
  * Se utiliza para obtener una estructura de mapeo de clases de herencia sobre diferentes tablas.
  * Como se utiliza como auxiliar de generateAll la pongo aca, talvez pueda ir en ModelUtils, pero
  * en realidad solo se usa para generar el esquema y para salvar.
  * 
  * @param $inheritanceClasses lista de clases de una estructura de herencia (clase de la instancia
  *        del objeto que se esta manejando y todas sus superclases) (no se asume ningun orden).
  */
 public static function getMultipleTableInheritance($inheritanceClasses)
 {
     Logger::getInstance()->dal_log("MTI::getMultipleTableInheritance");
     // Ahora depende de una aplicacion.
     // La estructura de MTI no pueden establecerse entre clases del modelo de distintas aplicaciones.
     $ctx = YuppContext::getInstance();
     $appName = $ctx->getApp();
     // 1. clases y sus subclases
     $e = array();
     // array por clave la clase y valor lista de subclases directas de dicha clase
     foreach ($inheritanceClasses as $class) {
         // Quiero poner solo las clases que esten en $inheritanceClasses, que pueden
         // no ser todas las de la estructura de herencia, esto sirve para
         // implementar getPartialInstancesToSave.
         // TODO: en que caso una clase no es de la estructura de herencia si lo
         //       que le paso como parametro es solo la estructura de herencia???
         //       Ver lo que le pasan todas las operaciones que invoque a esta getMultipleTableInheritance.
         $sclss = ModelUtils::getSubclassesOf($class, $appName);
         $e[$class] = array_intersect($inheritanceClasses, $sclss);
     }
     // 2. Arma array de clases y lista de subclases que se mapean en la misma tabla.
     $e1 = array();
     foreach ($e as $class => $subclasses) {
         $c_ins = new $class();
         if (!array_key_exists($class, $e1) || $e1[$class] === NULL) {
             $e1[$class] = array();
         }
         // armo otro array con las subclases que no tienen withTable.
         foreach ($subclasses as $subclass) {
             //$sc_ins = new $subclass();
             //echo $subclass . " " . $sc_ins->getWithTable() . "<br />";
             //if ( $sc_ins->getWithTable() === $c_ins->getWithTable() ) $e1[$class][] = $subclass; // solo si los withTable son iguales (o sea, que no lo redefine en la subclase)
             if (PersistentManager::isMappedOnSameTable($class, $subclass)) {
                 $e1[$class][] = $subclass;
                 //Logger::getInstance()->dal_log("isMapperOnSameTable: $class , $subclass " . __FILE__ . " " . __LINE__ );
             }
         }
     }
     //Logger::getInstance()->dal_log("clases y subclases en la misma tabla " . __FILE__ . " " . __LINE__ );
     //Logger::struct( $e1 );
     // 3. Todas las keys estan en $inheritanceClasses
     foreach ($e1 as $class => $sameTableFirstLevelSubclasses) {
         //echo "CLASS: $class<br />";
         if ($sameTableFirstLevelSubclasses !== NULL) {
             if (count($sameTableFirstLevelSubclasses) > 0) {
                 $merge = array_merge($sameTableFirstLevelSubclasses, array());
                 // copia los valores ???
                 foreach ($sameTableFirstLevelSubclasses as $subclass) {
                     $classesToMerge = $e1[$subclass];
                     if ($classesToMerge !== NULL) {
                         $merge = array_merge($merge, $classesToMerge);
                         $e1[$subclass] = NULL;
                     }
                 }
                 $e1[$class] = $merge;
             }
         }
     }
     /* Esta mal! D, E y B deberian ser NULL tambien.
     Array
     (
         [B] => 
         [C] => Array
             (
                 [0] => E
             )
     
         [D] => Array
             (
             )
     
         [E] => Array
             (
             )
     
         [F] => Array
             (
             )
     
         [G] => Array
             (
             )
     
         [A] => Array
             (
                 [0] => B
                 [1] => D
             )
     )
            */
     //$sol = array_filter( $e1, 'filter_not_null' );
     // no me deja hacer el filter ... lo hago a mano...
     $sol = array();
     foreach ($e1 as $class => $subclasses) {
         if ($subclasses !== NULL) {
             $sol[$class] = $subclasses;
         }
     }
     return $sol;
 }
コード例 #14
0
ファイル: core.mvc.Helpers.class.php プロジェクト: fkali/yupp
 /**
  * Select para modificar el modo de ejecucion.
  */
 public static function mode_chooser($params)
 {
     $ctx = YuppContext::getInstance();
     $config = YuppConfig::getInstance();
     $url = self::url(array('app' => 'core', 'controller' => 'core', 'action' => 'changeMode'));
     $res = '<form action="' . $url . '" style="width:270px; margin:0px; padding:0px;">';
     $res .= '<select name="mode">';
     foreach ($config->getAvailableModes() as $mode) {
         $res .= '<option value="' . $mode . '" ' . ($mode === $ctx->getMode() ? 'selected="true"' : '') . '>' . $mode . '</option>';
     }
     $res .= '<input type="hidden" name="back_app"  value="' . $ctx->getApp() . '" />';
     $res .= '<input type="hidden" name="back_controller" value="' . $ctx->getController() . '" />';
     $res .= '<input type="hidden" name="back_action"     value="' . $ctx->getAction() . '" />';
     $res .= '</select>';
     $res .= '<input type="submit" name="Cambiar" />';
     $res .= '</form>';
     return $res;
 }
コード例 #15
0
ファイル: list.view.php プロジェクト: fkali/yupp
      }
    </style>
  </head>
  <body>
    <h1>List</h1>
      
    <div align="center"><?php 
echo $m->flash('message');
?>
</div>
    
    <div id="actions">
      <?php 
$app = $m->get('app');
if (!isset($app)) {
    $app = YuppContext::getInstance()->getApp();
}
?>
      <a href="create?app=<?php 
echo $app;
?>
&class=<?php 
echo $m->get('class');
?>
">Create</a>
    </div>
    <br/>
    
    <?php 
echo DisplayHelper::model($m->get('list'), "list", $m->get('class'));
?>
コード例 #16
0
ファイル: index.php プロジェクト: fkali/yupp
YuppLoader::load('core.mvc', 'Helpers');
// Usado para acceder a la funcion h()
YuppLoader::load('core.utils', 'Logger');
//[SCRIPT_NAME] => /Persistent/index.php
// Dejo algunas variables globales utiles:
/*
 * Directorio base de la aplicacion, donde se encuentra EntryPoint,
 * desde el cual se pueden calcular URLs relativas y absolutisarlas
 * concatenandoles el base_dir. Necesario para el helper de links.
 */
$_base_dir = substr($_SERVER['SCRIPT_NAME'], 0, strrpos($_SERVER['SCRIPT_NAME'], '/'));
$lg = Logger::getInstance();
$lg->setFile('log.log');
$lg->on();
// TODO: considerar el language de la app
$ctx = YuppContext::getInstance();
$locale = $ctx->setLocale('en');
// Hace el request y catchea por posibles errores.
try {
    RequestManager::doRequest();
} catch (Exception $e) {
    // FIXME: mostrar la vista de error 500
    // FIXME: en modo PROD NUNCA deberia mostrar paths ni el stacktrace.
    // http://code.google.com/p/yupp/issues/detail?id=147
    if (YuppConfig::getInstance()->getCurrentMode() === YuppConfig::MODE_PROD) {
        echo 'Disculpe las molestias, verificaremos el error en breve.';
        // FIXME: i18n
        // Redirect a pagina de error por defecto?
        if (file_exists('ylogs/500')) {
            FileSystem::write('ylogs/500/err_' . date("Ymd.his") . '.log', print_r($ctx, true));
        }
コード例 #17
0
 public function deleteAction()
 {
     $context = YuppContext::getInstance();
     $clazz = String::firstToUpper($context->getController());
     $id = $this->params['id'];
     eval('$ins = ' . $clazz . '::get( $id );');
     $ins->delete(true);
     // Eliminacion logica, si fuera fisica tendria que actualizar los links a las entradas, o borrar tambien las entradas del user.
     $this->flash['message'] = "Objeto [{$id}] eliminado.";
     // FIXME: i18n
     return $this->redirect(array("action" => "list"));
     // FIXME: el redirect mata el flash!
 }