This patch allows php-eval to be used with php code from stdin.

Usage:

echo 'print "hello world!\n";' | drush php-eval -

The arg to php-eval should be '-' to indicate that the php code should be read from stdin. This could have been a test to check for an empty command, but then drush would hang waiting for input if you ran php-eval with no parameters.

There is an existing unix standard that - in place of a file means stdin; maybe this patch should have modified php-script instead, but I think this is okay as well.

The patch still needs documentation. I'm sketchy on the value of this, so someone who cares more about it will have to finish it up. For the record, I was working on this to investigate #926780: Use drush to write standard Unix scripts in php.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

greg.1.anderson’s picture

Title: Unix standardization for php-eval / php-script commands » Allow drush php-eval to execute code from stdin
John_Buehrer’s picture

Title: Allow drush php-eval to execute code from stdin » a test with a snippet

Yes, using STDIN with php-script would be appreciated too.

Meanwhile I'm wondering how to rebuild content_access
permissions in an automated way, ie, via Bash & Drush.
I'm guessing the error below isn't from the new STDIN feature?

$ thePhp=`cat <<EOF
  \\\$form_id = 'node_configure_rebuild_confirm';
  \\\$form_state['values'] = array (
    'confirm' => t('1'),
    'op' => t('Rebuild permissions'),
  );
  drupal_execute (\\\$form_id, \\\$form_state);
EOF
`

$ echo $thePhp
$form_id = 'node_configure_rebuild_confirm';
$form_state['values'] = array ( 'confirm' => t('1'), 'op' => t('Rebuild permissions'), );
drupal_execute ($form_id, $form_state);

$ alias dr
alias dr='drush -r /Applications/MAMP/htdocs/mySite'

$ echo $thePhp | dr php-eval -
WD php: call_user_func_array(): First argument is expected to be a valid callback, [error]
'node_configure_rebuild_confirm' was given in
/Applications/MAMP/htdocs/mySite/includes/form.inc on line 376.
call_user_func_array(): First argument is expected to be a valid callback, [warning]
'node_configure_rebuild_confirm' was given in
/Applications/MAMP/htdocs/mySite/includes/form.inc on line 376.

According to Pro Drupal Development p.247: "Simply provide the form ID and the values
for the form, and call drupal_execute()". But drush is nowhere to be found in that book.
(So who's the pro? :-)

greg.1.anderson’s picture

Title: a test with a snippet » Allow drush php-eval to execute code from stdin

Please do not change the topic of existing issues. Start new issues for new questions. Thank you.

Are you getting the error above after applying the patch in #0 manually? It has not been committed to HEAD yet.

John_Buehrer’s picture

Yes I applied the patch manually, though with a slight problem as shown below.

I don't know whether the above error is related to running via STDIN or not,
or trying to do this via Drush or not, or for other reasons.
Hence I put it here as an example of a real STDIN use-case.

$ cd /usr/local/drush

$ patch -p0  < /tmp/php-eval-from-stdin.patch
patching file commands/core/core.drush.inc
Hunk #1 succeeded at 626 (offset -50 lines).
Hunk #2 succeeded at 655 (offset -50 lines).
Hunk #3 FAILED at 856.
1 out of 3 hunks FAILED -- saving rejects to file commands/core/core.drush.inc.rej

$ cat commands/core/core.drush.inc.rej 
***************
*** 851,854 ****
    }
  
    return $bashrc_data;
- }--- 856,859 ----
    }
  
    return $bashrc_data;
+ }

$ tail commands/core/core.drush.inc
  $commands = drush_get_commands();
  foreach ($commands as $key => $command) {
    // Filter out old commands that still have spaces
    if (strpos($key, ' ') === FALSE) {
      $bashrc_data .= "function $key() {\n  $drush_command $key \"\$@\"\n}\n";
    }
  }

  return $bashrc_data;
}
greg.1.anderson’s picture

You should try the same script with php-script. I notice that your alias specifies -r but not -l. Does it work for other drush operations?

John_Buehrer’s picture

In my environment, this Drush alias works well for module downloads and make.

