ndex, $zones ) { $in = false; foreach ( $zones as $zone ) { if ( $index >= $zone['_a'] && $index <= $zone['_z'] ) { $in = true; } } return $in; } function _makeBaseTree( &$_tree, $inzones ) { $sqlU = str_replace( '_', 'U', substr( $this->_sql, $inzones['_a'], $inzones['_z'] - $inzones['_a'] ) ); $this->_lexs[ $inzones['_a'] ] = str_word_count( $sqlU, 2 ); $deep = 0; $branch[ $deep ] = 'SQL'; foreach ( $this->_lexs[ $inzones['_a'] ] as $index => $candidate_rule ) { $index += $inzones['_a']; if ( in_array( $candidate_rule, $this->_list_base_rules ) && $this->_inZone( $index, $inzones['out'] ) && $this->_inZone( $index, $this->_zonesQ['out'] ) ) { while ( ! isset( $this->_base_rules[ $branch[ $deep ] ] ) ) { unset( $branch[ $deep ] ); $deep --; } while ( ! in_array( $candidate_rule, $this->_base_rules[ $branch[ $deep ] ] ) ) { unset( $branch[ $deep ] ); $deep --; if ( $deep < 0 ) { exit; } } if ( in_array( $candidate_rule, $this->_base_rules[ $branch[ $deep ] ] ) ) { $deep ++; $branch[ $deep ] = $candidate_rule; $monkey = &$_tree; foreach ( $branch as $key => $value ) { $monkey = &$monkey[ $value ]; } $monkey['_a'] = $index + strlen( $candidate_rule ); if ( isset( $oldmonkey ) ) { $oldmonkey['_z'] = $index - 1; $oldmonkey['_SQL'] = substr( $this->sql, $oldmonkey['_a'], $oldmonkey['_z'] - $oldmonkey['_a'] ); } $oldmonkey = &$monkey; } } } $oldmonkey['_z'] = $inzones['_z']; $oldmonkey['_SQL'] = substr( $this->sql, $oldmonkey['_a'], $inzones['_z'] - $oldmonkey['_a'] ); } function _makeInterBranches( $inter_rule_key, $inter_rule_val, $begin, $end, $outzones ) { $poses = Array(); $length_rule = strlen( $inter_rule_val ); $lr = 0; $min_lr = 0; if ( substr( $this->_sql, $begin, 1 ) == '(' ) { $min_lr = 1; } if ( $inter_rule_val != '' ) { $pos = strpos( $this->_sql, $inter_rule_val, $begin ); while ( $pos !== false ) { if ( $this->_inZone( $pos, $outzones ) && $this->_inZone( $pos, $this->_zonesQ['out'] ) && $pos < $end ) { $poses[] = $pos; } $sbegin = $pos + 1; $pos = strpos( $this->_sql, $inter_rule_val, $sbegin ); } } $i = 0; $last_pos = $begin; foreach ( $poses as $pos ) { if ( ! in_array( trim( substr( $this->_sql, $last_pos + $lr, $pos - $last_pos - $lr ) ), $this->_noval_rules ) ) { $lr = ( $i > 0 ? $length_rule : $min_lr ); $inter_branches[ $i . '|' . $inter_rule_key ] = Array( '_a' => $last_pos, '_z' => $pos, '_SQL' => str_repeat( ' ', $lr ) . substr( $this->sql, $last_pos + $lr, $pos - $last_pos - $lr ) ); $last_pos = $pos; $i ++; } } if ( ! in_array( trim( substr( $this->_sql, $last_pos + $lr, $end - $last_pos - $lr ) ), $this->_noval_rules ) ) { $lr = ( $i > 0 ? $length_rule : $min_lr ); $inter_branches[ $i . '|' . $inter_rule_key ] = Array( '_a' => $last_pos, '_z' => $end, '_SQL' => str_repeat( ' ', $lr ) . substr( $this->sql, $last_pos + $lr, $end - $last_pos - $lr ) ); } return $inter_branches; } function _makeInterTree( &$_tree, $outzones ) { foreach ( $_tree as $branch_rule => $sub_tree ) { if ( $branch_rule != '_a' && $branch_rule != '_z' && $branch_rule != '_SQL' ) { $found_rule = false; $pur_rule = $branch_rule; if ( array_key_exists( $pur_rule, $this->_inter_rules ) ) { $found_rule = true; } else { $rules = explode( '|', $branch_rule, 2 ); if ( is_numeric( substr( $rules[0], 0, 1 ) ) ) { $pur_rule = $rules[1]; } if ( array_key_exists( $pur_rule, $this->_inter_rules ) ) { $found_rule = true; } } if ( $found_rule ) { foreach ( $this->_inter_rules[ $pur_rule ] as $inter_rule_key => $inter_rule_val ) { if ( is_numeric( $sub_tree['_a'] ) && is_numeric( $sub_tree['_z'] ) ) { $new_branches = $this->_makeInterBranches( $inter_rule_key, $inter_rule_val, $sub_tree['_a'], $sub_tree['_z'], $outzones ); if ( count( $new_branches ) > 1 || substr( $inter_rule_key, 0, 1 ) != '!' ) { if ( is_array( $new_branches ) ) { $_tree[ $branch_rule ] += $new_branches; } if ( substr( $inter_rule_key, 0, 1 ) == '!' ) { break; } } } } } $this->_makeInterTree( $_tree[ $branch_rule ], $outzones ); } } } function _makeChildsTree( &$_tree, $parents, &$inzones ) { foreach ( $_tree as $branch => $sub_tree ) { if ( $branch == '_SQL' && count( $_tree ) < 4 ) { $child = substr( $this->_sql, $_tree['_a'], $_tree['_z'] - $_tree['_a'] ); if ( strlen( $child ) > 0 ) { $pos = strpos( $child, '(', 1 ); if ( $pos !== false ) { $pos += $_tree['_a']; if ( isset( $inzones[ $pos ] ) ) { $new_tree = Array(); $this->_makeBaseTree( $new_tree, $inzones[ $pos ] ); if ( empty( $new_tree ) ) { unset( $new_tree ); // remontée récurcive jusqu'à la dernière base rule preg_match( '/([A-Z]+)\(/', substr( $this->_sql, $_tree['_a'], $pos - $_tree['_a'] + 1 ), $agr ); if ( isset( $agr[1] ) ) { $p = $agr[1]; $this->_inter_rules[ $p ] = Array( '*' . $p => ',' ); $this->_inter_rules[ '*' . $p ] = $this->_as; } else { $n = count( $parents ); while ( $n > 0 ) { if ( in_array( $parents[ $n ], $this->_list_base_rules ) ) { $p = $parents[ $n ]; $n = 0; } $n --; } } $new_tree[ $p ]['_a'] = $inzones[ $pos ]['_a']; $new_tree[ $p ]['_z'] = $inzones[ $pos ]['_z']; $new_tree[ $p ]['_SQL'] = ' ' . substr( $this->sql, $inzones[ $pos ]['_a'] + 1, $inzones[ $pos ]['_z'] - ( $inzones[ $pos ]['_a'] + 1 ) ); $parents = Array( 'SQL' ); } else { $parents[] = $branch; } $this->_makeInterTree( $new_tree, $inzones[ $pos ]['out'] ); $this->_makeChildsTree( $new_tree, $parents, $inzones[ $pos ] ); $_tree += $new_tree; } } } } elseif ( $branch != '_SQL' && $branch != '_a' && $branch != '_z' ) { $parents[] = $branch; $this->_makeChildsTree( $_tree[ $branch ], $parents, $inzones ); } } } function _reduceTree( &$_tree ) { while ( list( $branch, $sub_tree ) = each( $_tree ) ) { if ( $branch != '_SQL' && $branch != '_a' && $branch != '_z' ) { $this->_reduceTree( $_tree[ $branch ] ); if ( array_key_exists( '_a', $_tree ) && $_tree['_a'] == $sub_tree['_a'] && $_tree['_z'] == $sub_tree['_z'] && count( $_tree ) < 5 ) { $_tree = $sub_tree; } } } } function _makeAdvanceTree( &$_tree, $parent, $grand_parent ) { foreach ( (Array) $_tree as $branch => $sub_tree ) { if ( $branch == '_SQL' ) { if ( count( $_tree ) < 4 ) { $sub_tree = str_replace( "\r", ' ', $sub_tree ); $sub_tree = str_replace( "\n", ' ', $sub_tree ); if ( substr( $parent, - 2 ) == 'AS' ) { $_parent = $grand_parent; } else { $_parent = $parent; } $rules = explode( '|', $_parent, 2 ); if ( is_numeric( substr( $rules[0], 0, 1 ) ) ) { $num_rule = $rules[0]; $pur_rule = $rules[1]; } else { $num_rule = 0; $pur_rule = $rules[0]; } if ( $num_rule == 0 || substr( $pur_rule, 0, 1 ) != '!' ) { $subs = explode( ' ', $sub_tree ); $sub_tree = ''; if ( ! isset( $this->_sheet_rules[ $pur_rule ] ) ) { $this->_sheet_rules[ $pur_rule ] = Array(); } foreach ( $subs as $sub ) { $subU = strtoupper( $sub ); if ( ! in_array( $subU, $this->_noval_rules ) ) { if ( in_array( $subU, $this->_sheet_rules[ $pur_rule ] ) ) { $_tree[ $sub ] = $sub; } else { $sub_tree .= $sub . ' '; } } } } $lsub_tree = trim( $sub_tree ); if ( in_array( $pur_rule, $this->_table_rules ) ) { $_tree['TABLE'] = $lsub_tree; } elseif ( is_numeric( $lsub_tree ) || substr( $lsub_tree, 0, 1 ) == "'" ) { $_tree['VAL'] = $lsub_tree; } else { $lsubs = explode( '.', $lsub_tree ); if ( count( $lsubs ) > 1 ) { $_tree['TABLE'] = $lsubs[0]; $_tree['FIELD'] = $lsubs[1]; } else { $_tree['FIELD'] = str_replace( ',', '', $lsub_tree ); } } } unset( $_tree['_SQL'] ); unset( $_tree['_a'] ); unset( $_tree['_z'] ); } elseif ( $branch != '_SQL' && $branch != '_a' && $branch != '_z' ) { $this->_makeAdvanceTree( $_tree[ $branch ], $branch, $parent ); } } } function make() { $this->_reformatQuery(); $this->_zonesQuote(); $this->_zonesParenthesis(); $this->_makeBaseTree( $this->_tree, $this->_zonesP_tree ); $this->_makeInterTree( $this->_tree['SQL'], $this->_zonesP_tree['out'] ); $this->_makeChildsTree( $this->_tree['SQL'], Array( 'SQL' ), $this->_zonesP_tree ); $this->_reduceTree( $this->_tree ); $this->_makeAdvanceTree( $this->_tree, 'SQL', '' ); return $this->_tree; } }