How to pass an element in Crawler each function? - symfony

I parse my xml with Symfony's Crawler and cannot get how can I pass (other words continue) an element and not to include it into final array?
For example:
$node->filterXPath('//ExampleNode')->each(function(Crawler $child, $i) {
if (! count($child->filterXPath('//ChildNode'))) {
continue;
}
return $child->filterXPath('//ChildNode')->text();
});

You can use the Symfony\Component\DomCrawler\Crawler::reduce(Closure)
$crawler->reduce(function($result, $item) {
$childNodes = $item->filterXPath('//ChildNode');
if ($childNodes->count()) {
$result[] = $item;
}
});

Related

How to get Webform Element value into Custom Token

I create Custom Token and I want to get Webform Element and assign it to the Token, in my case the Element that I try to return is IP_ADDRESS , I tried to do the below and it didn't work:
use Drupal\webform\WebformSubmissionInterface;
function MODULE_token_info() {
// token info
}
function MODULE_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata, WebformSubmissionInterface $webform_submission = NULL) {
$ip = $webform_submission->getRemoteAddr();
$replacements = [];
if ($type == 'custom') {
foreach ($tokens as $name => $original) {
switch ($name) {
case 'order-cart':
$replacements[$original] = t('First Value');
break;
case 'city-token':
$replacements[$original] = getCity($ip);
break;
}
}
}
return $replacements;
}
I'm sure the $ip var is not the right way to retrieve Element value. also I don't wanna use the $_SERVER['REMOTE_ADDR'], I need to get the Submission Ip Address.
I'll appreciate the help, thanks

How do I modify wpDataTables cell values using filters?

In wpDataTables, I would like to modify (i.e. conditionally format) each cell value in a specific column for a specific table programmatically using PHP. How would I accomplish this?
First, install the Code Snippets plugin. Then create a new snippet set to "Run Snippet Everywhere" (required for JSON filtering) using the code below. It will filter both HTML and JSON. For more information, refer to wpDataTables - Filters.
function custom_wpdatatables_filter_initial_table_construct($tbl) {
// Edit below.
$table_name_to_modify = 'My Table Name';
$table_column_to_modify = 'my_table_column';
$cell_modification_function = function($value) {
return 'Modified: ' . $value;
};
// Check table name.
if ($tbl->getName() !== $table_name_to_modify) {
return $tbl;
}
$rows = $tbl->getDataRows();
foreach ($rows as &$row) {
if (array_key_exists($table_column_to_modify, $row)) {
$row['intermentobituary'] = $cell_modification_function($row['intermentobituary']);
}
}
$tbl->setDataRows($rows);
return $tbl;
}
add_filter('wpdatatables_filter_initial_table_construct', 'custom_wpdatatables_filter_initial_table_construct', 10, 1);
function custom_wpdatatables_filter_server_side_data($json, $tableId, $get) {
// Edit below.
$table_name_to_modify = 'My Table Name';
$table_column_to_modify = 'my_table_column';
$cell_modification_function = function($value) {
return 'Modified: ' . $value;
};
// Check table name.
$tableData = WDTConfigController::loadTableFromDB($tableId);
if (empty($tableData->content)) {
return $json;
} else if ($tableData->title !== $table_name_to_modify) {
return $json;
}
// Get columns.
$columns = [];
foreach ($tableData->columns as $column) {
// wdt_ID will be first column.
$columns[] = $column->orig_header;
}
// Modify column values.
$json = json_decode($json, true);
$rows = $json['data'];
foreach ($rows as $row_key => $row_value) {
foreach ($row_value as $row_attr_key => $row_attr_value) {
if ( ! empty($columns[$row_attr_key]) && $columns[$row_attr_key] === $table_column_to_modify) {
$rows[$row_key][$row_attr_key] = $cell_modification_function($row_attr_value);
}
}
}
$json['data'] = $rows;
return json_encode($json);
}
add_filter('wpdatatables_filter_server_side_data', 'custom_wpdatatables_filter_server_side_data', 10, 3);

Wordpress Display ACF only in first depth nav