I use "-r" because I'm typically don't `cd` into Drupal dirs during my work.
I don't use "-l" because "--help" says that's for multisite which I don't use.
Does it do other things, and hence I should use it anyway??

With php-script (and without STDIN) I get a similar failure as above.
I'm not sure where to ask about this.
Is Drush intended to be used this way?
Is more PHP context needed - eg, to run this snippet as a specific user?
Or maybe this problem is specific to the content_access module?
Do other people (such as yourself) see the same error?
Thanks.

$ cat > /tmp/qphp.php <<EOF
<?php
  # John's dynamic PHP file, from Bash
  \$form_id = 'node_configure_rebuild_confirm';
  \$form_state['values'] = array (
    'confirm' => t('1'),
    'op' => t('Rebuild permissions'),
  );
  drupal_execute (\$form_id, \$form_state);
EOF

$ dr php-script  --script-path=/tmp  qphp
WD php: call_user_func_array(): First argument is expected to be a valid callback, [error]
'node_configure_rebuild_confirm' was given in
/Applications/MAMP/htdocs/mySite/includes/form.inc on line 376.
call_user_func_array(): First argument is expected to be a valid callback, [warning]
'node_configure_rebuild_confirm' was given in
/Applications/MAMP/htdocs/mySite/includes/form.inc on line 376.
John_Buehrer’s picture

Some more info:

I get the same error if I replace "node_configure_rebuild_confirm" with "garbage_string".
But the former string does appear in my installation:

$ cd /Applications/MAMP/htdocs/mySite

$ find . -type f -exec grep -l node_configure_rebuild_confirm {} \;
./modules/node/node.admin.inc
./modules/node/node.module

