Egy field értékéből egy másik field kreálása - de hogyan kell ezt tisztességesen csinálni?

Sk8erPeter képe

Sziasztok!

Több esetben is szükségem lenne arra, hogy egy-egy field összetett értékeiből kikotorjak egy számomra szükséges értéket, és ezt kiírassam a node-nál egy külön fieldként, és ezt a "Manage display" fülön át is tudjam rendezni, húzni.

Ahhoz hasonlóan szeretném csinálni, ahogy a Display Suite is létrehozza a Dynamic fieldeket, Code fieldeket.
Mondjuk van egy Get Locations fieldem, ez GPS-koordinátákat, kiegészítő címadatokat, ilyesmiket tárol, és ebből szeretném kiszedni csupán a GPS-koordinátákat. Ezt épp a Display Suite egy Code fieldjével oldom meg, egy textarea-ba beokádva az alábbi kódot, és bejelölve a "Display Suite code" Text formatot:

  1. <?php
  2.  
  3. if(isset($entity->field_on_the_map['und'][0])){
  4. $on_the_map_getlocations_field_data = $entity->field_watermill_on_the_map['und'][0];
  5.  
  6. if(isset($on_the_map_getlocations_field_data['latitude']) && isset($on_the_map_getlocations_field_data['latitude'])){
  7.  
  8. print theme('getlocations_latitude_dms', $on_the_map_getlocations_field_data);
  9. print ' ';
  10. print theme('getlocations_longitude_dms', $on_the_map_getlocations_field_data);
  11. }
  12. }
  13. ?>

Hát ez így elég okádék, szóval ezt szeretném lecserélni olyan megoldásra, hogy mindezt modulból intézem el, normálisan, nem adatbázisban tárolva a kódot.

Másik példa: van egy Hierarchical Select fieldem, itt pl. a kiválasztott taxonómiaelem szülőjét is szeretném kiíratni egy külön fieldbe.

Előre is köszi!

Melyik modulhoz, modulokhoz kapcsolódik a téma?: 
Drupal verzió: 
szantog képe

Én úgy szoktam, hogy _node_preprocessben állítok változót neki, pl $vars['gps'], és egy ds preprocess fieldben adom hozzá, aminek a machine nameje gps. Ja, és moduleban a preprocesst, hogy esetleg másik sminknél ne legyen gáz. Kb ez volt idáig a legyszerűbb mód, ha ilyen kódolt nyavalyákat kellett nodebaszúrni.

1
0

----
Rájöttem, miért kérdezek olyan ritkán a drupal.hu-n. Amíg szedem össze az infokat a kérdéshez, mindig rájövök a megoldásra.

Sk8erPeter képe

Köszi a választ, akkor tehát első lépés: template_preprocess_node() felülbírálása modulban, aztán második lépés az, hogy "egy ds preprocess fieldben adom hozzá, aminek a machine nameje gps", de konkrétan melyik, Display Suite által kínált hookra gondolsz, amit implementálni kéne?

És így látszani fog a többi közt az admin-felületen, átpakolható lesz, meghatározva a sorrendet, stb.?
Köszi!

0
0
szantog képe

nem kell semmilyen ds vudu. Bármilyen változó, ami _node_preprocessből elérhető, hozzáadható preprocess fieldként dshez admin/structure/ds/fields/manage_preprocess: Ha csinálsz egy $vars['gps']-t a preprocessben, akkor itt hozzáadod, a lényeg, hogy a machine name a gps legyen, és ugyanolyan cibálható mező lesz, mint az összes többi.

1
0

----
Rájöttem, miért kérdezek olyan ritkán a drupal.hu-n. Amíg szedem össze az infokat a kérdéshez, mindig rájövök a megoldásra.

Sk8erPeter képe

