/** * Dada una instancia de PO, devuelve una estructura con las clases que se deben guardar * en distintas tablas y los atrbibutos de cada una con sus respectivos valores. */ public static function getPartialInstancesToSave($po_ins) { Logger::getInstance()->dal_log("MTI::getPartialInstancesToSave " . $po_ins->getClass()); //Logger::struct( $po_ins, __FILE__ . ".getPartialInstancesToSave " . __LINE__ ); // TODO: (performance) si el objeto no representa un MTI no deberia hacerse todo el trabajo de copiar cada atributo del objeto, // eso deberia verificarse antes, y de no ser un MTI, devolver nomas un array con el objeto entrante. // Para simplificar y no tener que hacer aGet sobre po_ins $values = $po_ins->getAttributeValues(); //$superclasses = ModelUtils::getAllAncestorsOf( $po_ins->getClass() ); // puede ser en cualquier orden! $superclasses = ModelUtils::getAllAncestorsOf($values['class']); // puede ser en cualquier orden! /* // Quiero la clase de nivel 1 $level1Class = NULL; foreach ( $superclasses as $class ) { if ( get_parent_class( $class ) == 'PersistentObject' ) { $level1Class = $class; break; // salir del foreach } } $struct = self::getMultipleTableInheritanceStructureToGenerateModel( array($level1Class) ); */ // Lo anterior es lo mismo que hacer esto: // NO! SERIA LO MISMO SI LA INSTANCIA QUE ME PASAN ES DE LA ULTIMA CLASE DE LA ESTRUCTURA DE HERENCIA. // CORRECCION, esta bien porque hace getClass, y obtiene la clase real que es la ultima de la estructura!!!! //$superclasses[] = $po_ins->getClass(); $superclasses[] = $values['class']; // Mapa de clases y subclases que se mapean en la misma tabla. $struct = self::getMultipleTableInheritance($superclasses); //Logger::getInstance()->dal_log("getMultipleTableInheritance (son las subclases en la misma tabla) " . __FILE__ . " " . __LINE__ ); //Logger::struct( $struct ); // TODO: Partial Instances no considera valores, tengo que setear los valores a mano a partir de los valores de po_ins. $partialInstances = self::getPartialInstantes($struct); // Instancias de las clases en $superclasses que solo tienen los atributos que van en cada tabla. Cada clase de estas se mapea directamente con una tabla. foreach ($partialInstances as $partialInstance) { $attrs_values = $partialInstance->getAttributeTypes(); // El tipo no lo uso para nada, solo necesito la declaracion de atributos. foreach ($attrs_values as $attr => $type) { //echo $partialInstance->getClass() . " " . $po_ins->getClass() . " $attr<br />"; //if ( $partialInstance->getClass() === $po_ins->getClass() || // Seteo atributos inyectados tambien, xq son de esta instancia! if ($partialInstance->getClass() === $values['class'] || !PersistentObject::isInyectedAttribute($attr)) { // =============================================================================== // aGet tiene cierta complejidad pidiendo values directamente es mas rapido //$partialInstance->aSet($attr, $po_ins->aGet($attr)); $partialInstance->aSet($attr, $values[$attr]); // PO garantiza que vienen valores para todos los indices, aunque sean NULL, por eso no es necesario hacer un isset($values[$attr]) } } // El deleted, si la instancia a salvar esta deleted, todos los registros deben estarlo! //$partialInstance->setDeleted( $po_ins->getDeleted() ); $partialInstance->setDeleted($values['deleted']); } // getPartialInstancesToSave return $partialInstances; // derecho para salvar cada uno usando save_object!!! }
/** * Devuelve HTML para edicion de un objeto como una tabla con 2 columnas, la primera de nombres de campos la segunda con campos con valores para modificar. */ private static function display_edit(PersistentObject $po) { $res = '<table>'; $attrs = $po->getAttributeTypes(); foreach ($attrs as $attr => $type) { // Los atributos inyectados no se deberian poder editar! $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>'; if ($po->isInyectedAttribute($attr)) { //$res .= $po->aGet($attr); $res .= self::field_to_html_show($attr, $type, $po->aGet($attr)); } else { if (DatabaseNormalization::isSimpleAssocName($attr)) { // Si es un fk a un id de un hasOne, quiero mostrar una lista de los posibles ids // de la clase de la relacion HO que le puedo asignar, y como esto es create o edit, // si tiene un valor actual, deberia quedar seleccionado en el select. $currentValue = $po->aGet($attr); // Puede ser NULL $role = DatabaseNormalization::getSimpleAssocName($attr); // email_id -> email $relClass = $po->getAttributeType($role); // Clase de la relacion HO // Objetos que puedo tener relacionadoss // Se puede en PHP 5.3.0... //$list = $relClass::listAll(new ArrayObject()); // Objetos que podria tener asociados // ... pero por las dudas ... $list = call_user_func_array(array($relClass, 'listAll'), array(new ArrayObject())); $select = '<select name="' . $attr . '"><option value=""></option>'; foreach ($list as $relObj) { $sel = $currentValue == $relObj->getId() ? ' selected="true"' : ''; $select .= '<option value="' . $relObj->getId() . '"' . $sel . '>' . $relClass . '[' . $relObj->getId() . ']</option>'; // TODO: Si se tuviera un toString en la clase se mostraria mejor } $select .= '</select>'; $res .= $select; } else { $maxStringLength = NULL; if ($type === Datatypes::TEXT) { $maxLengthConstraint = $po->getConstraintOfClass($attr, 'MaxLengthConstraint'); if ($maxLengthConstraint !== NULL) { $maxStringLength = $maxLengthConstraint->getValue(); } } $res .= self::field_to_html_edit($attr, $type, $po->aGet($attr), $maxStringLength); // Si el campo tiene errores, los muestro if ($po->getErrors()->hasFieldErrors($attr)) { $res .= '<div class="errors">'; $res .= self::fieldErrors($po, $attr); $res .= '</div>'; } } } $res .= '</td></tr>'; } $res .= '</table>'; return $res; }