/** * @brief Adds a related record to the current context. This provides * a lense through which to view the destination records of this related * record so that their permissions are evaluated as if they are part * of the relationship. * * @param Dataface_RelatedRecord $rec The related record to add for context. * @returns void * @since 2.0 * @see getRecordContext() * @see clearRecordContext() */ function addRecordContext(Dataface_RelatedRecord $rec) { $this->getRecordContext(); $destRecords = $rec->toRecords(); foreach ($destRecords as $destRec) { $this->recordContext[$destRec->getId()] = $rec; } Dataface_PermissionsTool::addContextMask($rec); }
/** * @brief Adds as related record's permissions as a permissions mask for * its destination records. Any call to getPermissions() on the destination * records will now have their permissions augmented by the relationship * permissions defined in the context record. * * @since 2.0 * @param Dataface_RelatedRecord $contextRecord The context record to provide permissions * for its destination records. * @returns void * @see removeContextMask() * @see getContextMasks() * @see getContextMask() * @see getPortalRecordPermissions() * @see getPortalFieldPermissions() */ function addContextMask(Dataface_RelatedRecord $contextRecord) { $app = Dataface_Application::getInstance(); if (!isset($this->contextMasks)) { $this->contextMasks = array(); } $parentPerms = $contextRecord->getParent()->getPermissions(array('relationship' => $contextRecord->_relationshipName)); $perms = array(); if (@$parentPerms['add new related record'] or @$parentPerms['add existing related record']) { $perms['new'] = 1; } if (@$parentPerms['delete related record']) { $perms['delete'] = 1; } else { if (isset($parentPerms['delete related record']) and !@$parentPerms['delete related record']) { $perms['delete'] = 0; } } if (@$parentPerms['edit related records']) { $perms['edit'] = 1; } else { if (isset($parentPerms['edit related records']) and !@$parentPerms['edit related records']) { $perms['edit'] = 0; } } if (@$parentPerms['view related records override']) { $perms['view'] = 1; } else { if (isset($parentPerms['view related records override']) and !@$parentPerms['view related records override']) { $perms['view'] = 0; } } if (@$parentPerms['find related records']) { $perms['find'] = 1; } else { if (isset($parentPerms['find related records']) and !@$parentPerms['find related records']) { $perms['find'] = 0; } } if (@$parentPerms['link related records']) { $perms['link'] = 1; } else { if (isset($parentPerms['link related records']) and !@$parentPerms['link related records']) { $perms['link'] = 0; } } $recordPerms = $perms; unset($perms); $domainTable = $contextRecord->_relationship->getDomainTable(); $destRecords = $contextRecord->toRecords(); $numDest = count($destRecords); $destRecordIndex = array(); $destRecordIds = array(); foreach ($destRecords as $destRecord) { $destRecordIndex[$destRecord->table()->tablename] = $destRecord; $id = $destRecord->getId(); $destRecordIds[$destRecord->table()->tablename] = $id; $this->contextMasks[$id] = $recordPerms; if ($numDest > 1) { // This is a many-to-many relationship if (strcmp($destRecord->table()->tablename, $domainTable) === 0) { // For many-to-many relationships // we don't want the user to be able to edit // the domain table. if (!@$parentPerms['add new related record']) { unset($this->contextMasks[$id]['new']); } unset($this->contextMasks[$id]['edit']); unset($this->contextMasks[$id]['link']); } else { // This is a join table if (@$parentPerms['remove related record']) { $this->contextMasks[$id]['delete'] = 1; } else { if (isset($parentPerms['remove related record']) and !@$parentPerms['remove related record']) { $this->contextMasks[$id]['delete'] = 0; } } } } } $relationship = $contextRecord->_relationship; $fields = $relationship->fields(true, true); $constrainedFields = array_flip($contextRecord->getConstrainedFields()); foreach ($fields as $field) { $fieldTable = $relationship->getTable($field); $fieldTableName = $fieldTable->tablename; $rec = $destRecordIndex[$fieldTableName]; $perms = null; if (strpos($field, '.') !== false) { list($junk, $fieldname) = explode('.', $field); } else { $fieldname = $field; } $perms = $rec->getPermissions(array('field' => $fieldname, 'nobubble' => 1)); if (!$perms) { $perms = array(); } $rfperms = $contextRecord->getParent()->getPermissions(array('relationship' => $contextRecord->_relationshipName, 'field' => $fieldname, 'nobubble' => 1)); //echo "RFPerms: ";print_r($rfperms); if ($rfperms) { foreach ($rfperms as $k => $v) { $perms[$k] = $v; } } if (isset($constrainedFields[$fieldTableName . '.' . $fieldname])) { $perms['edit'] = 0; } $id = $destRecordIds[$fieldTableName]; $this->contextMasks[$id . '#' . $fieldname] = $perms; unset($perms); } $this->_cache = array(); // Clear the cache because // the presence of this mask will // alter the result of permissions queries }
function testAddRelatedRecord() { $fragrance = df_get_record('fragrances', array('fragrance_id' => '=1')); $this->assertTrue($fragrance instanceof Dataface_Record, 'Loaded fragrance should be a Dataface_Record object.'); $formulasRelationship = $fragrance->table()->getRelationship('formulas'); $this->assertTrue($formulasRelationship instanceof Dataface_Relationship, 'The formulas relationship does not exist or could not be loaded.'); $relatedRecord = new Dataface_RelatedRecord($fragrance, 'formulas'); $this->assertTrue(!$relatedRecord->isDirty('formula_name'), 'Record should not be dirty when it is first created.'); $formula = $relatedRecord->toRecord('formulas'); $this->assertTrue($formula instanceof Dataface_Record, 'Formula should be a Dataface_Record'); $records = $relatedRecord->toRecords(); $this->assertTrue($records[0] instanceof Dataface_Record, 'Formulas record from toRecords() should be of type Dataface_Record.'); $relatedRecord->setValues(array('formula_name' => 'Test formula', 'formula_description' => 'This is just a test formula', 'ingredients' => array(0 => array('ingredient_id' => 3, 'concentration' => 10, 'concentration_units' => 1, 'amount' => 10, 'amount_units' => 2, '__id__' => 'new', '__order__' => 0), '__loaded__' => 1))); $this->assertTrue($relatedRecord->isDirty('formula_name'), 'The formula name should be dirty before it is saved.'); $this->assertTrue($relatedRecord->isDirty('ingredients'), 'The ingredients should be dirty befor it is saved.'); $io = new Dataface_IO('fragrances'); $res = $io->addRelatedRecord($relatedRecord); $this->assertTrue(!PEAR::isError($res), 'The result of saving a related formula should not be an error.'); }