OK, köszi, így már teljesen világos, működőképes is a dolog! Viszont az a problémám vele, hogy így nem csak adott content type-nál látszik pl. épp ez a GPS-mező, hanem ott is, ahol nem kéne (mármint persze ahol egyáltalán alkalmaztam a DS-layoutot).
Attól függetlenül, hogy mondjuk ez is bent van:

  1. if($variables['type'] == 'test_content_type'){
  2. $variables['blabla'] = 'ez a blabla variable, asdasd';
  3. }

Mivel a DS-ben hozzáadtam már, mint preprocess fieldet. Ott pedig nem lehet bundle-re korlátozni, csak entity type-ra.

Pl. egy mezei article content type-nál a GPS-mező nem szükséges.
Hogyan lehet ezt még szebben megoldani?

=============================
SZERK.: Na, most látom, hogy csak a Display Suite 7.x-1.6-os változatában nem lehet korlátozni, mert nincs ott a "Limit field" mező ("Limit this field on field UI per bundles and/or view modes. The values are in the form of $bundle|$view_mode. You may use * to select all. Enter multiple values per line.") A 7.x-2.0 változatnál már ott van!
DE továbbra is érdekelne ennek a modulbeli, Display Suite NÉLKÜLI megoldása (pl. ahol nincs telepítve a DS, ott kellhet). Ha már... :)
=============================

Amit még eddig nem próbáltam, az pl. a field_attach_preprocess() függvény (persze még sok más is), ezzel, vagy valami tök más függvénnyel nem tudom ezt valahogy megoldani?

Pl. a template_preprocess_node()-ban van egy ilyen:

  1. // Make the field variables available with the appropriate language.
  2. field_attach_preprocess('node', $node, $variables['content'], $variables);

Lehet, hogy köze nincs ahhoz, amiről beszélek, de hátha.
0
0
Sk8erPeter képe

Ahogy tartottam tőle, mindez Field grouppal nem működik, azt valahogy a
$variables['content']['group_tökmindegy']
tömbbe kéne valahogy beletákolni.

Ez csak azért meglepő, mert a code field Field grouppal együtt is hibátlanul megy. Mondjuk gondolom ott azért megy, mert a Display Suite valahogy elintézi a fentit. Vagy a korábban a field_attach_preprocess()-t használja, majd megnézem.

0
0
Sk8erPeter képe

Hát ez jó, itt lényegében ugyanazt mondják el, amiről itt beszélgetünk, kóddal illusztrálva:

http://www.lullabot.com/articles/display-suite-building-fancy-teasers-wi...

Viszont itt sem alkalmaznak semmi egyéb trükköt, tehát egyelőre betudom tényleg a Field group hibájának, bár lehet, hogy kellene mégis bevetni valami egyebet, meg lehet, hogy a module weight számít, fogalmam sincs...

Nem jut eszébe valakinek megoldás?

Most a template_preprocess_node-ban hiába adom hozzá a $variables['content']-hez is, akkor is a node legeslegvégén jelenik meg a mező értéke, de ráadásul label nélkül!

  1. $variables['akármi_gps'] = 'ide függvénnyel pakolok sima stringet';
  2. $variables['content']['group_tökmindegy_datasheet']['akármi_gps'] = $variables['akármi_gps'];
0
0
szantog képe

Ezt én is benyaltam.
A lényeg, hogy a preprocess fieldnek még nincs értéke, amikor a $content állítódik össze, mivel a preprocess olyankor még nem hívódik meg.

Szóval kicsi kézzel lehet hook_ds_fields_infoba beírni:

  1. function MODULE_ds_fields_info($entity_type) {
  2. $fields = array();
  3. $fields['my_field'] = array(
  4. 'title' => t('opps'),
  5. 'field_type' => DS_FIELD_TYPE_FUNCTION,
  6. 'function' => 'my_function',
  7. );
  8. return array('node' => $fields);
  9. }

És persze kell egy function my_function($params), ahol a $paramsban minden elérehető, ami kell.

1
0

----
Rájöttem, miért kérdezek olyan ritkán a drupal.hu-n. Amíg szedem össze az infokat a kérdéshez, mindig rájövök a megoldásra.