I write function for display acf in menu.
I need to display only in depth [0].
All work. But i still to se terrible notice:
Notice: Undefined index: nav_menu_item_depth in
here is my code:
add_filter('acf/location/rule_types', 'acf_location_rules_types');
function acf_location_rules_types($choices)
{
$choices['Menu']['menu_level'] = 'Livello Menu';
return $choices;
}
add_filter('acf/location/rule_values/menu_level', 'acf_location_rule_values_level');
function acf_location_rule_values_level($choices)
{
$choices[0] = '0';
$choices[1] = '1';
return $choices;
}
add_filter('acf/location/rule_match/menu_level', 'acf_location_rule_match_level', 10, 4);
function acf_location_rule_match_level($match, $rule, $options, $field_group)
{
global $current_screen;
if ($current_screen->id == 'nav-menus') {
if ($rule ['operator'] == "==") {
$match = ($options['nav_menu_item_depth'] == $rule['value']); // <-- Problem is here
}
}
return $match;
}
Some can help me to understand?
Thanks
Ciao Paolo! It worked for me by adding an isset() check on $options['nav_menu_item_depth']. My guess is that this runs on the whole nav-menus page before hitting the nav-items.
function acf_location_rule_match_level($match, $rule, $options, $field_group)
{
global $current_screen;
if ($current_screen->id == 'nav-menus' && isset($options['nav_menu_item_depth'])) {
if ($rule ['operator'] == "==") {
$match = ($options['nav_menu_item_depth'] == $rule['value']); // <-- Problem is here
}
}
return $match;
}
I'm pretty new to WP so I'd love to hear if there is a better way to do this or if this is a bad idea for some reason.

dynamically populated cascading dropdown error

I found very useful article on the web
for contact form 7
<?php
function ajax_cf7_populate_values() {
// read the CSV file in the $makes_models_years array
$makes_models_years = array();
$uploads_folder = wp_upload_dir()['basedir'];
$file = fopen($uploads_folder.'\make_model_year.csv', 'r');
$firstline = true;
while (($line = fgetcsv($file)) !== FALSE) {
if ($firstline) {
$firstline = false;
continue;
}
$makes_models_years[$line[0]][$line[1]][] = $line[2];
}
fclose($file);
// setup the initial array that will be returned to the the client side script as a JSON object.
$return_array = array(
'makes' => array_keys($makes_models_years),
'models' => array(),
'years' => array(),
'current_make' => false,
'current_model' => false
);
// collect the posted values from the submitted form
$make = key_exists('make', $_POST) ? $_POST['make'] : false;
$model = key_exists('model', $_POST) ? $_POST['model'] : false;
$year = key_exists('year', $_POST) ? $_POST['year'] : false;
// populate the $return_array with the necessary values
if ($make) {
$return_array['current_make'] = $make;
$return_array['models'] = array_keys($makes_models_years[$make]);
if ($model) {
$return_array['current_model'] = $model;
$return_array['years'] = $makes_models_years[$make][$model];
if ($year) {
$return_array['current_year'] = $year;
}
}
}
// encode the $return_array as a JSON object and echo it
echo json_encode($return_array);
wp_die();
}
// These action hooks are needed to tell WordPress that the cf7_populate_values() function needs to be called
// if a script is POSTing the action : 'cf7_populate_values'
add_action( 'wp_ajax_cf7_populate_values', 'ajax_cf7_populate_values' );
add_action( 'wp_ajax_nopriv_cf7_populate_values', 'ajax_cf7_populate_values' );
and some java
<script>
(function($) {
// create references to the 3 dropdown fields for later use.
var $makes_dd = $('[name="makes"]');
var $models_dd = $('[name="models"]');
var $years_dd = $('[name="years"]');
// run the populate_fields function, and additionally run it every time a value changes
populate_fields();
$('select').change(function() {
populate_fields();
});
function populate_fields() {
var data = {
// action needs to match the action hook part after wp_ajax_nopriv_ and wp_ajax_ in the server side script.
'action' : 'cf7_populate_values',
// pass all the currently selected values to the server side script.
'make' : $makes_dd.val(),
'model' : $models_dd.val(),
'year' : $years_dd.val()
};
// call the server side script, and on completion, update all dropdown lists with the received values.
$.post('/wp-admin/admin-ajax.php', data, function(response) {
all_values = response;
$makes_dd.html('').append($('<option>').text(' -- choose make -- '));
$models_dd.html('').append($('<option>').text(' -- choose model -- '));
$years_dd.html('').append($('<option>').text(' -- choose year -- '));
$.each(all_values.makes, function() {
$option = $("<option>").text(this).val(this);
if (all_values.current_make == this) {
$option.attr('selected','selected');
}
$makes_dd.append($option);
});
$.each(all_values.models, function() {
$option = $("<option>").text(this).val(this);
if (all_values.current_model == this) {
$option.attr('selected','selected');
}
$models_dd.append($option);
});
$.each(all_values.years, function() {
$option = $("<option>").text(this).val(this);
if (all_values.current_year == this) {
$option.attr('selected','selected');
}
$years_dd.append($option);
});
},'json');
}
})( jQuery );
</script>
but when i add it to me website nothing appear in the dropdowns. They are empty.
I tried to contact the blogger but there is no answer yet. Give me some advice
I copied the csv almost as the one in the post. So I think the function is mistaken... somewhere
I found the solution: in the article the file name is mistaken. It has to be "make_model_year.csv" !!!

