library/Garp/Content/Relation/Manager.php
public static function unrelate($options) {
        self::_normalizeOptionsForUnrelate($options);
        $modelA  = $options['modelA'];
        $modelB  = $options['modelB'];

        /**
         * If bindingModel is set, we can safely skip all those difficult checks below.
         */
        if (is_object($options['bindingModel'])) {
            return self::_unrelateHasAndBelongsToMany($options);
        }
        try {
            /**
             * If this succeeds, it's a regular relationship where the foreign key
             * resides inside modelA. Continue as usual.
             */
            $reference = $modelA->getReference(get_class($modelB), $options['rule']);
        } catch (Exception $e) {
            if (!self::isInvalidReferenceException($e)) {
                throw $e;
            }
            try {
                /**
                 * If this succeeds, the foreign key resides in the modelA.
                 * Flip modelA and modelB and keyA and keyB in order to normalize the
                 * given configuration.
                 * Call self::relate() recursively with these new options.
                 */
                $reference = $modelB->getReference(get_class($modelA), $options['rule']);

                $keyA = $options['keyA'];
                $keyB = $options['keyB'];
                $options['modelA'] = $modelB;
                $options['modelB'] = $modelA;
                $options['keyA'] = $keyB;
                $options['keyB'] = $keyA;
                return Garp_Content_Relation_Manager::unrelate($options);
            } catch (Exception $e) {
                if (!self::isInvalidReferenceException($e)) {
                    throw $e;
                }
                /**
                 * Goody, we're dealing with a hasAndBelongsToMany relationship here.
                 * Try to construct the intersection model and save the relation
                 * that way.
                 */
                return self::_unrelateHasAndBelongsToMany($options);
            }
        }

        /**
         * Figure out which model is leading. This depends on which of the two keys is provided.
         * This kind of flips the query around. For instance, when keyA is given, the query is
         * something like this:
         * UPDATE modelA SET foreignkey = NULL WHERE primarykey = keyA
         * When keyB is given however, the query goes something like this:
         * UPDATE modelA SET foreignkey = NULL WHERE foreignkey = keyB
         */
        $query = 'UPDATE `' . $modelA->getName() . '` SET ';
        $columnsToValues = array();
        foreach ($reference['columns'] as $column) {
            $columnsToValues[] = '`' . $column . '` = NULL';
        }
        $columnsToValues = implode(' AND ', $columnsToValues);
        $query .= $columnsToValues;
        $whereColumnsToValues = array();
        if ($options['keyA']) {
            $useColumns = 'refColumns';
            $useKeys = 'keyA';
        } else {
            $useColumns = 'columns';
            $useKeys = 'keyB';
        }
        foreach ($reference[$useColumns] as $i => $column) {
            $whereColumnsToValues[] = '`' . $column . '` = ' . $options[$useKeys][$i];
        }
        $whereColumnsToValues = implode(' AND ', $whereColumnsToValues);
        $query .= ' WHERE ';
        $query .= $whereColumnsToValues;

        return $modelA->getAdapter()->query($query);
    }
public static function unrelate($options) {
        self::_normalizeOptionsForUnrelate($options);
        $modelA  = $options['modelA'];
        $modelB  = $options['modelB'];

        /**
         * If bindingModel is set, we can safely skip all those difficult checks below.
         */
        if (is_object($options['bindingModel'])) {
            return self::_unrelateHasAndBelongsToMany($options);
        }
        try {
            /**
             * If this succeeds, it's a regular relationship where the foreign key
             * resides inside modelA. Continue as usual.
             */
            $reference = $modelA->getReference(get_class($modelB), $options['rule']);
        } catch (Exception $e) {
            if (!self::isInvalidReferenceException($e)) {
                throw $e;
            }
            try {
                /**
                 * If this succeeds, the foreign key resides in the modelA.
                 * Flip modelA and modelB and keyA and keyB in order to normalize the
                 * given configuration.
                 * Call self::relate() recursively with these new options.
                 */
                $reference = $modelB->getReference(get_class($modelA), $options['rule']);

                $keyA = $options['keyA'];
                $keyB = $options['keyB'];
                $options['modelA'] = $modelB;
                $options['modelB'] = $modelA;
                $options['keyA'] = $keyB;
                $options['keyB'] = $keyA;
                return Garp_Content_Relation_Manager::unrelate($options);
            } catch (Exception $e) {
                if (!self::isInvalidReferenceException($e)) {
                    throw $e;
                }
                /**
                 * Goody, we're dealing with a hasAndBelongsToMany relationship here.
                 * Try to construct the intersection model and save the relation
                 * that way.
                 */
                return self::_unrelateHasAndBelongsToMany($options);
            }
        }

        /**
         * Figure out which model is leading. This depends on which of the two keys is provided.
         * This kind of flips the query around. For instance, when keyA is given, the query is
         * something like this:
         * UPDATE modelA SET foreignkey = NULL WHERE primarykey = keyA
         * When keyB is given however, the query goes something like this:
         * UPDATE modelA SET foreignkey = NULL WHERE foreignkey = keyB
         */
        $query = 'UPDATE `' . $modelA->getName() . '` SET ';
        $columnsToValues = array();
        foreach ($reference['columns'] as $column) {
            $columnsToValues[] = '`' . $column . '` = NULL';
        }
        $columnsToValues = implode(' AND ', $columnsToValues);
        $query .= $columnsToValues;
        $whereColumnsToValues = array();
        if ($options['keyA']) {
            $useColumns = 'refColumns';
            $useKeys = 'keyA';
        } else {
            $useColumns = 'columns';
            $useKeys = 'keyB';
        }
        foreach ($reference[$useColumns] as $i => $column) {
            $whereColumnsToValues[] = '`' . $column . '` = ' . $options[$useKeys][$i];
        }
        $whereColumnsToValues = implode(' AND ', $whereColumnsToValues);
        $query .= ' WHERE ';
        $query .= $whereColumnsToValues;

        return $modelA->getAdapter()->query($query);
    }
