How to show / validate error of a node listing page - drupal

i am trying to save form state in database and want to view in a listing page with its error validation.
i.e, i want to validate a previously saved form state from my database.
this is a node type form .
i had already tried node_validate its not working because i fetch the data before submitting the node . so there is no nid and for that it is not working
and also tried drupal_validate_form but it is showing
[form_token] => The form has become outdated. Copy any unsaved work in the form below and then reload this page
EDIT
Any one with any help , "How to save a form inputs in data base and retrive it from database with out form submision.
Thank You In advance
Any help is most Appreciable.

If you look in Drupal Core, you see this in includes/form.inc at the drupal_validate_form function:
if (isset($form['#token'])) {
if (!drupal_valid_token($form_state['values']['form_token'], $form['#token'])) {
$path = current_path();
$query = drupal_get_query_parameters();
$url = url($path, array('query' => $query));
// Setting this error will cause the form to fail validation.
form_set_error('form_token', t('The form has become outdated. Copy any unsaved work in the form below and then reload this page.', array('#link' => $url)));
// Stop here and don't run any further validation handlers, because they
// could invoke non-safe operations which opens the door for CSRF
// vulnerabilities.
$validated_forms[$form_id] = TRUE;
return;
}
}`
This shows that the "form has become outdated" message is being set here. So, you can make the isset($form[#token']) condition false by unsetting #token to prevent this message from appearing.
All you have to do is load the form state you're going to validate, and call
unset($form[#token']); before you call drupal_validate_form.

Related

Cypress not stubbing json data in intercept?

I've been searching for a solution all day, googling and StackOverflowing, but nothing appears to be working.
I've got a very simple NextJS app. On page load, I load a fact from a third party API automatically. Then a user can enter a search query, press enter, and search again based on that query. I want to create a Cypress test that checks for the functionality of that search feature.
Right now, I'm getting a timeout on cy.wait(), and it states that No request ever occurred.
app.spec.js
import data from '../fixtures/data';
describe('Test search functionality', () => {
it('renders new fact when search is performed', () => {
// Visit page
cy.visit('/');
// Wait for page to finish loading initial fact
cy.wait(1000);
// Intercept call to API
cy.intercept("GET", `${process.env.NEXT_PUBLIC_API_ENDPOINT}/jokes/search?query=Test`, {
fixture: "data.json",
}).as("fetchFact");
// Type in search input
cy.get('input').type('Test');
// Click on search button
cy.get('.submit-btn').click();
// Wait for the request to be made
cy.wait('#fetchFact').its('response.statusCode').should('eq', 200);
cy.get('p.copy').should('contain', data.result[0].value);
})
});
One thing I've noticed, is that the data being displayed on the page is coming from the actual API response, rather than the json file I'm attempting to stub with. None of React code is written server-side either, this is all client-side.
As you can see, the test is pretty simple, and I feel like I've tried every variation of intercept, changing order of things, etc. What could be causing this timeout? Why isn't the json being stubbed correctly in place of the network request?
And of course, I figure out the issue minutes after posting this question.
I realized that Cypress doesn't like Next's way of handling env variables, and instead needed to create a cypress.env.json. I've updated my test to look like this:
import data from '../fixtures/data';
describe('Test search functionality', () => {
it('renders new fact when search is performed', () => {
// Visit page
cy.visit('/');
// Wait for page to finish loading initial fact
cy.wait(1000);
// Intercept call to API
const url = `${Cypress.env('apiEndpoint')}/jokes/search?query=Test`;
cy.intercept("GET", url, {
fixture: "data",
}).as("fetchFact");
// Type in search input
cy.get('input').type('Test');
// Click on search button
cy.get('.submit-btn').click();
// Wait for the request to be made
cy.wait('#fetchFact').its('response.statusCode').should('eq', 200);
cy.get('p.copy').should('contain', data.result[0].value);
})
});

Symfony form Event Listener for collection fields

I use event listener for change data dynamically based on user inputs. Each time I use PRE_SET_DATA and PRE_SUBMIT events for set data and fields choices. Here is the simple example of actions from PRE_SUBMIT:
// Pre set share locations by share day
if (array_key_exists('shares', $data)) {
foreach ($data['shares'] as $key => $share) {
if ($share['pickUpDay'] !== null) {
$shareType = $form->get('shares')->get($key);
$locations = $this->em->getRepository('AppBundle:Member\Location')->getLocationsByDay($client, $data['shares'][$key]['pickUpDay']);
$this->addLocationField($shareType, $locations);
}
}
}
Not matter what inside addLocationField function, it works right.
When I do $form->get('shares'), its my collection field, then I need to ->get(child) of this collection and set fields data and choices straight to this child. By when I add collection dynamically, Symfony shows error:
Child "n" does not exist.
And this problem happens only when I try to get data of new collection that was added dynamically. So I can't get to a collection field and change choices, so I receive error that my new value is not in a choice list.
Interesting that $data['shares'] have all data for new collection elements, but $form->get('shares') haven`t:
var_dump(count($event->getData()['shares'])) - return 1;
var_dump(count($form->get('shares'))) - return 0;
Is that mean that my PRE_SUBMIT works before Symfony collection functionality happen?
Someone know how to fix it?
I know your question is "old" and you probably found a solution but you were in the right direction when you said :
Is that mean that my PRE_SUBMIT works before Symfony collection functionality happen?
Your new collection is not submitted yet and it is not present in the model see this part of the doc
To make what you want to, you should use the SUBMIT event
NB : You can't add any field on POST_SUBMIT

