/** * Metodo auxiliar para cargar los objetos asociados en cascada, tanto los hasOne como los hasMany, * verificando previamente si no fueron ya cargados. * @param PersistentObject $obj el objeto al que hay que cargarle los objetos asociados. */ private function getCascadeAssocs($obj) { // Para saber si estaba limpia previamente, para poder limpiar lo que esta operacion ensucia (dirty bits) $wasClean = $obj->isClean(); // TODO: Verificar si para los objetos en hasOne, sus asociaciones son cargadas en cascada. // Para cada objeto hasOne, lo trae. // Para el objeto hago get para hasOne y getMany para los hasMany. $ho_attrs = $obj->getHasOne(); foreach ($ho_attrs as $attr => $assoc_class) { // attr = "email_id" ? $ho_instance = new $assoc_class(); $hasOneAttr = DatabaseNormalization::getSimpleAssocName($attr); // email $assoc_id = $ho_instance->aGet($attr); $assoc_obj = NULL; if (ArtifactHolder::getInstance()->existsModel($assoc_class, $assoc_id)) { $assoc_obj = ArtifactHolder::getInstance()->getModel($assoc_class, $assoc_id); } else { $assoc_obj = $this->get($assoc_class, $assoc_id); ArtifactHolder::getInstance()->addModel($assoc_obj); } //$obj->{"set".$attr}( $assoc_obj ); $obj->aSet($attr, $assoc_obj); } // Para cada objeto hasMany, lo trae // Para el objeto hago get para hasOne y getMany para los hasMany. $hm_attrs = $obj->getHasMany(); foreach ($hm_attrs as $attr => $class) { $this->getMany($obj, $attr); // Carga los elementos del atributo en la clase. } // TODO: si carga en cascada, entonces la instancia de obj y sus clases asociadas // se cargan todas en el mismo momento, por lo que no habria nada sucio, // y seria innecesario verificar si estaba sucia antes de la carga. // Solo limpia si la clase estaba limpia antes de la operacion if ($wasClean) { $obj->resetDirty(); } // Apaga las banderas que se prendieron en la carga }
public function nullable($attr) { // Atributos inyectados no son nullables. if (self::isInyectedAttribute($attr)) { return false; } if (DatabaseNormalization::isSimpleAssocName($attr)) { $attr = DatabaseNormalization::getSimpleAssocName($attr); } if (isset($this->constraints[$attr])) { foreach ($this->constraints[$attr] as $constraint) { if (get_class($constraint) === 'Nullable') { return $constraint->getValue(); } } } return true; // Por defecto es nullable. Es mas facil para generar las tablas, ahora se pone en not null solo si hay una restriccion que lo diga. }
/** * 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; }