Symfony ignore 404 status code for get request

I have an application which allows users to create wishes. I use the title of each wish to make an api request to unsplash to download a picture. I now have the problem, that a user can enter a title which doesnt return any images from unsplash. In this case I'd like to use a placeholder image but my code stops after getting an 404 error. Is there a way to ignore this error and just continue my loop?
public function fetchImagesFromUnsplash() {
$wishes = $this->repository->findAll();
foreach ($wishes as $wish) {
try {
$response = $this->httpClient->request('GET', 'https://api.unsplash.com/photos/random', [
'query' => [
'query' => $wish->getDescription(),
'client_id' => 'oa1DsGebE8ehCV9SrvcA1mCx-2QfvnufUKgsIY5N0Mk'
]
]);
} catch (TransportExceptionInterface $e) {
}
if ($response) {
$data = $response->getContent();
$data = json_decode($data, true);
$imageLink = $data['urls']['raw'];
$rawImage = file_get_contents($imageLink);
if ($rawImage) {
file_put_contents("public/images/" . sprintf('imageWish%d.jpg', $wish->getId()), $rawImage);
$wish->setImagePath(sprintf('public/images/imageWish%d.jpg', $wish->getId()));
} else {
$wish->setImagePath('placeholder.png');
}
$this->em->flush();
}
}
}
EDIT:
I tried this:
public function fetchImagesFromUnsplash() {
$wishes = $this->repository->findAll();
foreach ($wishes as $wish) {
try {
$response = $this->httpClient->request('GET', 'https://api.unsplash.com/photos/random', [
'query' => [
'query' => $wish->getDescription(),
'client_id' => 'oa1DsGebE8ehCV9SrvcA1mCx-2QfvnufUKgsIY5N0Mk'
]
]);
} catch (NotFoundHttpException $e) {
}
if ($response) {
$data = $response->getContent();
$data = json_decode($data, true);
$imageLink = $data['urls']['raw'];
$rawImage = file_get_contents($imageLink);
if ($rawImage) {
file_put_contents("public/images/" . sprintf('imageWish%d.jpg', $wish->getId()), $rawImage);
$wish->setImagePath(sprintf('public/images/imageWish%d.jpg', $wish->getId()));
} else {
$wish->setImagePath('placeholder.png');
}
}
}
$this->em->flush();
}
but it still stops after the first 404
As per the documentation:
When the HTTP status code of the response is in the 300-599 range
(i.e. 3xx, 4xx or 5xx) your code is expected to handle it. If you
don't do that, the getHeaders() and getContent() methods throw an
appropriate exception
You have to check the $response->getStatusCode(), or prepare to handle a ClientException (representing 4xx status codes).

Resources