I have following function:
public function id_callback($idnumber){}
And I call it this way:
for($i = 1; $i <= $fieldcount; $i++)
{
add_settings_field(
'id' . $i,
'ID' . $i,
array( $this, 'id_callback' ),
'my-setting-admin',
'setting_section_id'
);
}
How can I pass $i as an argument to id_callback?
Thanks in advance.
Your code is a little abstract, as it does not come with a specific context, however i'll try to help you. You basically have to create a variable and a method that sets that variable. Then you should use that method to change the variable in the for loop. Here is a quick example of what i'm talking about (i've created an example class that replicates a simple use case):
<?php
class Example_Callback {
public $id_callback;
public function set_id_callback($id_callback) {
$this->id_callback = $id_callback;
}
public function do_something() {
// here is your $i:
$callback_id = $this->id_callback;
// here you can do something with your $callback_id
}
public function test() {
$fieldcount = 5; // usually this should come from somewhere
for($i = 1; $i <= $fieldcount; $i++) {
$this->set_id_callback($i);
add_settings_field(
'id' . $i,
'ID' . $i,
array( $this, 'do_something' ),
'my-setting-admin',
'setting_section_id'
);
}
}
}
$callback = new Example_Callback();
$callback->test();
?>
Related
I am new in Drupal.
I am using imagemagick plugin for modify images. My problem is when it resize GIF image the image got messed up. I search the solution on internet i found the changes regarding that.
but i don't want to write code changes directly to plugins module file.
I want to override it's image_imagemagick_resize() function. I can not figure out how to Override it and where to put it's override function.
Default Function :-
function image_imagemagick_resize(stdClass $image, $width, $height) {
$image->ops[] = '-resize ' . (int) $width . 'x' . (int) $height . '!';
$image->info['width'] = $width;
$image->info['height'] = $height;
return TRUE;
}
Override Function:
function imageapi_imagemagick_image_resize(&$image, $width, $height) {
$extra = '';
if($image->info['mime_type'] == 'image/gif') {
$extra = '-coalesce ';
}
$image->ops[] = $extra . '-resize '. (int) $width .'x'. (int) $height .'!';
$image->info['width'] = $width;
$image->info['height'] = $height;
return TRUE;
}
Thanks
Hopefully image_imagemagick_resize invokes alter hooks via _image_imagemagick_alter_invoke :
function image_imagemagick_resize($source, $dest, $width, $height) {
$args = array('resize' => '-resize ' . (int) $width . 'x' . (int) $height . '!');
$args = _image_imagemagick_alter_invoke('resize', $source, $args);
return _image_imagemagick_convert($source, $dest, $args);
}
function _image_imagemagick_alter_invoke($op, $filepath, $args) {
foreach (module_implements('imagemagick_alter') as $module) {
$function = $module . '_imagemagick_alter';
$function($op, $filepath, $args);
}
return $args;
}
So you can override the resize parameters by implementing the hook_imagemagick_alter() in a custom module :
function mymodule_imagemagick_alter($op, $filepath, &$args) {
# altering $args...
}
I've just installed Polylang (Free version) and I have field group that is set to be displayed on front-page.
In the admin, fields are displaying correctly on the main language's front page but not on the translated front-page.
I've searched to see what could go wrong and it's obviously because of ACF that is only checking if we are on the front page with get_option('page_on_front').
And polylang doesn't seems to filter the value to set the right front-page.
So I found this mu-plugin:
<?php
class ACF_Page_Type_Polylang {
// Whether we hooked page_on_front
private $filtered = false;
public function __construct() {
add_filter( 'acf/location/rule_match/page_type', array( $this, 'hook_page_on_front' ) );
}
public function hook_page_on_front( $match ) {
if ( ! $this->filtered ) {
add_filter( 'option_page_on_front', array( $this, 'translate_page_on_front' ) );
// Prevent second hooking
$this->filtered = true;
}
return $match;
}
public function translate_page_on_front( $value ) {
if ( function_exists( 'pll_get_post' ) ) {
$value = pll_get_post( $value );
}
return $value;
}
}
new ACF_Page_Type_Polylang();
but it does not resolve the issue and i don't know why, the code seems correct.
If I only take this part :
add_filter( 'option_page_on_front', array( $this, 'translate_page_on_front' ) );
and convert it to :
add_filter( 'option_page_on_front',function() { return '346' });
(346 is the translated front-page ID)
it filters properly the option page_on_front and my fields are displaying correctly.
Can you help me make the mu-plugin works ?
I've found a way to make it work but I don't know if it's the right way ... can you please tell me ?
<?php
class ACF_Page_Type_Polylang {
// Whether we hooked page_on_front
private $filtered = false;
public function __construct() {
add_filter( 'acf/location/rule_match/page_type', array( $this, 'hook_page_on_front' ) );
}
public function hook_page_on_front( $match ) {
// Abort if polylang not activated
if ( !function_exists( 'pll_get_post' ) ) {
return $match;
}
// Get the main language front page
$front_page = (int) get_option('page_on_front');
// Get the translated page of the curent language
$translated_page = pll_get_post($front_page);
// Check if it's the same as the current page and set match to true if so
if($translated_page === get_the_id()) {
$match = true;
}
return $match;
}
}
new ACF_Page_Type_Polylang();
How can I create a production collection based on pricerange in Magento 2.
This is what i have so far:
<?php namespace Qxs\Related\Block;
class Related extends \Magento\Framework\View\Element\Template
{
protected $_productCollectionFactory;
public function __construct(
\Magento\Backend\Block\Template\Context $context,
\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory,
\Magento\Catalog\Model\Product\Attribute\Source\Status $productStatus,
\Magento\Catalog\Model\Product\Visibility $productVisibility,
array $data = []
)
{
$this->_productCollectionFactory = $productCollectionFactory;
$this->productStatus = $productStatus;
$this->productVisibility = $productVisibility;
parent::__construct($context, $data);
}
public function getProductCollection()
{
//var_dump($this->currentProduct());
$collection = $this->_productCollectionFactory->create();
$collection->addAttributeToSelect('*')
->addAttributeToFilter('special_price', ['from' => 0, 'to' => 1000])
->addAttributeToFilter('status', ['in' => $this->productStatus->getVisibleStatusIds()])
->setVisibility($this->productVisibility->getVisibleInSiteIds())
->setPageSize(5);
return $collection;
}
public function currentProduct()
{
return $this->_coreRegistry->registry('product');
}
}
?>
However, the code does not return a result including a price range. The result is totally empty but should return some products, how can I filter on price-range?
Thanks,
Range filters, to me work in this way, with addFieldToFilter. Have you tried it?
$orders = $this->_orderCollectionFactory->create()
->addAttributeToSelect('*')
->addFieldToFilter( 'created_at' , array('from' => $dateFrom, 'to' => $dateTo) )
->setOrder('created_at', 'desc' );
->setPageSize(200);
I have the following class:
class Foo
{
public function importBars(array $array)
{
foreach ($array as $key => $value) {
$this->importBar($key, $value);
}
}
public function importBar($key, $value)
{
// do stuff
}
}
I need to test that importBar is called count($array) times, and that it's called with the right parameters. Using $this->at() is not an option, as the order of the $array elements might change. I have:
public function testImportBars(array $array)
{
// Mock invocation ...
$logicalOrs = array();
foreach ($array as $sku => $value) {
$logicalOrs[] = $this->logicalOr($this->equalTo($key), $this->equalTo($value));
}
$mock->expects($this->exactly(count($array)))
->method('importBar')
->with(call_user_func_array(array($this, 'logicalOr'), $logicalOrs));
}
Which passes the tests. However, when I deliberately make it fail:
foreach ($array as $sku => $value) {
$logicalOrs[] = $this->logicalOr($this->equalTo($key), $this->equalTo(null));
}
... it still passes. It only fails if the $key is incorrect:
foreach ($array as $sku => $value) {
$logicalOrs[] = $this->logicalOr($this->equalTo(null), $this->equalTo(null));
}
... which suggests PHPUnit is only checking if the first parameter passed to Foo::importBar() is correct.
Is there a way to tell PHPUnit to verify arguments to methods when there is more than one?
After some trial and error, here is the closest solution I've come up with:
$rows = array();
foreach ($array as $key => $value) {
$rows[] = array($key, $value);
}
$method = $mock->expects($this->exactly(count($array)))
->method('importBar');
call_user_func_array(array($method, 'withConsecutive'), $rows);
See: http://phpunit.de/manual/4.1/en/test-doubles.html#test-doubles.mock-objects
Apparently the GridFieldExportButton only exports the currently visible data-set (paginated). Is there a way to make it export all the rows from a model?
Or alternatively: Is there a way to show all rows (eg. bypass pagination), so that the user can perform an export after showing all the rows? I don't want to show all rows all the time (which would probably be possible by setting ModelAdmin::set_page_length(<ridiculouslyHighNumber>);) but only on demand.
You can override ModelAdmin::getExportFields() to define the columns you want to export.
The method needs to return an array with column name as the key, and the db field as the value.
For example:
class MyCustomModelAdmin extends ModelAdmin {
....
public function getExportFields() {
return array(
'FirstName' => 'FirstName',
'Surname' => 'Surname',
'Age' => 'Age'
);
}
}
Solved it by creating a custom subclass of the GridFieldExportButton and using this for my models. The key is to use $gridField->getList(); instead of $gridField->getManipulatedList(); in the generateExportFileData method.
Here's the complete class for anybody interested:
class GridFieldExportAllButton extends GridFieldExportButton {
/**
* Generate export fields for CSV.
*
* #param GridField $gridField
* #return array
*/
public function generateExportFileData($gridField) {
$separator = $this->csvSeparator;
$csvColumns = ($this->exportColumns)
? $this->exportColumns
: singleton($gridField->getModelClass())->summaryFields();
$fileData = '';
$columnData = array();
$fieldItems = new ArrayList();
if($this->csvHasHeader) {
$headers = array();
// determine the CSV headers. If a field is callable (e.g. anonymous function) then use the
// source name as the header instead
foreach($csvColumns as $columnSource => $columnHeader) {
$headers[] = (!is_string($columnHeader) && is_callable($columnHeader)) ? $columnSource : $columnHeader;
}
$fileData .= "\"" . implode("\"{$separator}\"", array_values($headers)) . "\"";
$fileData .= "\n";
}
$items = $gridField->getList();
foreach($items as $item) {
$columnData = array();
foreach($csvColumns as $columnSource => $columnHeader) {
if(!is_string($columnHeader) && is_callable($columnHeader)) {
if($item->hasMethod($columnSource)) {
$relObj = $item->{$columnSource}();
} else {
$relObj = $item->relObject($columnSource);
}
$value = $columnHeader($relObj);
} else {
$value = $gridField->getDataFieldValue($item, $columnSource);
}
$value = str_replace(array("\r", "\n"), "\n", $value);
$columnData[] = '"' . str_replace('"', '\"', $value) . '"';
}
$fileData .= implode($separator, $columnData);
$fileData .= "\n";
$item->destroy();
}
return $fileData;
}
}
Thanks for this!
I had to use this for Members GF in Security Admin.
Created an extension for anyone interested.
class SecurityAdminExtension extends Extension{
function updateEditForm($form){
$gf = $form->Fields()->fieldByName('Root.Users.Members');
$gfConfig = $gf->getConfig();
$gfConfig->removeComponentsByType('GridFieldExportButton');
$gfConfig->addComponent(new GridFieldExportAllButton());
}
}
I while back, I created a little plugin to make it easy to export DataObjects to CSV or Excel files.
https://github.com/firebrandhq/excel-export
It comes with a button you can add to a grid field.
It's got a dependency on PHP-Excel.