first import

This commit is contained in:
Bachir Soussi Chiadmi
2015-04-08 11:40:19 +02:00
commit 1bc61b12ad
8435 changed files with 1582817 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
Requirements
------------
This module requires Drupal 6
Installation
------------
1. untar the nodequeue module into /modules or /sites/all/modules or copy this directory there.
2. Activate the module on the administer >> site building >> modules page
3. Create a node queue on administer >> content >> node queue
4. If using the Views module, you may customize the views automatically created for your queues at administer >> site building >> views

View 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.

View File

@@ -0,0 +1,141 @@
The Node Queue module allows an administrator to arbitrarily put nodes in a
group for some purpose; examples of this might be to highlight one particular
node, as in a typical news site's Lead Article. Another use might be to create
a block listing teasers for 5 forum posts that the admin thinks are important.
Another use might be to create a group of nodes, and then have a block or the
front page offer one of these randomly.
Queues can be set to allow only certain types of nodes to be added to the
queue. Queue can be a fixed size or of infinite length. And the admin can
select which roles have permission to add nodes to a given queue.
Once a queue is set up, a new tab will appear on eligible nodes for eligible
users. This tab will allow the user--regardless of edit permissions--to add or
remove that node from the queue. Queue admins can view the nodes in the queue,
and can modify the order of items already in the queue. Items may also appear
in a nodes links area to add/remove them from the queue.
When a node is added to the queue, it is added to the back of the queue. If a
queue is full when a node is added, the front of the queue is removed.
Nodequeue has support for nodes with i18n Internationalizations.
It is highly recommended that you use the Views module to display your queues.
However, if you choose not to, here is an alternative: Writing a PHP snippet.
To Create a Block to Display Node Titles of a Queue
===================================================
You'll need the Queue ID, which is easily extracted from the URL on the
queue administration page.
Create a new block, and insert the following PHP snippet into the block:
<?php print nodequeue_node_titles(QUEUEID); ?>
If you want this queue to be printed in the reverse order, you can tell it
to print backward:
<?php print nodequeue_node_titles(QUEUEID, '', true); ?>
The '' in the line above is an optional title field. Feel free to put
something here, but it's not terribly necessary in a block.
Programatically displaying nodes from a Queue
===================================================
The following funcitons can be used to display nodes from a subqueue, based on their position.
For more customized displays of content from a queue, please use the Views module (http://drupal.org/project/views).
For the most up to date Nodequeue API information, see http://drupal.org/node/293117.
Programmatic Ways of Displaying Content from a Queue
Nodequeue provides several functions which simplify getting a loaded node object from the front, back or a random position in a queue. For more selecting or displaying content in a more specific or complicated way, the Views module is probably your best bet.
Please note that there are some differences between the functions available in the 5.x-2.x and 6.x.-2.x versions of Nodequeue.
To Create a Block to Display Node Titles of a Queue
You'll need the Queue ID, which is easily extracted from the URL on the queue administration page.
Create a new block, and insert the following PHP snippet into the block:
<?php
print nodequeue_node_titles($subqueue_id);
?>
If you want this queue to be printed in the reverse order, you can tell it to print backward:
<?php
print nodequeue_node_titles($subqueue_id, '', TRUE);
?>
The '' in the line above is an optional title field. Feel free to put something here, but it's not terribly necessary in a block.
To Display a list of teasers from a queue:
Like above, you'll need the Queue ID.
Create a new page (or a new dashboard!) or any node type you like, really, and set the input filter to PHP. Insert the following PHP snippet:
With Nodequeue 6.x-2.x:
<?php
print nodequeue_view_nodes($subqueue_id);
?>
With Nodequeue 5.x-2.x
<?php
print nodequeue_nodes($subqueue_id);
?>
There are a few more options available here; changing the order of the nodes, whether or not to use teasers or full nodes, whether or not to display the links, and how much of the queue to display. See below.
To render the first or last node from a queue
With Nodequeue 6.x-2.x:
<?php
$node = nodequeue_load_front($subqueue_id);
$rendered_node = node_view($node);
?>
With Nodequeue 5.x-2.x:
<?php
$rendered_node = nodequeue_fetch_front($subqueue_id);
?>
Or
With Nodequeue 6.x-2.x:
<?php
$node = nodequeue_load_back($subqueue_id);
$rendered_node = node_view($node);
?>
With Nodequeue 5.x-2.x:
<?php
$rendered_node = nodequeue_fetch_back($subqueue_id);
?>
To render a random node from a queue
With Nodequeue 6.x-2.x:
<?php
$node = nodequeue_load_random_node($subqueue_id);
$rendered_node = node_view($node);
?>
With Nodequeue 5.x-2.x:
<?php
$rendered_node = nodequeue_fetch_random($subqueue_id);
?>
Remember that the front of the queue will have the least recently added nodes (unless it was rearranged manually), and the back will have the most recently added.
Actions Module Integration
==========================
The node queue module provides two actions, so that workflow can add and
remove items from queues.

View File

@@ -0,0 +1,89 @@
<?php
/**
* @file
* Miscellaneous functions for Nodequeue Service.
*
* @author Greg Harvey - http://www.drupaler.co.uk
*/
/**
* Returns an array of available nodequeue "channels" available.
*
* @return
* array with key of nodequeue ids and all settings within
*/
function nodequeue_service_get_nodequeues() {
if (module_exists('nodequeue')) {
// Fetch all of the queues.
$queues = nodequeue_load_queues(nodequeue_get_all_qids(0));
if (empty($queues)) {
return services_error(t('Nodequeue available, but no nodequeues exist.'));
}
else {
$availablequeues = array();
foreach ($queues as $queue) {
$availablequeues[$queue->qid]['qid'] = $queue->qid;
$availablequeues[$queue->qid]['title'] = $queue->title;
$availablequeues[$queue->qid]['subqueue_title'] = $queue->subqueue_title;
$availablequeues[$queue->qid]['size'] = $queue->size;
$availablequeues[$queue->qid]['link'] = $queue->link;
$availablequeues[$queue->qid]['link_remove'] = $queue->link_remove;
$availablequeues[$queue->qid]['owner'] = $queue->owner;
$availablequeues[$queue->qid]['show_in_ui'] = $queue->show_in_ui;
$availablequeues[$queue->qid]['show_in_tab'] = $queue->show_in_tab;
$availablequeues[$queue->qid]['show_in_links'] = $queue->show_in_links;
$availablequeues[$queue->qid]['reference'] = $queue->reference;
$availablequeues[$queue->qid]['reverse'] = $queue->reverse;
$availablequeues[$queue->qid]['subqueues'] = $queue->subqueues;
$availablequeues[$queue->qid]['types'] = $queue->types;
$availablequeues[$queue->qid]['roles'] = $queue->roles;
$availablequeues[$queue->qid]['count'] = $queue->count;
}
}
return $availablequeues;
}
else {
return services_error(t('Nodequeue module unavailable.'));
}
}
/**
* Returns an array of available subqueues by parent queue id.
*
* @param $qid
* integer representing the queue id of the parent nodequeue
*
* @return
* array with key of subqueue ids and all settings within
*/
function nodequeue_service_get_subqueues($qid) {
if (module_exists('nodequeue')) {
$subqueues = nodequeue_load_subqueues_by_queue($qid);
if (!empty($subqueues)) {
foreach ($subqueues as $subqueue) {
$availablequeues[$subqueue->sqid]['sqid'] = $subqueue->sqid;
$availablequeues[$subqueue->sqid]['qid'] = $qid;
$availablequeues[$subqueue->sqid]['reference'] = $subqueue->reference;
$availablequeues[$subqueue->sqid]['title'] = check_plain($subqueue->title);
$availablequeues[$subqueue->sqid]['count'] = $subqueue->count;
}
return $availablequeues;
}
else {
return services_error(t('Specified nodequeue has no subqueues.'));
}
}
else {
return services_error(t('Nodequeue module unavailable.'));
}
}
/**
* Access callback function for the nodequeue service.
*/
function nodequeue_service_get_nodequeues_access() {
if (user_access('get nodequeues')) {
return TRUE;
}
}

View File

@@ -0,0 +1,16 @@
name = Nodequeue Service
description = Provides a nodequeue service.
package = Nodequeue
core = 7.x
dependencies[] = services
dependencies[] = nodequeue
files[] = nodequeue_service.inc
; Information added by drupal.org packaging script on 2011-09-20
version = "7.x-2.0-beta1"
core = "7.x"
project = "nodequeue"
datestamp = "1316558104"

View File

@@ -0,0 +1,51 @@
<?php
/**
* @file
* Provides a nodequeue service.
*
* @author Greg Harvey - http://www.drupaler.co.uk
*/
/**
* Implements hook_permission().
*/
function nodequeue_service_permission() {
return array(
'get nodequeues' => array(
'title' => t('Get nodequeues'),
'description' => t('TODO Add a description for get nodequeues'),
),
);
}
/**
* Implements hook_service().
*/
function nodequeue_service_service() {
return array(
array(
'#method' => 'nodequeue.getQueues',
'#callback' => 'nodequeue_service_get_nodequeues',
'#access callback' => 'nodequeue_service_get_nodequeues_access',
'#file' => array('file' => 'inc', 'module' => 'nodequeue_service'),
'#return' => 'struct',
'#help' => t('Returns a keyed array by qid of available nodequeues and their settings.')
),
array(
'#method' => 'nodequeue.getSubQueues',
'#callback' => 'nodequeue_service_get_subqueues',
'#access callback' => 'nodequeue_service_get_nodequeues_access',
'#file' => array('file' => 'inc', 'module' => 'nodequeue_service'),
'#args' => array(
array(
'#name' => 'qid',
'#type' => 'int',
'#description' => t('A parent nodequeue queue ID.'),
),
),
'#return' => 'struct',
'#help' => t('Returns a keyed array by sqid of available subqueues and their settings.')
),
);
}

View File

@@ -0,0 +1,10 @@
The Nodequeue module allows an administrator or site editor to arbitrarily put nodes in a group for some purpose; examples of this might be to highlight one particular node, as in a typical news site's Lead Article. Another use might be to create a block listing teasers for 5 forum posts that the admin thinks are important. Another use might be to create a group of nodes, and then have a block or the front page offer one of these randomly.
Queues can be set to allow only certain types of nodes to be added to the queue. Queue can be a fixed size or of infinite length. And the admin can select which roles have permission to add nodes to a given queue.
<div class="clear-block"><a href="path:screenshot-lg.png"><img class="help-box help-right" src="path:screenshot-sm.png" /></a>Once a queue is set up, a new tab will appear on eligible nodes for eligible users. This tab will allow the user--regardless of edit permissions--to add or remove that node from the queue. Queue admins can view the nodes in the queue, and can modify the order of items already in the queue. Items may also appear in a nodes links area to add/remove them from the queue.
When a node is added to the queue, it is added to the <strong>back</strong> of the queue. If a queue is full when a node is added, the <strong>front</strong> of the queue is removed. In listings, the first item is the front and the last item is the back.
The queue administration page allows the administrator or site editor to arrange the queue in whatever order is suitable. There are 5 buttons for each entry; move up one, move to top (front), move down one, move to bottom, and remove from queue. Nodes may be added to the queue here using the autocomplete (in addition to the links and nodequeue tab) and there are various buttons to shuffle and clear the queue.
</div>

View File

@@ -0,0 +1,77 @@
Various API functions can be used as PHP snippets to include nodequeue functionality without Views. These are not nearly as powerful as simply using Nodequeue with Views, but they are available. Mostly these are leftover from older versions of nodequeue and they have not really been updated for Nodequeue 2.
<h2>To create a block to display node titles of a queue</h2>
You'll need the Queue ID, which is easily extracted from the URL on the
queue administration page.
Create a new block, and insert the following PHP snippet into the block:
<pre>
&lt;?php print nodequeue_node_titles(QUEUEID); ?&gt;
</pre>
If you want this queue to be printed in the reverse order, you can tell it
to print backward:
<pre>
&lt;?php print nodequeue_node_titles(QUEUEID, '', true); ?&gt;
</pre>
The '' in the line above is an optional title field. Feel free to put
something here, but it's not terribly necessary in a block.
<h2>To create a page to display node teasers of a queue</h2>
Like above, you'll need the Queue ID.
Create a new page (or a new dashboard!) or any node type you like, really,
and set the input filter to PHP. Insert the following PHP snippet:
<pre>
&lt;?php print nodequeue_nodes(QUEUEID); ?&gt;
</pre>
There are a few more options available here; changing the order of the nodes,
whether or not to use teasers or full nodes, whether or not to display the
links, and how much of the queue to display. See below.
<h2>To show just the first or last element of a queue</h2>
Starting with the examples above, but use the following:
<pre>
&lt;?php print nodequeue_fetch_front(QUEUEID); ?&gt;
</pre>
or
<pre>
&lt;?php print nodequeue_fetch_back(QUEUEID); ?&gt;
</pre>
Remember that the front of the queue will have the least recently added
nodes (unless it was rearranged manually), and the back will have the
most recently added.
<h2>Available functions and descriptions</h2>
<dl>
<dt><strong>nodequeue_node_titles($qid, $title = '', $backward = true, $from = 0, $count = 0)</strong></dt>
<dd>Display a title list of the queue. If backward is true (the default) the list will be from back (newest) to front (oldest).</dd>
<dt><strong>nodequeue_nodes($qid, $backward = true, $teasers = true, $links = true, $from = 0, $count = 0)</strong></dt>
<dd>Display the nodes of a queue. If backward is true (the default) the list will be from back (newest) to front (oldest). If $count is set to non-zero, it will use a range. For example, passing $from = 2 and $count = 2 will show the 3rd and 4th elements of the queue. ($count starts at 0, not 1.)
If $teasers is true, the node teaser will be shown; otherwise the full node will be shown.</dd>
<dt><strong>nodequeue_fetch_front($qid, $teasers = true, $links = true) </strong></dt>
<dd> Fetch the node at the front of the queue.</dd>
<dt><strong>nodequeue_fetch_back($qid, $teasers = true, $links = true) </strong></dt>
<dd> Fetch the node at the back of the queue.</dd>
<dt><strong>function nodequeue_fetch_random($qid, $teasers = true, $links = true) </strong></dt>
<dd> Fetch a random node from the queue</dd>
</dl>

View File

@@ -0,0 +1,12 @@
[advanced help settings]
line break = TRUE
[about]
title = About nodequeue
[smartqueue]
title = Smartqueues
[api]
title = Nodequeue API
weight = 10

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@@ -0,0 +1,65 @@
Smartqueues are a collection of subqueues wrapped up into a single queue; each subqueue within a smartqueue has some special attachment. For example, taxonomy smartqueues are attached to terms; nodes with a specific term can only be added to subqueues that match that term.
What this means is that if you have a taxonomy vocabulary named 'fruit', and in that vocabulary you have the terms 'apple', 'orange' and 'banana that you can create a taxonomy smartqueue associated with this vocabulary. A node tagged 'apple' will only be eligible to be added to the 'apple' subqueue. You could call this queue "Top %subqueues" and each taxonomy term will have its own top ten list. Each node will still only have a manageable number of queues listed on its nodequeue tab or on the links page.
Each kind of smartqueue will have its own rules; the form for creating that smartqueue should give you enough information to do so.
Smartqueue modules can be implemented with a fairly small amount of code; they might have to define an extra table to store information.
<h2>Smartqueue API</h2>
These are the hooks that a smartqueue module can use to implement.
Smartqueues should use the 'reference' field of the subqueue to determine what that particular subqueue is attached to, if at all possible.
<dl>
<dt><strong>hook_nodequeue_info()</strong></dt>
<dd>Collect info about all of the possible nodequeue types from owning modules. Returns an array; the key is the name of the 'module' for hook calls. The value is another array, which contains a 'title' and a 'description' for administrative purposes.</dd>
<dt><strong>hook_nodequeue_form($queue, &$form)</strong></dt>
<dd>Send the nodequeue edit form to the owning module for modification. This allows the smartqueue to modify the edit form to add additional fields or hide fields that are not appropriate.
$queue: The queue being edited.
&$form: The form. This may be modified.
</dd>
<dt><strong>hook_nodequeue_form_validate($queue, &$form_state, &$form)</strong></dt>
<dd>Validate the nodequeue edit form.
$queue: The queue being edited.
$form_state: The form state, which includes ['values'].
&$form: The actual form object. This may be modified.
</dd>
<dt><strong>hook_nodequeue_form_submit(&$queue, &$form_state)</strong></dt>
<dd>Send the nodequeue edit form to the owning module upon submit.
&$queue: The queue being edited. This may be modified prior to being saved.
$form_state: The form state, including the values.
</dd>
<dt><strong>hook_nodequeue_form_submit_finish($queue, &$form_state)</strong></dt>
<dd>Send the nodequeue edit form to the owning module after the queue has been saved. This is the only form state where you can be assured that the queue being edited will have a qid.
&$queue: The queue being edited. This may be modified prior to being saved.
$form_state: The form state, including the values that were submitted.
</dd>
<dt><strong>hook_nodequeue_subqueues(&$queue, $node)</strong></dt>
<dd>Fetch a list of subqueues that are valid for this node from the owning module. This is where the smartqueue module is likely to do the most work, since it has to determine which subqueues to display to a user here. This function is also responsible for creating smartqueues as they are needed.
$queue: The queue to check.
$node: The loaded node object being checked.
return: An array of subqueues. This will be keyed by $sqid.
</dd>
<dt><strong>hook_nodequeue_autocomplete($queue, $subqueue, $string)</strong></dt>
<dd>Fetch a list of nodes available to a given subqueue for autocomplete used on the queue arrange page.
$queue: The queue that owns the subqueue
$subqueue: The subqueue to check
$string: The string being matched.
return: An keyed array of nodes in the form $nid => $title, with a maximum of 10.
</dd>
</dl>

Binary file not shown.

After

Width:  |  Height:  |  Size: 795 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 615 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 622 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,301 @@
<?php
/**
* @file nodequeue.actions.inc
* Provides actions integration for nodequeues.
*/
/**
* Implements hook_action_info().
*/
function nodequeue_action_info() {
return array(
'nodequeue_add_action' => array(
'type' => 'node',
'label' => t('Add to Nodequeues'),
'configurable' => TRUE,
'triggers' => array(
'node_presave',
'node_insert',
'node_update',
),
),
'nodequeue_remove_action' => array(
'type' => 'node',
'label' => t('Remove from Nodequeues'),
'configurable' => TRUE,
'triggers' => array(
'node_delete',
),
),
);
}
/**
* Configuration form for Add to Nodequeues action.
*/
function nodequeue_add_action_form($context) {
// Default values for form.
if (!isset($context['qids'])) {
$context['qids'] = '';
}
$queues = nodequeue_load_queues(nodequeue_get_all_qids(0, 0, TRUE), TRUE);
foreach ($queues as $qid => $queue) {
$options[$qid] = $queue->title;
}
$form = array();
if (count($options)) {
// Add form components.
$form['qids'] = array(
'#type' => 'select',
'#title' => t("Queue"),
'#default_value' => $context['qids'],
'#multiple' => TRUE,
'#options' => $options,
'#required' => TRUE,
'#description' => t('Specify the queues into which the node should be submitted. If the queue is a smartqueue, the node shall be placed into every subqueue for which it is eligible.')
);
}
else {
drupal_set_message(t('Please <a href="@url">create</a> a nodequeue first.', array('@url' => url('admin/structure/nodequeue'))));
}
return $form;
}
/**
* Submit handler for Add to Nodequeues action configuration.
*/
function nodequeue_add_action_submit($form, &$form_state) {
return array(
'qids' => $form_state['values']['qids'],
);
}
/**
* Action to add a node to a queue.
*/
function nodequeue_add_action($node, $context) {
$queues = nodequeue_load_queues($context['qids'], TRUE);
// Filter out queues by node type. We choose not to use nodequeue_get_qids() because it checks for access control which only matters if we administering a queue.
$eligible_queues = array();
foreach ($queues as $queue) {
if (in_array($node->type, $queue->types)) {
$eligible_queues[$queue->qid] = $queue;
}
}
if (!empty($eligible_queues)) {
// Remove the node from the eligible queues (if needed).
nodequeue_remove_action($node, array('qids' => array_keys($eligible_queues)));
// Use API to get the eligible subqueues
$eligible_subqueues = nodequeue_get_subqueues_by_node($eligible_queues, $node);
// Add node to each subqueue.
foreach ($eligible_subqueues as $subqueue) {
nodequeue_subqueue_add($queues[$subqueue->qid], $subqueue, $node->nid);
}
}
}
/**
* Old-style action to add a node to a queue.
*/
function action_nodequeue_add($op, $edit = array(), $node) {
switch ($op) {
case 'metadata':
return array(
'description' => t('Add to Nodequeues'),
'type' => t('node'),
'batchable' => TRUE,
'configurable' => TRUE,
);
break;
case 'do':
$queues = nodequeue_load_queues($edit['qids'], TRUE);
// Filter out queues by node type. We choose not to use nodequeue_get_qids() because it checks for access control which only matters if we administering a queue.
$eligible_queues = array();
foreach ($queues as $queue) {
if (in_array($node->type, $queue->types)) {
$eligible_queues[$queue->qid] = $queue;
}
}
if (!empty($eligible_queues)) {
// Remove the node from the eligible queues (if needed).
action_nodequeue_remove('do', array('qids' => array_keys($eligible_queues)), $node);
// Use API to get the eligible subqueues
$eligible_subqueues = nodequeue_get_subqueues_by_node($eligible_queues, $node);
// Add node to each subqueue.
foreach ($eligible_subqueues as $subqueue) {
nodequeue_subqueue_add($queues[$subqueue->qid], $subqueue, $node->nid);
}
}
break;
// return an HTML config form for the action
case 'form':
// default values for form
if (!isset($edit['qids'])) {
$edit['qids'] = '';
}
$queues = nodequeue_load_queues(nodequeue_get_all_qids(0, 0, TRUE), TRUE);
foreach ($queues as $qid => $queue) {
$options[$qid] = $queue->title;
}
$form = array();
if (count($options)) {
// add form components
$form['qids'] = array(
'#type' => 'select',
'#title' => t("Queue"),
'#default_value' => $edit['qids'],
'#multiple' => TRUE,
'#options' => $options,
'#required' => TRUE,
'#description' => t('Specify the queues into which the node should be submitted. If the queue is a smartqueue, the node shall be placed into every subqueue for which it is eligible.')
);
}
else {
drupal_set_message(t('Please <a href="@url">create</a> a nodequeue first.', array('@url' => url('admin/structure/nodequeue'))));
}
return $form;
// validate the HTML form
// process the HTML form to store configuration
case 'submit':
$params = array(
'qids' => $edit['qids']
);
return $params;
break;
}
}
/**
* Configuration form for Remove from Nodequeues action.
*/
function nodequeue_remove_action_form($context) {
// Default values for form.
if (!isset($context['qids'])) {
$context['qids'] = array();
}
$queues = nodequeue_load_queues(nodequeue_get_all_qids(0, 0, TRUE), TRUE);
foreach ($queues as $qid => $queue) {
$options[$qid] = $queue->title;
}
// Add form components.
$form['qids'] = array(
'#type' => 'select',
'#title' => t("Queues"),
'#default_value' => $context['qids'],
'#multiple' => TRUE,
'#decription' => t('Specify the queues from which the node should be removed. If the queue is a smartqueue, the node shall be removed from all subqueues.'),
'#required' => TRUE,
'#options' => $options,
);
return $form;
}
/**
* Submit handler for Remove from Nodequeues action configuration.
*/
function nodequeue_remove_action_submit($form, &$form_state) {
return array(
'qids' => $form_state['values']['qids'],
);
}
function nodequeue_remove_action($node, $context) {
$qids = $context['qids'];
// If a node is being deleted, ensure it's also removed from any queues.
$args = $qids;
$result = db_select('nodequeue_nodes', 'n')
->fields('n')
->condition('nid', $node->nid)
->condition('qid', $args)
->execute()
->fetchAll();
foreach ($result as $obj) {
// This removes by nid, not position, because if we happen to have a
// node in a queue twice, the 2nd position would be wrong.
nodequeue_subqueue_remove_node($obj->sqid, $node->nid);
}
}
/**
* Old-style action to remove a node from a queue.
*/
function action_nodequeue_remove($op, $edit = array(), $node) {
switch ($op) {
case 'metadata':
return array(
'description' => t('Remove from Nodequeues'),
'type' => t('node'),
'batchable' => TRUE,
'configurable' => TRUE,
);
break;
case 'do':
$qids = $edit['qids'];
// If a node is being deleted, ensure it's also removed from any queues.
$args = $qids;
$result = db_select('nodequeue_nodes', 'n')
->fields('n')
->condition('nid', $node->nid)
->condition('qid', $args)
->execute()
->fetchAll();
foreach ($result as $obj) {
// This removes by nid, not position, because if we happen to have a
// node in a queue twice, the 2nd position would be wrong.
nodequeue_subqueue_remove_node($obj->sqid, $node->nid);
}
break;
// return an HTML config form for the action
case 'form':
// default values for form
if (!isset($edit['qids'])) {
$edit['qids'] = array();
}
$queues = nodequeue_load_queues(nodequeue_get_all_qids(0, 0, TRUE), TRUE);
foreach ($queues as $qid => $queue) {
$options[$qid] = $queue->title;
}
// add form components
$form['qids'] = array(
'#type' => 'select',
'#title' => t("Queues"),
'#default_value' => $edit['qids'],
'#multiple' => TRUE,
'#decription' => t('Specify the queues from which the node should be removed. If the queue is a smartqueue, the node shall be removed from all subqueues.'),
'#required' => TRUE,
'#options' => $options,
);
return $form;
break;
// validate the HTML form
// process the HTML form to store configuration
case 'submit':
$params = array(
'qids' => $edit['qids']
);
return $params;
break;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,271 @@
<?php
/**
* @file nodequeue.views.inc
* Provides support for the Views module.
*
* This implementation is almost entirely based around a relationship
* which is stapled to the 'node' table via hook_views_data_alter.
*
* The relationship allows you to define 0 or more queues that join the
* queue tables, limiting the join to just the queues selected. Once
* the queues are joined in, the queue fields will show up, and they
* have the usual array of arguments, sorts, fields and filters; since
* the real legwork is done by the relationship, most of these are
* really quite simple.
*/
/**
* Implements hook_views_data().
*/
function nodequeue_views_data() {
$data = array();
// ----------------------------------------------------------------
// nodequeue_nodes table
$data['nodequeue_nodes']['table']['group'] = t('Nodequeue');
// The nodequeue_nodes table is how nodequeue connects to the
// rest of the world, but we will only join it in via relationship.
// position
$data['nodequeue_nodes']['position'] = array(
'title' => t('Position'),
'help' => t('The position of the node within a queue.'),
'field' => array(
'handler' => 'views_handler_field_numeric',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'handler' => 'views_handler_argument_numeric',
),
);
// timestamp
$data['nodequeue_nodes']['timestamp'] = array(
'title' => t('Added date'),
'help' => t('The date the node was added to a queue.'),
'field' => array(
'handler' => 'views_handler_field_date',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort_date',
),
'filter' => array(
'handler' => 'views_handler_filter_date',
),
);
$data['nodequeue_nodes']['qid'] = array(
'title' => t('Queue ID'),
'help' => t('The ID of the queue the node belongs to.'),
'field' => array(
'handler' => 'views_handler_field_numeric',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'argument' => array(
'handler' => 'views_handler_argument_numeric',
'name field' => 'title',
'name table' => 'nodequeue_queue',
'empty field name' => t('No queue'),
),
);
$data['nodequeue_nodes']['sqid'] = array(
'title' => t('Subqueue ID'),
'help' => t('The ID of the subqueue the node belongs to.'),
'field' => array(
'handler' => 'views_handler_field_numeric',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'argument' => array(
'handler' => 'views_handler_argument_numeric',
'name field' => 'title',
'name table' => 'nodequeue_subqueue',
'empty field name' => t('No queue'),
),
);
// specialized is null/is not null filter
$data['nodequeue_nodes']['in_queue'] = array(
'title' => t('In queue'),
'help' => t('Filter to ensure a node IS or IS NOT in the related queue'),
'filter' => array(
'handler' => 'nodequeue_handler_filter_in_queue',
'label' => t('In queue'),
),
);
$data['nodequeue_queue']['name'] = array(
'title' => t('Queue machine name'),
'help' => t('The machine name of the queue.'),
'field' => array(
'handler' => 'views_handler_field',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_string',
),
'argument' => array(
'handler' => 'views_handler_argument_string',
),
);
// ----------------------------------------------------------------
// nodequeue_queue table
$data['nodequeue_queue']['table']['group'] = t('Nodequeue');
// For use with the relationship.
$data['nodequeue_queue']['table']['join'] = array(
'nodequeue_nodes' => array(
'left_field' => 'qid',
'field' => 'qid',
),
);
$data['nodequeue_queue']['title'] = array(
'title' => t('Queue title'),
'help' => t('The title of the nodequeue.'),
'field' => array(
'handler' => 'views_handler_field',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_string',
),
'argument' => array(
'handler' => 'views_handler_argument_string',
),
);
// ----------------------------------------------------------------
// nodequeue_subqueue table
$data['nodequeue_subqueue']['table']['group'] = t('Nodequeue');
// For use with the relationship.
$data['nodequeue_subqueue']['table']['join'] = array(
'nodequeue_nodes' => array(
'left_field' => 'sqid',
'field' => 'sqid',
),
);
$data['nodequeue_subqueue']['title'] = array(
'title' => t('Subqueue title'),
'help' => t('The title of the subqueue.'),
'field' => array(
'handler' => 'views_handler_field',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_string',
),
'argument' => array(
'handler' => 'views_handler_argument_string',
),
);
$data['nodequeue_subqueue']['reference'] = array(
'title' => t('Subqueue reference'),
'help' => t('The reference that defines a subqueue; what this actually is depends upon the type of subqueue, but is a taxonomy tid for smartqueue taxonomy, or a uid for authorview.'),
'field' => array(
'handler' => 'views_handler_field',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_string',
),
'argument' => array(
'handler' => 'views_handler_argument_string',
),
);
return $data;
}
/**
* Implements hook_views_data_alter().
*/
function nodequeue_views_data_alter(&$data) {
// queue relationship
$data['node']['nodequeue_rel'] = array(
'group' => t('Nodequeue'),
'title' => t('Queue'),
'help' => t('Create a relationship to a nodequeue.'),
'real field' => 'nid',
'relationship' => array(
'handler' => 'nodequeue_handler_relationship_nodequeue',
'base' => 'nodequeue_nodes',
'field' => 'nid',
'label' => t('queue'),
),
);
// links
$data['node']['nodequeue_links'] = array(
'group' => t('Nodequeue'),
'title' => t('Add/remove links'),
'help' => t('Display add/remove links for all eligible nodequeues. Note that this performs a node_load so could add many extra queries to a view.'),
'real field' => 'nid',
'field' => array(
'handler' => 'nodequeue_handler_field_links',
),
);
$data['node']['nodequeue_queue_tab'] = array(
'group' => t('Nodequeue'),
'title' => t('Link to tab'),
'help' => t('Display add/remove links for all eligible nodequeues. Note that this performs a node_load so could add many extra queries to a view.'),
'real field' => 'nid',
'field' => array(
'handler' => 'nodequeue_handler_field_queue_tab',
),
);
// all queues
$data['node']['nodequeue_all_queues'] = array(
'group' => t('Nodequeue'),
'title' => t('All queues'),
'help' => t('Display all queues a node is a member of.'),
'real field' => 'nid',
'field' => array(
'handler' => 'nodequeue_handler_field_all_queues',
),
);
// all subqueues
$data['node']['nodequeue_all_subqueues'] = array(
'group' => t('Nodequeue'),
'title' => t('All subqueues'),
'help' => t('Display all subqueues a node is a member of.'),
'real field' => 'nid',
'field' => array(
'handler' => 'nodequeue_handler_field_all_subqueues',
),
);
}

View File

@@ -0,0 +1,197 @@
<?php
/**
* @file
* Default views for nodequeue. This modifies an exported view; it might
* actually work better to create the view dynamically. It would be less
* code and more modifiable later.
*/
function nodequeue_views_default_views() {
$views = array();
if (variable_get('nodequeue_view_per_queue', 1) != 1) {
return $views;
}
$queues = nodequeue_load_queues(nodequeue_get_all_qids());
foreach ($queues as $queue) {
$view = new view;
$view->name = "nodequeue_$queue->qid";
$view->description = t("Display a list of all nodes in queue '@queue'", array('@queue' => $queue->title));
$view->tag = t('nodequeue');
$view->view_php = '';
$view->base_table = 'node';
$view->is_cacheable = '0';
$view->api_version = 2;
$view->disabled = FALSE; // Edit this to true to make a default view disabled initially
$view->display = array();
$display = new views_display;
$display->id = 'default';
$display->display_title = t('Defaults');
$display->display_plugin = 'default';
$display->position = '1';
$display->display_options = array(
'style_plugin' => 'default',
'style_options' => array(),
'row_plugin' => 'node',
'row_options' => array(
'teaser' => 1,
'links' => 1,
),
'relationships' => array(
'nodequeue_rel' => array(
'id' => 'nodequeue_rel',
'table' => 'node',
'field' => 'nodequeue_rel',
'label' => 'queue',
'required' => 1,
'limit' => TRUE,
'qids' => array($queue->qid => $queue->qid),
'relationship' => 'none',
),
),
'fields' => array(
'title' => array(
'id' => 'title',
'table' => 'node',
'field' => 'title',
'label' => '',
'relationship' => 'none',
'link_to_node' => 1,
),
),
'sorts' => array(
'position' => array(
'id' => 'position',
'table' => 'nodequeue_nodes',
'field' => 'position',
'order' => 'ASC',
'relationship' => 'nodequeue_rel',
),
),
'arguments' => array(),
'filters' => array(
'status_extra' => array(
'id' => 'status_extra',
'table' => 'node',
'field' => 'status_extra',
'operator' => '=',
'value' => '',
'group' => 0,
'exposed' => FALSE,
'expose' => array(
'operator' => FALSE,
'label' => '',
),
'relationship' => 'none',
),
),
'items_per_page' => 10,
'use_pager' => '1',
'pager_element' => 0,
'title' => t("Queue '@queue'", array('@queue' => $queue->title)),
'use_more' => 1,
);
$view->display['default'] = $display;
$display = new views_display;
$display->id = 'page';
$display->display_title = t('Page');
$display->display_plugin = 'page';
$display->position = '2';
$display->display_options = array(
'defaults' => array(
'access' => TRUE,
'title' => TRUE,
'header' => TRUE,
'header_format' => TRUE,
'header_empty' => TRUE,
'footer' => TRUE,
'footer_format' => TRUE,
'footer_empty' => TRUE,
'empty' => TRUE,
'empty_format' => TRUE,
'use_ajax' => TRUE,
'items_per_page' => TRUE,
'offset' => TRUE,
'use_pager' => TRUE,
'pager_element' => TRUE,
'use_more' => TRUE,
'distinct' => TRUE,
'link_display' => TRUE,
'style_plugin' => TRUE,
'style_options' => TRUE,
'row_plugin' => TRUE,
'row_options' => TRUE,
'relationships' => TRUE,
'fields' => TRUE,
'sorts' => TRUE,
'arguments' => TRUE,
'filters' => TRUE,
),
'relationships' => array(),
'fields' => array(),
'sorts' => array(),
'arguments' => array(),
'filters' => array(),
'path' => "nodequeue/$queue->qid",
);
$view->display['page'] = $display;
$display = new views_display;
$display->id = 'block';
$display->display_title = t('Block');
$display->display_plugin = 'block';
$display->position = '3';
$display->display_options = array(
'defaults' => array(
'access' => TRUE,
'title' => TRUE,
'header' => TRUE,
'header_format' => TRUE,
'header_empty' => TRUE,
'footer' => TRUE,
'footer_format' => TRUE,
'footer_empty' => TRUE,
'empty' => TRUE,
'empty_format' => TRUE,
'use_ajax' => TRUE,
'items_per_page' => FALSE,
'offset' => FALSE,
'use_pager' => FALSE,
'pager_element' => FALSE,
'use_more' => TRUE,
'distinct' => TRUE,
'link_display' => TRUE,
'style_plugin' => FALSE,
'style_options' => FALSE,
'row_plugin' => FALSE,
'row_options' => FALSE,
'relationships' => TRUE,
'fields' => TRUE,
'sorts' => TRUE,
'arguments' => TRUE,
'filters' => TRUE,
),
'relationships' => array(),
'fields' => array(),
'sorts' => array(),
'arguments' => array(),
'filters' => array(),
'style_plugin' => 'list',
'style_options' => array(
'type' => 'ul',
),
'row_plugin' => 'fields',
'row_options' => array(
'inline' => array(),
'separator' => '',
),
'block_description' => t("Queue '@queue'", array('@queue' => $queue->title)),
'items_per_page' => 5,
'offset' => 0,
'use_pager' => '0',
'pager_element' => 0,
);
$view->display['block'] = $display;
$views[$view->name] = $view;
}
return $views;
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* @file
* Argument handler for subqueues.
*/
/**
* Subqueues have titles that are determined by doing substitution from
* the subqueue_title on the queue using the title on the subqueue, which
* takes a little extra work to do here.
*/
class nodequeue_handler_argument_subqueue_qid extends views_handler_argument_numeric {
function summary_name_field() {
$this->queue_alias = $this->query->ensure_table('nodequeue_queue', $this->relationship);
$this->subqueue_alias = $this->name_table_alias = $this->query->ensure_table('nodequeue_subqueue', $this->relationship);
$this->queue_title_alias = $this->query->add_field($this->queue_alias, 'subqueue_title');
$this->subqueue_title_alias = $this->name_alias = $this->query->add_field($this->subqueue_alias, 'title');
}
function summary_name($data) {
$queue_title = $data->{$this->queue_title_alias};
$subqueue_title = $data->{$this->subqueue_title_alias};
$value = empty($queue_title) ? $subqueue_title : str_replace('%subqueue', $subqueue_title, $queue_title);
if (empty($value) && !empty($this->definition['empty field name'])) {
$value = $this->definition['empty field name'];
}
return check_plain($value);
}
}

View File

@@ -0,0 +1,82 @@
<?php
/**
* @file
* Field handler for all queues.
*
* @ingroup views_field_handlers
*/
class nodequeue_handler_field_all_queues extends views_handler_field_prerender_list {
/**
* Provide meaningful defaults.
*/
function options(&$options) {
parent::options($options);
$options['link_to_queue'] = TRUE;
$options['limit'] = FALSE;
$options['qids'] = array();
}
/**
* Provide "link to term" option.
*/
function options_form(&$form, &$form_state) {
parent::options_form($form, $form_state);
$form['link_to_queue'] = array(
'#title' => t('Link this field to queue arrange page'),
'#type' => 'checkbox',
'#default_value' => !empty($this->options['link_to_taxonomy']),
);
$form['limit'] = array(
'#type' => 'checkbox',
'#title' => t('Limit to queues'),
'#default_value' => $this->options['limit'],
);
$options = array();
$queues = nodequeue_load_queues(nodequeue_get_all_qids());
foreach ($queues as $queue) {
$options[$queue->qid] = $queue->title;
}
$form['qids'] = array(
'#prefix' => '<div><div id="edit-options-qids">',
'#suffix' => '</div></div>',
'#type' => 'checkboxes',
'#title' => t('Queues'),
'#options' => $options,
'#default_value' => $this->options['qids'],
'#states' => array(
'visible' => array(
':input[name="options[limit]"]' => array('checked' => TRUE)
),
),
);
}
function pre_render($values) {
$nids = array();
foreach ($values as $result) {
$nids[] = $result->{$this->field_alias};
}
if ($nids) {
$queue = '';
if (!empty($this->options['limit']) && !empty($this->options['qids'])) {
$queue = " AND nn.qid IN (" . implode(', ', array_keys(array_filter($this->options['qids']))) . ")";
}
$result = db_query("SELECT nn.nid, nn.qid, nq.title FROM {nodequeue_nodes} nn INNER JOIN {nodequeue_queue} nq ON nq.qid = nn.qid WHERE nn.nid IN (" . implode(', ', $nids) . ")$queue ORDER BY nq.title");
foreach ($result as $queue) {
if (empty($this->options['link_to_queue'])) {
$this->items[$queue->nid][$queue->qid] = check_plain($queue->title);
}
else {
$this->items[$queue->nid][$queue->qid] = l($queue->title, "admin/structure/nodequeue/$queue->qid");
}
}
}
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
* @file
* Field handler for all subqueues
*
* @ingroup views_field_handlers
*/
class nodequeue_handler_field_all_subqueues extends nodequeue_handler_field_all_queues {
function pre_render($values) {
if (user_access('manipulate queues') || user_access('manipulate all queues')) {
$nids = array();
foreach ($values as $result) {
$nids[] = $result->{$this->field_alias};
}
if ($nids) {
$queue = '';
if (!empty($this->options['limit']) && !empty($this->options['qids'])) {
$queue = " AND nn.qid IN (" . implode(', ', array_keys(array_filter($this->options['qids']))) . ")";
}
$result = db_query("SELECT nn.nid, nn.sqid, nn.qid, nq.subqueue_title, ns.title FROM {nodequeue_nodes} nn INNER JOIN {nodequeue_queue} nq ON nq.qid = nn.qid INNER JOIN {nodequeue_subqueue} ns on nn.sqid = ns.sqid WHERE nn.nid IN (" . implode(', ', $nids) . ")$queue ORDER BY ns.title, nq.subqueue_title");
foreach ($result as $queue) {
$title = empty($queue->subqueue_title) ? $queue->title : str_replace('%subqueue', $queue->title, $queue->subqueue_title);
if (empty($this->options['link_to_queue'])) {
$this->items[$queue->nid][$queue->sqid] = check_plain($title);
}
else {
$this->items[$queue->nid][$queue->sqid] = l($title, "admin/structure/nodequeue/$queue->qid/view/$queue->sqid");
}
}
}
}
}
}

View File

@@ -0,0 +1,14 @@
<?php
/**
* @file
* Views field handler for the nodequeue queue links
*/
class nodequeue_handler_field_links extends views_handler_field_node_link {
function render($values) {
if (user_access('manipulate queues') || user_access('manipulate all queues')) {
$nid = $values->{$this->aliases['nid']};
return theme('links', array('links' => nodequeue_node_links(node_load($nid))));
}
}
}

View File

@@ -0,0 +1,13 @@
<?php
/**
* @file
* Views field handler for the nodequeue queue links
*/
class nodequeue_handler_field_queue_tab extends views_handler_field_node_link {
function render($values) {
$text = !empty($this->options['text']) ? $this->options['text'] : t('view');
$nid = $values->{$this->aliases['nid']};
return l($text, "node/$nid/nodequeue");
}
}

View File

@@ -0,0 +1,12 @@
<?php
/**
* @file
* Handler to filter for nodes that are not in a queue.
*/
class nodequeue_handler_filter_in_queue extends views_handler_filter_boolean_operator {
function query() {
$this->ensure_my_table();
$this->query->add_where($this->options['group'], $this->table_alias . ".nid", $this->value, ($this->value ? '!=' : 'IS NULL'));
}
}

View File

@@ -0,0 +1,101 @@
<?php
/**
* @file
* Specialized relationship handler to add nodequeues.
*/
class nodequeue_handler_relationship_nodequeue extends views_handler_relationship {
/**
* Init handler to let relationships live on tables other than
* the table they operate on.
*/
function init(&$view, &$options) {
parent::init($view, $options);
// Tranlate an older setting which was using qids instead of machine names.
if (!empty($options['qids'])) {
$map = array_flip(nodequeue_get_qid_map());
foreach ($options['qids'] as $key => $value) {
$this->options['names'][$map[$key]] = ($value) ? $map[$key] : 0;
}
unset($this->options['qids']);
}
}
function option_definition() {
$options = parent::option_definition();
$options['limit']['default'] = FALSE;
$options['names']['default'] = array();
return $options;
}
/**
* Default options form that provides the label widget that all fields
* should have.
*/
function options_form(&$form, &$form_state) {
parent::options_form($form, $form_state);
$form['limit'] = array(
'#type' => 'checkbox',
'#title' => t('Limit to one or more queues (recommended)'),
'#default_value' => $this->options['limit'],
);
$options = array();
$queues = nodequeue_load_queues(nodequeue_get_all_qids(0, 0, TRUE), TRUE);
foreach ($queues as $queue) {
$options[$queue->name] = $queue->title;
}
$form['names'] = array(
'#prefix' => '<div><div id="edit-options-names">',
'#suffix' => '</div></div>',
'#type' => 'checkboxes',
'#title' => t('Queues'),
'#options' => $options,
'#default_value' => $this->options['names'],
'#process' => array('form_process_checkboxes', 'ctools_dependent_process'),
'#dependency' => array('edit-options-limit' => array(TRUE)),
);
}
/**
* Called to implement a relationship in a query.
*/
function query() {
// Figure out what base table this relationship brings to the party.
$join = new views_join();
$join->definition = array(
'table' => 'nodequeue_nodes',
'field' => 'nid',
'left_table' => 'node',
'left_field' => 'nid',
);
if (!empty($this->options['required'])) {
$join->definition['type'] = 'INNER';
}
if (!empty($this->options['limit'])) {
$names = array_keys(array_filter($this->options['names']));
$qids = array();
$map = nodequeue_get_qid_map();
foreach ($names as $name) {
if (isset($map[$name])) {
$qids[] = $map[$name];
}
}
$join->definition['extra'] = array(array(
'field' => 'qid',
'value' => $qids,
));
}
$join->construct();
$alias = $join->definition['table'] . '_' . $join->definition['left_table'];
$this->alias = $this->query->add_relationship($alias, $join, 'nodequeue_nodes', $this->relationship);
}
}

View File

@@ -0,0 +1,13 @@
.nodequeue-dragdrop .position {
font-weight: bold;
color: #999;
}
#edit-add-nid {
color: #999;
}
td.nodequeue-add-submit {
width: 80%;
}

View File

@@ -0,0 +1,25 @@
name = Nodequeue
description = Create queues which can contain nodes in arbitrary order
package = Nodequeue
core = 7.x
configure = admin/structure/nodequeue/settings
; Includes
files[] = includes/views/nodequeue.views.inc
files[] = includes/nodequeue.actions.inc
; Views Handlers
files[] = includes/views/nodequeue_handler_argument_subqueue_qid.inc
files[] = includes/views/nodequeue_handler_field_all_queues.inc
files[] = includes/views/nodequeue_handler_field_all_subqueues.inc
files[] = includes/views/nodequeue_handler_field_links.inc
files[] = includes/views/nodequeue_handler_field_queue_tab.inc
files[] = includes/views/nodequeue_handler_filter_in_queue.inc
files[] = includes/views/nodequeue_handler_relationship_nodequeue.inc
; Information added by drupal.org packaging script on 2011-09-20
version = "7.x-2.0-beta1"
core = "7.x"
project = "nodequeue"
datestamp = "1316558104"

View File

@@ -0,0 +1,416 @@
<?php
/**
* @file
* Install, update and uninstall functions for the nodequeue module.
*/
/**
* Implements hook_schema().
*/
function nodequeue_schema() {
$schema['nodequeue_queue'] = array(
'description' => 'Base table for queues, storing global information for each queue',
'fields' => array(
'qid' => array(
'description' => 'The primary identifier for a queue.',
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE
),
'name' => array(
'description' => 'The machine name for the queue.',
'type' => 'varchar',
'length' => 128,
),
'title' => array(
'description' => 'Title of a queue.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
),
'subqueue_title' => array(
'description' => 'Title of a subqueue.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
),
'size' => array(
'description' => 'How many nodes this queue will hold',
'type' => 'int',
'default' => 0,
),
'link' => array(
'description' => 'The link text to show under a node to add it to the queue.',
'type' => 'varchar',
'length' => 40,
),
'link_remove' => array(
'description' => 'The link text to show under a node to remove it from the queue.',
'type' => 'varchar',
'length' => 40,
),
'owner' => array(
'description' => '',
'type' => 'varchar',
'length' => 255,
),
'show_in_ui' => array(
'description' => '',
'type' => 'int',
'size' => 'tiny',
'default' => 1,
),
'show_in_tab' => array(
'description' => '',
'type' => 'int',
'size' => 'tiny',
'default' => 1,
),
'show_in_links' => array(
'description' => '',
'type' => 'int',
'size' => 'tiny',
'default' => 1,
),
'reference' => array(
'description' => '',
'type' => 'varchar',
'length' => 255,
'default' => '0',
),
'reverse' => array(
'description' => '',
'type' => 'int',
'size' => 'tiny',
'default' => 0,
),
'i18n' => array(
'description' => '',
'type' => 'int',
'size' => 'tiny',
'default' => 1,
),
), // fields
'primary key' => array('qid'),
'unique keys' => array(
'name' => array('name'),
),
); // nodequeue_queue.
$schema['nodequeue_roles'] = array(
'description' => 'Defines the roles which are allowed to use a particular nodequeue.',
'fields' => array(
'qid' => array(
'description' => 'Primary key for {nodequeue_queue}',
'type' => 'int',
'size' => 'big',
'unsigned' => TRUE,
'not null' => TRUE
),
'rid' => array(
'description' => 'Primary key for roles',
'type' => 'int',
'size' => 'big',
'unsigned' => TRUE,
'not null' => TRUE
),
), // fields
'indexes' => array(
'qid' => array('qid'),
'rid' => array('rid'),
), // indexes
); // nodequeue_roles
$schema['nodequeue_types'] = array(
'description' => 'Defines the node types which are allowed in each queue',
'fields' => array(
'qid' => array(
'description' => 'Primary key for {nodequeue_queue}',
'type' => 'int',
'size' => 'big',
'unsigned' => TRUE,
'not null' => TRUE
),
'type' => array(
'description' => 'Node Type',
'type' => 'varchar',
'length' => 255,
'not null' => FALSE
),
), // fields
'indexes' => array(
'qid' => array('qid'),
'type' => array('type'),
), // indexes
); // nodequeue_types
// Subqueues are minor queues that inherit all of the properties of
// the parent queue. A parent queue must have at least 1 subqueue
// to do anything. Reference is for the use of whatever is creating
// the subqueues in order to link it to some other ID easily.
$schema['nodequeue_subqueue'] = array(
'description' => 'Subqueues are minor queues that inherit all of the properties of the parent queue. A parent queue must have at least 1 subqueue to do anything. Reference is for the use of whatever is creating the subqueues in order to link it to some other ID easily.',
'fields' => array(
'sqid' => array(
'description' => 'Subqueue identifier',
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE,
),
'qid' => array(
'description' => 'Queue identifier.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
),
'reference' => array(
'description' => '',
'type' => 'varchar',
'length' => 255,
'default' => '0',
'not null' => FALSE
),
'title' => array(
'description' => '',
'type' => 'varchar',
'length' => 255,
'default' => '',
'not null' => FALSE
),
), // fields
'primary key' => array('sqid'),
'indexes' => array(
'qid' => array('qid'),
'reference' => array('reference'),
'title' => array('title'),
), // indexes
); // nodequeue_subqueue
$schema['nodequeue_nodes'] = array(
'description' => 'Indicates which nodes are in which queues/subqueues.',
'fields' => array(
'qid' => array(
'description' => 'Queue id',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
),
'sqid' => array(
'description' => 'Subqueue this node is in',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
),
'nid' => array(
'description' => 'Node id in this subqueue',
'type' => 'int',
'unsigned' => TRUE,
'not null' => FALSE
),
'position' => array(
'description' => 'The position of the node in this subqueue.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => FALSE
),
'timestamp' => array(
'description' => "The time that the item's position in the subqueue was updated.",
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
), // fields
'indexes' => array(
'sqid' => array('sqid', 'position'),
'nid' => array('nid'),
'qid_nid' => array('qid', 'nid'),
), // indexes
); // nodequeue_nodes
return $schema;
}
/**
* Implements hook_uninstall().
*/
function nodequeue_uninstall() {
// Remove our variables.
$variables = array(
'nodequeue_use_tab',
'nodequeue_tab_display_max',
'nodequeue_tab_name',
'nodequeue_autocomplete_limit',
'nodequeue_view_per_queue',
);
foreach ($variables as $variable) {
variable_del($variable);
}
}
/**
* There was a discrepancy between the link/link_remove fields created with
* node_install/node_schema, and the ones created with nodequeue_update_5000.
* This forces everyone to 40 characters.
*/
function nodequeue_update_6000() {
$ret = array();
db_change_field('nodequeue_queue', 'link', 'link', array('type' => 'varchar', 'length' => 40));
db_change_field('nodequeue_queue', 'link_remove', 'link_remove', array('type' => 'varchar', 'length' => 40));
return $ret;
}
/**
* @todo Please insert a Doxygen style comment for this hook_update_N.
*/
function nodequeue_update_6001() {
$ret = array();
db_add_field('nodequeue_queue', 'i18n', array('description' => '', 'type' => 'int', 'size' => 'tiny', 'default' => 1));
return $ret;
}
// The previous 6002 update has been moved to 5205.
/**
* Remove invalid entries from the nodequeue_nodes table created as a result of
* bugs like http://drupal.org/node/593858.
*/
function nodequeue_update_6003() {
$ret = array();
$invalid = db_query("SELECT count(nid) FROM {nodequeue_nodes} WHERE nid = 0")->fetchField();
if (!empty($invalid)) {
db_delete('nodequeue_nodes')
->condition('nid', 0)
->execute();
$t = get_t();
$ret[] = array('success' => TRUE, 'query' => $t("Deleted @invalid invalid entries from the {nodequeue_nodes} table.", array('@invalid' => $invalid)));
}
else {
$ret[] = array('success' => TRUE, 'query' => "No invalid entries found in the {nodequeue_nodes} table.");
}
return $ret;
}
/**
* Add a new index to {nodequeue_nodes}
*/
function nodequeue_update_6004() {
$ret = array();
db_add_index('nodequeue_nodes', '{nodequeue_nodes}_qid_nid_idx', array('qid', 'nid'));
return $ret;
}
/**
* Rename the 'nodequeue_automatic_views_generation'
* to 'nodequeue_view_per_queue'.
*/
function nodequeue_update_6005() {
$ret = array();
$ret[] = update_sql("UPDATE {system} set name = 'nodequeue_view_per_queue' where name = 'nodequeue_automatic_views_generation'");
return $ret;
}
/**
* Renaming indices so that they're consistent with what Schema module would
* expect.
*/
function nodequeue_update_7200() {
// Check if the indices weren't already renamed by a 6.x-2.x-dev version
// prior to 6.x-2.10.
if (!db_index_exists('nodequeue_nodes', 'sqid')) {
// Delete existing indexes
$del_indices = array(
'nodequeue_roles' => array('qid', 'rid'),
'nodequeue_types' => array('qid', 'type'),
'nodequeue_subqueue' => array('qid', 'reference', 'title'),
'nodequeue_nodes' => array('sqid', 'qid_nid'),
);
foreach ($del_indices as $table => $indices) {
foreach ($indices as $k => $index) {
db_drop_index($table, $table . "_" . $index . "_idx");
}
}
// Naming convention incorrect for this one
db_drop_index("nodequeue_nodes", "nodequeue_subqueue_nid_idx");
// Create new indexes
$add_indexes = array(
'nodequeue_roles' => array(
'qid' => array('qid'),
'rid' => array('rid'),
),
'nodequeue_types' => array(
'qid' => array('qid'),
'type' => array('type'),
),
'nodequeue_subqueue' => array(
'qid' => array('qid'),
'reference' => array('reference'),
'title' => array('title'),
),
'nodequeue_nodes' => array(
'sqid' => array('sqid', 'position'),
'qid_nid' => array('qid', 'nid'),
'nid' => array('nid'),
),
);
foreach ($add_indexes as $table => $indices) {
foreach ($indices as $name => $columns) {
db_add_index($table, $name, $columns);
}
}
}
}
/**
* Provide machine names and auto-generation of machine names for existing
* queues.
*/
function nodequeue_update_7201() {
// Check that the name field hasn't been created by a 6.x-2.x-dev version
// prior to 6.x-2.10.
if (!db_field_exists('nodequeue_queue', 'name')) {
$name_field = array(
'description' => 'The machine name for the queue.',
'type' => 'varchar',
'length' => 128,
);
db_add_field('nodequeue_queue', 'name', $name_field);
db_add_unique_key('nodequeue_queue', 'name', array('name'));
// Auto-generate machine names for existing queues and subqueues. Existing
// queues will be given the first 128 characters of the title, with all
// spaces replaced with underline characters, made lowercase and trimmed
// of excess whitespace. Nodequeues with empty titles will receive a name
// like 'queue_$qid'.
$result = db_query("SELECT qid, title FROM {nodequeue_queue}");
foreach ($result as $queue) {
if (!empty($queue->title)) {
// Basic formatting.
$new_name = strtolower(trim(substr($queue->title, 0, 128)));
// Regex to strip out all unwanted characters.
$new_name = preg_replace('/[^a-z0-9_]+/', '_', $new_name);
// Check if this queue name already exists.
if (nodequeue_machine_name_exists($new_name)) {
$tmp_name = $new_name;
$i = 0;
do {
// Append an incrementing numeric suffix until we find a unique name.
$unique_suffix = '_' . $i;
$new_name = truncate_utf8($tmp_name, 128 - drupal_strlen($unique_suffix, TRUE)) . $unique_suffix;
$i++;
} while (nodequeue_machine_name_exists($new_name));
}
}
else {
// Default to a name like 'queue_$qid' for queues that don't have a title.
$new_name = 'queue_' . $queue->qid;
}
db_update('nodequeue_queue')
->fields(array('name' => $new_name))
->condition('qid', $queue->qid)
->execute();
}
}
}

View File

@@ -0,0 +1,425 @@
/**
* Nodequeue object
*
* Settings:
*
* container
* up
* down
* top
* bottom:
* delete: input image
* order: input hidden
* add: input to add items
* path: path to add items
* tr: the base id of the tr
*/
Drupal.nodequeue = function(base, settings) {
// Set the properties for this object.
if (settings.container == null) {
settings.container = settings.row_class;
}
var max = function(array) {
return Math.max.apply(Math, array);
};
var array_rand = function(array) {
var i = array.length;
if (i == 0) return false;
while (--i) {
var j = Math.floor(Math.random() * ( i + 1 ));
var tempi = array[i];
var tempj = array[j];
array[i] = tempj;
array[j] = tempi;
}
}
var maxPosition = max($(settings.order).val().split(','));
this.settings = settings;
this.base = '#' + base;
// helper function to swap items in an array
var swap = function(array, a, b) {
var temp = array[a];
array[a] = array[b];
array[b] = temp;
}
var saveOrder = function(order) {
var new_order = '';
for (i in order) {
if (new_order) {
new_order += ',';
}
new_order += order[i];
}
$(settings.order).val(new_order);
$(settings.hidden).show();
}
var changeOrder = function(item, how) {
var order = $(settings.order).val().split(',');
if (how != 'add' && how != 'insert') {
var tr = $(item).parents('tr').get(0);
var id = $(tr).attr('id').replace(settings.tr, '');
var index = -1;
for (var i in order) {
if (order[i] == id) {
index = parseInt(i);
break;
}
}
}
switch (how) {
case 'add':
order.push(item);
break;
case 'insert':
order.unshift(item);
break;
case 'delete':
order.splice(index, 1);
break;
case 'top':
var temp = order[index];
order.splice(index, 1);
order.unshift(temp);
break;
case 'up':
swap(order, index, index - 1);
break;
case 'down':
swap(order, index, index + 1);
break;
case 'bottom':
var temp = order[index];
order.splice(index, 1);
order.push(temp);
break;
}
saveOrder(order);
}
var makeOrder = function(order) {
// Go through the new order and move each item to the bottom.
// Then everything will be where it was meant to be.
var last = $(settings.row_class + ':last');
for (var i in order) {
var item = $('#' + settings.tr + order[i]);
last.after(item);
changed($(item));
last = item;
}
restripeTable('#' + base);
}
this.changeOrder = changeOrder;
var restripeTable = function(table) {
// :even and :odd are reversed because jquery counts from 0 and
// we count from 1, so we're out of sync.
$('tbody tr:not(:hidden)', $(table))
.removeClass('even')
.removeClass('odd')
.filter(':even')
.addClass('odd')
.end()
.filter(':odd')
.addClass('even');
}
var changed = function(item) {
if (!item.is('.changed')) {
item.addClass('changed').css('color', 'red');
item.children('td:first').prepend(' <b>*</b> ');
$('p.nodequeue-warning').css('color', 'red');
}
}
this.restripeTable = restripeTable;
// Set as a function so we can be both a closure and called later
// when more items get added.
var bindButtons = function() {
if (settings.remove) {
$(settings.remove + ':not(.nodequeue-processed)')
.addClass('nodequeue-processed')
.click(function() { return false; })
.click(function(e) {
var item = $(this).parents(settings.container);
changeOrder(this, 'delete');
item.remove();
restripeTable('#' + base);
return false;
});
}
if (settings.clear_list) {
$(settings.clear_list + ':not(.nodequeue-processed)')
.addClass('nodequeue-processed')
.click(function() { return false; })
.click(function(e) {
$(settings.row_class).each(function() { $(this).remove() });
saveOrder([]);
});
}
if (settings.shuffle) {
$(settings.shuffle + ':not(.nodequeue-processed)')
.addClass('nodequeue-processed')
.click(function() { return false; })
.click(function(e) {
// randomize the order
var order = $(settings.order).val().split(',');
array_rand(order);
saveOrder(order);
makeOrder(order);
});
}
if (settings.reverse) {
$(settings.reverse + ':not(.nodequeue-processed)')
.addClass('nodequeue-processed')
.click(function() { return false; })
.click(function(e) {
// reverse the order
var order = $(settings.order).val().split(',');
order.reverse();
saveOrder(order);
makeOrder(order);
});
}
if (settings.up) {
$(settings.up + ':not(.nodequeue-processed)')
.addClass('nodequeue-processed')
.click(function() { return false; })
.click(function(e) {
var item = $(this).parents(settings.container);
var prev = $(item).prev();
if (prev.html() != null && item != prev) {
// move item
prev.before(item);
restripeTable('#' + base);
changed(item);
changeOrder(this, 'up');
}
return false;
});
}
if (settings.top) {
$(settings.top + ':not(.nodequeue-processed)')
.addClass('nodequeue-processed')
.click(function() { return false; })
.click(function(e) {
var item = $(this).parents(settings.container);
var first = $(item).siblings(':first');
first.before(item);
restripeTable('#' + base);
changeOrder(this, 'top');
changed(item);
return false;
});
}
if (settings.down) {
$(settings.down + ':not(.nodequeue-processed)')
.addClass('nodequeue-processed')
.click(function() { return false; })
.click(function(e) {
var item = $(this).parents(settings.container);
var next = $(item).next();
if (next.html() != null && item != next) {
// move item
next.after(item);
restripeTable('#' + base);
changeOrder(this, 'down');
changed(item);
}
return false;
});
}
if (settings.bottom) {
$(settings.bottom + ':not(.nodequeue-processed)')
.addClass('nodequeue-processed')
.click(function() { return false; })
.click(function(e) {
var item = $(this).parents(settings.container);
var last = $(item).siblings(':last');
// move item
last.after(item);
restripeTable('#' + base);
changeOrder(this, 'bottom');
changed(item);
return false;
});
}
if (settings.add) {
$(settings.add + ':not(.nodequeue-processed)')
.addClass('nodequeue-processed')
.click(function() { return false; })
.click(function(e) {
var input = this;
$(input).attr('disabled', true);
$(input).parent().addClass('throbbing');
var data = { position: maxPosition + 1 };
for (i in settings.post) {
data[$(settings.post[i]).attr('name')] = $(settings.post[i]).val();
}
$.ajax({
type: 'POST',
data: data,
url: settings.path,
global: true,
success: function (data) {
// Parse response
$(input).parent().removeClass('throbbing');
$(input).attr('disabled', false);
data = Drupal.parseJson(data);
if (data.status) {
// add new data
var new_content = $(data.data);
Drupal.freezeHeight();
// Hide the new content before adding to page.
maxPosition++;
// Add the form and re-attach behavior.
if (settings.add_location != 'top') {
$('#' + base + ' tbody').append(new_content);
changeOrder(maxPosition, 'add');
}
else {
$('#' + base + ' tbody').prepend(new_content);
changeOrder(maxPosition, 'insert');
}
changed(new_content);
bindButtons();
Drupal.unfreezeHeight();
// Add the extra data, if necessary
if (data.extra && settings.extra) {
var val = $(settings.extra).val();
if (val) {
val += ',';
}
val += data.extra;
$(settings.extra).val(val);
}
if (settings.clear) {
for (i in settings.clear) {
$(settings.clear[i]).val('');
}
}
return;
}
else {
// report the error
alert(data.error, 'Error');
}
},
error: function(data) {
alert(Drupal.t('An error occurred'));
$(input).parent().removeClass('throbbing');
$(input).attr('disabled', false);
}
});
return false;
});
}
}
// Focus if we're told to.
if (settings.focus) {
$(settings.focus).get(0).focus();
}
this.bindButtons = bindButtons();
}
Drupal.nodequeue.autoAttach = function() {
if (Drupal.settings && Drupal.settings.nodequeue) {
for (var base in Drupal.settings.nodequeue) {
if (!$('#'+ base + '.nodequeue-processed').size()) {
var settings = Drupal.settings.nodequeue[base];
var list = new Drupal.nodequeue(base, settings);
$('#'+ base).addClass('nodequeue-processed');
}
}
}
$('a.nodequeue-ajax-toggle').click(function() {
var a = this;
href = $(this).attr('href');
$(a).addClass('throbbing');
$.ajax({
type: 'POST',
data: { js: 1 },
url: href,
global: true,
dataType: 'json',
success: function (data) {
// Parse response
$(a).removeClass('throbbing');
// Change text on success
if (data.status) {
// Change label back
$(a).attr('href', data.href);
$(a).html(data.label);
if (data.sqid) {
$('#nodequeue-count-' + data.sqid).html(data.count);
}
if (data.href.search('remove-node') > -1) {
$(a).removeClass('toggle-add');
$(a).addClass('toggle-remove');
}
else {
$(a).removeClass('toggle-remove');
$(a).addClass('toggle-add');
}
return;
}
},
error: function(data) {
$(a).removeClass('throbbing');
}
});
return false;
});
}
if (Drupal.jsEnabled) {
$(document).ready(Drupal.nodequeue.autoAttach);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,177 @@
(function ($) {
Drupal.behaviors.nodequeueDrag = {
attach: function(context) {
$('.nodequeue-dragdrop').each(function() {
var table_id = $(this).attr('id');
var tableDrag = Drupal.tableDrag[table_id];
tableDrag.onDrop = function() {
$('#' + table_id + ' td.position').each(function(i) {
$(this).html(i + 1);
});
nodequeueUpdateNodePositions(table_id);
}
});
}
};
Drupal.behaviors.nodequeueReverse = {
attach: function(context) {
$('#edit-actions-reverse').click(function() {
var $table = $(this).parent().parent().find('.nodequeue-dragdrop:first');
var table_id = $table.attr('id');
// Reverse table rows.
$table.find('tr.draggable').each(function(i) {
$table.find('tbody').prepend(this);
});
nodequeueUpdateNodePositions(table_id);
nodequeueInsertChangedWarning(table_id);
nodequeueRestripeTable(table_id);
return false;
});
}
};
Drupal.behaviors.nodequeueShuffle = {
attach: function(context) {
$('#edit-actions-shuffle').click(function() {
var $table = $(this).parent().parent().find('.nodequeue-dragdrop:first');
var table_id = $table.attr('id');
// Randomize table rows.
var rows = $('#' + table_id + ' tbody tr:not(:hidden)').get();
rows.sort(function(){return (Math.round(Math.random())-0.5);});
$.each(rows, function(i, row) {
$('#' + table_id + ' tbody').prepend(this);
});
nodequeueUpdateNodePositions(table_id);
nodequeueInsertChangedWarning(table_id);
nodequeueRestripeTable(table_id);
return false;
});
}
};
Drupal.behaviors.nodequeueClear = {
attach: function(context) {
$('#edit-actions-clear').click(function() {
var $table = $(this).parent().parent().find('.nodequeue-dragdrop:first');
var table_id = $table.attr('id');
// Mark nodes for removal.
$('#' + table_id + ' .node-position').each(function(i) {
$(this).val('r');
});
// Remove table rows.
rows = $('#' + table_id + ' tbody tr:not(:hidden)').hide();
nodequeuePrependEmptyMessage(table_id);
nodequeueInsertChangedWarning(table_id);
return false;
});
}
};
Drupal.behaviors.nodequeueRemoveNode = {
attach: function(context) {
$('a.nodequeue-remove').css('display', 'block');
$('a.nodequeue-remove').click(function() {
a = $(this).attr('id');
a = '#' + a.replace('nodequeue-remove-', 'edit-') + '-position';
$(a).val('r');
// Hide the current row.
$(this).parent().parent().fadeOut('fast', function() {
var $table = $(this).parent().parent();
var table_id = $table.attr('id');
if ($('#' + table_id + ' tbody tr:not(:hidden)').size() == 0) {
nodequeuePrependEmptyMessage(table_id);
}
else {
nodequeueRestripeTable(table_id)
nodequeueInsertChangedWarning(table_id);
}
});
return false;
});
}
}
Drupal.behaviors.nodequeueClearTitle = {
attach: function(context) {
$('.subqueue-add-nid').focus(function() {
if (this.value == this.defaultValue) {
this.value = '';
$(this).css('color', '#000');
}
}).blur(function() {
if (!this.value.length) {
this.value = this.defaultValue;
$(this).css('color', '#999');
}
});
}
}
/**
* Updates node positions after nodequeue has been rearranged.
* It cares about the reverse order and populates nodes the other way round.
*/
function nodequeueUpdateNodePositions(table_id) {
// Check if reverse option is set.
var reverse = Drupal.settings.nodequeue.reverse[table_id.replace(/-/g, '_')];
var size = reverse ? $('#' + table_id + ' .node-position').size() : 1;
$('#' + table_id + ' tr').filter(":visible").find('.node-position').each(function(i) {
$(this).val(size);
reverse ? size-- : size++;
});
}
/**
* Restripe the nodequeue table after removing an element or changing the
* order of the elements.
*/
function nodequeueRestripeTable(table_id) {
$('#' + table_id + ' tbody tr:not(:hidden)')
.filter(':odd')
.removeClass('odd').addClass('even')
.end()
.filter(':even')
.removeClass('even').addClass('odd')
.end();
$('#' + table_id + ' tr:visible td.position').each(function(i) {
$(this).html(i + 1);
});
}
/**
* Add a row to the nodequeue table explaining that the queue is empty.
*/
function nodequeuePrependEmptyMessage(table_id) {
$('#' + table_id + ' tbody').prepend('<tr class="odd"><td colspan="6">'+Drupal.t('No nodes in this queue.')+'</td></tr>');
}
/**
* Display a warning reminding the user to save the nodequeue.
*/
function nodequeueInsertChangedWarning(table_id) {
if (Drupal.tableDrag[table_id].changed == false) {
$(Drupal.theme('tableDragChangedWarning')).insertAfter('#' + table_id).hide().fadeIn('slow');
Drupal.tableDrag[table_id].changed = true;
}
}
})(jQuery);

View File

@@ -0,0 +1,107 @@
<?php
/**
* @file
* Nodequeue generate drush integration.
*/
/**
* Implementation of hook_drush_command().
*
* @See drush_parse_command() for a list of recognized keys.
*
* @return
* An associative array describing your command(s).
*/
function nodequeue_generate_drush_command() {
$items = array();
$items['nodequeue-generate'] = array(
'description' => "Re-populates specified nodequeues with random nodes.",
'drupal dependencies' => array('nodequeue_generate'),
'arguments' => array(
'queue' => 'Machine name of queue to be re-populated.',
),
'aliases' => array('nqg'),
);
$items['nodequeue-generate-all'] = array(
'description' => "Re-populates nodequeues with random nodes.",
'drupal dependencies' => array('nodequeue_generate'),
'aliases' => array('nqga'),
);
$items['nodequeue-generate-rehash'] = array(
'description' => "Rehashes smartqueue subqueues for taxonomy smartqueue.",
'drupal dependencies' => array('nodequeue_generate', 'smartqueue'),
'aliases' => array('nqgr'),
);
return $items;
}
/**
* Implementation of hook_drush_help().
*/
function nodequeue_generate_drush_help($section) {
switch ($section) {
case 'drush:nodequeue-generate':
return dt("Re-populates specified nodequeues with random nodes.");
case 'drush:nodequeue-generate-all':
return dt("Re-populates all nodequeues with random nodes.");
case 'drush:nodequeue-generate-rehash':
return dt("Rehashes smartqueue subqueues for taxonomy smartqueue.");
}
}
/**
* Re-populates specified nodequeues with random nodes.
*/
function drush_nodequeue_generate() {
$args = func_get_args();
// At least one queue must be specified.
if (count($args) < 1) {
drush_set_error('error', dt('At least one queue must be specified.'));
}
// Get qids from machine names.
$qids = array();
foreach ($args as $queue) {
$qid = db_select('nodequeue_queue', 'nq')
->fields('nq', array('qid'))
->condition('name', $queue)
->execute()
->fetchField();
if ($qid) {
$qids[] = $qid;
}
else {
drush_set_error('error', dt('Queue @queue was not found.', array('@queue' => $queue)));
}
}
nodequeue_generate_rehash();
nodequeue_generate_repopulate_queues($qids);
}
/**
* Re-populates all nodequeues with random nodes.
*/
function drush_nodequeue_generate_all() {
$qids = db_select('nodequeue_queue', 'nq')
->fields('nq', array('qid'))
->execute()
->fetchAll(PDO::FETCH_COLUMN, 'qid');
nodequeue_generate_rehash();
nodequeue_generate_repopulate_queues($qids);
}
/**
* Rehashes smartqueue subqueues for taxonomy smartqueue.
*/
function drush_nodequeue_generate_rehash() {
nodequeue_generate_rehash();
}

View File

@@ -0,0 +1,14 @@
name = Nodequeue generate
description = Bulk assign nodes into queues for quickly populating a site.
package = Development
dependencies[] = nodequeue
core = 7.x
files[] = nodequeue_generate.module
; Information added by drupal.org packaging script on 2011-09-20
version = "7.x-2.0-beta1"
core = "7.x"
project = "nodequeue"
datestamp = "1316558104"

View File

@@ -0,0 +1,224 @@
<?php
/**
* Implements hook_menu().
*/
function nodequeue_generate_menu() {
$items['admin/structure/nodequeue/generate_nodequeue'] = array(
'title' => 'Generate queue assignments',
'description' => 'Bulk add nodes into queues',
'page callback' => 'drupal_get_form',
'page arguments' => array('nodequeue_generate_form'),
'access callback' => 'user_access',
'access arguments' => array('manipulate all queues'),
'type' => MENU_LOCAL_TASK,
);
return $items;
}
/**
* Menu callback; Returns the nodequeue generate form.
*/
function nodequeue_generate_form() {
$form['help'] = array(
'#markup' => '<p>' . t('Select which queues shall be <strong>emptied</strong> and re-populated with new nodes.') . '</p>'
);
$queues = nodequeue_load_queues(nodequeue_get_all_qids(25));
// Tableselect header.
$header = array(
'name' => 'Queue name',
'max_nodes' => 'Max nodes',
'subqueues' => 'Subqueues',
);
// Tableselect data.
$data = array();
foreach ($queues as $queue) {
$data[$queue->qid]['name'] = check_plain($queue->title);
$data[$queue->qid]['max_nodes'] = $queue->size == 0 ? t('Infinite') : $queue->size;
$data[$queue->qid]['subqueues'] = $queue->subqueues;
}
// Table select element.
$form['nodequeues'] = array(
'#type' => 'tableselect',
'#header' => $header,
'#options' => $data,
'#empty' => t('There are no queues.'),
);
$form['nodequeue_generate_nodes_limit'] = array(
'#type' => 'textfield',
'#title' => t('Nodes limit'),
'#description' => t('How many nodes to insert in a queue. This value is only taken into consideration for infinite queues.'),
'#size' => 3,
'#default_value' => 10,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Generate'),
);
return $form;
}
/**
* Validate nodequeue generate form submission.
*
* Make sure that at least one queue was selected.
*/
function nodequeue_generate_form_validate($form, &$form_state) {
$qids = array_keys(array_filter($form_state['values']['nodequeues']));
if (count($qids) < 1) {
form_set_error('nodequeues', t('You must select a Queue.'));
}
}
function nodequeue_generate_form_submit($form, &$form_state) {
// Get qids of all nodequeues that need to be re-populated and repopulate them.
$qids = array_keys(array_filter($form_state['values']['nodequeues']));
$nodes_limit = $form_state['values']['nodequeue_generate_nodes_limit'];
nodequeue_generate_rehash();
nodequeue_generate_repopulate_queues($qids, $nodes_limit);
}
/**
* Re-populates nodequeues with nodes.
*
* @param $qids Array of queues, that need to be repopulated.
*/
function nodequeue_generate_repopulate_queues($qids, $nodes_limit = 10) {
// Remove existing nodes from queues.
db_query("DELETE FROM {nodequeue_nodes} WHERE qid IN (:qids)", array(':qids' => $qids));
// Load all queues and their subqueues.
$queues = nodequeue_load_queues($qids);
$subqueues = nodequeue_load_subqueues_by_queue($qids);
// Re-populate subqueues
foreach ($qids as $qid) {
$queue = nodequeue_load($qid);
// Skip nodequeues that do not belong to any node types.
if (!empty($queue->types)) {
$limit = $queue->size ? $queue->size : $nodes_limit;
$callback = $queue->owner . '_nodequeue_generate';
if (function_exists($callback)) {
$callback($queue, $limit);
}
}
}
drupal_set_message(format_plural(count($qids), '1 queue populated', '@count queues populated.'));
}
/**
* Rebuild all smartqueue_taxonomy queues. Useful after a data migration has wiped your terms.
* When more smartqueue modules arrive, revisit this function.
*
* @param vids
* An array of vocabulary ids.
*/
function nodequeue_generate_rehash() {
// Delete existing smartqueue taxonomy subqueues
db_query("DELETE ns FROM {nodequeue_subqueue} ns INNER JOIN {nodequeue_queue} nq ON ns.qid = nq.qid WHERE nq.owner = 'smartqueue_taxonomy'");
// Get all queues, owned by Smartqueue taxonomy.
$qids = db_select('nodequeue_queue', 'nq')
->fields('nq', array('qid'))
->condition('owner', 'smartqueue_taxonomy')
->execute()
->fetchAll();
foreach ($qids as $qid) {
$queue = nodequeue_load($qid->qid);
$fields = explode('-', $queue->reference);
$tids = array();
foreach ($fields as $field) {
// Get all possible tids from this field.
$query = db_select('field_data_' . $field, 'f');
$query
->condition('f.entity_type', 'node')
->condition('f.bundle', $queue->types, 'IN')
->condition('f.deleted', FALSE)
->addField('f', $field . '_tid', 'tid');
$query = $query->distinct();
$query = $query->execute();
$tids += $query->fetchAll();
}
// Rehash for each tid.
$nids = array();
foreach ($tids as $tid) {
foreach ($fields as $field) {
$query = db_select('field_data_' . $field, 'f')
->condition('f.entity_type', 'node')
->condition('f.bundle', $queue->types, 'IN')
->condition('f.deleted', FALSE)
->condition('f.' . $field . '_tid', $tid->tid)
->fields('f', array('entity_id'))
->range(0, 1)
->execute();
$nids += $query->fetchAll();
}
foreach ($nids as $nid) {
$node = node_load($nid->entity_id);
nodequeue_api_subqueues($queue, $node);
}
}
}
}
/**
* Implements hook_nodequeue_generate() for owner 'nodequeue'.
*/
function nodequeue_nodequeue_generate($queue, $limit) {
$subqueues = nodequeue_load_subqueues_by_queue($queue->qid);
foreach ($subqueues as $subqueue) {
$nodes = db_select('node', 'n')
->condition('n.status', NODE_PUBLISHED)
->condition('n.type', $queue->types, 'IN')
->orderRandom()
->fields('n', array('nid'))
->range(0, $limit)
->execute()
->fetchAll();
foreach ($nodes as $node) {
nodequeue_subqueue_add($queue, $subqueue, $node->nid);
}
}
}
/**
* Implements hook_nodequeue_generate() for owner 'smartqueue_taxonomy'.
*/
function smartqueue_taxonomy_nodequeue_generate($queue, $limit) {
$subqueues = nodequeue_load_subqueues_by_queue($queue->qid);
foreach ($subqueues as $subqueue) {
$nodes = db_select('taxonomy_index', 'tn');
$nodes->join('node', 'n', 'n.nid=tn.nid');
$nodes->fields('n', array('nid'));
$nodes->condition('n.status', NODE_PUBLISHED);
$nodes->condition('n.type', $queue->types, 'IN');
$nodes->condition('tn.tid', $subqueue->reference);
$nodes->orderRandom();
$nodes->range(0, $limit);
$nodes = $nodes->execute();
$nodes = $nodes->fetchAll();
foreach ($nodes as $node) {
nodequeue_subqueue_add($queue, $subqueue, $node->nid);
}
}
}

View File

@@ -0,0 +1,13 @@
name = Smartqueue taxonomy
description = Creates a node queue for each taxonomy vocabulary
package = Nodequeue
core = 7.x
dependencies[] = nodequeue
dependencies[] = taxonomy
; Information added by drupal.org packaging script on 2011-09-20
version = "7.x-2.0-beta1"
core = "7.x"
project = "nodequeue"
datestamp = "1316558104"

View File

@@ -0,0 +1,92 @@
<?php
/**
* @file
* Install, update and uninstall functions for the smartqueue module.
*/
/**
* Implements hook_schema().
*/
function smartqueue_schema() {
$schema['smartqueue'] = array(
'description' => 'Table for smartqueues, storing global information for each queue.',
'fields' => array(
'qid' => array(
'description' => 'The primary identifier for a queue.',
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE
),
'use_parents' => array(
'description' => "Whether a queue is to use the terms' parents when displaying the queue selection.",
'type' => 'int',
'size' => 'tiny',
'default' => 0,
),
),
'primary key' => array('qid'),
);
return $schema;
}
/**
* Implements hook_update_N().
*
* Adds the smartqueue table.
*/
function smartqueue_update_6003() {
// Don't use hook_schema for database updates per http://drupal.org/node/150220.
// It's possible that users who installed the 2.7 or 2.8 versions of
// smartqueue will already have this table.
if (!db_table_exists('smartqueue')) {
$schema = array(
'description' => 'Table for smartqueues, storing global information for each queue.',
'fields' => array(
'qid' => array(
'description' => 'The primary identifier for a queue.',
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE
),
'use_parents' => array(
'description' => "Whether a queue is to use the terms' parents when displaying the queue selection.",
'type' => 'int',
'size' => 'tiny',
'default' => 0,
),
),
'primary key' => array('qid'),
);
db_create_table('smartqueue', $schema);
}
$result = db_query('SELECT q.qid FROM {nodequeue_queue} q LEFT JOIN {smartqueue} s ON q.qid = s.qid WHERE s.qid IS NULL');
foreach ($result as $queue) {
db_insert('smartqueue')
->fields(array('qid' => $queue->qid))
->execute();
}
}
/**
* Change reference field to rely on field names intead of field-ids.
*/
function smartqueue_update_7001() {
$results = db_select('nodequeue_queue', 'nq')
->fields('nq', array('qid','reference'))
->condition('owner', 'smartqueue_taxonomy', '=')
->execute();
foreach ($results as $result) {
$field_names = array();
$field_ids = explode('-', $result->reference);
foreach ($field_ids as $field_id) {
$field = field_info_field_by_id($field_id);
$field_names[] = $field['field_name'];
}
db_update('nodequeue_queue')
->fields(array('reference' => implode('-', $field_names)))
->condition('qid', $result->qid)
->execute();
}
}

View File

@@ -0,0 +1,295 @@
<?php
/**
* Implements hook_nodequeue_info().
*/
function smartqueue_nodequeue_info() {
return array('smartqueue_taxonomy' => array(
'title' => t('Taxonomy queue'),
'description' => t('Each particular grouping of taxonomy terms from the selected vocabularies have their own unique subqueue. You can place nodes into any of these subqueues based on which terms that node has been tagged with. Using this with large or too many taxonomies may degrade performance.'),
));
}
/**
* Implements hook_nodequeue_form().
*/
function smartqueue_taxonomy_nodequeue_form($queue, &$form) {
// Load data about taxonomy_term_reference fields.
$options = array();
$fields = field_info_fields();
foreach ($fields as $field_name => $field) {
if ($field['type'] == 'taxonomy_term_reference') {
$options[$field_name] = t('Field %field-name, selecting terms from vocabulary %vocabulary.', array('%field-name' => $field_name, '%vocabulary' => $field['settings']['allowed_values'][0]['vocabulary']));
}
}
$form['placeholder']['taxonomy_fields'] = array(
'#type' => 'checkboxes',
'#title' => t('Taxonomy fields'),
'#description' => t('Select which taxonomy term reference fields to use; each unique combination of terms from all of these fields will have a subqueue.'),
'#options' => $options,
);
$form['placeholder']['use_parents'] = array(
'#type' => 'checkbox',
'#title' => t('Assume parent term for hierarchical vocabs'),
'#description' => t("Instead of using the node's terms for nodequeue assignment use the top-most parents of a term. This has no effect if there in non-hierarchical vocabularies."),
'#default_value' => isset($queue->use_parents) ? $queue->use_parents : 0,
);
$form['subqueue_title'] = array(
'#type' => 'textfield',
'#title' => t('Subqueue title'),
'#default_value' => $queue->subqueue_title,
'#size' => 50,
'#maxlength' => 64,
'#description' => t('What to display for the subqueue title; use %subqueue to embed the actual subqueue title. This is used to distinguish multiple nodequeues with subqueues from each other, as internal subqueue title is filled automatically.'),
);
// Fields can be selected just when creating new taxonomy smartqueue.
// Disable it after that.
if (!empty($queue->qid)) {
$form['placeholder']['taxonomy_fields']['#disabled'] = TRUE;
$form['placeholder']['taxonomy_fields']['#default_value'] = explode('-', $queue->reference);
}
}
/**
* Implements hook_nodequeue_form_validate().
*/
function smartqueue_taxonomy_nodequeue_form_validate($queue, &$form_state, &$form) {
if (!isset($queue->qid)) {
$field_names = array_keys(array_filter($form_state['values']['taxonomy_fields']));
if (empty($field_names)) {
form_error($form['placeholder']['taxonomy_fields'], t('You must select at least one field.'));
}
// Convert this to our reference.
form_set_value($form['reference'], implode('-', $field_names), $form_state);
}
}
/**
* Implements hook_nodequeue_form_submit_finish().
*/
function smartqueue_taxonomy_nodequeue_form_submit_finish($queue, $form_state) {
// Check if queue already exists.
$qid = db_select('smartqueue', 's')
->fields('s', array('qid'))
->condition('qid', $queue->qid)
->execute()
->fetchField();
if ($qid) {
// Update existing queue.
db_update('smartqueue')
->fields(array(
'use_parents' => $form_state['values']['use_parents'],
))
->condition('qid', $queue->qid)
->execute();
}
else {
// Insert new queue.
db_insert('smartqueue')
->fields(array(
'qid' => $queue->qid,
'use_parents' => $form_state['values']['use_parents'],
))
->execute();
}
}
/**
* Implements hook_nodequeue_subqueues().
*
* Returns list of references for subqueues that can host a given node.
*/
function smartqueue_taxonomy_nodequeue_subqueues(&$queue, $node) {
$field_names = array();
// Check if at least one supported field exists in node and load
// selected tids.
foreach (explode('-', $queue->reference) as $field_name) {
// Save tids.
if ($field_values = field_get_items('node', $node, $field_name)) {
$field_names[$field_name] = array();
foreach ($field_values as $field_value) {
$field_names[$field_name][] = $field_value['tid'];
}
}
}
if (!empty($field_names) && $queue->use_parents) {
// Replace taxonomy IDs with their parents'.
foreach ($field_names as $field_name => &$tids) {
$tids = smartqueue_taxonomy_get_parents($tids);
}
}
// Forbid NO terms being set, but allow
// various non-terms to be set.
$empty = TRUE;
foreach ($field_names as $field_name => $tids) {
if (!empty($tids)) {
$empty = FALSE;
}
if (!count($field_names[$field_name])) {
$field_names[$field_name][] = 0;
}
}
if ($empty) {
return;
}
// Build reference strings for all subqueues.
$references = smartqueue_build_string(array_filter($field_names));
// We're returning an array of references for efficiency, but we also have
// to check to see if the references we've generated exist. If they don't,
// we have to create them.
$exists = array();
$subqueues = nodequeue_load_subqueues_by_reference(array($queue->qid => $references));
foreach ($subqueues as $subqueue) {
$exists[$subqueue->reference] = TRUE;
}
// Create subqueues if needed.
foreach ($references as $reference) {
if (empty($exists[$reference])) {
nodequeue_add_subqueue($queue, smartqueue_taxonomy_nodequeue_subqueue_title($queue, $reference), $reference);
}
}
return $references;
}
/**
* Implements hook_nodequeue_alter().
*/
function smartqueue_nodequeue_alter(&$data, $type) {
switch ($type) {
case 'load_queues':
$qids = array_keys($data);
$result = db_query("SELECT qid, use_parents FROM {smartqueue} WHERE qid IN (:qids)", array(':qids' => $qids));
foreach ($result as $queue) {
$data[$queue->qid]->use_parents = $queue->use_parents;
}
break;
}
}
/**
* Build an array of strings that represents all of the possible term
* combinations.
*/
function smartqueue_build_string($arrays) {
$array = array_shift($arrays);
$term = '';
if (empty($arrays)) {
return $array;
}
$substrings = smartqueue_build_string($arrays);
$strings = array();
foreach ($array as $term) {
foreach ($substrings as $string) {
$strings[] = "$term-$string";
}
}
return $strings;
}
/**
* Form title for a new taxonomy subqueue.
*
* @param $queue Queue object.
* @param $reference Subqueue reference string (tids imploded with '-').
*/
function smartqueue_taxonomy_nodequeue_subqueue_title($queue, $reference) {
$tids = explode('-', $reference);
foreach ($tids as $tid) {
// $tid can be 0, specifically meaning this term is unset.
if ($tid) {
$titles[$tid] = taxonomy_term_load($tid)->name;
}
}
// Create name using names of all term names. This could be
// done better, but is OK for now.
return implode('-', $titles);
}
/**
* Implements hook_taxonomy_term_update().
*
* Updates subqueue title if term name changes.
*/
function smartqueue_taxonomy_term_update($term) {
// Find subqueues that contain this term.
$result = db_query(
"SELECT nq.reference AS reference, sq.reference AS sqref, sq.sqid
FROM {nodequeue_queue} nq
INNER JOIN {nodequeue_subqueue} sq ON nq.qid = sq.qid
WHERE nq.owner = 'smartqueue_taxonomy'
AND (sq.reference = ?
OR sq.reference LIKE ?
OR sq.reference LIKE ?
OR sq.reference LIKE ?)",
array($term->tid, '%-' . $term->tid, $term->tid . '-%', '%-' . $term->tid . '-%')
)->fetchAll();
foreach ($result as $row) {
// Note that $row already contains the needed $row->reference.
$title = smartqueue_taxonomy_nodequeue_subqueue_title($row, $row->sqref);
nodequeue_subqueue_update_title($row->sqid, $title);
}
}
/**
* Implements hook_taxonomy_term_delete().
*
* Deletes subqueue if term is removed
*/
function smartqueue_taxonomy_term_delete($term) {
// Find subqueues that contain this term.
$result = db_query(
"SELECT sq.sqid FROM {nodequeue_subqueue} sq
INNER JOIN {nodequeue_queue} nq ON sq.qid = nq.qid
WHERE nq.owner = 'smartqueue_taxonomy'
AND (sq.reference = ?
OR sq.reference LIKE ?
OR sq.reference LIKE ?
OR sq.reference LIKE ?)",
array($term->tid, '%-' . $term->tid, $term->tid . '-%', '%-' . $term->tid . '-%')
)->fetchAll();
foreach ($result as $row) {
nodequeue_remove_subqueue($row->sqid);
}
}
/**
* Get the top-level parents of the given taxonomy terms.
*
* @param $tids, an array of taxonomy IDs
*
* @return an array of taxonomy IDs
*/
function smartqueue_taxonomy_get_parents($tids) {
if ($tids) {
$top_level_tids = array();
foreach ($tids as $tid) {
$parents = taxonomy_get_parents_all($tid);
$parent = array_pop($parents);
$top_level_tids[] = $parent->tid;
}
return array_unique($top_level_tids);
}
else {
return array();
}
}