first import
This commit is contained in:
339
sites/all/modules/file_entity/LICENSE.txt
Normal file
339
sites/all/modules/file_entity/LICENSE.txt
Normal file
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
342
sites/all/modules/file_entity/file_entity.admin.inc
Normal file
342
sites/all/modules/file_entity/file_entity.admin.inc
Normal file
@@ -0,0 +1,342 @@
|
||||
<?php
|
||||
|
||||
require_once dirname(__FILE__) . '/file_entity.pages.inc';
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Administrative interface for file type configuration.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Administrative form for browsing files and performing operations on them.
|
||||
*/
|
||||
function file_entity_admin_files($form, &$form_state) {
|
||||
if (!empty($form_state['values']['operation'])) {
|
||||
// The form is being rebuilt because an operation requiring confirmation
|
||||
// was selected. Hand off to the callback of the operation at this point
|
||||
// which should return a confirm form.
|
||||
$operation = $form_state['values']['operation'];
|
||||
$files = array_keys(array_filter($form_state['values']['files']));
|
||||
return call_user_func_array($operation['callback'], array($files));
|
||||
}
|
||||
|
||||
$limit = variable_get('file_entity_admin_files_limit', 50);
|
||||
|
||||
// Build the 'Update options' form.
|
||||
$form['options'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Update options'),
|
||||
'#attributes' => array('class' => array('container-inline')),
|
||||
);
|
||||
|
||||
$options = array();
|
||||
$form['#operations'] = module_invoke_all('file_operations_info');
|
||||
drupal_alter('file_entity_file_operations', $form['#operations']);
|
||||
|
||||
foreach ($form['#operations'] as $operation => $array) {
|
||||
$options[$operation] = $array['label'];
|
||||
}
|
||||
$form['options']['operation'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Operation'),
|
||||
'#title_display' => 'invisible',
|
||||
'#options' => $options,
|
||||
);
|
||||
$form['options']['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Update'),
|
||||
);
|
||||
|
||||
// Build the sortable table header.
|
||||
$header = array(
|
||||
'title' => array('data' => t('Title'), 'field' => 'f.filename'),
|
||||
'type' => array('data' => t('Type'), 'field' => 'f.filemime'),
|
||||
'size' => array('data' => t('Size'), 'field' => 'f.filesize'),
|
||||
'author' => array('data' => t('Author'), 'field' => 'u.name'),
|
||||
'timestamp' => array('data' => t('Updated'), 'field' => 'f.timestamp', 'sort' => 'desc'),
|
||||
'operations' => array('data' => t('Operations')),
|
||||
);
|
||||
|
||||
$query = db_select('file_managed', 'f')->extend('PagerDefault')->extend('TableSort');
|
||||
$query->join('users', 'u', 'f.uid = u.uid');
|
||||
$query->fields('f', array('fid'));
|
||||
$query->fields('u', array('uid'));
|
||||
$query->condition('f.status', FILE_STATUS_PERMANENT);
|
||||
$query->limit($limit);
|
||||
$query->orderByHeader($header);
|
||||
|
||||
foreach (array_keys(file_entity_get_hidden_stream_wrappers()) as $name) {
|
||||
$query->condition('f.uri', $name . '%', 'NOT LIKE');
|
||||
}
|
||||
|
||||
$result = $query->execute()->fetchAllKeyed();
|
||||
$files = file_load_multiple(array_keys($result));
|
||||
$form['#files'] = $files;
|
||||
|
||||
// This is used to add usernames to the table below.
|
||||
$accounts = user_load_multiple(array_values($result));
|
||||
|
||||
$destination = drupal_get_destination();
|
||||
$options = array();
|
||||
foreach ($files as $file) {
|
||||
$options[$file->fid] = array(
|
||||
'title' => theme('file_entity_file_link', array('file' => $file)),
|
||||
'type' => check_plain($file->filemime),
|
||||
'size' => format_size($file->filesize),
|
||||
'author' => theme('username', array('account' => $accounts[$file->uid])),
|
||||
'timestamp' => format_date($file->timestamp, 'short'),
|
||||
);
|
||||
|
||||
$options[$file->fid]['operations'] = array(
|
||||
'data' => array(
|
||||
'#theme' => 'links__file_operations',
|
||||
'#links' => array(),
|
||||
'#attributes' => array('class' => array('links', 'inline')),
|
||||
),
|
||||
);
|
||||
|
||||
$options[$file->fid]['operations']['data']['#links']['edit'] = array(
|
||||
'title' => t('Edit'),
|
||||
'href' => 'file/' . $file->fid . '/edit',
|
||||
'query' => $destination,
|
||||
);
|
||||
|
||||
$options[$file->fid]['operations']['data']['#links']['delete'] = array(
|
||||
'title' => t('Delete'),
|
||||
'href' => 'file/' . $file->fid . '/delete',
|
||||
'query' => $destination,
|
||||
);
|
||||
}
|
||||
|
||||
$form['files'] = array(
|
||||
'#type' => 'tableselect',
|
||||
'#header' => $header,
|
||||
'#options' => $options,
|
||||
'#empty' => t('No files available.'),
|
||||
'#attributes' => array('class' => array('file-display-table', 'clear')),
|
||||
);
|
||||
$form['pager'] = array('#markup' => theme('pager', array('tags' => NULL)));
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate file_entity_admin_files form submissions.
|
||||
*
|
||||
* Check if any files have been selected to perform the chosen
|
||||
* 'Update option' on.
|
||||
*/
|
||||
function file_entity_admin_files_validate($form, &$form_state) {
|
||||
// Error if there are no items to select.
|
||||
if (!is_array($form_state['values']['files']) || !count(array_filter($form_state['values']['files']))) {
|
||||
form_set_error('', t('No files selected.'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit handler for file_entity_admin_files.
|
||||
*/
|
||||
function file_entity_admin_files_submit($form, &$form_state) {
|
||||
$operations = $form['#operations'];
|
||||
$operation = $operations[$form_state['values']['operation']];
|
||||
|
||||
// In the case of an operation which needs confirmation, rebuild the form.
|
||||
if (!empty($operation['confirm'])) {
|
||||
$form_state['rebuild'] = TRUE;
|
||||
$form_state['values']['operation'] = $operation;
|
||||
return;
|
||||
}
|
||||
|
||||
// Filter out unchecked nodes
|
||||
$files = array_filter($form_state['values']['files']);
|
||||
if ($function = $operation['callback']) {
|
||||
// Add in callback arguments if present.
|
||||
if (isset($operation['callback arguments'])) {
|
||||
$args = array_merge(array($files), $operation['callback arguments']);
|
||||
}
|
||||
else {
|
||||
$args = array($files);
|
||||
}
|
||||
call_user_func_array($function, $args);
|
||||
cache_clear_all();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the file type admin overview page.
|
||||
*/
|
||||
function file_entity_list_types_page() {
|
||||
$types = file_info_file_types();
|
||||
$entity_info = entity_get_info('file');
|
||||
$field_ui = module_exists('field_ui');
|
||||
$header = array(
|
||||
array('data' => t('Name')),
|
||||
array('data' => t('Operations'), 'colspan' => $field_ui ? '3' : '1'),
|
||||
);
|
||||
$rows = array();
|
||||
|
||||
foreach ($types as $type => $info) {
|
||||
$row = array(array('data' => theme('file_entity_file_type_overview', $info)));
|
||||
$path = isset($entity_info['bundles'][$type]['admin']['real path']) ? $entity_info['bundles'][$type]['admin']['real path'] : NULL;
|
||||
if ($field_ui) {
|
||||
$row[] = array('data' => isset($path) ? l(t('manage fields'), $path . '/fields') : '');
|
||||
$row[] = array('data' => isset($path) ? l(t('manage display'), $path . '/display') : '');
|
||||
}
|
||||
$row[] = array('data' => isset($path) ? l(t('manage file display'), $path . '/file-display') : '');
|
||||
$rows[] = $row;
|
||||
}
|
||||
|
||||
$build['file_type_table'] = array(
|
||||
'#theme' => 'table',
|
||||
'#header' => $header,
|
||||
'#rows' => $rows,
|
||||
'#empty' => t('No file types available.'),
|
||||
);
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form callback; presents file display settings for a given view mode.
|
||||
*/
|
||||
function file_entity_file_display_form($form, &$form_state, $file_type, $view_mode) {
|
||||
$form['#file_type'] = $file_type;
|
||||
$form['#view_mode'] = $view_mode;
|
||||
$form['#tree'] = TRUE;
|
||||
$form['#attached']['js'][] = drupal_get_path('module', 'file_entity') . '/file_entity.admin.js';
|
||||
|
||||
// Retrieve available formatters for this file type and load all configured
|
||||
// filters for existing text formats.
|
||||
$formatters = file_info_formatter_types();
|
||||
foreach ($formatters as $name => $formatter) {
|
||||
if (isset($formatter['file types']) && !in_array($file_type, $formatter['file types'])) {
|
||||
unset($formatters[$name]);
|
||||
}
|
||||
}
|
||||
$current_displays = file_displays_load($file_type, $view_mode, TRUE);
|
||||
foreach ($current_displays as $name => $display) {
|
||||
$current_displays[$name] = (array) $display;
|
||||
}
|
||||
|
||||
// Formatter status.
|
||||
$form['displays']['status'] = array(
|
||||
'#type' => 'item',
|
||||
'#title' => t('Enabled displays'),
|
||||
'#prefix' => '<div id="file-displays-status-wrapper">',
|
||||
'#suffix' => '</div>',
|
||||
);
|
||||
$i=0;
|
||||
foreach ($formatters as $name => $formatter) {
|
||||
$form['displays']['status'][$name] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => check_plain($formatter['label']),
|
||||
'#default_value' => !empty($current_displays[$name]['status']),
|
||||
'#description' => isset($formatter['description']) ? filter_xss($formatter['description']) : NULL,
|
||||
'#parents' => array('displays', $name, 'status'),
|
||||
'#weight' => (isset($formatter['weight']) ? $formatter['weight'] : 0) + ($i / 1000),
|
||||
);
|
||||
$i++;
|
||||
}
|
||||
|
||||
// Formatter order (tabledrag).
|
||||
$form['displays']['order'] = array(
|
||||
'#type' => 'item',
|
||||
'#title' => t('Display precedence order'),
|
||||
'#theme' => 'file_entity_file_display_order',
|
||||
);
|
||||
foreach ($formatters as $name => $formatter) {
|
||||
$form['displays']['order'][$name]['label'] = array(
|
||||
'#markup' => check_plain($formatter['label']),
|
||||
);
|
||||
$form['displays']['order'][$name]['weight'] = array(
|
||||
'#type' => 'weight',
|
||||
'#title' => t('Weight for @title', array('@title' => $formatter['label'])),
|
||||
'#title_display' => 'invisible',
|
||||
'#delta' => 50,
|
||||
'#default_value' => isset($current_displays[$name]['weight']) ? $current_displays[$name]['weight'] : 0,
|
||||
'#parents' => array('displays', $name, 'weight'),
|
||||
);
|
||||
$form['displays']['order'][$name]['#weight'] = $form['displays']['order'][$name]['weight']['#default_value'];
|
||||
}
|
||||
|
||||
// Formatter settings.
|
||||
$form['display_settings_title'] = array(
|
||||
'#type' => 'item',
|
||||
'#title' => t('Display settings'),
|
||||
);
|
||||
$form['display_settings'] = array(
|
||||
'#type' => 'vertical_tabs',
|
||||
);
|
||||
$i=0;
|
||||
foreach ($formatters as $name => $formatter) {
|
||||
if (isset($formatter['settings callback']) && ($function = $formatter['settings callback']) && function_exists($function)) {
|
||||
$defaults = !empty($formatter['default settings']) ? $formatter['default settings'] : array();
|
||||
$settings = !empty($current_displays[$name]['settings']) ? $current_displays[$name]['settings'] : array();
|
||||
$settings += $defaults;
|
||||
$settings_form = $function($form, $form_state, $settings, $name, $file_type, $view_mode);
|
||||
if (!empty($settings_form)) {
|
||||
$form['displays']['settings'][$name] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => check_plain($formatter['label']),
|
||||
'#parents' => array('displays', $name, 'settings'),
|
||||
'#group' => 'display_settings',
|
||||
'#weight' => (isset($formatter['weight']) ? $formatter['weight'] : 0) + ($i / 1000),
|
||||
) + $settings_form;
|
||||
}
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
|
||||
$form['actions'] = array('#type' => 'actions');
|
||||
$form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration'));
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process file display settings form submissions.
|
||||
*/
|
||||
function file_entity_file_display_form_submit($form, &$form_state) {
|
||||
$file_type = $form['#file_type'];
|
||||
$view_mode = $form['#view_mode'];
|
||||
$displays = isset($form_state['values']['displays']) ? $form_state['values']['displays'] : array();
|
||||
$displays_original = file_displays_load($file_type, $view_mode, TRUE);
|
||||
foreach ($displays as $formatter_name => $display) {
|
||||
$display_original = isset($displays_original[$formatter_name]) ? $displays_original[$formatter_name] : file_display_new($file_type, $view_mode, $formatter_name);
|
||||
$display += (array) $display_original;
|
||||
file_display_save((object) $display);
|
||||
}
|
||||
drupal_set_message(t('Your settings have been saved.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns HTML for a file type label and description for the file type admin overview page.
|
||||
*/
|
||||
function theme_file_entity_file_type_overview($variables) {
|
||||
return check_plain($variables['label']) . '<div class="description">' . $variables['description'] . '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns HTML for a file display's display order table.
|
||||
*/
|
||||
function theme_file_entity_file_display_order($variables) {
|
||||
$element = $variables['element'];
|
||||
|
||||
$rows = array();
|
||||
foreach (element_children($element, TRUE) as $name) {
|
||||
$element[$name]['weight']['#attributes']['class'][] = 'file-display-order-weight';
|
||||
$rows[] = array(
|
||||
'data' => array(
|
||||
drupal_render($element[$name]['label']),
|
||||
drupal_render($element[$name]['weight']),
|
||||
),
|
||||
'class' => array('draggable'),
|
||||
);
|
||||
}
|
||||
$output = drupal_render_children($element);
|
||||
$output .= theme('table', array('rows' => $rows, 'attributes' => array('id' => 'file-displays-order')));
|
||||
drupal_add_tabledrag('file-displays-order', 'order', 'sibling', 'file-display-order-weight', NULL, NULL, TRUE);
|
||||
|
||||
return $output;
|
||||
}
|
45
sites/all/modules/file_entity/file_entity.admin.js
Normal file
45
sites/all/modules/file_entity/file_entity.admin.js
Normal file
@@ -0,0 +1,45 @@
|
||||
|
||||
(function ($) {
|
||||
|
||||
Drupal.behaviors.fileDisplayStatus = {
|
||||
attach: function (context, settings) {
|
||||
$('#file-displays-status-wrapper input.form-checkbox', context).once('display-status', function () {
|
||||
var $checkbox = $(this);
|
||||
// Retrieve the tabledrag row belonging to this display.
|
||||
var $row = $('#' + $checkbox.attr('id').replace(/-status$/, '-weight'), context).closest('tr');
|
||||
// Retrieve the vertical tab belonging to this display.
|
||||
var tab = $('#' + $checkbox.attr('id').replace(/-status$/, '-settings'), context).data('verticalTab');
|
||||
|
||||
// Bind click handler to this checkbox to conditionally show and hide the
|
||||
// display's tableDrag row and vertical tab pane.
|
||||
$checkbox.bind('click.displayStatusUpdate', function () {
|
||||
if ($checkbox.is(':checked')) {
|
||||
$row.show();
|
||||
if (tab) {
|
||||
tab.tabShow().updateSummary();
|
||||
}
|
||||
}
|
||||
else {
|
||||
$row.hide();
|
||||
if (tab) {
|
||||
tab.tabHide().updateSummary();
|
||||
}
|
||||
}
|
||||
// Restripe table after toggling visibility of table row.
|
||||
Drupal.tableDrag['file-displays-order'].restripeTable();
|
||||
});
|
||||
|
||||
// Attach summary for configurable displays (only for screen-readers).
|
||||
if (tab) {
|
||||
tab.fieldset.drupalSetSummary(function (tabContext) {
|
||||
return $checkbox.is(':checked') ? Drupal.t('Enabled') : Drupal.t('Disabled');
|
||||
});
|
||||
}
|
||||
|
||||
// Trigger our bound click handler to update elements to initial state.
|
||||
$checkbox.triggerHandler('click.displayStatusUpdate');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery);
|
128
sites/all/modules/file_entity/file_entity.api.php
Normal file
128
sites/all/modules/file_entity/file_entity.api.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Hooks provided by the File Entity module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Define file types.
|
||||
*
|
||||
* @return
|
||||
* An array whose keys are file type names and whose values are arrays
|
||||
* describing the file type, with the following key/value pairs:
|
||||
* - label: The human-readable name of the file type.
|
||||
* - default view callback: (optional) The name of the function that returns a
|
||||
* drupal_render() array for displaying the file. Used when there are no
|
||||
* administrator configured file formatters, or none of the configured ones
|
||||
* return a display. See hook_file_type_TYPE_default_view() for details.
|
||||
* - description: (optional) A short description of the file type.
|
||||
* - weight: (optional) A number defining the order in which the 'claim
|
||||
* callback' function for this type is called relative to the claim
|
||||
* callbacks of other defined types, when the type of a file needs to be
|
||||
* determined. The type with the lowest weighted claim callback to return
|
||||
* TRUE is assigned to the file. Also, on administrative pages listing file
|
||||
* types, the types are ordered by weight.
|
||||
* - admin: (optional) An array of information, to be added to the
|
||||
* ['bundles'][TYPE]['admin'] entry for the 'file' entity type, thereby
|
||||
* controlling the path at which Field UI pages are attached for this file
|
||||
* type, and which users may access them. Defaults to attaching the Field UI
|
||||
* pages to the admin/config/media/file-types/manage/TYPE path and requiring
|
||||
* 'administer site configuration' permission. See hook_entity_info() for
|
||||
* details about this array. This value can also be set to NULL to suppress
|
||||
* Field UI pages from attaching at all for this file type.
|
||||
*
|
||||
* @see hook_file_type_info_alter()
|
||||
*/
|
||||
function hook_file_type_info() {
|
||||
return array(
|
||||
'image' => array(
|
||||
'label' => t('Image'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform alterations on file types.
|
||||
*
|
||||
* @param $info
|
||||
* Array of information on file types exposed by hook_file_type_info()
|
||||
* implementations.
|
||||
*/
|
||||
function hook_file_type_info_alter(&$info) {
|
||||
// @todo Add example.
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Add documentation.
|
||||
*
|
||||
* Note: This is not really a hook. The function name is manually specified via
|
||||
* 'default view callback' in hook_file_type_info(), with this recommended
|
||||
* callback name pattern.
|
||||
*/
|
||||
function hook_file_type_TYPE_default_view($file, $view_mode, $langcode) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Define file formatters.
|
||||
*
|
||||
* @return
|
||||
* An array whose keys are file formatter names and whose values are arrays
|
||||
* describing the formatter.
|
||||
*
|
||||
* @todo Document key/value pairs that comprise a formatter.
|
||||
*
|
||||
* @see hook_file_formatter_info_alter()
|
||||
*/
|
||||
function hook_file_formatter_info() {
|
||||
// @todo Add example.
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform alterations on file formatters.
|
||||
*
|
||||
* @param $info
|
||||
* Array of information on file formatters exposed by
|
||||
* hook_file_formatter_info() implementations.
|
||||
*/
|
||||
function hook_file_formatter_info_alter(&$info) {
|
||||
// @todo Add example.
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Add documentation.
|
||||
*
|
||||
* Note: This is not really a hook. The function name is manually specified via
|
||||
* 'view callback' in hook_file_formatter_info(), with this recommended callback
|
||||
* name pattern.
|
||||
*/
|
||||
function hook_file_formatter_FORMATTER_view($file, $display, $langcode) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Add documentation.
|
||||
*
|
||||
* Note: This is not really a hook. The function name is manually specified via
|
||||
* 'settings callback' in hook_file_formatter_info(), with this recommended
|
||||
* callback name pattern.
|
||||
*/
|
||||
function hook_file_formatter_FORMATTER_settings($form, &$form_state, $settings) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Add documentation.
|
||||
*/
|
||||
function hook_file_displays_alter($displays, $file, $view_mode) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Add documentation.
|
||||
*/
|
||||
function hook_file_view($file, $view_mode, $langcode) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Add documentation.
|
||||
*/
|
||||
function hook_file_view_alter($build, $type) {
|
||||
}
|
117
sites/all/modules/file_entity/file_entity.field.inc
Normal file
117
sites/all/modules/file_entity/file_entity.field.inc
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Field API integration for the file_entity module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_field_formatter_info().
|
||||
*/
|
||||
function file_entity_field_formatter_info() {
|
||||
$info['file_rendered'] = array(
|
||||
'label' => t('Rendered file'),
|
||||
'description' => t('Display the file in a specific view mode'),
|
||||
'field types' => array('file', 'image'),
|
||||
'settings' => array('file_view_mode' => 'default'),
|
||||
);
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_formatter_settings_form().
|
||||
*/
|
||||
function file_entity_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
|
||||
$display = $instance['display'][$view_mode];
|
||||
$settings = $display['settings'];
|
||||
$element = array();
|
||||
|
||||
if ($display['type'] == 'file_rendered') {
|
||||
$element['file_view_mode'] = array(
|
||||
'#title' => t('View mode'),
|
||||
'#type' => 'select',
|
||||
'#options' => file_entity_view_mode_labels(),
|
||||
'#default_value' => $settings['file_view_mode'],
|
||||
// Never empty, so no #empty_option
|
||||
);
|
||||
}
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_formatter_settings_summary().
|
||||
*/
|
||||
function file_entity_field_formatter_settings_summary($field, $instance, $view_mode) {
|
||||
$display = $instance['display'][$view_mode];
|
||||
$settings = $display['settings'];
|
||||
$summary = NULL;
|
||||
|
||||
if ($display['type'] === 'file_rendered') {
|
||||
$view_mode_label = file_entity_view_mode_label($settings['file_view_mode'], t('Unknown'));
|
||||
$summary = t('View mode: %mode', array('%mode' => $view_mode_label));
|
||||
}
|
||||
|
||||
return $summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_formatter_view().
|
||||
*/
|
||||
function file_entity_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
|
||||
$settings = $display['settings'];
|
||||
$element = array();
|
||||
|
||||
if ($display['type'] == 'file_rendered') {
|
||||
$view_mode = $settings['file_view_mode'];
|
||||
|
||||
// To prevent infinite recursion caused by reference cycles, we store
|
||||
// diplayed nodes in a recursion queue.
|
||||
$recursion_queue = &drupal_static(__FUNCTION__, array());
|
||||
|
||||
// If no 'referencing entity' is set, we are starting a new 'reference
|
||||
// thread' and need to reset the queue.
|
||||
// @todo Bug: $entity->referencing_entity on files referenced in a different
|
||||
// thread on the page. E.g: 1 references 1+2 / 2 references 1+2 / visit homepage.
|
||||
// We'd need a more accurate way...
|
||||
if (!isset($entity->referencing_entity)) {
|
||||
$recursion_queue = array();
|
||||
}
|
||||
|
||||
// The recursion queue only needs to track files.
|
||||
if ($entity_type == 'file') {
|
||||
list($id) = entity_extract_ids($entity_type, $entity);
|
||||
$recursion_queue[$id] = $id;
|
||||
}
|
||||
|
||||
// Prevent 'empty' fields from causing a WSOD.
|
||||
$items = array_filter($items);
|
||||
|
||||
// Check the recursion queue to determine which nodes should be fully
|
||||
// displayed, and which nodes will only be displayed as a title.
|
||||
$files_display = array();
|
||||
foreach ($items as $delta => $item) {
|
||||
if (!isset($recursion_queue[$item['fid']])) {
|
||||
$files_display[$item['fid']] = file_load($item['fid']);
|
||||
}
|
||||
}
|
||||
|
||||
// Load and build the fully displayed nodes.
|
||||
if ($files_display) {
|
||||
foreach ($files_display as $fid => $file) {
|
||||
$files_display[$fid]->referencing_entity = $entity;
|
||||
$files_display[$fid]->referencing_field = $field['field_name'];
|
||||
}
|
||||
$files_built = file_view_multiple($files_display, $view_mode);
|
||||
}
|
||||
|
||||
// Assemble the render array.
|
||||
foreach ($items as $delta => $item) {
|
||||
if (isset($files_built[$item['fid']])) {
|
||||
$element[$delta] = $files_built[$item['fid']];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $element;
|
||||
}
|
526
sites/all/modules/file_entity/file_entity.file_api.inc
Normal file
526
sites/all/modules/file_entity/file_entity.file_api.inc
Normal file
@@ -0,0 +1,526 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* API extensions of Drupal core's file.inc.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns information about file types from hook_file_type_info().
|
||||
*
|
||||
* @param $file_type
|
||||
* (optional) A file type name. If ommitted, all file types will be returned.
|
||||
*
|
||||
* @return
|
||||
* Either a file type description, as provided by hook_file_type_info(), or an
|
||||
* array of all existing file types, keyed by file type name.
|
||||
*/
|
||||
function file_info_file_types($file_type = NULL) {
|
||||
$info = &drupal_static(__FUNCTION__);
|
||||
if (!isset($info)) {
|
||||
$info = module_invoke_all('file_type_info');
|
||||
|
||||
// Add support for the standard file types until this can be fully
|
||||
// abstracted out of Media module.
|
||||
$info += array(
|
||||
'application' => array('label' => t('Application (multipurpose)')),
|
||||
'audio' => array('label' => t('Audio')),
|
||||
'image' => array('label' => t('Image')),
|
||||
'text' => array('label' => t('Text')),
|
||||
'video' => array('label' => t('Video')),
|
||||
);
|
||||
|
||||
drupal_alter('file_type_info', $info);
|
||||
uasort($info, '_file_entity_sort_weight_label');
|
||||
}
|
||||
if ($file_type) {
|
||||
if (isset($info[$file_type])) {
|
||||
return $info[$file_type];
|
||||
}
|
||||
}
|
||||
else {
|
||||
return $info;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the file type of a passed in file object.
|
||||
*
|
||||
* The file type is determined by extracting the 'first' part of the file's
|
||||
* MIME type. For example, a PNG image with a MIME type of 'image/png' will
|
||||
* have a file type of 'image'.
|
||||
*
|
||||
* @link http://www.iana.org/assignments/media-types/index.html IANA list of official MIME media types @endlink
|
||||
*/
|
||||
function file_get_type($file) {
|
||||
// Ensure that a MIME type has been determined first.
|
||||
if (empty($file->filemime)) {
|
||||
$file->filemime = file_get_mimetype($file->uri);
|
||||
}
|
||||
return substr($file->filemime, 0, strpos($file->filemime, '/'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about file formatters from hook_file_formatter_info().
|
||||
*
|
||||
* @param $formatter_type
|
||||
* (optional) A file formatter type name. If ommitted, all file formatter
|
||||
* will be returned.
|
||||
*
|
||||
* @return
|
||||
* Either a file formatter description, as provided by
|
||||
* hook_file_formatter_info(), or an array of all existing file formatters,
|
||||
* keyed by formatter type name.
|
||||
*/
|
||||
function file_info_formatter_types($formatter_type = NULL) {
|
||||
$info = &drupal_static(__FUNCTION__);
|
||||
if (!isset($info)) {
|
||||
$info = module_invoke_all('file_formatter_info');
|
||||
drupal_alter('file_formatter_info', $info);
|
||||
uasort($info, '_file_entity_sort_weight_label');
|
||||
}
|
||||
if ($formatter_type) {
|
||||
if (isset($info[$formatter_type])) {
|
||||
return $info[$formatter_type];
|
||||
}
|
||||
}
|
||||
else {
|
||||
return $info;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the file info cache.
|
||||
*/
|
||||
function file_info_cache_clear() {
|
||||
drupal_static_reset('file_info_file_types');
|
||||
drupal_static_reset('file_info_formatter_types');
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a drupal_render() style array from an array of loaded files.
|
||||
*
|
||||
* @param $files
|
||||
* An array of files as returned by file_load_multiple().
|
||||
* @param $view_mode
|
||||
* View mode.
|
||||
* @param $weight
|
||||
* An integer representing the weight of the first file in the list.
|
||||
* @param $langcode
|
||||
* A string indicating the language field values are to be shown in. If no
|
||||
* language is provided the current content language is used.
|
||||
*
|
||||
* @return
|
||||
* An array in the format expected by drupal_render().
|
||||
*/
|
||||
function file_view_multiple($files, $view_mode = 'full', $weight = 0, $langcode = NULL) {
|
||||
if (empty($files)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
field_attach_prepare_view('file', $files, $view_mode, $langcode);
|
||||
entity_prepare_view('file', $files, $langcode);
|
||||
|
||||
$build = array();
|
||||
foreach ($files as $file) {
|
||||
$build[$file->fid] = file_view($file, $view_mode, $langcode);
|
||||
$build[$file->fid]['#weight'] = $weight;
|
||||
$weight++;
|
||||
}
|
||||
$build['#sorted'] = TRUE;
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an array for rendering the given file.
|
||||
*
|
||||
* @param $file
|
||||
* A file object.
|
||||
* @param $view_mode
|
||||
* View mode.
|
||||
* @param $langcode
|
||||
* (optional) A language code to use for rendering. Defaults to the global
|
||||
* content language of the current request.
|
||||
*
|
||||
* @return
|
||||
* An array as expected by drupal_render().
|
||||
*/
|
||||
function file_view($file, $view_mode = 'full', $langcode = NULL) {
|
||||
if (!isset($langcode)) {
|
||||
$langcode = $GLOBALS['language_content']->language;
|
||||
}
|
||||
|
||||
// Populate $file->content with a render() array.
|
||||
file_build_content($file, $view_mode, $langcode);
|
||||
|
||||
$build = $file->content;
|
||||
// We don't need duplicate rendering info in $file->content.
|
||||
unset($file->content);
|
||||
|
||||
$build += array(
|
||||
'#theme' => 'file_entity',
|
||||
'#file' => $file,
|
||||
'#view_mode' => $view_mode,
|
||||
'#language' => $langcode,
|
||||
);
|
||||
|
||||
// Add contextual links for this file, except when the file is already being
|
||||
// displayed on its own page. Modules may alter this behavior (for example,
|
||||
// to restrict contextual links to certain view modes) by implementing
|
||||
// hook_file_view_alter().
|
||||
if (!empty($file->fid) && !($view_mode == 'full' && file_is_page($file))) {
|
||||
$build['#contextual_links']['file'] = array('file', array($file->fid));
|
||||
}
|
||||
|
||||
// Allow modules to modify the structured file.
|
||||
$type = 'file';
|
||||
drupal_alter(array('file_view', 'entity_view'), $build, $type);
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a structured array representing the file's content.
|
||||
*
|
||||
* @param $file
|
||||
* A file object.
|
||||
* @param $view_mode
|
||||
* View mode, e.g. 'default', 'full', etc.
|
||||
* @param $langcode
|
||||
* (optional) A language code to use for rendering. Defaults to the global
|
||||
* content language of the current request.
|
||||
*/
|
||||
function file_build_content($file, $view_mode = 'full', $langcode = NULL) {
|
||||
if (!isset($langcode)) {
|
||||
$langcode = $GLOBALS['language_content']->language;
|
||||
}
|
||||
|
||||
// Remove previously built content, if exists.
|
||||
$file->content = array();
|
||||
|
||||
// Build the actual file display.
|
||||
// @todo Figure out how to clean this crap up.
|
||||
$file->content['file'] = file_view_file($file, $view_mode, $langcode);
|
||||
if (isset($file->content['file'])) {
|
||||
if (isset($file->content['file']['#theme']) && $file->content['file']['#theme'] != 'file_link') {
|
||||
unset($file->content['file']['#file']);
|
||||
}
|
||||
unset($file->content['file']['#view_mode']);
|
||||
unset($file->content['file']['#language']);
|
||||
}
|
||||
else {
|
||||
unset($file->content['file']);
|
||||
}
|
||||
|
||||
// Build fields content.
|
||||
// In case of a multiple view, file_view_multiple() already ran the
|
||||
// 'prepare_view' step. An internal flag prevents the operation from running
|
||||
// twice.
|
||||
field_attach_prepare_view('file', array($file->fid => $file), $view_mode, $langcode);
|
||||
entity_prepare_view('file', array($file->fid => $file), $langcode);
|
||||
$file->content += field_attach_view('file', $file, $view_mode, $langcode);
|
||||
|
||||
$links = array();
|
||||
$file->content['links'] = array(
|
||||
'#theme' => 'links__file',
|
||||
'#pre_render' => array('drupal_pre_render_links'),
|
||||
'#attributes' => array('class' => array('links', 'inline')),
|
||||
);
|
||||
$file->content['links']['file'] = array(
|
||||
'#theme' => 'links__file__file',
|
||||
'#links' => $links,
|
||||
'#attributes' => array('class' => array('links', 'inline')),
|
||||
);
|
||||
|
||||
// Allow modules to make their own additions to the file.
|
||||
module_invoke_all('file_view', $file, $view_mode, $langcode);
|
||||
module_invoke_all('entity_view', $file, 'file', $view_mode, $langcode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an array for rendering just the file portion of a file entity.
|
||||
*
|
||||
* @param $file
|
||||
* A file object.
|
||||
* @param $displays
|
||||
* Can be either:
|
||||
* - the name of a view mode;
|
||||
* - or an array of custom display settings, as returned by file_displays().
|
||||
* @param $langcode
|
||||
* (optional) A language code to use for rendering. Defaults to the global
|
||||
* content language of the current request.
|
||||
*
|
||||
* @return
|
||||
* An array as expected by drupal_render().
|
||||
*/
|
||||
function file_view_file($file, $displays = 'full', $langcode = NULL) {
|
||||
if (!isset($langcode)) {
|
||||
$langcode = $GLOBALS['language_content']->language;
|
||||
}
|
||||
|
||||
// Prepare incoming display specifications.
|
||||
if (is_string($displays)) {
|
||||
$view_mode = $displays;
|
||||
$displays = file_displays($file->type, $view_mode);
|
||||
}
|
||||
else {
|
||||
$view_mode = '_custom_display';
|
||||
}
|
||||
drupal_alter('file_displays', $displays, $file, $view_mode);
|
||||
_file_sort_array_by_weight($displays);
|
||||
|
||||
// Attempt to display the file with each of the possible displays. Stop after
|
||||
// the first successful one. See file_displays() for details.
|
||||
$element = NULL;
|
||||
foreach ($displays as $formatter_type => $display) {
|
||||
if (!empty($display['status'])) {
|
||||
$formatter_info = file_info_formatter_types($formatter_type);
|
||||
// Under normal circumstances, the UI prevents enabling formatters for
|
||||
// incompatible file types. In case this was somehow circumvented (for
|
||||
// example, a module updated its formatter definition without updating
|
||||
// existing display settings), perform an extra check here.
|
||||
if (isset($formatter_info['file types']) && !in_array($file->type, $formatter_info['file types'])) {
|
||||
continue;
|
||||
}
|
||||
if (isset($formatter_info['view callback']) && ($function = $formatter_info['view callback']) && function_exists($function)) {
|
||||
$display['type'] = $formatter_type;
|
||||
if (!empty($formatter_info['default settings'])) {
|
||||
if (empty($display['settings'])) {
|
||||
$display['settings'] = array();
|
||||
}
|
||||
$display['settings'] += $formatter_info['default settings'];
|
||||
}
|
||||
$element = $function($file, $display, $langcode);
|
||||
if (isset($element)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If none of the configured formatters were able to display the file, attempt
|
||||
// to display the file using the file type's default view callback.
|
||||
if (!isset($element)) {
|
||||
$file_type_info = file_info_file_types($file->type);
|
||||
if (isset($file_type_info['default view callback']) && ($function = $file_type_info['default view callback']) && function_exists($function)) {
|
||||
$element = $function($file, $view_mode, $langcode);
|
||||
}
|
||||
}
|
||||
|
||||
// If a render element was returned by a formatter or the file type's default
|
||||
// view callback, add some defaults to it and return it.
|
||||
if (isset($element)) {
|
||||
$element += array(
|
||||
'#file' => $file,
|
||||
'#view_mode' => $view_mode,
|
||||
'#language' => $langcode,
|
||||
);
|
||||
return $element;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of possible displays to use for a file type in a given view mode.
|
||||
*
|
||||
* It is common for a site to be configured with broadly defined file types
|
||||
* (e.g., 'video'), and to have different files of this type require different
|
||||
* displays (for example, the code required to display a YouTube video is
|
||||
* different than the code required to display a local QuickTime video).
|
||||
* Therefore, the site administrator can configure multiple displays for a given
|
||||
* file type. This function returns all of the displays that the administrator
|
||||
* enabled for the given file type in the given view mode. file_view_file() then
|
||||
* invokes each of these, and passes the specific file to display. Each display
|
||||
* implementation can inspect the file, and either return a render array (if it
|
||||
* is capable of displaying the file), or return nothing (if it is incapable of
|
||||
* displaying the file). The first render array returned is the one used.
|
||||
*
|
||||
* @param $file_type
|
||||
* The type of file.
|
||||
* @param $view_mode
|
||||
* The view mode.
|
||||
*
|
||||
* @return
|
||||
* An array keyed by the formatter type name. Each item in the array contains
|
||||
* the following key/value pairs:
|
||||
* - status: Whether this display is enabled. If not TRUE, file_view_file()
|
||||
* skips over it.
|
||||
* - weight: An integer that determines the order of precedence within the
|
||||
* returned array. The lowest weight display capable of displaying the file
|
||||
* is used.
|
||||
* - settings: An array of key/value pairs specific to the formatter type. See
|
||||
* hook_file_formatter_info() for details.
|
||||
*
|
||||
* @see hook_file_formatter_info()
|
||||
* @see file_view_file()
|
||||
*/
|
||||
function file_displays($file_type, $view_mode) {
|
||||
$cache = &drupal_static(__FUNCTION__, array());
|
||||
|
||||
// If the requested view mode isn't configured to use a custom display for its
|
||||
// fields, then don't use a custom display for its file either.
|
||||
if ($view_mode != 'default') {
|
||||
$view_mode_settings = field_view_mode_settings('file', $file_type);
|
||||
$view_mode = !empty($view_mode_settings[$view_mode]['custom_settings']) ? $view_mode : 'default';
|
||||
}
|
||||
|
||||
if (!isset($cache[$file_type][$view_mode])) {
|
||||
// Load the display configurations for the file type and view mode. If none
|
||||
// exist for the view mode, use the default view mode.
|
||||
$displays = file_displays_load($file_type, $view_mode, TRUE);
|
||||
if (empty($displays) && $view_mode != 'default') {
|
||||
$cache[$file_type][$view_mode] = file_displays($file_type, 'default');
|
||||
}
|
||||
else {
|
||||
// Convert the display objects to arrays and remove unnecessary keys.
|
||||
foreach ($displays as $formatter_name => $display) {
|
||||
$displays[$formatter_name] = array_intersect_key((array) $display, drupal_map_assoc(array('status', 'weight', 'settings')));
|
||||
}
|
||||
$cache[$file_type][$view_mode] = $displays;
|
||||
}
|
||||
}
|
||||
|
||||
return $cache[$file_type][$view_mode];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of {file_display} objects for the file type and view mode.
|
||||
*/
|
||||
function file_displays_load($file_type, $view_mode, $key_by_formatter_name = FALSE) {
|
||||
ctools_include('export');
|
||||
|
||||
$display_names = array();
|
||||
$prefix = $file_type . '__' . $view_mode . '__';
|
||||
foreach (array_keys(file_info_formatter_types()) as $formatter_name) {
|
||||
$display_names[] = $prefix . $formatter_name;
|
||||
}
|
||||
$displays = ctools_export_load_object('file_display', 'names', $display_names);
|
||||
|
||||
if ($key_by_formatter_name) {
|
||||
$prefix_length = strlen($prefix);
|
||||
$rekeyed_displays = array();
|
||||
foreach ($displays as $name => $display) {
|
||||
$rekeyed_displays[substr($name, $prefix_length)] = $display;
|
||||
}
|
||||
$displays = $rekeyed_displays;
|
||||
}
|
||||
|
||||
return $displays;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a {file_display} object to the database.
|
||||
*/
|
||||
function file_display_save($display) {
|
||||
ctools_include('export');
|
||||
ctools_export_crud_save('file_display', $display);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {file_display} object.
|
||||
*/
|
||||
function file_display_new($file_type, $view_mode, $formatter_name) {
|
||||
ctools_include('export');
|
||||
$display = ctools_export_crud_new('file_display');
|
||||
$display->name = implode('__', array($file_type, $view_mode, $formatter_name));
|
||||
return $display;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to sort an array by the value of each item's 'weight' key, while preserving relative order of items that have equal weight.
|
||||
*/
|
||||
function _file_sort_array_by_weight(&$a) {
|
||||
$i=0;
|
||||
foreach ($a as $key => $item) {
|
||||
if (!isset($a[$key]['weight'])) {
|
||||
$a[$key]['weight'] = 0;
|
||||
}
|
||||
$original_weight[$key] = $a[$key]['weight'];
|
||||
$a[$key]['weight'] += $i/1000;
|
||||
$i++;
|
||||
}
|
||||
uasort($a, 'drupal_sort_weight');
|
||||
foreach ($a as $key => $item) {
|
||||
$a[$key]['weight'] = $original_weight[$key];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* User sort function to sort by weight, then label/name.
|
||||
*/
|
||||
function _file_entity_sort_weight_label($a, $b) {
|
||||
$a_weight = isset($a['weight']) ? $a['weight'] : 0;
|
||||
$b_weight = isset($b['weight']) ? $b['weight'] : 0;
|
||||
if ($a_weight == $b_weight) {
|
||||
$a_label = isset($a['label']) ? $a['label'] : '';
|
||||
$b_label = isset($b['label']) ? $b['label'] : '';
|
||||
return strcasecmp($a_label, $b_label);
|
||||
}
|
||||
else {
|
||||
return $a_weight < $b_weight ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a file object which can be passed to file_save().
|
||||
*
|
||||
* @param $uri
|
||||
* A string containing the URI, path, or filename.
|
||||
* @param $use_existing
|
||||
* (Optional) If TRUE and there's an existing file in the {file_managed}
|
||||
* table with the passed in URI, then that file object is returned.
|
||||
* Otherwise, a new file object is returned. Default is TRUE.
|
||||
*
|
||||
* @return
|
||||
* A file object, or FALSE on error.
|
||||
*
|
||||
* @todo This should probably be named file_load_by_uri($uri, $create_if_not_exists).
|
||||
* @todo Remove this function when http://drupal.org/node/685818 is fixed.
|
||||
*/
|
||||
function file_uri_to_object($uri, $use_existing = TRUE) {
|
||||
$file = FALSE;
|
||||
$uri = file_stream_wrapper_uri_normalize($uri);
|
||||
|
||||
if ($use_existing) {
|
||||
// We should always attempt to re-use a file if possible.
|
||||
$files = entity_load('file', FALSE, array('uri' => $uri));
|
||||
$file = !empty($files) ? reset($files) : FALSE;
|
||||
}
|
||||
|
||||
if (empty($file)) {
|
||||
$file = new stdClass();
|
||||
$file->uid = $GLOBALS['user']->uid;
|
||||
$file->filename = basename($uri);
|
||||
$file->uri = $uri;
|
||||
$file->filemime = file_get_mimetype($uri);
|
||||
// This is gagged because some uris will not support it.
|
||||
$file->filesize = @filesize($uri);
|
||||
$file->timestamp = REQUEST_TIME;
|
||||
$file->status = FILE_STATUS_PERMANENT;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of operations which can be called on files.
|
||||
*
|
||||
* @return
|
||||
* An associave array of operations keyed by a system name.
|
||||
* - label: A string to show in the operations dropdown.
|
||||
* - callback (string): A callback function to call for the operation. This
|
||||
* function will be passed an array of file_ids which were selected.
|
||||
* - confirm (boolean): Whether or not this operation requires a confirm form
|
||||
* In the case where confirm is set to true, callback should be a function
|
||||
* which can return a confirm form.
|
||||
*/
|
||||
function hook_file_operations_info() {
|
||||
$operations = array(
|
||||
'archive_and_email' => array(
|
||||
'label' => t('Archive the selected files and email them'),
|
||||
'callback' => 'file_archiver_confirm_form',
|
||||
'confirm' => TRUE,
|
||||
),
|
||||
);
|
||||
return $operations;
|
||||
}
|
22
sites/all/modules/file_entity/file_entity.info
Normal file
22
sites/all/modules/file_entity/file_entity.info
Normal file
@@ -0,0 +1,22 @@
|
||||
name = File entity
|
||||
description = "Extends Drupal file entities to be fieldable and viewable."
|
||||
package = Media
|
||||
core = 7.x
|
||||
dependencies[] = field
|
||||
dependencies[] = file
|
||||
dependencies[] = ctools
|
||||
files[] = views/views_handler_argument_file_type.inc
|
||||
files[] = views/views_handler_field_file_type.inc
|
||||
files[] = views/views_handler_filter_file_type.inc
|
||||
files[] = views/views_plugin_row_file_view.inc
|
||||
files[] = tests/file_entity.test
|
||||
|
||||
; We have to add a fake version so Git checkouts do not fail Media dependencies
|
||||
version = 7.x-2.x-dev
|
||||
|
||||
; Information added by drupal.org packaging script on 2012-01-12
|
||||
version = "7.x-2.0-unstable3"
|
||||
core = "7.x"
|
||||
project = "file_entity"
|
||||
datestamp = "1326409240"
|
||||
|
248
sites/all/modules/file_entity/file_entity.install
Normal file
248
sites/all/modules/file_entity/file_entity.install
Normal file
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Install, update and uninstall functions for the file_entity module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_schema_alter().
|
||||
*/
|
||||
function file_entity_schema_alter(&$schema) {
|
||||
$schema['file_managed']['fields']['type'] = array(
|
||||
'description' => 'The type of this file.',
|
||||
'type' => 'varchar',
|
||||
'length' => 50,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
);
|
||||
$schema['file_managed']['indexes']['file_type'] = array('type');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_schema().
|
||||
*/
|
||||
function file_entity_schema() {
|
||||
$schema['file_display'] = array(
|
||||
'description' => 'Stores configuration options for file displays.',
|
||||
'fields' => array(
|
||||
// @todo Can be refactored as a compond primary key after
|
||||
// http://drupal.org/node/924236 is implemented.
|
||||
'name' => array(
|
||||
'description' => 'A combined string (FILE_TYPE__VIEW_MODE__FILE_FORMATTER) identifying a file display configuration. For integration with CTools Exportables, stored as a single string rather than as a compound primary key.',
|
||||
'type' => 'varchar',
|
||||
'length' => '255',
|
||||
'not null' => TRUE,
|
||||
),
|
||||
'weight' => array(
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
'description' => 'Weight of formatter within the display chain for the associated file type and view mode. A file is rendered using the lowest weighted enabled display configuration that matches the file type and view mode and that is capable of displaying the file.',
|
||||
),
|
||||
'status' => array(
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
'size' => 'tiny',
|
||||
'description' => 'The status of the display. (1 = enabled, 0 = disabled)',
|
||||
),
|
||||
'settings' => array(
|
||||
'type' => 'blob',
|
||||
'not null' => FALSE,
|
||||
'size' => 'big',
|
||||
'serialize' => TRUE,
|
||||
'description' => 'A serialized array of name value pairs that store the formatter settings for the display.',
|
||||
),
|
||||
),
|
||||
'primary key' => array('name'),
|
||||
'export' => array(
|
||||
// Integrate {file_display} with CTools Exportables.
|
||||
// @see help/export.html documentation bundled with the CTools project.
|
||||
'key' => 'name',
|
||||
'key name' => 'Name',
|
||||
'primary key' => 'name',
|
||||
// The {file_display}.status field is used to control whether the display
|
||||
// is active in the display chain. CTools-level disabling is something
|
||||
// different, and it's not yet clear how to interpret it for file displays.
|
||||
// Until that's figured out, prevent CTools-level disabling.
|
||||
'can disable' => FALSE,
|
||||
'default hook' => 'file_default_displays',
|
||||
'identifier' => 'file_display',
|
||||
'api' => array(
|
||||
'owner' => 'file_entity',
|
||||
'api' => 'file_default_displays',
|
||||
'minimum_version' => 1,
|
||||
'current_version' => 1,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_install().
|
||||
*/
|
||||
function file_entity_install() {
|
||||
$schema = array();
|
||||
file_entity_schema_alter($schema);
|
||||
$spec = $schema['file_managed']['fields']['type'];
|
||||
$indexes_new = array('indexes' => $schema['file_managed']['indexes']);
|
||||
|
||||
// If another module (e.g., Media) had added a {file_managed}.type field,
|
||||
// then change it to the expected specification. Otherwise, add the field.
|
||||
if (db_field_exists('file_managed', 'type')) {
|
||||
// db_change_field() will fail if any records have type=NULL, so update
|
||||
// them to the new default value.
|
||||
db_update('file_managed')->fields(array('type' => $spec['default']))->isNull('type')->execute();
|
||||
|
||||
// Indexes using a field being changed must be dropped prior to calling
|
||||
// db_change_field(). However, the database API doesn't provide a way to do
|
||||
// this without knowing what the old indexes are. Therefore, it is the
|
||||
// responsibility of the module that added them to drop them prior to
|
||||
// allowing this module to be installed.
|
||||
db_change_field('file_managed', 'type', 'type', $spec, $indexes_new);
|
||||
}
|
||||
else {
|
||||
db_add_field('file_managed', 'type', $spec, $indexes_new);
|
||||
}
|
||||
|
||||
// Update all files with empty types to use the first part of filemime.
|
||||
db_update('file_managed')
|
||||
->expression('type', "SUBSTRING_INDEX(filemime, '/', 1)")
|
||||
->condition('type', '')
|
||||
->execute();
|
||||
|
||||
// Set permissions.
|
||||
$roles = user_roles();
|
||||
foreach ($roles as $rid => $role) {
|
||||
user_role_grant_permissions($rid, array('view file'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_uninstall().
|
||||
*/
|
||||
function file_entity_uninstall() {
|
||||
db_drop_field('file_managed', 'type');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the {file_display} database table.
|
||||
*/
|
||||
function file_entity_update_7000() {
|
||||
$schema['file_display'] = array(
|
||||
'description' => 'Stores configuration options for file displays.',
|
||||
'fields' => array(
|
||||
'name' => array(
|
||||
'description' => 'A combined string (FILE_TYPE__VIEW_MODE__FILE_FORMATTER) identifying a file display configuration. For integration with CTools Exportables, stored as a single string rather than as a compound primary key.',
|
||||
'type' => 'varchar',
|
||||
'length' => '255',
|
||||
'not null' => TRUE,
|
||||
),
|
||||
'weight' => array(
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
'description' => 'Weight of formatter within the display chain for the associated file type and view mode. A file is rendered using the lowest weighted enabled display configuration that matches the file type and view mode and that is capable of displaying the file.',
|
||||
),
|
||||
'status' => array(
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
'size' => 'tiny',
|
||||
'description' => 'The status of the display. (1 = enabled, 0 = disabled)',
|
||||
),
|
||||
'settings' => array(
|
||||
'type' => 'blob',
|
||||
'not null' => FALSE,
|
||||
'size' => 'big',
|
||||
'serialize' => TRUE,
|
||||
'description' => 'A serialized array of name value pairs that store the formatter settings for the display.',
|
||||
),
|
||||
),
|
||||
'primary key' => array('name'),
|
||||
);
|
||||
|
||||
db_create_table('file_display', $schema['file_display']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move file display configurations from the 'file_displays' variable to the
|
||||
* {file_display} database table.
|
||||
*/
|
||||
function file_entity_update_7001() {
|
||||
$file_displays = variable_get('file_displays');
|
||||
if (!empty($file_displays)) {
|
||||
foreach ($file_displays as $file_type => $file_type_displays) {
|
||||
if (!empty($file_type_displays)) {
|
||||
foreach ($file_type_displays as $view_mode => $view_mode_displays) {
|
||||
if (!empty($view_mode_displays)) {
|
||||
foreach ($view_mode_displays as $formatter_name => $display) {
|
||||
if (!empty($display)) {
|
||||
db_merge('file_display')
|
||||
->key(array(
|
||||
'name' => implode('__', array($file_type, $view_mode, $formatter_name)),
|
||||
))
|
||||
->fields(array(
|
||||
'status' => isset($display['status']) ? $display['status'] : 0,
|
||||
'weight' => isset($display['weight']) ? $display['weight'] : 0,
|
||||
'settings' => isset($display['settings']) ? serialize($display['settings']) : NULL,
|
||||
))
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
variable_del('file_displays');
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty update function to trigger a theme registry rebuild.
|
||||
*/
|
||||
function file_entity_update_7100() { }
|
||||
|
||||
/**
|
||||
* Update all files with empty types to use the first part of filemime.
|
||||
*
|
||||
* For example, an png image with filemime 'image/png' will be assigned a file
|
||||
* type of 'image'.
|
||||
*/
|
||||
function file_entity_update_7101() {
|
||||
db_update('file_managed')
|
||||
->expression('type', "SUBSTRING_INDEX(filemime, '/', 1)")
|
||||
->condition('type', '')
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty update function to trigger an entity cache rebuild.
|
||||
*/
|
||||
function file_entity_update_7102() { }
|
||||
|
||||
/**
|
||||
* Intentionally left blank.
|
||||
*/
|
||||
function file_entity_update_7103() { }
|
||||
|
||||
/**
|
||||
* Assign view file permission when updating without the Media module.
|
||||
*/
|
||||
function file_entity_update_7104() {
|
||||
if (!module_exists('media')) {
|
||||
$roles = user_roles(FALSE, 'view file');
|
||||
if (empty($roles)) {
|
||||
// Set permissions.
|
||||
$roles = user_roles();
|
||||
foreach ($roles as $rid => $role) {
|
||||
user_role_grant_permissions($rid, array('view file'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
774
sites/all/modules/file_entity/file_entity.module
Normal file
774
sites/all/modules/file_entity/file_entity.module
Normal file
@@ -0,0 +1,774 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Extends Drupal file entities to be fieldable and viewable.
|
||||
*/
|
||||
|
||||
/**
|
||||
* As part of extending Drupal core's file entity API, this module adds some
|
||||
* functions to the 'file' namespace. For organization, those are kept in the
|
||||
* 'file_entity.file_api.inc' file.
|
||||
*/
|
||||
require_once dirname(__FILE__) . '/file_entity.file_api.inc';
|
||||
|
||||
// @todo Remove when http://drupal.org/node/977052 is fixed.
|
||||
require_once dirname(__FILE__) . '/file_entity.field.inc';
|
||||
|
||||
/**
|
||||
* Implements hook_help().
|
||||
*/
|
||||
function file_entity_help($path, $arg) {
|
||||
switch ($path) {
|
||||
case 'admin/config/media/file-types':
|
||||
$output = '<p>' . t('When a file is uploaded to this website, it is assigned one of the following types, based on what kind of file it is.') . '</p>';
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Access callback for files.
|
||||
*/
|
||||
function file_entity_access($op) {
|
||||
return (user_access('administer files') || user_access($op . ' file'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_menu().
|
||||
*/
|
||||
function file_entity_menu() {
|
||||
// File Configuration
|
||||
$items['admin/config/media/file-types'] = array(
|
||||
'title' => 'File types',
|
||||
'description' => 'Manage settings for the type of files used on your site.',
|
||||
'page callback' => 'file_entity_list_types_page',
|
||||
'access arguments' => array('administer site configuration'),
|
||||
'file' => 'file_entity.admin.inc',
|
||||
);
|
||||
$items['admin/config/media/file-types/manage/%'] = array(
|
||||
'title' => 'Manage file types',
|
||||
'description' => 'Manage settings for the type of files used on your site.',
|
||||
);
|
||||
$items['admin/content/file'] = array(
|
||||
'title' => 'Files',
|
||||
'description' => 'Manage files used on your site.',
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('file_entity_admin_files'),
|
||||
'access arguments' => array('administer files'),
|
||||
'type' => MENU_LOCAL_TASK | MENU_NORMAL_ITEM,
|
||||
'file' => 'file_entity.admin.inc',
|
||||
);
|
||||
$items['admin/content/file/list'] = array(
|
||||
'title' => 'List',
|
||||
'type' => MENU_DEFAULT_LOCAL_TASK,
|
||||
);
|
||||
// general view, edit, delete for files
|
||||
$items['file/%file'] = array(
|
||||
'page callback' => 'file_entity_view_page',
|
||||
'page arguments' => array(1),
|
||||
'access callback' => 'file_entity_access',
|
||||
'access arguments' => array('view'),
|
||||
'file' => 'file_entity.pages.inc',
|
||||
);
|
||||
$items['file/%file/view'] = array(
|
||||
'title' => 'View',
|
||||
'type' => MENU_DEFAULT_LOCAL_TASK,
|
||||
'weight' => -10,
|
||||
);
|
||||
$items['file/%file/edit'] = array(
|
||||
'title' => 'Edit',
|
||||
'page callback' => 'file_entity_page_edit',
|
||||
'page arguments' => array(1),
|
||||
'access callback' => 'file_entity_access',
|
||||
'access arguments' => array('edit'),
|
||||
'weight' => 0,
|
||||
'type' => MENU_LOCAL_TASK,
|
||||
'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
|
||||
'file' => 'file_entity.pages.inc',
|
||||
);
|
||||
$items['file/%file/delete'] = array(
|
||||
'title' => 'Delete',
|
||||
'page callback' => 'file_entity_page_delete',
|
||||
'page arguments' => array(1),
|
||||
'access callback' => 'file_entity_access',
|
||||
'access arguments' => array('edit'),
|
||||
'weight' => 1,
|
||||
'type' => MENU_LOCAL_TASK,
|
||||
'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
|
||||
'file' => 'file_entity.pages.inc',
|
||||
);
|
||||
|
||||
// Attach a "Manage file display" tab to each file type in the same way that
|
||||
// Field UI attaches "Manage fields" and "Manage display" tabs. Note that
|
||||
// Field UI does not have to be enabled; we're just using the same IA pattern
|
||||
// here for attaching the "Manage file display" page.
|
||||
$entity_info = entity_get_info('file');
|
||||
foreach ($entity_info['bundles'] as $file_type => $bundle_info) {
|
||||
if (isset($bundle_info['admin'])) {
|
||||
// Get the base path and access.
|
||||
$path = $bundle_info['admin']['path'];
|
||||
$access = array_intersect_key($bundle_info['admin'], drupal_map_assoc(array('access callback', 'access arguments')));
|
||||
$access += array(
|
||||
'access callback' => 'user_access',
|
||||
'access arguments' => array('administer site configuration'),
|
||||
);
|
||||
|
||||
// The file type must be passed to the page callbacks. It might be
|
||||
// configured as a wildcard (multiple file types sharing the same menu
|
||||
// router path).
|
||||
$file_type_argument = isset($bundle_info['admin']['bundle argument']) ? $bundle_info['admin']['bundle argument'] : $file_type;
|
||||
|
||||
// Add the 'Manage file display' tab.
|
||||
$items["$path/file-display"] = array(
|
||||
'title' => 'Manage file display',
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('file_entity_file_display_form', $file_type_argument, 'default'),
|
||||
'type' => MENU_LOCAL_TASK,
|
||||
'weight' => 3,
|
||||
'file' => 'file_entity.admin.inc',
|
||||
) + $access;
|
||||
|
||||
// Add a secondary tab for each view mode.
|
||||
$weight = 0;
|
||||
$view_modes = array('default' => array('label' => t('Default'))) + $entity_info['view modes'];
|
||||
foreach ($view_modes as $view_mode => $view_mode_info) {
|
||||
$items["$path/file-display/$view_mode"] = array(
|
||||
'title' => $view_mode_info['label'],
|
||||
'page arguments' => array('file_entity_file_display_form', $file_type_argument, $view_mode),
|
||||
'type' => ($view_mode == 'default' ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK),
|
||||
'weight' => ($view_mode == 'default' ? -10 : $weight++),
|
||||
'file' => 'file_entity.admin.inc',
|
||||
// View modes for which the 'custom settings' flag isn't TRUE are
|
||||
// disabled via this access callback. This needs to extend, rather
|
||||
// than override normal $access rules.
|
||||
'access callback' => '_file_entity_view_mode_menu_access',
|
||||
'access arguments' => array_merge(array($file_type_argument, $view_mode, $access['access callback']), $access['access arguments']),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_permission().
|
||||
*/
|
||||
function file_entity_permission() {
|
||||
return array(
|
||||
'administer files' => array(
|
||||
'title' => t('Administer files'),
|
||||
'description' => t('Add, edit or delete files and administer settings.'),
|
||||
),
|
||||
'view file' => array(
|
||||
'title' => t('View file'),
|
||||
'description' => t('View all files.'),
|
||||
),
|
||||
'edit file' => array(
|
||||
'title' => t('Edit file'),
|
||||
'description' => t('Edit all files.'),
|
||||
),
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Implements hook_admin_paths().
|
||||
*/
|
||||
function file_entity_admin_paths() {
|
||||
$paths = array(
|
||||
'file/*/edit' => TRUE,
|
||||
'file/*/delete' => TRUE,
|
||||
);
|
||||
return $paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_theme().
|
||||
*/
|
||||
function file_entity_theme() {
|
||||
return array(
|
||||
'file_entity' => array(
|
||||
'render element' => 'elements',
|
||||
'template' => 'file_entity',
|
||||
),
|
||||
'file_entity_file_type_overview' => array(
|
||||
'variables' => array('label' => NULL, 'description' => NULL),
|
||||
'file' => 'file_entity.admin.inc',
|
||||
),
|
||||
'file_entity_file_display_order' => array(
|
||||
'render element' => 'element',
|
||||
'file' => 'file_entity.admin.inc',
|
||||
),
|
||||
'file_entity_file_link' => array(
|
||||
'variables' => array('file' => NULL, 'icon_directory' => NULL),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_info_alter().
|
||||
*
|
||||
* Extends the core file entity to be fieldable. Modules can define file types
|
||||
* via hook_file_type_info(). For each defined type, create a bundle, so that
|
||||
* fields can be configured per file type.
|
||||
*/
|
||||
function file_entity_entity_info_alter(&$entity_info) {
|
||||
$entity_info['file']['fieldable'] = TRUE;
|
||||
$entity_info['file']['entity keys']['bundle'] = 'type';
|
||||
$entity_info['file']['bundles'] = array();
|
||||
$entity_info['file']['uri callback'] = 'file_entity_uri';
|
||||
$entity_info['file']['view modes']['full'] = array(
|
||||
'label' => t('Full'),
|
||||
'custom settings' => FALSE,
|
||||
);
|
||||
foreach (file_info_file_types() as $type => $info) {
|
||||
$info += array(
|
||||
// Provide a default administration path for Field UI, but not if 'admin'
|
||||
// has been explicitly set to NULL.
|
||||
'admin' => array(
|
||||
'path' => 'admin/config/media/file-types/manage/%',
|
||||
'real path' => 'admin/config/media/file-types/manage/' . $type,
|
||||
'bundle argument' => 5,
|
||||
),
|
||||
);
|
||||
$entity_info['file']['bundles'][$type] = array_intersect_key($info, drupal_map_assoc(array('label', 'admin')));
|
||||
$entity_info['file']['view callback'] = 'file_view_multiple';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* URI callback for file entities.
|
||||
*/
|
||||
function file_entity_uri($file) {
|
||||
$uri['path'] = 'file/' . $file->fid;
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_extra_fields().
|
||||
*
|
||||
* Adds 'file' as an extra field, so that its display and form component can be
|
||||
* weighted relative to the fields that are added to file entity bundles.
|
||||
*/
|
||||
function file_entity_field_extra_fields() {
|
||||
$info = array();
|
||||
|
||||
foreach (file_type_get_names() as $type => $name) {
|
||||
$info['file'][$type]['form']['filename'] = array(
|
||||
'label' => t('File name'),
|
||||
'description' => t('File name'),
|
||||
'weight' => -10,
|
||||
);
|
||||
$info['file'][$type]['form']['preview'] = array(
|
||||
'label' => t('File'),
|
||||
'description' => t('File preview'),
|
||||
'weight' => -5,
|
||||
);
|
||||
$info['file'][$type]['display']['file'] = array(
|
||||
'label' => t('File'),
|
||||
'description' => t('File display'),
|
||||
'weight' => 0,
|
||||
);
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_file_presave().
|
||||
*/
|
||||
function file_entity_file_presave($file) {
|
||||
// Always ensure the filemime property is current.
|
||||
if (!empty($file->original) || empty($file->filemime)) {
|
||||
$file->filemime = file_get_mimetype($file->uri);
|
||||
}
|
||||
|
||||
// Always update file type based on filemime.
|
||||
$file->type = file_get_type($file);
|
||||
|
||||
field_attach_presave('file', $file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_file_insert().
|
||||
*/
|
||||
function file_entity_file_insert($file) {
|
||||
field_attach_insert('file', $file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_file_update().
|
||||
*/
|
||||
function file_entity_file_update($file) {
|
||||
field_attach_update('file', $file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_file_delete().
|
||||
*/
|
||||
function file_entity_file_delete($file) {
|
||||
field_attach_delete('file', $file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_file_formatter_info().
|
||||
*/
|
||||
function file_entity_file_formatter_info() {
|
||||
$formatters = array();
|
||||
|
||||
// Allow file field formatters to be reused for displaying the file entity's
|
||||
// file pseudo-field.
|
||||
if (module_exists('file')) {
|
||||
foreach (field_info_formatter_types() as $field_formatter_type => $field_formatter_info) {
|
||||
if (in_array('file', $field_formatter_info['field types'])) {
|
||||
$formatters['file_field_' . $field_formatter_type] = array(
|
||||
'label' => $field_formatter_info['label'],
|
||||
'view callback' => 'file_entity_file_formatter_file_field_view',
|
||||
);
|
||||
if (isset($field_formatter_info['settings'])) {
|
||||
$formatters['file_field_' . $field_formatter_type] += array(
|
||||
'default settings' => $field_formatter_info['settings'],
|
||||
'settings callback' => 'file_entity_file_formatter_file_field_settings',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add a simple file formatter for displaying an image in a chosen style.
|
||||
if (module_exists('image')) {
|
||||
$formatters['file_image'] = array(
|
||||
'label' => t('Image'),
|
||||
'default settings' => array('image_style' => ''),
|
||||
'view callback' => 'file_entity_file_formatter_file_image_view',
|
||||
'settings callback' => 'file_entity_file_formatter_file_image_settings',
|
||||
);
|
||||
}
|
||||
|
||||
return $formatters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_file_formatter_FORMATTER_view().
|
||||
*
|
||||
* This function provides a bridge to the field formatter API, so that file
|
||||
* field formatters can be reused for displaying the file entity's file
|
||||
* pseudo-field.
|
||||
*/
|
||||
function file_entity_file_formatter_file_field_view($file, $display, $langcode) {
|
||||
if (strpos($display['type'], 'file_field_') === 0) {
|
||||
$field_formatter_type = substr($display['type'], strlen('file_field_'));
|
||||
$field_formatter_info = field_info_formatter_types($field_formatter_type);
|
||||
if (isset($field_formatter_info['module'])) {
|
||||
// Set $display['type'] to what hook_field_formatter_*() expects.
|
||||
$display['type'] = $field_formatter_type;
|
||||
|
||||
// Set $items to what file field formatters expect. See file_field_load(),
|
||||
// and note that, here, $file is already a fully loaded entity.
|
||||
$items = array((array) $file);
|
||||
|
||||
// Invoke hook_field_formatter_prepare_view() and
|
||||
// hook_field_formatter_view(). Note that we are reusing field formatter
|
||||
// functions, but we are not displaying a Field API field, so we set
|
||||
// $field and $instance accordingly, and do not invoke
|
||||
// hook_field_prepare_view(). This assumes that the formatter functions do
|
||||
// not rely on $field or $instance. A module that implements formatter
|
||||
// functions that rely on $field or $instance (and therefore, can only be
|
||||
// used for real fields) can prevent this formatter from being used on the
|
||||
// pseudo-field by removing it within hook_file_formatter_info_alter().
|
||||
$field = $instance = NULL;
|
||||
if (($function = ($field_formatter_info['module'] . '_field_formatter_prepare_view')) && function_exists($function)) {
|
||||
$fid = $file->fid;
|
||||
// hook_field_formatter_prepare_view() alters $items by reference.
|
||||
$grouped_items = array($fid => &$items);
|
||||
$function('file', array($fid => $file), $field, array($fid => $instance), $langcode, $grouped_items, array($fid => $display));
|
||||
}
|
||||
if (($function = ($field_formatter_info['module'] . '_field_formatter_view')) && function_exists($function)) {
|
||||
$element = $function('file', $file, $field, $instance, $langcode, $items, $display);
|
||||
// We passed the file as $items[0], so return the corresponding element.
|
||||
if (isset($element[0])) {
|
||||
return $element[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_file_formatter_FORMATTER_settings().
|
||||
*
|
||||
* This function provides a bridge to the field formatter API, so that file
|
||||
* field formatters can be reused for displaying the file entity's file
|
||||
* pseudo-field.
|
||||
*/
|
||||
function file_entity_file_formatter_file_field_settings($form, &$form_state, $settings, $formatter_type, $file_type, $view_mode) {
|
||||
if (strpos($formatter_type, 'file_field_') === 0) {
|
||||
$field_formatter_type = substr($formatter_type, strlen('file_field_'));
|
||||
$field_formatter_info = field_info_formatter_types($field_formatter_type);
|
||||
|
||||
// Invoke hook_field_formatter_settings_form(). We are reusing field
|
||||
// formatter functions, but we are not working with a Field API field, so
|
||||
// set $field accordingly. Unfortunately, the API is for $settings to be
|
||||
// transfered via the $instance parameter, so we must mock it.
|
||||
if (isset($field_formatter_info['module']) && ($function = ($field_formatter_info['module'] . '_field_formatter_settings_form')) && function_exists($function)) {
|
||||
$field = NULL;
|
||||
$mock_instance['display'][$view_mode] = array(
|
||||
'type' => $field_formatter_type,
|
||||
'settings' => $settings,
|
||||
);
|
||||
return $function($field, $mock_instance, $view_mode, $form, $form_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_file_formatter_FORMATTER_view().
|
||||
*
|
||||
* Returns a drupal_render() array to display an image of the chosen style.
|
||||
*
|
||||
* This formatter is only capable of displaying local images. If the passed in
|
||||
* file is either not local or not an image, nothing is returned, so that
|
||||
* file_view_file() can try another formatter.
|
||||
*/
|
||||
function file_entity_file_formatter_file_image_view($file, $display, $langcode) {
|
||||
$scheme = file_uri_scheme($file->uri);
|
||||
$local_wrappers = file_get_stream_wrappers(STREAM_WRAPPERS_LOCAL);
|
||||
if (isset($local_wrappers[$scheme]) && strpos($file->filemime, 'image/') === 0 && $image = image_load($file->uri)) {
|
||||
if (!empty($display['settings']['image_style'])) {
|
||||
$element = array(
|
||||
'#theme' => 'image_style',
|
||||
'#style_name' => $display['settings']['image_style'],
|
||||
'#path' => $file->uri,
|
||||
'#width' => $image->info['width'],
|
||||
'#height' => $image->info['height'],
|
||||
);
|
||||
}
|
||||
else {
|
||||
$element = array(
|
||||
'#theme' => 'image',
|
||||
'#path' => $file->uri,
|
||||
'#width' => $image->info['width'],
|
||||
'#height' => $image->info['height'],
|
||||
);
|
||||
}
|
||||
return $element;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_file_formatter_FORMATTER_settings().
|
||||
*
|
||||
* Returns form elements for configuring the 'file_image' formatter.
|
||||
*/
|
||||
function file_entity_file_formatter_file_image_settings($form, &$form_state, $settings) {
|
||||
$element = array();
|
||||
$element['image_style'] = array(
|
||||
'#title' => t('Image style'),
|
||||
'#type' => 'select',
|
||||
'#options' => image_style_options(FALSE),
|
||||
'#default_value' => $settings['image_style'],
|
||||
'#empty_option' => t('None (original image)'),
|
||||
);
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu access callback for the 'view mode file display settings' pages.
|
||||
*
|
||||
* Based on _field_ui_view_mode_menu_access(), but the Field UI module might not
|
||||
* be enabled.
|
||||
*/
|
||||
function _file_entity_view_mode_menu_access($file_type, $view_mode, $access_callback) {
|
||||
// Deny access if the view mode isn't configured to use custom display
|
||||
// settings.
|
||||
$view_mode_settings = field_view_mode_settings('file', $file_type);
|
||||
$visibility = ($view_mode == 'default') || !empty($view_mode_settings[$view_mode]['custom_settings']);
|
||||
if (!$visibility) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Otherwise, continue to an $access_callback check.
|
||||
$args = array_slice(func_get_args(), 3);
|
||||
$callback = empty($access_callback) ? 0 : trim($access_callback);
|
||||
if (is_numeric($callback)) {
|
||||
return (bool) $callback;
|
||||
}
|
||||
elseif (function_exists($access_callback)) {
|
||||
return call_user_func_array($access_callback, $args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_modules_enabled().
|
||||
*/
|
||||
function file_entity_modules_enabled($modules) {
|
||||
file_info_cache_clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_modules_disabled().
|
||||
*/
|
||||
function file_entity_modules_disabled($modules) {
|
||||
file_info_cache_clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_views_api().
|
||||
*/
|
||||
function file_entity_views_api() {
|
||||
return array(
|
||||
'api' => 3,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the current page is the full page view of the passed-in file.
|
||||
*
|
||||
* @param $file
|
||||
* A file object.
|
||||
*/
|
||||
function file_is_page($file) {
|
||||
$page_file = menu_get_object('file', 1);
|
||||
return (!empty($page_file) ? $page_file->fid == $file->fid : FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process variables for file_entity.tpl.php
|
||||
*
|
||||
* The $variables array contains the following arguments:
|
||||
* - $file
|
||||
* - $view_mode
|
||||
*
|
||||
* @see file_entity.tpl.php
|
||||
*/
|
||||
function template_preprocess_file_entity(&$variables) {
|
||||
$view_mode = $variables['view_mode'] = $variables['elements']['#view_mode'];
|
||||
$variables['file'] = $variables['elements']['#file'];
|
||||
$file = $variables['file'];
|
||||
|
||||
$variables['date'] = format_date($file->timestamp);
|
||||
$account = user_load($file->uid);
|
||||
$variables['name'] = theme('username', array('account' => $account));
|
||||
|
||||
// @todo Use entity_uri once http://drupal.org/node/1057242 is fixed.
|
||||
//$uri = entity_uri('file', $file);
|
||||
//$variables['file_url'] = url($uri['path'], $uri['options']);
|
||||
$variables['file_url'] = file_create_url($file->uri);
|
||||
$label = entity_label('file', $file);
|
||||
$variables['label'] = check_plain($label);
|
||||
$variables['page'] = $view_mode == 'full' && file_is_page($file);
|
||||
|
||||
// Disable the file name from being displayed as the title until we can
|
||||
// figure out a better way to control this.
|
||||
// @see http://drupal.org/node/1245266
|
||||
$variables['page'] = TRUE;
|
||||
|
||||
// Flatten the file object's member fields.
|
||||
$variables = array_merge((array) $file, $variables);
|
||||
|
||||
// Helpful $content variable for templates.
|
||||
$variables += array('content' => array());
|
||||
foreach (element_children($variables['elements']) as $key) {
|
||||
$variables['content'][$key] = $variables['elements'][$key];
|
||||
}
|
||||
|
||||
// Make the field variables available with the appropriate language.
|
||||
field_attach_preprocess('file', $file, $variables['content'], $variables);
|
||||
|
||||
// Display post information only on certain file types.
|
||||
if (variable_get('file_submitted_' . $file->type, FALSE)) {
|
||||
$variables['display_submitted'] = TRUE;
|
||||
$variables['submitted'] = t('Uploaded by !username on !datetime', array('!username' => $variables['name'], '!datetime' => $variables['date']));
|
||||
$variables['user_picture'] = theme_get_setting('toggle_file_user_picture') ? theme('user_picture', array('account' => $account)) : '';
|
||||
}
|
||||
else {
|
||||
$variables['display_submitted'] = FALSE;
|
||||
$variables['submitted'] = '';
|
||||
$variables['user_picture'] = '';
|
||||
}
|
||||
|
||||
// Gather file classes.
|
||||
$variables['classes_array'][] = drupal_html_class('file-' . $file->type);
|
||||
$variables['classes_array'][] = drupal_html_class('file-' . $file->filemime);
|
||||
if ($file->status != FILE_STATUS_PERMANENT) {
|
||||
$variables['classes_array'][] = 'file-temporary';
|
||||
}
|
||||
|
||||
// Change the 'file-entity' class into 'file'
|
||||
if ($variables['classes_array'][0] == 'file-entity') {
|
||||
$variables['classes_array'][0] = 'file';
|
||||
}
|
||||
|
||||
// Clean up name so there are no underscores.
|
||||
$variables['theme_hook_suggestions'][] = 'file__' . $file->type;
|
||||
$variables['theme_hook_suggestions'][] = 'file__' . $file->type . '__' . $view_mode;
|
||||
$variables['theme_hook_suggestions'][] = 'file__' . str_replace(array('/', '-'), array('__', '_'), $file->filemime);
|
||||
$variables['theme_hook_suggestions'][] = 'file__' . str_replace(array('/', '-'), array('__', '_'), $file->filemime) . '__' . $view_mode;
|
||||
$variables['theme_hook_suggestions'][] = 'file__' . $file->fid;
|
||||
$variables['theme_hook_suggestions'][] = 'file__' . $file->fid . '__' . $view_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file type name of the passed file or file type string.
|
||||
*
|
||||
* @param $file
|
||||
* A file object or string that indicates the file type to return.
|
||||
*
|
||||
* @return
|
||||
* The file type name or FALSE if the file type is not found.
|
||||
*/
|
||||
function file_type_get_name($file) {
|
||||
$type = is_object($file) ? $file->type : $file;
|
||||
$info = entity_get_info('file');
|
||||
return isset($info['bundles'][$type]['label']) ? $info['bundles'][$type]['label'] : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of available file type names.
|
||||
*
|
||||
* @return
|
||||
* An array of file type names, keyed by the type.
|
||||
*/
|
||||
function file_type_get_names() {
|
||||
$names = &drupal_static(__FUNCTION__);
|
||||
|
||||
if (!isset($names)) {
|
||||
$info = entity_get_info('file');
|
||||
foreach ($info['bundles'] as $bundle => $bundle_info) {
|
||||
$names[$bundle] = $bundle_info['label'];
|
||||
}
|
||||
}
|
||||
|
||||
return $names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_file_mimetype_mapping_alter().
|
||||
*/
|
||||
function file_entity_file_mimetype_mapping_alter(&$mapping) {
|
||||
// Fix the mime type mapping for ogg.
|
||||
// @todo Remove when http://drupal.org/node/1239376 is fixed in core (7.8).
|
||||
$new_mappings['ogg'] = 'audio/ogg';
|
||||
|
||||
// Add support for m4v.
|
||||
// @todo Remove when http://drupal.org/node/1290486 is fixed in core (7.9).
|
||||
$new_mappings['m4v'] = 'video/x-m4v';
|
||||
|
||||
// Add support for mka and mkv.
|
||||
// @todo Remove when http://drupal.org/node/1293140 is fixed in core.
|
||||
$new_mappings['mka'] = 'audio/x-matroska';
|
||||
$new_mappings['mkv'] = 'video/x-matroska';
|
||||
|
||||
// Add support for webp.
|
||||
// @todo Remove when http://drupal.org/node/1347624 is fixed in core.
|
||||
$new_mappings['webp'] = 'image/webp';
|
||||
|
||||
foreach ($new_mappings as $extension => $mime_type) {
|
||||
if (!in_array($mime_type, $mapping['mimetypes'])) {
|
||||
// If the mime type does not already exist, add it.
|
||||
$mapping['mimetypes'][] = $mime_type;
|
||||
}
|
||||
|
||||
// Get the index of the mime type and assign the extension to that key.
|
||||
$index = array_search($mime_type, $mapping['mimetypes']);
|
||||
$mapping['extensions'][$extension] = $index;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of available view modes for file entities.
|
||||
*/
|
||||
function file_entity_view_mode_labels() {
|
||||
$labels = &drupal_static(__FUNCTION__);
|
||||
|
||||
if (!isset($options)) {
|
||||
$entity_info = entity_get_info('file');
|
||||
$labels = array('default' => t('Default'));
|
||||
foreach ($entity_info['view modes'] as $machine_name => $mode) {
|
||||
$labels[$machine_name] = $mode['label'];
|
||||
}
|
||||
}
|
||||
|
||||
return $labels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the label for a specific file entity view mode.
|
||||
*/
|
||||
function file_entity_view_mode_label($view_mode, $default = FALSE) {
|
||||
$labels = file_entity_view_mode_labels();
|
||||
return isset($labels[$view_mode]) ? $labels[$view_mode] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_file_operations_info().
|
||||
*/
|
||||
function file_entity_file_operations_info() {
|
||||
$operations = array(
|
||||
'delete' => array(
|
||||
'label' => t('Delete selected files'),
|
||||
'callback' => 'file_entity_multiple_delete_confirm_operation',
|
||||
'confirm' => TRUE,
|
||||
),
|
||||
);
|
||||
return $operations;
|
||||
}
|
||||
|
||||
/**
|
||||
* File operation to show a confirm form for file deletion.
|
||||
*
|
||||
* @param array $files
|
||||
* An array of file_ids to delete.
|
||||
* @return type
|
||||
*/
|
||||
function file_entity_multiple_delete_confirm_operation($files) {
|
||||
// This function is a form generation function.
|
||||
$form = array();
|
||||
$form_state = array();
|
||||
// Set the submit handler explicitly because this form is being built
|
||||
// under a different form_id.
|
||||
$form['#submit'] = array();
|
||||
$form['#submit'][] = 'file_entity_multiple_delete_confirm_submit';
|
||||
return file_entity_multiple_delete_confirm($form, $form_state, $files);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to get a list of hidden stream wrappers.
|
||||
*
|
||||
* This is used in several places to filter queries for media so that files in
|
||||
* temporary:// don't show up.
|
||||
*/
|
||||
function file_entity_get_hidden_stream_wrappers() {
|
||||
return array_diff_key(file_get_stream_wrappers(STREAM_WRAPPERS_ALL), file_get_stream_wrappers(STREAM_WRAPPERS_VISIBLE));
|
||||
}
|
||||
|
||||
/**
|
||||
* A copy of theme_file_file_link() that makes the link point to file/[fid].
|
||||
*
|
||||
* @see theme_file_file_link()
|
||||
* @return type
|
||||
*/
|
||||
function theme_file_entity_file_link($variables) {
|
||||
$file = $variables['file'];
|
||||
$icon_directory = $variables['icon_directory'];
|
||||
|
||||
$url = 'file/' . $file->fid;
|
||||
$icon = theme('file_icon', array('file' => $file, 'icon_directory' => $icon_directory));
|
||||
|
||||
// Set options as per anchor format described at
|
||||
// http://microformats.org/wiki/file-format-examples
|
||||
$options = array(
|
||||
'attributes' => array(
|
||||
'type' => $file->filemime . '; length=' . $file->filesize,
|
||||
),
|
||||
);
|
||||
|
||||
// Use the description as the link text if available.
|
||||
if (empty($file->description)) {
|
||||
$link_text = $file->filename;
|
||||
}
|
||||
else {
|
||||
$link_text = $file->description;
|
||||
$options['attributes']['title'] = check_plain($file->filename);
|
||||
}
|
||||
|
||||
return '<span class="file">' . $icon . ' ' . l($link_text, $url, $options) . '</span>';
|
||||
}
|
190
sites/all/modules/file_entity/file_entity.pages.inc
Normal file
190
sites/all/modules/file_entity/file_entity.pages.inc
Normal file
@@ -0,0 +1,190 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Supports file operations including View, Edit, and Delete.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Menu callback; view a single file entity.
|
||||
*/
|
||||
function file_entity_view_page($file) {
|
||||
// @todo Implement granular editorial access: http://drupal.org/node/696970.
|
||||
// In the meantime, protect information about private files from being
|
||||
// discovered by unprivileged users. File IDs are autoincrement, so one can
|
||||
// attempt discovery by trying to access different media/ID paths. See also
|
||||
// media_browser_list(). This logic potentially belongs within
|
||||
// media_access(), but that would require extending that function's
|
||||
// signature to accept a $file paramter, and this is temporary code anyway.
|
||||
if (!user_access('administer files') && (file_uri_scheme($file->uri) === 'private')) {
|
||||
return MENU_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
drupal_set_title($file->filename);
|
||||
return file_view($file, 'full');
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; presents the Media editing form.
|
||||
*/
|
||||
function file_entity_page_edit($file) {
|
||||
drupal_set_title(t('<em>Edit @type</em> @title', array('@type' => $file->type, '@title' => $file->filename)), PASS_THROUGH);
|
||||
return drupal_get_form('file_entity_edit', $file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Form builder: Builds the edit file form.
|
||||
*/
|
||||
function file_entity_edit($form, &$form_state, $file) {
|
||||
$form_state['file'] = $file;
|
||||
|
||||
$form['#attributes']['class'][] = 'file-form';
|
||||
if (!empty($file->type)) {
|
||||
$form['#attributes']['class'][] = 'file-' . $file->type . '-form';
|
||||
}
|
||||
|
||||
// Basic file information.
|
||||
// These elements are just values so they are not even sent to the client.
|
||||
foreach (array('fid', 'type', 'uid', 'timestamp') as $key) {
|
||||
$form[$key] = array(
|
||||
'#type' => 'value',
|
||||
'#value' => isset($file->$key) ? $file->$key : NULL,
|
||||
);
|
||||
}
|
||||
|
||||
$form['filename'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Name'),
|
||||
'#default_value' => $file->filename,
|
||||
'#required' => TRUE,
|
||||
'#maxlength' => 255,
|
||||
'#weight' => -10,
|
||||
);
|
||||
|
||||
$form['preview'] = array(
|
||||
'#theme' => 'file_link',
|
||||
'#file' => $file,
|
||||
'#weight' => -5,
|
||||
);
|
||||
|
||||
// Add the buttons.
|
||||
$form['actions'] = array('#type' => 'actions');
|
||||
$form['actions']['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Save'),
|
||||
'#weight' => 5,
|
||||
'#submit' => array('file_entity_edit_submit'),
|
||||
);
|
||||
$form['actions']['delete'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Delete'),
|
||||
'#weight' => 10,
|
||||
'#submit' => array('file_entity_delete_submit'),
|
||||
);
|
||||
|
||||
field_attach_form('file', $file, $form, $form_state);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form validation handler for the file entity edit form.
|
||||
*/
|
||||
function file_entity_edit_validate($form, &$form_state) {
|
||||
entity_form_field_validate('file', $form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submit handler for the media submit form.
|
||||
*/
|
||||
function file_entity_edit_submit($form, &$form_state) {
|
||||
$file = $form_state['file'];
|
||||
entity_form_submit_build_entity('file', $file, $form, $form_state);
|
||||
file_save($file);
|
||||
$form_state['redirect'] = 'file/' . $file->fid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; shows delete confirmation form.
|
||||
*/
|
||||
function file_entity_page_delete($file) {
|
||||
drupal_set_title(t('<em>Delete @type</em> @title', array('@type' => $file->type, '@title' => $file->filename)), PASS_THROUGH);
|
||||
// Don't bother showing the form if the item is in use, since we won't allow
|
||||
// them to delete it anyway.
|
||||
$references = file_usage_list($file);
|
||||
if (!empty($references)) {
|
||||
return t('The file %title is in use and cannot be deleted.', array('%title' => $file->filename));
|
||||
}
|
||||
else {
|
||||
$files = array($file->fid => $file->fid);
|
||||
return drupal_get_form('file_entity_multiple_delete_confirm', $files, 'file/' . $file->fid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm form for the request to delete files.
|
||||
*
|
||||
* @param array $files
|
||||
* An array of file_ids to delete.
|
||||
*/
|
||||
function file_entity_multiple_delete_confirm($form, &$form_state, $files, $redirect_path = NULL) {
|
||||
$form['files'] = array('#tree' => TRUE);
|
||||
$form['file_titles'] = array('#theme' => 'item_list');
|
||||
|
||||
$files = file_load_multiple($files);
|
||||
foreach ($files as $fid => $file) {
|
||||
$form['files'][$fid] = array(
|
||||
'#type' => 'value',
|
||||
'#value' => $fid,
|
||||
);
|
||||
$form['file_titles']['#items'][] = check_plain($file->filename);
|
||||
}
|
||||
$form['operation'] = array('#type' => 'hidden', '#value' => 'delete');
|
||||
|
||||
$confirm_question = format_plural(count($files),
|
||||
'Are you sure you want to delete this file?',
|
||||
'Are you sure you want to delete these files?');
|
||||
|
||||
return confirm_form($form,
|
||||
$confirm_question,
|
||||
$redirect_path,
|
||||
t('This action cannot be undone.'),
|
||||
t('Delete'),
|
||||
t('Cancel'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to delete files and notify the user of the result.
|
||||
*/
|
||||
function file_entity_multiple_delete_confirm_submit($form, &$form_state) {
|
||||
if ($form_state['values']['confirm']) {
|
||||
$files = file_load_multiple(array_keys($form_state['values']['files']));
|
||||
foreach ($files as $fid => $file) {
|
||||
$result = file_delete($file);
|
||||
if (is_array($result)) {
|
||||
drupal_set_message(t('The file @title is in use and cannot be deleted.', array('@title' => $file->filename)), 'warning');
|
||||
}
|
||||
elseif (!$result) {
|
||||
drupal_set_message(t('The file @title was not deleted due to an error.', array('@title' => $file->filename)), 'error');
|
||||
}
|
||||
else {
|
||||
$message = t('File @title was deleted', array('@title' => $file->filename));
|
||||
$form_state['redirect'] = user_access('administer files') ? 'admin/content/file' : '<front>';
|
||||
watchdog('file', $message);
|
||||
drupal_set_message($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submit handler for the Delete button on the media edit form.
|
||||
*/
|
||||
function file_entity_delete_submit($form, &$form_state) {
|
||||
$fid = $form_state['values']['fid'];
|
||||
$destination = array();
|
||||
if (isset($_GET['destination'])) {
|
||||
$destination = drupal_get_destination();
|
||||
unset($_GET['destination']);
|
||||
}
|
||||
$form_state['redirect'] = array('file/' . $fid . '/delete', array('query' => $destination));
|
||||
}
|
111
sites/all/modules/file_entity/file_entity.tokens.inc
Normal file
111
sites/all/modules/file_entity/file_entity.tokens.inc
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Token integration for the file_entity module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_token_info().
|
||||
*/
|
||||
function file_entity_token_info() {
|
||||
// File type tokens.
|
||||
$info['types']['file-type'] = array(
|
||||
'name' => t('File type'),
|
||||
'description' => t('Tokens associated with file types.'),
|
||||
'needs-data' => 'file_type',
|
||||
);
|
||||
$info['tokens']['file-type']['name'] = array(
|
||||
'name' => t('Name'),
|
||||
'description' => t('The name of the file type.'),
|
||||
);
|
||||
$info['tokens']['file-type']['machine-name'] = array(
|
||||
'name' => t('Machine-readable name'),
|
||||
'description' => t('The unique machine-readable name of the file type.'),
|
||||
);
|
||||
$info['tokens']['file-type']['count'] = array(
|
||||
'name' => t('File count'),
|
||||
'description' => t('The number of files belonging to the file type.'),
|
||||
);
|
||||
$info['tokens']['file-type']['edit-url'] = array(
|
||||
'name' => t('Edit URL'),
|
||||
'description' => t("The URL of the file type's edit page."),
|
||||
);
|
||||
|
||||
// File tokens.
|
||||
$info['tokens']['file']['type'] = array(
|
||||
'name' => t('File type'),
|
||||
'description' => t('The file type of the file.'),
|
||||
'type' => 'file-type',
|
||||
);
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_tokens().
|
||||
*/
|
||||
function file_entity_tokens($type, $tokens, array $data = array(), array $options = array()) {
|
||||
$replacements = array();
|
||||
|
||||
$url_options = array('absolute' => TRUE);
|
||||
if (isset($options['language'])) {
|
||||
$url_options['language'] = $options['language'];
|
||||
$language_code = $options['language']->language;
|
||||
}
|
||||
else {
|
||||
$language_code = NULL;
|
||||
}
|
||||
|
||||
$sanitize = !empty($options['sanitize']);
|
||||
|
||||
// File tokens.
|
||||
if ($type == 'file' && !empty($data['file'])) {
|
||||
$file = $data['file'];
|
||||
|
||||
foreach ($tokens as $name => $original) {
|
||||
switch ($name) {
|
||||
case 'type':
|
||||
if ($file_type = file_info_file_types($file->type)) {
|
||||
$replacements[$original] = $sanitize ? check_plain($file_type['label']) : $file_type['label'];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Chained token relationships.
|
||||
if (($file_type_tokens = token_find_with_prefix($tokens, 'type')) && $file_type = file_info_file_types($file->type)) {
|
||||
$file_type['type'] = $file->type;
|
||||
$replacements += token_generate('file-type', $file_type_tokens, array('file_type' => $file_type), $options);
|
||||
}
|
||||
}
|
||||
|
||||
// File type tokens.
|
||||
if ($type == 'file-type' && !empty($data['file_type'])) {
|
||||
$file_type = $data['file_type'];
|
||||
|
||||
foreach ($tokens as $name => $original) {
|
||||
switch ($name) {
|
||||
case 'name':
|
||||
$replacements[$original] = $sanitize ? check_plain($file_type['label']) : $file_type['label'];
|
||||
break;
|
||||
case 'machine-name':
|
||||
// This is a machine name so does not ever need to be sanitized.
|
||||
$replacements[$original] = $file_type['type'];
|
||||
break;
|
||||
case 'count':
|
||||
$query = db_select('file_managed');
|
||||
$query->condition('type', $file_type['type']);
|
||||
$query->addTag('file_type_file_count');
|
||||
$count = $query->countQuery()->execute()->fetchField();
|
||||
$replacements[$original] = (int) $count;
|
||||
break;
|
||||
case 'edit-url':
|
||||
$replacements[$original] = url('admin/config/media/file-types/manage/' . $file_type['type'] . '/fields', $url_options);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $replacements;
|
||||
}
|
93
sites/all/modules/file_entity/file_entity.tpl.php
Normal file
93
sites/all/modules/file_entity/file_entity.tpl.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Default theme implementation to display a file.
|
||||
*
|
||||
* Available variables:
|
||||
* - $label: the (sanitized) file name of the file.
|
||||
* - $content: An array of file items. Use render($content) to print them all,
|
||||
* or print a subset such as render($content['field_example']). Use
|
||||
* hide($content['field_example']) to temporarily suppress the printing of a
|
||||
* given element.
|
||||
* - $user_picture: The file owner's picture from user-picture.tpl.php.
|
||||
* - $date: Formatted added date. Preprocess functions can reformat it by
|
||||
* calling format_date() with the desired parameters on the $timestamp
|
||||
* variable.
|
||||
* - $name: Themed username of file owner output from theme_username().
|
||||
* - $file_url: Direct URL of the current file.
|
||||
* - $display_submitted: Whether submission information should be displayed.
|
||||
* - $submitted: Submission information created from $name and $date during
|
||||
* template_preprocess_file().
|
||||
* - $classes: String of classes that can be used to style contextually through
|
||||
* CSS. It can be manipulated through the variable $classes_array from
|
||||
* preprocess functions. The default values can be one or more of the
|
||||
* following:
|
||||
* - file-entity: The current template type, i.e., "theming hook".
|
||||
* - file-[type]: The current file type. For example, if the file is a
|
||||
* "Image" file it would result in "file-image". Note that the machine
|
||||
* name will often be in a short form of the human readable label.
|
||||
* - file-[mimetype]: The current file's MIME type. For exampe, if the file
|
||||
* is a PNG image, it would result in "file-image-png"
|
||||
* - $title_prefix (array): An array containing additional output populated by
|
||||
* modules, intended to be displayed in front of the main title tag that
|
||||
* appears in the template.
|
||||
* - $title_suffix (array): An array containing additional output populated by
|
||||
* modules, intended to be displayed after the main title tag that appears in
|
||||
* the template.
|
||||
*
|
||||
* Other variables:
|
||||
* - $file: Full file object. Contains data that may not be safe.
|
||||
* - $type: File type, i.e. image, audio, video, etc.
|
||||
* - $uid: User ID of the file owner.
|
||||
* - $timestamp: Time the file was added formatted in Unix timestamp.
|
||||
* - $classes_array: Array of html class attribute values. It is flattened
|
||||
* into a string within the variable $classes.
|
||||
* - $zebra: Outputs either "even" or "odd". Useful for zebra striping in
|
||||
* listings.
|
||||
* - $id: Position of the file. Increments each time it's output.
|
||||
*
|
||||
* File status variables:
|
||||
* - $view_mode: View mode, e.g. 'default', 'full', etc.
|
||||
* - $page: Flag for the full page state.
|
||||
* - $is_front: Flags true when presented in the front page.
|
||||
* - $logged_in: Flags true when the current user is a logged-in member.
|
||||
* - $is_admin: Flags true when the current user is an administrator.
|
||||
*
|
||||
* Field variables: for each field instance attached to the file a corresponding
|
||||
* variable is defined, e.g. $file->caption becomes $caption. When needing to
|
||||
* access a field's raw values, developers/themers are strongly encouraged to
|
||||
* use these variables. Otherwise they will have to explicitly specify the
|
||||
* desired field language, e.g. $file->caption['en'], thus overriding any
|
||||
* language negotiation rule that was previously applied.
|
||||
*
|
||||
* @see template_preprocess()
|
||||
* @see template_preprocess_file()
|
||||
* @see template_process()
|
||||
*/
|
||||
?>
|
||||
<div id="file-<?php print $file->fid ?>" class="<?php print $classes ?>"<?php print $attributes; ?>>
|
||||
|
||||
<?php if (!$page): ?>
|
||||
<?php print render($title_prefix); ?>
|
||||
<h2<?php print $title_attributes; ?>><a href="<?php print $file_url; ?>"><?php print $label; ?></a></h2>
|
||||
<?php print render($title_suffix); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($display_submitted): ?>
|
||||
<div class="submitted">
|
||||
<?php print $submitted; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="content"<?php print $content_attributes; ?>>
|
||||
<?php
|
||||
// We hide the links now so that we can render them later.
|
||||
hide($content['links']);
|
||||
print render($content);
|
||||
?>
|
||||
</div>
|
||||
|
||||
<?php print render($content['links']); ?>
|
||||
|
||||
</div>
|
52
sites/all/modules/file_entity/file_entity.views.inc
Normal file
52
sites/all/modules/file_entity/file_entity.views.inc
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Views integration for the file_entity module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_views_data().
|
||||
*/
|
||||
function file_entity_views_data() {
|
||||
// File type
|
||||
$data['file_managed']['type'] = array(
|
||||
'title' => t('Type'),
|
||||
'help' => t('The type of the file (for example, "audio", "image", "video", etc).'),
|
||||
'field' => array(
|
||||
'handler' => 'views_handler_field_file_type',
|
||||
'click sortable' => TRUE,
|
||||
),
|
||||
'sort' => array(
|
||||
'handler' => 'views_handler_sort',
|
||||
),
|
||||
'filter' => array(
|
||||
'handler' => 'views_handler_filter_file_type',
|
||||
),
|
||||
'argument' => array(
|
||||
'handler' => 'views_handler_argument_file_type',
|
||||
),
|
||||
);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_views_plugins().
|
||||
*/
|
||||
function file_entity_views_plugins() {
|
||||
return array(
|
||||
'module' => 'views', // This just tells our themes are elsewhere.
|
||||
'row' => array(
|
||||
'file' => array(
|
||||
'title' => t('File'),
|
||||
'help' => t('Display the file with standard file view.'),
|
||||
'handler' => 'views_plugin_row_file_view',
|
||||
'base' => array('file_managed'), // only works with 'file' as base.
|
||||
'uses options' => TRUE,
|
||||
'type' => 'normal',
|
||||
'help topic' => 'style-file',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
113
sites/all/modules/file_entity/tests/file_entity.test
Normal file
113
sites/all/modules/file_entity/tests/file_entity.test
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Test integration for the file_entity module.
|
||||
*/
|
||||
|
||||
class FileEntityTestHelper extends DrupalWebTestCase {
|
||||
protected $files = array();
|
||||
|
||||
function setUp($modules = array()) {
|
||||
$modules[] = 'file_entity';
|
||||
parent::setUp($modules);
|
||||
|
||||
$this->setUpFiles();
|
||||
}
|
||||
|
||||
function setUpFiles() {
|
||||
$types = array('text', 'image');
|
||||
foreach ($types as $type) {
|
||||
foreach ($this->drupalGetTestFiles($type) as $file) {
|
||||
$this->files[$type][] = file_save($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FileEntityUnitTestCase extends FileEntityTestHelper {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'File entity unit tests',
|
||||
'description' => 'Test basic file entity funcitonality.',
|
||||
'group' => 'File entity',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Regression tests for core issue http://drupal.org/node/1239376.
|
||||
*/
|
||||
function testMimeTypeMappings() {
|
||||
$tests = array(
|
||||
'public://test.ogg' => 'audio/ogg',
|
||||
'public://test.mkv' => 'video/x-m4v',
|
||||
'public://test.mka' => 'audio/x-matroska',
|
||||
'public://test.mkv' => 'video/x-matroska',
|
||||
'public://test.webp' => 'image/webp',
|
||||
);
|
||||
foreach ($tests as $input => $expected) {
|
||||
$this->assertEqual(file_get_mimetype($input), $expected);
|
||||
}
|
||||
}
|
||||
|
||||
function testFileEntity() {
|
||||
$file = reset($this->files['text']);
|
||||
|
||||
// Test entity ID, revision ID, and bundle.
|
||||
$ids = entity_extract_ids('file', $file);
|
||||
$this->assertIdentical($ids, array($file->fid, NULL, 'text'));
|
||||
|
||||
// Test the entity URI callback.
|
||||
$uri = entity_uri('file', $file);
|
||||
$this->assertEqual($uri['path'], "file/{$file->fid}");
|
||||
}
|
||||
}
|
||||
|
||||
class FileEntityTokenTestCase extends FileEntityTestHelper {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'File entity tokens',
|
||||
'description' => 'Test the file entity tokens.',
|
||||
'group' => 'File entity',
|
||||
);
|
||||
}
|
||||
|
||||
function testFileEntityTokens() {
|
||||
$tokens = array(
|
||||
'type' => 'Text',
|
||||
'type:name' => 'Text',
|
||||
'type:machine-name' => 'text',
|
||||
'type:count' => count($this->files['text']),
|
||||
);
|
||||
$this->assertTokens('file', array('file' => $this->files['text'][0]), $tokens);
|
||||
|
||||
$tokens = array(
|
||||
'type' => 'Image',
|
||||
'type:name' => 'Image',
|
||||
'type:machine-name' => 'image',
|
||||
'type:count' => count($this->files['image']),
|
||||
);
|
||||
$this->assertTokens('file', array('file' => $this->files['image'][0]), $tokens);
|
||||
}
|
||||
|
||||
function assertTokens($type, array $data, array $tokens, array $options = array()) {
|
||||
$token_input = drupal_map_assoc(array_keys($tokens));
|
||||
$values = token_generate($type, $token_input, $data, $options);
|
||||
foreach ($tokens as $token => $expected) {
|
||||
if (!isset($expected)) {
|
||||
$this->assertTrue(!isset($values[$token]), t("Token value for [@type:@token] was not generated.", array('@type' => $type, '@token' => $token)));
|
||||
}
|
||||
elseif (!isset($values[$token])) {
|
||||
$this->fail(t("Token value for [@type:@token] was not generated.", array('@type' => $type, '@token' => $token)));
|
||||
}
|
||||
elseif (!empty($options['regex'])) {
|
||||
$this->assertTrue(preg_match('/^' . $expected . '$/', $values[$token]), t("Token value for [@type:@token] was '@actual', matching regular expression pattern '@expected'.", array('@type' => $type, '@token' => $token, '@actual' => $values[$token], '@expected' => $expected)));
|
||||
}
|
||||
else {
|
||||
$this->assertIdentical($values[$token], $expected, t("Token value for [@type:@token] was '@actual', expected value '@expected'.", array('@type' => $type, '@token' => $token, '@actual' => $values[$token], '@expected' => $expected)));
|
||||
}
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
}
|
13
sites/all/modules/file_entity/tests/file_entity_test.info
Normal file
13
sites/all/modules/file_entity/tests/file_entity_test.info
Normal file
@@ -0,0 +1,13 @@
|
||||
name = "File Entity Test"
|
||||
description = "Support module for File Entity tests."
|
||||
package = Testing
|
||||
core = 7.x
|
||||
dependencies[] = file_entity
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by drupal.org packaging script on 2012-01-12
|
||||
version = "7.x-2.0-unstable3"
|
||||
core = "7.x"
|
||||
project = "file_entity"
|
||||
datestamp = "1326409240"
|
||||
|
100
sites/all/modules/file_entity/tests/file_entity_test.module
Normal file
100
sites/all/modules/file_entity/tests/file_entity_test.module
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* File Entity Test
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Implements hook_menu().
|
||||
*/
|
||||
function file_entity_test_menu() {
|
||||
$items = array();
|
||||
|
||||
$items['file-entity-test/file/add'] = array(
|
||||
'title' => 'Add file',
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('file_entity_test_add_form'),
|
||||
'access arguments' => array('administer site configuration'),
|
||||
'file' => 'file_entity_test.pages.inc',
|
||||
);
|
||||
$items['file-entity-test/file/%file'] = array(
|
||||
'title' => 'View file',
|
||||
'page callback' => 'file_entity_test_view_page',
|
||||
'page arguments' => array(2),
|
||||
'access arguments' => array('administer site configuration'),
|
||||
'file' => 'file_entity_test.pages.inc',
|
||||
);
|
||||
$items['file-entity-test/file/%file/view'] = array(
|
||||
'title' => 'View',
|
||||
'type' => MENU_DEFAULT_LOCAL_TASK,
|
||||
'weight' => -10,
|
||||
);
|
||||
$items['file-entity-test/file/%file/preview'] = array(
|
||||
'title' => 'Preview',
|
||||
'page callback' => 'file_entity_test_preview_page',
|
||||
'page arguments' => array(2),
|
||||
'access arguments' => array('administer site configuration'),
|
||||
'weight' => 0,
|
||||
'type' => MENU_LOCAL_TASK,
|
||||
'file' => 'file_entity_test.pages.inc',
|
||||
);
|
||||
$items['file-entity-test/file/%file/edit'] = array(
|
||||
'title' => 'Edit',
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('file_entity_test_edit_form', 2),
|
||||
'access arguments' => array('administer site configuration'),
|
||||
'weight' => 1,
|
||||
'type' => MENU_LOCAL_TASK,
|
||||
'file' => 'file_entity_test.pages.inc',
|
||||
);
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_file_type_info().
|
||||
*/
|
||||
function file_entity_test_file_type_info() {
|
||||
return array(
|
||||
'file_entity_test' => array(
|
||||
'label' => t('Test'),
|
||||
'description' => t('A file type defined by the File Entity Test module. Used for testing only.'),
|
||||
'claim callback' => 'file_entity_test_file_type_file_entity_test_claim',
|
||||
'default view callback' => 'file_entity_test_file_type_file_entity_test_default_view',
|
||||
'weight' => 100,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_file_type_TYPE_claim().
|
||||
*
|
||||
* Returns TRUE if the passed in file should be assigned the 'file_entity_test'
|
||||
* file type.
|
||||
*/
|
||||
function file_entity_test_file_type_file_entity_test_claim($file) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_file_type_TYPE_default_view().
|
||||
*/
|
||||
function file_entity_test_file_type_file_entity_test_default_view($file, $view_mode, $langcode) {
|
||||
return array(
|
||||
'#type' => 'link',
|
||||
'#title' => $file->filename,
|
||||
'#href' => file_create_url($file->uri),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_info_alter().
|
||||
*/
|
||||
function file_entity_test_entity_info_alter(&$entity_info) {
|
||||
$entity_info['file']['view modes']['file_entity_test_preview'] = array(
|
||||
'label' => t('Test Preview'),
|
||||
'custom settings' => TRUE,
|
||||
);
|
||||
}
|
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Test pages for the File Entity Test module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Form callback; upload a file.
|
||||
*/
|
||||
function file_entity_test_add_form($form, &$form_state) {
|
||||
$form['file'] = array(
|
||||
'#type' => 'managed_file',
|
||||
'#required' => TRUE,
|
||||
'#title' => 'File',
|
||||
'#upload_location' => 'public://',
|
||||
);
|
||||
$form['actions'] = array('#type' => 'actions');
|
||||
$form['actions']['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Save'),
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submit callback; save the uploaded file.
|
||||
*/
|
||||
function file_entity_test_add_form_submit($form, &$form_state) {
|
||||
$file = file_load($form_state['values']['file']);
|
||||
if (!$file->status) {
|
||||
$file->status = FILE_STATUS_PERMANENT;
|
||||
file_save($file);
|
||||
}
|
||||
drupal_set_message(t('Your file has been saved.'));
|
||||
$form_state['redirect'] = 'file-entity-test/file/' . $file->fid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Page callback; view a file.
|
||||
*/
|
||||
function file_entity_test_view_page($file) {
|
||||
return file_view($file, 'full');
|
||||
}
|
||||
|
||||
/**
|
||||
* Page callback; preview a file.
|
||||
*/
|
||||
function file_entity_test_preview_page($file) {
|
||||
return file_view($file, 'file_entity_test_preview');
|
||||
}
|
||||
|
||||
/**
|
||||
* Form callback; edit a file.
|
||||
*/
|
||||
function file_entity_test_edit_form($form, &$form_state, $file) {
|
||||
$form_state['file'] = $file;
|
||||
field_attach_form('file', $file, $form, $form_state);
|
||||
$form['file'] = file_view($file, 'file_entity_test_preview');
|
||||
|
||||
// Add internal file properties needed by
|
||||
// file_entity_test_edit_form_validate().
|
||||
foreach (array('fid', 'type') as $key) {
|
||||
$form[$key] = array('#type' => 'value', '#value' => $file->$key);
|
||||
}
|
||||
|
||||
$form['actions'] = array('#type' => 'actions');
|
||||
$form['actions']['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Save'),
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form validation handler for the file edit form.
|
||||
*/
|
||||
function file_entity_test_edit_form_validate($form, &$form_state) {
|
||||
entity_form_field_validate('file', $form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submit handler for the file edit form
|
||||
*/
|
||||
function file_entity_test_edit_form_submit($form, &$form_state) {
|
||||
$file = $form_state['file'];
|
||||
entity_form_submit_build_entity('file', $file, $form, $form_state);
|
||||
file_save($file);
|
||||
drupal_set_message(t('Your changes to the file have been saved.'));
|
||||
$form_state['redirect'] = 'file-entity-test/file/' . $file->fid;
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Argument handler to accept a file type.
|
||||
*/
|
||||
class views_handler_argument_file_type extends views_handler_argument_string {
|
||||
|
||||
/**
|
||||
* Override the behavior of summary_name(). Get the user friendly version
|
||||
* of the file type.
|
||||
*/
|
||||
function summary_name($data) {
|
||||
return $this->file_type($data->{$this->name_alias});
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the behavior of title(). Get the user friendly version of the
|
||||
* file type.
|
||||
*/
|
||||
function title() {
|
||||
return $this->file_type($this->argument);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to return the human-readable type of the file.
|
||||
*/
|
||||
function file_type($type) {
|
||||
$output = file_type_get_name($type);
|
||||
if (empty($output)) {
|
||||
$output = t('Unknown file type');
|
||||
}
|
||||
return check_plain($output);
|
||||
}
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Field handler to translate a file type into its readable form.
|
||||
*/
|
||||
class views_handler_field_file_type extends views_handler_field_file {
|
||||
function option_definition() {
|
||||
$options = parent::option_definition();
|
||||
$options['machine_name'] = array('default' => FALSE);
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide machine_name option for to file type display.
|
||||
*/
|
||||
function options_form(&$form, &$form_state) {
|
||||
parent::options_form($form, $form_state);
|
||||
|
||||
$form['machine_name'] = array(
|
||||
'#title' => t('Output machine name'),
|
||||
'#description' => t('Display field as the file type machine name.'),
|
||||
'#type' => 'checkbox',
|
||||
'#default_value' => !empty($this->options['machine_name']),
|
||||
'#fieldset' => 'more',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render file type as human readable name, unless using machine_name option.
|
||||
*/
|
||||
function render_name($data, $values) {
|
||||
if ($this->options['machine_name'] != 1 && $data !== NULL && $data !== '') {
|
||||
return t($this->sanitize_value(file_type_get_name($data)));
|
||||
}
|
||||
return $this->sanitize_value($data);
|
||||
}
|
||||
|
||||
function render($values) {
|
||||
$value = $this->get_value($values);
|
||||
return $this->render_link($this->render_name($value, $values), $values);
|
||||
}
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Filter by file type
|
||||
*/
|
||||
class views_handler_filter_file_type extends views_handler_filter_in_operator {
|
||||
function get_value_options() {
|
||||
if (!isset($this->value_options)) {
|
||||
$this->value_title = t('File types');
|
||||
$options = array();
|
||||
foreach (file_type_get_names() as $type => $name) {
|
||||
$options[$type] = t($name);
|
||||
}
|
||||
asort($options);
|
||||
$this->value_options = $options;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains the file view row style plugin.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Plugin which performs a file_view on the resulting object.
|
||||
*
|
||||
* Most of the code on this object is in the theme function.
|
||||
*/
|
||||
class views_plugin_row_file_view extends views_plugin_row {
|
||||
// Basic properties that let the row style follow relationships.
|
||||
var $base_table = 'file_managed';
|
||||
var $base_field = 'fid';
|
||||
|
||||
// Stores the files loaded with pre_render.
|
||||
var $files = array();
|
||||
|
||||
function option_definition() {
|
||||
$options = parent::option_definition();
|
||||
|
||||
$options['view_mode'] = array('default' => 'default');
|
||||
$options['links'] = array('default' => TRUE);
|
||||
return $options;
|
||||
}
|
||||
|
||||
function options_form(&$form, &$form_state) {
|
||||
parent::options_form($form, $form_state);
|
||||
|
||||
$form['view_mode'] = array(
|
||||
'#type' => 'select',
|
||||
'#options' => file_entity_view_mode_labels(),
|
||||
'#title' => t('View mode'),
|
||||
'#default_value' => $this->options['view_mode'],
|
||||
);
|
||||
$form['links'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Display links'),
|
||||
'#default_value' => $this->options['links'],
|
||||
);
|
||||
}
|
||||
|
||||
function summary_title() {
|
||||
$view_mode_label = file_entity_view_mode_label($this->options['view_mode'], t('Unknown'));
|
||||
return check_plain($view_mode_label);
|
||||
}
|
||||
|
||||
function pre_render($values) {
|
||||
$fids = array();
|
||||
foreach ($values as $row) {
|
||||
$fids[] = $row->{$this->field_alias};
|
||||
}
|
||||
$this->files = file_load_multiple($fids);
|
||||
}
|
||||
|
||||
function render($row) {
|
||||
$file = $this->files[$row->{$this->field_alias}];
|
||||
$file->view = $this->view;
|
||||
$build = file_view($file, $this->options['view_mode']);
|
||||
|
||||
return drupal_render($build);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user