ここで複数のタグのサポートなどを追加するのはとても簡単なので、これはかなり無駄になります。どちらの方法でも、完全に吹き飛ばされたツリー解析を行う必要があります。
無効な入力は一切処理されないことに注意してください。タグは適切にバランスを取る必要があります
function get_node_contents( $node ) {
    $orig = $node;
    $ret = "[code]" . $node->content;
    if( @$node->children ) {
        foreach( $node->children as $node ) {
            $ret .= get_node_contents( $node );
        }
    }
    if( @$orig->endContent ) {
        $ret .= $orig->endContent;
    }
    return $ret."[/code]";
}
function reduce_depth( $str, $maxDepth = 4 ) {
    $index = 0;
    $len = strlen( $str );
    $reg = '/(\[code\]|\[\/code\])/';
    $root = new stdClass;
    $root->children = array();
    $depth = 0;
    $ret = "";
    $pos = strpos( $str, "[code]" );
    if( $pos ) {
        $ret .= substr( $str, 0, $pos - 0);
    }
    while( $index < $len  ) {
        if( !preg_match( $reg, $str, $matches, PREG_OFFSET_CAPTURE, $index )) {
            break;
        }
        $index = ( $matches[1][1] + strlen( $matches[1][0] ) );
        $tag = $matches[1][0];
        $next = preg_match( $reg, $str, $matches, PREG_OFFSET_CAPTURE, $index );
        $content = "";
        if( $next ) {
            $content = substr( $str, $index, $matches[1][1] - $index );
        }
        if( $tag === "[code]" ) {
            if( $depth === 0 ) {
                $parent = $root->children[] = new stdClass;
                $parent->content = $content;
                $depth++;
            }
            else if ( $depth++ > $maxDepth ) {
                continue;
            }
            else {
                if( !@$parent->children ) {
                    $parent->children = array();
                }
                $child = $parent->children[] = new stdClass;
                $child->content = $content;
                $child->parent = $parent;
                $parent = $child;
            }        
        }
        else {                
            $depth--;
            if( @$parent->parent ) {
                $parent = $parent->parent;
            }
            if( @$content ) {
                $parent->endContent = $content;
            }                
        }
    }
    foreach( $root->children as $node ) {
        $ret .= get_node_contents( $node );
    }
    $ret .= substr( $str, $index, $len - $index );
    return $ret;
}
echo reduce_depth( "asdasdas[code]l[/code][code]a[code]lol[/code][code]b[code]c[code]d[code]e[code]f[code]g[/code][/code][/code][/code][/code][/code][/code]aasdasdsasd", 4 ). "\n";
echo reduce_depth( "[code]a[code]b[code]c[code]d[code]e[code]f[code]g[/code][/code][/code][/code][/code][/code][/code]", 4 ) . "\n";
echo reduce_depth( "[code]a[code]b[code]c[code]d[code]TEST[/code][code]e[code]f[code]g[/code][/code][/code][/code][/code][/code][/code]", 4 ) . "\n";
echo reduce_depth("[code][code]bugi[/code]bugi2[/code]", 1) . "\n"; 
echo reduce_depth("[code][code]bugi[/code]bugi2[code]bugi3[/code]bugi4[code]bugi5[/code]bugi6[/code]", 3) . "\n"; 
/*
    asdasdas[code]l[/code][code]a[code]lol[/code][code]b[code]c[code]d[code]e[/code][/code][/code][/code][/code]aasdasdsasd
    [code]a[code]b[code]c[code]d[code]e[/code][/code][/code][/code][/code]
    [code]a[code]b[code]c[code]d[code]TEST[/code][code]e[/code][/code][/code][/code][/code]
    [code][code]bugi[/code]bugi2[/code]
    [code][code]bugi[/code][code]bugi3[/code][code]bugi5[/code]bugi6[/code]
*/