FINAL suepr merge step : added all modules to this super repos
This commit is contained in:
339
sites/all/modules/contrib/migrate/migrate_extras/LICENSE.txt
Normal file
339
sites/all/modules/contrib/migrate/migrate_extras/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.
|
46
sites/all/modules/contrib/migrate/migrate_extras/README.txt
Normal file
46
sites/all/modules/contrib/migrate/migrate_extras/README.txt
Normal file
@@ -0,0 +1,46 @@
|
||||
The Migrate Extras module provides extensions to Migrate (http://drupal.org/project/migrate)
|
||||
to support various contributed modules. The ideal place to implement migration support
|
||||
for a contributed module is in that module. That way, the migration support is always
|
||||
self-consistent with the current module implementation - it's not practical for the
|
||||
migrate_extras module to keep up with changes to all other contrib modules. Support
|
||||
for contributed modules may be added to migrate_extras for two reasons - if the module's
|
||||
maintainer does not accept a patch providing migration support, or as an intermediate
|
||||
step before submitting such a patch to the other module.
|
||||
|
||||
In cases where modules supported by migrate_extras end up implementing the support
|
||||
themselves, you could at least temporarily end up with redundant implementations.
|
||||
The extra implementation may be disabled at admin/content/migrate/configure.
|
||||
|
||||
The following modules are currently supported in Migrate Extras on Drupal 7 (note
|
||||
that Date module support has moved into the Date module itself):
|
||||
|
||||
Address Field
|
||||
Entity API
|
||||
Flag
|
||||
Geofield
|
||||
Interval
|
||||
Media
|
||||
Name Field
|
||||
Pathauto
|
||||
Phone Number (cck_phone)
|
||||
Private Messages
|
||||
Profile2
|
||||
Rules
|
||||
User Relationships
|
||||
Voting API
|
||||
Webform
|
||||
|
||||
Compatibility
|
||||
-------------
|
||||
This release of Migrate Extras requires Migrate V2.4-beta1 or later.
|
||||
|
||||
Migrate_Extras_Examples
|
||||
----------------
|
||||
See the Examples folder for a few implemented Migrations that you can run and
|
||||
inspect.
|
||||
|
||||
Maintainers
|
||||
-----------
|
||||
Frank Carey http://drupal.org/user/112063
|
||||
Mike Ryan - http://drupal.org/user/4420
|
||||
Moshe Weitzman - http://drupal.org/user/23
|
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Primary value passed to this field must be the two letter ISO country code of
|
||||
* the address.
|
||||
*
|
||||
* Arguments are used to specify all the other values:
|
||||
* 'administrative_area' - The administrative area of this address. (i.e. State/Province)
|
||||
* 'sub_administrative_area' - The sub administrative area of this address.
|
||||
* 'locality' - The locality of this address. (i.e. City)
|
||||
* 'dependent_locality' - The dependent locality of this address.
|
||||
* 'postal_code' - The postal code of this address.
|
||||
* 'thoroughfare' - The thoroughfare of this address. (i.e. Street address)
|
||||
* 'premise' - The premise of this address. (i.e. Apartment / Suite number)
|
||||
* 'sub_premise' - The sub_premise of this address.
|
||||
* 'organisation_name' - Contents of a primary OrganisationName element in the xNL XML.
|
||||
* 'name_line' - Contents of a primary NameLine element in the xNL XML.
|
||||
* 'first_name' - Contents of the FirstName element of a primary PersonName element in the xNL XML.
|
||||
* 'last_name' - Contents of the LastName element of a primary PersonName element in the xNL XML.
|
||||
* 'data' - Additional data for this address.
|
||||
*
|
||||
* Add the source field mappings to the argument array then add null mappings to
|
||||
* avoid having fields flagged as as unmapped:
|
||||
* @code
|
||||
* $arguments = array(
|
||||
* 'thoroughfare' => array('source_field' => 'profile_address'),
|
||||
* 'locality' => array('source_field' => 'profile_city'),
|
||||
* 'administrative_area' => array('source_field' => 'profile_state'),
|
||||
* );
|
||||
* // The country should be passed in as the primary value.
|
||||
* $this->addFieldMapping('field_user_address', 'profile_country')
|
||||
* ->arguments($arguments);
|
||||
* // Since the excerpt is mapped via an argument, add a null mapping so it's
|
||||
* // not flagged as unmapped.
|
||||
* $this->addFieldMapping(NULL, 'profile_address');
|
||||
* $this->addFieldMapping(NULL, 'profile_city');
|
||||
* $this->addFieldMapping(NULL, 'profile_state');
|
||||
* @endcode
|
||||
*/
|
||||
class MigrateAddressFieldHandler extends MigrateFieldHandler {
|
||||
public function __construct() {
|
||||
$this->registerTypes(array('addressfield'));
|
||||
}
|
||||
|
||||
public function prepare($entity, array $field_info, array $instance, array $values) {
|
||||
$arguments = array();
|
||||
if (isset($values['arguments'])) {
|
||||
$arguments = array_filter($values['arguments']);
|
||||
unset($values['arguments']);
|
||||
}
|
||||
$language = $this->getFieldLanguage($entity, $field_info, $arguments);
|
||||
|
||||
// Setup the standard Field API array for saving.
|
||||
$delta = 0;
|
||||
foreach ($values as $value) {
|
||||
$return[$language][$delta] = array('country' => $value) + array_intersect_key($arguments, $field_info['columns']);
|
||||
$delta++;
|
||||
}
|
||||
|
||||
return isset($return) ? $return : NULL;
|
||||
}
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Primary value passed to this field must be the two letter ISO country code of
|
||||
* the phone number.
|
||||
*
|
||||
* Subfields are used to specify all the other values:
|
||||
* 'number' - The actual phone number.
|
||||
* 'extension' - The extension.
|
||||
*
|
||||
* @code
|
||||
* // The country should be passed in as the primary value.
|
||||
* $this->addFieldMapping('field_user_phone', 'profile_country');
|
||||
* $this->addFieldMapping('field_user_phone:number', 'profile_number');
|
||||
* $this->addFieldMapping('field_user_phone:extension', 'profile_extension');
|
||||
* @endcode
|
||||
*/
|
||||
class MigrateCckPhoneHandler extends MigrateFieldHandler {
|
||||
public function __construct() {
|
||||
$this->registerTypes(array('phone_number'));
|
||||
}
|
||||
|
||||
public function fields($type) {
|
||||
return array(
|
||||
'number' => t('Subfield: The phone number itself'),
|
||||
'extension' => t('Extension: An optional extension'),
|
||||
);
|
||||
}
|
||||
|
||||
public function prepare($entity, array $field_info, array $instance, array $values) {
|
||||
$arguments = array();
|
||||
if (isset($values['arguments'])) {
|
||||
$arguments = array_filter($values['arguments']);
|
||||
unset($values['arguments']);
|
||||
}
|
||||
$language = $this->getFieldLanguage($entity, $field_info, $arguments);
|
||||
|
||||
// Setup the standard Field API array for saving.
|
||||
$delta = 0;
|
||||
foreach ($values as $value) {
|
||||
$return[$language][$delta] = array('country_codes' => drupal_strtolower($value));
|
||||
if (isset($arguments['number'])) {
|
||||
if (is_array($arguments['number'])) {
|
||||
$return[$language][$delta]['number'] = $arguments['number'][$delta];
|
||||
}
|
||||
else {
|
||||
$return[$language][$delta]['number'] = $arguments['number'];
|
||||
}
|
||||
}
|
||||
if (isset($arguments['extension'])) {
|
||||
if (is_array($arguments['extension'])) {
|
||||
$return[$language][$delta]['extension'] = $arguments['extension'][$delta];
|
||||
}
|
||||
else {
|
||||
$return[$language][$delta]['extension'] = $arguments['extension'];
|
||||
}
|
||||
}
|
||||
$delta++;
|
||||
}
|
||||
|
||||
return isset($return) ? $return : NULL;
|
||||
}
|
||||
}
|
275
sites/all/modules/contrib/migrate/migrate_extras/entity_api.inc
Normal file
275
sites/all/modules/contrib/migrate/migrate_extras/entity_api.inc
Normal file
@@ -0,0 +1,275 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Support for entity types implementing the Entity API.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Destination class implementing migration into entity types.
|
||||
*
|
||||
* To make entity properties that correspond to columns in the entity's base
|
||||
* table available as FieldMapping destinations, they must be present in Entity
|
||||
* API's entity property info and have setter callbacks defined. Because the
|
||||
* EntityDefaultMetadataController doesn't add setter callbacks to the default
|
||||
* entity property info it produces, the custom entity needs to provide this
|
||||
* either in an implementation of hook_entity_property_info(), or via EntityAPI
|
||||
* in a custom metadata controller class.
|
||||
*/
|
||||
class MigrateDestinationEntityAPI extends MigrateDestinationEntity {
|
||||
|
||||
/**
|
||||
* Info about the current entity type.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $info;
|
||||
|
||||
/**
|
||||
* Name of the entity id key (for example, nid for nodes).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* Name of the entity revision key (for example, vid for nodes).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $revision;
|
||||
|
||||
/**
|
||||
* Gets the schema for the base key(s) of an entity type.
|
||||
*
|
||||
* @param string $entity_type
|
||||
* A Drupal entity type.
|
||||
*/
|
||||
static public function getKeySchema($entity_type = NULL) {
|
||||
// Migrate UI invokes $destination->getKeySchema() without any parameters.
|
||||
if (!$entity_type) {
|
||||
if (isset($this)) {
|
||||
if ($this instanceof MigrateDestination) {
|
||||
$entity_type = $this->entityType;
|
||||
}
|
||||
elseif ($this instanceof Migration) {
|
||||
$entity_type = $this->destination->entityType;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
$info = entity_get_info($entity_type);
|
||||
$schema = drupal_get_schema($info['base table']);
|
||||
|
||||
$key = isset($info['entity keys']['name']) ? $info['entity keys']['name'] : $info['entity keys']['id'];
|
||||
$key_schema = $schema['fields'][$key];
|
||||
|
||||
$revision_key = isset($info['entity keys']['revision']) ? $info['entity keys']['revision'] : NULL;
|
||||
$revision_schema = empty($revision_key) ? NULL : $schema['fields'][$revision_key];
|
||||
|
||||
// We can't have any form of serial fields here, since the mapping table
|
||||
// already has it's own.
|
||||
$key_schema['auto_increment'] = FALSE;
|
||||
if ($key_schema['type'] == 'serial') {
|
||||
$key_schema['type'] = 'int';
|
||||
}
|
||||
|
||||
$return = array($key => $key_schema);
|
||||
if (!empty($revision_key)) {
|
||||
$return[$revision_key] = $revision_schema;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an options array (language, text_format), used for creating fields.
|
||||
*
|
||||
* @param string $language
|
||||
* @param string $text_format
|
||||
*/
|
||||
static public function options($language, $text_format) {
|
||||
return compact('language', 'text_format');
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic initialization
|
||||
*
|
||||
* @param string $entity_type
|
||||
* @param string $bundle
|
||||
* @param array $options
|
||||
* Options (language, text_format) used for creating fields.
|
||||
*/
|
||||
public function __construct($entity_type, $bundle, array $options = array()) {
|
||||
parent::__construct($entity_type, $bundle, $options);
|
||||
|
||||
$this->info = entity_get_info($entity_type);
|
||||
$this->id = isset($this->info['entity keys']['name']) ? $this->info['entity keys']['name'] : $this->info['entity keys']['id'];
|
||||
$this->revision = isset($this->info['entity keys']['revision']) ? $this->info['entity keys']['revision'] : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of fields available to be mapped for entities attached to
|
||||
* a particular bundle.
|
||||
*
|
||||
* @param Migration $migration
|
||||
* Optionally, the migration containing this destination.
|
||||
* @return array
|
||||
* Keys: machine names of the fields (to be passed to addFieldMapping)
|
||||
* Values: Human-friendly descriptions of the fields.
|
||||
*/
|
||||
public function fields($migration = NULL) {
|
||||
$properties = entity_get_property_info($this->entityType);
|
||||
$fields = array();
|
||||
|
||||
foreach ($properties['properties'] as $name => $property_info) {
|
||||
if (isset($property_info['setter callback'])) {
|
||||
$fields[$name] = $property_info['description'];
|
||||
}
|
||||
}
|
||||
|
||||
// Then add in anything provided by handlers
|
||||
$fields += migrate_handler_invoke_all('Entity', 'fields', $this->entityType, $this->bundle);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes multiple entities.
|
||||
*
|
||||
* @param array $ids
|
||||
* An array of entity ids of the entities to delete.
|
||||
*/
|
||||
public function bulkRollback(array $ids) {
|
||||
migrate_instrument_start('entity_delete_multiple');
|
||||
$this->prepareRollback($ids);
|
||||
$result = entity_delete_multiple($this->entityType, $ids);
|
||||
$this->completeRollback($ids);
|
||||
migrate_instrument_stop('entity_delete_multiple');
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports a single entity.
|
||||
*
|
||||
* @param stdClass $entity
|
||||
* Generic entity object, refilled with any fields mapped in the Migration.
|
||||
* @param stdClass $row
|
||||
* Raw source data object - passed through to prepare/complete handlers.
|
||||
*
|
||||
* @return array
|
||||
* An array of key fields (entity id, and revision id if applicable) of the
|
||||
* entity that was saved if successful. FALSE on failure.
|
||||
*/
|
||||
public function import(stdClass $entity, stdClass $row) {
|
||||
$migration = Migration::currentMigration();
|
||||
|
||||
// Updating previously-migrated content?
|
||||
if (isset($row->migrate_map_destid1)) {
|
||||
if (isset($entity->{$this->id})) {
|
||||
if ($entity->{$this->id} != $row->migrate_map_destid1) {
|
||||
throw new MigrateException(t("Incoming id !id and map destination id !destid1 don't match",
|
||||
array('!id' => $entity->{$this->id}, '!destid1' => $row->migrate_map_destid1)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$entity->{$this->id} = $row->migrate_map_destid1;
|
||||
}
|
||||
}
|
||||
elseif ($migration->getSystemOfRecord() == Migration::SOURCE) {
|
||||
unset($entity->{$this->id});
|
||||
}
|
||||
|
||||
if (isset($row->migrate_map_destid2)) {
|
||||
if (isset($entity->{$this->revision})) {
|
||||
if ($entity->{$this->revision} != $row->migrate_map_destid2) {
|
||||
throw new MigrateException(t("Incoming revision !id and map destination revision !destid2 don't match",
|
||||
array('!id' => $entity->{$this->revision}, '!destid2' => $row->migrate_map_destid2)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$entity->{$this->revision} = $row->migrate_map_destid2;
|
||||
}
|
||||
}
|
||||
|
||||
if ($migration->getSystemOfRecord() == Migration::DESTINATION) {
|
||||
if (!isset($entity->{$this->id})) {
|
||||
throw new MigrateException(t('System-of-record is DESTINATION, but no destination id provided'));
|
||||
}
|
||||
// Load the entity that's being updated, update its values, then
|
||||
// substitute the (fake) passed in entity with that one.
|
||||
$old_entity = entity_load_single($this->entityType, $entity->{$this->id});
|
||||
if (empty($old_entity)) {
|
||||
throw new MigrateException(t("Failed to load entity of type %type and id %id", array('%type' => $this->entityType, '%id' => $entity->{$this->id})));
|
||||
}
|
||||
|
||||
// Prepare the entity to get the right array structure.
|
||||
$this->prepare($entity, $row);
|
||||
|
||||
foreach ($entity as $field => $value) {
|
||||
$old_entity->$field = $entity->$field;
|
||||
}
|
||||
$entity = $old_entity;
|
||||
}
|
||||
else {
|
||||
// Create a real entity object, update its values with the ones we have
|
||||
// and pass it along.
|
||||
$new_entity = array();
|
||||
if (!empty($this->bundle) && !empty($this->info['entity keys']['bundle'])) {
|
||||
$new_entity[$this->info['entity keys']['bundle']] = $this->bundle;
|
||||
}
|
||||
$new_entity = entity_create($this->entityType, $new_entity);
|
||||
foreach ($entity as $field => $value) {
|
||||
$new_entity->$field = $entity->$field;
|
||||
}
|
||||
|
||||
// If a destination id exists, the entity is obviously not new.
|
||||
if (!empty($new_entity->{$this->id}) && isset($new_entity->is_new)) {
|
||||
unset($new_entity->is_new);
|
||||
}
|
||||
$entity = $new_entity;
|
||||
$this->prepare($entity, $row);
|
||||
}
|
||||
|
||||
$updating = (!empty($entity->{$this->id}) && empty($entity->is_new));
|
||||
|
||||
migrate_instrument_start('entity_save');
|
||||
entity_save($this->entityType, $entity);
|
||||
// It's probably not worth keeping the static cache around.
|
||||
entity_get_controller($this->entityType)->resetCache();
|
||||
migrate_instrument_stop('entity_save');
|
||||
|
||||
$this->complete($entity, $row);
|
||||
|
||||
if (isset($entity->{$this->id}) && $entity->{$this->id} > 0) {
|
||||
if ($updating) {
|
||||
$this->numUpdated++;
|
||||
}
|
||||
else {
|
||||
$this->numCreated++;
|
||||
}
|
||||
$return = array($entity->{$this->id});
|
||||
|
||||
if (isset($entity->{$this->revision}) && $entity->{$this->revision} > 0) {
|
||||
$return[] = array($entity->{$this->revision});
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the field cache after an import or rollback.
|
||||
*/
|
||||
public function postImport() {
|
||||
field_cache_clear();
|
||||
}
|
||||
public function postRollback() {
|
||||
field_cache_clear();
|
||||
}
|
||||
}
|
164
sites/all/modules/contrib/migrate/migrate_extras/flag.inc
Normal file
164
sites/all/modules/contrib/migrate/migrate_extras/flag.inc
Normal file
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Flag module integration
|
||||
*/
|
||||
|
||||
/**
|
||||
* Destination class implementing when you want just an insert into flag_content table.
|
||||
*/
|
||||
class MigrateDestinationFlagSimple extends MigrateDestination {
|
||||
public function __construct($fid) {
|
||||
parent::__construct();
|
||||
$this->fid = $fid;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
$flag = flag_get_flag(NULL, $this->fid);
|
||||
return t('flag (!flag)', array('!flag' => $flag->name));
|
||||
}
|
||||
|
||||
static public function getKeySchema() {
|
||||
return array(
|
||||
'fcid' => array(
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a membership.
|
||||
*
|
||||
* @param $id
|
||||
* IDs to be deleted.
|
||||
*/
|
||||
public function bulkRollback(array $ids) {
|
||||
migrate_instrument_start(__METHOD__);
|
||||
db_delete('flag_content')
|
||||
->condition('fcid', $ids, 'IN')
|
||||
->execute();
|
||||
migrate_instrument_stop(__METHOD__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a single flag_content.
|
||||
*
|
||||
* @param $entity
|
||||
* Object object to build. Prefilled with any fields mapped in the Migration.
|
||||
* @param $row
|
||||
* Raw source data object - passed through to prepare/complete handlers.
|
||||
* @return array
|
||||
* Array of key fields of the object that was saved if
|
||||
* successful. FALSE on failure.
|
||||
*/
|
||||
public function import(stdClass $entity, stdClass $row) {
|
||||
if (isset($entity->timestamp)) {
|
||||
$entity->timestamp = Migration::timestamp($entity->timestamp);
|
||||
}
|
||||
|
||||
$entity->fid = $this->fid;
|
||||
|
||||
if (!empty($entity->fcid)) {
|
||||
$return = drupal_write_record('flag_content', $entity, 'fcid');
|
||||
}
|
||||
else {
|
||||
$return = drupal_write_record('flag_content', $entity);
|
||||
}
|
||||
if ($return) {
|
||||
// Update the flag_counts table.
|
||||
$count = db_select('flag_content')
|
||||
->fields('flag_content')
|
||||
->condition('fid', $this->fid)
|
||||
->condition('content_type', $entity->content_type)
|
||||
->condition('content_id', $entity->content_id)
|
||||
->countQuery()
|
||||
->execute()
|
||||
->fetchField();
|
||||
db_merge('flag_counts')
|
||||
->key(array(
|
||||
'fid' => $this->fid,
|
||||
'content_id' => $entity->content_id,
|
||||
))
|
||||
->fields(array(
|
||||
'content_type' => $entity->content_type,
|
||||
'count' => $count,
|
||||
'last_updated' => REQUEST_TIME,
|
||||
))
|
||||
->execute();
|
||||
return array($entity->fcid);
|
||||
}
|
||||
}
|
||||
|
||||
public function fields() {
|
||||
return array(
|
||||
'fcid' => 'Flag content ID',
|
||||
'fid' => 'Flag ID',
|
||||
'content_type' => '',
|
||||
'content_id' => '',
|
||||
'uid' => 'User ID',
|
||||
'timestamp' => '',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Field handler - this will expose flags as fields on the object they're
|
||||
* attached to, and set the flag to the value mapped in addFieldMapping().
|
||||
*/
|
||||
abstract class MigrateExtrasFlagHandler extends MigrateDestinationHandler {
|
||||
/**
|
||||
* Make the flags assigned to this object visible.
|
||||
*/
|
||||
public function fields($entity_type, $bundle) {
|
||||
$fields = array();
|
||||
if (module_exists('flag')) {
|
||||
$flags = flag_get_flags($entity_type, $bundle);
|
||||
foreach ($flags as $flag_name => $flag) {
|
||||
$fields[$flag_name] = $flag->title;
|
||||
}
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Because we can't identify what kind of entity is passed to complete, we
|
||||
* implement a separate handler for each type.
|
||||
*/
|
||||
class MigrateExtrasNodeFlagHandler extends MigrateExtrasFlagHandler {
|
||||
public function __construct() {
|
||||
$this->registerTypes(array('node'));
|
||||
}
|
||||
|
||||
public function complete($node, stdClass $row) {
|
||||
if (!module_exists('flag')) return;
|
||||
|
||||
$flags = flag_get_flags('node', $node->type);
|
||||
$fields = array();
|
||||
foreach ($flags as $flag_name => $flag) {
|
||||
if (!empty($node->$flag_name)) {
|
||||
flag('flag', $flag_name, $node->nid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MigrateExtrasUserFlagHandler extends MigrateExtrasFlagHandler {
|
||||
public function __construct() {
|
||||
$this->registerTypes(array('user'));
|
||||
}
|
||||
|
||||
public function complete($user, stdClass $row) {
|
||||
if (!module_exists('flag')) return;
|
||||
|
||||
$flags = flag_get_flags('user', 'user');
|
||||
$fields = array();
|
||||
foreach ($flags as $flag_name => $flag) {
|
||||
if (!empty($user->$flag_name)) {
|
||||
flag('flag', $flag_name, $user->uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* Primary value passed to this field must be the geometry type of the geofield: Point, LineString, Polygon
|
||||
*
|
||||
* Arguments are used to specify all the other values:
|
||||
* 'wkt' - Well Known Text
|
||||
* 'lat' - Latitude.
|
||||
* 'lon' - Longitude
|
||||
* 'top' - Top Latitude
|
||||
* 'bottom' - Bottom Latitude
|
||||
* 'right' - Right Longitude
|
||||
* 'left' - Left Longitude
|
||||
*
|
||||
* Add the source field mappings to the argument array then add null mappings to
|
||||
* avoid having fields flagged as as unmapped:
|
||||
* @code
|
||||
* $geo_arguments = array(
|
||||
* 'lat' => array('source_field' => 'source_field_latidute'),
|
||||
* 'lon' => array('source_field' => 'source_field_longitude'),
|
||||
* );
|
||||
* // The geometry type should be passed in as the primary value.
|
||||
* $this->addFieldMapping('field_geofield_dest', 'field_source_geotype')
|
||||
* ->arguments($geo_arguments);
|
||||
* // Since the excerpt is mapped via an argument, add a null mapping so it's
|
||||
* // not flagged as unmapped.
|
||||
* $this->addFieldMapping(NULL, 'source_field_latitude');
|
||||
* $this->addFieldMapping(NULL, 'source_field_longitude');
|
||||
* @endcode
|
||||
*/
|
||||
class MigrateGeoFieldHandler extends MigrateFieldHandler {
|
||||
public function __construct() {
|
||||
$this->registerTypes(array('geofield'));
|
||||
}
|
||||
|
||||
public function prepare($entity, array $field_info, array $instance, array $values) {
|
||||
$arguments = array();
|
||||
|
||||
if (isset($values['arguments'])) {
|
||||
$arguments = array_filter($values['arguments']);
|
||||
unset($values['arguments']);
|
||||
}
|
||||
$language = $this->getFieldLanguage($entity, $field_info, $arguments);
|
||||
|
||||
// Setup the standard Field API array for saving.
|
||||
$delta = 0;
|
||||
foreach ($values as $value) {
|
||||
$return[$language][$delta] = array('geo_type' => $value) + array_intersect_key($arguments, $field_info['columns']);
|
||||
$delta++;
|
||||
}
|
||||
|
||||
return isset($return) ? $return : NULL;
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Primary value passed to this field must be interval value itself (number of
|
||||
* periods).
|
||||
*
|
||||
* Pass the period as an argument, e.g.:
|
||||
*
|
||||
* @code
|
||||
* $arguments = array('period' => 'month');
|
||||
* $this->addFieldMapping('field_subscription_duration', 'num_months')
|
||||
* ->arguments($arguments);
|
||||
* @endcode
|
||||
*/
|
||||
class MigrateIntervalFieldHandler extends MigrateFieldHandler {
|
||||
public function __construct() {
|
||||
$this->registerTypes(array('interval'));
|
||||
}
|
||||
|
||||
public function prepare($entity, array $field_info, array $instance, array $values) {
|
||||
$arguments = array();
|
||||
if (isset($values['arguments'])) {
|
||||
$arguments = array_filter($values['arguments']);
|
||||
unset($values['arguments']);
|
||||
}
|
||||
$language = $this->getFieldLanguage($entity, $field_info, $arguments);
|
||||
|
||||
// Setup the standard Field API array for saving.
|
||||
$delta = 0;
|
||||
foreach ($values as $value) {
|
||||
$return[$language][$delta] = array(
|
||||
'interval' => $value,
|
||||
'period' => $arguments['period'],
|
||||
);
|
||||
$delta++;
|
||||
}
|
||||
|
||||
return isset($return) ? $return : NULL;
|
||||
}
|
||||
}
|
169
sites/all/modules/contrib/migrate/migrate_extras/media.inc
Normal file
169
sites/all/modules/contrib/migrate/migrate_extras/media.inc
Normal file
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Destination class implementing migration into media entities.
|
||||
*/
|
||||
class MigrateDestinationMedia extends MigrateDestinationFile {
|
||||
/**
|
||||
* Call this from the prepare() method of a migration that contains media
|
||||
* image files, if you want to rewrite the IMG tags into media references.
|
||||
*
|
||||
* @param $entity
|
||||
* Entity object being built.
|
||||
* @param $field
|
||||
* Name of the text field within the entity to be modified. Defaults to 'body'.
|
||||
*/
|
||||
static public function rewriteImgTags($entity, $field = 'body') {
|
||||
if (is_array($entity->$field)) {
|
||||
migrate_instrument_start('MigrateDestinationMedia rewriteImgTags');
|
||||
foreach ($entity->$field as $language => $values) {
|
||||
$body = $values[0]['value'];
|
||||
break;
|
||||
}
|
||||
// Quickly skip any non-candidates
|
||||
if (!stristr($body, '<img')) {
|
||||
migrate_instrument_stop('MigrateDestinationMedia rewriteImgTags');
|
||||
return;
|
||||
}
|
||||
// Pass full img tags into the callback
|
||||
$new_body = preg_replace_callback('|<img [^>]*>|i', array(self, 'replaceCallback'),
|
||||
$body);
|
||||
$entity->{$field}[$language][0]['value'] = $new_body;
|
||||
migrate_instrument_stop('MigrateDestinationMedia rewriteImgTags');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If a referenced image can be found in the files table, replace the <img> tag
|
||||
* with a media JSON reference.
|
||||
*
|
||||
* @param array $matches
|
||||
*/
|
||||
static protected function replaceCallback(array $matches) {
|
||||
$src_matches = array();
|
||||
// Default to the original <img> tag
|
||||
$result = $matches[0];
|
||||
// Extract the src parameter
|
||||
if (preg_match('|src=[\'"]([^\'"]+)[\'"]|i', $matches[0], $src_matches)) {
|
||||
// Replace the scheme and host portions of the referenced URI with the
|
||||
// Drupal scheme as it's saved in the file_unmanaged table
|
||||
$src = $src_matches[1];
|
||||
$fid = db_select('file_managed', 'f')
|
||||
->fields('f', array('fid'))
|
||||
->condition('filename', basename($src))
|
||||
->execute()
|
||||
->fetchField();
|
||||
if ($fid) {
|
||||
$image_info = array(
|
||||
'type' => 'media',
|
||||
'view_mode' => 'media_large',
|
||||
'fid' => $fid,
|
||||
'attributes' => array(
|
||||
'alt' => '',
|
||||
'title' => '',
|
||||
'class' => 'media-image',
|
||||
'typeof' => 'foaf:Image',
|
||||
'wysiwyg' => 1,
|
||||
),
|
||||
);
|
||||
// Get the height and width parameters if present
|
||||
preg_match('|width=[\'"]([^\'"]+)[\'"]|i', $matches[0], $width);
|
||||
preg_match('|height=[\'"]([^\'"]+)[\'"]|i', $matches[0], $height);
|
||||
// image width
|
||||
if ($width) {
|
||||
$image_info['attributes']['width'] = $width[1];
|
||||
}
|
||||
// image height
|
||||
if ($height) {
|
||||
$image_info['attributes']['height'] = $height[1];
|
||||
}
|
||||
|
||||
$result = '[[' . drupal_json_encode($image_info) . ']]';
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for creating Youtube file entities.
|
||||
*/
|
||||
class MigrateExtrasFileYoutube implements MigrateFileInterface {
|
||||
/**
|
||||
* Implementation of MigrateFileInterface::fields().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static public function fields() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of MigrateFileInterface::processFiles().
|
||||
*
|
||||
* @param $value
|
||||
* The URI or local filespec of a file to be imported.
|
||||
* @param $owner
|
||||
* User ID (uid) to be the owner of the file.
|
||||
* @return object
|
||||
* The file entity being created or referenced.
|
||||
*/
|
||||
public function processFile($value, $owner) {
|
||||
// Convert the Youtube URI into a local stream wrapper.
|
||||
if (class_exists('MediaInternetYouTubeHandler')) {
|
||||
$handler = new MediaInternetYouTubeHandler($value);
|
||||
$destination = $handler->parse($value);
|
||||
$file = file_uri_to_object($destination, TRUE);
|
||||
}
|
||||
elseif (class_exists('MediaInternetOEmbedHandler')) {
|
||||
$handler = new MediaInternetOEmbedHandler($value);
|
||||
$file = $handler->getFileObject();
|
||||
}
|
||||
else {
|
||||
MigrationBase::displayMessage(t('Could not find a handler for YouTube videos'));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Create a file entity object for this Youtube reference, and see if we
|
||||
// can get the video title.
|
||||
if (empty($file->fid) && $info = $handler->getOEmbed()) {
|
||||
$file->filename = truncate_utf8($info['title'], 255);
|
||||
}
|
||||
$file = file_save($file);
|
||||
if (is_object($file)) {
|
||||
return $file;
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Basic support for the deprecated media field type.
|
||||
class MigrateMediaFieldHandler extends MigrateFileFieldHandler {
|
||||
public function __construct() {
|
||||
$this->registerTypes(array('media'));
|
||||
}
|
||||
/**
|
||||
* Implementation of MigrateFieldHandler::fields().
|
||||
*
|
||||
* @param $type
|
||||
* The field type.
|
||||
* @param $instance
|
||||
* Instance info for the field.
|
||||
* @param Migration $migration
|
||||
* The migration context for the parent field. We can look at the mappings
|
||||
* and determine which subfields are relevant.
|
||||
* @return array
|
||||
*/
|
||||
public function fields($type, $instance, $migration = NULL) {
|
||||
$fields = parent::fields($type, $instance, $migration);
|
||||
unset($fields['description']);
|
||||
unset($fields['display']);
|
||||
$fields += array(
|
||||
'title' => t('Subfield: String to be used as the title value'),
|
||||
'data' => t('Subfield: Additional data about the field'),
|
||||
);
|
||||
return $fields;
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
name = Migrate Extras
|
||||
description = "Adds migrate module integration with contrib modules and other miscellaneous tweaks."
|
||||
core = 7.x
|
||||
package=Development
|
||||
|
||||
dependencies[] = migrate
|
||||
files[] = addressfield.inc
|
||||
files[] = cck_phone.inc
|
||||
files[] = entity_api.inc
|
||||
files[] = flag.inc
|
||||
files[] = geofield.inc
|
||||
files[] = interval.inc
|
||||
files[] = media.inc
|
||||
files[] = name.inc
|
||||
files[] = pathauto.inc
|
||||
files[] = privatemsg.inc
|
||||
files[] = profile2.inc
|
||||
files[] = rules.inc
|
||||
files[] = user_relationships.inc
|
||||
files[] = votingapi.inc
|
||||
files[] = webform.inc
|
||||
files[] = tests/pathauto.test
|
||||
|
||||
; Information added by drupal.org packaging script on 2012-11-07
|
||||
version = "7.x-2.5"
|
||||
core = "7.x"
|
||||
project = "migrate_extras"
|
||||
datestamp = "1352299013"
|
||||
|
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Implementation of hook_migrate_api().
|
||||
*/
|
||||
function migrate_extras_migrate_api() {
|
||||
$api = array(
|
||||
'api' => 2,
|
||||
'destination handlers' => array(
|
||||
'MigratePathautoHandler',
|
||||
'MigrateExtrasNodeFlagHandler',
|
||||
'MigrateExtrasUserFlagHandler',
|
||||
),
|
||||
'field handlers' => array(
|
||||
'MigrateAddressFieldHandler',
|
||||
'MigrateCckPhoneHandler',
|
||||
'MigrateGeoFieldHandler',
|
||||
'MigrateIntervalFieldHandler',
|
||||
'MigrateNameHandler',
|
||||
'MigrateMediaFieldHandler',
|
||||
)
|
||||
);
|
||||
return $api;
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
function migrate_extras_init() {
|
||||
// Set variable to FALSE to disable rules processing.
|
||||
if (module_exists('rules') && !variable_get('migrate_extras_rules', TRUE)) {
|
||||
foreach (rules_get_event_sets() as $key => $set) {
|
||||
$GLOBALS['conf']['rules_inactive_sets'][] = $key;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,345 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* migrate_extras_media.features.field.inc
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_field_default_fields().
|
||||
*/
|
||||
function migrate_extras_media_field_default_fields() {
|
||||
$fields = array();
|
||||
|
||||
// Exported field: 'node-migrate_extras_media_example-body'
|
||||
$fields['node-migrate_extras_media_example-body'] = array(
|
||||
'field_config' => array(
|
||||
'active' => '1',
|
||||
'cardinality' => '1',
|
||||
'deleted' => '0',
|
||||
'entity_types' => array(
|
||||
0 => 'node',
|
||||
),
|
||||
'field_name' => 'body',
|
||||
'foreign keys' => array(
|
||||
'format' => array(
|
||||
'columns' => array(
|
||||
'format' => 'format',
|
||||
),
|
||||
'table' => 'filter_format',
|
||||
),
|
||||
),
|
||||
'indexes' => array(
|
||||
'format' => array(
|
||||
0 => 'format',
|
||||
),
|
||||
),
|
||||
'module' => 'text',
|
||||
'settings' => array(),
|
||||
'translatable' => '1',
|
||||
'type' => 'text_with_summary',
|
||||
),
|
||||
'field_instance' => array(
|
||||
'bundle' => 'migrate_extras_media_example',
|
||||
'default_value' => NULL,
|
||||
'deleted' => '0',
|
||||
'description' => '',
|
||||
'display' => array(
|
||||
'default' => array(
|
||||
'label' => 'hidden',
|
||||
'module' => 'text',
|
||||
'settings' => array(),
|
||||
'type' => 'text_default',
|
||||
'weight' => 0,
|
||||
),
|
||||
'teaser' => array(
|
||||
'label' => 'hidden',
|
||||
'module' => 'text',
|
||||
'settings' => array(
|
||||
'trim_length' => 600,
|
||||
),
|
||||
'type' => 'text_summary_or_trimmed',
|
||||
'weight' => 0,
|
||||
),
|
||||
),
|
||||
'entity_type' => 'node',
|
||||
'field_name' => 'body',
|
||||
'label' => 'Body',
|
||||
'required' => FALSE,
|
||||
'settings' => array(
|
||||
'display_summary' => TRUE,
|
||||
'text_processing' => 1,
|
||||
'user_register_form' => FALSE,
|
||||
),
|
||||
'widget' => array(
|
||||
'module' => 'text',
|
||||
'settings' => array(
|
||||
'rows' => 20,
|
||||
'summary_rows' => 5,
|
||||
),
|
||||
'type' => 'text_textarea_with_summary',
|
||||
'weight' => '31',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Exported field: 'node-migrate_extras_media_example-field_document'
|
||||
$fields['node-migrate_extras_media_example-field_document'] = array(
|
||||
'field_config' => array(
|
||||
'active' => '1',
|
||||
'cardinality' => '-1',
|
||||
'deleted' => '0',
|
||||
'entity_types' => array(),
|
||||
'field_name' => 'field_document',
|
||||
'foreign keys' => array(
|
||||
'fid' => array(
|
||||
'columns' => array(
|
||||
'fid' => 'fid',
|
||||
),
|
||||
'table' => 'file_managed',
|
||||
),
|
||||
),
|
||||
'indexes' => array(
|
||||
'fid' => array(
|
||||
0 => 'fid',
|
||||
),
|
||||
),
|
||||
'module' => 'file',
|
||||
'settings' => array(
|
||||
'display_default' => 0,
|
||||
'display_field' => 0,
|
||||
'uri_scheme' => 'public',
|
||||
),
|
||||
'translatable' => '0',
|
||||
'type' => 'file',
|
||||
),
|
||||
'field_instance' => array(
|
||||
'bundle' => 'migrate_extras_media_example',
|
||||
'deleted' => '0',
|
||||
'description' => '',
|
||||
'display' => array(
|
||||
'default' => array(
|
||||
'label' => 'above',
|
||||
'module' => 'file',
|
||||
'settings' => array(),
|
||||
'type' => 'file_default',
|
||||
'weight' => 3,
|
||||
),
|
||||
'teaser' => array(
|
||||
'label' => 'above',
|
||||
'settings' => array(),
|
||||
'type' => 'hidden',
|
||||
'weight' => 0,
|
||||
),
|
||||
),
|
||||
'entity_type' => 'node',
|
||||
'field_name' => 'field_document',
|
||||
'label' => 'Document',
|
||||
'required' => 0,
|
||||
'settings' => array(
|
||||
'description_field' => 0,
|
||||
'file_directory' => '',
|
||||
'file_extensions' => 'pdf doc docx txt',
|
||||
'max_filesize' => '',
|
||||
'user_register_form' => FALSE,
|
||||
),
|
||||
'widget' => array(
|
||||
'active' => 1,
|
||||
'module' => 'media',
|
||||
'settings' => array(
|
||||
'allowed_schemes' => array(
|
||||
'private' => 0,
|
||||
'public' => 'public',
|
||||
'wordpress' => 0,
|
||||
'youtube' => 0,
|
||||
),
|
||||
'allowed_types' => array(
|
||||
'audio' => 0,
|
||||
'default' => 'default',
|
||||
'image' => 0,
|
||||
'video' => 0,
|
||||
),
|
||||
'progress_indicator' => 'throbber',
|
||||
),
|
||||
'type' => 'media_generic',
|
||||
'weight' => '34',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Exported field: 'node-migrate_extras_media_example-field_media_image'
|
||||
$fields['node-migrate_extras_media_example-field_media_image'] = array(
|
||||
'field_config' => array(
|
||||
'active' => '1',
|
||||
'cardinality' => '1',
|
||||
'deleted' => '0',
|
||||
'entity_types' => array(),
|
||||
'field_name' => 'field_media_image',
|
||||
'foreign keys' => array(
|
||||
'fid' => array(
|
||||
'columns' => array(
|
||||
'fid' => 'fid',
|
||||
),
|
||||
'table' => 'file_managed',
|
||||
),
|
||||
),
|
||||
'indexes' => array(
|
||||
'fid' => array(
|
||||
0 => 'fid',
|
||||
),
|
||||
),
|
||||
'module' => 'file',
|
||||
'settings' => array(
|
||||
'display_default' => 0,
|
||||
'display_field' => 0,
|
||||
'uri_scheme' => 'public',
|
||||
),
|
||||
'translatable' => '0',
|
||||
'type' => 'file',
|
||||
),
|
||||
'field_instance' => array(
|
||||
'bundle' => 'migrate_extras_media_example',
|
||||
'deleted' => '0',
|
||||
'description' => '',
|
||||
'display' => array(
|
||||
'default' => array(
|
||||
'label' => 'above',
|
||||
'module' => 'file',
|
||||
'settings' => array(),
|
||||
'type' => 'file_default',
|
||||
'weight' => 2,
|
||||
),
|
||||
'teaser' => array(
|
||||
'label' => 'above',
|
||||
'settings' => array(),
|
||||
'type' => 'hidden',
|
||||
'weight' => 0,
|
||||
),
|
||||
),
|
||||
'entity_type' => 'node',
|
||||
'field_name' => 'field_media_image',
|
||||
'label' => 'Media image',
|
||||
'required' => 0,
|
||||
'settings' => array(
|
||||
'description_field' => 0,
|
||||
'file_directory' => '',
|
||||
'file_extensions' => 'jpg jpeg gif png',
|
||||
'max_filesize' => '',
|
||||
'user_register_form' => FALSE,
|
||||
),
|
||||
'widget' => array(
|
||||
'active' => 1,
|
||||
'module' => 'media',
|
||||
'settings' => array(
|
||||
'allowed_schemes' => array(
|
||||
'private' => 0,
|
||||
'public' => 'public',
|
||||
'wordpress' => 0,
|
||||
'youtube' => 0,
|
||||
),
|
||||
'allowed_types' => array(
|
||||
'audio' => 0,
|
||||
'default' => 0,
|
||||
'image' => 'image',
|
||||
'video' => 0,
|
||||
),
|
||||
'progress_indicator' => 'throbber',
|
||||
),
|
||||
'type' => 'media_generic',
|
||||
'weight' => '33',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Exported field: 'node-migrate_extras_media_example-field_youtube_video'
|
||||
$fields['node-migrate_extras_media_example-field_youtube_video'] = array(
|
||||
'field_config' => array(
|
||||
'active' => '1',
|
||||
'cardinality' => '-1',
|
||||
'deleted' => '0',
|
||||
'entity_types' => array(),
|
||||
'field_name' => 'field_youtube_video',
|
||||
'foreign keys' => array(
|
||||
'fid' => array(
|
||||
'columns' => array(
|
||||
'fid' => 'fid',
|
||||
),
|
||||
'table' => 'file_managed',
|
||||
),
|
||||
),
|
||||
'indexes' => array(
|
||||
'fid' => array(
|
||||
0 => 'fid',
|
||||
),
|
||||
),
|
||||
'module' => 'file',
|
||||
'settings' => array(
|
||||
'display_default' => 0,
|
||||
'display_field' => 0,
|
||||
'uri_scheme' => 'public',
|
||||
),
|
||||
'translatable' => '0',
|
||||
'type' => 'file',
|
||||
),
|
||||
'field_instance' => array(
|
||||
'bundle' => 'migrate_extras_media_example',
|
||||
'deleted' => '0',
|
||||
'description' => '',
|
||||
'display' => array(
|
||||
'default' => array(
|
||||
'label' => 'above',
|
||||
'module' => 'file',
|
||||
'settings' => array(),
|
||||
'type' => 'file_default',
|
||||
'weight' => 1,
|
||||
),
|
||||
'teaser' => array(
|
||||
'label' => 'above',
|
||||
'settings' => array(),
|
||||
'type' => 'hidden',
|
||||
'weight' => 0,
|
||||
),
|
||||
),
|
||||
'entity_type' => 'node',
|
||||
'field_name' => 'field_youtube_video',
|
||||
'label' => 'Youtube video',
|
||||
'required' => 0,
|
||||
'settings' => array(
|
||||
'description_field' => 0,
|
||||
'file_directory' => '',
|
||||
'file_extensions' => 'txt',
|
||||
'max_filesize' => '',
|
||||
'user_register_form' => FALSE,
|
||||
),
|
||||
'widget' => array(
|
||||
'active' => 1,
|
||||
'module' => 'media',
|
||||
'settings' => array(
|
||||
'allowed_schemes' => array(
|
||||
'private' => 0,
|
||||
'public' => 0,
|
||||
'wordpress' => 0,
|
||||
'youtube' => 'youtube',
|
||||
),
|
||||
'allowed_types' => array(
|
||||
'audio' => 0,
|
||||
'default' => 0,
|
||||
'image' => 0,
|
||||
'video' => 'video',
|
||||
),
|
||||
'progress_indicator' => 'throbber',
|
||||
),
|
||||
'type' => 'media_generic',
|
||||
'weight' => '32',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Translatables
|
||||
// Included for use with string extractors like potx.
|
||||
t('Body');
|
||||
t('Document');
|
||||
t('Media image');
|
||||
t('Youtube video');
|
||||
|
||||
return $fields;
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* migrate_extras_media.features.inc
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_node_info().
|
||||
*/
|
||||
function migrate_extras_media_node_info() {
|
||||
$items = array(
|
||||
'migrate_extras_media_example' => array(
|
||||
'name' => t('Migrate Extras Media Example'),
|
||||
'base' => 'node_content',
|
||||
'description' => t('Content type for testing Migrate Extras support for the Media module.'),
|
||||
'has_title' => '1',
|
||||
'title_label' => t('Title'),
|
||||
'help' => '',
|
||||
),
|
||||
);
|
||||
return $items;
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
core = "7.x"
|
||||
dependencies[] = "features"
|
||||
dependencies[] = "file"
|
||||
dependencies[] = "media"
|
||||
dependencies[] = "media_youtube"
|
||||
dependencies[] = "migrate"
|
||||
dependencies[] = "migrate_extras"
|
||||
description = "Examples for migrating Media"
|
||||
features[field][] = "node-migrate_extras_media_example-body"
|
||||
features[field][] = "node-migrate_extras_media_example-field_document"
|
||||
features[field][] = "node-migrate_extras_media_example-field_media_image"
|
||||
features[field][] = "node-migrate_extras_media_example-field_youtube_video"
|
||||
features[node][] = "migrate_extras_media_example"
|
||||
files[] = migrate_extras_media.migrate.inc
|
||||
name = "Migrate Extras Media"
|
||||
package = "Migrate Examples"
|
||||
|
||||
; Information added by drupal.org packaging script on 2012-11-07
|
||||
version = "7.x-2.5"
|
||||
core = "7.x"
|
||||
project = "migrate_extras"
|
||||
datestamp = "1352299013"
|
||||
|
@@ -0,0 +1,247 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Examples and test fodder for migration of Media entities and fields.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Migration class for media images.
|
||||
*/
|
||||
class MigrateExampleMediaImageMigration extends XMLMigration {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->description = t('Example migration of media images');
|
||||
|
||||
$this->map = new MigrateSQLMap($this->machineName,
|
||||
array(
|
||||
'filename' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'description' => 'Image filename',
|
||||
)
|
||||
),
|
||||
MigrateDestinationMedia::getKeySchema()
|
||||
);
|
||||
|
||||
// Source fields available in the XML file.
|
||||
$fields = array(
|
||||
'filename' => t('Image filename, relative to the source directory'),
|
||||
'description' => t('Description of the image'),
|
||||
);
|
||||
|
||||
// Our test data is in an XML file
|
||||
$xml_folder = drupal_get_path('module', 'migrate_extras_media');
|
||||
$items_url = $xml_folder . '/migrate_extras_media.xml';
|
||||
$item_xpath = '/source_data/item/image';
|
||||
$item_ID_xpath = 'filename';
|
||||
$items_class = new MigrateItemsXML($items_url, $item_xpath, $item_ID_xpath);
|
||||
$this->source = new MigrateSourceMultiItems($items_class, $fields);
|
||||
|
||||
// In the simplest case, just pass the media type.
|
||||
$this->destination = new MigrateDestinationMedia('image');
|
||||
|
||||
// The source images are in a local directory - specify the parent.
|
||||
$this->addFieldMapping('source_dir')
|
||||
->defaultValue(drupal_get_path('module', 'migrate_extras_media') . '/source_files');
|
||||
// The 'value' of the media destination is mapped to the source field
|
||||
// representing the media itself - in this case, a filename relative to
|
||||
// source_dir.
|
||||
$this->addFieldMapping('value', 'filename')
|
||||
->xpath('filename');
|
||||
// Fields on the entity can be mapped in the usual way.
|
||||
$this->addFieldMapping('field_image_description', 'description')
|
||||
->xpath('description');
|
||||
|
||||
$this->addFieldMapping('uid')
|
||||
->defaultValue(1);
|
||||
|
||||
$this->addUnmigratedDestinations(array('field_image_description:format',
|
||||
'field_image_description:language', 'destination_dir', 'destination_file',
|
||||
'file_replace', 'preserve_files', 'timestamp'));
|
||||
if (module_exists('path')) {
|
||||
$this->addUnmigratedDestinations(array('path'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Migration class for media_youtube entities.
|
||||
*/
|
||||
class MigrateExampleMediaVideoMigration extends XMLMigration {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->description = t('Example migration of Youtube videos');
|
||||
|
||||
$this->map = new MigrateSQLMap($this->machineName,
|
||||
array(
|
||||
'uri' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'description' => 'YouTube URI',
|
||||
)
|
||||
),
|
||||
MigrateDestinationMedia::getKeySchema()
|
||||
);
|
||||
|
||||
// Source fields available in the XML file.
|
||||
$fields = array(
|
||||
'uri' => t('URI of a YouTube video'),
|
||||
'description' => t('Description of the video'),
|
||||
);
|
||||
|
||||
// Our test data is in an XML file
|
||||
$xml_folder = drupal_get_path('module', 'migrate_extras_media');
|
||||
$items_url = $xml_folder . '/migrate_extras_media.xml';
|
||||
$item_xpath = '/source_data/item/video';
|
||||
$item_ID_xpath = 'uri';
|
||||
$items_class = new MigrateItemsXML($items_url, $item_xpath, $item_ID_xpath);
|
||||
$this->source = new MigrateSourceMultiItems($items_class, $fields);
|
||||
|
||||
// In this case, we need to specify the file_class in the second paramter -
|
||||
// this class understands how to translate a http://www.youtube.com/ URI
|
||||
// into Drupal's Youtube file scheme (youtube://).
|
||||
$this->destination = new MigrateDestinationMedia('video',
|
||||
'MigrateExtrasFileYoutube');
|
||||
|
||||
// We just need to map the 'value' in the media destination to the Youtube
|
||||
// URI.
|
||||
$this->addFieldMapping('value', 'uri')
|
||||
->xpath('uri');
|
||||
|
||||
$this->addFieldMapping('field_video_description', 'description')
|
||||
->xpath('description');
|
||||
$this->addFieldMapping('uid')
|
||||
->defaultValue(1);
|
||||
|
||||
$this->addUnmigratedDestinations(array('field_video_description:format',
|
||||
'field_video_description:language', 'timestamp'));
|
||||
if (module_exists('path')) {
|
||||
$this->addUnmigratedDestinations(array('path'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Migration class for nodes with media fields.
|
||||
*/
|
||||
class MigrateExampleMediaNodeMigration extends XMLMigration {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->description = t('Example migration into the Media module');
|
||||
$this->dependencies =
|
||||
array('MigrateExampleMediaImage', 'MigrateExampleMediaVideo');
|
||||
|
||||
$this->map = new MigrateSQLMap($this->machineName,
|
||||
array(
|
||||
'id' => array(
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'description' => 'Media ID',
|
||||
)
|
||||
),
|
||||
MigrateDestinationNode::getKeySchema()
|
||||
);
|
||||
|
||||
// Source fields available in the XML file.
|
||||
$fields = array(
|
||||
'id' => t('Source id'),
|
||||
'title' => t('Title'),
|
||||
'body' => t('Description'),
|
||||
'video_uri' => t('A YouTube URI'),
|
||||
'video_description' => t('Description for a YouTube video'),
|
||||
'image_filename' => t('Image filename'),
|
||||
'image_description' => t('Image description'),
|
||||
'document_filename' => t('Document filename'),
|
||||
);
|
||||
|
||||
// Our test data is in an XML file
|
||||
$xml_folder = drupal_get_path('module', 'migrate_extras_media');
|
||||
$items_url = $xml_folder . '/migrate_extras_media.xml';
|
||||
$item_xpath = '/source_data/item';
|
||||
$item_ID_xpath = 'id';
|
||||
$items_class = new MigrateItemsXML($items_url, $item_xpath, $item_ID_xpath);
|
||||
$this->source = new MigrateSourceMultiItems($items_class, $fields);
|
||||
$this->destination = new MigrateDestinationNode('migrate_extras_media_example');
|
||||
|
||||
// Basic fields
|
||||
$this->addFieldMapping('title', 'title')
|
||||
->xpath('title');
|
||||
$this->addFieldMapping('uid')
|
||||
->defaultValue(1);
|
||||
$this->addFieldMapping('body', 'body')
|
||||
->xpath('body');
|
||||
$this->addFieldMapping('body:format')
|
||||
->defaultValue('filtered_html');
|
||||
|
||||
// The image and Youtube media entities are imported via their own
|
||||
// migrations above, we just need to link the fields to them. We do this
|
||||
// by mapping the primary keys of those migrations (URL and filename) to
|
||||
// the primary field values, and specifying a file_class of MigrateFileFid.
|
||||
$this->addFieldMapping('field_youtube_video', 'video_uri')
|
||||
->xpath('video/uri')
|
||||
->sourceMigration('MigrateExampleMediaVideo');
|
||||
$this->addFieldMapping('field_youtube_video:file_class')
|
||||
->defaultValue('MigrateFileFid');
|
||||
|
||||
$this->addFieldMapping('field_media_image', 'image_filename')
|
||||
->xpath('image/filename')
|
||||
->sourceMigration('MigrateExampleMediaImage');
|
||||
$this->addFieldMapping('field_media_image:file_class')
|
||||
->defaultValue('MigrateFileFid');
|
||||
|
||||
// We have not created a separate migration for documents, we're using the
|
||||
// file field handler to get those. This works just like it does for regular
|
||||
// file fields.
|
||||
$this->addFieldMapping('field_document', 'document_filename')
|
||||
->xpath('document/filename');
|
||||
// This isn't technically necessary - MigrateFileUri is the default
|
||||
$this->addFieldMapping('field_document:file_class')
|
||||
->defaultValue('MigrateFileUri');
|
||||
$this->addFieldMapping('field_document:source_dir')
|
||||
->defaultValue(drupal_get_path('module', 'migrate_extras_media') . '/source_files');
|
||||
$this->addFieldMapping('field_document:destination_file', 'document_filename')
|
||||
->xpath('document/filename');
|
||||
|
||||
// Unmapped destination fields
|
||||
$this->addUnmigratedDestinations(array('is_new', 'status', 'promote',
|
||||
'revision', 'language', 'sticky', 'created', 'changed', 'revision_uid',
|
||||
'log', 'tnid', 'body:summary', 'body:language',
|
||||
'comment'));
|
||||
$this->addUnmigratedDestinations(array('field_media_image:language',
|
||||
'field_media_image:display', 'field_media_image:description',
|
||||
'field_youtube_video:language', 'field_youtube_video:description',
|
||||
'field_youtube_video:display', 'field_document:language', 'field_document:destination_dir',
|
||||
'field_document:file_replace', 'field_document:preserve_files',
|
||||
'field_document:description', 'field_document:display'));
|
||||
if (module_exists('path')) {
|
||||
$this->addUnmigratedDestinations(array('path'));
|
||||
if (module_exists('pathauto')) {
|
||||
$this->addUnmigratedDestinations(array('pathauto'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->addUnmigratedSources(array('image_description', 'video_description'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of Migration::prepare().
|
||||
*/
|
||||
public function prepare($node, $row) {
|
||||
// This will replace any <img> tags in the body with the media module's
|
||||
// JSON references.
|
||||
MigrateDestinationMedia::rewriteImgTags($node);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of hook_migrate_api().
|
||||
*/
|
||||
function migrate_extras_media_migrate_api() {
|
||||
$api = array(
|
||||
'api' => 2,
|
||||
);
|
||||
return $api;
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Code for the Migrate Extras Media feature.
|
||||
*/
|
||||
|
||||
include_once('migrate_extras_media.features.inc');
|
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<source_data>
|
||||
<item>
|
||||
<id>3</id>
|
||||
<title>Simple example</title>
|
||||
<body>This is pretty straight-forward.</body>
|
||||
<document>
|
||||
<filename>docs/test_doc.txt</filename>
|
||||
</document>
|
||||
<video>
|
||||
<uri>http://www.youtube.com/watch?v=tgbNymZ7vqY</uri>
|
||||
<description>Best video ever</description>
|
||||
</video>
|
||||
</item>
|
||||
<item>
|
||||
<id>8</id>
|
||||
<title>Another example</title>
|
||||
<body><![CDATA[So is this. Well, except for the image here, which we want to translate
|
||||
from an <img> tag to Media module tagging:
|
||||
<img src="images/watchdog-ok.png" />]]>
|
||||
</body>
|
||||
<document>
|
||||
<filename>docs/random.docx</filename>
|
||||
</document>
|
||||
<image>
|
||||
<filename>images/watchdog-ok.png</filename>
|
||||
<description>A simple checkmark</description>
|
||||
</image>
|
||||
<video>
|
||||
<uri>http://www.youtube.com/watch?v=kfVsfOSbJY0</uri>
|
||||
<description>NOT the best video ever</description>
|
||||
</video>
|
||||
</item>
|
||||
</source_data>
|
Binary file not shown.
@@ -0,0 +1 @@
|
||||
Just a sample text document for import.
|
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implementation of hook_field_default_fields().
|
||||
*/
|
||||
function migrate_extras_pathauto_field_default_fields() {
|
||||
$fields = array();
|
||||
|
||||
// Exported field: 'node-migrate_example_pathauto-body'
|
||||
$fields['node-migrate_example_pathauto-body'] = array(
|
||||
'field_config' => array(
|
||||
'active' => '1',
|
||||
'cardinality' => '1',
|
||||
'deleted' => '0',
|
||||
'entity_types' => array(
|
||||
'0' => 'node',
|
||||
),
|
||||
'field_name' => 'body',
|
||||
'foreign keys' => array(
|
||||
'format' => array(
|
||||
'columns' => array(
|
||||
'format' => 'format',
|
||||
),
|
||||
'table' => 'filter_format',
|
||||
),
|
||||
),
|
||||
'indexes' => array(
|
||||
'format' => array(
|
||||
'0' => 'format',
|
||||
),
|
||||
),
|
||||
'module' => 'text',
|
||||
'settings' => array(),
|
||||
'translatable' => '1',
|
||||
'type' => 'text_with_summary',
|
||||
),
|
||||
'field_instance' => array(
|
||||
'bundle' => 'migrate_example_pathauto',
|
||||
'default_value' => NULL,
|
||||
'deleted' => '0',
|
||||
'description' => '',
|
||||
'display' => array(
|
||||
'default' => array(
|
||||
'label' => 'hidden',
|
||||
'module' => 'text',
|
||||
'settings' => array(),
|
||||
'type' => 'text_default',
|
||||
'weight' => 0,
|
||||
),
|
||||
'teaser' => array(
|
||||
'label' => 'hidden',
|
||||
'module' => 'text',
|
||||
'settings' => array(
|
||||
'trim_length' => 600,
|
||||
),
|
||||
'type' => 'text_summary_or_trimmed',
|
||||
'weight' => 0,
|
||||
),
|
||||
),
|
||||
'entity_type' => 'node',
|
||||
'field_name' => 'body',
|
||||
'label' => 'Body',
|
||||
'required' => FALSE,
|
||||
'settings' => array(
|
||||
'display_summary' => TRUE,
|
||||
'text_processing' => 1,
|
||||
'user_register_form' => FALSE,
|
||||
),
|
||||
'widget' => array(
|
||||
'module' => 'text',
|
||||
'settings' => array(
|
||||
'rows' => 20,
|
||||
'summary_rows' => 5,
|
||||
),
|
||||
'type' => 'text_textarea_with_summary',
|
||||
'weight' => -4,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Translatables
|
||||
// Included for use with string extractors like potx.
|
||||
t('Body');
|
||||
|
||||
return $fields;
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implementation of hook_node_info().
|
||||
*/
|
||||
function migrate_extras_pathauto_node_info() {
|
||||
$items = array(
|
||||
'migrate_example_pathauto' => array(
|
||||
'name' => t('Migrate example - pathauto'),
|
||||
'base' => 'node_content',
|
||||
'description' => t('This content type is used for demonstrating and testing Migrate Example support for the Pathauto module.'),
|
||||
'has_title' => '1',
|
||||
'title_label' => t('Title'),
|
||||
'help' => '',
|
||||
),
|
||||
);
|
||||
return $items;
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
core = "7.x"
|
||||
dependencies[] = "features"
|
||||
dependencies[] = "migrate_extras"
|
||||
dependencies[] = "pathauto"
|
||||
description = "Examples of migrating with the Pathauto module"
|
||||
features[field][] = "node-migrate_example_pathauto-body"
|
||||
features[node][] = "migrate_example_pathauto"
|
||||
files[] = migrate_extras_pathauto.migrate.inc
|
||||
name = "Migrate Extras Pathauto Example"
|
||||
package = "Migrate Examples"
|
||||
project = "migrate_extras_pathauto_example"
|
||||
version = "7.x-2.1-beta1"
|
||||
|
||||
; Information added by drupal.org packaging script on 2012-11-07
|
||||
version = "7.x-2.5"
|
||||
core = "7.x"
|
||||
project = "migrate_extras"
|
||||
datestamp = "1352299013"
|
||||
|
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Examples and test fodder for migration with Pathauto enabled.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Migration class to test import with Pathauto enabled.
|
||||
*/
|
||||
class MigrateExamplePathautoMigration extends XMLMigration {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->description = t('Example migration with Pathauto enabled');
|
||||
|
||||
$this->map = new MigrateSQLMap($this->machineName,
|
||||
array(
|
||||
'id' => array(
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'description' => 'Pathauto ID',
|
||||
)
|
||||
),
|
||||
MigrateDestinationNode::getKeySchema()
|
||||
);
|
||||
|
||||
// Source fields available in the XML file.
|
||||
$fields = array(
|
||||
'id' => t('Source id'),
|
||||
'title' => t('Title'),
|
||||
'body' => t('Description'),
|
||||
);
|
||||
|
||||
// Our test data is in an XML file
|
||||
$xml_folder = drupal_get_path('module', 'migrate_extras_pathauto');
|
||||
$items_url = $xml_folder . '/migrate_extras_pathauto.xml';
|
||||
$item_xpath = '/source_data/item';
|
||||
$item_ID_xpath = 'id';
|
||||
$items_class = new MigrateItemsXML($items_url, $item_xpath, $item_ID_xpath);
|
||||
$this->source = new MigrateSourceMultiItems($items_class, $fields);
|
||||
$this->destination = new MigrateDestinationNode('migrate_example_pathauto');
|
||||
|
||||
// Basic fields
|
||||
$this->addFieldMapping('title', 'title')
|
||||
->xpath('title');
|
||||
$this->addFieldMapping('uid')
|
||||
->defaultValue(1);
|
||||
$this->addFieldMapping('body', 'body')
|
||||
->xpath('body');
|
||||
|
||||
// Disable application of pathauto during migration
|
||||
$this->addFieldMapping('pathauto')
|
||||
->defaultValue(FALSE);
|
||||
|
||||
// Unmapped destination fields
|
||||
$this->addUnmigratedDestinations(array('is_new', 'status', 'promote',
|
||||
'revision', 'language', 'sticky', 'created', 'changed', 'revision_uid',
|
||||
'path'));
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
include_once('migrate_extras_pathauto.features.inc');
|
||||
|
||||
/*
|
||||
* Implementation of hook_migrate_api().
|
||||
*/
|
||||
function migrate_extras_pathauto_migrate_api() {
|
||||
$api = array(
|
||||
'api' => 2,
|
||||
);
|
||||
return $api;
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<source_data>
|
||||
<item>
|
||||
<id>3</id>
|
||||
<title>Simple example</title>
|
||||
<body>This is pretty straight-forward.</body>
|
||||
</item>
|
||||
<item>
|
||||
<id>8</id>
|
||||
<title>Another example</title>
|
||||
<body>So is this.</body>
|
||||
</item>
|
||||
</source_data>
|
@@ -0,0 +1,3 @@
|
||||
1,1
|
||||
2,1
|
||||
3,1
|
|
@@ -0,0 +1,14 @@
|
||||
core = "7.x"
|
||||
dependencies[] = "migrate_extras"
|
||||
dependencies[] = "profile2"
|
||||
description = "Examples of migrating into Profile2 entities"
|
||||
files[] = migrate_extras_profile2.migrate.inc
|
||||
name = "Migrate Extras Profile2 Example"
|
||||
package = "Migrate Examples"
|
||||
|
||||
; Information added by drupal.org packaging script on 2012-11-07
|
||||
version = "7.x-2.5"
|
||||
core = "7.x"
|
||||
project = "migrate_extras"
|
||||
datestamp = "1352299013"
|
||||
|
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
function migrate_extras_profile2_install() {
|
||||
$type = entity_create('profile2_type', array(
|
||||
'type' => 'migrate_extras_profile2',
|
||||
'label' => t('migrate_extras_profile2'),
|
||||
'weight' => 0,
|
||||
'data' => array('registration' => FALSE, 'use_page' => TRUE),
|
||||
));
|
||||
$type->save();
|
||||
}
|
||||
|
||||
function migrate_extras_profile2_uninstall() {
|
||||
if ($entities = entity_load_multiple_by_name('profile2_type', array('migrate_extras_profile2'))) {
|
||||
list($id) = entity_extract_ids('profile2_type', reset($entities));
|
||||
entity_delete('profile2_type', $id);
|
||||
}
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Examples and test fodder for migration into profile2 entities.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Migration class to test import of various date fields.
|
||||
*/
|
||||
class MigrateExampleProfile2Migration extends Migration {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->description = t('Example migration into profile2 entities');
|
||||
|
||||
$this->map = new MigrateSQLMap($this->machineName,
|
||||
array(
|
||||
'id' => array(
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
)
|
||||
),
|
||||
MigrateDestinationProfile2::getKeySchema()
|
||||
);
|
||||
|
||||
// Our test data is in a CSV file
|
||||
$this->source = new MigrateSourceCSV(__DIR__ . '/migrate_extras_profile2.csv', $this->csvcolumns(), array(), $this->fields());
|
||||
$this->destination = new MigrateDestinationProfile2('migrate_extras_profile2');
|
||||
|
||||
$this->addFieldMapping('uid')
|
||||
->defaultValue(1);
|
||||
|
||||
// Unmapped destination fields
|
||||
$this->addUnmigratedDestinations(array('id'));
|
||||
}
|
||||
|
||||
function csvcolumns() {
|
||||
$columns[0] = array('id', 'Source ID');
|
||||
$columns[1] = array('uid', 'User ID');
|
||||
return $columns;
|
||||
}
|
||||
|
||||
function fields() {
|
||||
return array(
|
||||
'id' => 'Source ID',
|
||||
'uid' => 'User ID',
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Implementation of hook_migrate_api().
|
||||
*/
|
||||
function migrate_extras_profile2_migrate_api() {
|
||||
$api = array(
|
||||
'api' => 2,
|
||||
);
|
||||
return $api;
|
||||
}
|
54
sites/all/modules/contrib/migrate/migrate_extras/name.inc
Normal file
54
sites/all/modules/contrib/migrate/migrate_extras/name.inc
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Primary value passed to this field must be the 'given' name.
|
||||
* it cannot be NULL, but may be an empty string.
|
||||
*
|
||||
* Arguments are used to specify all the other values:
|
||||
* 'title' => array('source_field' => 'title'),
|
||||
* 'middle' => array('source_field' => 'middle'),
|
||||
* 'family' => array('source_field' => 'family'),
|
||||
* 'generational' => array('source_field' => 'generational'),
|
||||
* 'credentials' => array('source_field' => 'credentials'),
|
||||
*
|
||||
* Add the source field mappings to the argument array then add null mappings to
|
||||
* avoid having fields flagged as as unmapped:
|
||||
* @code
|
||||
* $arguments = array(
|
||||
* 'title' => array('source_field' => 'profile_title'),
|
||||
* 'middle' => array('source_field' => 'profile_middle_name'),
|
||||
* 'family' => array('source_field' => 'profile_last_name'),
|
||||
* );
|
||||
* // The given name should be passed in as the primary value.
|
||||
* $this->addFieldMapping('field_name', 'profile_first_name')
|
||||
* ->arguments($arguments);
|
||||
* // Since the excerpt is mapped via an argument, add a null mapping so it's
|
||||
* // not flagged as unmapped.
|
||||
* $this->addFieldMapping(NULL, 'profile_title');
|
||||
* $this->addFieldMapping(NULL, 'profile_middle_name');
|
||||
* $this->addFieldMapping(NULL, 'profile_last_name');
|
||||
* @endcode
|
||||
*/
|
||||
class MigrateNameHandler extends MigrateFieldHandler {
|
||||
public function __construct() {
|
||||
$this->registerTypes(array('name'));
|
||||
}
|
||||
|
||||
public function prepare($entity, array $field_info, array $instance, array $values) {
|
||||
$arguments = array();
|
||||
if (isset($values['arguments'])) {
|
||||
$arguments = array_filter($values['arguments']);
|
||||
unset($values['arguments']);
|
||||
}
|
||||
$language = $this->getFieldLanguage($entity, $field_info, $arguments);
|
||||
|
||||
// Setup the standard Field API array for saving.
|
||||
$delta = 0;
|
||||
foreach ($values as $value) {
|
||||
$return[$language][$delta] = array('given' => $value) + array_intersect_key($arguments, $field_info['columns']);
|
||||
$delta++;
|
||||
}
|
||||
|
||||
return isset($return) ? $return : NULL;
|
||||
}
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Support for the Pathauto module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Field handler.
|
||||
*/
|
||||
class MigratePathautoHandler extends MigrateDestinationHandler {
|
||||
public function __construct() {
|
||||
$this->registerTypes(array('node', 'user', 'taxonomy_term'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the destination field visible.
|
||||
*/
|
||||
public function fields() {
|
||||
if (module_exists('pathauto')) {
|
||||
return array(
|
||||
'pathauto' =>
|
||||
t('Pathauto: Perform aliasing (set to 0 to prevent alias generation during migration'),
|
||||
);
|
||||
}
|
||||
else {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
public function prepare($entity, stdClass $row) {
|
||||
if (isset($entity->pathauto)) {
|
||||
if (!isset($entity->path)) {
|
||||
$entity->path = array();
|
||||
}
|
||||
elseif (is_string($entity->path)) {
|
||||
// If MigratePathEntityHandler->prepare() hasn't run yet, support
|
||||
// the alias (set as $entity->path as a string) being formatted properly
|
||||
// in the path alias array.
|
||||
$path = $entity->path;
|
||||
$entity->path = array();
|
||||
$entity->path['alias'] = $path;
|
||||
}
|
||||
$entity->path['pathauto'] = $entity->pathauto;
|
||||
if (!isset($entity->path['alias'])) {
|
||||
$entity->path['alias'] = '';
|
||||
}
|
||||
unset($entity->pathauto);
|
||||
}
|
||||
}
|
||||
}
|
141
sites/all/modules/contrib/migrate/migrate_extras/privatemsg.inc
Normal file
141
sites/all/modules/contrib/migrate/migrate_extras/privatemsg.inc
Normal file
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Privatemag module integration
|
||||
*
|
||||
* Limitations:
|
||||
* - No updating of messages.
|
||||
* - No threading
|
||||
* - Messages are marked as deleted and not actually deleted. Thats the
|
||||
* privatemsg API.
|
||||
* - All these limitations can be helped by http://drupal.org/node/1184984.
|
||||
*/
|
||||
|
||||
class MigrateDestinationPrivateMsg extends MigrateDestinationEntity {
|
||||
|
||||
/**
|
||||
* An array with content ids of imported messages. Not yet used.
|
||||
*/
|
||||
var $importedIds = array();
|
||||
|
||||
static public function getKeySchema() {
|
||||
return array(
|
||||
'mid' => array(
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic initialization
|
||||
*
|
||||
* @param array $options
|
||||
* Options applied to private messages.
|
||||
*/
|
||||
public function __construct(array $options = array()) {
|
||||
parent::__construct('privatemsg_message', 'privatemsg_message', $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of fields available to be mapped/
|
||||
*
|
||||
* @return array
|
||||
* Keys: machine names of the fields (to be passed to addFieldMapping)
|
||||
* Values: Human-friendly descriptions of the fields.
|
||||
*/
|
||||
public function fields() {
|
||||
$fields = array(
|
||||
// 'mid' => 'Message ID', // Updating not supported. See http://drupal.org/node/1184984.
|
||||
'subject' => 'Subject',
|
||||
'body' => 'Body',
|
||||
'format' => 'Text format name for the Body',
|
||||
'recipients' => 'User IDs of recipients',
|
||||
'timestamp' => 'Timestamp',
|
||||
'author' => 'User ID of author',
|
||||
'is_new' => 'TRUE if unread by recipient, FALSE if read by recipient',
|
||||
);
|
||||
|
||||
// Then add in anything provided by handlers
|
||||
$fields += migrate_handler_invoke_all('Entity', 'fields', $this->entityType, $this->bundle);
|
||||
$fields += migrate_handler_invoke_all('PrivateMsg', 'fields', $this->entityType, $this->bundle);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark provided message as deleted.
|
||||
*
|
||||
* @param $id
|
||||
* IDs to be deleted.
|
||||
*/
|
||||
public function rollback(array $id) {
|
||||
migrate_instrument_start(__METHOD__);
|
||||
// Delete recipients of the message.
|
||||
db_delete('pm_index')
|
||||
->condition('mid', reset($id))
|
||||
->execute();
|
||||
// Delete message itself.
|
||||
db_delete('pm_message')
|
||||
->condition('mid', reset($id))
|
||||
->execute();
|
||||
migrate_instrument_stop(__METHOD__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a single message.
|
||||
*
|
||||
* @param $entity
|
||||
* Object object to build. Prefilled with any fields mapped in the Migration.
|
||||
* @param $row
|
||||
* Raw source data object - passed through to prepare/complete handlers.
|
||||
* @return array
|
||||
* Array of key fields of the object that was saved if
|
||||
* successful. FALSE on failure.
|
||||
*/
|
||||
public function import(stdClass $entity, stdClass $row) {
|
||||
$this->prepare($entity, $row);
|
||||
|
||||
// The privatemsg API does not support updating. See http://drupal.org/node/1184984
|
||||
// $message['mid'] = $entity->mid;
|
||||
|
||||
// The two user_load() calls here could by slow. If so, one could experiment
|
||||
// with entity cache module - http://drupal.org/project/entitycache.
|
||||
$options = array();
|
||||
if (isset($entity->timestamp)) $options['timestamp'] = Migration::timestamp($entity->timestamp);
|
||||
if (isset($entity->author)) $options['author'] = user_load($entity->author);
|
||||
if (isset($entity->format)) $options['format'] = $entity->format;
|
||||
|
||||
if (!is_array($entity->recipients)) {
|
||||
$entity->recipients = array($entity->recipients);
|
||||
}
|
||||
|
||||
foreach ($entity->recipients as $uid) {
|
||||
$entity->to[] = user_load($uid);
|
||||
}
|
||||
|
||||
// FYI, API is at http://api.worldempire.ch/api/privatemsg/privatemsg.module/function/privatemsg_new_thread/7-2
|
||||
$return = privatemsg_new_thread($entity->to, $entity->subject, $entity->body, $options);
|
||||
|
||||
if (!empty($return['success'])) {
|
||||
$this->complete((object)$return, $row);
|
||||
// Set the read status for the recipient (defaults to unread, so only need
|
||||
// to set if read)
|
||||
$mid = $return['message']->mid;
|
||||
if (isset($entity->is_new) && $entity->is_new == PRIVATEMSG_READ) {
|
||||
foreach ($entity->to as $account) {
|
||||
privatemsg_message_change_status($mid, $entity->is_new, $account);
|
||||
}
|
||||
}
|
||||
return array($mid);
|
||||
}
|
||||
else {
|
||||
$migration = Migration::currentMigration();
|
||||
$migration->saveMessage(reset($return['messages']['error']));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
189
sites/all/modules/contrib/migrate/migrate_extras/profile2.inc
Normal file
189
sites/all/modules/contrib/migrate/migrate_extras/profile2.inc
Normal file
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Support for profile2 destinations.
|
||||
*/
|
||||
|
||||
// TODO:
|
||||
// Make sure this works with updates, explicit destination keys
|
||||
|
||||
/**
|
||||
* Destination class implementing migration into nodes.
|
||||
*/
|
||||
class MigrateDestinationProfile2 extends MigrateDestinationEntity {
|
||||
|
||||
var $entity_type = 'profile2';
|
||||
var $entity_info = NULL;
|
||||
var $entity_key = NULL;
|
||||
|
||||
static public function getKeySchema() {
|
||||
$key = 'pid'; // Hard coded since $this->entity_key not in object context.
|
||||
return array(
|
||||
$key => array(
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an options array for profile2 destinations.
|
||||
*
|
||||
* @param string $language
|
||||
* Default language for profiles created via this destination class.
|
||||
* @param string $text_format
|
||||
* Default text format for profiles created via this destination class.
|
||||
*/
|
||||
static public function options($language, $text_format) {
|
||||
return compact('language', 'text_format');
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic initialization
|
||||
*
|
||||
* @param string $bundle
|
||||
* A.k.a. the profile type.
|
||||
* @param array $options
|
||||
* Options applied to profiles.
|
||||
*/
|
||||
public function __construct($bundle, array $options = array()) {
|
||||
parent::__construct($this->entity_type, $bundle, $options);
|
||||
$this->entity_info = entity_get_info('profile2');
|
||||
$this->entity_key = $this->entity_info['entity keys']['id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of fields available to be mapped for the node type (bundle)
|
||||
*
|
||||
* @return array
|
||||
* Keys: machine names of the fields (to be passed to addFieldMapping)
|
||||
* Values: Human-friendly descriptions of the fields.
|
||||
*/
|
||||
public function fields() {
|
||||
$fields = array();
|
||||
$type = ucfirst($this->entity_type) . ': ';
|
||||
// First the core (node table) properties
|
||||
$fields[$this->entity_key] = $type . t('Existing profile ID');
|
||||
$fields['uid'] = $type . t('Authored by (uid)');
|
||||
$fields['revision_uid'] = $type . t('Modified (uid)');
|
||||
//$fields['created'] = $type . t('Created timestamp');
|
||||
//$fields['changed'] = $type . t('Modified timestamp');
|
||||
//$fields['status'] = $type . t('Published');
|
||||
//$fields['revision'] = $type . t('Create new revision');
|
||||
$fields['language'] = $type . t('Language (fr, en, ...)');
|
||||
|
||||
// Then add in anything provided by handlers
|
||||
$fields += migrate_handler_invoke_all('Entity', 'fields', $this->entityType, $this->bundle);
|
||||
$fields += migrate_handler_invoke_all('Profile2', 'fields', $this->entityType, $this->bundle);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a batch of profiles at once.
|
||||
*
|
||||
* @param $ids
|
||||
* Array of profile IDs to be deleted.
|
||||
*/
|
||||
public function bulkRollback(array $ids) {
|
||||
migrate_instrument_start('profile2_delete_multiple');
|
||||
$this->prepareRollback($ids);
|
||||
entity_delete_multiple($this->entity_type, $ids);
|
||||
$this->completeRollback($ids);
|
||||
migrate_instrument_stop('profile2_delete_multiple');
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a single entity.
|
||||
*
|
||||
* @param $entity
|
||||
* Entity object to build. Prefilled with any fields mapped in the Migration.
|
||||
* @param $row
|
||||
* Raw source data object - passed through to prepare/complete handlers.
|
||||
* @return array
|
||||
* Array of key fields of the entity that was saved if
|
||||
* successful. FALSE on failure.
|
||||
*/
|
||||
public function import(stdClass $entity, stdClass $row) {
|
||||
$migration = Migration::currentMigration();
|
||||
$type = $this->entity_info['entity keys']['bundle'];
|
||||
$entity->$type = $this->bundle;
|
||||
list($id, $vid, $bundle) = entity_extract_ids($this->entity_type, $entity);
|
||||
|
||||
// Updating previously-migrated content?
|
||||
if (isset($row->migrate_map_destid1)) {
|
||||
// Make sure is_new is off
|
||||
$entity->is_new = FALSE;
|
||||
if (!empty($id)) {
|
||||
if ($id != $row->migrate_map_destid1) {
|
||||
throw new MigrateException(t("Incoming id !id and map destination id !destid1 don't match",
|
||||
array('!id' => $id, '!destid1' => $row->migrate_map_destid1)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$entity->{$this->entity_key} = $row->migrate_map_destid1;
|
||||
}
|
||||
}
|
||||
if ($migration->getSystemOfRecord() == Migration::DESTINATION) {
|
||||
if (empty($id)) {
|
||||
throw new MigrateException(t('System-of-record is DESTINATION, but no destination id provided'));
|
||||
}
|
||||
$old_entity = entity_load_single($this->entity_type, $id);
|
||||
if (!isset($entity->created)) {
|
||||
$entity->created = $old_entity->created;
|
||||
}
|
||||
if (!isset($entity->uid)) {
|
||||
$entity->uid = $old_entity->uid;
|
||||
}
|
||||
}
|
||||
|
||||
// Invoke migration prepare handlers
|
||||
$this->prepare($entity, $row);
|
||||
|
||||
// Trying to update an existing entity
|
||||
if ($migration->getSystemOfRecord() == Migration::DESTINATION) {
|
||||
// Incoming data overrides existing data.
|
||||
foreach ($entity as $field => $value) {
|
||||
$old_entity->$field = $value;
|
||||
}
|
||||
// Use the loaded entity from now on.
|
||||
$entity = $old_entity;
|
||||
}
|
||||
else {
|
||||
// Create a full profile class.
|
||||
$entity = entity_create($this->entity_type, (array) $entity);
|
||||
}
|
||||
|
||||
if (empty($id) && !(isset($entity->is_new) && $entity->is_new)) {
|
||||
$updating = TRUE;
|
||||
}
|
||||
else {
|
||||
$updating = FALSE;
|
||||
}
|
||||
|
||||
migrate_instrument_start('entity_save');
|
||||
entity_save($this->entity_type, $entity);
|
||||
migrate_instrument_stop('entity_save');
|
||||
|
||||
list($id, $vid, $bundle) = entity_extract_ids($this->entity_type, $entity);
|
||||
|
||||
if (isset($id)) {
|
||||
if ($updating) {
|
||||
$this->numUpdated++;
|
||||
}
|
||||
else {
|
||||
$this->numCreated++;
|
||||
}
|
||||
|
||||
$return = array($id);
|
||||
}
|
||||
else {
|
||||
$return = FALSE;
|
||||
}
|
||||
|
||||
$this->complete($entity, $row);
|
||||
return $return;
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Rules module integration
|
||||
*/
|
||||
|
||||
// Nothing yet. See migrate_extras_init() to disable rules during a migration.
|
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Test pathauto migration.
|
||||
*/
|
||||
class MigrateExtrasPathautoUnitTest extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Pathauto migration',
|
||||
'description' => 'Test disabling of pathauto during migration',
|
||||
'group' => 'Migrate',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('migrate', 'migrate_extras', 'features', 'token', 'path',
|
||||
'pathauto', 'migrate_extras_pathauto');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that setting 'pathauto' to FALSE when migrating actually prevents
|
||||
* pathauto from creating an alias.
|
||||
*/
|
||||
function testPathautoImport() {
|
||||
$migration = Migration::getInstance('MigrateExamplePathauto');
|
||||
$result = $migration->processImport();
|
||||
$this->assertEqual($result, Migration::RESULT_COMPLETED,
|
||||
t('Import returned RESULT_COMPLETED'));
|
||||
$rawnodes = node_load_multiple(FALSE, array('type' => 'migrate_example_pathauto'), TRUE);
|
||||
$this->assertEqual(count($rawnodes), 2, t('Two sample nodes created'));
|
||||
$count = db_select('url_alias', 'ua')
|
||||
->fields('ua', array('source'))
|
||||
->countQuery()
|
||||
->execute()
|
||||
->fetchField();
|
||||
$this->assertEqual($count, 0, t('No aliases generated'));
|
||||
}
|
||||
}
|
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Import User Relationships.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Destination class implementing migration into user_relationships table.
|
||||
*/
|
||||
class MigrateDestinationUserRelationships extends MigrateDestination {
|
||||
protected $typeID;
|
||||
protected $typeName;
|
||||
|
||||
/**
|
||||
* Construct a destination for the specified user relationship type. Interprets
|
||||
* the type as a type name - if that fails, assumes it's a type ID (rtid).
|
||||
*
|
||||
* @param mixed $type_name
|
||||
* Name of a user relationship type, or its rtid.
|
||||
*/
|
||||
public function __construct($type_name) {
|
||||
parent::__construct();
|
||||
$type = user_relationships_type_load(array('name' => $type_name));
|
||||
if ($type) {
|
||||
$this->typeName = $type_name;
|
||||
$this->typeID = $type->rtid;
|
||||
}
|
||||
else {
|
||||
$type = user_relationships_type_load($type_name);
|
||||
$this->typeName = $type->name;
|
||||
$this->typeID = $type_name;
|
||||
}
|
||||
}
|
||||
|
||||
static public function getKeySchema() {
|
||||
return array(
|
||||
'rid' => array(
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'description' => 'Relationship ID',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a membership.
|
||||
*
|
||||
* @param $id
|
||||
* ID to be deleted.
|
||||
*/
|
||||
public function rollback(array $id) {
|
||||
migrate_instrument_start(__METHOD__);
|
||||
if ($relationship = user_relationships_load(array('rid' => $id['destid1']))) {
|
||||
$account = new stdClass;
|
||||
user_relationships_delete_relationship(current($relationship), $account);
|
||||
}
|
||||
migrate_instrument_stop(__METHOD__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a single membership.
|
||||
*
|
||||
* @param $entity
|
||||
* Object object to build. Prefilled with any fields mapped in the Migration.
|
||||
* @param $row
|
||||
* Raw source data object - passed through to prepare/complete handlers.
|
||||
* @return array
|
||||
* Array of key fields of the object that was saved if
|
||||
* successful. FALSE on failure.
|
||||
*/
|
||||
public function import(stdClass $entity, stdClass $row) {
|
||||
// Normalize to unix timestamps.
|
||||
foreach (array('created_at', 'updated_at') as $property) {
|
||||
if (isset($entity->$property)) {
|
||||
$entity->$property = Migration::timestamp($entity->$property);
|
||||
}
|
||||
}
|
||||
|
||||
$entity->rtid = $this->typeID;
|
||||
|
||||
$op = isset($entity->op) ? $entity->op : 'approve';
|
||||
if ($saved = user_relationships_save_relationship($entity, $op)) {
|
||||
return array($saved->rid);
|
||||
}
|
||||
}
|
||||
|
||||
public function fields() {
|
||||
return array(
|
||||
'rid' => 'Relationship ID',
|
||||
'requester_id' => 'User ID of relationship requestor',
|
||||
'requestee_id' => 'User ID of relationship requestee',
|
||||
'approved' => 'Whether the requestee approved the relationship',
|
||||
'created_at' => 'Timestamp when the relationship was created',
|
||||
'updated_at' => 'Timestamp when the relationship was last updated',
|
||||
'flags' => 'UR_OK (0) or UR_BANNED (1)',
|
||||
'op' => 'Default value is \'approve\'. Sent as second param to user_relationships_save_relationship().'
|
||||
);
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return t('User relationship type: !type', array('!type' => $this->typeName));
|
||||
}
|
||||
}
|
168
sites/all/modules/contrib/migrate/migrate_extras/votingapi.inc
Normal file
168
sites/all/modules/contrib/migrate/migrate_extras/votingapi.inc
Normal file
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
// $Id$
|
||||
|
||||
/**
|
||||
* @file
|
||||
* VotingAPI module integration
|
||||
*/
|
||||
|
||||
/**
|
||||
* Destination class for the votingapi_vote table.
|
||||
*/
|
||||
class MigrateDestinationVotingapi extends MigrateDestination {
|
||||
public function __toString() {
|
||||
return t('votingapi');
|
||||
}
|
||||
|
||||
/**
|
||||
* An array with content ids of imported votes. Used for recalculating results.
|
||||
*/
|
||||
var $importedIds = array();
|
||||
|
||||
static public function getKeySchema() {
|
||||
return array(
|
||||
'vote_id' => array(
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the provided votes and recalculate the results.
|
||||
*
|
||||
* @param $id
|
||||
* IDs to be deleted.
|
||||
*/
|
||||
public function bulkRollback(array $ids) {
|
||||
migrate_instrument_start(__METHOD__);
|
||||
|
||||
foreach ($ids as $id) {
|
||||
$votes[]['vote_id'] = $id;
|
||||
}
|
||||
votingapi_delete_votes($votes);
|
||||
|
||||
// foreach($votes as $vote) {
|
||||
// votingapi_recalculate_results($vote['content_type'], $vote['content_id'], TRUE);
|
||||
// }
|
||||
|
||||
migrate_instrument_stop(__METHOD__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a single vote.
|
||||
*
|
||||
* @param $entity
|
||||
* Object object to build. Prefilled with any fields mapped in the Migration.
|
||||
* @param $row
|
||||
* Raw source data object - passed through to prepare/complete handlers.
|
||||
* @return array
|
||||
* Array of key fields of the object that was saved if
|
||||
* successful. FALSE on failure.
|
||||
*/
|
||||
public function import(stdClass $entity, stdClass $row) {
|
||||
$this->prepare($entity, $row);
|
||||
|
||||
// Votes have to be assigned to an entity.
|
||||
if (empty($entity->entity_id)) {
|
||||
watchdog('VotingAPI Import', 'Skipped import due to empty entity_id for vote import: @serial', array('@serial' => json_encode($row)), WATCHDOG_ERROR);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (isset($entity->timestamp)) {
|
||||
$entity->timestamp = Migration::timestamp($entity->timestamp);
|
||||
}
|
||||
|
||||
// Just converting $entity to an array doesn't work...
|
||||
$vote = array();
|
||||
$vote['entity_type'] = $entity->entity_type;
|
||||
$vote['entity_id'] = $entity->entity_id;
|
||||
$vote['value_type'] = $entity->value_type;
|
||||
$vote['value'] = $entity->value;
|
||||
$vote['uid'] = $entity->uid;
|
||||
$vote['tag'] = $entity->tag;
|
||||
$vote['timestamp'] = $entity->timestamp;
|
||||
$vote['vote_source'] = $entity->vote_source;
|
||||
votingapi_add_votes($vote);
|
||||
if (isset($vote[0]['vote_id'])) {
|
||||
$entity->vote_id = $vote[0]['vote_id'];
|
||||
$this->complete($entity, $row);
|
||||
$this->importedIds[$entity->entity_type][] = $entity->entity_id;
|
||||
return array($entity->vote_id);
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We're done with importing votes, recalculate the results.
|
||||
*/
|
||||
function postImport() {
|
||||
foreach ($this->importedIds as $entity_type => $entity_ids) {
|
||||
$this->importedIds = array_unique($this->importedIds);
|
||||
foreach ($entity_ids as $entity_id) {
|
||||
votingapi_recalculate_results($entity_type, $entity_id, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of fields available to be mapped/
|
||||
*
|
||||
* @return array
|
||||
* Keys: machine names of the fields (to be passed to addFieldMapping)
|
||||
* Values: Human-friendly descriptions of the fields.
|
||||
*/
|
||||
public function fields() {
|
||||
return array(
|
||||
'vote_id' => 'Vote ID',
|
||||
'entity_type' => "Entity Type (defaults to 'node')",
|
||||
'entity_id' => 'Entity ID',
|
||||
'value' => 'Numeric vote value',
|
||||
'value_type' => "Value type (percent/points, defaults to 'percent')",
|
||||
'tag' => "Tag (defaults to 'vote')",
|
||||
'uid' => 'User ID',
|
||||
'timestamp' => 'Timestamp',
|
||||
'vote_source' => 'Vote Source IP Address',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Give handlers a shot at modifying the object before saving it.
|
||||
*
|
||||
* @param $entity
|
||||
* Entity object to build. Prefilled with any fields mapped in the Migration.
|
||||
* @param $source_row
|
||||
* Raw source data object - passed through to prepare handlers.
|
||||
*/
|
||||
public function prepare(stdClass $entity, stdClass $source_row) {
|
||||
$migration = Migration::currentMigration();
|
||||
$entity->migrate = array(
|
||||
'machineName' => $migration->getMachineName(),
|
||||
);
|
||||
|
||||
// Call any prepare handler for this specific Migration.
|
||||
if (method_exists($migration, 'prepare')) {
|
||||
$migration->prepare($entity, $source_row);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Give handlers a shot at modifying the object (or taking additional action)
|
||||
* after saving it.
|
||||
*
|
||||
* @param $object
|
||||
* Entity object to build. This is the complete object after saving.
|
||||
* @param $source_row
|
||||
* Raw source data object - passed through to complete handlers.
|
||||
*/
|
||||
public function complete(stdClass $entity, stdClass $source_row) {
|
||||
$migration = Migration::currentMigration();
|
||||
|
||||
// Call any complete handler for this specific Migration.
|
||||
if (method_exists($migration, 'complete')) {
|
||||
$migration->complete($entity, $source_row);
|
||||
}
|
||||
}
|
||||
}
|
282
sites/all/modules/contrib/migrate/migrate_extras/webform.inc
Normal file
282
sites/all/modules/contrib/migrate/migrate_extras/webform.inc
Normal file
@@ -0,0 +1,282 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Destination class for the webform_submissions table.
|
||||
*
|
||||
* Working component types:
|
||||
* - email
|
||||
* - date ('Y-m-d')
|
||||
* - file (use the file id)
|
||||
* - markup
|
||||
* - pagebreak (content is ignored)
|
||||
* - select (looks up the key by default, pass 'source_type' => 'value' as an
|
||||
* argument to try to match the value)
|
||||
* - textfield
|
||||
* - textarea
|
||||
* - time ('H:i:s')
|
||||
* Untested/needs work:
|
||||
* - grid
|
||||
* - hidden
|
||||
*/
|
||||
class MigrateDestinationWebformSubmission extends MigrateDestination {
|
||||
static public function getKeySchema() {
|
||||
return array(
|
||||
'sid' => array(
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'unsigned' => TRUE,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The webform of the destination.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $node;
|
||||
public function getWebform() {
|
||||
return $this->node;
|
||||
}
|
||||
|
||||
/**
|
||||
* An array mapping our custom names to component ids.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $component_cids;
|
||||
|
||||
/**
|
||||
* Constructs a destination for a given webform node.
|
||||
*
|
||||
* @param object $node
|
||||
* A node object that's type has been enabled for webform use.
|
||||
*/
|
||||
public function __construct($node) {
|
||||
parent::__construct();
|
||||
|
||||
if (empty($node)) {
|
||||
throw new Exception(t("You must provide a webform node"));
|
||||
}
|
||||
// Make sure it's a webform node.
|
||||
$types = webform_variable_get('webform_node_types');
|
||||
if (!in_array($node->type, $types)) {
|
||||
throw new Exception(t("The node must be configured to accept webform submissions but %type was not", array('%type' => $node->type)));
|
||||
}
|
||||
$this->node = $node;
|
||||
|
||||
// Webform expects the component values to be keyed by cid, so we need a
|
||||
// hash to map prefixed field names to cid.
|
||||
$this->component_cids = array();
|
||||
foreach ($this->node->webform['components'] as $component) {
|
||||
$this->component_cids['data_' . $component['form_key']] = $component['cid'];
|
||||
}
|
||||
|
||||
// We use the functions in this file in import() but load it here so we
|
||||
// only do it once.
|
||||
module_load_include('inc', 'webform', 'includes/webform.submissions');
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return t('Submission for the <a href="!link">%title</a> Webform', array(
|
||||
'!link' => url('node/' . $this->node->nid),
|
||||
'%title' => $this->node->title,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of fields available to be mapped.
|
||||
*
|
||||
* @return array
|
||||
* Keys: machine names of the fields (to be passed to addFieldMapping)
|
||||
* Values: Human-friendly descriptions of the fields.
|
||||
*/
|
||||
public function fields() {
|
||||
// Fields defined by the schema. nid is omitted since it should come from
|
||||
// $this->node.
|
||||
$fields = array(
|
||||
'sid' => t('The unique identifier for this submission.'),
|
||||
'uid' => t('The id of the user that completed this submission.'),
|
||||
'is_draft' => t('Is this a draft of the submission?'),
|
||||
'submitted' => t('Timestamp of when the form was submitted.'),
|
||||
'remote_addr' => t('The IP address of the user that submitted the form.'),
|
||||
);
|
||||
|
||||
// Create a field for each component on the webform.
|
||||
foreach ($this->node->webform['components'] as $component) {
|
||||
// TODO: Seems like we should skip over page break components.
|
||||
$fields['data_' . $component['form_key']] = t('@type: @name', array('@type' => $component['type'], '@name' => $component['name']));
|
||||
}
|
||||
|
||||
// Then add in anything provided by handlers.
|
||||
$fields += migrate_handler_invoke_all('WebformSubmission', 'fields', $this->node);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Give handlers a shot at modifying the object before saving it.
|
||||
*
|
||||
* @param $entity
|
||||
* Webform submission object to build. Prefilled with any fields mapped in
|
||||
* the Migration.
|
||||
* @param $source_row
|
||||
* Raw source data object - passed through to prepare handlers.
|
||||
*/
|
||||
public function prepare($entity, stdClass $source_row) {
|
||||
$migration = Migration::currentMigration();
|
||||
$entity->migrate = array(
|
||||
'machineName' => $migration->getMachineName(),
|
||||
);
|
||||
// Call any general object handlers.
|
||||
migrate_handler_invoke_all('WebformSubmission', 'prepare', $entity, $source_row, $this->node);
|
||||
|
||||
// Then call any prepare handler for this specific Migration.
|
||||
if (method_exists($migration, 'prepare')) {
|
||||
$migration->prepare($entity, $source_row, $this->node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Give handlers a shot at modifying the object (or taking additional action)
|
||||
* after saving it.
|
||||
*
|
||||
* @param $entity
|
||||
* Webform submission object to build. This is the complete object after
|
||||
* saving.
|
||||
* @param $source_row
|
||||
* Raw source data object - passed through to complete handlers.
|
||||
*/
|
||||
public function complete($entity, stdClass $source_row) {
|
||||
$migration = Migration::currentMigration();
|
||||
// Call any general object handlers.
|
||||
migrate_handler_invoke_all('WebformSubmission', 'complete', $entity, $source_row, $this->node);
|
||||
// Then call any complete handler for this specific Migration.
|
||||
if (method_exists($migration, 'complete')) {
|
||||
$migration->complete($entity, $source_row, $this->node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a record.
|
||||
*
|
||||
* @param $entity
|
||||
* Webform submission object to build. This is the complete object after
|
||||
* saving.
|
||||
* @param $source_row
|
||||
* Raw source data object - passed through to complete handlers.
|
||||
*/
|
||||
public function import(stdClass $entity, stdClass $row) {
|
||||
// Updating previously-migrated content?
|
||||
$migration = Migration::currentMigration();
|
||||
if (isset($row->migrate_map_destid1)) {
|
||||
if (isset($entity->sid) && $entity->sid != $row->migrate_map_destid1) {
|
||||
throw new MigrateException(t("Incoming sid !sid and map destination sid !destid1 don't match",
|
||||
array('!sid' => $entity->sid, '!destid1' => $row->migrate_map_destid1)));
|
||||
}
|
||||
else {
|
||||
$entity->sid = $row->migrate_map_destid1;
|
||||
}
|
||||
}
|
||||
|
||||
$entity->nid = $this->node->nid;
|
||||
|
||||
// Move the data from our custom keys back to webform's component ids.
|
||||
$data = array();
|
||||
foreach ($this->component_cids as $field_name => $cid) {
|
||||
if (isset($entity->$field_name)) {
|
||||
// Move the arguments out and kill any extraneous wrapper arrays.
|
||||
$value = $entity->$field_name;
|
||||
$arguments = array();
|
||||
if (is_array($value) && isset($value['arguments'])) {
|
||||
$arguments = (array) $value['arguments'];
|
||||
unset($value['arguments']);
|
||||
$value = count($value) ? reset($value) : $value;
|
||||
}
|
||||
// Avoid a warning if they passed in an empty array.
|
||||
$arguments += array('source_type' => 'key');
|
||||
|
||||
// By default passed to select components are assumed to be the
|
||||
// key. If the key should be looked up use the add a
|
||||
// array('source_type' => 'value') argument to the field mapping.
|
||||
$component = $this->node->webform['components'][$cid];
|
||||
if ($component['type'] == 'select' && $arguments['source_type'] == 'value') {
|
||||
$options = _webform_select_options($component);
|
||||
$id = array_search($value, $options);
|
||||
$data[$cid] = ($id === FALSE) ? NULL : $id;
|
||||
}
|
||||
else {
|
||||
$data[$cid] = $value;
|
||||
}
|
||||
unset($entity->$field_name);
|
||||
}
|
||||
}
|
||||
$entity->data = webform_submission_data($this->node, $data);
|
||||
|
||||
// Invoke migration prepare handlers
|
||||
$this->prepare($entity, $row);
|
||||
|
||||
migrate_instrument_start('webform_submission_update/insert');
|
||||
// Determine if it's an insert or update.
|
||||
if (empty($entity->sid)) {
|
||||
$updating = FALSE;
|
||||
$sid = webform_submission_insert($this->node, $entity);
|
||||
}
|
||||
else {
|
||||
// If the sid was specified but doesn't exist we'll need to stick an
|
||||
// empty record in so webform's update has something to stick to.
|
||||
$status = db_merge('webform_submissions')
|
||||
->key(array(
|
||||
'sid' => $entity->sid,
|
||||
))
|
||||
->insertFields(array(
|
||||
'sid' => $entity->sid,
|
||||
'nid' => $entity->nid,
|
||||
'submitted' => $entity->submitted,
|
||||
'remote_addr' => $entity->remote_addr,
|
||||
'is_draft' => $entity->is_draft,
|
||||
'bundle' => $entity->bundle,
|
||||
))
|
||||
->execute();
|
||||
// If db_merge() makes no changes $status is NULL so make a less
|
||||
// elegant comparison.
|
||||
$updating = MergeQuery::STATUS_INSERT !== $status;
|
||||
$sid = webform_submission_update($this->node, $entity);
|
||||
}
|
||||
migrate_instrument_stop('webform_submission_update/insert');
|
||||
|
||||
if (isset($sid)) {
|
||||
$entity->sid = $sid;
|
||||
|
||||
if ($updating) {
|
||||
$this->numUpdated++;
|
||||
}
|
||||
else {
|
||||
$this->numCreated++;
|
||||
}
|
||||
$return = array($sid);
|
||||
}
|
||||
else {
|
||||
$return = FALSE;
|
||||
}
|
||||
|
||||
// Invoke migration complete handlers
|
||||
$this->complete($entity, $row);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a batch of submissions at once.
|
||||
*
|
||||
* @param $sids
|
||||
* Array of submission IDs to be deleted.
|
||||
*/
|
||||
public function bulkRollback(array $sids) {
|
||||
migrate_instrument_start(__METHOD__);
|
||||
foreach (webform_get_submissions(array('sid' => $sids)) as $submission) {
|
||||
webform_submission_delete($this->node, $submission);
|
||||
}
|
||||
migrate_instrument_stop(__METHOD__);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user