public static function unrelate ( $ options ) { self :: _normalizeOptionsForUnrelate ( $ options ) ; $ modelA = $ options [ 'modelA' ] ; $ modelB = $ options [ 'modelB' ] ; /**
         * If bindingModel is set, we can safely skip all those difficult checks below.
         */ if ( is_object ( $ options [ 'bindingModel' ] ) ) { return self :: _unrelateHasAndBelongsToMany ( $ options ) ; } try { /**
             * If this succeeds, it's a regular relationship where the foreign key
             * resides inside modelA. Continue as usual.
             */ $ reference = $ modelA -> getReference ( get_class ( $ modelB ) , $ options [ 'rule' ] ) ; } catch ( Exception $ e ) { if ( ! self :: isInvalidReferenceException ( $ e ) ) { throw $ e ; } try { /**
                 * If this succeeds, the foreign key resides in the modelA.
                 * Flip modelA and modelB and keyA and keyB in order to normalize the
                 * given configuration.
                 * Call self::relate() recursively with these new options.
                 */ $ reference = $ modelB -> getReference ( get_class ( $ modelA ) , $ options [ 'rule' ] ) ; $ keyA = $ options [ 'keyA' ] ; $ keyB = $ options [ 'keyB' ] ; $ options [ 'modelA' ] = $ modelB ; $ options [ 'modelB' ] = $ modelA ; $ options [ 'keyA' ] = $ keyB ; $ options [ 'keyB' ] = $ keyA ; return Garp_Content_Relation_Manager :: unrelate ( $ options ) ; } catch ( Exception $ e ) { if ( ! self :: isInvalidReferenceException ( $ e ) ) { throw $ e ; } /**
                 * Goody, we're dealing with a hasAndBelongsToMany relationship here.
                 * Try to construct the intersection model and save the relation
                 * that way.
                 */ return self :: _unrelateHasAndBelongsToMany ( $ options ) ; } } /**
         * Figure out which model is leading. This depends on which of the two keys is provided.
         * This kind of flips the query around. For instance, when keyA is given, the query is
         * something like this:
         * UPDATE modelA SET foreignkey = NULL WHERE primarykey = keyA
         * When keyB is given however, the query goes something like this:
         * UPDATE modelA SET foreignkey = NULL WHERE foreignkey = keyB
         */ $ query = 'UPDATE `' . $ modelA -> getName ( ) . '` SET ' ; $ columnsToValues = array ( ) ; foreach ( $ reference [ 'columns' ] as $ column ) { $ columnsToValues [ ] = '`' . $ column . '` = NULL' ; } $ columnsToValues = implode ( ' AND ' , $ columnsToValues ) ; $ query .= $ columnsToValues ; $ whereColumnsToValues = array ( ) ; if ( $ options [ 'keyA' ] ) { $ useColumns = 'refColumns' ; $ useKeys = 'keyA' ; } else { $ useColumns = 'columns' ; $ useKeys = 'keyB' ; } foreach ( $ reference [ $ useColumns ] as $ i => $ column ) { $ whereColumnsToValues [ ] = '`' . $ column . '` = ' . $ options [ $ useKeys ] [ $ i ] ; } $ whereColumnsToValues = implode ( ' AND ' , $ whereColumnsToValues ) ; $ query .= ' WHERE ' ; $ query .= $ whereColumnsToValues ; return $ modelA -> getAdapter ( ) -> query ( $ query ) ; }
Unrelate records.

@param array|Garp_Util_Configuration $options Lots o' options:
'modelA'    string|Garp_Model_Db  The first model or classname thereof
'modelB'    string|Garp_Model_Db  The second model or classname thereof
'keyA'      mixed                 Primary key(s) of the first model
'keyB'      mixed                 Primary key(s) of the second model
'rule'      string                The rule that stores this relationship in one of the
reference maps
@return bool Success
Unrelate records .