0

How does data in file/[id]/usage get compiled?

From what tables does it determine a use?

Is there a way to track down how/where it gets this data and troubleshoot? Does it take include revision data?

  • 3
    I think instead of throwing a bounty on that question you should try to enhance it. Make it relevant to others, make it reproducible, provide context, all that. In the current state it's nearly completely unclear what you're actually asking. – leymannx Feb 17 at 18:12
  • 1
    Yeah, there's absolutely no way to answer this question definitely. You're essentially asking every possible way you could produce bad DB foreign keys and troubleshoot how it could happen. That's too abstract and isn't really Drupal specific. – Shawn Conn Feb 18 at 8:44
  • I'm simply asking where the revision data comes from. Not too far fetched. It is relevant to others since I've seen this issue unanswered elsewhere. – Sam Feb 18 at 14:37
  • Relevant to others means making others think: oh yes, this question indeed needs a good answer. Right now the only correct answer to your question is: revision data comes from the database. Not too far fetched. But I guess this is not what you want. So please help us to help you. :) – leymannx Feb 18 at 22:04
  • @leymannx This question indeed is relevant to others, and saying in the database is being pedantic but I have adjusted grammar to be more clear. – Sam Feb 19 at 2:23
1
+50

This route is provided by the File Entity module. See the hook_menu() implementation where it's registering a callback for that page: file_entity_usage_page.

$items['file/%file/usage'] = array(
  'title' => 'Usage',
  'page callback' => 'file_entity_usage_page',
  'page arguments' => array(1),
  'access callback' => 'file_entity_access',
  'access arguments' => array('update', 1),
  'type' => MENU_LOCAL_TASK,
  'context' => MENU_CONTEXT_PAGE,
  'file' => 'file_entity.pages.inc',
);

Inside file_entity_usage_page() in the file_entity.pages.inc file following function from core's includes/file.inc gets called which retrieves the information directly from the file_usage table.

function file_usage_list(stdClass $file) {
  $result = db_select('file_usage', 'f')
    ->fields('f', array('module', 'type', 'id', 'count'))
    ->condition('fid', $file->fid)
    ->condition('count', 0, '>')
    ->execute();
  $references = array();
  foreach ($result as $usage) {
    $references[$usage->module][$usage->type][$usage->id] = $usage->count;
  }
  return $references;
}

Core's includes/file.inc file provides the API for handling file uploads and server file management. It also provides a function file_usage_add() which gets called every time a managed file gets uploaded and which adds newly added file IDs to the file_usage table.

function file_usage_add(stdClass $file, $module, $type, $id, $count = 1) {
  db_merge('file_usage')
    ->key(array(
      'fid' => $file->fid,
      'module' => $module,
      'type' => $type,
      'id' => $id,
    ))
    ->fields(array('count' => $count))
    ->expression('count', 'count + :count', array(':count' => $count))
    ->execute();
}

The file_usage table gets installed from core upon Drupal installation from modules/system/system.install's function system_schema().

$schema['file_usage'] = array(
  'description' => 'Track where a file is used.',
  'fields' => array(
    'fid' => array(
      'description' => 'File ID.',
      'type' => 'int',
      'unsigned' => TRUE,
      'not null' => TRUE,
    ),
    'module' => array(
      'description' => 'The name of the module that is using the file.',
      'type' => 'varchar',
      'length' => 255,
      'not null' => TRUE,
      'default' => '',
    ),
    'type' => array(
      'description' => 'The name of the object type in which the file is used.',
      'type' => 'varchar',
      'length' => 64,
      'not null' => TRUE,
      'default' => '',
    ),
    'id' => array(
      'description' => 'The primary key of the object using the file.',
      'type' => 'int',
      'unsigned' => TRUE,
      'not null' => TRUE,
      'default' => 0,
    ),
    'count' => array(
      'description' => 'The number of times this file is used by this object.',
      'type' => 'int',
      'unsigned' => TRUE,
      'not null' => TRUE,
      'default' => 0,
    ),
  ),
  'primary key' => array('fid', 'type', 'id', 'module'),
  'indexes' => array(
    'type_id' => array('type', 'id'),
    'fid_count' => array('fid', 'count'),
    'fid_module' => array('fid', 'module'),
  ),
);

Yes, on file/%file/usage not only the nodes get listed where a certain file is being referenced, also node revisions are listed.

enter image description here

On file/%file/edit then you have the option to replace this file on all listed places, and as another option to "Keep (the) original filename", which then replaces the file everywhere it's being used and keeps its former URL intact.

1

I couldn't find any /usage path in core. You must be using a custom or contrib file manager module.

From what tables does it determine a use?

According to file_usage_list the file usage info is stored in the file_usage table, so I bet the custom or contrib module must be reading from there.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.