usuario1818018
Por ejemplo, tengo este tipo de código:
<?php
/**
* Order
*
* The WooCommerce order class handles order data.
*
* @class WC_Order
* @version 1.6.4
* @package WooCommerce/Classes
* @category Class
* @author WooThemes
*/
class WC_Order {
/** @public int Order (post) ID */
public $id;
/** @public string Order status. */
public $status;
/** @public string Order date (placed). */
public $order_date;
/** @public string Order date (paid). */
public $modified_date;
/** @public string Note added by the customer. */
public $customer_note;
/** @public array Order (post) meta/custom fields. */
public $order_custom_fields;
global $wpdb, $woocommerce;
if ( empty( $type ) )
$type = array( 'line_item' );
if ( ! is_array( $type ) )
$type = array( $type );
$items = $this->get_items( $type );
$count = 0;
foreach ( $items as $item ) {
if ( ! empty( $item['qty'] ) )
$count += $item['qty'];
else
$count ++;
}
return apply_filters( 'woocommerce_get_item_count', $count, $type, $this );
}
/**
* Return an array of fees within this order.
*
* @access public
* @return array
*/
public function get_fees() {
return $this->get_items( 'fee' );
}
/**
* Return an array of taxes within this order.
*
* @access public
* @return void
*/
public function get_taxes() {
return $this->get_items( 'tax' );
}
/**
* Get taxes, merged by code, formatted ready for output.
*
* @access public
* @return void
*/
public function get_tax_totals() {
$taxes = $this->get_items( 'tax' );
$tax_totals = array();
foreach ( $taxes as $key => $tax ) {
$code = $tax[ 'name' ];
if ( ! isset( $tax_totals[ $code ] ) ) {
$tax_totals[ $code ] = new stdClass();
$tax_totals[ $code ]->amount = 0;
}
$tax_totals[ $code ]->is_compound = $tax[ 'compound' ];
$tax_totals[ $code ]->label = isset( $tax[ 'label' ] ) ? $tax[ 'label' ] : $tax[ 'name' ];
$tax_totals[ $code ]->amount += $tax[ 'tax_amount' ] + $tax[ 'shipping_tax_amount' ];
$tax_totals[ $code ]->formatted_amount = woocommerce_price( $tax_totals[ $code ]->amount );
}
return apply_filters( 'woocommerce_order_tax_totals', $tax_totals, $this );
}
/**
* has_meta function for order items.
*
* @access public
* @return array of meta data
*/
public function has_meta( $order_item_id ) {
global $wpdb;
return $wpdb->get_results( $wpdb->prepare("SELECT meta_key, meta_value, meta_id, order_item_id
FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id = %d
ORDER BY meta_key,meta_id", absint( $order_item_id ) ), ARRAY_A );
}
/**
* Get order item meta.
*
* @access public
* @param mixed $item_id
* @param string $key (default: '')
* @param bool $single (default: false)
* @return void
*/
public function get_item_meta( $order_item_id, $key = '', $single = false ) {
return get_metadata( 'order_item', $order_item_id, $key, $single );
}
Quiero hacer coincidir todos los ganchos de WordPress: “do_action” y “apply_filters” con tres opciones: apply_filters (‘woocommerce_order_tax_totals’, $tax_totals, $this), archivo, número de línea
Un ejemplo de lo que estoy tratando de hacer se puede ver aquí:
http://etivite.com/api-hooks/buddypress/trigger/apply_filters/bp_get_total_mention_count_for_user/
http://adambrown.info/p/wp_hooks/hook/activated_plugin?version=3.6&file=wp-admin/includes/plugin.php
Intenté sacar algo pero sin éxito:
<?php
$path = $_SERVER['DOCUMENT_ROOT'] . '/wp-content/plugins/iphorm-form-builder';
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) {
if (substr($filename, -3) == 'php') {
$file = file($filename);
if ($file !== false) {
$matches1 = preg_grep( '/do_action\((.+)\);/', $file);
$matches2 = preg_grep( '/apply_filters\((.+)\);/', $file );
$arr = array_filter(array_merge($matches1, $matches2));
$out="";
echo "found in $filename:";
echo "<pre>";
foreach ($arr as $key => $value) {
$out .= $file[$key-2];
$out .= $file[$key-1];
$out .= $file[$key];
$out .= $file[$key+1];
$out .= $file[$key+2];
}
echo htmlentities($out);
echo "</pre>";
} else {
echo "failed reading to array";
}
}
}
joe frambach
Esto se puede hacer de manera muy simple aprovechando los comandos de shell incorporados.
<?php
$path = $_SERVER['DOCUMENT_ROOT'] . '/wp-content/plugins/iphorm-form-builder';
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) {
if (substr($filename, -3) == 'php') {
$context = shell_exec('grep -H -n -C4 do_action ' . escapeshellarg($filename));
if (!empty($context)) {
echo "found in $filename:";
echo "<pre>";
echo htmlentities($context);
echo "</pre>";
} else {
echo "failed reading to array";
}
}
}
Documentación relevante:
Ejecute el comando a través de Shell y devuelva la salida completa como una cadena
Escape de una cadena para usarla como argumento de shell
Grep searches the named input FILEs (or standard input if no files are named, or the file name - is given) for lines containing a match to the given PATTERN. By default, grep prints the matching lines. -C NUM, --context=NUM Print NUM lines of output context. Places a line containing -- between contiguous groups of matches. -H, --with-filename Print the filename for each match. -n, --line-number Prefix each line of output with the line number within its input file.
Editar
Dependiendo de cuántos directorios y archivos tenga en su proyecto, es posible que no funcione. Básicamente, está creando un nuevo proceso en un nuevo shell para cada archivo. Eso no es genial. Si prefiere obtener una gran cantidad de datos y analizarlos más tarde, haga esto en su lugar:
<?php
$path = $_SERVER['DOCUMENT_ROOT'] . '/wp-content/plugins/iphorm-form-builder';
$grep = shell_exec('grep --include=*.php -RHn -C4 do_action ' . escapeshellarg($path));
$matches = explode("\n--\n", $grep);
if (empty($matches)) {
echo "failed reading to array";
}
else {
foreach ($matches as $match) {
echo "<pre>";
echo htmlentities($match);
echo "</pre>";
}
}
-
Vaya, esto es genial, estoy creando un complemento ahora mismo 🙂 El directorio de contenido puede estar en cualquier lugar, si se usa en el contexto de WP, esto es más a prueba de balas:
$path = WP_CONTENT_DIR . '/plugins/plugin-name';
– brasofilo
20 de septiembre de 2013 a las 16:38
-
Hola Joe, perdón por la demora, no estuve cerca de una computadora por mucho tiempo 🙂 ¡Muchas gracias!
– usuario1818018
6 oct 2013 a las 9:33
anubhava
No necesita recorrer los datos del archivo línea por línea. Simplemente lea los datos en una variable y aplique expresiones regulares:
$data = file_get_contents( $filename );
if (preg_match_all(
'~((?:[^\n]*\n){0,4}) *do_action\s*\(\s*([^)]+)\s*\)\s*;[^\n]*\n((?:[^\n]*\n){0,4})~',
$data, $arr)) {
// match found, now dump the results
// $arr[1] will print 4 lines before the match
// $arr[2] will print function arguments for do_action
// $arr[3] will print 4 lines after the match
print_r($arr);
}
-
@JoeFrambach: Sí, de hecho
$arr[3] will print 4 lines after the match
y tiene razón sobre las primeras 4 líneas del archivo, verifique la edición ahora.– anubhava
18/09/2013 a las 20:38
Daniel Giménez
Esto no se puede hacer solo con expresiones regulares dadas las limitaciones del motor de expresiones regulares de PHP. Específicamente, y me sorprendió, no puedes tener traseros de longitud variable.
La razón por la que necesita mirar atrás es si tuvo la ocurrencia de hacer_acción o aplicar_filtros en líneas consecutivas, entonces la primera coincidencia evitará la segunda coincidencia si no tiene una mirada hacia adelante, e incluso si usa una mirada hacia adelante, no hay forma de obtener las dos filas anteriores de la segunda coincidencia sin la mirada hacia atrás. Sin mencionar que ni siquiera sé si puede incluir el contenido de una afirmación de mirar alrededor en el resultado.
Esta solución crea una expresión regular para encontrar las líneas en las que ocurre la función y luego usa dos expresiones regulares más para encontrar las líneas antes y después. Tuve cuidado de tener cuidado con el inicio y el final del archivo al diseñar las expresiones regulares.
$offset = 0;
while (preg_match('/^.*?(?:apply_filters|do_action)\s*\(.+?\)\s*;.*(?:\n\r|\n|\r|$)/m', $file, $match, PREG_OFFSET_CAPTURE, $offset))
{
$index = $match[0][1];
$offset = $index + strlen($match[0][0]);
$hasBefore = preg_match('/(?:.*(?:\n\r|\n|\r).*$)|[^\n\r].*$/',
substr($file, 0, $index), $beforeMatch);
$hasAfter = preg_match('/^(?:.*(?:\n\r|\n|\r|$)){0,2}/',
substr($file, $offset), $afterMatch);
if ($hasBefore) print_r($beforeMatch);
print_r($match[0][0]);
if ($hasAfter) print_r($afterMatch);
}
phpviolín
Esto solo muestra dos líneas antes y dos líneas después. Puede usar la repetición si quiere más, pero me parece, por el intento de solución, que esto era lo que realmente quería el operador.
Consulte este hilo para obtener algunos consejos sobre cómo obtener más atención para preguntas antiguas: meta.stackexchange.com/questions/7046/…
– Adán Lear
♦
18/09/2013 a las 15:30
¿Cuál es el resultado esperado para el código de ejemplo que ha dado?
-Joe Frambach
18 de septiembre de 2013 a las 16:16
Ah, creo que lo entiendo. La terminología que necesita es “contexto”. Quiere una línea emparejada, con 4 líneas de contexto.
-Joe Frambach
18/09/2013 a las 20:26
WTF??
global $wpdb, $woocommerce;
en una clase– Elías Van Ootegem
20 de septiembre de 2013 a las 12:13
@EliasVanOotegem bienvenido a wordpress. Comprueba tu cordura en la puerta.
-Joe Frambach
20/09/2013 a las 15:25