Sk8erPeter képe

Jaja, köszi, én is itt kezdtem el utánanézni a tisztességesebb megoldásoknak (ennél a kérdésnél a D6-osra vonatkozott):
http://drupal.hu/comment/68390#comment-68390

Akkor láttam ezt a DS_FIELD_TYPE_FUNCTION-t.

Ezenkívül találtam ezt a cikket, ami igen röviden, lényegre törően összefoglalja, miről is van szó:

Creating custom display suite fields or how I learned to stop worrying and use hook_ds_fields_info()
http://previousnext.com.au/blog/creating-custom-display-suite-fields-or-...

Kipróbálni még nem volt időm, de mindenképp visszajelzek, ha megtörtént.

0
0
Sk8erPeter képe

Még azt néztem egyébként, hogy valszeg kódból bundle-re és view mode-ra korlátozni a 'ui_limit' kulcssal lehet:

'ui_limit' => array('article|full', '*|search_index'),

innen:
hook_ds_fields_info()
http://drupalcontrib.org/api/drupal/contributions!ds!ds.api.php/function...

0
0
Sk8erPeter képe

Az előbb linkelt cikk, a hook_ds_fields_info() tanulmányozása, meg persze szantog sok tanácsa rengeteget segített abban, hogy ezek után mindössze 10 perc volt működésre bírni, amit szerettem volna, mindenféle csúnya textarea-kba behányt PHP-kódok nélkül, szépen fájlban tartva a kódot.

Nálam egy Get Locations field térképen bejelölt koordinátáinak kinyerése volt a cél egy adott bundle-nél (itt: mytestbundle), minden view mode-ra érvényesen (*), annak érdekében, hogy ezt egy külön GPS-mezőként is meg tudjam mutatni, és oda húzhassam a "Manage display" fülön, a Display Suite régiói között, ahol szükségem van rá. Természetesen ellenőrizni kellett, hogy egyáltalán ez a mező be van-e állítva, vagy nincs.
Figyelem, az alábbi kódban a mező nyelvsemlegessége "be van drótozva" (lásd 'und' kulcs), tehát amennyiben valakinél a mezőfordítás be van állítva az adott mezőre, akkor ez a kód pici átalakításra szorul, tehát csak szemléltető jelleggel mutatom meg, de talán másnak is hasznos lehet. A lényeg látható belőle: az entitás egyéb mezőinek értéke is elérhető.
Természetesen a MYMODULE helyettesítendő a saját modulunk nevével.

  1. /**
  2.  * @see http://previousnext.com.au/blog/creating-custom-display-suite-fields-or-how-i-learned-stop-worrying-and-use-hookdsfieldsinfo
  3.  */
  4.  
  5. /**
  6.  * Implements hook_ds_fields_info().
  7.  * @see http://drupalcontrib.org/api/drupal/contributions!ds!ds.api.php/function/hook_ds_fields_info/7
  8.  */
  9. function MYMODULE_ds_fields_info($entity_type) {
  10. $fields = array();
  11.  
  12. $fields['node']['mytestbundle_gps'] = array(
  13. // title: title of the field
  14. 'title' => t('GPS'),
  15. // type: type of field
  16. // - DS_FIELD_TYPE_FUNCTION : calls a custom function.
  17. 'field_type' => DS_FIELD_TYPE_FUNCTION,
  18. // ui_limit : only used for the manage display screen so
  19. // you can limit fields to show based on bundles or view modes
  20. // the values are always in the form of $bundle|$view_mode
  21. // You may use * to select all.
  22. // Make sure you use the machine name.
  23. 'ui_limit' => array('mytestbundle|*'),
  24. // function: only for DS_FIELD_TYPE_FUNCTION.
  25. 'function' => 'MYMODULE_mytestbundle_ds_field_gps',
  26. );
  27.  
  28. if (isset($fields[$entity_type])) {
  29. return array($entity_type => $fields[$entity_type]);
  30. }
  31. return array();
  32. }
  33.  
  34. /**
  35.  * Generate GPS coordinates as a DS field
  36.  * Example: 46° 2' 27.24" N 18° 40' 37.2" E
  37.  */
  38. function MYMODULE_mytestbundle_ds_field_gps($field, $title = NULL){
  39. $output = '';
  40.  
  41. if(isset($field['entity']->field_teststuff_on_the_map['und'][0])){
  42. $on_the_map_getlocations_field_data = $field['entity']->field_teststuff_on_the_map['und'][0];
  43.  
  44. if(isset($on_the_map_getlocations_field_data['latitude']) && isset($on_the_map_getlocations_field_data['latitude'])){
  45. $output .= theme('getlocations_latitude_dms', $on_the_map_getlocations_field_data);
  46. $output .= ' ';
  47. $output .= theme('getlocations_longitude_dms', $on_the_map_getlocations_field_data);
  48. }
  49. }
  50.  
  51. return $output;
  52. }
