/** * Validate related class and inverse on a field map * @param epFieldMap $fm the field map to be checked * @param string $class the name of the class that the field belongs to * @return array (errors) */ protected function _validateRelationshipField(&$fm, $class) { // array to hold error messages $errors = array(); // // 1. check the opposite class for the field // // string for class and field $class_field = '[' . $class . '::' . $fm->getName() . ']'; // does the relation field have the related class defined? if (!($rclass = $fm->getClass())) { // shouldn't happend $errors[] = $class_field . ' does not have opposite class specified'; return $errors; } // does the related class exist? if (!isset($this->class_maps[$rclass])) { // alert if not $errors[] = 'Class [' . $rclass . '] for ' . $class_field . ' does not exist'; return $errors; } // // 2. check inverse of the field // // does this field have an inverse? if (!($inverse = $fm->getInverse())) { return $errors; } // get the related class map $rcm = $this->class_maps[$rclass]; // get all fields point to the current class in the related class $rfields = $rcm->getFieldsOfClass($class); // 2.a. default inverse (that is, set to true) if (true === $inverse) { // the related class must have only one relationship var to the current class if (!$rfields) { $errors[] = 'No inverse found for ' . $class_field; } else { if (count($rfields) > 1) { $errors[] = 'Ambiguilty in the inverse of ' . $class_field; } else { $rfms = array_values($rfields); $fm->setInverse($rfms[0]->getName()); $rfms[0]->setInverse($fm->getName()); } } return $errors; } // 2.b. inverse is specified // check if inverse exists if (!isset($rfields[$fm->getClass() . ':' . $inverse]) || !$rfields[$fm->getClass() . ':' . $inverse]) { $errors[] = 'Inverse of ' . $class_field . ' (' . $fm->getClass() . '::' . $inverse . ') does not exist'; return $errors; } // get the field map for the inverse $rfm = $rfields[$fm->getClass() . ':' . $inverse]; // set up the inverse on the other side -only if- inverse on the other side // is -not- already set or set to default if (!($rinverse = $rfm->getInverse()) || $rinverse === true) { $rfm->setInverse($fm->getName()); return $errors; } // if specified, check duality if ($class != $rfm->getClass() || $rinverse != $fm->getName()) { $errors[] = 'Inverse of [' . $rcm->getName() . '::' . $fm->getName() . '] is not specified as ' . $class_field; } return $errors; }