Miért is akarjunk mi parancssorból Drupal-t futtatni? Például akkor hasznos ha egy import szkirptet írunk, ami nagyon sokáig is futhat. Vagy ha a futás kimenete olyan információ, amit aztán a linux parancssorból vagy egy bash scriptben akarunk felhasználni.
Oké, van nekünk Batch API-nk a hosszú futásokhoz, meg Drush is van a CLI-hez. De azért nézzük meg , mit tudunk kezdeni egy egyszerű php fájllal.
Először is érdemes belepillantani a Drupal index.php-ba, a cron.php-va, ha még nem tettük meg. Kiderül, hogy ezek faék egyszerű fájlok, így aztán innen fogunk puskázni.
Első naiv próbálkozás
Legyen a cli.php fájl tartalma ez:
<span style="color: #000000"><span style="color: #0000BB"><?php<br />define</span><span style="color: #007700">(</span><span style="color: #DD0000">'DRUPAL_ROOT'</span><span style="color: #007700">, </span><span style="color: #0000BB">getcwd</span><span style="color: #007700">()); <br />include_once </span><span style="color: #0000BB">DRUPAL_ROOT </span><span style="color: #007700">. </span><span style="color: #DD0000">'/includes/bootstrap.inc'</span><span style="color: #007700">; <br /></span><span style="color: #0000BB">drupal_bootstrap</span><span style="color: #007700">(</span><span style="color: #0000BB">DRUPAL_BOOTSTRAP_FULL</span><span style="color: #007700">); <br /></span><span style="color: #0000BB">?></span></span>
Futtassuk így:
# php cli.php
Rögtön kapunk is egy csomó hibát, mert nem létezik a REMOTE_ADDR kulcs egy tömbben. Ez a tömb nem lehet más, csak a $_SERVER. Érthető is, hiszen nem böngészőből hívjuk meg a scriptet. Javítsuk ezt a hibát azzal, hogy pótoljuk ezt az értéket.
<span style="color: #000000"><span style="color: #0000BB"><?php<br />$_SERVER</span><span style="color: #007700">[</span><span style="color: #DD0000">'REMOTE_ADDR'</span><span style="color: #007700">] = </span><span style="color: #DD0000">'127.0.0.1'</span><span style="color: #007700">; <br /></span><span style="color: #0000BB">?></span></span>
Tegyünk egy kis óvintézkedést, és állítsuk le a szkript futását, ha nem parancssorból futtatjuk. Ezt így tehetjük meg:
<span style="color: #000000"><span style="color: #0000BB"><?php<br /></span><span style="color: #007700">if (</span><span style="color: #0000BB">php_sapi_name</span><span style="color: #007700">() !== </span><span style="color: #DD0000">'cli'</span><span style="color: #007700">) { <br /> exit(</span><span style="color: #0000BB">1</span><span style="color: #007700">); <br />} <br /></span><span style="color: #0000BB">?></span></span>
Ezzel teljesen kizárjuk a webszervert, így a legtöbb biztonsági kockázatnak elejét vettük.
A teljes kód
Nos nagyjából ennyi, a teljes kód mindössze ennyi:
<span style="color: #000000"><span style="color: #0000BB"><?php<br />define</span><span style="color: #007700">(</span><span style="color: #DD0000">'DRUPAL_ROOT'</span><span style="color: #007700">, </span><span style="color: #0000BB">getcwd</span><span style="color: #007700">()); <br /><br />if (</span><span style="color: #0000BB">php_sapi_name</span><span style="color: #007700">() !== </span><span style="color: #DD0000">'cli'</span><span style="color: #007700">) { <br /> exit(</span><span style="color: #0000BB">1</span><span style="color: #007700">); <br />} <br /><br /></span><span style="color: #0000BB">$_SERVER</span><span style="color: #007700">[</span><span style="color: #DD0000">'REMOTE_ADDR'</span><span style="color: #007700">] = </span><span style="color: #DD0000">'127.0.0.1'</span><span style="color: #007700">; <br /><br />include_once </span><span style="color: #0000BB">DRUPAL_ROOT </span><span style="color: #007700">. </span><span style="color: #DD0000">'/includes/bootstrap.inc'</span><span style="color: #007700">; <br /></span><span style="color: #0000BB">drupal_bootstrap</span><span style="color: #007700">(</span><span style="color: #0000BB">DRUPAL_BOOTSTRAP_FULL</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">?></span></span>
Ezután bármit megtehetünk a kis php szkriptben. Például meghívhatunk egy hook-ot minden modulban így:
<span style="color: #000000"><span style="color: #0000BB"><?php<br /> module_invoke_all</span><span style="color: #007700">(</span><span style="color: #DD0000">'xmlrpc'</span><span style="color: #007700">); <br /></span><span style="color: #0000BB">?></span></span>
Vagy bármely modul egy tetszőleges függvényét így:
<span style="color: #000000"><span style="color: #0000BB"><?php<br /> import_modulom_import_fuggvenye</span><span style="color: #007700">(); <br /></span><span style="color: #0000BB">?></span></span>
Fontos, hogy kinek a nevében fut!
Egy dologra viszont oda kell figyelni: a php-t futtató szerver felhasználó. Debian/Ubuntu rendszereken www-data az alapbeállítás, de szervertől függően ez bármi lehet. A fájlkezelés miatt fontos, ugyanis a fájlokat tartalmazó könyvtárban (pl.: sites/default/files) minden fájlnak a webszerver a tulajdonosa, ezzel lehet írni-olvasni a fájlokat. Ha mi egy másik felhasználó nevében futtatjuk a ki import php szkriptünket, ami mondjuk képeket is importál, akkor bizony az új vagy módosított fájloknak más lesz a tulajdonosa. És ez baj, mert akkor később a web-ről már nem tudjuk módosítani, vagy akár törölni ezeket.
Ezerféle módon megoldhatjuk ezt a problémát, a két legegyszerűbbet mutatom be.
Legjobb megoldás, ha a php-t a megfelelő felhasználó nevében futtatjuk. Ha pl. www-data nevében fut az Apache vagy másik webszerver, akkor így:
# sudo -u www-data php cli.php
Erre viszont nincs mindig lehetőség. Egyszerű, de nagyszerű megoldás az is, ha a cli.php futása után egyszerűen átadjuk a megfelelő felhasználónak a files könyvtár tartalmát:
# chown -R www-data sites/default/files
Ez az egész ötlet nekem egy importálás miatt kellett, és nagyon jól bevált. Remélem másnak is hasznos lesz.