web-dev-qa-db-fra.com

Comment puis-je obtenir entity_type et entity_id à partir d'une page d'entité?

Certaines pages (chemins) représentent une entité. Par exemple:

  • Les pages de ces chemins représentent une entité de nœud, entity_id (nid) est XX:
    • / node/xx
    • / node/xx/delete
    • / node/xx/edit
  • La page de ce chemin représente une entité de serveur de recherche (définie par le module API de recherche), entity_id (nom_machine) est 'Apache_solr':
    • / admin/config/search/search_api/server/Apache_solr

Comment chargez-vous les données de base sur cette entité (id et type) lorsque le hook ou la fonction dans laquelle vous vous trouvez ne vous la remet pas?

La manière standard d'obtenir l'entité courante est apparemment d'utilisermenu_get_object($entity_type,$position_of_id_in_url) . Cependant, cela suppose que vous codez pour un seul type d'entité: vous devez indiquer le type d'entité par programme et, pire encore, vous, l'être humain, devez rechercher et coder en dur dans la position URL des ID d'entité que cette entité utilise .

Le plus proche que je puisse trouver jusqu'à présent est d'obtenir l'URI du système sous-jacent pour la page (par exemple substr(request_uri(),strlen($base_path))), puis d'écrire une liste de commutateurs monstrueuse basée sur quelque chose comme cette suggestion , deviner, puis des cas de codage en dur pour chaque entité possible que vous pensez qu'un site pourrait avoir. Mais il doit y avoir quelque chose de mieux que ça, non?

Bien qu'une solution générale à partir du noyau soit la meilleure, j'accepterai également une réponse qui dépend de modules communs tels que ctools (gestionnaire de pages, contextes, etc.), API d'entité , Devel , etc.

