Preview image in ACF gutenberg block - image

Is it possible to add an image to the gutenber block preview when using ACF to register the block ?
Here's the code to register the block:
acf_register_block(array(
'name' => 'bk-raisons',
'title' => __('Les raisons', 'diezel'),
'description' => __('Les raisons', 'diezel'),
'render_callback' => 'my_acf_block_render_callback',
'category' => 'spira-custom',
'icon' => 'align-wide',
'keywords' => array('bk-raisons'),
));
The preview appears when hovering the block.
Thank you !

I finally found a solution.
I don't know if you use Twig (Timber) or not.
If not check this : https://stackoverflow.com/a/67846162/6696150
For my part with Timber
When you declared your block add example attributes :
$img_quadruple = array(
'name' => 'img-quadruple',
'title' => __('Quatre images'),
'title_for_render' => 'img-quadruple',
'description' => __(''),
'render_callback' => 'ccn_acf_block_render_callback',
'category' => 'imgs',
'icon' => '',
'mode' => 'edit',
'keywords' => array( 'quatre images' ),
'example' => array(
'attributes' => array(
'mode' => 'preview',
'data' => array(
'preview_image_help' => get_template_directory_uri().'/assets/img/preview/preview_img_quadruple.jpg',
),
)
)
);
And when your declared your callback :
function ccn_acf_block_render_callback( $block, $content = '', $is_preview = false ) {
$context = Timber::context();
// Store block values.
$context['block'] = $block;
// Store field values.
$context['fields'] = get_fields();
// back-end previews
if ( $is_preview && ! empty( $block['data'] ) ) {
echo '<img src="'. $block['data']['preview_image_help'] .'" style="width:100%; height:auto;">';
return;
} elseif ( $is_preview ) {
echo 'Other condition';
return;
}
// Store $is_preview value.
$context['is_preview'] = $is_preview;
// Render the block.
Timber::render('gutenberg/gut_' . strtolower($block['title_for_render']) . '.twig', $context );
}

Related

Where is the file after create by "$service->spreadsheets->create($requestBody)"