New operation in hook_access()

Is it possible to define a new operation for a node access?
As I know, the operations for a node that are used in hook_access() are:
create
delete
update
view
I have a custom content type for which I need another operation, such as "suggest."
short answer is NO as node_access() who is responsible to call hook_access() does a check
on the $op parameter
if (!$node || !in_array($op,
array('view', 'update', 'delete',
'create'), TRUE)) {
return FALSE; }
you can attach some extra info to the node object in your suggest() function - hopefully called before node_access() - then check these extra informations in your hook_access() and return TRUE/FALSE according.
another option consists in hardcode permission checks into the suggest() action itself without messing around with hook_access.

Drupal hook_user stop execution

I need to use Drupal 6's "hook_user" to update a 3rd party API whenever a user updates their profile.
Therefore I use the 'update' operation. The problem I am facing is that I just cannot see how I can stop execution if the 3rd party API update fails.
I.e. the user updates their username, but if the API fails, prevent Drupal from updating the local record.
function myhooks_user($op, &$edit, &$account, $category) {
switch ( $op )
{
case 'update':
if ( FALSE === updateAPI($data) )
{
drupal_set_message("Cannot update user information", "error", false);
return false;
}
break;
}
}
At the moment, the return false doesn't stop execution.
There is not a way to stop execution.
You should be able to overwrite $edit, with what's in the db. That way there wont be any change. I haven't tried this out, but it should work just fine.
Why do you want to do this anyways? You could just add a row in the db, and update the profile at a later time with cron instead, to avoid frustrated users that need to do the same edit over and over.

Automatically refresh Drupal node after hook_view

I'm trying to show updated results for a CCK Computed Field.
The computation is based on fields in another node, so are not being automatically updated.
So: I'm calling node_save($node) in hook_view, which does make the adjustment but the results don't show until I refresh the page.
Is there a way to refresh the page automatically, or should I be approaching this from a different angle?
Edit: In response to Henrik's questions, here's more detail:
The hook_view and its node_save are below, the rest of the code is in a Computed Field in the 'project' content type, summing up values from another node. Without the node_save, I have to edit and save the 'project' node to get the result. With it, I just need to refresh the page.
Adding drupal_goto(drupal_get_destination()) in the hook_view gives a 'page not found', rather than the vicious loop I was expecting. Is there another place I could put it?
function mymodule_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
switch ($op) {
case 'view':
if($node->type == 'project') {
project_view($node);
break;
}
}
}
function project_view($node) {
node_save($node);
return $node;
}
Edit 1: Given the newly posted code and additional explanations, I have three suggestions that might solve the problem without redirecting:
As project_view() does not take the node argument by reference, you might want to actually grab its (potentially updated) result in mymodule_nodeapi by writing
$node = project_view($node);
instead of just
project_view($node);
If that works, it should also work without the indirection via project_view() by just calling node_save($node) directly in mymodule_nodeapi. (node_save() takes the node argument by reference).
AFAIK, computed fields basically provide two working modes that you can switch via checkbox on the field configuration form:
Computing the field once on node_save(), storing the result in the database, updating only on new save operations.
Not storing the field at all, instead recomputing it every time the node is viewed.
Have you tried the 'always recompute' option already?
Edit 2: My original answer was flawed in two ways at once, as it used a completely wrong function to retrieve the current request URI and did not check for recursion (as lazysoundsystem pointed out very courteously ;)
So the following has been updated to an actually tested version of doing the redirection:
Is there a way to refresh the page
automatically
You could try:
if (!$_REQUEST['stop_redirect']) {
drupal_goto(request_uri(), array('stop_redirect' => true));
}
This will cause Drupal to send a redirect header to the client, causing a new request of the current page, making sure not to redirect again immediately.
If the value is only ever going to be computed, you could just add something to your node at load time.
function mymodule_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
switch ($op) {
case 'load':
if($node->type == 'project') {
$node->content['myfield'] = array('#value' => mymodule_calculate_value(), '#weight' => 4, '#theme' => 'my_theme');
}
break;
}
}
}

Resources