Mon besoin immédiat est de modifier les formulaires, dans hook_field_widget_form() , pour un widget qui peut (avec la configuration et les modules appropriés) être attaché à tout type d'entité champable. Donc, même si une solution générale serait la meilleure, j'accepterais également une réponse étroite qui ne fonctionne que dans cette fonction ou dans les formulaires (l'id et les données spécifiques au type d'entité semblent être enterrés dans $ form, mais saisis dans une entité type spécifique, donc le retirer de $ form semble être un problème de poulet et d'oeuf).

------------ ÉDITER ------------------

Il semble que certaines personnes ont du mal à comprendre le problème général simple. Voici un autre cas d'utilisation (un autre problème séparé mais connexe auquel je suis confronté). Supposons que vous ayez une vue qui répertorie certaines entités. Cette vue se présente comme un bloc/volet sur les pages qui peuvent représenter une entité, comme une page de nœud ou un profil utilisateur (ou les deux). Vous disposez d'un hook configuré qui lit les données des vues et examine les résultats (foreach $view->result as...). Disons que c'est hook_views_pre_render , ce qui signifie que vous n'avez que l'objet $ view. Vous voulez faire quelque chose (par exemple, supprimer la ligne ou modifier certaines données de champ) si la ligne des résultats de la vue a le même ID d'entité et le même type d'entité que la page. Vous avez la logique pour extraire ces données des résultats de la vue, donc tout ce dont vous avez besoin est de rechercher le entity_type et entity_id de la page en cours de génération, pour faire une comparaison. Ces données sont dans Drupal quelque part. Si ce n'était pas le cas, Drupal n'aurait pas pu comprendre qu'il devait charger cette vue. Alors, comment voulez-vous l'obtenir lorsqu'il n'est pas transmis au crochet ou à la fonction dans laquelle vous vous trouvez?

J'ai repéré quelque chose qui fonctionne comme ceci dans le module Token Filter (version D7):

  // Attempt to fetch the entity that is being viewed via a backtrace to the
  // field_attach_view($entity_type, $entity) function and parameters §if found.
    $backtrace = debug_backtrace();
    foreach ($backtrace as $caller) {
      if ($caller['function'] == 'field_attach_view') {
        $entity_type = $caller['args'][0];
        $entity = $caller['args'][2];
        // do stuff with entity
        break;
      }  
    } 

Assez intelligent - il comprend une fonction qui doit s'être produite avant d'appeler sa fonction qui contiendra $ entity_type et $ entity ($ entity_id fonctionnerait également à la place de $ entity), et regarde en arrière à travers l'objet backtrace jusqu'à ce qu'il le trouve.

Token Filter est un module de traitement de champ, il saura donc que sa fonction aura toujours été appelée après un appel à field_attach_view () . Je ne suis pas s'il y a une bonne alternative générique à field_attach_view - mais l'approche générale semble fonctionner et un candidat spécifique à la casse peut toujours être trouvé pour n'importe quel cas spécifique en supprimant code de débogage de la trace (anciennement lien cassé corrigé) dans le point du code où vous devez obtenir l'entité, et voir ce qui est disponible (puis vérifier la logique et tester pour vous assurer qu'elle est toujours présente).

4

Dans Drupal Core, vous ne pouvez pas le faire. Le problème pertinent pour ajouter une telle fonctionnalité est ici .

Ce que le noyau lui-même fait toujours passer autour de deux arguments:

function($entity, $entity_type)
4
Letharion

La manière la plus simple que j'ai trouvée pour résoudre ce problème est d'implémenter hook_entity_load() .

function MODULE_entity_load($entities, $entity_type) {
  foreach ($entities as $entity) {
    $entity->entity_type = $entity_type;
  }
}

Ensuite, l'objet renvoyé par menu_get_object() aura un entity_type lié.

4
Kai

Ce qui suit me permet d'obtenir l'entité et le type d'entité par chemin:

/**
 * Get the entity and entity-type by path.
 *
 * @param string $path
 *   The path to the entity page.
 * @return array|boolean
 *   Contains the entity and the entity-type or false if entity or type could
 *   not be determinded.
 */
function custom_module_get_entity_and_entity_type_by_path($path) {
  $item = menu_get_item($_GET['internal_path']);
  if (empty($item['access']) || empty($item['page_arguments'][0]) || empty($item['load_functions'])) {
    return FALSE;
  }

  $entity = $item['page_arguments'][0];

  // Get entity-type.
  $load_function = reset($item['load_functions']);
  $entity_types = entity_get_info();
  dpm($entity_types);
  $entity_type = '';
  foreach ($entity_types as $type => $type_definition) {
    if ($load_function == $type_definition['load hook']) {
      // When the load_function from menu_get_item matches "load hook" of the
      // entity type definition, then the entity_type was found.
      $entity_type = $type;
      break;
    }
  }
  if (!$entity_type) {
    return FALSE;
  }

  return array('entity' => $entity, 'entity_type' => $entity_type);
}
1
LarS

cela peut-il aider?

function entity_by_path($path) {
    $router_item = menu_get_item($path);

    $ent_sug_array = array();
    foreach ($router_item['map'] as $key => $value) {
        if(is_object($value) && isset($value->type)) {
           $ent_sug_array[$key] =  $value;
        }
    }

    $ent_sug = false;
    if(count($ent_sug_array) > 1) {
        $lf_sug = false;
        if(isset($router_item['load_functions'])) {
            if(count($router_item['load_functions']) == 1) {
                reset($router_item['load_functions']);
                $lf_sug = key($router_item['load_functions']);
            }
        }
        if($lf_sug !== false) {
            $ent_sug = is_object($router_item['map'][$lg_sug] && isset($router_item['map'][$lg_sug]->type)) ? $router_item['map'][$lg_sug] : $ent_sug;
        }
    } elseif(count($ent_sug_array) == 1) {
        $ent_sug = reset($ent_sug_array);
    }

    if(!empty($ent_sug)) {
        $bundle = $ent_sug->type;
        $ent_type = method_exists($ent_sug, 'entityType') ? $ent_sug->entityType() : false; //eck case
        if(empty($ent_type)) {
            $aclass = get_class($ent_sug);
            if($aclass == 'stdClass') {
                //node, user, core entity case
                if(isset($router_item['load_functions'])) {
                    $lf = reset($router_item['load_functions']);
                    $ei = entity_get_info();
                    foreach ($ei as $key => $value) {
                        if(empty('load hook'))
                            continue;
                        if($lf == $value['load hook']) {
                            $ent_type = $key;
                            break;
                        }
                    }
                }
            }else{
                //custom entity case
                $ent_type = $aclass;
            }
        }

        return array('entity'=>$ent_sug, 'type'=>$ent_type, 'bundle'=>$bundle);
    }

    return false;
}