2
0
Sk8erPeter képe

Javítom magam:

Figyelem, az alábbi kódban a mező nyelvsemlegessége "be van drótozva" (lásd 'und' kulcs)

Ez egy csúnya megoldás, ami elkerülhető a field_get_items() használatával.

Ehhez ezt a cikket nagyon tudom ajánlani:
http://www.computerminds.co.uk/articles/rendering-drupal-7-fields-right-way
Aki a moduljában/sminkjében fieldekkel babrál, annak itt megfontolandó tanácsok vannak, konkrétan az előbb linkelt field_get_items() és a field_view_value(), ill. a field_view_field() használata javasolt.

Tehát ami ROSSZ:

  1. // ROSSZ
  2. $block['content'] = $node->field_name['und'][0]['safe_value'];

HELYETTE JÓ PÉLDÁK:

$output = field_view_field('node', $node, 'field_name');

  1. $node = node_load($nid);
  2. $field = field_get_items('node', $node, 'field_name');
  3. $output = field_view_value('node', $node, 'field_name', $field[$delta]);

  1. $node = node_load($nid);
  2. $image = field_get_items('node', $node, 'field_image');
  3. $output = field_view_value('node', $node, 'field_image', $image[0], array(
  4. 'type' => 'image',
  5. 'settings' => array(
  6. 'image_style' => 'thumbnail',
  7. 'image_link' => 'content',
  8. ),
  9. ));

=========================

Ezek alapján a javított kód:
(a kód első fele jó, tehát a hook_ds_fields_info() implementálása ugyanaz marad)

http://drupal.stackexchange.com/questions/45198/how-to-output-get-locati...

  1. /**
  2.  * Generate GPS coordinates as a DS field
  3.  * Example: 46° 2' 27.24" N 18° 40' 37.2" E
  4.  */
  5. function MYMODULE_mytestbundle_ds_field_gps($field, $title = NULL){
  6. $output = '';
  7.  
  8. // http://www.computerminds.co.uk/articles/rendering-drupal-7-fields-right-way
  9. // instead of the ugly $on_the_map_getlocations_field_data = $field['entity']->field_teststuff_on_the_map['und'][0];
  10. $on_the_map_getlocations_field = field_get_items('node', $field['entity'], 'field_teststuff_on_the_map');
  11.  
  12.  
  13. if(isset($on_the_map_getlocations_field[0])){
  14. $on_the_map_getlocations_field_data = $on_the_map_getlocations_field[0];
  15.  
  16. if(isset($on_the_map_getlocations_field_data['latitude']) && isset($on_the_map_getlocations_field_data['latitude'])){
  17. $output .= theme('getlocations_latitude_dms', $on_the_map_getlocations_field_data);
  18. $output .= ' ';
  19. $output .= theme('getlocations_longitude_dms', $on_the_map_getlocations_field_data);
  20. }
  21. }
  22.  
  23. return $output;
  24. }
2
0