Thank you very much for reading this, its quite long!
I run my function:
public function createSpreadSheet()
{
$client = $this->getClient();
$service = new \Google_Service_Sheets($client);
// TODO: Assign values to desired properties of `requestBody`:
$requestBody = new \Google_Service_Sheets_Spreadsheet();
$response = $service->spreadsheets->create($requestBody);
echo '<pre>', var_export($response, true), '</pre>', "\n";
}
I got a result:
Google_Service_Sheets_Spreadsheet::__set_state(array(
'collection_key' => 'sheets',
'developerMetadataType' => 'Google_Service_Sheets_DeveloperMetadata',
'developerMetadataDataType' => 'array',
'namedRangesType' => 'Google_Service_Sheets_NamedRange',
'namedRangesDataType' => 'array',
'propertiesType' => 'Google_Service_Sheets_SpreadsheetProperties',
'propertiesDataType' => '',
'sheetsType' => 'Google_Service_Sheets_Sheet',
'sheetsDataType' => 'array',
'spreadsheetId' => '1QlBQo_YHQpiiMBWn6b6wSMVWkiFRx4grJhPParXUUSU',
'spreadsheetUrl' => 'https://docs.google.com/spreadsheets/d/1QlBQo_YHQpiiMBWn6b6wSMVWkiFRx4grJhPParXUUSU/edit',
'internal_gapi_mappings' =>
array (
),
modelData' =>
array (
),
'processed' =>
array (
),
'properties' =>
Google_Service_Sheets_SpreadsheetProperties::__set_state(array(
'autoRecalc' => 'ON_CHANGE',
'defaultFormatType' => 'Google_Service_Sheets_CellFormat',
'defaultFormatDataType' => '',
'iterativeCalculationSettingsType' => 'Google_Service_Sheets_IterativeCalculationSettings',
'iterativeCalculationSettingsDataType' => '',
'locale' => 'en_US',
'timeZone' => 'Etc/GMT',
'title' => 'Untitled spreadsheet',
'internal_gapi_mappings' =>
array (
),
'modelData' =>
array (
),
'processed' =>
array (
),
'defaultFormat' =>
Google_Service_Sheets_CellFormat::__set_state(array(
'backgroundColorType' => 'Google_Service_Sheets_Color',
'backgroundColorDataType' => '',
'bordersType' => 'Google_Service_Sheets_Borders',
'bordersDataType' => '',
'horizontalAlignment' => NULL,
'hyperlinkDisplayType' => NULL,
'numberFormatType' => 'Google_Service_Sheets_NumberFormat',
'numberFormatDataType' => '',
.........
.........
))
I access to the link it returned:
'https://docs.google.com/spreadsheets/d/1QlBQo_YHQpiiMBWn6b6wSMVWkiFRx4grJhPParXUUSU/edit'
it gives me this 'request access' page, then I press the request access
I open my email and get this:
Your message wasn't delivered to xxxxxx#xxxxxxxx.iam.gserviceaccount.com because the domain admanager-1x3x71x4x27x4.iam.gserviceaccount.com couldn't be found. Check for typos or unnecessary spaces and try again.
Is there something wrong and what should I do? I just want to open the file and check where it is.
Thank you very much!

Returning user input after AJAX call in Drupal 7 hook_form_FORM_ID_alter

I am using the hook_form_FORM_ID_alter in Drupal 7 to create a custom form so that the user can enter and edit data which is then attached to a custom node type.
For a new node the default number of input boxes in a group is 10, this can then be added to in groups of 5. When the node is reloaded for editing the saved data is used to create the form with whatever number of inputs have been saved previously and also the ability to add more fields in the same manner as required.
I have managed to get both the initial version of the form and the editing version to work using the following code however when the 'add five' button is pressed and the AJAX called (in both cases), any values which have been entered without saving are removed.
<?php
/**
* Implements hook_form_FORM_ID_alter().
*/
function entries_form_form_entries_node_form_alter(&$form, &$form_state, $form_id) {
$node = $form['#node'];
// fieldset
$form["section"] = array(
'#type' => 'fieldset',
'#title'=> 'Section 1',
);
$form["section"]["termwrapper"] = array(
"#type" => 'container',
"#attributes" => array(
"id" => 'groupWrapper',
),
);
$form["section"]["termwrapper"]["terms"]["#tree"] = TRUE;
if(!isset($form_state['fired'])){
$form_state['terms'] = $node->entries_form['term'];
}
foreach ($form_state['terms'] as $key => $values) {
$form["section"]["termwrapper"]["terms"][$key] = array(
'#type' => 'textfield',
'#size' => 20,
'#attributes' => array(
'class' => array('left'),
),
'#value' => $values,
);
}
$form['section']['addFive_button'] = array(
'#type' => 'submit',
'#value' => t('+5'),
'#submit' => array('entries_form_add_five_submit'),
'#ajax' => array(
'callback' => 'entries_form_commands_add_callback',
'wrapper' => 'groupWrapper',
),
'#prefix' => "<div class='clear'></div>",
);
dpm($form_state);
}
function entries_form_commands_add_callback($form, $form_state) {
return $form["section"]["termwrapper"];
}
function entries_form_add_five_submit($form, &$form_state){
$form_state['rebuild'] = TRUE;
$form_state['fired'] = 1;
$values = $form_state['values'];
$form_state['terms'] = $values['terms'];
$numterms = count($values['terms']);
$addfivearray = array_fill($numterms,5,'');
$form_state['terms'] = array_merge($values['terms'],$addfivearray);
}
/**
* Implements hook_node_submit().
*/
function entries_form_node_submit($node, $form, &$form_state) {
$values = $form_state['values'];
$node->entries_form['term'] = $values['term'];
}
/**
* Implements hook_node_prepare().
*/
function entries_form_node_prepare($node) {
if (empty($node->entries_form)){
$node->entries_form['term'] = array_fill(0, 10, '');
}
}
/**
* Implements hook_node_load().
*/
function entries_form_node_load($nodes, $types) {
if($types[0] == 'entries'){
$result = db_query('SELECT * FROM {mytable} WHERE nid IN(:nids)', array(':nids' => array_keys($nodes)))->fetchAllAssoc('nid');
foreach ($nodes as &$node) {
$node->entries_form['term'] = json_decode($result[$node->nid]->term);
}
}
}
/**
* Implements hook_node_insert().
*/
function entries_form_node_insert($node) {
if (isset($node->entries_form)) {
db_insert('mytable')
->fields(array(
'nid' => $node->nid,
'term' => json_encode($node->entries_form['term']),
))
->execute();
}
}
How can I keep the values which have been typed in and retain the ajax functionality?
Any help or pointers much appreciated. This is my first dip into Drupal so I'm sure there is something which hopefully is quite obvious that I'm missing.
Ok, I think I finally have the answer.
Within the foreach that builds the form input boxes I had set '#value' => $values, when it seems that '#default_value' => $values, should have been set instead.
The updated section of the code that is now working for me is as follows
foreach ($form_state['terms'] as $key => $values) {
$form["section"]["termwrapper"]["terms"][$key] = array(
'#type' => 'textfield',
'#size' => 20,
'#attributes' => array(
'class' => array('left'),
),
'#default_value' => $values,
);
}
Seems to be as simple as that. Hope this helps someone else.

drupal custom views filter

First time on stackoverflow so , i will try to be as clear as possible.
I'm using drupal 7 and views 3.
I needed to create a custom views filter that handle dates range. So i looked at example and tried to mimic the behavior and i get some trouble.
It seems that when i extend my own class from views_handler_filter , the query method is never invoked BUT if i extend my class from let's say views_handler_filter_string, it works oO...
I must forget something but i'm stuck here ...
Here is my code, if someone can take a look and advise me about what happend , i would be very grateful.
Thanks everyone !
Here is my .views.inc file :
<?php
class v3d_date_custom_filter extends views_handler_filter {
var $always_multiple = TRUE;
function value_form(&$form, &$form_state) {
//parent::value_form($form, $form_state);
$form['value']['v3d_date']['period'] = array(
'#type' => 'select',
'#title' => 'Period',
'#options' => array(
'7_days' => 'Last 7 days',
'yesterday' => 'Yesterday',
'today' => 'Today',
'custom' => 'Custom dates'),
'#default_value' => 'custom',
'#attributes' => array("onclick" => "period_click(this);"),
);
$form['value']['v3d_date']['start_date'] = array(
'#type' => 'date_popup',
'#date_format' => 'Y-m-d',
'#title' => 'Start date',
'#size' => 30);
$form['value']['v3d_date']['end_date'] = array(
'#type' => date_popup',
'#title' => 'End date',
'#date_format' => 'Y-m-d',
'#size' => 30);
}
function exposed_validate(&$form, &$form_state) {
if(is_null($form_state['values']['start_date']) &&
is_null($form_state['values']['start_date'])) {
return TRUE;
}
/*
* If we get array for start_date or end_date
* errors occured, but the date module will handle it.
*/
if(!is_string($form_state['values']['start_date']) ||
!is_string($form_state['values']['end_date'])) {
return TRUE;
}
/* Get day, month and year from start_date string */
if(!preg_match('/(\d+)-(\d+)-(\d+)/',
$form_state['values']['start_date'],
$start_date
)) {
return TRUE; }
/* Get day, month and year from end_date string */
if(!preg_match('/(\d+)-(\d+)-(\d+)/',
$form_state['values']['end_date'],
$end_date
)) {
return TRUE; }
/* Create timestamps and compare */
$start_date = mktime(0,0,0,$start_date[1],$start_date[2],$start_date[3]);
$end_date = mktime(0,0,0,$end_date[1],$end_date[2],$end_date[3]);
if($start_date >= $end_date) {
form_set_error('start_date','Start date must be anterior to end date.');
}
}
function query() {
die('fdsfds');
$this->ensure_my_table();
$field = "$this->table_alias.$this->real_field";
dsm($this);
}
}
?>
And my .module file
<?php
function custom_filters_views_api() {
return array(
'api'=>3,
'path' => drupal_get_path('module','custom_filters') . '/views',
);
}
?>
And part of my views_data that use my custom filter :
<?php
function voice_views_data() {
$data['v_tp_voice']['date_utc_agent'] = array(
'title' => t('date_utc_agent'),
'help' => 'date_utc_agent',
'field' => array('handler' => 'views_handler_field'),
'filter' => array('handler' => 'v3d_date_custom_filter'),
'sort' => array('handler' => 'views_handler_sort')
);
I am working on this same problem. My setup looks very much like yours, though I do call parent::value_form($form, $form_state) in my value_form function.
I found that in the value_form function, I had to have something like
$form['value'] = array(
'#type' => 'checkbox',
'#title' => "Filter by Date",
'#default_value' => $this->value,
);
in order to have my query() function called. Doing something like $form['value']['before'] = array( ...
didn't work.

Sending a campaign to a segment

Anyone know how to get a campaign to send to a segment? This code isn't working. It will send an email to all people in the campaign. It will not use the segment. (This is some more text so I can get it to pass the validation of SO.)
My code:
//get member list
$memberArray = $api->listMembers($inStockListId);
foreach ($memberArray['data'] as $member) {
$memberInfo = $api->listMemberInfo($inStockListId, $member['email']);
$_productId = $memberInfo['data'][0]['merges']['PRODUCTID'];
$productId='34';
if ($productId == $_productId) {
array_push($emailArray, $member['email']);
}
}
//create new segment for campaign
$listStaticSegmentId = $api->listStaticSegmentAdd($inStockListId, 'inStockStaticSegment');
//add members to segment
$val = $api->listStaticSegmentMembersAdd($inStockListId, $listStaticSegmentId, $emailArray);
$conditions = array();
$conditions[] = array(
'field' => 'email',
'op' => 'like',
'value' => '%'
);
$segment_options = array(
'match' => 'all',
'conditions' => $conditions
);
$type = 'regular';
$options = array(
'template_id' => $campaignTemplateId,
'list_id' => $inStockListId,
'subject' => 'In-Stock Notification',
'from_email' => 'from#email.com',
'from_name' => 'My From Name'
);
$content = array(
'html_main' => 'some pretty html content',
'html_sidecolumn' => 'this goes in a side column',
'html_header' => 'this gets placed in the header',
'html_footer' => 'the footer with an *|UNSUB|* message',
'text' => 'text content text content *|UNSUB|*'
);
$newCampaignId = $api->campaignCreate($type, $options, $content, $segment_options);
I figured it out. Essentially, here is the flow. If you want detailed code, send me a message and I'll be glad to help.
$api = new MCAPI($this->_apiKey);
$api->listMemberInfo($this->_listId, $member['email']);
$api->listUpdateMember($this->_listId, $member['email'], $mergeVars);
$api->listStaticSegmentDel($this->_listId, $segment['id']);
$api->listStaticSegmentAdd($this->_listId, $segmentName);
$api->listStaticSegmentMembersAdd($this->_listId, $segmentId, $emailArray);
$api->campaignCreate($type, $options, $content, $segment_options);
//$api->campaignSendTest($newCampaignId, array($member['email']));
$api->campaignSendNow($newCampaignId);
Note, this is done via the MailChimp PHP API.

How to "print" a theme during AJAX request (Drupal)

When users click on a button (with id graph), I'd like to fill the default Drupal content div (<div class="content">) with a graphael instance.
The JavaScript:
jQuery(document).ready(function($) {
$('#toggle #graph').click(function() {
$.ajax({
url: "http://www.mysite.com/?q=publications/callback",
type: 'POST',
data: {
'format' : 'graph'
},
success: function(response) {
$('div#content div.content').html(response);
}
});
});
});
The PHP:
$items['publications/callback'] = array(
'type' => MENU_CALLBACK,
'title' => 'All Publications Callback',
'page callback' => '_process_publications',
'page arguments' => array(t('journal')),
'access callback' => TRUE,
);
which leads to the page callback: (I'm concerned with the if code block)
function _process_publications($venue) {
if( isset($_POST['format']) && $_POST['format'] == "graph" ){
_make_bar_chart($venue);
}
elseif( isset($_POST['format']) && $_POST['format'] == "list" ) {
_make_list($venue);
}
else{
return("<p>blah</p>");
}
}
and finally the function called within the callback function:
function _make_bar_chart($venue) {
// get active database connection
$mysql = Database::getConnection();
// if connection is successful, proceed
if($mysql){
// do stuff
$graphael = array(
'method' => 'bar',
'values' => $ycoordinates,
'params' => array(
'colors' => $colors,
'font' => '10px Arial, sans-serif',
'opts' => array(
'gutter' => '20%',
'type' => 'square',
),
'label' => array(
'values' => $xcoordinates,
'isBottom' => true,
),
),
'extend' => array(
'label' => array(
'values' => $ycoordinates,
'params' => array('attrText' => array(
'fill' => '#aaa',
'font' => '10px Arial, sans-serif',
)),
),
),
);
return theme('graphael', $graphael);
}
// else, connection was unsuccessful
else{
print("<p>bad connection</p>");
}
}
THE PROBLEM: returning a theme doesn't really send anything back to the AJAX request (unlike print statements). I tried to print the theme, but that produces a white screen of death. How would I generate the graph without printing something?
Much thanks to nevets on the Drupal forums for the helpful hint: http://drupal.org/node/1664798#comment-6177944
If you want to use AJAX with Drupal, you are best off actually using Drupal-specific AJAX-related functions. In my theme's page.tpl.php file, I added the following to make the links which would call AJAX:
<?php
// drupal_add_library is invoked automatically when a form element has the
// '#ajax' property, but since we are not rendering a form here, we have to
// do it ourselves.
drupal_add_library('system', 'drupal.ajax');
// The use-ajax class is special, so that the link will call without causing
// a page reload. Note the /nojs portion of the path - if javascript is
// enabled, this part will be stripped from the path before it is called.
$link1 = l(t('Graph'), 'ajax_link_callback/graph/nojs/', array('attributes' => array('class' => array('use-ajax'))));
$link2 = l(t('List'), 'ajax_link_callback/list/nojs/', array('attributes' => array('class' => array('use-ajax'))));
$link3 = l(t('Create Alert'), 'ajax_link_callback/alert/nojs/', array('attributes' => array('class' => array('use-ajax'))));
$output = "<span>$link1</span><span>$link2</span><span>$link3</span><div id='myDiv'></div>";
print $output;
?>
When one of the links above is clicked, the callback function is called (e.g. ajax_link_callback/graph):
// A menu callback is required when using ajax outside of the Form API.
$items['ajax_link_callback/graph'] = array(
'page callback' => 'ajax_link_response_graph',
'access callback' => 'user_access',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
.. and the callback to which it refers:
function ajax_link_response_graph($type = 'ajax') {
if ($type == 'ajax') {
$output = _make_bar_chart('journal');
$commands = array();
// See ajax_example_advanced.inc for more details on the available commands
// and how to use them.
$commands[] = ajax_command_html('div#content div.content', $output);
$page = array('#type' => 'ajax', '#commands' => $commands);
ajax_deliver($page);
}
else {
$output = t("This is some content delivered via a page load.");
return $output;
}
}
This replaces any HTML within <div class="content"> with the graphael chart returned from _make_bar_chart above.

Resources