Extending Context List module to show names of blocks/nodes - drupal

I did do a search on this, but found nothing and it is a custom module. It is called Context List Named and extends the Context List module so that the blocks will show titles instead of node or block number. The project maintainer created two hooks for me, but I have not been able to figure out how to get it working. Here is my function:
function context_list_named_context_list_reaction_block_name(&$block_name, &$details) {
if(preg_match('/^nodeblock:(\d+)$/', $block_name)) {
$block = block_load('nodeblock',$details->delta);
$block_name = $block->subject;
//$block_name = ;
}
elseif(preg_match('/^block:(\d+)$/', $block_name)) {
$block = block_load('block',$details->delta);
$block_name = $block->subject;
//return $block_name;
}
$block_name = 'test';
}
So you can see that I am just trying to set $block_name = 'test'; just to get started, but I am not seeing anything change on the Context List page. (Context block info module offers the same type of list with just the node/block numbers as well.)

Related

Drupal 8 | Wrong alias used

Bonjour,
I have a problem on Drupal 8 that I can't solve, that's why I'm calling on you.
I have 2 aliases for the same node :
/public/event/10
/pro/event/10
I have a block_1 that only appears on the " /public/* " pages and a block_2 on the " /pro/* " pages.
When I access to the url "/pro/event/10", block_1 is displayed and not block_2.
I conclude that Drupal selects the alias "/public/event/10" (probably the first one he finds) while I'm on the page "/pro/event/10".
How can I programmatically tell Drupal the right alias to use?
Thank you in advance for your help.
Here is the code if it can help someone
class OOutboundPathProcessor implements OutboundPathProcessorInterface
{
function processOutbound($path, &$options = [], Request $request = NULL, BubbleableMetadata $bubbleable_metadata = NULL)
{
// Only for nodes
if (!isset($options['entity_type']) OR $options['entity_type'] !== 'node')
{
return $path;
}
// Get current 'space'
$espace = \Drupal::service('session')->get('espace');
// Get the node to process
$node = $options['entity'];
// New path
$str_path = "/%s/%s/%s";
$new_path = sprintf($str_path, $espace, $node->bundle(), $node->id());
// Check new path
$isValid = \Drupal::service('path.validator')->isValid($new_path);
if ($isValid === true) return $new_path;
return $path;
}
}
You might want to create your own path_processor_outbound service by implementing OutboundPathProcessorInterface.
This implementation may work on /node/{id} paths if the current requests path matches /public/event/** or /pro/event/**.
Analyzing the node entity for it's type (bundle): If it is event generate and return your desired path; if it is not event don't manipulate the path and return the original.
Writing the actual implementation in PHP code may be your own pleasure ;-)

Drupal 7, save new node while editing old

My need is to change behavior of edit form, for several content types.
The objective is:
-After update button has been pressed, don't update the node but create a new one with values from old node. I could do that by passing old node's fields values to "/node/add/my_content" form but this require a lot of work (the forms are quite complicated) and on edit page i have already all values ready in my fields.
So i already tried hook_form_alter
function mymodule_form_alter (&$form, &$form_state, $form_id) {
switch ($form_id) {
case 'my_not_update_form':
$node = $form_state['node'];
if (!isset($node->nid) || isset($node->is_new)) {
// This is a new node.
}
else {
$new_node = new StdClass();
$new_node->type = 'my_not_update_form';
node_object_prepare($new_node);
$new_node->uid = $user->uid;
$new_node->language = 'und';
$new_node->title = NULL;
$form['vid']['#value'] = NULL;
$form['nid']['#value'] = NULL;
$form['created']['#value'] = $new_node->created;
$form['changed']['#default_value'] = NULL;
$form['#node'] = $new_node;
$form['#entity'] = $new_node;
$form_state['node'] = $new_node;
$form_state['build_info']['args'][0] = $new_node;
}
break;
}
}
So with the above code i'm able to create a new node but the "create date" parameter always stay the same as create date parameter of an old node and none of the above line can solve that problem.
If you want to create an entirely new node when you submit edits to an existing node, then you want to use hook_node_presave(), which allows you to set any property of the node object before it's saved to the database.
In this example unsetting the nid and vid, and explicitly setting the is_new property will achieve this:
function my_module_node_presave($node) {
unset($node->nid);
unset($node->vid);
$node->is_new = TRUE;
}
This will leave the existing node untouched and unedited, and will instead create an entirely new node.
So to fully change the behavior of form update i give up on hook_form_alter() and instead i used hook_node_presave
function mymodule_node_presave($node) {
if($node->is_new == FALSE || isset($node->nid)) {
unset($node->nid);
unset($node->vid);
unset($node->vuuid);
$node -> created = time();
$node -> timestamp = time();
$node-> is_new = TRUE;
$node -> changed = time();
unset($node->revision_timestamp);
unset($node->num_revisions);
unset($node->current_revision_id);
unset($node->is_current);
unset($node->is_pending);
unset($node->revision_moderation);
unset($node->date);
unset($node->vuuid);
unset($node->data);
}
}

Send Gravity Forms data to redirection page

I have a very simple form created with Gravity Forms;
It submits two numbers and then redirects to a different result page.
How do I retrieve those two numbers on the result page?
add_filter("gform_confirmation_4", "custom_confirmation", 3, 4 );
function custom_confirmation($confirmation, $form, $lead, $ajax)
Gives a custom confirmation. Each field value can be retrieved by using $lead[{field ID}]
I have a solution for this based on using a combination of form submission hooks and the GForms API. It's a horrible plugin so I apologise for the messiness of the logic flow. It's important to use the framework methods rather than processing the data yourself since there are a good amount of hacks and shonky things going on in there to correctly match field IDs and so forth.
I will provide a solution to pass a submission from one form to pre-populate another. Changing the destination for POST data is pretty straightforward, they have an example for it on their gform_form_tag hook documentation page. Yes, that really is the only way of doing it.
Without further ado here is the code. I've set it up to work off form configuration to make things simpler for the end user, so it works like this:
Select "allow field to be populated dynamically" in your destination form field's advanced settings and choose a parameter name for each.
Add matching CSS classes on the source fields of the other form(s) to setup the associations.
Add a CSS class to the source forms themselves so that we can quickly check if the redirection is necessary.
.
$class = 'GForms_Redirector';
add_filter('gform_pre_submission', array($class, 'checkForSubmissionRedirection'), 10, 1);
add_filter('gform_confirmation', array($class, 'performSubmissionRedirection'), 10, 4);
abstract class GForms_Redirector
{
const SOURCE_FORMS_CLASS_MATCH = 'submission-redirect';
const DEST_PAGE_SLUG = 'submit-page-slug';
const DEST_FORM_ID = 1;
protected static $submissionRedirectUrl;
// first, read sent data and generate redirection URL
function checkForSubmissionRedirection($form)
{
if (false !== preg_match('#\W' . self::SOURCE_FORMS_CLASS_MATCH . '\W#', $form['cssClass'])) {
// load page for base redirect URL
$destPage = get_page_by_path(self::DEST_PAGE_SLUG);
// load form for reading destination form config
$destForm = RGFormsModel::get_form_meta(self::DEST_FORM_ID, true);
$destForm = RGFormsModel::add_default_properties($destForm);
// generate submission data for this form (there seem to be no hooks before gform_confirmation that allow access to this. DUMB.)
$formData = GFFormsModel::create_lead($form);
// create a querystring for the new form based on mapping dynamic population parameters to CSS class names in source form
$queryVars = array();
foreach ($destForm['fields'] as $destField) {
if (empty($destField['inputName'])) {
continue;
}
foreach ($form['fields'] as $field) {
if (preg_match('#(\s|^)' . preg_quote($destField['inputName'], '#') . '(\s|$)#', $field['cssClass'])) {
$queryVars[$destField['inputName']] = $formData[$field['id']];
break;
}
}
}
// set the redirect URL to be used later
self::$submissionRedirectUrl = get_permalink($destPage) . "?" . http_build_query($queryVars);
}
}
// when we get to the confirmation step we set the redirect URL to forward on to
function performSubmissionRedirection($confirmation, $form, $entry, $is_ajax = false)
{
if (self::$submissionRedirectUrl) {
return array('redirect' => self::$submissionRedirectUrl);
}
return $confirmation;
}
}
If you wanted to pass the form values someplace else via the querystring then you'd merely need to cut out my code from the callback and build your own URL to redirect to.
This is a very old question, now you can send it using a Query String on the confirmation settings.
They have the documentation on this link:
How to send data from a form using confirmations
Just follow the first step and it will be clear to you.

Flex Async Madness - Any way to wait for a rpc.Responder to get a response before going to the next statement?

I feel like I must be doing this wrong. I've got a function that is supposed to construct a query based on an API's description of available fields. Here's what I've got:
var query_fields = getQueryFieldsFor(sobject_name);
// Need query fields for the next statement, which actually does the query
public function getQueryFieldsFor(sObject:String):String{
//helper function to get queryfields for given sobject
var queryFields:String = '';
app.connection.describeSObject(sObject,
new mx.rpc.Responder(
function(result:DescribeSObjectResult):void{
var returnFields:String = '';
for ( var field:Field in result.fields ){
if(field.active){
returnFields.concat(field.name+',')
}
}
returnFields.slice(0, returnFields.length-1); //remove last comma
queryFields = returnFields;
}, function(error):void{
Alert.show('error in getQueryFieldsFor function');
})
);
return queryFields;
}
I know this doesn't work, and I think I understand why. However, I keep running into this type of issue and I believe I'm just thinking about it/designing it wrong. So what's a better pattern here? Would really appreciate any insight on this. Many thanks in advance.
It would be better to externalize your functions and execute your next line of code after the fact:
public function getQueryFieldsFor(sObject:String):String
{
var responder:Responder = new Responder( onResult, onFault);
app.connection.describeSObject(sObject, responder);
}
private function onResult(result:DescribeSObjectResult):void
{
var returnFields:String = '';
for ( var field:Field in result.fields ){
if(field.active){
returnFields.concat(field.name+',')
}
}
returnFields.slice(0, returnFields.length-1); //remove last comma
queryFields = returnFields;
}
Your main problem though is not the code, but a lack of thinking asynchronously. You cannot have a function called "getQueryFields" that will return it instantly. What you want to do is think in the request/response way. You're trying to get some data, a request is made to a service, gets the data back, updates a property which is then binded to a view which gets redrawn. This is the proper way to do any webapp.
It might be beneficial for you to also look at application frameworks like RobotLegs and Parsley since it helps you manage these situations. Parsley also has a task library which lets you perform several asynchronous task one after another.

Accessing the object/row being edited in Dynamic Data

I'm modifying the "Edit.aspx" default page template used by ASP.NET Dynamic Data and adding some additional controls. I know that I can find the type of object being edited by looking at DetailsDataSource.GetTable().EntityType, but how can I see the actual object itself? Also, can I change the properties of the object and tell the data context to submit those changes?
Maybe you have found a solution already, however I'd like to share my expresience on this.
It turned out to be a great pita, but I've managed to obtain the editing row. I had to extract the DetailsDataSource WhereParameters and then create a query in runtime.
The code below works for tables with a single primary key. If you have compound keys, I guess, it will require modifications:
Parameter param = null;
foreach(object item in (DetailsDataSource.WhereParameters[0] as DynamicQueryStringParameter).GetWhereParameters(DetailsDataSource)) {
param = (Parameter)item;
break;
}
IQueryable query = DetailsDataSource.GetTable().GetQuery();
ParameterExpression lambdaArgument = Expression.Parameter(query.ElementType, "");
object paramValue = Convert.ChangeType(param.DefaultValue, param.Type);
Expression compareExpr = Expression.Equal(
Expression.Property(lambdaArgument, param.Name),
Expression.Constant(paramValue)
);
Expression lambda = Expression.Lambda(compareExpr, lambdaArgument);
Expression filteredQuery = Expression.Call(typeof(Queryable), "Where", new Type[] { query.ElementType }, query.Expression, lambda);
var WANTED = query.Provider.CreateQuery(filteredQuery).Cast<object>().FirstOrDefault<object>();
If it's a DD object you may be able to use FieldTemplateUserControl.FindFieldTemplate(controlId). Then if you need to you can cast it as an ITextControl to manipulate data.
Otherwise, try using this extension method to find the child control:
public static T FindControl<T>(this Control startingControl, string id) where T : Control
{
T found = startingControl.FindControl(id) as T;
if (found == null)
{
found = FindChildControl<T>(startingControl, id);
}
return found;
}
I found another solution, the other ones did not work.
In my case, I've copied Edit.aspx in /CustomPages/Devices/
Where Devices is the name of the table for which I want this custom behaviour.
Add this in Edit.aspx -> Page_Init()
DetailsDataSource.Selected += entityDataSource_Selected;
Add this in Edit.aspx :
protected void entityDataSource_Selected(object sender, EntityDataSourceSelectedEventArgs e)
{
Device device = e.Results.Cast<Device>().First();
// you have the object/row being edited !
}
Just change Device to your own table name.

Resources