$ find . -type f -exec grep -n node_configure_rebuild_confirm {} \;
71:function node_configure_rebuild_confirm() {
79:function node_configure_rebuild_confirm_submit($form, &$form_state) {
1446:    'page arguments' => array('node_configure_rebuild_confirm'),

This quest comes when I see a common message in the status report:
"The content access permissions need to be rebuilt. Please visit this page."
(http://localhost:8888/mySite/admin/content/node-settings/rebuild)

With a front-end Curl login (http://drupal.org/node/89710),
I discover the form_id of this rebuild page:

$ grep form_id /tmp/qtmp.html
<input type="hidden" name="form_id" id="edit-search-theme-form"
  value="search_theme_form"  />
<input type="hidden" name="form_id" id="edit-node-configure-rebuild-confirm"
  value="node_configure_rebuild_confirm"  />

Often I can simply "press the button" with another Curl operation.
But rebuilding these permissions runs some Javascript with a progress bar,
and more HTTP GETs - which are hard to parse.
So I thought I'd invoke the form instead via the Drush back-end
with a php snippet read from STDIN.
Would you expect Drush to work for this?

greg.1.anderson’s picture

The first thing to test is whether your alias is bootstrapping your Drupal site correctly. Does dr status show that your database is connected?

I would think that you would want to do the above operation more than once, and therefore would use drush php-script rather than php-eval from stdin.

John_Buehrer’s picture

My Drush->Drupal DB connection seems OK, can you confirm this based on info below?
Should the Drupal user shown below be "root" rather than "Anonymous"?

Can you confirm that my php-eval example above works or fails
in a known-to-be-good Drush/Drupal installation -
and whether this sort of Drush thing is expected to work in the first place ?

$ dr status
 Drupal version         :  6.19                                  
 Site URI               :  http://default                        
 Database driver        :  mysqli                                
 Database hostname      :  localhost                             
 Database username      :  penguinUser                           
 Database name          :  penguinDB                             
 Database               :  Connected                             
 Drupal bootstrap       :  Successful                            
 Drupal user            :  Anonymous                             
 Default theme          :  garland                               
 Administration theme   :  garland                               
 PHP configuration      :  /Applications/MAMP/conf/php5/php.ini  
 Drush version          :  3.3                                   
 Drush configuration    :                                        
 Drupal root            :  /Applications/MAMP/htdocs/mySite 
 Site path              :  sites/default                         
 File directory path    :  sites/default/files                   

$ dr vget private_key
drupal_private_key: "31e57f20e02480e048c8bbd57e400f614b07fe8b6639c4bb9de59be7552d3b67"

$ dr sql-query "SELECT uid,name,pass,mail FROM {users}"
uid	name	pass	mail
0			
1	root	8c4e600b97595baf98f089713114c391	drupal_root@localhost
3	John	d41d8cd98f00b204e9800998ecf8427e	drupal_john@localhost
4	Joe	d41d8cd98f00b204e9800998ecf8427e	drupal_joe@localhost
5	Tom	d41d8cd98f00b204e9800998ecf8427e	drupal_tom@localhost

$ dr -v info
Initialized Drupal 6.19 root directory at /Applications/MAMP/htdocs/mySite  [notice]
Initialized Drupal site default at sites/default  [notice]
Warning: The command name "info" is deprecated.  Please use a recommended form instead  [warning]
  (pm-releases).
No information available.  [error]
An error occurred at function : drush_pm_releases  [error]
Command dispatch complete  [notice]

$ dr -d pm-releases
Drush bootstrap phase : _drush_bootstrap_drupal_root() [0.27 sec, 2.77 MB]  [bootstrap]
Initialized Drupal 6.19 root directory at /Applications/MAMP/htdocs/mySite [0.3 sec, 3.28  [notice]
MB]
Drush bootstrap phase : _drush_bootstrap_drupal_site() [0.35 sec, 3.29 MB]  [bootstrap]
Initialized Drupal site default at sites/default [0.55 sec, 3.33 MB]  [notice]
Drush bootstrap phase : _drush_bootstrap_drupal_configuration() [0.57 sec, 3.37 MB]  [bootstrap]
Drush bootstrap phase : _drush_bootstrap_drupal_database() [0.65 sec, 3.38 MB]  [bootstrap]
Successfully connected to the Drupal database. [0.65 sec, 3.38 MB]  [bootstrap]
Drush bootstrap phase : _drush_bootstrap_drupal_full() [0.72 sec, 3.61 MB]  [bootstrap]
Drush bootstrap phase : _drush_bootstrap_drupal_login() [1.56 sec, 16.6 MB]  [bootstrap]
Found command: pm-releases (commandfile=pm) [1.59 sec, 16.59 MB]  [bootstrap]
Initializing drush commandfile: drush_make [1.59 sec, 16.6 MB]  [bootstrap]
Initializing drush commandfile: drush_make_d_o [1.59 sec, 16.6 MB]  [bootstrap]
Initializing drush commandfile: user [1.59 sec, 16.6 MB]  [bootstrap]
No information available. [2.39 sec, 16.93 MB]  [error]
An error occurred at function : drush_pm_releases [2.39 sec, 16.69 MB]  [error]
Command dispatch complete [2.4 sec, 16.67 MB]  [notice]
 Timer  Cum (sec)  Count  Avg (msec) 
 page   1.829      1      1829.27    
Peak memory usage was 17.12 MB [2.4 sec, 16.67 MB]  [memory]

Running the same php-script code in succession just gives the same error over again.
Is there another implementation of "do the above operation more than once" ?
The Pro Drupal Development book mentions a batch mode on p.560 but I'm not
sure whether this applies to Drush - no examples are given of callbacks & Drush.

Thanks for your assistance.
Please let me know if there's a better place for this topic.
I guess this exceeds the STDIN test case for php-eval ?

greg.1.anderson’s picture

Title: Allow drush php-eval to execute code from stdin » Allow drush php-script to execute code from stdin
Status: Needs work » Needs review
FileSize
653 bytes

I think it is reasonable to allow evaluation from stdin, but it should be supported in php-script, not php-eval. Patch included.

@John_Buehrer: If you are still having trouble with #3 - #10, try again with HEAD and post in a separate issue.

moshe weitzman’s picture

Status: Needs review » Fixed

Looks reasonable to me. Committed.

The OP sounds like he should just do drush eval "node_access_rebuild();"

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.