function &buildWidget(&$record, &$field, &$form, $formFieldName, $new = false) { /* * * This field uses a table widget. * */ $table =& $record->_table; $formTool =& Dataface_FormTool::getInstance(); $factory =& Dataface_FormTool::factory(); $widget =& $field['widget']; $el =& $factory->addElement('table', $formFieldName, $widget['label']); if (isset($widget['fields'])) { $widget_fields =& $widget['fields']; foreach ($widget_fields as $widget_field) { $widget_field =& Dataface_Table::getTableField($widget_field, $this->db); if (PEAR::isError($widget_field)) { return $widget_field; } $widget_widget = $formTool->buildWidget($record, $widget_field, $factory, $widget_field['name']); $el->addField($widget_widget); } } else { if (isset($field['fields'])) { foreach (array_keys($field['fields']) as $field_key) { $widget_widget = $formTool->buildWidget($record, $field['fields'][$field_key], $factory, $field['fields'][$field_key]['name']); $el->addField($widget_widget); unset($widget_widget); } } } return $el; }
/** * Gets the values of the foreign keys of a particular relationship. This returns an associative * array with the following structure: * Array( * "table1" => Array( "field1"=>"value1", "field2"=>"value2", ... ), * "table2" => Array( "field1"=>"value1", "field2"=>"value2", ... ), * ... * ); * @param relationship_name The name of the relationship * @param values Supplementary values passed as array with keys = absolute field names, values = serialized values. * @param sql If provided, this will be used as the select statement that we dissect. * @parseValues If true we parse out variables. If false, we simply return the variables to be parsed later. * @throws PEAR_Error if there is insufficient values supplied for the foreign key to work. * */ function getForeignKeyValues($values = null, $sql = null, $record = null) { if (is_object($record)) { $record_id = $record->getId(); } if (!isset($values) and !isset($sql) and !isset($record) and isset($this->_cache[__FUNCTION__])) { return $this->_cache[__FUNCTION__]; } if (!isset($values) and !isset($sql) and is_object($record) and isset($this->_cache[__FUNCTION__ . $record_id])) { return $this->_cache[__FUNCTION__ . $record_id]; } // Strategy: // ---------- // 1. Label all fields involved in the foreign key so that fields that are equal have the // same label. Eg: In the query: // select * // from Students // inner join Student_Courses // on Students.id = Student_Courses.studentid // inner join Courses // on Student_Courses.courseid = Courses.id // where // Students.id = '$id' // // In the above query Students.id and Student_Course.studentid would have the same label, and // Student_Courses.courseid and Courses.id would have the same label. // ie: Label(Students.id) = Label(Student_Courses.studentid) ^ Label(Student_Courses.courseid) = Label(Courses.id) // // 2. Assign values for each label. All fields with a particular label have the same value. // In the above query, we would have: // Value(Label(Students.id)) = '$id' // **Note from above that Label(Students.id)=Label(Student_Courses.studentid) so their values are also equal. // // 3. For labels without a value find out if one of the fields assuming that label is an auto-increment field. If so // we assign the special value '__Tablename__auto_increment__' where "Tablename" is the name of the table whose // field is to be auto incremented. // // 4. Collect the the values in a structure so that we can lookup the values of any particular field in any particular // table easily. Return this structure. $relationship =& $this->_schema; if ($sql !== null) { // An SQL query was specified as a parameter, we parse this and use the resulting data structure // for the rest of the computations. if (is_string($sql)) { $parser = new SQL_Parser(null, 'MySQL'); $sql = $parser->parse($sql); } $select =& $sql; } else { // We use the 'parsed_sql' entry in the relationship as the basis for our dissection. $select =& $relationship['parsed_sql']; } // Build equivalence classes for column names. $labels = array(); $vals = array(); $this->_makeEquivalenceLabels($labels, $vals, $select); // Fill in some default values if (is_array($values)) { foreach ($values as $field_name => $field_value) { if (!$field_value) { continue; } // we don't want empty and null values to act as defaults because they // tend to screw things up when we are adding related records. if (isset($labels[$field_name])) { $label = $labels[$field_name]; } else { $label = $field_name; $labels[$field_name] = $label; } $vals[$label] = $field_value; } } // next we need to find 'circular links'. Ie: There may be columns that are only specified to be equal to each other. Most of the // time this means that one of the fields is an auto increment field that will be automatically filled in. We need to insert // a special value (in this case), so that we know this is the case. foreach ($labels as $field_name => $label) { if (!isset($vals[$label])) { $field =& Dataface_Table::getTableField($field_name); $table_auto_increment = null; foreach ($labels as $auto_field_name => $auto_label) { if ($auto_label == $label) { $auto_field =& Dataface_Table::getTableField($auto_field_name); if ($auto_field['Extra'] == 'auto_increment') { list($table_auto_increment) = explode('.', $auto_field_name); unset($auto_field); break; } unset($auto_field); } } if (isset($table_auto_increment)) { //list($table) = explode('.', $field_name); $vals[$label] = "__" . $table_auto_increment . "__auto_increment__"; } else { $vals[$label] = new Dataface_Relationship_ForeignKey($this, $labels, $label); } unset($field); } } $table_cols = array(); foreach ($labels as $field_name => $label) { $fieldArr =& Dataface_Table::getTableField($field_name); list($table, $field) = explode('.', $field_name); if (!$table) { continue; } if (!isset($table_cols[$table])) { $table_cols[$table] = array(); } $table_cols[$table][$field] = (is_scalar(@$vals[$label]) and $record !== null and !preg_match('/(blob|binary)/', strtolower($fieldArr['Type']))) ? $record->parseString(@$vals[$label]) : @$vals[$label]; unset($fieldArr); } // make sure that each table at least sets all of the mandatory fields. foreach ($table_cols as $table => $cols) { $tableObject =& Dataface_Table::loadTable($table); foreach (array_keys($tableObject->mandatoryFields()) as $key) { if (!isset($cols[$key])) { $this->errors[] = PEAR::raiseError(DATAFACE_TABLE_RELATED_RECORD_REQUIRED_FIELD_MISSING_ERROR, null, null, null, "Could not generate SQL to add new record to relationship '" . $this->_name . "' because not all of the required fields have values. In particular, the field '{$key}' of table '{$table}' is missing but is a key of the table."); } } unset($tableObject); } if (!isset($values) and !isset($sql) and !isset($record)) { $this->_cache[__FUNCTION__] = $table_cols; } if (!isset($values) and !isset($sql) and is_object($record)) { $this->_cache[__FUNCTION__ . $record_id] = $table_cols; } return $table_cols; }
function &buildWidget(&$record, &$field, &$form, $formFieldName, $new = false) { /* * * This field uses a table widget. * */ //$field['display'] = 'block'; $table =& $record->_table; $formTool =& Dataface_FormTool::getInstance(); $factory =& Dataface_FormTool::factory(); $widget =& $field['widget']; $el =& $factory->addElement('grid', $formFieldName, $widget['label']); $el->setProperties($widget); $rperms = $record->getPermissions(array('relationship' => $field['relationship'])); if (!$record->checkPermission('add new related record', array('relationship' => $field['relationship']))) { //echo "No add new ".$record->_table->tablename; $el->addNew = false; } if (!$record->checkPermission('add existing related record', array('relationship' => $field['relationship']))) { //echo "No add new ".$record->_table->tablename; $el->addExisting = false; } if (isset($field['relationship'])) { $relationship =& $table->getRelationship($field['relationship']); if (!$record->checkPermission('remove related record', array('relationship' => $field['relationship']))) { $el->delete = false; } else { if ($relationship->isOneToMany() and isset($rperms['delete related record']) and !@$rperms['delete related record']) { $el->delete = false; } } if (!$relationship->supportsRemove()) { $el->delete = false; } if (!$relationship->supportsAddNew()) { $el->addNew = false; } if (!$relationship->supportsAddExisting()) { $el->addExisting = false; } else { $el->addExistingFilters = $relationship->getAddExistingFilters(); } $el->table = $relationship->getDomainTable(); if (isset($widget['columns'])) { $columns = array_map('trim', explode(',', $widget['columns'])); } else { $columns = $relationship->_schema['short_columns']; } $count = 0; $subfactory = new HTML_QuickForm(); $dummyRelatedRecord = new Dataface_RelatedRecord($record, $relationship->getName()); //print_r($dummyRelatedRecord->getPermissions()); $orderCol = $relationship->getOrderColumn(); if (!$orderCol or PEAR::isError($orderCol)) { $el->reorder = false; } foreach ($columns as $column) { $colTable =& $relationship->getTable($column); if (!$colTable) { echo "Could not find table for column {$column}"; } $colPerms = $dummyRelatedRecord->getPermissions(array('field' => $column)); if (!@$colPerms['view']) { unset($colTable); unset($dummyRecord); continue; } // We need to be a bit more refined on this one. We need to take // into account the context being that we are in a relationship. $dummyRecord = new Dataface_Record($colTable->tablename, $record->vals()); /* if ( !$dummyRecord->checkPermission('view', array('field'=>$column, 'recordmask'=>array('view'=>1))) ) { unset($colTable); unset($dummyRecord); continue; } */ $colFieldDef =& $colTable->getField($column); $columnElement =& $formTool->buildWidget($dummyRecord, $colFieldDef, $subfactory, $column, false); $defaultValue = $colTable->getDefaultValue($column); $columnElement->setValue($defaultValue); $el->defaults[$column] = $defaultValue; $el->addField($colFieldDef, $columnElement, $colPerms); unset($columnElement); unset($colFieldDef); unset($dummyRecord); unset($colTable); unset($elementFilter); } } else { if (isset($widget['fields'])) { $widget_fields =& $widget['fields']; foreach ($widget_fields as $widget_field) { $widget_field =& Dataface_Table::getTableField($widget_field, $this->db); if (PEAR::isError($widget_field)) { return $widget_field; } $widget_widget = $formTool->buildWidget($record, $widget_field, $factory, $widget_field['name']); $defaultValue = $table->getDefaultValue($widget_field['name']); $widget_widget->setValue($defaultValue); $el->addField($widget_widget); $el->defaults[$widget_field['name']] = $defaultValue; } } else { if (isset($field['fields'])) { foreach (array_keys($field['fields']) as $field_key) { $widget_widget = $formTool->buildWidget($record, $field['fields'][$field_key], $factory, $field['fields'][$field_key]['name']); $defaultValue = $table->getDefaultValue($widget_field['name']); $widget_widget->setValue($defaultValue); $el->defaults[$widget_field['name']] = $defaultValue; $el->addField($widget_widget); unset($widget_widget); } } } } return $el; }