New module 'Pathauto'
This commit is contained in:
parent
3563734b2c
commit
0197478295
17 changed files with 5146 additions and 0 deletions
156
modules/pathauto/API.txt
Normal file
156
modules/pathauto/API.txt
Normal file
|
@ -0,0 +1,156 @@
|
|||
This document explains how to provide "Pathauto integration" in a
|
||||
module. You need this if you would like to provide additional tokens
|
||||
or if your module has paths and you wish to have them automatically
|
||||
aliased. The simplest integration is just to provide tokens so we
|
||||
cover that first. More advanced integration requires an
|
||||
implementation of hook_pathauto to provide a settings form.
|
||||
|
||||
It may be helpful to review some examples of integration from the
|
||||
pathauto_node.inc, pathauto_taxonomy.inc, and pathauto_user.inc files.
|
||||
|
||||
|
||||
==================
|
||||
1 - Providing additional tokens
|
||||
==================
|
||||
|
||||
If all you want is to enable tokens for your module you will simply
|
||||
need to implement two functions:
|
||||
|
||||
hook_token_values
|
||||
hook_token_list
|
||||
|
||||
See the token.module and it's API.txt for more information about this
|
||||
process.
|
||||
|
||||
If the token is intended to generate a path expected to contain slashes,
|
||||
the token name must end in 'path', 'path-raw' or 'alias'. This indicates to
|
||||
Pathauto that the slashes should not be removed from the replacement value.
|
||||
|
||||
When an object is created (whether it is a node or a user or a
|
||||
taxonomy term) the data that Pathauto hands to the token_values in the
|
||||
$object is in a specific format. This is the format that most people
|
||||
write code to handle. However, during edits and bulk updates the data
|
||||
may be in a totally different format. So, if you are writing a
|
||||
hook_token_values implementation to add special tokens, be sure to
|
||||
test creation, edit, and bulk update cases to make sure your code will
|
||||
handle it.
|
||||
|
||||
==================
|
||||
2 - Settings hook - To create aliases for your module
|
||||
==================
|
||||
You must implement hook_pathauto($op), where $op is always (at this
|
||||
time) 'settings'. Return an object (NOT an array) containing the
|
||||
following members, which will be used by pathauto to build a group
|
||||
of settings for your module and define the variables for saving your
|
||||
settings:
|
||||
|
||||
module - The name of your module (e.g., 'node')
|
||||
groupheader - The translated label for the settings group (e.g.,
|
||||
t('Node path settings')
|
||||
patterndescr - The translated label for the default pattern (e.g.,
|
||||
t('Default path pattern (applies to all node types with blank patterns below)')
|
||||
patterndefault - A translated default pattern (e.g., t('[cat]/[title].html'))
|
||||
placeholders - An array whose keys consist of the translated placeholders
|
||||
which will appear in patterns (e.g., t('[title]')) and values are
|
||||
the translated description of the placeholders (e.g.,
|
||||
t('The title of the node, with spaces and punctuation.')
|
||||
patternitems - For modules which need to express multiple patterns
|
||||
(for example, the node module supports a separate pattern for each
|
||||
node type), an array whose keys consist of identifiers for each
|
||||
pattern (e.g., the node type name) and values consist of the
|
||||
translated label for the pattern
|
||||
supportsfeeds - Modules which support RSS feeds should set this to the
|
||||
string that's appended to a path for its feed (usually 'feed') , so
|
||||
when administrators enable "Create feed aliases" an alias for this
|
||||
content type's feed will be generated in addition to the base alias.
|
||||
bulkname - For modules which support a bulk update operation, the
|
||||
translated label for the action (e.g., t('Bulk update node paths'))
|
||||
bulkdescr - For modules which support a bulk update operation, a
|
||||
translated, more thorough description of what the operation will do
|
||||
(e.g., t('Generate aliases for all existing nodes which do not already have aliases.'))
|
||||
|
||||
|
||||
==================
|
||||
2 - $alias = pathauto_create_alias($module, $op, $placeholders, $src, $type=NULL)
|
||||
==================
|
||||
|
||||
At the appropriate time (usually when a new item is being created for
|
||||
which a generated alias is desired), call pathauto_create_alias() to
|
||||
generate and create the alias. See the user, taxonomy, and nodeapi hook
|
||||
implementations in pathauto.module for examples.
|
||||
|
||||
$module - The name of your module (e.g., 'node')
|
||||
$op - Operation being performed on the item ('insert', 'update', or
|
||||
'bulkupdate')
|
||||
$placeholders - An array whose keys consist of the translated placeholders
|
||||
which appear in patterns and values are the "clean" values to be
|
||||
substituted into the pattern. Call pathauto_cleanstring() on any
|
||||
values which you do not know to be purely alphanumeric, to substitute
|
||||
any non-alphanumerics with the user's designated separator. Note that
|
||||
if the pattern has multiple slash-separated components (e.g., [catpath]),
|
||||
pathauto_cleanstring() should be called for each component, not the
|
||||
complete string.
|
||||
Example: $placeholders[t('[title]')] = pathauto_cleanstring($node->title);
|
||||
$src - The "real" URI of the content to be aliased (e.g., "node/$node->nid")
|
||||
$type - For modules which provided patternitems in hook_autopath(),
|
||||
the relevant identifier for the specific item to be aliased (e.g.,
|
||||
$node->type)
|
||||
|
||||
pathauto_create_alias() returns the alias that was created.
|
||||
|
||||
|
||||
==================
|
||||
3 - Bulk update function
|
||||
==================
|
||||
|
||||
If a module supports bulk updating of aliases, it must provide a
|
||||
function of this form, to be called by pathauto when the corresponding
|
||||
checkbox is selected and the settings page submitted:
|
||||
|
||||
function <module>_pathauto_bulkupdate()
|
||||
|
||||
The function should iterate over the content items controlled by the
|
||||
module, calling pathauto_create_alias() for each one. It is
|
||||
recommended that the function report on its success (e.g., with a
|
||||
count of created aliases) via drupal_set_message().
|
||||
|
||||
|
||||
==================
|
||||
4 - Bulk delete hook_path_alias_types()
|
||||
==================
|
||||
|
||||
For modules that create new types of pages that can be aliased with pathauto, a
|
||||
hook implementation is needed to allow the user to delete them all at once.
|
||||
|
||||
function hook_path_alias_types()
|
||||
|
||||
This hook returns an array whose keys match the beginning of the source paths
|
||||
(e.g.: "node/", "user/", etc.) and whose values describe the type of page (e.g.:
|
||||
"content", "users"). Like all displayed strings, these descriptionsshould be
|
||||
localized with t(). Use % to match interior pieces of a path; "user/%/track". This
|
||||
is a database wildcard, so be careful.
|
||||
|
||||
|
||||
==================
|
||||
Modules that extend node and/or taxonomy
|
||||
==================
|
||||
|
||||
NOTE: this is basically not true any more. If you feel you need this file an issue.
|
||||
|
||||
Many contributed Drupal modules extend the core node and taxonomy
|
||||
modules. To extend pathauto patterns to support their extensions, they
|
||||
may implement the pathauto_node and pathauto_taxonomy hooks.
|
||||
|
||||
To do so, implement the function <modulename>_pathauto_node (or _taxonomy),
|
||||
accepting the arguments $op and $node (or $term). Two operations are
|
||||
supported:
|
||||
|
||||
$op = 'placeholders' - return an array keyed on placeholder strings
|
||||
(e.g., t('[eventyyyy]')) valued with descriptions (e.g. t('The year the
|
||||
event starts.')).
|
||||
$op = 'values' - return an array keyed on placeholder strings, valued
|
||||
with the "clean" actual value for the passed node or category (e.g.,
|
||||
pathauto_cleanstring(date('M', $eventstart)));
|
||||
|
||||
See contrib/pathauto_node_event.inc for an example of extending node
|
||||
patterns.
|
50
modules/pathauto/INSTALL.txt
Normal file
50
modules/pathauto/INSTALL.txt
Normal file
|
@ -0,0 +1,50 @@
|
|||
**Installation:
|
||||
|
||||
Pathauto is an extension to the path module, which must be enabled.
|
||||
|
||||
Pathauto also relies on the Token module, which must be downloaded and
|
||||
enabled separately.
|
||||
|
||||
1. Unpack the Pathauto folder and contents in the appropriate modules
|
||||
directory of your Drupal installation. This is probably
|
||||
sites/all/modules/
|
||||
2. Enable the Pathauto module in the administration tools.
|
||||
3. If you're not using Drupal's default administrative account, make
|
||||
sure "administer pathauto" is enabled through access control administration.
|
||||
4. Visit the Pathauto settings page and make appropriate configurations
|
||||
For 5.x: Administer > Site configuration > Pathauto
|
||||
For 6.x: Administer > Site building > URL alias > Automated alias settings
|
||||
|
||||
**Transliteration support:
|
||||
If you desire transliteration support in the creation of URLs (e.g. the
|
||||
replacement of À with A) then you will need to rename the file
|
||||
i18n-ascii.example.txt to i18n-ascii.txt
|
||||
|
||||
You can then freely edit the i18n-ascii.txt without worrying that your changes
|
||||
will be over-written by upgrades of Pathauto.
|
||||
|
||||
For details on how to transliterate any UTF8 character, please see the full
|
||||
i18n-ascii-fill.txt file information at http://drupal.org/node/185664
|
||||
|
||||
**Upgrading from previous versions:
|
||||
If you are upgrading from Pathauto 5.x-1.x to 5.x-2.x (or 6.x-2.x) then you
|
||||
will probably need to change your patterns.
|
||||
|
||||
For content patterns:
|
||||
[user] is now [author-name]
|
||||
[cat] is now [term]
|
||||
|
||||
There may be other changes as well. Please review the pattern examples on
|
||||
Administration > Site Configuration > Pathauto
|
||||
|
||||
If you upgraded from Pathauto 5.x-1.x directly without enabling Token
|
||||
first then you will need to
|
||||
1) download/install the Token module
|
||||
2) disable the Pathauto module
|
||||
3) re-enable the Pathauto module
|
||||
|
||||
Upgrade to 6.x:
|
||||
Note that the settings page has moved so that it is more logically grouped with
|
||||
other URL alias related items under
|
||||
Administer > Site building > URL alias > Automated alias settings
|
||||
|
339
modules/pathauto/LICENSE.txt
Normal file
339
modules/pathauto/LICENSE.txt
Normal file
|
@ -0,0 +1,339 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
94
modules/pathauto/README.txt
Normal file
94
modules/pathauto/README.txt
Normal file
|
@ -0,0 +1,94 @@
|
|||
Please read this file and also the INSTALL.txt.
|
||||
They contain answers to many common questions.
|
||||
If you are developing for this module, the API.txt may be interesting.
|
||||
If you are upgrading, check the CHANGELOG.txt for major changes.
|
||||
|
||||
**Description:
|
||||
The Pathauto module provides support functions for other modules to
|
||||
automatically generate aliases based on appropriate criteria, with a
|
||||
central settings path for site administrators.
|
||||
|
||||
Implementations are provided for core content types: nodes, taxonomy
|
||||
terms, and users (including blogs and tracker pages).
|
||||
|
||||
Pathauto also provides a way to delete large numbers of aliases. This feature
|
||||
is available at Administer > Site building > URL aliases > Delete aliases
|
||||
|
||||
**Benefits:
|
||||
Besides making the page address more reflective of its content than
|
||||
"node/138", it's important to know that modern search engines give
|
||||
heavy weight to search terms which appear in a page's URL. By
|
||||
automatically using keywords based directly on the page content in the URL,
|
||||
relevant search engine hits for your page can be significantly
|
||||
enhanced.
|
||||
|
||||
**Installation AND Upgrades:
|
||||
See the INSTALL.txt file.
|
||||
|
||||
**Notices:
|
||||
Pathauto just adds URL aliases to nodes, users, and taxonomy terms. Because
|
||||
it's an alias, the standard Drupal URL (for example node/123 or
|
||||
taxonomy/term/1) will still function as normal. If you have external links
|
||||
to your site pointing to standard Drupal URLs, or hardcoded links in a module,
|
||||
template, node or menu which point to standard Drupal URLs it will bypass the
|
||||
alias set by Pathauto.
|
||||
|
||||
There are reasons you might not want two URLs for the same content on your
|
||||
site. If this applies to you, please note that you will need to update any
|
||||
hard coded links in your nodes or blocks.
|
||||
|
||||
If you use the "system path" (i.e. node/10) for menu items and settings like
|
||||
that, Drupal will replace it with the url_alias.
|
||||
|
||||
For external links, you might want to consider the Path Redirect or
|
||||
Global Redirect modules, which allow you to set forwarding either per item or
|
||||
across the site to your aliased URLs.
|
||||
|
||||
URLs (not) Getting Replaced With Aliases:
|
||||
Please bear in mind that only URLs passed through Drupal's l() or url()
|
||||
functions will be replaced with their aliases during page output. If a module
|
||||
or your template contains hardcoded links, such as 'href="node/$node->nid"'
|
||||
those won't get replaced with their corresponding aliases. Use the
|
||||
Drupal API instead:
|
||||
|
||||
* 'href="'. url("node/$node->nid") .'"' or
|
||||
* l("Your link title", "node/$node->nid")
|
||||
|
||||
See http://api.drupal.org/api/HEAD/function/url and
|
||||
http://api.drupal.org/api/HEAD/function/l for more information.
|
||||
|
||||
** Disabling Pathauto for a specific node type (or taxonomy)
|
||||
When the pattern for a node type is left blank, the default pattern will be
|
||||
used. But if the default pattern is also blank, Pathauto will be disabled
|
||||
for that node type.
|
||||
|
||||
** Bulk Updates Must be Run Multiple Times:
|
||||
As of 5.x-2.x Pathauto now performs bulk updates in a manner which is more
|
||||
likely to succeed on large sites. The drawback is that it needs to be run
|
||||
multiple times. If you want to reduce the number of times that you need to
|
||||
run Pathauto you can increase the "Maximum number of objects to alias in a
|
||||
bulk update:" setting under General Settings.
|
||||
|
||||
**WYSIWYG Conflicts - FCKEditor, TinyMCE, etc.
|
||||
If you use a WYSIWYG editor, please disable it for the Pathauto admin page.
|
||||
Failure to do so may cause errors about "preg_replace" problems due to the <p>
|
||||
tag being added to the "strings to replace". See http://drupal.org/node/175772
|
||||
|
||||
**Credits:
|
||||
The original module combined the functionality of Mike Ryan's autopath with
|
||||
Tommy Sundstrom's path_automatic.
|
||||
|
||||
Significant enhancements were contributed by jdmquin @ www.bcdems.net.
|
||||
|
||||
Matt England added the tracker support.
|
||||
|
||||
Other suggestions and patches contributed by the Drupal community.
|
||||
|
||||
Current maintainers:
|
||||
Greg Knaddison - http://growingventuresolutions.com
|
||||
Mike Ryan - http://mikeryan.name
|
||||
Frederik 'Freso' S. Olesen - http://freso.dk
|
||||
|
||||
**Changes:
|
||||
See the CHANGELOG.txt file.
|
||||
|
564
modules/pathauto/i18n-ascii.example.txt
Normal file
564
modules/pathauto/i18n-ascii.example.txt
Normal file
|
@ -0,0 +1,564 @@
|
|||
; global transliteration
|
||||
[default]
|
||||
À = "A"
|
||||
Á = "A"
|
||||
 = "A"
|
||||
à = "A"
|
||||
Ä = "Ae"
|
||||
Å = "A"
|
||||
Æ = "A"
|
||||
Ā = "A"
|
||||
Ą = "A"
|
||||
Ă = "A"
|
||||
Ç = "C"
|
||||
Ć = "C"
|
||||
Č = "C"
|
||||
Ĉ = "C"
|
||||
Ċ = "C"
|
||||
Ď = "D"
|
||||
Đ = "D"
|
||||
È = "E"
|
||||
É = "E"
|
||||
Ê = "E"
|
||||
Ë = "E"
|
||||
Ē = "E"
|
||||
Ę = "E"
|
||||
Ě = "E"
|
||||
Ĕ = "E"
|
||||
Ė = "E"
|
||||
Ĝ = "G"
|
||||
Ğ = "G"
|
||||
Ġ = "G"
|
||||
Ģ = "G"
|
||||
Ĥ = "H"
|
||||
Ħ = "H"
|
||||
Ì = "I"
|
||||
Í = "I"
|
||||
Î = "I"
|
||||
Ï = "I"
|
||||
Ī = "I"
|
||||
Ĩ = "I"
|
||||
Ĭ = "I"
|
||||
Į = "I"
|
||||
İ = "I"
|
||||
IJ = "IJ"
|
||||
Ĵ = "J"
|
||||
Ķ = "K"
|
||||
Ľ = "L"
|
||||
Ĺ = "L"
|
||||
Ļ = "L"
|
||||
Ŀ = "L"
|
||||
Ł = "L"
|
||||
Ñ = "N"
|
||||
Ń = "N"
|
||||
Ň = "N"
|
||||
Ņ = "N"
|
||||
Ŋ = "N"
|
||||
Ò = "O"
|
||||
Ó = "O"
|
||||
Ô = "O"
|
||||
Õ = "O"
|
||||
Ö = "Oe"
|
||||
Ø = "O"
|
||||
Ō = "O"
|
||||
Ő = "O"
|
||||
Ŏ = "O"
|
||||
Œ = "OE"
|
||||
Ŕ = "R"
|
||||
Ř = "R"
|
||||
Ŗ = "R"
|
||||
Ś = "S"
|
||||
Ş = "S"
|
||||
Ŝ = "S"
|
||||
Ș = "S"
|
||||
Š = "S"
|
||||
Ť = "T"
|
||||
Ţ = "T"
|
||||
Ŧ = "T"
|
||||
Ț = "T"
|
||||
Ù = "U"
|
||||
Ú = "U"
|
||||
Û = "U"
|
||||
Ü = "Ue"
|
||||
Ū = "U"
|
||||
Ů = "U"
|
||||
Ű = "U"
|
||||
Ŭ = "U"
|
||||
Ũ = "U"
|
||||
Ų = "U"
|
||||
Ŵ = "W"
|
||||
Ŷ = "Y"
|
||||
Ÿ = "Y"
|
||||
Ý = "Y"
|
||||
Ź = "Z"
|
||||
Ż = "Z"
|
||||
Ž = "Z"
|
||||
à = "a"
|
||||
á = "a"
|
||||
â = "a"
|
||||
ã = "a"
|
||||
ä = "ae"
|
||||
ā = "a"
|
||||
ą = "a"
|
||||
ă = "a"
|
||||
å = "a"
|
||||
æ = "ae"
|
||||
ç = "c"
|
||||
ć = "c"
|
||||
č = "c"
|
||||
ĉ = "c"
|
||||
ċ = "c"
|
||||
ď = "d"
|
||||
đ = "d"
|
||||
è = "e"
|
||||
é = "e"
|
||||
ê = "e"
|
||||
ë = "e"
|
||||
ē = "e"
|
||||
ę = "e"
|
||||
ě = "e"
|
||||
ĕ = "e"
|
||||
ė = "e"
|
||||
ƒ = "f"
|
||||
ĝ = "g"
|
||||
ğ = "g"
|
||||
ġ = "g"
|
||||
ģ = "g"
|
||||
ĥ = "h"
|
||||
ħ = "h"
|
||||
ì = "i"
|
||||
í = "i"
|
||||
î = "i"
|
||||
ï = "i"
|
||||
ī = "i"
|
||||
ĩ = "i"
|
||||
ĭ = "i"
|
||||
į = "i"
|
||||
ı = "i"
|
||||
ij = "ij"
|
||||
ĵ = "j"
|
||||
ķ = "k"
|
||||
ĸ = "k"
|
||||
ł = "l"
|
||||
ľ = "l"
|
||||
ĺ = "l"
|
||||
ļ = "l"
|
||||
ŀ = "l"
|
||||
ñ = "n"
|
||||
ń = "n"
|
||||
ň = "n"
|
||||
ņ = "n"
|
||||
ʼn = "n"
|
||||
ŋ = "n"
|
||||
ò = "o"
|
||||
ó = "o"
|
||||
ô = "o"
|
||||
õ = "o"
|
||||
ö = "oe"
|
||||
ø = "o"
|
||||
ō = "o"
|
||||
ő = "o"
|
||||
ŏ = "o"
|
||||
œ = "oe"
|
||||
ŕ = "r"
|
||||
ř = "r"
|
||||
ŗ = "r"
|
||||
ś = "s"
|
||||
š = "s"
|
||||
ş = "s"
|
||||
ť = "t"
|
||||
ţ = "t"
|
||||
ù = "u"
|
||||
ú = "u"
|
||||
û = "u"
|
||||
ü = "ue"
|
||||
ū = "u"
|
||||
ů = "u"
|
||||
ű = "u"
|
||||
ŭ = "u"
|
||||
ũ = "u"
|
||||
ų = "u"
|
||||
ŵ = "w"
|
||||
ÿ = "y"
|
||||
ý = "y"
|
||||
ŷ = "y"
|
||||
ż = "z"
|
||||
ź = "z"
|
||||
ž = "z"
|
||||
ß = "ss"
|
||||
ſ = "ss"
|
||||
Α = "A"
|
||||
Ά = "A"
|
||||
Ἀ = "A"
|
||||
Ἁ = "A"
|
||||
Ἂ = "A"
|
||||
Ἃ = "A"
|
||||
Ἄ = "A"
|
||||
Ἅ = "A"
|
||||
Ἆ = "A"
|
||||
Ἇ = "A"
|
||||
ᾈ = "A"
|
||||
ᾉ = "A"
|
||||
ᾊ = "A"
|
||||
ᾋ = "A"
|
||||
ᾌ = "A"
|
||||
ᾍ = "A"
|
||||
ᾎ = "A"
|
||||
ᾏ = "A"
|
||||
Ᾰ = "A"
|
||||
Ᾱ = "A"
|
||||
Ὰ = "A"
|
||||
Ά = "A"
|
||||
ᾼ = "A"
|
||||
Β = "B"
|
||||
Γ = "G"
|
||||
Δ = "D"
|
||||
Ε = "E"
|
||||
Έ = "E"
|
||||
Ἐ = "E"
|
||||
Ἑ = "E"
|
||||
Ἒ = "E"
|
||||
Ἓ = "E"
|
||||
Ἔ = "E"
|
||||
Ἕ = "E"
|
||||
Έ = "E"
|
||||
Ὲ = "E"
|
||||
Ζ = "Z"
|
||||
Η = "I"
|
||||
Ή = "I"
|
||||
Ἠ = "I"
|
||||
Ἡ = "I"
|
||||
Ἢ = "I"
|
||||
Ἣ = "I"
|
||||
Ἤ = "I"
|
||||
Ἥ = "I"
|
||||
Ἦ = "I"
|
||||
Ἧ = "I"
|
||||
ᾘ = "I"
|
||||
ᾙ = "I"
|
||||
ᾚ = "I"
|
||||
ᾛ = "I"
|
||||
ᾜ = "I"
|
||||
ᾝ = "I"
|
||||
ᾞ = "I"
|
||||
ᾟ = "I"
|
||||
Ὴ = "I"
|
||||
Ή = "I"
|
||||
ῌ = "I"
|
||||
Θ = "TH"
|
||||
Ι = "I"
|
||||
Ί = "I"
|
||||
Ϊ = "I"
|
||||
Ἰ = "I"
|
||||
Ἱ = "I"
|
||||
Ἲ = "I"
|
||||
Ἳ = "I"
|
||||
Ἴ = "I"
|
||||
Ἵ = "I"
|
||||
Ἶ = "I"
|
||||
Ἷ = "I"
|
||||
Ῐ = "I"
|
||||
Ῑ = "I"
|
||||
Ὶ = "I"
|
||||
Ί = "I"
|
||||
Κ = "K"
|
||||
Λ = "L"
|
||||
Μ = "M"
|
||||
Ν = "N"
|
||||
Ξ = "KS"
|
||||
Ο = "O"
|
||||
Ό = "O"
|
||||
Ὀ = "O"
|
||||
Ὁ = "O"
|
||||
Ὂ = "O"
|
||||
Ὃ = "O"
|
||||
Ὄ = "O"
|
||||
Ὅ = "O"
|
||||
Ὸ = "O"
|
||||
Ό = "O"
|
||||
Π = "P"
|
||||
Ρ = "R"
|
||||
Ῥ = "R"
|
||||
Σ = "S"
|
||||
Τ = "T"
|
||||
Υ = "Y"
|
||||
Ύ = "Y"
|
||||
Ϋ = "Y"
|
||||
Ὑ = "Y"
|
||||
Ὓ = "Y"
|
||||
Ὕ = "Y"
|
||||
Ὗ = "Y"
|
||||
Ῠ = "Y"
|
||||
Ῡ = "Y"
|
||||
Ὺ = "Y"
|
||||
Ύ = "Y"
|
||||
Φ = "F"
|
||||
Χ = "X"
|
||||
Ψ = "PS"
|
||||
Ω = "O"
|
||||
Ώ = "O"
|
||||
Ὠ = "O"
|
||||
Ὡ = "O"
|
||||
Ὢ = "O"
|
||||
Ὣ = "O"
|
||||
Ὤ = "O"
|
||||
Ὥ = "O"
|
||||
Ὦ = "O"
|
||||
Ὧ = "O"
|
||||
ᾨ = "O"
|
||||
ᾩ = "O"
|
||||
ᾪ = "O"
|
||||
ᾫ = "O"
|
||||
ᾬ = "O"
|
||||
ᾭ = "O"
|
||||
ᾮ = "O"
|
||||
ᾯ = "O"
|
||||
Ὼ = "O"
|
||||
Ώ = "O"
|
||||
ῼ = "O"
|
||||
α = "a"
|
||||
ά = "a"
|
||||
ἀ = "a"
|
||||
ἁ = "a"
|
||||
ἂ = "a"
|
||||
ἃ = "a"
|
||||
ἄ = "a"
|
||||
ἅ = "a"
|
||||
ἆ = "a"
|
||||
ἇ = "a"
|
||||
ᾀ = "a"
|
||||
ᾁ = "a"
|
||||
ᾂ = "a"
|
||||
ᾃ = "a"
|
||||
ᾄ = "a"
|
||||
ᾅ = "a"
|
||||
ᾆ = "a"
|
||||
ᾇ = "a"
|
||||
ὰ = "a"
|
||||
ά = "a"
|
||||
ᾰ = "a"
|
||||
ᾱ = "a"
|
||||
ᾲ = "a"
|
||||
ᾳ = "a"
|
||||
ᾴ = "a"
|
||||
ᾶ = "a"
|
||||
ᾷ = "a"
|
||||
β = "b"
|
||||
γ = "g"
|
||||
δ = "d"
|
||||
ε = "e"
|
||||
έ = "e"
|
||||
ἐ = "e"
|
||||
ἑ = "e"
|
||||
ἒ = "e"
|
||||
ἓ = "e"
|
||||
ἔ = "e"
|
||||
ἕ = "e"
|
||||
ὲ = "e"
|
||||
έ = "e"
|
||||
ζ = "z"
|
||||
η = "i"
|
||||
ή = "i"
|
||||
ἠ = "i"
|
||||
ἡ = "i"
|
||||
ἢ = "i"
|
||||
ἣ = "i"
|
||||
ἤ = "i"
|
||||
ἥ = "i"
|
||||
ἦ = "i"
|
||||
ἧ = "i"
|
||||
ᾐ = "i"
|
||||
ᾑ = "i"
|
||||
ᾒ = "i"
|
||||
ᾓ = "i"
|
||||
ᾔ = "i"
|
||||
ᾕ = "i"
|
||||
ᾖ = "i"
|
||||
ᾗ = "i"
|
||||
ὴ = "i"
|
||||
ή = "i"
|
||||
ῂ = "i"
|
||||
ῃ = "i"
|
||||
ῄ = "i"
|
||||
ῆ = "i"
|
||||
ῇ = "i"
|
||||
θ = "th"
|
||||
ι = "i"
|
||||
ί = "i"
|
||||
ϊ = "i"
|
||||
ΐ = "i"
|
||||
ἰ = "i"
|
||||
ἱ = "i"
|
||||
ἲ = "i"
|
||||
ἳ = "i"
|
||||
ἴ = "i"
|
||||
ἵ = "i"
|
||||
ἶ = "i"
|
||||
ἷ = "i"
|
||||
ὶ = "i"
|
||||
ί = "i"
|
||||
ῐ = "i"
|
||||
ῑ = "i"
|
||||
ῒ = "i"
|
||||
ΐ = "i"
|
||||
ῖ = "i"
|
||||
ῗ = "i"
|
||||
κ = "k"
|
||||
λ = "l"
|
||||
μ = "m"
|
||||
ν = "n"
|
||||
ξ = "ks"
|
||||
ο = "o"
|
||||
ό = "o"
|
||||
ὀ = "o"
|
||||
ὁ = "o"
|
||||
ὂ = "o"
|
||||
ὃ = "o"
|
||||
ὄ = "o"
|
||||
ὅ = "o"
|
||||
ὸ = "o"
|
||||
ό = "o"
|
||||
π = "p"
|
||||
ρ = "r"
|
||||
ῤ = "r"
|
||||
ῥ = "r"
|
||||
σ = "s"
|
||||
ς = "s"
|
||||
τ = "t"
|
||||
υ = "y"
|
||||
ύ = "y"
|
||||
ϋ = "y"
|
||||
ΰ = "y"
|
||||
ὐ = "y"
|
||||
ὑ = "y"
|
||||
ὒ = "y"
|
||||
ὓ = "y"
|
||||
ὔ = "y"
|
||||
ὕ = "y"
|
||||
ὖ = "y"
|
||||
ὗ = "y"
|
||||
ὺ = "y"
|
||||
ύ = "y"
|
||||
ῠ = "y"
|
||||
ῡ = "y"
|
||||
ῢ = "y"
|
||||
ΰ = "y"
|
||||
ῦ = "y"
|
||||
ῧ = "y"
|
||||
φ = "f"
|
||||
χ = "x"
|
||||
ψ = "ps"
|
||||
ω = "o"
|
||||
ώ = "o"
|
||||
ὠ = "o"
|
||||
ὡ = "o"
|
||||
ὢ = "o"
|
||||
ὣ = "o"
|
||||
ὤ = "o"
|
||||
ὥ = "o"
|
||||
ὦ = "o"
|
||||
ὧ = "o"
|
||||
ᾠ = "o"
|
||||
ᾡ = "o"
|
||||
ᾢ = "o"
|
||||
ᾣ = "o"
|
||||
ᾤ = "o"
|
||||
ᾥ = "o"
|
||||
ᾦ = "o"
|
||||
ᾧ = "o"
|
||||
ὼ = "o"
|
||||
ώ = "o"
|
||||
ῲ = "o"
|
||||
ῳ = "o"
|
||||
ῴ = "o"
|
||||
ῶ = "o"
|
||||
ῷ = "o"
|
||||
¨ = ""
|
||||
΅ = ""
|
||||
᾿ = ""
|
||||
῾ = ""
|
||||
῍ = ""
|
||||
῝ = ""
|
||||
῎ = ""
|
||||
῞ = ""
|
||||
῏ = ""
|
||||
῟ = ""
|
||||
῀ = ""
|
||||
῁ = ""
|
||||
΄ = ""
|
||||
΅ = ""
|
||||
` = ""
|
||||
῭ = ""
|
||||
ͺ = ""
|
||||
᾽ = ""
|
||||
А = "A"
|
||||
Б = "B"
|
||||
В = "V"
|
||||
Г = "G"
|
||||
Д = "D"
|
||||
Е = "E"
|
||||
Ё = "E"
|
||||
Ж = "ZH"
|
||||
З = "Z"
|
||||
И = "I"
|
||||
Й = "I"
|
||||
К = "K"
|
||||
Л = "L"
|
||||
М = "M"
|
||||
Н = "N"
|
||||
О = "O"
|
||||
П = "P"
|
||||
Р = "R"
|
||||
С = "S"
|
||||
Т = "T"
|
||||
У = "U"
|
||||
Ф = "F"
|
||||
Х = "KH"
|
||||
Ц = "TS"
|
||||
Ч = "CH"
|
||||
Ш = "SH"
|
||||
Щ = "SHCH"
|
||||
Ы = "Y"
|
||||
Э = "E"
|
||||
Ю = "YU"
|
||||
Я = "YA"
|
||||
а = "A"
|
||||
б = "B"
|
||||
в = "V"
|
||||
г = "G"
|
||||
д = "D"
|
||||
е = "E"
|
||||
ё = "E"
|
||||
ж = "ZH"
|
||||
з = "Z"
|
||||
и = "I"
|
||||
й = "I"
|
||||
к = "K"
|
||||
л = "L"
|
||||
м = "M"
|
||||
н = "N"
|
||||
о = "O"
|
||||
п = "P"
|
||||
р = "R"
|
||||
с = "S"
|
||||
т = "T"
|
||||
у = "U"
|
||||
ф = "F"
|
||||
х = "KH"
|
||||
ц = "TS"
|
||||
ч = "CH"
|
||||
ш = "SH"
|
||||
щ = "SHCH"
|
||||
ы = "Y"
|
||||
э = "E"
|
||||
ю = "YU"
|
||||
я = "YA"
|
||||
Ъ = ""
|
||||
ъ = ""
|
||||
Ь = ""
|
||||
ь = ""
|
||||
|
||||
ð = "d"
|
||||
Ð = "D"
|
||||
þ = "th"
|
||||
Þ = "TH"
|
569
modules/pathauto/i18n-ascii.txt
Normal file
569
modules/pathauto/i18n-ascii.txt
Normal file
|
@ -0,0 +1,569 @@
|
|||
; global transliteration
|
||||
[default]
|
||||
À = "A"
|
||||
Á = "A"
|
||||
 = "A"
|
||||
à = "A"
|
||||
Ä = "Ae"
|
||||
Å = "A"
|
||||
Æ = "A"
|
||||
Ā = "A"
|
||||
Ą = "A"
|
||||
Ă = "A"
|
||||
Ç = "C"
|
||||
Ć = "C"
|
||||
Č = "C"
|
||||
Ĉ = "C"
|
||||
Ċ = "C"
|
||||
Ď = "D"
|
||||
Đ = "D"
|
||||
È = "E"
|
||||
É = "E"
|
||||
Ê = "E"
|
||||
Ë = "E"
|
||||
Ē = "E"
|
||||
Ę = "E"
|
||||
Ě = "E"
|
||||
Ĕ = "E"
|
||||
Ė = "E"
|
||||
Ĝ = "G"
|
||||
Ğ = "G"
|
||||
Ġ = "G"
|
||||
Ģ = "G"
|
||||
Ĥ = "H"
|
||||
Ħ = "H"
|
||||
Ì = "I"
|
||||
Í = "I"
|
||||
Î = "I"
|
||||
Ï = "I"
|
||||
Ī = "I"
|
||||
Ĩ = "I"
|
||||
Ĭ = "I"
|
||||
Į = "I"
|
||||
İ = "I"
|
||||
IJ = "IJ"
|
||||
Ĵ = "J"
|
||||
Ķ = "K"
|
||||
Ľ = "L"
|
||||
Ĺ = "L"
|
||||
Ļ = "L"
|
||||
Ŀ = "L"
|
||||
Ł = "L"
|
||||
Ñ = "NI"
|
||||
Ń = "N"
|
||||
Ň = "N"
|
||||
Ņ = "N"
|
||||
Ŋ = "N"
|
||||
Ò = "O"
|
||||
Ó = "O"
|
||||
Ô = "O"
|
||||
Õ = "O"
|
||||
Ö = "Oe"
|
||||
Ø = "O"
|
||||
Ō = "O"
|
||||
Ő = "O"
|
||||
Ŏ = "O"
|
||||
Œ = "OE"
|
||||
Ŕ = "R"
|
||||
Ř = "R"
|
||||
Ŗ = "R"
|
||||
Ś = "S"
|
||||
Ş = "S"
|
||||
Ŝ = "S"
|
||||
Ș = "S"
|
||||
Š = "S"
|
||||
Ť = "T"
|
||||
Ţ = "T"
|
||||
Ŧ = "T"
|
||||
Ț = "T"
|
||||
Ù = "U"
|
||||
Ú = "U"
|
||||
Û = "U"
|
||||
Ü = "Ue"
|
||||
Ū = "U"
|
||||
Ů = "U"
|
||||
Ű = "U"
|
||||
Ŭ = "U"
|
||||
Ũ = "U"
|
||||
Ų = "U"
|
||||
Ŵ = "W"
|
||||
Ŷ = "Y"
|
||||
Ÿ = "Y"
|
||||
Ý = "Y"
|
||||
Ź = "Z"
|
||||
Ż = "Z"
|
||||
Ž = "Z"
|
||||
à = "a"
|
||||
á = "a"
|
||||
â = "a"
|
||||
ã = "a"
|
||||
ä = "ae"
|
||||
ā = "a"
|
||||
ą = "a"
|
||||
ă = "a"
|
||||
å = "a"
|
||||
æ = "ae"
|
||||
ç = "c"
|
||||
ć = "c"
|
||||
č = "c"
|
||||
ĉ = "c"
|
||||
ċ = "c"
|
||||
ď = "d"
|
||||
đ = "d"
|
||||
è = "e"
|
||||
é = "e"
|
||||
ê = "e"
|
||||
ë = "e"
|
||||
ē = "e"
|
||||
ę = "e"
|
||||
ě = "e"
|
||||
ĕ = "e"
|
||||
ė = "e"
|
||||
ƒ = "f"
|
||||
ĝ = "g"
|
||||
ğ = "g"
|
||||
ġ = "g"
|
||||
ģ = "g"
|
||||
ĥ = "h"
|
||||
ħ = "h"
|
||||
ì = "i"
|
||||
í = "i"
|
||||
î = "i"
|
||||
ï = "i"
|
||||
ī = "i"
|
||||
ĩ = "i"
|
||||
ĭ = "i"
|
||||
į = "i"
|
||||
ı = "i"
|
||||
ij = "ij"
|
||||
ĵ = "j"
|
||||
ķ = "k"
|
||||
ĸ = "k"
|
||||
ł = "l"
|
||||
ľ = "l"
|
||||
ĺ = "l"
|
||||
ļ = "l"
|
||||
ŀ = "l"
|
||||
ñ = "ni"
|
||||
ń = "n"
|
||||
ň = "n"
|
||||
ņ = "n"
|
||||
ʼn = "n"
|
||||
ŋ = "n"
|
||||
ò = "o"
|
||||
ó = "o"
|
||||
ô = "o"
|
||||
õ = "o"
|
||||
ö = "oe"
|
||||
ø = "o"
|
||||
ō = "o"
|
||||
ő = "o"
|
||||
ŏ = "o"
|
||||
œ = "oe"
|
||||
ŕ = "r"
|
||||
ř = "r"
|
||||
ŗ = "r"
|
||||
ś = "s"
|
||||
š = "s"
|
||||
ş = "s"
|
||||
ť = "t"
|
||||
ţ = "t"
|
||||
ù = "u"
|
||||
ú = "u"
|
||||
û = "u"
|
||||
ü = "ue"
|
||||
ū = "u"
|
||||
ů = "u"
|
||||
ű = "u"
|
||||
ŭ = "u"
|
||||
ũ = "u"
|
||||
ų = "u"
|
||||
ŵ = "w"
|
||||
ÿ = "y"
|
||||
ý = "y"
|
||||
ŷ = "y"
|
||||
ż = "z"
|
||||
ź = "z"
|
||||
ž = "z"
|
||||
ß = "ss"
|
||||
ſ = "ss"
|
||||
Α = "A"
|
||||
Ά = "A"
|
||||
Ἀ = "A"
|
||||
Ἁ = "A"
|
||||
Ἂ = "A"
|
||||
Ἃ = "A"
|
||||
Ἄ = "A"
|
||||
Ἅ = "A"
|
||||
Ἆ = "A"
|
||||
Ἇ = "A"
|
||||
ᾈ = "A"
|
||||
ᾉ = "A"
|
||||
ᾊ = "A"
|
||||
ᾋ = "A"
|
||||
ᾌ = "A"
|
||||
ᾍ = "A"
|
||||
ᾎ = "A"
|
||||
ᾏ = "A"
|
||||
Ᾰ = "A"
|
||||
Ᾱ = "A"
|
||||
Ὰ = "A"
|
||||
Ά = "A"
|
||||
ᾼ = "A"
|
||||
Β = "B"
|
||||
Γ = "G"
|
||||
Δ = "D"
|
||||
Ε = "E"
|
||||
Έ = "E"
|
||||
Ἐ = "E"
|
||||
Ἑ = "E"
|
||||
Ἒ = "E"
|
||||
Ἓ = "E"
|
||||
Ἔ = "E"
|
||||
Ἕ = "E"
|
||||
Έ = "E"
|
||||
Ὲ = "E"
|
||||
Ζ = "Z"
|
||||
Η = "I"
|
||||
Ή = "I"
|
||||
Ἠ = "I"
|
||||
Ἡ = "I"
|
||||
Ἢ = "I"
|
||||
Ἣ = "I"
|
||||
Ἤ = "I"
|
||||
Ἥ = "I"
|
||||
Ἦ = "I"
|
||||
Ἧ = "I"
|
||||
ᾘ = "I"
|
||||
ᾙ = "I"
|
||||
ᾚ = "I"
|
||||
ᾛ = "I"
|
||||
ᾜ = "I"
|
||||
ᾝ = "I"
|
||||
ᾞ = "I"
|
||||
ᾟ = "I"
|
||||
Ὴ = "I"
|
||||
Ή = "I"
|
||||
ῌ = "I"
|
||||
Θ = "TH"
|
||||
Ι = "I"
|
||||
Ί = "I"
|
||||
Ϊ = "I"
|
||||
Ἰ = "I"
|
||||
Ἱ = "I"
|
||||
Ἲ = "I"
|
||||
Ἳ = "I"
|
||||
Ἴ = "I"
|
||||
Ἵ = "I"
|
||||
Ἶ = "I"
|
||||
Ἷ = "I"
|
||||
Ῐ = "I"
|
||||
Ῑ = "I"
|
||||
Ὶ = "I"
|
||||
Ί = "I"
|
||||
Κ = "K"
|
||||
Λ = "L"
|
||||
Μ = "M"
|
||||
Ν = "N"
|
||||
Ξ = "KS"
|
||||
Ο = "O"
|
||||
Ό = "O"
|
||||
Ὀ = "O"
|
||||
Ὁ = "O"
|
||||
Ὂ = "O"
|
||||
Ὃ = "O"
|
||||
Ὄ = "O"
|
||||
Ὅ = "O"
|
||||
Ὸ = "O"
|
||||
Ό = "O"
|
||||
Π = "P"
|
||||
Ρ = "R"
|
||||
Ῥ = "R"
|
||||
Σ = "S"
|
||||
Τ = "T"
|
||||
Υ = "Y"
|
||||
Ύ = "Y"
|
||||
Ϋ = "Y"
|
||||
Ὑ = "Y"
|
||||
Ὓ = "Y"
|
||||
Ὕ = "Y"
|
||||
Ὗ = "Y"
|
||||
Ῠ = "Y"
|
||||
Ῡ = "Y"
|
||||
Ὺ = "Y"
|
||||
Ύ = "Y"
|
||||
Φ = "F"
|
||||
Χ = "X"
|
||||
Ψ = "PS"
|
||||
Ω = "O"
|
||||
Ώ = "O"
|
||||
Ὠ = "O"
|
||||
Ὡ = "O"
|
||||
Ὢ = "O"
|
||||
Ὣ = "O"
|
||||
Ὤ = "O"
|
||||
Ὥ = "O"
|
||||
Ὦ = "O"
|
||||
Ὧ = "O"
|
||||
ᾨ = "O"
|
||||
ᾩ = "O"
|
||||
ᾪ = "O"
|
||||
ᾫ = "O"
|
||||
ᾬ = "O"
|
||||
ᾭ = "O"
|
||||
ᾮ = "O"
|
||||
ᾯ = "O"
|
||||
Ὼ = "O"
|
||||
Ώ = "O"
|
||||
ῼ = "O"
|
||||
α = "a"
|
||||
ά = "a"
|
||||
ἀ = "a"
|
||||
ἁ = "a"
|
||||
ἂ = "a"
|
||||
ἃ = "a"
|
||||
ἄ = "a"
|
||||
ἅ = "a"
|
||||
ἆ = "a"
|
||||
ἇ = "a"
|
||||
ᾀ = "a"
|
||||
ᾁ = "a"
|
||||
ᾂ = "a"
|
||||
ᾃ = "a"
|
||||
ᾄ = "a"
|
||||
ᾅ = "a"
|
||||
ᾆ = "a"
|
||||
ᾇ = "a"
|
||||
ὰ = "a"
|
||||
ά = "a"
|
||||
ᾰ = "a"
|
||||
ᾱ = "a"
|
||||
ᾲ = "a"
|
||||
ᾳ = "a"
|
||||
ᾴ = "a"
|
||||
ᾶ = "a"
|
||||
ᾷ = "a"
|
||||
β = "b"
|
||||
γ = "g"
|
||||
δ = "d"
|
||||
ε = "e"
|
||||
έ = "e"
|
||||
ἐ = "e"
|
||||
ἑ = "e"
|
||||
ἒ = "e"
|
||||
ἓ = "e"
|
||||
ἔ = "e"
|
||||
ἕ = "e"
|
||||
ὲ = "e"
|
||||
έ = "e"
|
||||
ζ = "z"
|
||||
η = "i"
|
||||
ή = "i"
|
||||
ἠ = "i"
|
||||
ἡ = "i"
|
||||
ἢ = "i"
|
||||
ἣ = "i"
|
||||
ἤ = "i"
|
||||
ἥ = "i"
|
||||
ἦ = "i"
|
||||
ἧ = "i"
|
||||
ᾐ = "i"
|
||||
ᾑ = "i"
|
||||
ᾒ = "i"
|
||||
ᾓ = "i"
|
||||
ᾔ = "i"
|
||||
ᾕ = "i"
|
||||
ᾖ = "i"
|
||||
ᾗ = "i"
|
||||
ὴ = "i"
|
||||
ή = "i"
|
||||
ῂ = "i"
|
||||
ῃ = "i"
|
||||
ῄ = "i"
|
||||
ῆ = "i"
|
||||
ῇ = "i"
|
||||
θ = "th"
|
||||
ι = "i"
|
||||
ί = "i"
|
||||
ϊ = "i"
|
||||
ΐ = "i"
|
||||
ἰ = "i"
|
||||
ἱ = "i"
|
||||
ἲ = "i"
|
||||
ἳ = "i"
|
||||
ἴ = "i"
|
||||
ἵ = "i"
|
||||
ἶ = "i"
|
||||
ἷ = "i"
|
||||
ὶ = "i"
|
||||
ί = "i"
|
||||
ῐ = "i"
|
||||
ῑ = "i"
|
||||
ῒ = "i"
|
||||
ΐ = "i"
|
||||
ῖ = "i"
|
||||
ῗ = "i"
|
||||
κ = "k"
|
||||
λ = "l"
|
||||
μ = "m"
|
||||
ν = "n"
|
||||
ξ = "ks"
|
||||
ο = "o"
|
||||
ό = "o"
|
||||
ὀ = "o"
|
||||
ὁ = "o"
|
||||
ὂ = "o"
|
||||
ὃ = "o"
|
||||
ὄ = "o"
|
||||
ὅ = "o"
|
||||
ὸ = "o"
|
||||
ό = "o"
|
||||
π = "p"
|
||||
ρ = "r"
|
||||
ῤ = "r"
|
||||
ῥ = "r"
|
||||
σ = "s"
|
||||
ς = "s"
|
||||
τ = "t"
|
||||
υ = "y"
|
||||
ύ = "y"
|
||||
ϋ = "y"
|
||||
ΰ = "y"
|
||||
ὐ = "y"
|
||||
ὑ = "y"
|
||||
ὒ = "y"
|
||||
ὓ = "y"
|
||||
ὔ = "y"
|
||||
ὕ = "y"
|
||||
ὖ = "y"
|
||||
ὗ = "y"
|
||||
ὺ = "y"
|
||||
ύ = "y"
|
||||
ῠ = "y"
|
||||
ῡ = "y"
|
||||
ῢ = "y"
|
||||
ΰ = "y"
|
||||
ῦ = "y"
|
||||
ῧ = "y"
|
||||
φ = "f"
|
||||
χ = "x"
|
||||
ψ = "ps"
|
||||
ω = "o"
|
||||
ώ = "o"
|
||||
ὠ = "o"
|
||||
ὡ = "o"
|
||||
ὢ = "o"
|
||||
ὣ = "o"
|
||||
ὤ = "o"
|
||||
ὥ = "o"
|
||||
ὦ = "o"
|
||||
ὧ = "o"
|
||||
ᾠ = "o"
|
||||
ᾡ = "o"
|
||||
ᾢ = "o"
|
||||
ᾣ = "o"
|
||||
ᾤ = "o"
|
||||
ᾥ = "o"
|
||||
ᾦ = "o"
|
||||
ᾧ = "o"
|
||||
ὼ = "o"
|
||||
ώ = "o"
|
||||
ῲ = "o"
|
||||
ῳ = "o"
|
||||
ῴ = "o"
|
||||
ῶ = "o"
|
||||
ῷ = "o"
|
||||
¨ = ""
|
||||
΅ = ""
|
||||
᾿ = ""
|
||||
῾ = ""
|
||||
῍ = ""
|
||||
῝ = ""
|
||||
῎ = ""
|
||||
῞ = ""
|
||||
῏ = ""
|
||||
῟ = ""
|
||||
῀ = ""
|
||||
῁ = ""
|
||||
΄ = ""
|
||||
΅ = ""
|
||||
` = ""
|
||||
῭ = ""
|
||||
ͺ = ""
|
||||
᾽ = ""
|
||||
А = "A"
|
||||
Б = "B"
|
||||
В = "V"
|
||||
Г = "G"
|
||||
Д = "D"
|
||||
Е = "E"
|
||||
Ё = "E"
|
||||
Ж = "ZH"
|
||||
З = "Z"
|
||||
И = "I"
|
||||
Й = "I"
|
||||
К = "K"
|
||||
Л = "L"
|
||||
М = "M"
|
||||
Н = "N"
|
||||
О = "O"
|
||||
П = "P"
|
||||
Р = "R"
|
||||
С = "S"
|
||||
Т = "T"
|
||||
У = "U"
|
||||
Ф = "F"
|
||||
Х = "KH"
|
||||
Ц = "TS"
|
||||
Ч = "CH"
|
||||
Ш = "SH"
|
||||
Щ = "SHCH"
|
||||
Ы = "Y"
|
||||
Э = "E"
|
||||
Ю = "YU"
|
||||
Я = "YA"
|
||||
а = "A"
|
||||
б = "B"
|
||||
в = "V"
|
||||
г = "G"
|
||||
д = "D"
|
||||
е = "E"
|
||||
ё = "E"
|
||||
ж = "ZH"
|
||||
з = "Z"
|
||||
и = "I"
|
||||
й = "I"
|
||||
к = "K"
|
||||
л = "L"
|
||||
м = "M"
|
||||
н = "N"
|
||||
о = "O"
|
||||
п = "P"
|
||||
р = "R"
|
||||
с = "S"
|
||||
т = "T"
|
||||
у = "U"
|
||||
ф = "F"
|
||||
х = "KH"
|
||||
ц = "TS"
|
||||
ч = "CH"
|
||||
ш = "SH"
|
||||
щ = "SHCH"
|
||||
ы = "Y"
|
||||
э = "E"
|
||||
ю = "YU"
|
||||
я = "YA"
|
||||
Ъ = ""
|
||||
ъ = ""
|
||||
Ь = ""
|
||||
ь = ""
|
||||
|
||||
ð = "d"
|
||||
Ð = "D"
|
||||
þ = "th"
|
||||
Þ = "TH"
|
||||
|
||||
¿ = ""
|
||||
¡ = ""
|
||||
º = ""
|
||||
ª = ""
|
463
modules/pathauto/pathauto.admin.inc
Normal file
463
modules/pathauto/pathauto.admin.inc
Normal file
|
@ -0,0 +1,463 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Admin page callbacks for the Pathauto module.
|
||||
*
|
||||
* @ingroup pathauto
|
||||
*/
|
||||
|
||||
/**
|
||||
* Form builder; Configure the Pathauto system.
|
||||
*
|
||||
* @ingroup forms
|
||||
* @see system_settings_form()
|
||||
*/
|
||||
function pathauto_admin_settings() {
|
||||
_pathauto_include();
|
||||
|
||||
// Generate the form - settings applying to all patterns first
|
||||
$form['general'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#weight' => -20,
|
||||
'#title' => t('General settings'),
|
||||
'#collapsible' => TRUE,
|
||||
'#collapsed' => TRUE,
|
||||
);
|
||||
|
||||
$form['general']['pathauto_verbose'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Verbose'),
|
||||
'#default_value' => variable_get('pathauto_verbose', FALSE),
|
||||
'#description' => t('Display alias changes (except during bulk updates).'),
|
||||
);
|
||||
|
||||
$form['general']['pathauto_separator'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Separator'),
|
||||
'#size' => 1,
|
||||
'#maxlength' => 1,
|
||||
'#default_value' => variable_get('pathauto_separator', '-'),
|
||||
'#description' => t('Character used to separate words in titles. This will replace any spaces and punctuation characters. Using a space or + character can cause unexpected results.'),
|
||||
);
|
||||
|
||||
$form['general']['pathauto_case'] = array(
|
||||
'#type' => 'radios',
|
||||
'#title' => t('Character case'),
|
||||
'#default_value' => variable_get('pathauto_case', 1),
|
||||
'#options' => array(t('Leave case the same as source token values.'), t('Change to lower case')),
|
||||
);
|
||||
|
||||
$max_length = _pathauto_get_schema_alias_maxlength();
|
||||
|
||||
$form['general']['pathauto_max_length'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Maximum alias length'),
|
||||
'#size' => 3,
|
||||
'#maxlength' => 3,
|
||||
'#default_value' => variable_get('pathauto_max_length', 100),
|
||||
'#min_value' => 1,
|
||||
'#max_value' => $max_length,
|
||||
'#description' => t('Maximum length of aliases to generate. 100 is recommended. See <a href="@pathauto-help">Pathauto help</a> for details.', array('@pathauto-help' => url('admin/help/pathauto'))),
|
||||
'#element_validate' => array('_pathauto_validate_numeric_element'),
|
||||
);
|
||||
|
||||
$form['general']['pathauto_max_component_length'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Maximum component length'),
|
||||
'#size' => 3,
|
||||
'#maxlength' => 3,
|
||||
'#default_value' => variable_get('pathauto_max_component_length', 100),
|
||||
'#min_value' => 1,
|
||||
'#max_value' => $max_length,
|
||||
'#description' => t('Maximum text length of any component in the alias (e.g., [title]). 100 is recommended. See <a href="@pathauto-help">Pathauto help</a> for details.', array('@pathauto-help' => url('admin/help/pathauto'))),
|
||||
'#element_validate' => array('_pathauto_validate_numeric_element'),
|
||||
);
|
||||
|
||||
$form['general']['pathauto_max_bulk_update'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Maximum number of objects to alias in a bulk update'),
|
||||
'#size' => 4,
|
||||
'#maxlength' => 4,
|
||||
'#default_value' => variable_get('pathauto_max_bulk_update', 50),
|
||||
'#min_value' => 0,
|
||||
'#description' => t('Maximum number of objects of a given type which should be aliased during a bulk update. The default is 50 and the recommended number depends on the speed of your server. If bulk updates "time out" or result in a "white screen" then reduce the number.'),
|
||||
'#element_validate' => array('_pathauto_validate_numeric_element'),
|
||||
);
|
||||
|
||||
$actions = array(
|
||||
t('Do nothing. Leave the old alias intact.'),
|
||||
t('Create a new alias. Leave the existing alias functioning.'),
|
||||
t('Create a new alias. Delete the old alias.'));
|
||||
|
||||
if (function_exists('path_redirect_save')) {
|
||||
$actions[] = t('Create a new alias. Redirect from old alias.');
|
||||
}
|
||||
elseif (variable_get('pathauto_update_action', 2) == 3) {
|
||||
// the redirect action is selected, but path_redirect is not enabled
|
||||
// let's set the variable back to the default
|
||||
variable_set('pathauto_update_action', 2);
|
||||
}
|
||||
|
||||
$form['general']['pathauto_update_action'] = array(
|
||||
'#type' => 'radios',
|
||||
'#title' => t('Update action'),
|
||||
'#default_value' => variable_get('pathauto_update_action', 2),
|
||||
'#options' => $actions,
|
||||
'#description' => t('What should pathauto do when updating an existing content item which already has an alias?'),
|
||||
);
|
||||
|
||||
$form['general']['pathauto_transliterate'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Transliterate prior to creating alias'),
|
||||
'#default_value' => variable_get('pathauto_transliterate', FALSE),
|
||||
'#description' => t('When a pattern includes certain characters (such as those with accents) should Pathauto attempt to transliterate them into the ASCII-96 alphabet?'),
|
||||
'#disabled' => !_pathauto_get_i18n_file(),
|
||||
);
|
||||
$i18n_locations = _pathauto_get_i18n_possible_files();
|
||||
foreach ($i18n_locations as $key => $file) {
|
||||
$i18n_locations[$key] = check_plain($file);
|
||||
if (file_exists($file)) {
|
||||
$i18n_locations[$key] .= ' - <span class="admin-enabled">' . t('File exists') . '</span>';
|
||||
}
|
||||
else {
|
||||
$i18n_locations[$key] .= ' - <span class="admin-disabled">' . t('Does not exist') . '</span>';
|
||||
}
|
||||
}
|
||||
$form['general']['pathauto_transliterate']['#description'] .= ' ' . t('Transliteration is determined by the i18n-ascii.txt file in the following possible locations, in order of precedence: !locations', array('!locations' => theme('item_list', $i18n_locations)));
|
||||
if ($form['general']['pathauto_transliterate']['#disabled']) {
|
||||
// Perhaps they've removed the file, set the transliterate option to FALSE
|
||||
variable_set('pathauto_transliterate', FALSE);
|
||||
}
|
||||
|
||||
$form['general']['pathauto_reduce_ascii'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Reduce strings to letters and numbers from ASCII-96'),
|
||||
'#default_value' => variable_get('pathauto_reduce_ascii', FALSE),
|
||||
'#description' => t('Filters the new alias to only letters and numbers found in the ASCII-96 set.'),
|
||||
);
|
||||
|
||||
// Default words to ignore
|
||||
$ignore_words = array(
|
||||
'a', 'an', 'as', 'at', 'before', 'but', 'by', 'for', 'from', 'is', 'in',
|
||||
'into', 'like', 'of', 'off', 'on', 'onto', 'per', 'since', 'than', 'the',
|
||||
'this', 'that', 'to', 'up', 'via', 'with',
|
||||
);
|
||||
$form['general']['pathauto_ignore_words'] = array(
|
||||
'#type' => 'textarea',
|
||||
'#title' => t('Strings to Remove'),
|
||||
'#default_value' => variable_get('pathauto_ignore_words', implode(',', $ignore_words)),
|
||||
'#description' => t('Words to strip out of the URL alias, separated by commas. Do not place punctuation in here and do not use WYSIWYG editors on this field.'),
|
||||
'#wysiwyg' => FALSE,
|
||||
);
|
||||
|
||||
$form['punctuation'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#weight' => -10,
|
||||
'#title' => t('Punctuation settings'), '#collapsible' => TRUE,
|
||||
'#collapsed' => TRUE,
|
||||
);
|
||||
|
||||
$punctuation = pathauto_punctuation_chars();
|
||||
foreach ($punctuation as $name => $details) {
|
||||
$details['default'] = 0;
|
||||
if ($details['value'] == variable_get('pathauto_separator', '-')) {
|
||||
$details['default'] = 1;
|
||||
}
|
||||
$form['punctuation']['pathauto_punctuation_'. $name] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => $details['name'],
|
||||
'#default_value' => variable_get('pathauto_punctuation_'. $name, $details['default']),
|
||||
'#options' => array(
|
||||
'0' => t('Remove'),
|
||||
'1' => t('Replace by separator'),
|
||||
'2' => t('No action (do not replace)'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Call the hook on all modules - an array of 'settings' objects is returned
|
||||
$all_settings = module_invoke_all('pathauto', 'settings');
|
||||
foreach ($all_settings as $settings) {
|
||||
$module = $settings->module;
|
||||
$patterndescr = $settings->patterndescr;
|
||||
$patterndefault = $settings->patterndefault;
|
||||
$groupheader = $settings->groupheader;
|
||||
$supportsfeeds = isset($settings->supportsfeeds) ? $settings->supportsfeeds : NULL;
|
||||
variable_set('pathauto_' . $module . '_supportsfeeds', $supportsfeeds);
|
||||
|
||||
$form[$module] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => $groupheader,
|
||||
'#collapsible' => TRUE,
|
||||
'#collapsed' => TRUE,
|
||||
);
|
||||
|
||||
// Prompt for the default pattern for this module
|
||||
$variable = 'pathauto_' . $module . '_pattern';
|
||||
$form[$module][$variable] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => $patterndescr,
|
||||
'#default_value' => variable_get($variable, $patterndefault),
|
||||
'#size' => 65,
|
||||
'#maxlength' => 1280,
|
||||
'#element_validate' => array('_pathauto_validate_pattern_element'),
|
||||
'#after_build' => array('_pathauto_validate_pattern_element'),
|
||||
'#token_types' => array($settings->token_type),
|
||||
'#parents' => array($variable),
|
||||
);
|
||||
|
||||
// If the module supports a set of specialized patterns, set
|
||||
// them up here
|
||||
if (isset($settings->patternitems)) {
|
||||
foreach ($settings->patternitems as $itemname => $itemlabel) {
|
||||
$variable = 'pathauto_' . $module . '_' . $itemname . '_pattern';
|
||||
$form[$module][$variable] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => $itemlabel,
|
||||
'#default_value' => variable_get($variable, ''),
|
||||
'#size' => 65,
|
||||
'#maxlength' => 1280,
|
||||
'#element_validate' => array('_pathauto_validate_pattern_element'),
|
||||
'#after_build' => array('_pathauto_validate_pattern_element'),
|
||||
'#token_types' => array($settings->token_type),
|
||||
'#parents' => array($variable),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Display the user documentation of placeholders supported by
|
||||
// this module, as a description on the last pattern
|
||||
$form[$module]['token_help'] = array(
|
||||
'#title' => t('Replacement patterns'),
|
||||
'#type' => 'fieldset',
|
||||
'#collapsible' => TRUE,
|
||||
'#collapsed' => TRUE,
|
||||
'#description' => t('Use -raw replacements for text to avoid problems with HTML entities.'),
|
||||
);
|
||||
|
||||
// Use the token tree if available.
|
||||
$doc = theme('token_tree', array($settings->token_type), FALSE);
|
||||
if (empty($doc)) {
|
||||
$doc = "<dl>\n";
|
||||
foreach ($settings->placeholders as $name => $description) {
|
||||
$doc .= '<dt>'. $name .'</dt>';
|
||||
$doc .= '<dd>'. $description .'</dd>';
|
||||
}
|
||||
$doc .= "</dl>\n";
|
||||
}
|
||||
$form[$module]['token_help']['help'] = array(
|
||||
'#type' => 'markup',
|
||||
'#value' => $doc,
|
||||
);
|
||||
|
||||
// If the module supports bulk updates, offer the update action here
|
||||
if ($settings->bulkname) {
|
||||
$variable = 'pathauto_' . $module . '_bulkupdate';
|
||||
if (variable_get($variable, FALSE)) {
|
||||
variable_set($variable, FALSE);
|
||||
$function = $module . '_pathauto_bulkupdate';
|
||||
call_user_func($function);
|
||||
}
|
||||
$form[$module][$variable] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $settings->bulkname,
|
||||
'#default_value' => FALSE,
|
||||
'#description' => $settings->bulkdescr,
|
||||
);
|
||||
}
|
||||
|
||||
// If the module supports feeds, offer to generate aliases for them
|
||||
if ($supportsfeeds) {
|
||||
$variable = 'pathauto_' . $module . '_applytofeeds';
|
||||
$current = variable_get($variable, $supportsfeeds);
|
||||
// This checks for the old style from 2.0 and earlier. TODO: At some point we can drop that.
|
||||
if (is_numeric($current)) {
|
||||
$current = $supportsfeeds;
|
||||
}
|
||||
|
||||
$form[$module][$variable] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Internal feed alias text (leave blank to disable)'),
|
||||
'#size' => 65,
|
||||
'#maxlength' => 1280,
|
||||
'#default_value' => $current,
|
||||
'#description' => t('The text to use for aliases for RSS feeds. Examples are "0/feed" (used throughout Drupal core) and "feed" (used by some contributed Drupal modules, like Views).'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($do_index_bulkupdate) && $do_index_bulkupdate) {
|
||||
drupal_set_message(format_plural($indexcount,
|
||||
'Bulk generation of index aliases completed, one alias generated.',
|
||||
'Bulk generation of index aliases completed, @count aliases generated.'));
|
||||
}
|
||||
|
||||
return system_settings_form($form);
|
||||
}
|
||||
|
||||
/**
|
||||
* Element validation callback for URL alias patterns.
|
||||
*
|
||||
* This function performs the following validations:
|
||||
* - Checks if the pattern has at least one token.
|
||||
* - Checks if any tokens with raw companions are being used and recommends
|
||||
* use of the raw tokens.
|
||||
*/
|
||||
function _pathauto_validate_pattern_element(&$element, &$form_state) {
|
||||
// Get the current value of the element (since this can be used during both
|
||||
// form display and validation).
|
||||
$value = isset($element['#value']) ? $element['#value'] : $element['#default_value'];
|
||||
|
||||
// Empty patterns need no further validation.
|
||||
if (!drupal_strlen($value)) {
|
||||
return $element;
|
||||
}
|
||||
|
||||
// Check to see if the required token functions are available.
|
||||
if (!function_exists('token_scan') || !function_exists('token_element_validate_token_context')) {
|
||||
drupal_set_message(t('Please make sure you are using the latest version of the Token module.'), 'warning', FALSE);
|
||||
return $element;
|
||||
}
|
||||
|
||||
// Check for at least one token.
|
||||
$tokens = token_scan($value);
|
||||
if (empty($tokens)) {
|
||||
form_error($element, t('The %name should contain at least one token to ensure unique URL aliases are created.', array('%name' => $element['#title'])));
|
||||
}
|
||||
else {
|
||||
token_element_validate_token_context($element, $form_state);
|
||||
}
|
||||
|
||||
// Find any non-raw tokens that do have a raw companion token and warn.
|
||||
module_load_include('inc', 'pathauto');
|
||||
$not_raw_tokens = array();
|
||||
$raw_tokens = _pathauto_get_raw_tokens();
|
||||
foreach ($tokens as $token) {
|
||||
if (substr($token, -4) === '-raw') {
|
||||
// Skip raw tokens.
|
||||
continue;
|
||||
}
|
||||
elseif (in_array($token . '-raw', $raw_tokens)) {
|
||||
drupal_set_message(t('You are using the token [%token] which has a raw companion token [%raw_token]. For Pathauto patterns you should use the -raw version of tokens unless you really know what you are doing. See the <a href="@pathauto-help">Pathauto help</a> for more details.', array('%token' => $token, '%raw_token' => $token . '-raw', '@pathauto-help' => url('admin/help/pathauto'))), 'error', FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a form element that should have an numeric value.
|
||||
*/
|
||||
function _pathauto_validate_numeric_element($element, &$form_state) {
|
||||
$value = $element['#value'];
|
||||
|
||||
if (!is_numeric($value)) {
|
||||
form_error($element, t('The field %name is not a valid number.', array('%name' => $element['#title'])));
|
||||
}
|
||||
elseif (isset($element['#max_value']) && $value > $element['#max_value']) {
|
||||
form_error($element, t('The field %name cannot be greater than @max.', array('%name' => $element['#title'], '@max' => $element['#max_value'])));
|
||||
}
|
||||
elseif (isset($element['#min_value']) && $value < $element['#min_value']) {
|
||||
form_error($element, t('The field %name cannot be less than @min.', array('%name' => $element['#title'], '@min' => $element['#min_value'])));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate pathauto_admin_settings form submissions.
|
||||
*/
|
||||
function pathauto_admin_settings_validate($form, &$form_state) {
|
||||
module_load_include('inc', 'pathauto');
|
||||
|
||||
// Perform a basic check for HTML characters in the strings to remove field.
|
||||
if (strip_tags($form_state['values']['pathauto_ignore_words']) != $form_state['values']['pathauto_ignore_words']) {
|
||||
form_set_error('pathauto_ignore_words', t('The <em>Strings to remove</em> field must not contain HTML. Make sure to disable any WYSIWYG editors for this field.'));
|
||||
}
|
||||
|
||||
// Validate that the separator is not set to be removed per http://drupal.org/node/184119
|
||||
// This isn't really all that bad so warn, but still allow them to save the value.
|
||||
$separator = $form_state['values']['pathauto_separator'];
|
||||
$punctuation = pathauto_punctuation_chars();
|
||||
foreach ($punctuation as $name => $details) {
|
||||
if ($details['value'] == $separator) {
|
||||
$action = $form_state['values']['pathauto_punctuation_' . $name];
|
||||
if ($action == 0) {
|
||||
drupal_set_message(t('You have configured the @name to be the separator and to be removed when encountered in strings. This can cause problems with your patterns and especially with the catpath and termpath patterns. You should probably set the action for @name to be "replace by separator"', array('@name' => $details['name'])), 'error');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; select certain alias types to delete.
|
||||
*/
|
||||
function pathauto_admin_delete() {
|
||||
/* TODO:
|
||||
1) all - DONE
|
||||
2) all node aliases - DONE
|
||||
4) all user aliases - DONE
|
||||
5) all taxonomy aliases - DONE
|
||||
6) by node type
|
||||
7) by taxonomy vocabulary
|
||||
8) no longer existing aliases (see http://drupal.org/node/128366 )
|
||||
9) where src like 'pattern' - DON'T DO
|
||||
10) where dst like 'pattern' - DON'T DO
|
||||
*/
|
||||
|
||||
$form['delete'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Choose aliases to delete'),
|
||||
'#collapsible' => FALSE,
|
||||
'#collapsed' => FALSE,
|
||||
);
|
||||
|
||||
// First we do the "all" case
|
||||
$total_count = db_result(db_query('SELECT count(1) FROM {url_alias}'));
|
||||
$form['delete']['all_aliases'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('All aliases'),
|
||||
'#default_value' => FALSE,
|
||||
'#description' => t('Delete all aliases. Number of aliases which will be deleted: %count.', array('%count' => $total_count)),
|
||||
);
|
||||
|
||||
// Next, iterate over an array of objects/alias types which can be deleted and provide checkboxes
|
||||
$objects = module_invoke_all('path_alias_types');
|
||||
foreach ($objects as $internal_name => $label) {
|
||||
$count = db_result(db_query("SELECT count(1) FROM {url_alias} WHERE src LIKE '%s%%'", $internal_name));
|
||||
$form['delete'][$internal_name] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $label, // This label is sent through t() in the hard coded function where it is defined
|
||||
'#default_value' => FALSE,
|
||||
'#description' => t('Delete aliases for all @label. Number of aliases which will be deleted: %count.', array('@label' => $label, '%count' => $count)),
|
||||
);
|
||||
}
|
||||
|
||||
// Warn them and give a button that shows we mean business
|
||||
$form['warning'] = array('#value' => '<p>' . t('<strong>Note:</strong> there is no confirmation. Be sure of your action before clicking the "Delete aliases now!" button.<br />You may want to make a backup of the database and/or the url_alias table prior to using this feature.') . '</p>');
|
||||
$form['buttons']['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Delete aliases now!'),
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process pathauto_admin_delete form submissions.
|
||||
*/
|
||||
function pathauto_admin_delete_submit($form, &$form_state) {
|
||||
foreach ($form_state['values'] as $key => $value) {
|
||||
if ($value) {
|
||||
if ($key === 'all_aliases') {
|
||||
db_query('DELETE FROM {url_alias}');
|
||||
drupal_set_message(t('All of your path aliases have been deleted.'));
|
||||
}
|
||||
$objects = module_invoke_all('path_alias_types');
|
||||
if (array_key_exists($key, $objects)) {
|
||||
db_query("DELETE FROM {url_alias} WHERE src LIKE '%s%%'", $key);
|
||||
drupal_set_message(t('All of your %type path aliases have been deleted.', array('%type' => $objects[$key])));
|
||||
}
|
||||
}
|
||||
}
|
||||
$form_state['redirect'] = 'admin/build/path/delete_bulk';
|
||||
}
|
21
modules/pathauto/pathauto.api.php
Normal file
21
modules/pathauto/pathauto.api.php
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Documentation for pathauto API.
|
||||
*
|
||||
* @see hook_token_info
|
||||
* @see hook_tokens
|
||||
*/
|
||||
|
||||
function hook_path_alias_types() {
|
||||
}
|
||||
|
||||
function hook_pathauto($op) {
|
||||
}
|
||||
|
||||
function hook_pathauto_bulkupdate() {
|
||||
}
|
||||
|
||||
function hook_pathauto_alias_alter(&$alias, $context) {
|
||||
}
|
752
modules/pathauto/pathauto.inc
Normal file
752
modules/pathauto/pathauto.inc
Normal file
|
@ -0,0 +1,752 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Miscellaneous functions for Pathauto.
|
||||
*
|
||||
* @ingroup pathauto
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check to see if there is already an alias pointing to a different item.
|
||||
*
|
||||
* @param $alias
|
||||
* A string alias.
|
||||
* @param $source
|
||||
* A string that is the internal path.
|
||||
* @param $language
|
||||
* A string indicating the path's language.
|
||||
* @return
|
||||
* TRUE if an alias exists, FALSE if not.
|
||||
*/
|
||||
function _pathauto_alias_exists($alias, $source, $language = '') {
|
||||
$pid = db_result(db_query_range("SELECT pid FROM {url_alias} WHERE src <> '%s' AND dst = '%s' AND language IN ('%s', '') ORDER BY language DESC, pid DESC", $source, $alias, $language, 0, 1));
|
||||
|
||||
if (module_exists('path_redirect') && function_exists('path_redirect_delete_multiple')) {
|
||||
// Delete from path_redirect the exact same alias to the same node.
|
||||
path_redirect_delete_multiple(NULL, array('source' => $alias, 'redirect' => $source));
|
||||
|
||||
// If there still is this alias used in path_redirect, then create a different alias.
|
||||
$redirects = path_redirect_load_multiple(NULL, array('source' => $alias));
|
||||
}
|
||||
|
||||
if ($pid || !empty($redirects)) {
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches an existing URL alias given a path and optional language.
|
||||
*
|
||||
* @param $source
|
||||
* An internal Drupal path.
|
||||
* @param $language
|
||||
* An optional language code to look up the path in.
|
||||
* @return
|
||||
* FALSE if no alias was found or an associative array containing the
|
||||
* following keys:
|
||||
* - pid: Unique path alias identifier.
|
||||
* - alias: The URL alias.
|
||||
*/
|
||||
function _pathauto_existing_alias_data($source, $language = '') {
|
||||
return db_fetch_array(db_query_range("SELECT pid, dst AS alias, language FROM {url_alias} WHERE src = '%s' AND language IN ('%s', '') ORDER BY language DESC, pid DESC", $source, $language, 0, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up a string segment to be used in an URL alias.
|
||||
*
|
||||
* Performs the following possible alterations:
|
||||
* - Remove all HTML tags.
|
||||
* - Process the string through the transliteration module.
|
||||
* - Replace or remove punctuation with the separator character.
|
||||
* - Remove back-slashes.
|
||||
* - Replace non-ascii and non-numeric characters with the separator.
|
||||
* - Remove common words.
|
||||
* - Replace whitespace with the separator character.
|
||||
* - Trim duplicate, leading, and trailing separators.
|
||||
* - Convert to lower-case.
|
||||
* - Shorten to a desired length and logical position based on word boundaries.
|
||||
*
|
||||
* This function should *not* be called on URL alias or path strings because it
|
||||
* is assumed that they are already clean.
|
||||
*
|
||||
* @param $string
|
||||
* A string to clean.
|
||||
* @return
|
||||
* The cleaned string.
|
||||
*/
|
||||
function pathauto_cleanstring($string) {
|
||||
static $strings = array();
|
||||
|
||||
// Empty strings do not need any proccessing.
|
||||
if ($string === '' || $string === NULL) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Check if the string has already been processed, and if so return the
|
||||
// cached result.
|
||||
if (isset($strings[$string])) {
|
||||
return $strings[$string];
|
||||
}
|
||||
|
||||
// Remove all HTML tags from the string.
|
||||
$output = strip_tags(decode_entities($string));
|
||||
|
||||
// Optionally remove accents and transliterate
|
||||
if (variable_get('pathauto_transliterate', FALSE)) {
|
||||
static $translations;
|
||||
|
||||
if (!isset($translations)) {
|
||||
$translations = FALSE;
|
||||
if ($file = _pathauto_get_i18n_file()) {
|
||||
$translations = parse_ini_file($file);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($translations)) {
|
||||
$output = strtr($output, $translations);
|
||||
}
|
||||
}
|
||||
|
||||
// Replace or drop punctuation based on user settings
|
||||
$separator = variable_get('pathauto_separator', '-');
|
||||
$punctuation = pathauto_punctuation_chars();
|
||||
foreach ($punctuation as $name => $details) {
|
||||
$action = variable_get('pathauto_punctuation_'. $name, 0);
|
||||
// 2 is the action for "do nothing" with the punctuation
|
||||
if ($action != 2) {
|
||||
// Slightly tricky inline if which either replaces with the separator or nothing
|
||||
$output = str_replace($details['value'], ($action ? $separator : ''), $output);
|
||||
}
|
||||
}
|
||||
|
||||
// Reduce strings to letters and numbers
|
||||
if (variable_get('pathauto_reduce_ascii', FALSE)) {
|
||||
$pattern = '/[^a-zA-Z0-9\/]+/';
|
||||
$output = preg_replace($pattern, $separator, $output);
|
||||
}
|
||||
|
||||
// Calculate and statically cache the ignored words regex expression.
|
||||
static $ignore_words_regex;
|
||||
if (!isset($ignore_words_regex)) {
|
||||
$ignore_words = array(
|
||||
'a', 'an', 'as', 'at', 'before', 'but', 'by', 'for', 'from', 'is', 'in',
|
||||
'into', 'like', 'of', 'off', 'on', 'onto', 'per', 'since', 'than', 'the',
|
||||
'this', 'that', 'to', 'up', 'via', 'with',
|
||||
);
|
||||
$ignore_words = variable_get('pathauto_ignore_words', $ignore_words);
|
||||
$ignore_words_regex = preg_replace(array('/^[,\s]+|[,\s]+$/', '/[,\s]+/'), array('', '\b|\b'), $ignore_words);
|
||||
if ($ignore_words_regex) {
|
||||
$ignore_words_regex = '\b' . $ignore_words_regex . '\b';
|
||||
}
|
||||
}
|
||||
|
||||
// Get rid of words that are on the ignore list
|
||||
if ($ignore_words_regex) {
|
||||
if (function_exists('mb_eregi_replace')) {
|
||||
$words_removed = mb_eregi_replace($ignore_words_regex, '', $output);
|
||||
}
|
||||
else {
|
||||
$words_removed = preg_replace("/$ignore_words_regex/i", '', $output);
|
||||
}
|
||||
if (drupal_strlen(trim($words_removed)) > 0) {
|
||||
$output = $words_removed;
|
||||
}
|
||||
}
|
||||
|
||||
// Always replace whitespace with the separator.
|
||||
$output = preg_replace('/\s+/', $separator, $output);
|
||||
|
||||
// Trim duplicates and remove trailing and leading separators.
|
||||
$output = _pathauto_clean_separators($output);
|
||||
|
||||
// Optionally convert to lower case.
|
||||
if (variable_get('pathauto_case', 1)) {
|
||||
$output = drupal_strtolower($output);
|
||||
}
|
||||
|
||||
// Enforce the maximum component length.
|
||||
$maxlength = min(variable_get('pathauto_max_component_length', 100), _pathauto_get_schema_alias_maxlength());
|
||||
$output = drupal_substr($output, 0, $maxlength);
|
||||
|
||||
// Cache this result in the static array.
|
||||
$strings[$string] = $output;
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims duplicate, leading, and trailing separators from a string.
|
||||
*
|
||||
* @param $string
|
||||
* The string to clean path separators from.
|
||||
* @param $separator
|
||||
* The path separator to use when cleaning.
|
||||
* @return
|
||||
* The cleaned version of the string.
|
||||
*
|
||||
* @see pathauto_cleanstring()
|
||||
* @see pathauto_clean_alias()
|
||||
*/
|
||||
function _pathauto_clean_separators($string, $separator = NULL) {
|
||||
$output = $string;
|
||||
|
||||
if (!isset($separator)) {
|
||||
$separator = variable_get('pathauto_separator', '-');
|
||||
}
|
||||
|
||||
// Clean duplicate or trailing separators.
|
||||
if (strlen($separator)) {
|
||||
// Escape the separator.
|
||||
$seppattern = preg_quote($separator, '/');
|
||||
|
||||
// Trim any leading or trailing separators.
|
||||
$output = preg_replace("/^$seppattern+|$seppattern+$/", '', $output);
|
||||
|
||||
// Replace trailing separators around slashes.
|
||||
if ($separator !== '/') {
|
||||
$output = preg_replace("/$seppattern+\/|\/$seppattern+/", "/", $output);
|
||||
}
|
||||
|
||||
// Replace multiple separators with a single one.
|
||||
$output = preg_replace("/$seppattern+/", $separator, $output);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up an URL alias.
|
||||
*
|
||||
* Performs the following alterations:
|
||||
* - Trim duplicate, leading, and trailing back-slashes.
|
||||
* - Trim duplicate, leading, and trailing separators.
|
||||
* - Shorten to a desired length and logical position based on word boundaries.
|
||||
*
|
||||
* @param $alias
|
||||
* A string with the URL alias to clean up.
|
||||
* @return
|
||||
* The cleaned URL alias.
|
||||
*/
|
||||
function pathauto_clean_alias($alias) {
|
||||
$output = $alias;
|
||||
|
||||
// Trim duplicate, leading, and trailing back-slashes.
|
||||
$output = _pathauto_clean_separators($output, '/');
|
||||
|
||||
// Trim duplicate, leading, and trailing separators.
|
||||
$output = _pathauto_clean_separators($output);
|
||||
|
||||
// Enforce the maximum length.
|
||||
$separator = variable_get('pathauto_separator', '-');
|
||||
$maxlength = min(variable_get('pathauto_max_length', 100), _pathauto_get_schema_alias_maxlength());
|
||||
$output = drupal_substr($output, 0, $maxlength);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply patterns to create an alias.
|
||||
*
|
||||
* @param $module
|
||||
* The name of your module (e.g., 'node').
|
||||
* @param $op
|
||||
* Operation being performed on the content being aliased
|
||||
* ('insert', 'update', 'return', or 'bulkupdate').
|
||||
* @param $placeholders
|
||||
* An array whose keys consist of the translated placeholders
|
||||
* which appear in patterns (e.g., t('[title]')) and values are the
|
||||
* actual values to be substituted into the pattern (e.g., $node->title).
|
||||
* @param $source
|
||||
* An internal Drupal path to be aliased.
|
||||
* @param $entity_id
|
||||
* The entity ID (node ID, user ID, etc.).
|
||||
* @param $type
|
||||
* For modules which provided pattern items in hook_pathauto(),
|
||||
* the relevant identifier for the specific item to be aliased
|
||||
* (e.g., $node->type).
|
||||
* @param $language
|
||||
* A string specify the path's language.
|
||||
* @return
|
||||
* The alias that was created.
|
||||
*
|
||||
* @see _pathauto_set_alias()
|
||||
* @see pathauto_get_placeholders()
|
||||
*/
|
||||
function pathauto_create_alias($module, $op, $placeholders, $source, $entity_id, $type = NULL, $language = '') {
|
||||
// Retrieve and apply the pattern for this content type
|
||||
if (!empty($type)) {
|
||||
$pattern = trim(variable_get("pathauto_{$module}_{$type}_{$language}_pattern", ''));
|
||||
if (empty($pattern)) {
|
||||
$pattern = trim(variable_get("pathauto_{$module}_{$type}_pattern", ''));
|
||||
}
|
||||
}
|
||||
if (empty($pattern)) {
|
||||
$pattern = trim(variable_get("pathauto_{$module}_pattern", ''));
|
||||
}
|
||||
// No pattern? Do nothing (otherwise we may blow away existing aliases...)
|
||||
if (empty($pattern)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($module == 'taxonomy') {
|
||||
// Get proper path for term.
|
||||
$term_path = taxonomy_term_path(taxonomy_get_term($entity_id));
|
||||
if ($term_path != $source) {
|
||||
// Quietly alias 'taxonomy/term/[tid]' with proper path for term.
|
||||
$update_data = _pathauto_existing_alias_data($source, $language);
|
||||
_pathauto_set_alias($source, $term_path, $module, $entity_id, $update_data['pid'], FALSE, $update_data['old_alias'], $language);
|
||||
// Set $source as proper path.
|
||||
$source = $term_path;
|
||||
}
|
||||
}
|
||||
|
||||
// Special handling when updating an item which is already aliased.
|
||||
$existing_alias = NULL;
|
||||
if ($op == 'update' || $op == 'bulkupdate') {
|
||||
if ($existing_alias = _pathauto_existing_alias_data($source, $language)) {
|
||||
switch (variable_get('pathauto_update_action', 2)) {
|
||||
case 0:
|
||||
// If an alias already exists, and the update action is set to do nothing,
|
||||
// then gosh-darn it, do nothing.
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Replace the placeholders with the values provided by the module.
|
||||
$alias = str_replace($placeholders['tokens'], $placeholders['values'], $pattern);
|
||||
|
||||
// Check if the token replacement has not actually replaced any values. If
|
||||
// that is the case, then stop because we should not generate an alias.
|
||||
// @see token_scan()
|
||||
$pattern_tokens_removed = preg_replace('/\[([^\s]+?)\]/', '', $pattern);
|
||||
if ($alias === $pattern_tokens_removed) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$alias = pathauto_clean_alias($alias);
|
||||
|
||||
// Allow other modules to alter the alias.
|
||||
$context = array(
|
||||
'module' => $module,
|
||||
'op' => $op,
|
||||
'source' => $source,
|
||||
'entity_id' => $entity_id,
|
||||
'type' => $type,
|
||||
'language' => $language,
|
||||
'pattern' => $pattern,
|
||||
);
|
||||
drupal_alter('pathauto_alias', $alias, $context);
|
||||
|
||||
// If we have arrived at an empty string, discontinue.
|
||||
if (!drupal_strlen($alias)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// If the alias already exists, generate a new, hopefully unique, variant
|
||||
if (_pathauto_alias_exists($alias, $source, $language)) {
|
||||
$maxlength = min(variable_get('pathauto_max_length', 100), _pathauto_get_schema_alias_maxlength());
|
||||
$separator = variable_get('pathauto_separator', '-');
|
||||
$original_alias = $alias;
|
||||
|
||||
$i = 0;
|
||||
do {
|
||||
// Append an incrementing numeric suffix until we find a unique alias.
|
||||
$unique_suffix = $separator . $i;
|
||||
$alias = drupal_substr($original_alias, 0, $maxlength - drupal_strlen($unique_suffix, TRUE)) . $unique_suffix;
|
||||
$i++;
|
||||
} while (_pathauto_alias_exists($alias, $source, $language));
|
||||
|
||||
// Alert the user why this happened.
|
||||
_pathauto_verbose(t('The automatically generated alias %original_alias conflicted with an existing alias. Alias changed to %alias.', array(
|
||||
'%original_alias' => $original_alias,
|
||||
'%alias' => $alias,
|
||||
)), $op);
|
||||
}
|
||||
|
||||
// Return the generated alias if requested.
|
||||
if ($op == 'return') {
|
||||
return $alias;
|
||||
}
|
||||
|
||||
// Build the new path alias array and send it off to be created.
|
||||
$path = array(
|
||||
'source' => $source,
|
||||
'alias' => $alias,
|
||||
'language' => $language,
|
||||
);
|
||||
$success = _pathauto_set_alias($path, $existing_alias, $op);
|
||||
|
||||
// Also create a related feed alias if requested and supported.
|
||||
$feedappend = trim(variable_get('pathauto_' . $module . '_applytofeeds', ''));
|
||||
if (drupal_strlen($feedappend)) {
|
||||
// For forums and taxonomies, the source doesn't always form the base of the RSS feed (i.e. image galleries)
|
||||
if ($module == 'taxonomy' || $module == 'forum' && !empty($entity_id)) {
|
||||
$source = "taxonomy/term/{$entity_id}";
|
||||
}
|
||||
|
||||
// Build the feed path alias array and send it off to be created.
|
||||
$path = array(
|
||||
'source' => "$source/$feedappend",
|
||||
'alias' => "$alias/feed",
|
||||
'language' => $language,
|
||||
);
|
||||
$existing_alias = _pathauto_existing_alias_data($path['source'], $path['language']);
|
||||
_pathauto_set_alias($path, $existing_alias, $op);
|
||||
}
|
||||
|
||||
return $success ? $alias : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if the given path is a valid menu callback.
|
||||
*
|
||||
* Taken from menu_execute_active_handler().
|
||||
*
|
||||
* @param $path
|
||||
* A string containing a relative path.
|
||||
* @return
|
||||
* TRUE if the path already exists.
|
||||
*/
|
||||
function _pathauto_path_is_callback($path) {
|
||||
$menu = menu_get_item($path);
|
||||
if (isset($menu['path']) && $menu['path'] == $path) {
|
||||
return TRUE;
|
||||
}
|
||||
elseif (is_file('./' . $path) || is_dir('./' . $path)) {
|
||||
// Do not allow existing files or directories to get assigned an automatic
|
||||
// alias. Note that we do not need to use is_link() to check for symbolic
|
||||
// links since this returns TRUE for either is_file() or is_dir() already.
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private function for Pathauto to create an alias.
|
||||
*
|
||||
* @param $path
|
||||
* An associative array containing the following keys:
|
||||
* - source: The internal system path.
|
||||
* - alias: The URL alias.
|
||||
* - pid: (optional) Unique path alias identifier.
|
||||
* - language: (optional) The language of the alias.
|
||||
* @param $existing_alias
|
||||
* (optional) An associative array of the existing path alias.
|
||||
* @param $op
|
||||
* An optional string with the operation being performed.
|
||||
* @return
|
||||
* TRUE if the path was saved, or NULL otherwise.
|
||||
*
|
||||
* @see path_set_alias()
|
||||
*/
|
||||
function _pathauto_set_alias($path, $existing_alias = NULL, $op = NULL) {
|
||||
$verbose = _pathauto_verbose(NULL, $op);
|
||||
|
||||
// Alert users that an existing callback cannot be overridden automatically
|
||||
if (_pathauto_path_is_callback($path['alias'])) {
|
||||
if ($verbose) {
|
||||
_pathauto_verbose(t('Ignoring alias %alias due to existing path conflict.', array('%alias' => $path['alias'])));
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Alert users if they are trying to create an alias that is the same as the internal path
|
||||
if ($path['source'] == $path['alias']) {
|
||||
if ($verbose) {
|
||||
_pathauto_verbose(t('Ignoring alias %alias because it is the same as the internal path.', array('%alias' => $path['alias'])));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$path += array(
|
||||
'pid' => NULL,
|
||||
'language' => '',
|
||||
);
|
||||
|
||||
// Skip replacing the current alias with an identical alias
|
||||
if (empty($existing_alias) || $existing_alias['alias'] != $path['alias']) {
|
||||
// If there is already an alias, respect some update actions.
|
||||
if (!empty($existing_alias)) {
|
||||
switch (variable_get('pathauto_update_action', 2)) {
|
||||
case 0:
|
||||
// Do not create the alias.
|
||||
return;
|
||||
case 1:
|
||||
// Create a new alias instead of overwriting the existing by leaving
|
||||
// $path['pid'] empty.
|
||||
break;
|
||||
case 3:
|
||||
// Create a redirect
|
||||
if (module_exists('path_redirect') && function_exists('path_redirect_save')) {
|
||||
$redirect = array(
|
||||
'source' => $existing_alias['alias'],
|
||||
'language' => $existing_alias['language'],
|
||||
'redirect' => $path['source'],
|
||||
);
|
||||
path_redirect_save($redirect);
|
||||
}
|
||||
// Intentionally fall through to the next condition since we still
|
||||
// want to replace the existing alias.
|
||||
case 2:
|
||||
// Both the redirect and delete actions should overwrite the existing
|
||||
// alias.
|
||||
$path['pid'] = $existing_alias['pid'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Save the path array.
|
||||
path_set_alias($path['source'], $path['alias'], $path['pid'], $path['language']);
|
||||
|
||||
if ($verbose) {
|
||||
if (!empty($redirect)) {
|
||||
_pathauto_verbose(t('Created new alias %alias for %source, replacing %old_alias. %old_alias now redirects to %alias.', array('%alias' => $path['alias'], '%source' => $path['source'], '%old_alias' => $existing_alias['alias'])));
|
||||
}
|
||||
elseif (!empty($existing_alias['pid'])) {
|
||||
_pathauto_verbose(t('Created new alias %alias for %source, replacing %old_alias.', array('%alias' => $path['alias'], '%source' => $path['source'], '%old_alias' => $existing_alias['alias'])));
|
||||
}
|
||||
else {
|
||||
_pathauto_verbose(t('Created new alias %alias for %source.', array('%alias' => $path['alias'], '%source' => $path['source'])));
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output a helpful message if verbose output is enabled.
|
||||
*
|
||||
* Verbose output is only enabled when:
|
||||
* - The 'pathauto_verbose' setting is enabled.
|
||||
* - The current user has the 'notify of path changes' permission.
|
||||
* - The $op parameter is anything but 'bulkupdate' or 'return'.
|
||||
*
|
||||
* @param $message
|
||||
* An optional string of the verbose message to display. This string should
|
||||
* already be run through t().
|
||||
* @param $op
|
||||
* An optional string with the operation being performed.
|
||||
* @return
|
||||
* TRUE if verbose output is enabled, or FALSE otherwise.
|
||||
*/
|
||||
function _pathauto_verbose($message = NULL, $op = NULL) {
|
||||
static $verbose;
|
||||
|
||||
if (!isset($verbose)) {
|
||||
$verbose = variable_get('pathauto_verbose', FALSE) && user_access('notify of path changes');
|
||||
}
|
||||
|
||||
if (!$verbose || (isset($op) && in_array($op, array('bulkupdate', 'return')))) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ($message) {
|
||||
drupal_set_message($message);
|
||||
}
|
||||
|
||||
return $verbose;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generalized function to get tokens across all Pathauto types.
|
||||
*
|
||||
* @param $object
|
||||
* A user, node, or category object.
|
||||
* @return
|
||||
* Tokens for that object formatted in the way that
|
||||
* Pathauto expects to see them.
|
||||
*/
|
||||
function pathauto_get_placeholders($type, $object) {
|
||||
if (!function_exists('token_get_values')) {
|
||||
// TODO at some point try removing this and see if install profiles have problems again.
|
||||
watchdog('Pathauto', 'It appears that you have installed Pathauto, which depends on token, but token is either not installed or not installed properly.');
|
||||
return array('tokens' => array(), 'values' => array());
|
||||
}
|
||||
|
||||
$options = array('pathauto' => TRUE);
|
||||
$full = token_get_values($type, $object, TRUE, $options);
|
||||
$tokens = token_prepare_tokens($full->tokens);
|
||||
$values = pathauto_clean_token_values($full, $options);
|
||||
return array('tokens' => $tokens, 'values' => $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean tokens so they are URL friendly.
|
||||
*
|
||||
* @param $full
|
||||
* An array of token values from token_get_values() that need to be "cleaned"
|
||||
* for use in the URL.
|
||||
*
|
||||
* @return
|
||||
* An array of the cleaned tokens.
|
||||
*/
|
||||
function pathauto_clean_token_values($full, $options = array()) {
|
||||
$replacements = array();
|
||||
foreach ($full->values as $key => $value) {
|
||||
$token = $full->tokens[$key];
|
||||
if (strpos($token, 'path') !== FALSE && is_array($value) && !empty($options['pathauto'])) {
|
||||
// If the token name contains 'path', the token value is an array, and
|
||||
// the 'pathauto' option was passed to token_get_values(), then the token
|
||||
// should have each segment cleaned, and then glued back together to
|
||||
// construct a value resembling an URL.
|
||||
$segments = array_map('pathauto_cleanstring', $value);
|
||||
$replacements[$token] = implode('/', $segments);
|
||||
}
|
||||
elseif (preg_match('/(path|alias|url|url-brief)(-raw)?$/', $token)) {
|
||||
// Token name matches an URL-type name and should be left raw.
|
||||
$replacements[$token] = $value;
|
||||
}
|
||||
else {
|
||||
// Token is not an URL, so it should have its value cleaned.
|
||||
$replacements[$token] = pathauto_cleanstring($value);
|
||||
}
|
||||
}
|
||||
return $replacements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of arrays for punctuation values.
|
||||
*
|
||||
* Returns an array of arrays for punctuation values keyed by a name, including
|
||||
* the value and a textual description.
|
||||
* Can and should be expanded to include "all" non text punctuation values.
|
||||
*
|
||||
* @return
|
||||
* An array of arrays for punctuation values keyed by a name, including the
|
||||
* value and a textual description.
|
||||
*/
|
||||
function pathauto_punctuation_chars() {
|
||||
static $punctuation;
|
||||
|
||||
if (!isset($punctuation)) {
|
||||
$punctuation = array();
|
||||
$punctuation['double_quotes'] = array('value' => '"', 'name' => t('Double quotes "'));
|
||||
$punctuation['quotes'] = array('value' => "'", 'name' => t("Single quotes (apostrophe) '"));
|
||||
$punctuation['backtick'] = array('value' => '`', 'name' => t('Back tick `'));
|
||||
$punctuation['comma'] = array('value' => ',', 'name' => t('Comma ,'));
|
||||
$punctuation['period'] = array('value' => '.', 'name' => t('Period .'));
|
||||
$punctuation['hyphen'] = array('value' => '-', 'name' => t('Hyphen -'));
|
||||
$punctuation['underscore'] = array('value' => '_', 'name' => t('Underscore _'));
|
||||
$punctuation['colon'] = array('value' => ':', 'name' => t('Colon :'));
|
||||
$punctuation['semicolon'] = array('value' => ';', 'name' => t('Semicolon ;'));
|
||||
$punctuation['pipe'] = array('value' => '|', 'name' => t('Pipe |'));
|
||||
$punctuation['left_curly'] = array('value' => '{', 'name' => t('Left curly bracket {'));
|
||||
$punctuation['left_square'] = array('value' => '[', 'name' => t('Left square bracket ['));
|
||||
$punctuation['right_curly'] = array('value' => '}', 'name' => t('Right curly bracket }'));
|
||||
$punctuation['right_square'] = array('value' => ']', 'name' => t('Right square bracket ]'));
|
||||
$punctuation['plus'] = array('value' => '+', 'name' => t('Plus +'));
|
||||
$punctuation['equal'] = array('value' => '=', 'name' => t('Equal ='));
|
||||
$punctuation['asterisk'] = array('value' => '*', 'name' => t('Asterisk *'));
|
||||
$punctuation['ampersand'] = array('value' => '&', 'name' => t('Ampersand &'));
|
||||
$punctuation['percent'] = array('value' => '%', 'name' => t('Percent %'));
|
||||
$punctuation['caret'] = array('value' => '^', 'name' => t('Caret ^'));
|
||||
$punctuation['dollar'] = array('value' => '$', 'name' => t('Dollar $'));
|
||||
$punctuation['hash'] = array('value' => '#', 'name' => t('Hash #'));
|
||||
$punctuation['at'] = array('value' => '@', 'name' => t('At @'));
|
||||
$punctuation['exclamation'] = array('value' => '!', 'name' => t('Exclamation !'));
|
||||
$punctuation['tilde'] = array('value' => '~', 'name' => t('Tilde ~'));
|
||||
$punctuation['left_parenthesis'] = array('value' => '(', 'name' => t('Left parenthesis ('));
|
||||
$punctuation['right_parenthesis'] = array('value' => ')', 'name' => t('Right parenthesis )'));
|
||||
$punctuation['question_mark'] = array('value' => '?', 'name' => t('Question mark ?'));
|
||||
$punctuation['less_than'] = array('value' => '<', 'name' => t('Less than <'));
|
||||
$punctuation['greater_than'] = array('value' => '>', 'name' => t('Greater than >'));
|
||||
$punctuation['slash'] = array('value' => '/', 'name' => t('Slash /'));
|
||||
$punctuation['back_slash'] = array('value' => '\\', 'name' => t('Backslash \\'));
|
||||
}
|
||||
|
||||
return $punctuation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the maximum length of the {url_alias}.dst field from the schema.
|
||||
*
|
||||
* @return
|
||||
* An integer of the maximum URL alias length allowed by the database.
|
||||
*/
|
||||
function _pathauto_get_schema_alias_maxlength() {
|
||||
static $maxlength;
|
||||
if (!isset($maxlength)) {
|
||||
$schema = drupal_get_schema('url_alias');
|
||||
$maxlength = $schema['fields']['dst']['length'];
|
||||
}
|
||||
return $maxlength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch an array of non-raw tokens that have matching raw tokens.
|
||||
*
|
||||
* @return
|
||||
* An array of tokens.
|
||||
*/
|
||||
function _pathauto_get_raw_tokens() {
|
||||
static $raw_tokens;
|
||||
|
||||
if (!isset($raw_tokens)) {
|
||||
$raw_tokens = array();
|
||||
|
||||
// Build one big list of tokens.
|
||||
foreach (token_get_list('all') as $tokens) {
|
||||
$raw_tokens = array_merge($raw_tokens, array_keys($tokens));
|
||||
}
|
||||
|
||||
// Filter out any tokens without -raw as a suffix.
|
||||
foreach ($raw_tokens as $index => $token) {
|
||||
if (substr($token, -4) !== '-raw') {
|
||||
unset($raw_tokens[$index]);
|
||||
}
|
||||
}
|
||||
|
||||
array_unique($raw_tokens);
|
||||
}
|
||||
|
||||
return $raw_tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the possible paths of the i18n-ascii.txt transliteration file.
|
||||
*
|
||||
* @return
|
||||
* An array of possible file paths.
|
||||
*/
|
||||
function _pathauto_get_i18n_possible_files() {
|
||||
$file = 'i18n-ascii.txt';
|
||||
$files = array(
|
||||
conf_path() . '/' . $file,
|
||||
"sites/all/$file",
|
||||
drupal_get_path('module', 'pathauto') . '/' . $file,
|
||||
);
|
||||
// Always prefer $conf['pathauto_i18n_file'] if defined.
|
||||
if ($conf_file = variable_get('pathauto_i18n_file', '')) {
|
||||
array_unshift($files, $conf_file);
|
||||
}
|
||||
return $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the path to the i18n-ascii.txt transliteration file
|
||||
*
|
||||
* @return
|
||||
* The complete path or FALSE if not found in any of the possible paths.
|
||||
*
|
||||
* @see _pathauto_get_i18n_possible_files()
|
||||
*/
|
||||
function _pathauto_get_i18n_file() {
|
||||
static $i18n_file;
|
||||
|
||||
if (!isset($i18n_file)) {
|
||||
$i18n_file = FALSE;
|
||||
foreach (_pathauto_get_i18n_possible_files() as $file) {
|
||||
if (file_exists($file)) {
|
||||
$i18n_file = $file;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $i18n_file;
|
||||
}
|
13
modules/pathauto/pathauto.info
Normal file
13
modules/pathauto/pathauto.info
Normal file
|
@ -0,0 +1,13 @@
|
|||
name = Pathauto
|
||||
description = Provides a mechanism for modules to automatically generate aliases for the content they manage.
|
||||
dependencies[] = path
|
||||
dependencies[] = token
|
||||
core = 6.x
|
||||
recommends[] = path_redirect
|
||||
|
||||
; Information added by drupal.org packaging script on 2011-10-31
|
||||
version = "6.x-1.6"
|
||||
core = "6.x"
|
||||
project = "pathauto"
|
||||
datestamp = "1320076535"
|
||||
|
109
modules/pathauto/pathauto.install
Normal file
109
modules/pathauto/pathauto.install
Normal file
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Install, update, and uninstall functions for Pathauto.
|
||||
*
|
||||
* @ingroup pathauto
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implementation of hook_install().
|
||||
*/
|
||||
function pathauto_install() {
|
||||
// Check to see if taxonomy module is enabled before we set those variables
|
||||
if (module_exists('taxonomy')) {
|
||||
variable_set('pathauto_modulelist', array('node', 'user', 'taxonomy'));
|
||||
variable_set('pathauto_taxonomy_supportsfeeds', '0/feed');
|
||||
variable_set('pathauto_taxonomy_pattern', 'category/[vocab-raw]/[catpath-raw]');
|
||||
variable_set('pathauto_taxonomy_bulkupdate', FALSE);
|
||||
variable_set('pathauto_taxonomy_applytofeeds', FALSE);
|
||||
variable_set('pathauto_taxonomy_2_pattern', '');
|
||||
variable_set('pathauto_taxonomy_1_pattern', '');
|
||||
}
|
||||
else {
|
||||
// Node and user are required so we don't have to check
|
||||
variable_set('pathauto_modulelist', array('node', 'user'));
|
||||
}
|
||||
// Set the rest of the pathauto default variables
|
||||
variable_set('pathauto_ignore_words', 'a,an,as,at,before,but,by,for,from,is,in,into,like,of,off,on,onto,per,since,than,the,this,that,to,up,via,with');
|
||||
variable_set('pathauto_indexaliases', FALSE);
|
||||
variable_set('pathauto_indexaliases_bulkupdate', FALSE);
|
||||
variable_set('pathauto_max_component_length', '100');
|
||||
variable_set('pathauto_max_length', '100');
|
||||
variable_set('pathauto_node_bulkupdate', FALSE);
|
||||
variable_set('pathauto_node_forum_pattern', '');
|
||||
variable_set('pathauto_node_image_pattern', '');
|
||||
variable_set('pathauto_node_page_pattern', '');
|
||||
variable_set('pathauto_node_pattern', 'content/[title-raw]');
|
||||
variable_set('pathauto_node_story_pattern', '');
|
||||
variable_set('pathauto_punctuation_quotes', 0);
|
||||
variable_set('pathauto_separator', '-');
|
||||
variable_set('pathauto_update_action', '2');
|
||||
variable_set('pathauto_user_bulkupdate', FALSE);
|
||||
variable_set('pathauto_user_pattern', 'users/[user-raw]');
|
||||
variable_set('pathauto_user_supportsfeeds', NULL);
|
||||
variable_set('pathauto_verbose', FALSE);
|
||||
variable_set('pathauto_node_applytofeeds', '');
|
||||
|
||||
// Make sure we "replace hyphen with separator" by default
|
||||
variable_set('pathauto_punctuation_hyphen', 1); // 1 is replace
|
||||
|
||||
// Set the weight to 1
|
||||
db_query("UPDATE {system} SET weight = 1 WHERE name = 'pathauto'");
|
||||
|
||||
// Clear the cache to get these to take effect.
|
||||
cache_clear_all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_uninstall().
|
||||
*/
|
||||
function pathauto_uninstall() {
|
||||
// Delete all the pathauto variables and then clear the variable cache
|
||||
db_query("DELETE FROM {variable} WHERE name LIKE 'pathauto_%'");
|
||||
cache_clear_all('variables', 'cache');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the weight a little heavier to allow taxonomy to do its work.
|
||||
*/
|
||||
function pathauto_update_1() {
|
||||
$ret = array();
|
||||
$ret[] = update_sql("UPDATE {system} SET weight = 1 WHERE name = 'pathauto'");
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* pathauto_update_4 was a backport of a feature which is in core of Drupal 6
|
||||
* hence it is removed from the 6.x branch even though the goal is to support
|
||||
* Pathauto 5.x-1.x -> 6.x-2.x upgrades.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Delete the pathauto_node_supportsfeeds.
|
||||
*/
|
||||
function pathauto_update_3() {
|
||||
// Do nothing, this update was a mistake
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* New style naming for the punctuation chars.
|
||||
*/
|
||||
function pathauto_update_4() {
|
||||
variable_set('pathauto_punctuation_quotes', variable_get('pathauto_quotes', 0));
|
||||
variable_del('pathauto_quotes');
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the url_alias_extra table which wasn't used.
|
||||
*/
|
||||
function pathauto_update_7() {
|
||||
$ret = array();
|
||||
if (db_table_exists('url_alias_extra')) {
|
||||
db_drop_table($ret, 'url_alias_extra');
|
||||
}
|
||||
return $ret;
|
||||
}
|
39
modules/pathauto/pathauto.js
Normal file
39
modules/pathauto/pathauto.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
if (Drupal.jsEnabled) {
|
||||
$(document).ready(function() {
|
||||
if ($("#edit-pathauto-perform-alias").size() && $("#edit-pathauto-perform-alias").attr("checked")) {
|
||||
// Disable input and hide its description.
|
||||
$("#edit-path").attr("disabled","disabled");
|
||||
$("#edit-path-wrapper > div.description").hide(0);
|
||||
}
|
||||
$("#edit-pathauto-perform-alias").bind("click", function() {
|
||||
if ($("#edit-pathauto-perform-alias").attr("checked")) {
|
||||
// Auto-alias checked; disable input.
|
||||
$("#edit-path").attr("disabled","disabled");
|
||||
$("#edit-path-wrapper > div[class=description]").slideUp('fast');
|
||||
}
|
||||
else {
|
||||
// Auto-alias unchecked; enable input.
|
||||
$("#edit-path").removeAttr("disabled");
|
||||
$("#edit-path")[0].focus();
|
||||
$("#edit-path-wrapper > div[class=description]").slideDown('fast');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Drupal.verticalTabs = Drupal.verticalTabs || {};
|
||||
|
||||
Drupal.verticalTabs.path = function() {
|
||||
var path = $('#edit-path').val();
|
||||
var automatic = $('#edit-pathauto-perform-alias').attr('checked');
|
||||
|
||||
if (automatic) {
|
||||
return Drupal.t('Automatic alias');
|
||||
}
|
||||
if (path) {
|
||||
return Drupal.t('Alias: @alias', { '@alias': path });
|
||||
}
|
||||
else {
|
||||
return Drupal.t('No alias');
|
||||
}
|
||||
}
|
||||
}
|
656
modules/pathauto/pathauto.module
Normal file
656
modules/pathauto/pathauto.module
Normal file
|
@ -0,0 +1,656 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pathauto Pathauto: Automatically generates aliases for content
|
||||
*
|
||||
* The Pathauto module automatically generates path aliases for various kinds of
|
||||
* content (nodes, categories, users) without requiring the user to manually
|
||||
* specify the path alias. This allows you to get aliases like
|
||||
* /category/my-node-title.html instead of /node/123. The aliases are based upon
|
||||
* a "pattern" system which the administrator can control.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Main file for the Pathauto module, which automatically generates aliases for content.
|
||||
*
|
||||
* @ingroup pathauto
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_help().
|
||||
*/
|
||||
function pathauto_help($path, $arg) {
|
||||
switch ($path) {
|
||||
case 'admin/help#pathauto':
|
||||
$output = t('<p>Provides a mechanism for modules to automatically generate aliases for the content they manage.</p>
|
||||
<h2>Settings</h2>
|
||||
<p>The <strong>Maximum Alias Length</strong> and <strong>Maximum component length</strong> values
|
||||
default to 100 and have a limit of 128 from pathauto. This length is limited by the length of the dst
|
||||
column of the url_alias database table. The default database schema for this column is 128. If you
|
||||
set a length that is equal to that of the one set in the dst column it will cause problems in situations
|
||||
where the system needs to append additional words to the aliased URL. For example... URLs generated
|
||||
for feeds will have "/feed" added to the end. You should enter a value that is the length of the dst
|
||||
column minus the length of any strings that might get added to the end of the URL. The length of
|
||||
strings that might get added to the end of your URLs depends on which modules you have enabled and
|
||||
on your Pathauto settings. The recommended and default value is 100.</p>
|
||||
<p><strong>Raw Tokens</strong> In Pathauto it is appropriate to use the -raw form of tokens. Paths are
|
||||
sent through a filtering system which ensures that raw user content is filtered. Failure to use -raw
|
||||
tokens can cause problems with the Pathauto punctuation filtering system.</p>');
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_perm().
|
||||
*/
|
||||
function pathauto_perm() {
|
||||
return array(
|
||||
'administer pathauto',
|
||||
'notify of path changes',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_menu().
|
||||
*/
|
||||
function pathauto_menu() {
|
||||
$items['admin/build/path/pathauto'] = array(
|
||||
'title' => 'Automated alias settings',
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('pathauto_admin_settings'),
|
||||
'access arguments' => array('administer pathauto'),
|
||||
'type' => MENU_LOCAL_TASK,
|
||||
'weight' => 10,
|
||||
'file' => 'pathauto.admin.inc',
|
||||
);
|
||||
|
||||
$items['admin/build/path/delete_bulk'] = array(
|
||||
'title' => 'Delete aliases',
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('pathauto_admin_delete'),
|
||||
'access arguments' => array('administer url aliases'),
|
||||
'type' => MENU_LOCAL_TASK,
|
||||
'weight' => 30,
|
||||
'file' => 'pathauto.admin.inc',
|
||||
);
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include all Pathauto include files.
|
||||
*/
|
||||
function _pathauto_include() {
|
||||
module_load_include('inc', 'pathauto');
|
||||
module_load_include('inc', 'pathauto', 'pathauto_node');
|
||||
module_load_include('inc', 'pathauto', 'pathauto_taxonomy');
|
||||
module_load_include('inc', 'pathauto', 'pathauto_user');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_token_list().
|
||||
*/
|
||||
function pathauto_token_list($type = 'all') {
|
||||
$tokens = array();
|
||||
if (module_exists('taxonomy')) {
|
||||
if ($type == 'taxonomy' || $type == 'all') {
|
||||
$tokens['taxonomy']['catpath'] = t('As [cat], but including its supercategories separated by /.');
|
||||
$tokens['taxonomy']['catpath-raw'] = t('As [cat-raw], but including its supercategories separated by /.');
|
||||
$tokens['taxonomy']['catalias'] = t('The URL alias of the taxonomy term.');
|
||||
$tokens['taxonomy']['catalias-raw'] = t('The URL alias of the taxonomy term.');
|
||||
}
|
||||
if ($type == 'node' || $type == 'all') {
|
||||
$tokens['node']['termpath'] = t('As [term], but including its supercategories separated by /.');
|
||||
$tokens['node']['termpath-raw'] = t('As [term-raw], but including its supercategories separated by /.');
|
||||
$tokens['node']['termalias'] = t('The URL alias of the taxonomy term.');
|
||||
$tokens['node']['termalias-raw'] = t('The URL alias of the taxonomy term.');
|
||||
}
|
||||
}
|
||||
if (module_exists('book')) {
|
||||
if ($type == 'node' || $type == 'all') {
|
||||
$tokens['node']['bookpathalias'] = t('The URL alias of the parent book of the node.');
|
||||
$tokens['node']['bookpathalias-raw'] = t('The URL alias of the parent book of the node.');
|
||||
}
|
||||
}
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_token_values().
|
||||
*/
|
||||
function pathauto_token_values($type, $object = NULL, $options = array(), $label = NULL) {
|
||||
$values = array();
|
||||
|
||||
switch ($type) {
|
||||
case 'node':
|
||||
// Token [bookpathalias].
|
||||
if (module_exists('book')) {
|
||||
$values['bookpathalias'] = '';
|
||||
$values['bookpathalias-raw'] = '';
|
||||
if (!empty($object->book['plid']) && $parent = book_link_load($object->book['plid'])) {
|
||||
$values['bookpathalias-raw'] = drupal_get_path_alias($parent['href']);
|
||||
$values['bookpathalias'] = check_plain($values['bookpathalias-raw']);
|
||||
}
|
||||
}
|
||||
|
||||
// Tokens [termpath], [termpath-raw], and [termalias].
|
||||
if (module_exists('taxonomy')) {
|
||||
// Get the lowest-weighted term from the lowest-weighted vocabulary.
|
||||
// This query is copied from @taxonomy_node_get_terms()
|
||||
$term = db_fetch_object(db_query_range('SELECT t.* FROM {term_node} r INNER JOIN {term_data} t ON r.tid = t.tid INNER JOIN {vocabulary} v ON t.vid = v.vid WHERE r.vid = %d ORDER BY v.weight, t.weight, t.name', $object->vid, 0, 1));
|
||||
if ($term) {
|
||||
$values = array_merge($values, pathauto_token_values('taxonomy', $term, $options, 'term'));
|
||||
}
|
||||
else {
|
||||
$values['termpath'] = $values['termpath-raw'] = $values['termalias'] = '';
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'taxonomy':
|
||||
// In the realm of nodes these are 'terms', in the realm of taxonomy, 'cats'.
|
||||
if (!isset($label)) {
|
||||
$label = 'cat';
|
||||
}
|
||||
|
||||
$values[$label . 'path'] = '';
|
||||
$values[$label . 'path-raw'] = '';
|
||||
$values[$label . 'alias'] = '';
|
||||
$values[$label . 'alias-raw'] = '';
|
||||
|
||||
// Tokens [catpath] and [catpath-raw].
|
||||
if (isset($object->tid)) {
|
||||
$parents = taxonomy_get_parents_all($object->tid);
|
||||
$catpath = $catpath_raw = array();
|
||||
foreach ($parents as $parent) {
|
||||
array_unshift($catpath, check_plain($parent->name));
|
||||
array_unshift($catpath_raw, $parent->name);
|
||||
}
|
||||
$values[$label . 'path'] = !empty($options['pathauto']) ? $catpath : implode('/', $catpath);
|
||||
$values[$label . 'path-raw'] = !empty($options['pathauto']) ? $catpath_raw : implode('/', $catpath_raw);
|
||||
|
||||
// Token [catalias-raw] and [catalias].
|
||||
$values[$label . 'alias-raw'] = drupal_get_path_alias(taxonomy_term_path($object));
|
||||
$values[$label . 'alias'] = check_plain($values[$label . 'alias-raw']);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_path_alias_types().
|
||||
*
|
||||
* Used primarily by the bulk delete form.
|
||||
*/
|
||||
function pathauto_path_alias_types() {
|
||||
$objects['user/'] = t('Users');
|
||||
$objects['node/'] = t('Content');
|
||||
if (module_exists('blog')) {
|
||||
$objects['blog/'] = t('User blogs');
|
||||
}
|
||||
if (module_exists('taxonomy')) {
|
||||
$objects['taxonomy/term/'] = t('Taxonomy terms');
|
||||
}
|
||||
if (module_exists('forum')) {
|
||||
$objects['forum/'] = t('Forums');
|
||||
}
|
||||
if (module_exists('contact')) {
|
||||
$objects['user/%/contact'] = t('User contact forms');
|
||||
}
|
||||
if (module_exists('tracker')) {
|
||||
$objects['user/%/track'] = t('User trackers');
|
||||
}
|
||||
return $objects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the proper SQL to perform cross-db and field-type concatenation.
|
||||
*
|
||||
* @return
|
||||
* A string of SQL with the concatenation.
|
||||
*/
|
||||
function _pathauto_sql_concat() {
|
||||
$args = func_get_args();
|
||||
switch ($GLOBALS['db_type']) {
|
||||
case 'mysql':
|
||||
case 'mysqli':
|
||||
return 'CONCAT(' . implode(', ', $args) . ')';
|
||||
default:
|
||||
// The ANSI standard of concatentation uses the double-pipe.
|
||||
return '(' . implode(' || ', $args) . ')';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_attach_rename_bundle().
|
||||
*
|
||||
* Respond to machine name changes for pattern variables.
|
||||
*/
|
||||
function pathauto_field_attach_rename_bundle($entity_type, $bundle_old, $bundle_new) {
|
||||
$result = db_query("SELECT name FROM {variable} WHERE name LIKE '%s%%'", "pathauto_{$entity_type}_{$bundle_old}_");
|
||||
while ($variable = db_result($result)) {
|
||||
$value = variable_get($variable, '');
|
||||
variable_del($variable);
|
||||
$variable = strtr($variable, array("{$entity_type}_{$bundle_old}" => "{$entity_type}_{$bundle_new}"));
|
||||
variable_set($variable, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_attach_delete_bundle().
|
||||
*
|
||||
* Respond to sub-types being deleted, their patterns can be removed.
|
||||
*/
|
||||
function pathauto_field_attach_delete_bundle($entity_type, $bundle) {
|
||||
$result = db_query("SELECT name FROM {variable} WHERE name LIKE '%s%%'", "pathauto_{$entity_type}_{$bundle}_");
|
||||
while ($variable = db_result($result)) {
|
||||
variable_del($variable);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Some node related functions.
|
||||
|
||||
/**
|
||||
* Implements hook_nodeapi().
|
||||
*/
|
||||
function pathauto_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
|
||||
switch ($op) {
|
||||
case 'presave':
|
||||
// About to be saved (before insert/update)
|
||||
if (!empty($node->pathauto_perform_alias) && isset($node->old_alias)
|
||||
&& $node->path == '' && $node->old_alias != '') {
|
||||
/**
|
||||
* There was an old alias, but when pathauto_perform_alias was checked
|
||||
* the javascript disabled the textbox which led to an empty value being
|
||||
* submitted. Restoring the old path-value here prevents the Path module
|
||||
* from deleting any old alias before Pathauto gets control.
|
||||
*/
|
||||
$node->path = $node->old_alias;
|
||||
}
|
||||
break;
|
||||
case 'insert':
|
||||
case 'update':
|
||||
// Skip processing if the user has disabled pathauto for the node.
|
||||
if (isset($node->pathauto_perform_alias) && empty($node->pathauto_perform_alias)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_pathauto_include();
|
||||
// Get the specific pattern or the default
|
||||
if (variable_get('language_content_type_'. $node->type, 0)) {
|
||||
$pattern = trim(variable_get('pathauto_node_'. $node->type .'_'. $node->language .'_pattern', FALSE));
|
||||
}
|
||||
if (empty($pattern)) {
|
||||
$pattern = trim(variable_get('pathauto_node_'. $node->type .'_pattern', FALSE));
|
||||
if (empty($pattern)) {
|
||||
$pattern = trim(variable_get('pathauto_node_pattern', FALSE));
|
||||
}
|
||||
}
|
||||
// Only do work if there's a pattern
|
||||
if ($pattern) {
|
||||
$placeholders = pathauto_get_placeholders('node', $node);
|
||||
$src = "node/$node->nid";
|
||||
if ($alias = pathauto_create_alias('node', $op, $placeholders, $src, $node->nid, $node->type, $node->language)) {
|
||||
$node->path = $alias;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'delete':
|
||||
path_set_alias('node/'. $node->nid);
|
||||
path_set_alias('node/'. $node->nid .'/feed');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_node_type().
|
||||
*/
|
||||
function pathauto_node_type($op, $info) {
|
||||
switch ($op) {
|
||||
case 'update':
|
||||
if (!empty($info->old_type) && $info->old_type != $info->type) {
|
||||
pathauto_field_attach_rename_bundle('node', $info->old_type, $info->type);
|
||||
}
|
||||
break;
|
||||
case 'delete':
|
||||
pathauto_field_attach_delete_bundle('node', $info->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_alter().
|
||||
*
|
||||
* This allows alias creators to override Pathauto and specify their
|
||||
* own aliases (Pathauto will be invisible to other users). Inserted
|
||||
* into the path module's fieldset in the node form.
|
||||
*/
|
||||
function pathauto_form_alter(&$form, $form_state, $form_id) {
|
||||
// Process only node forms.
|
||||
if (isset($form['type']) && isset($form['#node']) && $form['type']['#value'] .'_node_form' == $form_id) {
|
||||
$node = $form['#node'];
|
||||
$pattern = FALSE;
|
||||
|
||||
// Find if there is an automatic alias pattern for this node type.
|
||||
if (isset($form['language'])) {
|
||||
$language = isset($form['language']['#value']) ? $form['language']['#value'] : $form['language']['#default_value'];
|
||||
$pattern = trim(variable_get('pathauto_node_'. $form['type']['#value'] .'_'. $language .'_pattern', ''));
|
||||
}
|
||||
if (!$pattern) {
|
||||
$pattern = trim(variable_get('pathauto_node_'. $form['type']['#value'] .'_pattern', ''));
|
||||
if (!$pattern) {
|
||||
$pattern = trim(variable_get('pathauto_node_pattern', ''));
|
||||
}
|
||||
}
|
||||
|
||||
// If there is a pattern, show the automatic alias checkbox.
|
||||
if ($pattern) {
|
||||
if (!isset($node->pathauto_perform_alias)) {
|
||||
if (!empty($node->nid)) {
|
||||
// If this is not a new node, compare it's current alias to the
|
||||
// alias that would be genereted by pathauto. If they are the same,
|
||||
// then keep the automatic alias enabled.
|
||||
_pathauto_include();
|
||||
$placeholders = pathauto_get_placeholders('node', $node);
|
||||
$pathauto_alias = pathauto_create_alias('node', 'return', $placeholders, "node/{$node->nid}", $node->nid, $node->type, $node->language);
|
||||
$node->pathauto_perform_alias = isset($node->path) && $node->path == $pathauto_alias;
|
||||
}
|
||||
else {
|
||||
// If this is a new node, enable the automatic alias.
|
||||
$node->pathauto_perform_alias = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Add JavaScript that will disable the path textfield when the automatic
|
||||
// alias checkbox is checked.
|
||||
drupal_add_js(drupal_get_path('module', 'pathauto') .'/pathauto.js');
|
||||
|
||||
// Override path.module's vertical tabs summary.
|
||||
$form['path']['#attached']['js']['vertical-tabs'] = drupal_get_path('module', 'pathauto') . '/pathauto.js';
|
||||
|
||||
$form['path']['pathauto_perform_alias'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Automatic alias'),
|
||||
'#default_value' => $node->pathauto_perform_alias,
|
||||
'#description' => t('An alias will be generated for you. If you wish to create your own alias below, uncheck this option.'),
|
||||
'#weight' => -1,
|
||||
);
|
||||
|
||||
if (user_access('administer pathauto')) {
|
||||
$form['path']['pathauto_perform_alias']['#description'] .= ' '. t('To control the format of the generated aliases, see the <a href="@pathauto">automated alias settings</a>.', array('@pathauto' => url('admin/build/path/pathauto')));
|
||||
}
|
||||
|
||||
if ($node->pathauto_perform_alias && !empty($node->old_alias) && empty($node->path)) {
|
||||
$form['path']['path']['#default_value'] = $node->old_alias;
|
||||
$node->path = $node->old_alias;
|
||||
}
|
||||
|
||||
// For Pathauto to remember the old alias and prevent the Path-module from deleteing it when Pathauto wants to preserve it
|
||||
if (isset($node->path)) {
|
||||
$form['path']['old_alias'] = array(
|
||||
'#type' => 'value',
|
||||
'#value' => $node->path,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_node_operations().
|
||||
*/
|
||||
function pathauto_node_operations() {
|
||||
$operations['pathauto_update_alias'] = array(
|
||||
'label' => t('Update URL alias'),
|
||||
'callback' => 'pathauto_node_update_alias_multiple',
|
||||
'callback arguments' => array('bulkupdate', TRUE),
|
||||
);
|
||||
return $operations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the URL aliases for an individual node.
|
||||
*
|
||||
* @param $node
|
||||
* A node object.
|
||||
* @param $op
|
||||
* Operation being performed on the node ('insert', 'update' or 'bulkupdate').
|
||||
*/
|
||||
function pathauto_node_update_alias($node, $op) {
|
||||
module_load_include('inc', 'pathauto');
|
||||
$placeholders = pathauto_get_placeholders('node', $node);
|
||||
if ($alias = pathauto_create_alias('node', $op, $placeholders, "node/{$node->nid}", $node->nid, $node->type, $node->language)) {
|
||||
$node->path = $alias;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the URL aliases for multiple nodes.
|
||||
*
|
||||
* @param $nids
|
||||
* An array of node IDs.
|
||||
* @param $op
|
||||
* Operation being performed on the nodes ('insert', 'update' or
|
||||
* 'bulkupdate').
|
||||
* @param $message
|
||||
* A boolean if TRUE will display a message about how many nodes were
|
||||
* updated.
|
||||
*/
|
||||
function pathauto_node_update_alias_multiple($nids, $op, $message = FALSE) {
|
||||
foreach ($nids as $nid) {
|
||||
if ($node = node_load($nid, NULL, TRUE)) {
|
||||
pathauto_node_update_alias($node, $op);
|
||||
}
|
||||
}
|
||||
if ($message) {
|
||||
drupal_set_message(format_plural(count($nids), 'Updated URL alias for 1 node.', 'Updated URL aliases for @count nodes.'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper function backwards compatibility. Should be avoided.
|
||||
*
|
||||
* @param $nodes
|
||||
* An array of node IDs.
|
||||
*
|
||||
* @see pathauto_node_update_alias_multiple().
|
||||
*/
|
||||
function pathauto_node_operations_update($nodes) {
|
||||
return pathauto_node_update_alias_multiple($nodes, 'bulkupdate');
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Taxonomy related functions.
|
||||
|
||||
/**
|
||||
* Implements hook_taxonomy().
|
||||
*/
|
||||
function pathauto_taxonomy($op, $type, $object = NULL) {
|
||||
switch ($type) {
|
||||
case 'term':
|
||||
switch ($op) {
|
||||
case 'insert':
|
||||
case 'update':
|
||||
$term = (object) $object;
|
||||
|
||||
// Skip processing if the user has disabled pathauto for the term.
|
||||
if (isset($term->pathauto_perform_alias) && empty($term->pathauto_perform_alias)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear the taxonomy term's static cache.
|
||||
if ($op == 'update') {
|
||||
taxonomy_get_term($term->tid, TRUE);
|
||||
}
|
||||
|
||||
// Use the category info to automatically create an alias
|
||||
_pathauto_include();
|
||||
if ($term->name) {
|
||||
$count = _taxonomy_pathauto_alias($term, $op);
|
||||
}
|
||||
|
||||
// For all children generate new alias (important if [catpath] used)
|
||||
foreach (taxonomy_get_tree($term->vid, $term->tid) as $subcategory) {
|
||||
$count = _taxonomy_pathauto_alias($subcategory, $op);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
// If the category is deleted, remove the path aliases
|
||||
$term = (object) $object;
|
||||
path_set_alias('taxonomy/term/'. $term->tid);
|
||||
path_set_alias(taxonomy_term_path($term));
|
||||
path_set_alias('forum/'. $term->tid);
|
||||
path_set_alias('taxonomy/term/'. $term->tid .'/0/feed');
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'vocabulary':
|
||||
$vocabulary = (object) $object;
|
||||
switch ($op) {
|
||||
case 'delete':
|
||||
pathauto_field_attach_delete_bundle('taxonomy', $vocabulary->vid);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// User related functions.
|
||||
|
||||
/**
|
||||
* Implements hook_user().
|
||||
*/
|
||||
function pathauto_user($op, &$edit, &$user, $category = NULL) {
|
||||
switch ($op) {
|
||||
case 'insert':
|
||||
case 'update':
|
||||
// Build the user object.
|
||||
$pathauto_user = (object) array_merge((array) $user, $edit);
|
||||
|
||||
// Skip processing if the user has disabled pathauto for the account.
|
||||
if (isset($pathauto_user->pathauto_perform_alias) && empty($pathauto_user->pathauto_perform_alias)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Use the username to automatically create an alias
|
||||
_pathauto_include();
|
||||
if ($user->name) {
|
||||
$placeholders = pathauto_get_placeholders('user', $pathauto_user);
|
||||
$src = 'user/'. $user->uid;
|
||||
$alias = pathauto_create_alias('user', $op, $placeholders, $src, $user->uid);
|
||||
|
||||
if (module_exists('blog')) {
|
||||
$new_user = drupal_clone($user);
|
||||
if ($category == 'account') {
|
||||
$new_user->roles = isset($edit['roles']) ? $edit['roles'] : array();
|
||||
$new_user->roles[DRUPAL_AUTHENTICATED_RID] = 'authenticated user'; // Add this back
|
||||
}
|
||||
if (node_access('create', 'blog', $new_user)) {
|
||||
$src = 'blog/'. $user->uid;
|
||||
$alias = pathauto_create_alias('blog', $op, $placeholders, $src, $user->uid);
|
||||
}
|
||||
else {
|
||||
path_set_alias('blog/'. $user->uid);
|
||||
path_set_alias('blog/'. $user->uid .'/feed');
|
||||
}
|
||||
}
|
||||
if (module_exists('tracker')) {
|
||||
$src = 'user/'. $user->uid .'/track';
|
||||
$alias = pathauto_create_alias('tracker', $op, $placeholders, $src, $user->uid);
|
||||
}
|
||||
if (module_exists('contact')) {
|
||||
$src = 'user/'. $user->uid .'/contact';
|
||||
$alias = pathauto_create_alias('contact', $op, $placeholders, $src, $user->uid);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'delete':
|
||||
// If the user is deleted, remove the path aliases
|
||||
$user = (object) $user;
|
||||
path_set_alias('user/'. $user->uid);
|
||||
|
||||
// They may have enabled these modules and/or feeds when the user was created, so let's try to delete all of them
|
||||
path_set_alias('blog/'. $user->uid);
|
||||
path_set_alias('blog/'. $user->uid .'/feed');
|
||||
path_set_alias('user/'. $user->uid .'/track');
|
||||
path_set_alias('user/'. $user->uid .'/track/feed');
|
||||
path_set_alias('user/'. $user->uid .'/contact');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_user_operations().
|
||||
*/
|
||||
function pathauto_user_operations() {
|
||||
$operations['pathauto_update_alias'] = array(
|
||||
'label' => t('Update URL alias'),
|
||||
'callback' => 'pathauto_user_update_alias_multiple',
|
||||
'callback arguments' => array('bulkupdate', TRUE),
|
||||
);
|
||||
return $operations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the URL aliases for an individual user account.
|
||||
*
|
||||
* @param $account
|
||||
* A user account object.
|
||||
* @param $op
|
||||
* Operation being performed on the account ('insert', 'update' or
|
||||
* 'bulkupdate').
|
||||
*
|
||||
* @todo Remove support for any sub-path aliases.
|
||||
*/
|
||||
function pathauto_user_update_alias($account, $op) {
|
||||
module_load_include('inc', 'pathauto');
|
||||
$placeholders = pathauto_get_placeholders('user', $account);
|
||||
pathauto_create_alias('user', $op, $placeholders, "user/{$account->uid}", $account->uid);
|
||||
|
||||
if (module_exists('blog')) {
|
||||
if (node_access('create', 'blog', $account)) {
|
||||
pathauto_create_alias('blog', $op, $placeholders, "blog/{$account->uid}", $account->uid);
|
||||
}
|
||||
else {
|
||||
path_set_alias('blog/'. $user->uid);
|
||||
path_set_alias('blog/'. $user->uid .'/feed');
|
||||
}
|
||||
}
|
||||
if (module_exists('tracker')) {
|
||||
$alias = pathauto_create_alias('tracker', $op, $placeholders, "user/{$account->uid}/track", $user->uid);
|
||||
}
|
||||
if (module_exists('contact')) {
|
||||
$alias = pathauto_create_alias('contact', $op, $placeholders, "user/{$account->uid}/contact", $user->uid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the URL aliases for multiple user accounts.
|
||||
*
|
||||
* @param $uids
|
||||
* An array of user account IDs.
|
||||
* @param $op
|
||||
* Operation being performed on the accounts ('insert', 'update' or
|
||||
* 'bulkupdate').
|
||||
* @param $message
|
||||
* A boolean if TRUE will display a message about how many accounts were
|
||||
* updated.
|
||||
*/
|
||||
function pathauto_user_update_alias_multiple($uids, $op, $message = FALSE) {
|
||||
foreach ($uids as $uid) {
|
||||
if ($account = user_load($uid)) {
|
||||
pathauto_user_update_alias($account, $op);
|
||||
}
|
||||
}
|
||||
if ($message) {
|
||||
drupal_set_message(format_plural(count($uids), 'Updated URL alias for 1 user account.', 'Updated URL aliases for @count user accounts.'));
|
||||
}
|
||||
}
|
830
modules/pathauto/pathauto.test
Normal file
830
modules/pathauto/pathauto.test
Normal file
|
@ -0,0 +1,830 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Functionality tests for Pathauto.
|
||||
*
|
||||
* @ingroup pathauto
|
||||
*/
|
||||
|
||||
/**
|
||||
* Helper test class with some added functions for testing.
|
||||
*/
|
||||
class PathautoTestHelper extends DrupalWebTestCase {
|
||||
function setUp(array $modules = array()) {
|
||||
$modules[] = 'path';
|
||||
$modules[] = 'token';
|
||||
$modules[] = 'pathauto';
|
||||
$modules[] = 'taxonomy';
|
||||
parent::setUp($modules);
|
||||
}
|
||||
|
||||
function assertToken($type, $object, $token, $expected) {
|
||||
$this->assertTokens($type, $object, array($token => $expected));
|
||||
}
|
||||
|
||||
function assertTokens($type, $object, array $tokens) {
|
||||
$values = pathauto_get_placeholders($type, $object);
|
||||
$values = $values['values'];
|
||||
foreach ($tokens as $token => $expected) {
|
||||
$this->assertIdentical($values[$token], $expected, t("Token value for [@token] was '@actual', expected value '@expected'.", array('@token' => $token, '@actual' => $values[$token], '@expected' => $expected)));
|
||||
}
|
||||
}
|
||||
|
||||
function saveAlias($source, $alias, $language = '') {
|
||||
path_set_alias($source, $alias, NULL, $language);
|
||||
return db_fetch_array(db_query_range("SELECT * FROM {url_alias} WHERE src = '%s' AND dst = '%s' AND language = '%s' ORDER BY pid DESC", $source, $alias, $language, 0, 1));
|
||||
}
|
||||
|
||||
function saveEntityAlias($entity_type, $entity, $alias, $language = '') {
|
||||
$uri = $this->entity_uri($entity_type, $entity);
|
||||
return $this->saveAlias($uri['path'], $alias, $language);
|
||||
}
|
||||
|
||||
function assertEntityAlias($entity_type, $entity, $expected_alias, $language = '') {
|
||||
$uri = $this->entity_uri($entity_type, $entity);
|
||||
$this->assertAlias($uri['path'], $expected_alias, $language);
|
||||
}
|
||||
|
||||
function assertEntityAliasExists($entity_type, $entity) {
|
||||
$uri = $this->entity_uri($entity_type, $entity);
|
||||
return $this->assertAliasExists(array('source' => $uri['path']));
|
||||
}
|
||||
|
||||
function assertNoEntityAlias($entity_type, $entity, $language = '') {
|
||||
$uri = $this->entity_uri($entity_type, $entity);
|
||||
$this->assertEntityAlias($entity_type, $entity, $uri['path'], $language);
|
||||
}
|
||||
|
||||
function assertNoEntityAliasExists($entity_type, $entity) {
|
||||
$uri = $this->entity_uri($entity_type, $entity);
|
||||
$this->assertNoAliasExists(array('source' => $uri['path']));
|
||||
}
|
||||
|
||||
function assertAlias($source, $expected_alias, $language = '') {
|
||||
drupal_clear_path_cache();
|
||||
$alias = drupal_get_path_alias($source, $language);
|
||||
$this->assertIdentical($alias, $expected_alias, t("Alias for %source with language '@language' was %actual, expected %expected.", array('%source' => $source, '%actual' => $alias, '%expected' => $expected_alias, '@language' => $language)));
|
||||
}
|
||||
|
||||
function assertAliasExists($conditions) {
|
||||
$path = $this->path_load($conditions);
|
||||
$this->assertTrue($path, t('Alias with conditions @conditions found.', array('@conditions' => var_export($conditions, TRUE))));
|
||||
return $path;
|
||||
}
|
||||
|
||||
function assertNoAliasExists($conditions) {
|
||||
$alias = $this->path_load($conditions);
|
||||
$this->assertFalse($alias, t('Alias with conditions @conditions not found.', array('@conditions' => var_export($conditions, TRUE))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Backport of Drupal 7's entity_uri() function.
|
||||
*/
|
||||
protected function entity_uri($entity_type, $entity) {
|
||||
$uri = array();
|
||||
|
||||
switch ($entity_type) {
|
||||
case 'node':
|
||||
$uri['path'] = 'node/' . $entity->nid;
|
||||
break;
|
||||
case 'taxonomy_term':
|
||||
$uri['path'] = taxonomy_term_path($entity);
|
||||
break;
|
||||
case 'user':
|
||||
$uri['path'] = 'user/' . $entity->uid;
|
||||
break;
|
||||
default:
|
||||
return $this->fail(t('Unknown entity @type.', array('@type' => $entity_type)));
|
||||
}
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Backport of Drupal 7's path_load() function.
|
||||
*/
|
||||
protected function path_load($conditions) {
|
||||
if (is_numeric($conditions)) {
|
||||
$conditions = array('pid' => $conditions);
|
||||
}
|
||||
elseif (is_string($conditions)) {
|
||||
$conditions = array('src' => $conditions);
|
||||
}
|
||||
|
||||
// Adjust for some D7 {url_alias} column name changes so we can keep
|
||||
// the test files in sync.
|
||||
if (isset($conditions['source'])) {
|
||||
$conditions['src'] = $conditions['source'];
|
||||
unset($conditions['source']);
|
||||
}
|
||||
if (isset($conditions['alias'])) {
|
||||
$conditions['dst'] = $conditions['alias'];
|
||||
unset($conditions['alias']);
|
||||
}
|
||||
|
||||
$args = array();
|
||||
$schema = drupal_get_schema_unprocessed('system', 'url_alias');
|
||||
foreach ($conditions as $field => $value) {
|
||||
$field_type = $schema['fields'][$field]['type'];
|
||||
if (is_array($value)) {
|
||||
$conditions[$field] = "$field = " . db_placeholders($value, $field_type);
|
||||
$args = array_merge($args, $value);
|
||||
}
|
||||
else {
|
||||
$placeholder = db_type_placeholder($field_type);
|
||||
$conditions[$field] = "$field = $placeholder";
|
||||
$args[] = $value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$sql = "SELECT * FROM {url_alias} WHERE " . implode(' AND ', $conditions);
|
||||
return db_fetch_array(db_query_range($sql, $args, 0, 1));
|
||||
}
|
||||
|
||||
function deleteAllAliases() {
|
||||
db_query("DELETE FROM {url_alias}");
|
||||
drupal_clear_path_cache();
|
||||
}
|
||||
|
||||
function addVocabulary(array $vocabulary = array()) {
|
||||
$vocabulary += array(
|
||||
'name' => drupal_strtolower($this->randomName(5)),
|
||||
'nodes' => array('story' => 'story'),
|
||||
);
|
||||
taxonomy_save_vocabulary($vocabulary);
|
||||
return (object) $vocabulary;
|
||||
}
|
||||
|
||||
function addTerm(stdClass $vocabulary, array $term = array()) {
|
||||
$term += array(
|
||||
'name' => drupal_strtolower($this->randomName(5)),
|
||||
'vid' => $vocabulary->vid,
|
||||
);
|
||||
taxonomy_save_term($term);
|
||||
return (object) $term;
|
||||
}
|
||||
|
||||
function addNodeType(array $type) {
|
||||
if (!isset($type['name'])) {
|
||||
$type['name'] = $this->randomName(8);
|
||||
}
|
||||
|
||||
$type += array(
|
||||
'type' => drupal_strtolower($type['name']),
|
||||
'module' => 'node',
|
||||
'description' => $this->randomName(40),
|
||||
'custom' => TRUE,
|
||||
'modified' => TRUE,
|
||||
'locked' => FALSE,
|
||||
'help' => '',
|
||||
'min_word_count' => '',
|
||||
);
|
||||
|
||||
$type = (object) _node_type_set_defaults($type);
|
||||
node_type_save($type);
|
||||
node_types_rebuild();
|
||||
return $type;
|
||||
}
|
||||
|
||||
function assertEntityPattern($entity_type, $bundle, $language = '', $expected) {
|
||||
$this->refreshVariables();
|
||||
$variables = array(
|
||||
"pathauto_{$entity_type}_{$bundle}_{$language}_pattern",
|
||||
"pathauto_{$entity_type}_{$bundle}_pattern",
|
||||
"pathauto_{$entity_type}_pattern",
|
||||
);
|
||||
$pattern = '';
|
||||
foreach ($variables as $variable) {
|
||||
if ($pattern = variable_get($variable, '')) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->assertIdentical($expected, $pattern);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unit tests for Pathauto functions.
|
||||
*/
|
||||
class PathautoUnitTestCase extends PathautoTestHelper {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Pathauto unit tests',
|
||||
'description' => 'Unit tests for Pathauto functions.',
|
||||
'group' => 'Pathauto',
|
||||
'dependencies' => array('token'),
|
||||
);
|
||||
}
|
||||
|
||||
function setUp(array $modules = array()) {
|
||||
parent::setUp($modules);
|
||||
module_load_include('inc', 'pathauto');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test _pathauto_get_schema_alias_maxlength().
|
||||
*/
|
||||
function testGetSchemaAliasMaxLength() {
|
||||
$this->assertIdentical(_pathauto_get_schema_alias_maxlength(), 128);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test pathauto_cleanstring().
|
||||
*/
|
||||
function testCleanString() {
|
||||
$tests = array();
|
||||
variable_set('pathauto_ignore_words', ', in, is,that, the , this, with, ');
|
||||
variable_set('pathauto_max_component_length', 35);
|
||||
|
||||
// Test the 'ignored words' removal.
|
||||
$tests['this'] = 'this';
|
||||
$tests['this with that'] = 'this-with-that';
|
||||
$tests['this thing with that thing'] = 'thing-thing';
|
||||
|
||||
// Test length truncation and duplicate separator removal.
|
||||
$tests[' - Pathauto is the greatest - module ever in Drupal history - '] = 'pathauto-greatest-module-ever-drupa';
|
||||
|
||||
// Test that HTML tags are removed.
|
||||
$tests['This <span class="text">text</span> has <br /><a href="http://example.com"><strong>HTML tags</strong></a>.'] = 'text-has-html-tags';
|
||||
$tests[check_plain('This <span class="text">text</span> has <br /><a href="http://example.com"><strong>HTML tags</strong></a>.')] = 'text-has-html-tags';
|
||||
|
||||
foreach ($tests as $input => $expected) {
|
||||
$output = pathauto_cleanstring($input);
|
||||
$this->assertEqual($output, $expected, t("pathauto_cleanstring('@input') expected '@expected', actual '@output'", array('@input' => $input, '@expected' => $expected, '@output' => $output)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the feed alias functionality of pathauto_create_alias().
|
||||
*/
|
||||
function testFeedAliases() {
|
||||
variable_set('pathauto_node_pattern', '[title-raw]');
|
||||
variable_set('pathauto_node_applytofeeds', '');
|
||||
|
||||
// Create a node with an empty title, which should not create an alias.
|
||||
$node = $this->drupalCreateNode(array('title' => ''));
|
||||
$this->assertNoAliasExists(array('source' => "node/{$node->nid}"));
|
||||
$this->assertNoAliasExists(array('source' => "node/{$node->nid}/feed"));
|
||||
|
||||
// Add a title to the node. This should still not generate a feed alias.
|
||||
$node->title = 'Node title';
|
||||
pathauto_nodeapi($node, 'update');
|
||||
$this->assertAliasExists(array('source' => "node/{$node->nid}", 'alias' => 'node-title'));
|
||||
$this->assertNoAliasExists(array('source' => "node/{$node->nid}/feed"));
|
||||
|
||||
// Enable feeds for nodes. A feed alias should now be generated.
|
||||
variable_set('pathauto_node_applytofeeds', ' feed ');
|
||||
pathauto_nodeapi($node, 'update');
|
||||
$this->assertAliasExists(array('source' => "node/{$node->nid}/feed", 'alias' => 'node-title/feed'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test _pathauto_get_raw_tokens().
|
||||
*/
|
||||
function testGetRawTokens() {
|
||||
$raw_tokens = _pathauto_get_raw_tokens();
|
||||
$this->assertFalse(in_array('node-path', $raw_tokens), 'Non-raw tokens not included.');
|
||||
$this->assertTrue(in_array('node-path-raw', $raw_tokens), 'Token [catpath] has a matching raw token.');
|
||||
$this->assertFalse(in_array('node-url-raw', $raw_tokens), 'Token [catalias] does not have a matching raw token.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the different update actions in pathauto_create_alias().
|
||||
*/
|
||||
function testUpdateActions() {
|
||||
// Test PATHAUTO_UPDATE_ACTION_NO_NEW with unaliased node and 'insert'.
|
||||
variable_set('pathauto_update_action', 0);
|
||||
$node = $this->drupalCreateNode(array('title' => 'First title'));
|
||||
$this->assertEntityAlias('node', $node, 'content/first-title');
|
||||
|
||||
// Default action is PATHAUTO_UPDATE_ACTION_DELETE.
|
||||
variable_set('pathauto_update_action', 2);
|
||||
$node->title = 'Second title';
|
||||
pathauto_nodeapi($node, 'update');
|
||||
$this->assertEntityAlias('node', $node, 'content/second-title');
|
||||
$this->assertNoAliasExists(array('alias' => 'content/first-title'));
|
||||
|
||||
// Test PATHAUTO_UPDATE_ACTION_LEAVE.
|
||||
variable_set('pathauto_update_action', 1);
|
||||
$node->title = 'Third title';
|
||||
pathauto_nodeapi($node, 'update');
|
||||
$this->assertEntityAlias('node', $node, 'content/third-title');
|
||||
$this->assertAliasExists(array('source' => "node/{$node->nid}", 'alias' => 'content/second-title'));
|
||||
|
||||
variable_set('pathauto_update_action', 2);
|
||||
$node->title = 'Fourth title';
|
||||
pathauto_nodeapi($node, 'update');
|
||||
$this->assertEntityAlias('node', $node, 'content/fourth-title');
|
||||
$this->assertNoAliasExists(array('alias' => 'content/third-title'));
|
||||
// The older second alias is not deleted yet.
|
||||
$older_path = $this->assertAliasExists(array('source' => "node/{$node->nid}", 'alias' => 'content/second-title'));
|
||||
path_set_alias(NULL, NULL, $older_path['pid']);
|
||||
|
||||
variable_set('pathauto_update_action', 0);
|
||||
$node->title = 'Fifth title';
|
||||
pathauto_nodeapi($node, 'update');
|
||||
$this->assertEntityAlias('node', $node, 'content/fourth-title');
|
||||
$this->assertNoAliasExists(array('alias' => 'content/fith-title'));
|
||||
|
||||
// Test PATHAUTO_UPDATE_ACTION_NO_NEW with unaliased node and 'update'.
|
||||
$this->deleteAllAliases();
|
||||
pathauto_nodeapi($node, 'update');
|
||||
$this->assertEntityAlias('node', $node, 'content/fifth-title');
|
||||
|
||||
// Test PATHAUTO_UPDATE_ACTION_NO_NEW with unaliased node and 'bulkupdate'.
|
||||
$this->deleteAllAliases();
|
||||
$node->title = 'Sixth title';
|
||||
pathauto_node_update_alias($node, 'bulkupdate');
|
||||
$this->assertEntityAlias('node', $node, 'content/sixth-title');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that pathauto_create_alias() will not create an alias for a pattern
|
||||
* that does not get any tokens replaced.
|
||||
*/
|
||||
function testNoTokensNoAlias() {
|
||||
$node = $this->drupalCreateNode(array('title' => ''));
|
||||
$this->assertNoEntityAlias('node', $node);
|
||||
|
||||
$node->title = 'hello';
|
||||
pathauto_nodeapi($node, 'update');
|
||||
$this->assertEntityAlias('node', $node, 'content/hello');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the handling of path vs non-path tokens in pathauto_clean_token_values().
|
||||
*
|
||||
* @see PathautoBookTokenTestCase::testBookPathAlias()
|
||||
*/
|
||||
//function testPathTokens() {
|
||||
//}
|
||||
|
||||
function testEntityBundleRenamingDeleting() {
|
||||
// Create a vocabulary type.
|
||||
$vocabulary = $this->addVocabulary();
|
||||
variable_set('pathauto_taxonomy_pattern', 'base');
|
||||
variable_set('pathauto_taxonomy_' . $vocabulary->vid . '_pattern', 'bundle');
|
||||
$this->assertEntityPattern('taxonomy', $vocabulary->vid, '', 'bundle');
|
||||
|
||||
// Delete the vocabulary, which should cause its pattern variable to also
|
||||
// be deleted.
|
||||
taxonomy_del_vocabulary($vocabulary->vid);
|
||||
$this->assertEntityPattern('taxonomy', $vocabulary->vid, '', 'base');
|
||||
|
||||
// Create a node type and test that it's pattern variable works.
|
||||
$type = $this->addNodeType(array('type' => 'old_name'));
|
||||
variable_set('pathauto_node_pattern', 'base');
|
||||
variable_set("pathauto_node_old_name_pattern", 'bundle');
|
||||
$this->assertEntityPattern('node', 'old_name', '', 'bundle');
|
||||
|
||||
// Rename the node type's machine name, which should cause its pattern
|
||||
// variable to also be renamed.
|
||||
$type->type = 'new_name';
|
||||
$type->old_type = 'old_name';
|
||||
node_type_save($type);
|
||||
node_types_rebuild();
|
||||
$this->assertEntityPattern('node', 'new_name', '', 'bundle');
|
||||
$this->assertEntityPattern('node', 'old_name', '', 'base');
|
||||
|
||||
// Delete the node type, which should cause its pattern variable to also
|
||||
// be deleted.
|
||||
node_type_delete($type->type);
|
||||
$this->assertEntityPattern('node', 'new_name', '', 'base');
|
||||
}
|
||||
|
||||
function testNoExistingPathAliases() {
|
||||
variable_set('pathauto_node_page_pattern', '[title-raw]');
|
||||
variable_set('pathauto_punctuation_period', 2); // Do not replace periods.
|
||||
|
||||
// Check that Pathauto does not create an alias of '/admin'.
|
||||
$node = $this->drupalCreateNode(array('title' => 'Admin', 'type' => 'page'));
|
||||
$this->assertNoEntityAlias('node', $node);
|
||||
|
||||
// Check that Pathauto does not create an alias of '/modules'.
|
||||
$node->title = 'Modules';
|
||||
node_save($node);
|
||||
$this->assertNoEntityAlias('node', $node);
|
||||
|
||||
// Check that Pathauto does not create an alias of '/index.php'.
|
||||
$node->title = 'index.php';
|
||||
node_save($node);
|
||||
$this->assertNoEntityAlias('node', $node);
|
||||
|
||||
// Check that a safe value gets an automatic alias. This is also a control
|
||||
// to ensure the above tests work properly.
|
||||
$node->title = 'Safe value';
|
||||
node_save($node);
|
||||
$this->assertEntityAlias('node', $node, 'safe-value');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper test class with some added functions for testing.
|
||||
*/
|
||||
class PathautoFunctionalTestHelper extends PathautoTestHelper {
|
||||
protected $admin_user;
|
||||
|
||||
function setUp(array $modules = array()) {
|
||||
parent::setUp($modules);
|
||||
|
||||
// Set pathauto settings we assume to be as-is in this test.
|
||||
variable_set('pathauto_node_page_pattern', 'content/[title-raw]');
|
||||
|
||||
// Allow other modules to add additional permissions for the admin user.
|
||||
$permissions = array(
|
||||
'administer pathauto',
|
||||
'administer url aliases',
|
||||
'create url aliases',
|
||||
'administer nodes',
|
||||
'administer users',
|
||||
);
|
||||
$args = func_get_args();
|
||||
if (isset($args[1]) && is_array($args[1])) {
|
||||
$permissions = array_merge($permissions, $args[1]);
|
||||
}
|
||||
$this->admin_user = $this->drupalCreateUser($permissions);
|
||||
|
||||
$this->drupalLogin($this->admin_user);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic pathauto functionality.
|
||||
*/
|
||||
class PathautoFunctionalTestCase extends PathautoFunctionalTestHelper {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Pathauto basic tests',
|
||||
'description' => 'Test basic pathauto functionality.',
|
||||
'group' => 'Pathauto',
|
||||
'dependencies' => array('token'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic functional testing of Pathauto.
|
||||
*/
|
||||
function testNodeEditing() {
|
||||
// Create node for testing.
|
||||
$random_title = $this->randomName(10);
|
||||
$title = ' Simpletest title ' . $random_title . ' [';
|
||||
$automatic_alias = 'content/simpletest-title-' . strtolower($random_title);
|
||||
$node = $this->drupalCreateNode(array('title' => $title, 'type' => 'page'));
|
||||
|
||||
// Look for alias generated in the form.
|
||||
$this->drupalGet('node/' . $node->nid . '/edit');
|
||||
$this->assertFieldChecked('edit-pathauto-perform-alias');
|
||||
$this->assertFieldByName('path', $automatic_alias, 'Proper automated alias generated.');
|
||||
|
||||
// Check whether the alias actually works.
|
||||
$this->drupalGet($automatic_alias);
|
||||
$this->assertText($title, 'Node accessible through automatic alias.');
|
||||
|
||||
// Manually set the node's alias.
|
||||
$manual_alias = 'content/' . $node->nid;
|
||||
$edit = array(
|
||||
'pathauto_perform_alias' => FALSE,
|
||||
'path' => $manual_alias,
|
||||
);
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
$this->assertText(t('@type @title has been updated', array('@type' => 'Page', '@title' => $title)));
|
||||
|
||||
// Check that the automatic alias checkbox is now unchecked by default.
|
||||
$this->drupalGet('node/' . $node->nid . '/edit');
|
||||
$this->assertNoFieldChecked('edit-pathauto-perform-alias');
|
||||
$this->assertFieldByName('path', $manual_alias);
|
||||
|
||||
// Submit the node form with the default values.
|
||||
$this->drupalPost(NULL, array(), t('Save'));
|
||||
$this->assertText(t('@type @title has been updated', array('@type' => 'Page', '@title' => $title)));
|
||||
|
||||
// Test that the old (automatic) alias has been deleted and only accessible
|
||||
// through the new (manual) alias.
|
||||
$this->drupalGet($automatic_alias);
|
||||
$this->assertResponse(404, 'Node not accessible through automatic alias.');
|
||||
$this->drupalGet($manual_alias);
|
||||
$this->assertText($title, 'Node accessible through manual alias.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test node operations.
|
||||
*/
|
||||
function testNodeOperations() {
|
||||
$node1 = $this->drupalCreateNode(array('title' => 'node1'));
|
||||
$node2 = $this->drupalCreateNode(array('title' => 'node2'));
|
||||
|
||||
// Delete all current URL aliases.
|
||||
$this->deleteAllAliases();
|
||||
|
||||
$edit = array(
|
||||
'operation' => 'pathauto_update_alias',
|
||||
"nodes[{$node1->nid}]" => TRUE,
|
||||
);
|
||||
$this->drupalPost('admin/content/node', $edit, t('Update'));
|
||||
$this->assertText('Updated URL alias for 1 node.');
|
||||
|
||||
$this->assertEntityAlias('node', $node1, 'content/' . $node1->title);
|
||||
$this->assertEntityAlias('node', $node2, 'node/' . $node2->nid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test user operations.
|
||||
*/
|
||||
function testUserOperations() {
|
||||
$account = $this->drupalCreateUser();
|
||||
|
||||
// Delete all current URL aliases.
|
||||
$this->deleteAllAliases();
|
||||
|
||||
$edit = array(
|
||||
'operation' => 'pathauto_update_alias',
|
||||
"accounts[{$account->uid}]" => TRUE,
|
||||
);
|
||||
$this->drupalPost('admin/user/user', $edit, t('Update'));
|
||||
$this->assertText('Updated URL alias for 1 user account.');
|
||||
|
||||
$this->assertEntityAlias('user', $account, 'users/' . drupal_strtolower($account->name));
|
||||
$this->assertEntityAlias('user', $this->admin_user, 'user/' . $this->admin_user->uid);
|
||||
}
|
||||
|
||||
function testSettingsValidation() {
|
||||
$edit = array();
|
||||
$edit['pathauto_max_length'] = 'abc';
|
||||
$edit['pathauto_max_component_length'] = 'abc';
|
||||
$this->drupalPost('admin/build/path/pathauto', $edit, 'Save configuration');
|
||||
$this->assertText('The field Maximum alias length is not a valid number.');
|
||||
$this->assertText('The field Maximum component length is not a valid number.');
|
||||
$this->assertNoText('The configuration options have been saved.');
|
||||
|
||||
$edit['pathauto_max_length'] = '0';
|
||||
$edit['pathauto_max_component_length'] = '0';
|
||||
$this->drupalPost('admin/build/path/pathauto', $edit, 'Save configuration');
|
||||
$this->assertText('The field Maximum alias length cannot be less than 1.');
|
||||
$this->assertText('The field Maximum component length cannot be less than 1.');
|
||||
$this->assertNoText('The configuration options have been saved.');
|
||||
|
||||
$edit['pathauto_max_length'] = '999';
|
||||
$edit['pathauto_max_component_length'] = '999';
|
||||
$this->drupalPost('admin/build/path/pathauto', $edit, 'Save configuration');
|
||||
$this->assertText('The field Maximum alias length cannot be greater than 128.');
|
||||
$this->assertText('The field Maximum component length cannot be greater than 128.');
|
||||
$this->assertNoText('The configuration options have been saved.');
|
||||
|
||||
$edit['pathauto_max_length'] = '50';
|
||||
$edit['pathauto_max_component_length'] = '50';
|
||||
$this->drupalPost('admin/build/path/pathauto', $edit, 'Save configuration');
|
||||
$this->assertText('The configuration options have been saved.');
|
||||
}
|
||||
|
||||
function testPatternsValidation() {
|
||||
$edit = array();
|
||||
$edit['pathauto_node_pattern'] = '[title-raw]/[user-created-small]/[cat]/[term]';
|
||||
$edit['pathauto_node_page_pattern'] = 'page';
|
||||
$this->drupalPost('admin/build/path/pathauto', $edit, 'Save configuration');
|
||||
$this->assertText('The Default path pattern (applies to all node types with blank patterns below) is using the following invalid tokens: [user-created-small], [cat].');
|
||||
$this->assertText('The Pattern for all Page paths should contain at least one token to ensure unique URL aliases are created.');
|
||||
$this->assertNoText('The configuration options have been saved.');
|
||||
|
||||
$edit['pathauto_node_pattern'] = '[title-raw]';
|
||||
$edit['pathauto_node_page_pattern'] = 'page/[title-raw]';
|
||||
$edit['pathauto_node_story_pattern'] = '';
|
||||
$this->drupalPost('admin/build/path/pathauto', $edit, 'Save configuration');
|
||||
$this->assertText('The configuration options have been saved.');
|
||||
}
|
||||
}
|
||||
|
||||
class PathautoLocaleTestCase extends PathautoFunctionalTestHelper {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Pathauto localization tests',
|
||||
'description' => 'Test pathauto functionality with localization and translation.',
|
||||
'group' => 'Pathauto',
|
||||
'dependencies' => array('token'),
|
||||
);
|
||||
}
|
||||
|
||||
function setUp(array $modules = array()) {
|
||||
$modules[] = 'locale';
|
||||
$modules[] = 'translation';
|
||||
parent::setUp($modules, array('administer languages'));
|
||||
|
||||
// Add predefined French language and reset the locale cache.
|
||||
require_once './includes/locale.inc';
|
||||
locale_add_language('fr', NULL, NULL, LANGUAGE_LTR, '', 'fr');
|
||||
language_list('language', TRUE);
|
||||
drupal_init_language();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that when an English node is updated, its old English alias is
|
||||
* updated and its newer French alias is left intact.
|
||||
*/
|
||||
function testLanguageAliases() {
|
||||
$node = array(
|
||||
'title' => 'English node',
|
||||
'language' => 'en',
|
||||
'path' => 'english-node',
|
||||
'pathauto_perform_alias' => FALSE,
|
||||
);
|
||||
$node = $this->drupalCreateNode($node);
|
||||
$english_alias = $this->path_load(array('alias' => 'english-node'));
|
||||
$this->assertTrue($english_alias, 'Alias created with proper language.');
|
||||
|
||||
// Also save a French alias that should not be left alone, even though
|
||||
// it is the newer alias.
|
||||
$this->saveEntityAlias('node', $node, 'french-node', 'fr');
|
||||
|
||||
// Add an alias with the soon-to-be generated alias, causing the upcoming
|
||||
// alias update to generate a unique alias with the '-0' suffix.
|
||||
$this->saveAlias('node/invalid', 'content/english-node', '');
|
||||
|
||||
// Update the node, triggering a change in the English alias.
|
||||
$node->pathauto_perform_alias = TRUE;
|
||||
pathauto_nodeapi($node, 'update');
|
||||
|
||||
// Check that the new English alias replaced the old one.
|
||||
$this->assertEntityAlias('node', $node, 'content/english-node-0', 'en');
|
||||
$this->assertEntityAlias('node', $node, 'french-node', 'fr');
|
||||
$this->assertAliasExists(array('pid' => $english_alias['pid'], 'alias' => 'content/english-node-0'));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Unit tests for the book tokens provided by Pathauto.
|
||||
*/
|
||||
class PathautoBookTokenTestCase extends PathautoTestHelper {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Pathauto book tokens',
|
||||
'description' => 'Unit tests for the book tokens provided by Pathauto.',
|
||||
'group' => 'Pathauto',
|
||||
'dependencies' => array('token'),
|
||||
);
|
||||
}
|
||||
|
||||
function setUp(array $modules = array()) {
|
||||
$modules[] = 'book';
|
||||
parent::setUp($modules);
|
||||
|
||||
variable_set('book_allowed_types', array('book', 'page'));
|
||||
variable_set('pathauto_node_book_pattern', '[bookpathalias]/[title-raw]');
|
||||
}
|
||||
|
||||
function testBookPathAlias() {
|
||||
// Add a non-book node.
|
||||
$non_book_node = $this->drupalCreateNode(array('type' => 'book'));
|
||||
$this->assertToken('node', $non_book_node, 'bookpathalias', '');
|
||||
|
||||
// Add a root book page.
|
||||
$parent_node = $this->drupalCreateNode(array(
|
||||
'type' => 'book',
|
||||
'title' => 'Root',
|
||||
'book' => array('bid' => 'new') + _book_link_defaults('new'),
|
||||
));
|
||||
$tokens = array(
|
||||
'bookpathalias' => '',
|
||||
);
|
||||
$this->assertTokens('node', $parent_node, $tokens);
|
||||
|
||||
// Add a first child page.
|
||||
$child_node1 = $this->drupalCreateNode(array(
|
||||
'type' => 'book',
|
||||
'title' => 'Sub page1',
|
||||
'book' => array(
|
||||
'bid' => $parent_node->book['bid'],
|
||||
'plid' => $parent_node->book['mlid'],
|
||||
) + _book_link_defaults('new'),
|
||||
));
|
||||
$tokens = array(
|
||||
'bookpathalias' => 'root',
|
||||
);
|
||||
$this->assertTokens('node', $child_node1, $tokens);
|
||||
|
||||
// Add a second child page.
|
||||
$child_node2 = $this->drupalCreateNode(array(
|
||||
'type' => 'book',
|
||||
'title' => 'Sub page2',
|
||||
'book' => array(
|
||||
'bid' => $parent_node->book['bid'],
|
||||
'plid' => $parent_node->book['mlid'],
|
||||
) + _book_link_defaults('new'),
|
||||
));
|
||||
$tokens = array(
|
||||
'bookpathalias' => 'root',
|
||||
);
|
||||
$this->assertTokens('node', $child_node2, $tokens);
|
||||
|
||||
// Add a child page on an existing child page.
|
||||
$sub_child_node1 = $this->drupalCreateNode(array(
|
||||
'type' => 'book',
|
||||
'title' => 'Sub-sub Page1',
|
||||
'book' => array(
|
||||
'bid' => $parent_node->book['bid'],
|
||||
'plid' => $child_node1->book['mlid'],
|
||||
) + _book_link_defaults('new'),
|
||||
));
|
||||
$tokens = array(
|
||||
'bookpathalias' => 'root/sub-page1',
|
||||
);
|
||||
$this->assertTokens('node', $sub_child_node1, $tokens);
|
||||
|
||||
// Test that path tokens should not be altered.
|
||||
$this->saveEntityAlias('node', $child_node1, 'My Crazy/Alias/');
|
||||
pathauto_nodeapi($sub_child_node1, 'update');
|
||||
$this->assertEntityAlias('node', $sub_child_node1, 'My Crazy/Alias/sub-sub-page1');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Unit tests for the taxonomy tokens provided by Pathauto.
|
||||
*/
|
||||
class PathautoTaxonomyTokenTestCase extends PathautoFunctionalTestHelper {
|
||||
protected $vocab;
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Pathauto taxonomy tokens',
|
||||
'description' => 'Unit tests for the taxonomy tokens provided by Pathauto.',
|
||||
'group' => 'Pathauto',
|
||||
'dependencies' => array('token'),
|
||||
);
|
||||
}
|
||||
|
||||
function setUp(array $modules = array()) {
|
||||
$modules[] = 'taxonomy';
|
||||
parent::setUp($modules);
|
||||
|
||||
variable_set('pathauto_taxonomy_pattern', 'category/[vocab-raw]/[cat-raw]');
|
||||
// Reset the static taxonomy.module caches.
|
||||
taxonomy_vocabulary_load(0, TRUE);
|
||||
taxonomy_get_term(0, TRUE);
|
||||
$this->vocab = $this->addVocabulary();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the [catpath] and [catalias] tokens.
|
||||
*/
|
||||
function testCatTokens() {
|
||||
$term1 = $this->addTerm($this->vocab);
|
||||
$tokens = array(
|
||||
'catpath' => $term1->name,
|
||||
'catalias' => "category/{$this->vocab->name}/{$term1->name}",
|
||||
);
|
||||
$this->assertTokens('taxonomy', $term1, $tokens);
|
||||
|
||||
// Change the term name to check that the alias is also changed.
|
||||
// Regression test for http://drupal.org/node/822174.
|
||||
$term1->oldname = $term1->name;
|
||||
$term1->name = drupal_strtolower($this->randomName());
|
||||
$form_values = (array) $term1;
|
||||
taxonomy_save_term($form_values);
|
||||
$tokens = array(
|
||||
'catpath' => $term1->name,
|
||||
);
|
||||
$this->assertTokens('taxonomy', $term1, $tokens);
|
||||
|
||||
$term2 = $this->addTerm($this->vocab, array('parent' => $term1->tid));
|
||||
$tokens = array(
|
||||
'catpath' => "{$term1->name}/{$term2->name}",
|
||||
'catalias' => "category/{$this->vocab->name}/{$term2->name}",
|
||||
);
|
||||
$this->assertTokens('taxonomy', $term2, $tokens);
|
||||
|
||||
$term3 = $this->addTerm($this->vocab, array('parent' => $term2->tid, 'name' => ' foo/bar fer|zle '));
|
||||
$tokens = array(
|
||||
'catpath' => "{$term1->name}/{$term2->name}/foobar-ferzle",
|
||||
'catalias' => "category/{$this->vocab->name}/foobar-ferzle",
|
||||
);
|
||||
$this->assertTokens('taxonomy', $term3, $tokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the [termpath] token.
|
||||
*/
|
||||
function testTermTokens() {
|
||||
$term1 = $this->addTerm($this->vocab, array('weight' => 5));
|
||||
$term2 = $this->addTerm($this->vocab, array('weight' => -5));
|
||||
$term3 = $this->addTerm($this->vocab, array('weight' => 0));
|
||||
|
||||
$node = $this->drupalCreateNode(array(
|
||||
'type' => 'story',
|
||||
'taxonomy' => array($term1->tid, $term2->tid, $term3->tid),
|
||||
));
|
||||
$tokens = array(
|
||||
'termpath' => $term2->name,
|
||||
'termalias' => "category/{$this->vocab->name}/{$term2->name}",
|
||||
);
|
||||
$this->assertTokens('node', $node, $tokens);
|
||||
$this->assertToken('node', $node, 'termpath', $term2->name);
|
||||
$this->assertToken('node', $node, 'termalias', "category/{$this->vocab->name}/{$term2->name}");
|
||||
|
||||
$non_term_node = $this->drupalCreateNode(array('type' => 'story'));
|
||||
$tokens = array(
|
||||
'termpath' => '',
|
||||
'termalias' => '',
|
||||
);
|
||||
$this->assertTokens('node', $non_term_node, $tokens);
|
||||
}
|
||||
}
|
117
modules/pathauto/pathauto_node.inc
Normal file
117
modules/pathauto/pathauto_node.inc
Normal file
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Hook implementations for node module integration.
|
||||
*
|
||||
* @ingroup pathauto
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_pathauto().
|
||||
*/
|
||||
function node_pathauto($op) {
|
||||
switch ($op) {
|
||||
case 'settings':
|
||||
$settings = array();
|
||||
$settings['module'] = 'node';
|
||||
$settings['token_type'] = 'node';
|
||||
$settings['groupheader'] = t('Node paths');
|
||||
$settings['patterndescr'] = t('Default path pattern (applies to all node types with blank patterns below)');
|
||||
$settings['patterndefault'] = 'content/[title-raw]';
|
||||
$settings['bulkname'] = t('Bulk generate aliases for nodes that are not aliased');
|
||||
$settings['bulkdescr'] = t('Generate aliases for all existing nodes which do not already have aliases.');
|
||||
|
||||
$patterns = token_get_list('node');
|
||||
foreach ($patterns as $type => $pattern_set) {
|
||||
if ($type != 'global') {
|
||||
foreach ($pattern_set as $pattern => $description) {
|
||||
$settings['placeholders']['['. $pattern .']'] = $description;
|
||||
}
|
||||
}
|
||||
}
|
||||
$settings['supportsfeeds'] = 'feed';
|
||||
|
||||
if (module_exists('locale')) {
|
||||
$languages = array('' => t('Language neutral')) + locale_language_list('name');
|
||||
}
|
||||
else {
|
||||
$languages = array();
|
||||
}
|
||||
foreach (node_get_types('names') as $node_type => $node_name) {
|
||||
if (variable_get('language_content_type_'. $node_type, 0) && count($languages)) {
|
||||
$settings['patternitems'][$node_type] = t('Default path pattern for @node_type (applies to all @node_type node types with blank patterns below)', array('@node_type' => $node_name));
|
||||
foreach ($languages as $lang_code => $lang_name) {
|
||||
if (!empty($lang_code)) {
|
||||
$settings['patternitems'][$node_type .'_'. $lang_code] = t('Pattern for all @node_type paths in @language', array('@node_type' => $node_name, '@language' => $lang_name));
|
||||
}
|
||||
else {
|
||||
$settings['patternitems'][$node_type .'_'. $lang_code] = t('Pattern for all language neutral @node_type paths', array('@node_type' => $node_name));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$settings['patternitems'][$node_type] = t('Pattern for all @node_type paths', array('@node_type' => $node_name));
|
||||
}
|
||||
}
|
||||
return (object) $settings;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate aliases for all nodes without aliases.
|
||||
*/
|
||||
function node_pathauto_bulkupdate() {
|
||||
// From all node types, only attempt to update those with patterns
|
||||
$pattern_types = array();
|
||||
|
||||
// If there's a default pattern we assume all types might be updated.
|
||||
if (trim(variable_get('pathauto_node_pattern', ''))) {
|
||||
$pattern_types = array_keys(node_get_types('names'));
|
||||
}
|
||||
else {
|
||||
// Check first for a node specific pattern...
|
||||
$languages = array();
|
||||
if (module_exists('locale')) {
|
||||
$languages = array('' => t('Language neutral')) + locale_language_list('name');
|
||||
}
|
||||
foreach (array_keys(node_get_types('names')) as $type) {
|
||||
if (trim(variable_get('pathauto_node_'. $type .'_pattern', ''))) {
|
||||
$pattern_types[$type] = $type;
|
||||
continue;
|
||||
}
|
||||
// ...then for a node-language pattern.
|
||||
if (variable_get('language_content_type_'. $type, 0) && $languages) {
|
||||
foreach ($languages as $lang_code => $lang_name) {
|
||||
if (trim(variable_get('pathauto_node_'. $type .'_'. $lang_code .'_pattern', ''))) {
|
||||
$pattern_types[$type] = $type;
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
if (count($pattern_types)) {
|
||||
$concat = _pathauto_sql_concat("'node/'", 'n.nid');
|
||||
$sql = "SELECT n.nid FROM {node} n LEFT JOIN {url_alias} ua ON $concat = ua.src WHERE ua.src IS NULL AND n.type IN (". db_placeholders($pattern_types, 'varchar') .')';
|
||||
$query = db_query_range($sql, $pattern_types, 0, variable_get('pathauto_max_bulk_update', 50));
|
||||
|
||||
$placeholders = array();
|
||||
while ($nid = db_result($query)) {
|
||||
$node = node_load($nid, NULL, TRUE);
|
||||
$placeholders = pathauto_get_placeholders('node', $node);
|
||||
$source = "node/$node->nid";
|
||||
if (pathauto_create_alias('node', 'bulkupdate', $placeholders, $source, $node->nid, $node->type, $node->language)) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drupal_set_message(format_plural($count,
|
||||
'Bulk generation of nodes completed, one alias generated.',
|
||||
'Bulk generation of nodes completed, @count aliases generated.'));
|
||||
}
|
169
modules/pathauto/pathauto_taxonomy.inc
Normal file
169
modules/pathauto/pathauto_taxonomy.inc
Normal file
|
@ -0,0 +1,169 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Hook implementations for taxonomy module integration.
|
||||
*
|
||||
* @ingroup pathauto
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_pathauto().
|
||||
*/
|
||||
function taxonomy_pathauto($op) {
|
||||
switch ($op) {
|
||||
case 'settings':
|
||||
$settings = array();
|
||||
$settings['module'] = 'taxonomy';
|
||||
$settings['token_type'] = 'taxonomy';
|
||||
$settings['groupheader'] = t('Taxonomy term paths');
|
||||
$settings['patterndescr'] = t('Default path pattern (applies to all vocabularies with blank patterns below)');
|
||||
$settings['patterndefault'] = 'category/[vocab-raw]/[catpath-raw]';
|
||||
$patterns = token_get_list('taxonomy');
|
||||
foreach ($patterns as $type => $pattern_set) {
|
||||
if ($type != 'global') {
|
||||
foreach ($pattern_set as $pattern => $description) {
|
||||
$settings['placeholders']['['. $pattern .']'] = $description;
|
||||
}
|
||||
}
|
||||
}
|
||||
$settings['supportsfeeds'] = '0/feed';
|
||||
$settings['bulkname'] = t('Bulk generate aliases for terms that are not aliased');
|
||||
$settings['bulkdescr'] = t('Generate aliases for all existing terms which do not already have aliases.');
|
||||
|
||||
$vocabularies = taxonomy_get_vocabularies();
|
||||
if (sizeof($vocabularies) > 0) {
|
||||
$settings['patternitems'] = array();
|
||||
$forum_vid = variable_get('forum_nav_vocabulary', '');
|
||||
foreach ($vocabularies as $vocab) {
|
||||
if ($vocab->vid != $forum_vid) {
|
||||
$vocabname = $vocab->name;
|
||||
$fieldlabel = t('Pattern for all %vocab-name paths', array('%vocab-name' => $vocabname));
|
||||
$settings['patternitems'][$vocab->vid] = $fieldlabel;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (object) $settings;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate aliases for all categories without aliases.
|
||||
*/
|
||||
function taxonomy_pathauto_bulkupdate() {
|
||||
// From all node types, only attempt to update those with patterns
|
||||
$pattern_vids = array();
|
||||
foreach (taxonomy_get_vocabularies() as $vid => $info) {
|
||||
// Exclude forum module's vocabulary.
|
||||
if ($vid == variable_get('forum_nav_vocabulary', '')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$pattern = trim(variable_get('pathauto_taxonomy_'. $vid .'_pattern', ''));
|
||||
|
||||
// If it's not set, check the default
|
||||
// TODO - If there's a default we shouldn't do this crazy where statement because all vocabs get aliases
|
||||
// TODO - Special casing to exclude the forum vid (and the images vid and...?)
|
||||
if (empty($pattern)) {
|
||||
$pattern = trim(variable_get('pathauto_taxonomy_pattern', ''));
|
||||
}
|
||||
if (!empty($pattern)) {
|
||||
$pattern_vids[] = $vid;
|
||||
}
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
if (!empty($pattern_vids)) {
|
||||
$concat = _pathauto_sql_concat("'taxonomy/term/'", 'td.tid');
|
||||
$sql = "SELECT td.tid FROM {term_data} td LEFT JOIN {url_alias} ua ON $concat = ua.src WHERE ua.src IS NULL AND td.vid IN (" . db_placeholders($pattern_vids, 'int') . ")";
|
||||
$query = db_query_range($sql, $pattern_vids, 0, variable_get('pathauto_max_bulk_update', 50));
|
||||
|
||||
while ($tid = db_result($query)) {
|
||||
$term = taxonomy_get_term($tid);
|
||||
$count += _taxonomy_pathauto_alias($term, 'bulkupdate');
|
||||
}
|
||||
}
|
||||
|
||||
drupal_set_message(format_plural($count,
|
||||
'Bulk generation of terms completed, one alias generated.',
|
||||
'Bulk generation of terms completed, @count aliases generated.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create aliases for taxonomy objects.
|
||||
*
|
||||
* @param $category
|
||||
* A taxonomy object.
|
||||
*/
|
||||
function _taxonomy_pathauto_alias($category, $op) {
|
||||
$count = 0;
|
||||
|
||||
$placeholders = pathauto_get_placeholders('taxonomy', $category);
|
||||
|
||||
$forum_vid = variable_get('forum_nav_vocabulary', '');
|
||||
// If we're in a forum vocabulary, also create a forum container, forum, or forum topic alias.
|
||||
if (module_exists('forum') && $forum_vid == (int)$category->vid) {
|
||||
$source = 'forum/'. $category->tid;
|
||||
if (pathauto_create_alias('forum', $op, $placeholders, $source, $category->tid, $category->vid)) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$source = taxonomy_term_path($category);
|
||||
if (pathauto_create_alias('taxonomy', $op, $placeholders, $source, $category->tid, $category->vid)) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_pathauto() for forum module.
|
||||
*/
|
||||
function forum_pathauto($op) {
|
||||
switch ($op) {
|
||||
case 'settings':
|
||||
$settings = array();
|
||||
$settings['module'] = 'forum';
|
||||
$settings['token_type'] = 'taxonomy';
|
||||
$settings['groupheader'] = t('Forum paths');
|
||||
$settings['patterndescr'] = t('Pattern for forums and forum containers');
|
||||
$settings['patterndefault'] = '[vocab-raw]/[catpath-raw]';
|
||||
$patterns = token_get_list('taxonomy');
|
||||
foreach ($patterns as $type => $pattern_set) {
|
||||
if ($type != 'global') {
|
||||
foreach ($pattern_set as $pattern => $description) {
|
||||
$settings['placeholders']['['. $pattern .']'] = $description;
|
||||
}
|
||||
}
|
||||
}
|
||||
$settings['supportsfeeds'] = '0/feed';
|
||||
$settings['bulkname'] = t('Bulk generate aliases for forum paths that are not aliased');
|
||||
$settings['bulkdescr'] = t('Generate aliases for all existing forums and forum containers which do not already have aliases.');
|
||||
return (object) $settings;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate aliases for all forums and forum containers without aliases.
|
||||
*/
|
||||
function forum_pathauto_bulkupdate() {
|
||||
$concat = _pathauto_sql_concat("'forum/'", 'td.tid');
|
||||
$forum_vid = variable_get('forum_nav_vocabulary', '');
|
||||
$sql = "SELECT td.tid FROM {term_data} td LEFT JOIN {url_alias} ua ON $concat = ua.src WHERE ua.src IS NULL AND td.vid = %d";
|
||||
$query = db_query_range($sql, $forum_vid, 0, variable_get('pathauto_max_bulk_update', 50));
|
||||
|
||||
$count = 0;
|
||||
while ($tid = db_result($query)) {
|
||||
$term = taxonomy_get_term($tid);
|
||||
$count += _taxonomy_pathauto_alias($term, 'bulkupdate');
|
||||
}
|
||||
|
||||
drupal_set_message(format_plural($count,
|
||||
'Bulk update of forums and forum containers completed, one alias generated.',
|
||||
'Bulk update of forums and forum containers completed, @count aliases generated.'));
|
||||
}
|
205
modules/pathauto/pathauto_user.inc
Normal file
205
modules/pathauto/pathauto_user.inc
Normal file
|
@ -0,0 +1,205 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Hook implementations for user module integration.
|
||||
*
|
||||
* @ingroup pathauto
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_pathauto().
|
||||
*/
|
||||
function user_pathauto($op) {
|
||||
switch ($op) {
|
||||
case 'settings':
|
||||
$settings = array();
|
||||
$settings['module'] = 'user';
|
||||
$settings['token_type'] = 'user';
|
||||
$settings['groupheader'] = t('User paths');
|
||||
$settings['patterndescr'] = t('Pattern for user account page paths');
|
||||
$settings['patterndefault'] = 'users/[user-raw]';
|
||||
$patterns = token_get_list('user');
|
||||
foreach ($patterns as $type => $pattern_set) {
|
||||
if ($type != 'global') {
|
||||
foreach ($pattern_set as $pattern => $description) {
|
||||
$settings['placeholders']['['. $pattern .']'] = $description;
|
||||
}
|
||||
}
|
||||
}
|
||||
$settings['bulkname'] = t('Bulk generate aliases for users that are not aliased');
|
||||
$settings['bulkdescr'] = t('Generate aliases for all existing user account pages which do not already have aliases.');
|
||||
return (object) $settings;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_pathauto().
|
||||
*/
|
||||
function blog_pathauto($op) {
|
||||
switch ($op) {
|
||||
case 'settings':
|
||||
$settings = array();
|
||||
$settings['module'] = 'blog';
|
||||
$settings['token_type'] = 'user';
|
||||
$settings['groupheader'] = t('Blog paths');
|
||||
$settings['patterndescr'] = t('Pattern for blog page paths');
|
||||
$settings['patterndefault'] = 'blogs/[user-raw]';
|
||||
$patterns = token_get_list('user');
|
||||
foreach ($patterns['user'] as $pattern => $description) {
|
||||
$settings['placeholders']['['. $pattern .']'] = $description;
|
||||
}
|
||||
$settings['supportsfeeds'] = 'feed';
|
||||
$settings['bulkname'] = t('Bulk generate aliases for blogs that are not aliased');
|
||||
$settings['bulkdescr'] = t('Generate aliases for all existing blog pages which do not already have aliases.');
|
||||
return (object) $settings;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_pathauto() for user-tracker aliases.
|
||||
*/
|
||||
function tracker_pathauto($op) {
|
||||
switch ($op) {
|
||||
case 'settings':
|
||||
$settings = array();
|
||||
$settings['module'] = 'tracker';
|
||||
$settings['token_type'] = 'user';
|
||||
$settings['groupheader'] = t('User tracker paths');
|
||||
$settings['patterndescr'] = t('Pattern for user-tracker page paths');
|
||||
$settings['patterndefault'] = 'users/[user-raw]/track';
|
||||
$patterns = token_get_list('user');
|
||||
foreach ($patterns['user'] as $pattern => $description) {
|
||||
$settings['placeholders']['['. $pattern .']'] = $description;
|
||||
}
|
||||
$settings['supportsfeeds'] = 'feed';
|
||||
$settings['bulkname'] = t('Bulk generate aliases for user-tracker paths that are not aliased');
|
||||
$settings['bulkdescr'] = t('Generate aliases for all existing user-tracker pages which do not already have aliases.');
|
||||
return (object) $settings;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_pathauto().
|
||||
*/
|
||||
function contact_pathauto($op) {
|
||||
switch ($op) {
|
||||
case 'settings':
|
||||
$settings = array();
|
||||
$settings['module'] = 'contact';
|
||||
$settings['token_type'] = 'user';
|
||||
$settings['groupheader'] = t('User contact forms paths');
|
||||
$settings['patterndescr'] = t('Pattern for the user contact form paths');
|
||||
$settings['patterndefault'] = 'users/[user-raw]/contact';
|
||||
$patterns = token_get_list('user');
|
||||
foreach ($patterns['user'] as $pattern => $description) {
|
||||
$settings['placeholders']['['. $pattern .']'] = $description;
|
||||
}
|
||||
$settings['bulkname'] = t('Bulk generate aliases for user contact form paths that are not aliased');
|
||||
$settings['bulkdescr'] = t('Generate aliases for all existing user contact form pages which do not already have aliases.');
|
||||
return (object) $settings;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk generate aliases for all users without aliases.
|
||||
*/
|
||||
function user_pathauto_bulkupdate() {
|
||||
$concat = _pathauto_sql_concat("'user/'", 'u.uid');
|
||||
$sql = "SELECT u.uid FROM {users} u LEFT JOIN {url_alias} ua ON $concat = ua.src WHERE u.uid > 0 AND ua.src IS NULL";
|
||||
$query = db_query_range($sql, 0, variable_get('pathauto_max_bulk_update', 50));
|
||||
|
||||
$count = 0;
|
||||
$placeholders = array();
|
||||
while ($uid = db_result($query)) {
|
||||
$account = user_load($uid);
|
||||
$placeholders = pathauto_get_placeholders('user', $account);
|
||||
$source = 'user/'. $account->uid;
|
||||
if (pathauto_create_alias('user', 'bulkupdate', $placeholders, $source, $account->uid)) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
drupal_set_message(format_plural($count,
|
||||
'Bulk generation of users completed, one alias generated.',
|
||||
'Bulk generation of users completed, @count aliases generated.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk generate aliases for all blogs without aliases.
|
||||
*/
|
||||
function blog_pathauto_bulkupdate() {
|
||||
$concat = _pathauto_sql_concat("'blog/'", 'u.uid');
|
||||
$sql = "SELECT u.uid FROM {users} u LEFT JOIN {url_alias} ua ON $concat = ua.src WHERE u.uid > 0 AND ua.src IS NULL";
|
||||
$query = db_query_range($sql, 0, variable_get('pathauto_max_bulk_update', 50));
|
||||
|
||||
$count = 0;
|
||||
$placeholders = array();
|
||||
while ($uid = db_result($query)) {
|
||||
$account = user_load($uid);
|
||||
$placeholders = pathauto_get_placeholders('user', $account);
|
||||
$source = 'blog/'. $account->uid;
|
||||
if (pathauto_create_alias('blog', 'bulkupdate', $placeholders, $source, $account->uid)) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
drupal_set_message(format_plural($count,
|
||||
'Bulk generation of user blogs completed, one alias generated.',
|
||||
'Bulk generation of user blogs completed, @count aliases generated.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk generate aliases for user trackers without aliases.
|
||||
*/
|
||||
function tracker_pathauto_bulkupdate() {
|
||||
$concat = _pathauto_sql_concat("'user/'", 'u.uid', "'/track'");
|
||||
$sql = "SELECT u.uid FROM {users} u LEFT JOIN {url_alias} ua ON $concat = ua.src WHERE u.uid > 0 AND ua.src IS NULL";
|
||||
$query = db_query_range($sql, 0, variable_get('pathauto_max_bulk_update', 50));
|
||||
|
||||
$count = 0;
|
||||
$placeholders = array();
|
||||
while ($uid = db_result($query)) {
|
||||
$account = user_load($uid);
|
||||
$placeholders = pathauto_get_placeholders('user', $account);
|
||||
$src = 'user/'. $account->uid .'/track';
|
||||
if (pathauto_create_alias('tracker', 'bulkupdate', $placeholders, $src, $account->uid)) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
drupal_set_message(format_plural($count,
|
||||
'Bulk generation of user tracker pages completed, one alias generated.',
|
||||
'Bulk generation of user tracker pages completed, @count aliases generated.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk generate aliases for all users without aliases
|
||||
*/
|
||||
function contact_pathauto_bulkupdate() {
|
||||
$sql = "SELECT u.uid FROM {users} u LEFT JOIN {url_alias} ua ON CONCAT(CONCAT('user/', CAST(u.uid AS CHAR)), '/contact') = ua.src WHERE u.uid > 0 AND ua.src IS NULL";
|
||||
$query = db_query_range($sql, 0, variable_get('pathauto_max_bulk_update', 50));
|
||||
|
||||
$count = 0;
|
||||
$placeholders = array();
|
||||
while ($uid = db_result($query)) {
|
||||
$account = user_load($uid);
|
||||
$placeholders = pathauto_get_placeholders('user', $account);
|
||||
$source = 'user/'. $account->uid .'/contact';
|
||||
if (pathauto_create_alias('contact', 'bulkupdate', $placeholders, $source, $account->uid)) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
drupal_set_message(format_plural($count,
|
||||
'Bulk generation of contact pages completed, one alias generated.',
|
||||
'Bulk generation of contact pages completed, @count aliases generated.'));
|
||||
}
|
Reference in a new issue