initial commit

This commit is contained in:
Chris Sewell
2012-11-28 03:55:08 -05:00
parent 7adb399b2e
commit cf140a2e97
3247 changed files with 492437 additions and 0 deletions

150
lib/symfony/vendor/propel-generator/CHANGELOG vendored Executable file
View File

@ -0,0 +1,150 @@
P R O P E L C H A N G E S
============================
Mar 7, 2007 - 1.2.1
ChangeLog for 1.2.1 at http://propel.phpdb.org/trac/query?status=closed&milestone=1.2.1&resolution=fixed&order=priority
Aug 31, 2006 - 1.2.0
Breaking Changes:
*** New API for generic accessors and settors (see API docs). The methods are
the same but the default indexing has changed.
*** New API for validators (see Wiki / docs).
Major Changes (for complete list see issue tracker at http://propel.phpdb.org):
- Propel now compatible w/ PHP >= 5.0.5 & 5.1.x
- New MySQLi driver for Propel (use 'mysqli' instead of 'mysql')
- Added propel-gen script to standard-installed versions of Propel also
- New XSD schema for validating the XML datamodel descriptions (schema.xml)
- Support for specifying vendor-specific info in the schema.xml
- Better support for sequences in reverse engineering PostgreSQL databases
- #146 Added 'size' attribute to <index-column> and <unique-column>
- New extensible OO builder classes for generating PHP5 classes and SQL DDL
- Identifier escaping in generated SQL (note: for Postgres this means columns
are case-sensitive)
- Numerous improvements to validation framework, including new, cleaner API
- Added doCountJoin*() methods to the generated Peer classes
- Obj->save() calls now return the number of affected rows (if supported by db)
- See http://propel.phpdb.org/trac/report/9 for complete list of closed tickets
by milestone.
April 7, 2005 - 1.1.0
Big Changes:
*** Changed retrieveByPK() to return NULL instead of throw Exception if no row
was matched. (Dave Lawson)
*** New PHP runtime conf format has changed (must regenerate conf file).
*** Dropped support for deprecated ini-format runtime properties file. (Hans)
*** Cleanup of build properties files, removal of deprecated properties. (Hans)
New Features:
- Schema attributes are no longer case-sensitive.
- New <vendor> tag allows specifying vendor-specific attributes. (Pavel)
- MySQL identifiers escaping added to SQL generation templates. (Pavel)
- MySQL unique indexes SQL generation added. (Pavel)
- Added support for interface="" attribute of <table> tag; defaults to Persistent. (Hans)
- Added doSelectJoinAll() to generated peer classes. (Hans)
- Added doDeleteAll() method to remove all rows from specified table. (Hans)
- Added support for returning affected rows from update methods in peer classes. (Hans)
- Added PHPUnit2-based unit testing framework to replace old bookstore-test.php
- Added schema validation / error throwing to schema parser. (Pavel)
- Logging is now optional (no log section means no logger used). (David Z<>lke)
- Added TIMESTAMP_BU, DATE_BU types for "before-unix" (pre 1970) dates. (Hans)
Bug Fixes:
- Fixed E_STRICT error in generated Peer doCount() method (Hans)
- Fixed bug when using doSelectJoin*() methods with tables that have lazyload columns. (Hans)
- Fixed logic bugs in doSelectJoinExcept*() method generation. (Hans)
- Fixed support for temporal (date/time) default values. (Hans)
- Fixed bug where setting only default values in object would result in no save. (Hans)
- Fixes to PropelSQLExecTask to handle non-typical queries (Dominik, Hans).
- Fixed bug in enumerated inheritance when using string coltype (Kaspars)
- Fixes to charset / encoding in schema creation. (Joe Cai, Pavel)
- Fixed nested external schema bug. (Pavel)
- Fixed unexpected results bug in NodePeer::buildFamilyCriteria(). (Dave Lawson)
- Fixed clearSelectColumns() to also clear $asColumns. (Fabien Potencier)
Oct. 24, 2004 - 1.0.0
Big Changes:
- Removed Transaction class, refactoring functionality into Creole
Connection classes (Dave Lawson)
- New NodePeer for handling hierarchies (Dave Lawson)
- Propel has a new default directory layout for projects. All project
files are now located in one directory.
projects/
|- bookstore/
| |- build/
| |- schema.xml
| |- runtime.properties <-- deprecated
| |- runtime-conf.xml <-- new standard
- Added new default XML format for setting Propel's runtime properties.
(see dir layout above).
- Added new build.xml to wrap build-propel.xml. New file is preferred
way to build projects, as it allows for inclusion of project-specific
build.properties files. Propel is finally fully multi-project friendly.
- Support for specifying "lazy-load" columns in schema XML. Lazy load
columns will only be populated on demand. This means that by default
object hyradtion will not include these columns (so smaller, faster
objects), but also that an additional query is executed when data is
needed. (This is particularly useful for BLOB/CLOB columns.)
Minor Changes:
[Generated Classes]
- Peer::populateObject() method deprecated (will remove in Propel 1.1) in
favor of Object->hydrate()
- Removed Peer::buildCriteria() method in favor of Object->buildCriteria()
and Object->buildPkeyCriteria()
- Peer doSelect*() family of methods now [consistently] only takes
Criteria objects for parameter.
- No more support in generated Peer classes for using Criteria with
different DB name.
- Date/time setter methods now perform a strtotime() conversion on passed
data and throw a PropelException is such a conversion cannot be performed.
- New copy() method replaces non-working __clone() impl. __clone() unused due
to desire to have a way to copy objects w/o necessarying copying rows.
[Default Properties]
- The schema include pattern changed to *schema.xml (instead of
*-schema.xml), for added flexibility in layout.
[SQL Generator]
- Updated model classes to recognize boolean values in case-insensitive
manner (allow "TRUE" & "true").
- Updated model classes to recognize Propel types in case-insensitive
manner (allow "integer" & "INTEGER").
June 8, 2003 - 1.0.0-beta1
Bug Fixes:
- Fixed 'creole' target to include database name in generated schema XML
- Fixed Propel to work correctly with tables that have pkey, but no
autoIncrement cols
- Fixed Criteria toString() method to work [for SELECT clauses only]
- TIMESTAMP defaults to DATETIME for MySQL
- Added support for COMMENT keyword (for descriptions from schema) in
MySQL table definitions
- Fixed Table->containsColumn() method in propel-generator
- Fixed insert-sql to work with multi-line & complex SQL statements (Dominik del Bondio)
May 2, 2004 - 1.0.0-alpha2
Bug Fixes:
- LONGVARCHAR no longer considered LOB column (HL)
- Added INDEX for MySQL/InnoDB foreign keys
- Removed old references to BOOLEANINT/BOOLEANCHAR from platform classes (HL)
- Allow missing autoIncrement column w/o requiring idMethod="none" (HL)
- Fixed parse errors in generated classes w/ multi-column primary key (HL)
New Features:
- Added column validator framework and validator suite (MA)
- Added doCount() method to generated peers (MA)
--$Id: CHANGELOG,v 1.11 2005/04/07 22:25:52 hlellelid Exp $

176
lib/symfony/vendor/propel-generator/INSTALL vendored Executable file
View File

@ -0,0 +1,176 @@
I N S T A L L I N G P R O P E L
==================================
This is a quick guide for installing Propel and building the provided sample
bookstore application. For more information on installation / configuration
see the online user guide available from main site: http://propel.phpdb.org
Prerequisites
-------------
Before you can install and run Propel you will need to have the following:
* PHP >= 5.0.0
Propel will only work with PHP5. Additionally, you must have a command-
line version of PHP5 in order to use PHING to build the classes and SQL
files for your data model. PHP must also have compiled in XML (libxml2, xsl)
support in order to take advantage of all build options.
* PHING >= 2.0.0
Propel uses the PHING build system to build the classes and SQL definition
files for your data model. PHING is an open-source project build system
based on Apache ANT. PHING 2 is the (development) version built for PHP5.
See http://phing.tigris.org/ to learn how to install Phing (it's easy).
* Creole >- 1.0.0
Creole is a Uniform DB API framework for PHP5. Creole is available as a PEAR
package or can be installed in a more traditional manner. See
http://creole.phpdb.org/ to get a copy of the Creole classes.
* A supported RDBMS
Creole currently supports MySQL, MS SQL Server, PostgreSQL, and SQLite. We
are working on support for Oracle and the new MySQLi drivers but this should
be considered alpha, at best.
Quick Install (PEAR)
--------------------
It is now possible to install both the Propel runtime and the generator classes as
PEAR packages. This is the quickest way to get up and running with Propel, but may
not be quite as easy to configure as the traditional installation method.
* Propel Generator:
% pear install http://propel.phpdb.org/pear/propel_generator-current.tgz
To use the generator to build sql, php classes, etc. simply use the propel-gen shell
script:
% propel-gen /path/to/my/projectdir
(See the sample bookstore project directory in your PEAR data directory for a sample
projectdir.)
* Propel Runtime:
% pear install http://propel.phpdb.org/pear/propel_runtime-current.tgz
It is recommended that you read over the traditional install guide also, so that you
understand the roles of some of the various files. In the PEAR install these files
(e.g. the main build.properties and the sample bookstore project) are stored in the
PEAR data dir (e.g. /usr/local/lib/php/data, C:\PHP\PEAR\data).
Traditional Installation
------------------------
Installation of Propel involves a few steps because Propel is composed of a generator
and runtime classes which are (now) packaged separately.
Begin installation of Propel by choosing a base directory and unpacking the archive.
For the sake of simplicity, we'll assume that you are installing from a package
(instead of CVS) into /var/www/php/.
% cd /var/www/php
% tar zxf /path/to/propel-x.x.x.tar.gz
% ln -s propel-x.x.x propel
A. Propel Generator
The Propel generator classes don't need any special setup. The classes and Phing
scripts are located in the propel-generator/ directory (which in our example is
/var/www/php/propel/generator).
B. Runtime Classes
The runtime classes were unpacked to the propel/ directory (in this example,
/var/www/php/propel). In order to use these classes in runtime applications, you will
need to make sure that they are on the PHP include_path. In our example, the
following directory would need to be added to your PHP include_path:
/var/www/php/propel/classes. You could also copy the
/var/www/php/propel/classes/propel directory to a location that is already on your
include_path, e.g. the directory where PEAR classes are located:
% cp -r /var/www/php/propel/runtime/classes/propel /usr/local/lib/php/
Another option on *nix systems is to create a symlink:
% ln -s /var/www/php/propel/runtime/classes/propel /usr/local/lib/php/propel
Quick Test
----------
If you want to quickly test & see whether your installation is working, you can use
the default configuration which will build the example application using SQLite.
Here is how to run the simple test on Unix (use corresponding commands for Windows).
If you run into trouble, don't panic -- just continue reading the INSTALL guide and
consult the Installation chapter of the online user guide at http://propel.phpdb.org.
Change to your propel-generator dir (e.g.)
$> cd /var/www/php/propel/generator
If using Propel from CVS, copy/rename the build.properties-sample file:
$> cp build.properties-sample build.properties
Run Phing to build the classes and SQL files, specifying the bookstore project
$> phing -Dproject=bookstore
Run the 'insert-sql' target which will add the tables to the SQLite db
$> phing -Dproject=bookstore insert-sql
Run the test script that uses the generated classes against the bookstore db:
$> cd test/
$> php -f bookstore-test.php
You should see a bunch of output as it tests use cases. Hopefully there aren't any
"FAILED" messages. If you get a failed message immediately indicating that it can't
find one of the tables make sure that you a) ran the 'insert'-sql' target and that
you are running the bookstore-test.php script from the main propel directory *and*
that you call PHP with the -qC options so that it won't chdir() into the scripts
directory. (The path for the bookstore.db is ./test/bookstore.db so you can see
that you need to be in the main propel directory for that to work.)
Configure
---------
To get Propel to work with your own db setup, create a new project (easiest way is
to use the bookstore project directory as a template). Create your datamodel schema,
modify the build.properties for that project to specify database connection
information, and set the db connection runtime properties in runtime-conf.xml.
Build
-----
This assumes that you have already installed and configured a copy of PHING 2.
% cd /var/www/php/propel/generator
% phing -Dproject=mykillerapp
This will build the SQL files and the object & peer classes based on your datamodel
schema XML file.
The resulting files will be placed in:
/var/www/php/propel/generator/projects/mykillerapp/build
If you encounter any problems, try adding -verbose or -debug to get more output
from the PHING build process.
You're Done!
------------
At this point hopefully you have successfully built the classes and SQL definitions
for the sample bookstore application. If you encountered problems, please visit
http://propel.phpdb.org to read additional documention, browse through the users
mailing list, or add a bug report.
Enjoy!
--$Id: INSTALL,v 1.4 2005/03/24 00:24:07 hlellelid Exp $

506
lib/symfony/vendor/propel-generator/LICENSE vendored Executable file
View File

@ -0,0 +1,506 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
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 and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it
becomes a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, 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 library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete 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 distribute a copy of this License along with the
Library.
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 Library or any portion
of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
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 Library, 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 Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you 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.
If distribution of 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 satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be 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.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library 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.
9. 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 Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
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 with
this License.
11. 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 Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library 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 Library.
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.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library 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.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser 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 Library
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 Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
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
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "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
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. 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 LIBRARY 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
LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. 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 library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
--$Id: LICENSE,v 1.1 2004/07/14 02:18:14 hlellelid Exp $

View File

@ -0,0 +1,67 @@
#!/bin/sh
# Shell wrapper for Propel generator
# $Id$
#
# This script will do the following:
# - check for PHING_COMMAND env, if found, use it.
# - if not found assume php is on the path
# - check for PROPEL_GEN_HOME evn, if found use it
# - if not look for it
if [ -z "$PROPEL_GEN_HOME" ] ; then
# echo "WARNING: PROPEL_GEN_HOME environment not set. Attempting to guess."
# try to find Propel
if [ -d /opt/propel/generator ] ; then
PROPEL_GEN_HOME=/opt/propel/generator
fi
if [ -d "${HOME}/opt/propel/generator" ] ; then
PROPEL_GEN_HOME="${HOME}/opt/propel/generator"
fi
if [ -d "/usr/local/propel/generator" ] ; then
PROPEL_GEN_HOME="/usr/local/propel/generator"
fi
if [ -d "${HOME}/usr/propel/generator" ] ; then
PROPEL_GEN_HOME="${HOME}/usr/propel/generator"
fi
## resolve links - $0 may be a link to phing's home
PRG="$0"
progname=`basename "$0"`
saveddir=`pwd`
# need this for relative symlinks
dirname_prg=`dirname "$PRG"`
cd "$dirname_prg"
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
PROPEL_GEN_HOME=`dirname "$PRG"`/..
cd "$saveddir"
# make it fully qualified
PROPEL_GEN_HOME=`cd "$PROPEL_GEN_HOME" && pwd`
# make it available in PHP via getenv("PROPEL_GEN_HOME")
export PROPEL_GEN_HOME
fi
if (test -z "$PHING_COMMAND") ; then
# echo "WARNING: PHING_COMMAND environment not set. (Assuming phing on PATH)"
export PHING_COMMAND="phing"
fi
$PHING_COMMAND -f $PROPEL_GEN_HOME/build.xml -Dusing.propel-gen=true -Dproject.dir=$*

View File

@ -0,0 +1,47 @@
@echo off
rem *********************************************************************
rem ** The Propel generator convenience script for Windows based systems
rem ** $Id$
rem *********************************************************************
rem This script will do the following:
rem - check for PHING_COMMAND env, if found, use it.
rem - if not found detect php, if found use it, otherwise err and terminate
rem - check for PROPEL_GEN_HOME evn, if found use it
rem - if not found error and leave
if "%OS%"=="Windows_NT" @setlocal
rem %~dp0 is expanded pathname of the current script under NT
set DEFAULT_PROPEL_GEN_HOME=%~dp0..
goto init
goto cleanup
:init
if "%PROPEL_GEN_HOME%" == "" set PROPEL_GEN_HOME=%DEFAULT_PROPEL_GEN_HOME%
set DEFAULT_PROPEL_GEN_HOME=
if "%PHING_COMMAND%" == "" goto no_phingcommand
goto run
goto cleanup
:run
%PHING_COMMAND% -f %PROPEL_GEN_HOME%\build.xml -Dusing.propel-gen=true -Dproject.dir=%*
goto cleanup
:no_phingcommand
REM echo ------------------------------------------------------------------------
REM echo WARNING: Set environment var PHING_COMMAND to the location of your phing
REM echo executable (e.g. C:\PHP\phing.bat).
REM echo Proceeding with assumption that phing.bat is on Path
REM echo ------------------------------------------------------------------------
set PHING_COMMAND=phing.bat
goto init
:cleanup
if "%OS%"=="Windows_NT" @endlocal
REM pause

View File

@ -0,0 +1,566 @@
<project name="propel" default="main" basedir=".">
<!--
Note - You should not have to edit this file.
Instead, if calling build-propel.xml directly, edit the build.properties
that is in the same directory. If calling build-propel.xml via another
build file, you can also use the build.properties in the same directory,
or set the property propel.contextProperties to the file
to use in place of build.properties (e.g. project.properties).
-->
<property name="build.properties" value="build.properties"/>
<property name="propel.contextProperties" value="./${build.properties}"/>
<property name="propel.home" value="."/>
<available file="${propel.home}/build.properties" property="globalBuildPopertiesExists"/>
<if>
<and>
<isset property="globalBuildPopertiesExists"/>
</and>
<then>
<property file="${propel.home}/build.properties"/>
</then>
</if>
<!--
The default.properties file will map old properties to the new ones along
with setting the corret defaults.
-->
<property file="${propel.home}/default.properties"/>
<!--
Do forward declarations of all of our tasks to
centralize them and clean up the targets.
-->
<path id="propelclasses">
<pathelement dir="${propel.home}/classes/"/>
</path>
<taskdef
name="propel-data-model"
classname="propel.phing.PropelDataModelTask" classpathRef="propelclasses"/>
<taskdef
name="propel-old-om"
classname="propel.phing.PropelOldOMTask" classpathRef="propelclasses"/>
<taskdef
name="propel-om"
classname="propel.phing.PropelOMTask" classpathRef="propelclasses"/>
<taskdef
name="propel-data-dtd"
classname="propel.phing.PropelDataDTDTask" classpathRef="propelclasses"/>
<taskdef
name="propel-data-dump"
classname="propel.phing.PropelDataDumpTask" classpathRef="propelclasses"/>
<taskdef
name="propel-data-sql"
classname="propel.phing.PropelDataSQLTask" classpathRef="propelclasses"/>
<taskdef
name="propel-creole-transform"
classname="propel.phing.PropelCreoleTransformTask" classpathRef="propelclasses"/>
<taskdef
name="propel-sql"
classname="propel.phing.PropelSQLTask" classpathRef="propelclasses"/>
<taskdef
name="propel-old-sql"
classname="propel.phing.PropelOldSQLTask" classpathRef="propelclasses"/>
<taskdef
name="propel-sql-exec"
classname="propel.phing.PropelSQLExec" classpathRef="propelclasses"/>
<taskdef
name="propel-graphviz"
classname="propel.phing.PropelGraphvizTask" classpathRef="propelclasses"/>
<!-- ================================================================ -->
<!-- M A I N T A R G E T -->
<!-- ================================================================ -->
<!-- This default target will run all the targets that generate -->
<!-- source. You will probably only run this target once then -->
<!-- call individual targets as necessary to update your sources -->
<!-- when you change your XML schema. -->
<!-- ================================================================ -->
<target
name="main"
description="==> generates sql + om classes">
<phingcall target="sql"/>
<phingcall target="om"/>
<phingcall target="convert-props"/>
</target>
<target
name="old-build"
description="==> generates sql + [new] om classes">
<phingcall target="sql"/>
<phingcall target="old-om"/>
<phingcall target="convert-props"/>
</target>
<!-- ================================================================ -->
<!-- C H E C K R U N O N L Y O N S C H E M A C H A N G E -->
<!-- ================================================================ -->
<!-- Maps the propel.runOnlyOnSchemaChange to -->
<!-- propel.internal.runOnlyOnSchemaChange -->
<!-- ================================================================ -->
<target name="check-run-only-on-schema-change">
<condition property="propel.internal.runOnlyOnSchemaChange">
<equals arg1="${propel.runOnlyOnSchemaChange}" arg2="true"/>
</condition>
</target>
<!-- ================================================================ -->
<!-- G E N E R A T E P R O J E C T S Q L -->
<!-- ================================================================ -->
<!-- Generate the SQL for your project, These are in addition -->
<!-- to the base Turbine tables! The tables you require for your -->
<!-- project should be specified in project-schema.xml. -->
<!-- ================================================================ -->
<target
name="sql-check"
depends="check-run-only-on-schema-change"
if="propel.internal.runOnlyOnSchemaChange">
<uptodate
property="propel.internal.sql.uptodate"
targetfile="${propel.sql.dir}/${propel.schema.default.basename}.sql">
<srcfiles dir="${propel.schema.dir}" includes="**/${propel.schema.default.basename}.xml" />
</uptodate>
</target>
<!-- temporary target to check whether postgres is being used with identifier quoting ON.
If so, a warning is issued, since identifier quoting is only paritally implemented & this point. -->
<target name="pgsql-quoting-check">
<if>
<and>
<equals arg1="${propel.database}" arg2="pgsql"/>
<equals arg1="${propel.disableIdentifierQuoting}" arg2=""/>
</and>
<then>
<warn>ATTENTION: It appears you are using PostgreSQL and you have identifier-quoting turned on.</warn>
<warn>It is suggested that you disable identifier quoting when using PostgreSQL -- especially if you</warn>
<warn>have case-sensitive columns in your database.</warn>
<warn></warn>
<warn>To disable identifier quoting, add the following property to your build.properties (or specify</warn>
<warn>it using -D on commandline):</warn>
<warn></warn>
<warn>propel.disableIdentifierQuoting=true</warn>
<warn></warn>
<warn>You can ignore this warning if you understand the issues related to case-sensitivity and Propel's</warn>
<warn>DDL-only implementation of identifier quoting.</warn>
</then>
</if>
</target>
<target
name="sql"
depends="sql-check,pgsql-quoting-check"
unless="propel.internal.sql.uptodate"
description="==> generates the SQL for your project">
<echo message="+------------------------------------------+"/>
<echo message="| |"/>
<echo message="| Generating SQL for YOUR Propel project! |"/>
<echo message="| |"/>
<echo message="+------------------------------------------+"/>
<phingcall target="sql-template"/>
</target>
<target name="sql-template">
<propel-sql
validate="${propel.schema.validate}"
xsd="${propel.schema.xsd.file}"
xsl="${propel.schema.xsl.file}"
outputDirectory="${propel.sql.dir}"
sqldbmap="${propel.sql.dir}/sqldb.map"
targetDatabase="${propel.database}"
templatePath="${propel.templatePath}"
packageObjectModel="${propel.packageObjectModel}"
>
<mapper type="glob" from="${propel.sql.mapper.from}" to="${propel.sql.mapper.to}"/>
<schemafileset dir="${propel.schema.dir}"
includes="${propel.schema.sql.includes}"
excludes="${propel.schema.sql.excludes}"
/>
</propel-sql>
</target>
<target
name="old-sql"
depends="sql-check"
unless="propel.internal.sql.uptodate"
description="==> generates the SQL for your project">
<echo message="+------------------------------------------+"/>
<echo message="| |"/>
<echo message="| Generating SQL for YOUR Propel project! |"/>
<echo message="| (using deprecated legacy SQL template) |"/>
<echo message="| |"/>
<echo message="+------------------------------------------+"/>
<phingcall target="old-sql-template"/>
</target>
<target name="old-sql-template">
<propel-old-sql
validate="${propel.schema.validate}"
xsd="${propel.schema.xsd.file}"
xsl="${propel.schema.xsl.file}"
outputDirectory="${propel.sql.dir}"
sqldbmap="${propel.sql.dir}/sqldb.map"
targetDatabase="${propel.database}"
templatePath="${propel.templatePath}"
packageObjectModel="${propel.packageObjectModel}"
>
<mapper type="glob" from="${propel.sql.mapper.from}" to="${propel.sql.mapper.to}"/>
<schemafileset dir="${propel.schema.dir}"
includes="${propel.schema.sql.includes}"
excludes="${propel.schema.sql.excludes}"
/>
</propel-old-sql>
</target>
<!-- ================================================================ -->
<!-- C R E A T E T A R G E T D A T A B A S E -->
<!-- ================================================================ -->
<!-- Create the target database by executing a generated script -->
<!-- that is capable of performing the task. -->
<!-- ================================================================ -->
<target name="create-db-check">
<condition property="propel.internal.manualCreation">
<equals arg1="${propel.database.manualCreation}" arg2="true"/>
</condition>
</target>
<target
name="create-db"
unless="propel.internal.manualCreation"
depends="create-db-check"
description="==> generates the target database">
<propel-data-model
validate="${propel.schema.validate}"
xsd="${propel.schema.xsd.file}"
xsl="${propel.schema.xsl.file}"
controlTemplate="${propel.template.sqlDbInit}"
outputDirectory="${propel.sql.dir}"
outputFile="create-db.sql"
targetDatabase="${propel.database}"
dbEncoding="${propel.database.encoding}"
templatePath="${propel.templatePath}"
packageObjectModel="${propel.packageObjectModel}"
>
<schemafileset dir="${propel.schema.dir}"
includes="${propel.schema.create-db.includes}"
excludes="${propel.schema.create-db.excludes}"
/>
</propel-data-model>
<echo message="Executing the create-db.sql script ..."/>
<sql
autocommit="true"
driver="${propel.database.driver}"
onerror="continue"
src="${propel.sql.dir}/create-db.sql"
url="${propel.database.createUrl}"
/>
</target>
<!-- ================================================================ -->
<!-- I N S E R T S I N G L E S Q L F I L E S -->
<!-- ================================================================ -->
<target
name="insert-sql"
description="==> inserts the generated sql ">
<propel-sql-exec
autocommit="true"
driver="${propel.database.driver}"
onerror="continue"
sqldbmap="${propel.sql.dir}/sqldb.map"
srcDir="${propel.sql.dir}"
url="${propel.database.buildUrl}"
/>
</target>
<!-- ================================================================ -->
<!-- C R E O L E TO X M L -->
<!-- ================================================================ -->
<target
name="creole"
description="==> generate xml schema from Creole metadata">
<echo message="+-----------------------------------------------+"/>
<echo message="| |"/>
<echo message="| Generating XML from Creole connection ! |"/>
<echo message="| |"/>
<echo message="+-----------------------------------------------+"/>
<propel-creole-transform
dbDriver="${propel.database.driver}"
dbSchema="${propel.database.schema}"
dbEncoding="${propel.database.encoding}"
dbUrl="${propel.database.url}"
outputFile="${propel.schema.dir}/${propel.default.schema.basename}.xml"
samePhpName="${propel.samePhpName}"
addVendorInfo="${propel.addVendorInfo}"
addValidators="${propel.addValidators}"
/>
</target>
<!-- ================================================================ -->
<!-- Generate SQL from XML data file -->
<!-- ================================================================ -->
<target
name="datasql"
description="==> generates sql from data xml">
<echo message="+-----------------------------------------------+"/>
<echo message="| |"/>
<echo message="| Generating SQL from data XML ! |"/>
<echo message="| |"/>
<echo message="+-----------------------------------------------+"/>
<propel-data-sql
validate="${propel.schema.validate}"
xsd="${propel.schema.xsd.file}"
xsl="${propel.schema.xsl.file}"
outputDirectory="${propel.sql.dir}"
sqldbmap="${propel.sql.dir}/sqldb.map"
dbEncoding="${propel.database.encoding}"
targetDatabase="${propel.database}"
templatePath="${propel.templatePath}"
datadbmap="${propel.schema.dir}/datadb.map"
srcDir="${propel.schema.dir}"
>
<mapper type="glob" from="${propel.datasql.mapper.from}" to="${propel.datasql.mapper.to}"/>
<schemafileset dir="${propel.schema.dir}"
includes="${propel.schema.datadtd.includes}"
excludes="${propel.schema.datadtd.excludes}"
/>
</propel-data-sql>
</target>
<!-- ================================================================ -->
<!-- Dump data from database into xml file -->
<!-- ================================================================ -->
<target
name="datadump"
description="==> dump data from database into xml file">
<echo message="+-----------------------------------------------+"/>
<echo message="| |"/>
<echo message="| Dumping the data from database into XML |"/>
<echo message="| |"/>
<echo message="+-----------------------------------------------+"/>
<propel-data-dump
validate="${propel.schema.validate}"
xsd="${propel.schema.xsd.file}"
xsl="${propel.schema.xsl.file}"
targetDatabase="${propel.database}"
datadbmap="${propel.schema.dir}/datadb.map"
databaseDriver="${propel.database.driver}"
dbEncoding="${propel.database.encoding}"
databaseUrl="${propel.database.url}"
outputDirectory="${propel.schema.dir}"
templatePath="${propel.templatePath}">
<mapper type="glob" from="${propel.datadump.mapper.from}" to="${propel.datadump.mapper.to}"/>
<schemafileset dir="${propel.schema.dir}"
includes="${propel.schema.datadtd.includes}"
excludes="${propel.schema.datadtd.excludes}"
/>
</propel-data-dump>
</target>
<!-- ================================================================ -->
<!-- G E N E R A T E P R O J E C T D A T A D T D -->
<!-- ================================================================ -->
<!-- Generate the DATA DTD for your project -->
<!-- ================================================================ -->
<target
name="datadtd"
description="==> generates the DATA DTD for your project">
<echo message="+-----------------------------------------------+"/>
<echo message="| |"/>
<echo message="| Generating Data DTD for YOUR Propel project! |"/>
<echo message="| |"/>
<echo message="+-----------------------------------------------+"/>
<propel-data-dtd
validate="${propel.schema.validate}"
xsd="${propel.schema.xsd.file}"
xsl="${propel.schema.xsl.file}"
targetDatabase="${propel.database}"
outputDirectory="${propel.output.dir}"
templatePath="${propel.templatePath}">
<!-- TODO: add properties for the mapper type, from, and to -->
<mapper type="glob" from="${propel.datadtd.mapper.from}" to="${propel.datadtd.mapper.to}"/>
<schemafileset dir="${propel.schema.dir}"
includes="${propel.schema.datadtd.includes}"
excludes="${propel.schema.datadtd.excludes}"
/>
</propel-data-dtd>
</target>
<!-- ================================================================ -->
<!-- G E N E R A T E P R O J E C T P E E R B A S E D O M -->
<!-- ================================================================ -->
<!-- Generate the Peer-based object model for your project. -->
<!-- These are in addition to the base Propel OM! -->
<!-- ================================================================ -->
<target
name="om-check"
depends="check-run-only-on-schema-change"
if="propel.internal.runOnlyOnSchemaChange">
<uptodate
property="propel.internal.om.uptodate"
targetfile="${propel.php.dir}/report.${propel.project}.om.generation">
<srcfiles dir="${propel.schema.dir}" includes="**/${propel.schema.om.includes}.xml" />
</uptodate>
</target>
<target
name="om"
depends="om-check"
unless="propel.internal.om.uptodate"
description="==> generates the Peer-based object model for your project">
<echo message="+------------------------------------------+"/>
<echo message="| |"/>
<echo message="| Generating Peer-based Object Model for |"/>
<echo message="| YOUR Propel project! (NEW OM BUILDERS)! |"/>
<echo message="| |"/>
<echo message="+------------------------------------------+"/>
<phingcall target="om-template"/>
<!--<phingcall target="om-tar"/>-->
</target>
<target name="om-template">
<propel-om
validate="${propel.schema.validate}"
xsd="${propel.schema.xsd.file}"
xsl="${propel.schema.xsl.file}"
outputDirectory="${propel.php.dir}"
targetDatabase="${propel.database}"
targetPackage="${propel.targetPackage}"
templatePath="${propel.templatePath}"
targetPlatform="${propel.targetPlatform}"
packageObjectModel="${propel.packageObjectModel}"
>
<schemafileset dir="${propel.schema.dir}"
includes="${propel.schema.om.includes}"
excludes="${propel.schema.om.excludes}"
/>
</propel-om>
</target>
<!-- the new OM tasks -->
<target
name="old-om"
depends="om-check"
unless="propel.internal.om.uptodate"
description="==> generates the OLD Peer-based object model for your project">
<echo message="+------------------------------------------+"/>
<echo message="| |"/>
<echo message="| Generating Peer-based Object Model for |"/>
<echo message="| YOUR Propel project (OLD OM TEMPLATES). |"/>
<echo message="| |"/>
<echo message="+------------------------------------------+"/>
<phingcall target="old-om-template"/>
<!--<phingcall target="om-tar"/>-->
</target>
<target name="old-om-template">
<propel-old-om
validate="${propel.schema.validate}"
xsd="${propel.schema.xsd.file}"
xsl="${propel.schema.xsl.file}"
outputDirectory="${propel.php.dir}"
targetDatabase="${propel.database}"
targetPackage="${propel.targetPackage}"
templatePath="${propel.templatePath}"
targetPlatform="${propel.targetPlatform}">
<schemafileset dir="${propel.schema.dir}"
includes="${propel.schema.om.includes}"
excludes="${propel.schema.om.excludes}"
/>
</propel-old-om>
</target>
<!-- ================================================================== -->
<!-- P R O P S T O P H P A R R A Y -->
<!-- ================================================================== -->
<target
name="convert-props"
description="==> converts properties file to PHP array">
<echo message="+------------------------------------------+"/>
<echo message="| |"/>
<echo message="| Converting project properties file to an |"/>
<echo message="| array dump for run-time performance. |"/>
<echo message="| |"/>
<echo message="+------------------------------------------+"/>
<capsule
templatePath="${propel.templatePath}"
controlTemplate="${propel.template.conf}"
outputDirectory="${propel.phpconf.dir}"
outputFile="${propel.runtime.phpconf.file}">
<assign name="propertiesFile" value="${propel.conf.dir}/${propel.runtime.conf.file}"/>
</capsule>
</target>
<target
name="graphviz"
depends="sql-check"
description="==> generates Graphviz file for your project">
<echo message="+------------------------------------------+"/>
<echo message="| |"/>
<echo message="| Generating Graphiz for YOUR Propel |"/>
<echo message="| project! |"/>
<echo message="| |"/>
<echo message="+------------------------------------------+"/>
<propel-graphviz
outputDirectory="${propel.graph.dir}"
targetDatabase="${propel.database}"
sqldbmap="${propel.sql.dir}/sqldb.map"
packageObjectModel="${propel.packageObjectModel}">
<mapper type="glob" from="${propel.sql.mapper.from}" to="${propel.sql.mapper.to}"/>
<schemafileset dir="${propel.schema.dir}"
includes="${propel.schema.sql.includes}"
excludes="${propel.schema.sql.excludes}"
/>
</propel-graphviz>
</target>
</project>

View File

@ -0,0 +1,190 @@
# -------------------------------------------------------------------
#
# P R O P E L C O N F I G U R A T I O N F I L E
#
# -------------------------------------------------------------------
# This file contains some example properties. Ideally properties
# should be specified in the project-specific build.properties file;
# however, this file can be used to specify non-default properties
# that you would like to use accross all of your Propel projects.
# -------------------------------------------------------------------
#
propel.home = .
# -------------------------------------------------------------------
#
# P R O J E C T
#
# -------------------------------------------------------------------
# This is the name of your Propel project. The name of your Propel
# project is used (by default) to determine where the generator will
# find needed configuration files and will place resuilting build
# files. E.g. if your project is named 'killerapp', Propel will
# look here for schema.xml and runtime-conf.xml files:
#
# projects/killerapp/
#
# -------------------------------------------------------------------
# You can set this here, but it's preferrable to set this in a
# project-specific build.properties file.
#
# propel.project = bookstore
# -------------------------------------------------------------------
#
# T A R G E T D A T A B A S E
#
# -------------------------------------------------------------------
# This is the target database, only considered when generating
# the SQL for your Propel project. Your possible choices are:
#
# mssql, mysql, oracle, pgsql, sqlite
# -------------------------------------------------------------------
# You can set this here, but it's preferrable to set this in a
# project-specific build.properties file.
#
# propel.database = mysql
# -------------------------------------------------------------------
#
# O B J E C T M O D E L I N F O R M A T I O N
#
# -------------------------------------------------------------------
# These settings will allow you to customize the way your
# Peer-based object model is created.
# -------------------------------------------------------------------
# addGenericAccessors
# If true, Propel adds methods to get database fields by name/position.
#
# addGenericMutators
# If true, Propel adds methods to set database fields by name/position.
#
# addSaveMethod
# If true, Propel adds tracking code to determine how to save objects.
#
# addTimeStamp
# If true, Propel true puts time stamps in phpdoc of generated om files.
#
# basePrefix
# A string to pre-pend to the file names of base data and peer objects.
#
# complexObjectModel
# If true, Propel generates data objects with collection support and
# methods to easily retreive foreign key relationships.
#
# targetPackage
# Sets the PHP "package" the om files will generated to, e.g.
# "com.company.project.om".
#
# targetPlatform
# Sets whether Propel is building classes for php5 (default)
# or php4 (experimental).
#
# packageObjectModel
# Sets whether Propel is packaging ObjectModel fro several
# [package].schema.xml files. The <database package="packageName">
# attribute has to be set then. (warning: this is experimental!)
#
# -------------------------------------------------------------------
# classes will be put in (and included from) this directory
# e.g. if package is "bookstore" then om will expect include('bookstore/Book.php'); to work.
# use dot-path notation -- e.g. my.bookstore -> my/bookstore.
#
propel.targetPackage = ${propel.project}
propel.addGenericAccessors = false
propel.addGenericMutators = false
propel.addSaveMethod = true
propel.addTimeStamp = true
propel.basePrefix = Base
propel.complexObjectModel = true
propel.targetPlatform = php5
propel.packageObjectModel = false
# -------------------------------------------------------------------
#
# D B C O N N E C T I O N S E T T I N G S
#
# -------------------------------------------------------------------
# Creole connection settings. These connection settings are used by
# build tagets that perform database operations (e.g. 'insert-sql',
# 'creole').
#
# You can set them here, but it's preferrable to set these properties
# in a project-specific build.properties file.
#
# If you want to use a custom driver, specify it below, otherwise
# leave it blank or comment it out to use Creole stock driver.
#
# propel.database.driver = creole.drivers.sqlite.SQLiteConnection
# Note that if you do not wish to specify the database (e.g. if you
# are using multiple databses) you can use the @DB@ token which
# will be replaced with a database at runtime.
#
# propel.database.url = mysql://root@localhost/bookstore
# Use the URL below to specify a DSN to used to create the database.
# Note that this URL should not contain the database name, as you will
# get an error if the database does not exist.
# (This does not apply to SQLite since the databse is automatically created
# when the connection is made -- if it does not already exist.)
#
# propel.database.createUrl = mysql://root@localhost/
# -------------------------------------------------------------------
#
# C R E O L E TO X M L
#
# -------------------------------------------------------------------
# These settings only applies to the 'creole' target.
# -------------------------------------------------------------------
#
# samePhpName
# If true, the Creole task will set the phpName attribute for the
# tables and columns to be the same as SQL name.
#
# addVendorInfo
# If true, the Creole task will add vendor specific information
# to the database schema
#
# addValidators
# Bitfield like option to turn on/off addition of Validator and
# Rule tags to the schema. Uses a boolean syntax like in php.ini.
# Allowed tokens are:
# none add no validators)
# all add all validators)
# maxlength add maxlengths for string type columns)
# maxvalue add maxvalue for numeric columns)
# type add notmatch validators for numeric columns)
# required add required validators for required columns)
# unique add unique validators for unique indexes)
# Allowed operators are:
# & bitwise AND
# | bitwise OR
# ~ bitwise NOT
#
# -------------------------------------------------------------------
# propel.samePhpName = false
# propel.addVendorInfo=true
# propel.addValidators=none
# -------------------------------------------------------------------
#
# D A T A B A S E B U I L D C O N F I G
#
# -------------------------------------------------------------------
# Some databases provide some configuration options that can be set
# in this script.
#
# === MySQL
# propel.mysql.tableType
# Use this property to set the table type of generated tables (e.g. InnoDB, MyISAM).

177
lib/symfony/vendor/propel-generator/build.xml vendored Executable file
View File

@ -0,0 +1,177 @@
<!--
Use this file to faciliate easy per-project building.
Simply create a build.properties file in your project directory,
for example ./projects/bookstore/build.properties, that contains
any needed (i.e. to override) values for that project.
Call this build script and specify the name of the project and
(optionally) the name of the target you wish to execute (default is
'main' target) of build-propel.xml.
Normal use:
$> phing -Dproject=bookstore
Specific target:
$> phing -Dproject=bookstore -Dtarget=insert-sql
-->
<project name="propel-project-builder" default="main" basedir=".">
<!-- in case ${project.dir} was specified on command line, we set the project.dir
property here. If it wasn't set, then this will be bogus, but it will
be overridden by the "set-project-dir" target. -->
<property name="propel.project.dir" value="${project.dir}"/>
<resolvepath propertyName="propel.project.dir" file="${propel.project.dir}" dir="${application.startdir}"/>
<!-- set a default target if none provided -->
<property name="target" value="main"/>
<!-- Set a default name for the build.properties file.
This allows for overriding the name of the build.properties file; however,
Propel still expects to find the file in the ${propel.project.dir}.
-->
<property name="build.properties" value="build.properties"/>
<target name="check-buildprops-exists">
<available file="${propel.project.dir}/${build.properties}" property="projBuildPopertiesExists"/>
</target>
<target name="check-buildprops" unless="projBuildPopertiesExists" depends="check-buildprops-exists">
<echo message="====================================================="/>
<echo message="Could not open ${build.properties} file:"/>
<echo message=" ${propel.project.dir}/${build.properties}"/>
<echo message=" "/>
<echo message="Make sure that '${propel.project.dir}' is a valid path"/>
<echo message="and that it contains a ${build.properties} file."/>
<echo message="====================================================="/>
<fail message="Missing configuration file (see description above)."/>
</target>
<target name="check-project-or-dir-set">
<condition property="projectOrDirSet">
<or>
<isset property="project"/>
<isset property="project.dir"/>
</or>
</condition>
</target>
<target name="check-buildprops-for-propel-gen" if="using.propel-gen" unless="projBuildPopertiesExists" depends="check-buildprops-exists">
<echo message="=========================================================="/>
<echo message="Could not open ${build.properties} file:"/>
<echo message=" ${propel.project.dir}/${build.properties}"/>
<echo message=" "/>
<echo message="Project directory not specified or invalid. You must "/>
<echo message="specify the path to your project directory and your "/>
<echo message="project directory must contain your ${build.properties} "/>
<echo message="and schema.xml files. "/>
<echo message=" "/>
<echo message="Usage: "/>
<echo message=" "/>
<echo message="$&gt; propel-gen /path/to/projectdir [target]"/>
<echo message=" "/>
<echo message="=========================================================="/>
<fail message="No project directory specified."/>
</target>
<target name="check-project-set" unless="projectOrDirSet" depends="check-project-or-dir-set">
<echo message="====================================================="/>
<echo message="Project not specified. You must enter a project name. "/>
<echo message="In the future you can enter it on the command line: "/>
<echo message=" "/>
<echo message="-Dproject=bookstore"/>
<echo message=" "/>
<echo message="This will attempt to find your project directory in"/>
<echo message="the default directory (./projects/bookstore)."/>
<echo message=" "/>
<echo message="You can also avoid this message and specicfy a custom "/>
<echo message="directory, using the project.dir property:"/>
<echo message=" "/>
<echo message="-Dproject.dir=/path/to/bookstore"/>
<echo message="====================================================="/>
<input propertyname="project" promptChar=":">Project name</input>
<property name="propel.project" value="${project}" override="true"/>
</target>
<target name="set-project-dir" unless="project.dir" depends="check-project-set">
<echo>No project.dir was specified, using default path: ./projects/${project}</echo>
<property name="propel.project.dir" value="./projects/${project}" override="true"/>
</target>
<target name="configure" depends="set-project-dir,check-buildprops-for-propel-gen,check-buildprops">
<echo msg="Loading project-specific props from ${propel.project.dir}/${build.properties}"/>
<property file="${propel.project.dir}/${build.properties}"/>
</target>
<target name="main" depends="configure" description="The main target. Includes project-specific build.properties and calls the build-propel.xml script">
<phing phingfile="./build-propel.xml" target="${target}"/>
</target>
<!--
Convenience mappings to build-propel.xml main targets
This makes it possible to use this buildfile w/o needing to specify
target as a property, e.g.:
$> phing -Dproject=bookstore insert-sql
The main reason for this is just consistency w/ old build-propel.xml file
(primarily for documentation & user confusion avoidance reasons). There are relatively
few & infrequently changing main targets of build-propel.xml, so it's a non-
issue as far as maintenance is concerned.
-->
<target name="convert-props" depends="configure">
<phing phingfile="build-propel.xml" target="convert-props"/>
</target>
<target name="create-db" depends="configure">
<phing phingfile="build-propel.xml" target="create-db"/>
</target>
<target name="creole" depends="configure">
<phing phingfile="build-propel.xml" target="creole"/>
</target>
<target name="datadtd" depends="configure">
<phing phingfile="build-propel.xml" target="datadtd"/>
</target>
<target name="datadump" depends="configure">
<phing phingfile="build-propel.xml" target="datadump"/>
</target>
<target name="datasql" depends="configure">
<phing phingfile="build-propel.xml" target="datasql"/>
</target>
<target name="insert-sql" depends="configure">
<phing phingfile="build-propel.xml" target="insert-sql"/>
</target>
<target name="om" depends="configure">
<phing phingfile="build-propel.xml" target="om"/>
</target>
<target name="new-om" depends="configure">
<phing phingfile="build-propel.xml" target="new-om"/>
</target>
<target name="sql" depends="configure">
<phing phingfile="build-propel.xml" target="sql"/>
</target>
<target name="old-sql" depends="configure">
<phing phingfile="build-propel.xml" target="old-sql"/>
</target>
<target name="graphviz" depends="configure">
<phing phingfile="build-propel.xml" target="graphviz"/>
</target>
</project>

View File

@ -0,0 +1,124 @@
<!--
Use this file to faciliate easy per-project building.
Simply create a build.properties file in this directory,
that contains any needed (i.e. to override) values for this project.
Call this build script and specify the name of the project and
(optionally) the name of the target you wish to execute (default is
'main' target) of build-propel.xml.
Normal use:
$> phing
Specific target:
$> phing -Dtarget=insert-sql
-->
<project name="propel-project-builder" default="main" basedir=".">
<!-- set to this dir -->
<property name="project.dir" value="."/>
<!-- set a default target if none provided -->
<property name="target" value="main"/>
<target name="buildpropescheck">
<available file="./build.properties" property="projBuildPopertiesExists"/>
</target>
<target name="init">
<echo msg="Loading project-specific props from ./build.properties"/>
<property file="./build.properties"/>
</target>
<target name="checkproject" unless="propel.project">
<fail msg="Build failed. Please make sure that propel.project is set to your project-name in local build.properties"/>
</target>
<target name="checkhome" unless="propel.home">
<fail msg="Build failed. Please make sure that propel.home is set to the propel-generator-dir in local build.properties"/>
</target>
<target name="checkschemadir" unless="propel.schema.dir">
<fail msg="Build failed. Please make sure that propel.schema.dir is set to '.' in local build.properties"/>
</target>
<target name="checkconfdir" unless="propel.conf.dir">
<fail msg="Build failed. Please make sure that propel.conf.dir is set to '.' in local build.properties"/>
</target>
<target name="checkoutputdir" unless="propel.output.dir">
<fail msg="Build failed. Please make sure that propel.output.dir is set to a directory of your choice (e.g. './build/') local build.properties"/>
</target>
<target name="configure" depends="init,checkproject,checkhome,checkschemadir,checkconfdir,checkoutputdir">
<property name="project" value="{$propel.project}"/>
</target>
<target name="main" depends="configure"
description="The main target. Includes project-specific build.properties and calls the build-propel.xml script">
<phing phingfile="${propel.home}/build-propel.xml" target="${target}"/>
</target>
<!--
Convenience mappings to build-propel.xml main targets
This makes it possible to use this buildfile w/o needing to specify
target as a property, e.g.:
$> phing -Dproject=bookstore insert-sql
The main reason for this is just consistency w/ old build-propel.xml file
(primarily for documentation & user confusion avoidance reasons). There are relatively
few & infrequently changing main targets of build-propel.xml, so it's a non-
issue as far as maintenance is concerned.
-->
<target name="convert-props" depends="configure">
<phing phingfile="${propel.home}/build-propel.xml" target="convert-props"/>
</target>
<target name="create-db" depends="configure">
<phing phingfile="${propel.home}/build-propel.xml" target="create-db"/>
</target>
<target name="creole" depends="configure">
<phing phingfile="${propel.home}/build-propel.xml" target="creole"/>
</target>
<target name="datadtd" depends="configure">
<phing phingfile="${propel.home}/build-propel.xml" target="datadtd"/>
</target>
<target name="datadump" depends="configure">
<phing phingfile="${propel.home}/build-propel.xml" target="datadump"/>
</target>
<target name="datasql" depends="configure">
<phing phingfile="${propel.home}/build-propel.xml" target="datasql"/>
</target>
<target name="insert-sql" depends="configure">
<phing phingfile="${propel.home}/build-propel.xml" target="insert-sql"/>
</target>
<target name="om" depends="configure">
<phing phingfile="${propel.home}/build-propel.xml" target="om"/>
</target>
<target name="new-om" depends="configure">
<phing phingfile="${propel.home}/build-propel.xml" target="new-om"/>
</target>
<target name="sql" depends="configure">
<phing phingfile="${propel.home}/build-propel.xml" target="sql"/>
</target>
<target name="old-sql" depends="configure">
<phing phingfile="${propel.home}/build-propel.xml" target="old-sql"/>
</target>
<target name="graphviz" depends="configure">
<phing phingfile="${propel.home}/build-propel.xml" target="graphviz"/>
</target>
</project>

View File

@ -0,0 +1,33 @@
<?php
/*
* $Id: EngineException.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'phing/BuildException.php';
/**
* The base class of all exceptions thrown by the engine.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Daniel Rall <dlr@collab.net> (Torque)
* @author Jason van Zyl <jvz@apache.org> (Torque)
* @version $Revision: 536 $
* @package propel.engine
*/
class EngineException extends BuildException {}

View File

@ -0,0 +1,221 @@
<?php
/*
* $Id: DataModelBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
/**
* This is the base class for any builder class that is using the data model.
*
* This could be extended by classes that build SQL DDL, PHP classes, configuration
* files, input forms, etc.
*
* This class has a static method to return the correct builder subclass identified by
* a given key. Note that in order for this factory method to work, the properties have to have
* been loaded first. Usage should look something like this (from within a AbstractProelDataModelTask subclass):
*
* <code>
* DataModelBuilder::setBuildProperties($this->getPropelProperties());
* $builder = DataModelBuilder::builderFactory($table, 'peer');
* // $builder (by default) instanceof PHP5ComplexPeerBuilder
* </code>
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder
*/
abstract class DataModelBuilder {
// --------------------------------------------------------------
// Static properties & methods
// --------------------------------------------------------------
/**
* Build properties (after they've been transformed from "propel.some.name" => "someName").
* @var array string[]
*/
private static $buildProperties = array();
/**
* Sets the [name transformed] build properties to use.
* @param array Property values keyed by [transformed] prop names.
*/
public static function setBuildProperties($props)
{
self::$buildProperties = $props;
}
/**
* Get a specific [name transformed] build property.
* @param string $name
* @return string
*/
public static function getBuildProperty($name)
{
return isset(self::$buildProperties[$name]) ? self::$buildProperties[$name] : null;
}
/**
* Imports and returns the classname of the builder class for specified 'type'.
* @param $type The "key" for class to load.
* @return string The unqualified classname.
*/
public static function getBuilderClass($type)
{
if (empty(self::$buildProperties)) {
throw new BuildException("Cannot determine builder class when no build properties have been loaded (hint: Did you call DataModelBuilder::setBuildProperties(\$props) first?)");
}
$propname = 'builder' . ucfirst(strtolower($type)) . 'Class';
$classpath = self::getBuildProperty($propname);
if (empty($classpath)) {
throw new BuildException("Unable to find class path for '$propname' property.");
}
// This is a slight hack to workaround camel case inconsistencies for the DDL classes.
// Basically, we want to turn ?.?.?.sqliteDDLBuilder into ?.?.?.SqliteDDLBuilder
$lastdotpos = strrpos($classpath, '.');
if ($lastdotpos) $classpath{$lastdotpos+1} = strtoupper($classpath{$lastdotpos+1});
else ucfirst($classpath);
return Phing::import($classpath);
}
/**
* Factory method to load a new builder instance based on specified type.
* @param Table $table
* @param $type The "key" for class to load.
* @throws BuildException if specified class cannot be found / loaded.
*/
public static function builderFactory(Table $table, $type)
{
$classname = self::getBuilderClass($type);
return new $classname($table);
}
/**
* Utility function to build a path for use in include()/require() statement.
*
* Supports two function signatures:
* (1) getFilePath($dotPathClass);
* (2) getFilePath($dotPathPrefix, $className);
*
* @param string $path dot-path to class or to package prefix.
* @param string $classname class name
* @return string
*/
public static function getFilePath($path, $classname = null, $extension = '.php')
{
$path = strtr(ltrim($path, '.'), '.', '/');
if ($classname !== null) {
if ($path !== "") { $path .= '/'; }
return $path . $classname . $extension;
} else {
return $path . $extension;
}
}
// --------------------------------------------------------------
// Non-static properties & methods inherited by subclasses
// --------------------------------------------------------------
/**
* The current table.
* @var Table
*/
private $table;
/**
* An array of warning messages that can be retrieved for display (e.g. as part of phing build process).
* @var array string[]
*/
private $warnings = array();
/**
* Creates new instance of DataModelBuilder subclass.
* @param Table $table The Table which we are using to build [OM, DDL, etc.].
*/
public function __construct(Table $table)
{
$this->table = $table;
}
/**
* Returns the Platform class for this table (database).
* @return Platform
*/
protected function getPlatform()
{
return $this->getTable()->getDatabase()->getPlatform();
}
/**
* Returns the database for current table.
* @return Database
*/
protected function getDatabase()
{
return $this->getTable()->getDatabase();
}
/**
* Returns the current Table object.
* @return Table
*/
protected function getTable()
{
return $this->table;
}
/**
* Pushes a message onto the stack of warnings.
* @param string $msg The warning message.
*/
protected function warn($msg)
{
$this->warnings[] = $msg;
}
/**
* Gets array of warning messages.
* @return array string[]
*/
public function getWarnings()
{
return $this->warnings;
}
/**
* Wraps call to Platform->quoteIdentifier() with a check to see whether quoting is enabled.
*
* All subclasses should call this quoteIdentifier() method rather than calling the Platform
* method directly. This method is used by both DataSQLBuilder and DDLBuilder, and potentially
* in the OM builders also, which is why it is defined in this class.
*
* @param string $text The text to quote.
* @return string Quoted text.
*/
public function quoteIdentifier($text)
{
if (!self::getBuildProperty('disableIdentifierQuoting')) {
return $this->getPlatform()->quoteIdentifier($text);
}
return $text;
}
}

View File

@ -0,0 +1,107 @@
<?php
/*
* $Id: ClassTools.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
/**
* Tools to support class & package inclusion and referencing.
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 536 $
* @package propel.engine.builder.om
*/
class ClassTools {
/**
* Gets just classname, given a dot-path to class.
* @param string $qualifiedName
* @return string
*/
public static function classname($qualifiedName)
{
$pos = strrpos($qualifiedName, '.');
if ($pos === false) {
return $qualifiedName; // there is no '.' in the qualifed name
} else {
return substr($qualifiedName, $pos + 1); // start just after '.'
}
}
/**
* Gets the path to be used in include()/require() statement.
*
* Supports two function signatures:
* (1) getFilePath($dotPathClass);
* (2) getFilePath($dotPathPrefix, $className);
*
* @param string $path dot-path to class or to package prefix.
* @param string $classname class name
* @return string
*/
public static function getFilePath($path, $classname = null, $extension = '.php')
{
$path = strtr(ltrim($path, '.'), '.', '/');
if ($classname !== null) {
if ($path !== "") { $path .= '/'; }
return $path . $classname . $extension;
} else {
return $path . $extension;
}
}
/**
* Gets the basePeer path if specified for table/db.
* If not, will return 'propel.util.BasePeer'
* @return string
*/
public static function getBasePeer(Table $table) {
$class = $table->getBasePeer();
if ($class === null) {
$class = "propel.util.BasePeer";
}
return $class;
}
/**
* Gets the baseClass path if specified for table/db.
* If not, will return 'propel.om.BaseObject'
* @return string
*/
public static function getBaseClass(Table $table) {
$class = $table->getBaseClass();
if ($class === null) {
$class = "propel.om.BaseObject";
}
return $class;
}
/**
* Gets the interface path if specified for table.
* If not, will return 'propel.om.Persistent'.
* @return string
*/
public static function getInterface(Table $table) {
$interface = $table->getInterface();
if ($interface === null && !$table->isReadOnly()) {
$interface = "propel.om.Persistent";
}
return $interface;
}
}

View File

@ -0,0 +1,409 @@
<?php
/*
* $Id: OMBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/DataModelBuilder.php';
/**
* Baseclass for OM-building classes.
*
* OM-building classes are those that build a PHP (or other) class to service
* a single table. This includes Peer classes, Entity classes, Map classes,
* Node classes, etc.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.om
*/
abstract class OMBuilder extends DataModelBuilder {
/**
* Peer builder class for current table.
* @var DataModelBuilder
*/
private $peerBuilder;
/**
* Stub Peer builder class for current table.
* @var DataModelBuilder
*/
private $stubPeerBuilder;
/**
* Object builder class for current table.
* @var DataModelBuilder
*/
private $objectBuilder;
/**
* Stub Object builder class for current table.
* @var DataModelBuilder
*/
private $stubObjectBuilder;
/**
* MapBuilder builder class for current table.
* @var DataModelBuilder
*/
private $mapBuilderBuilder;
/**
* Stub Interface builder class for current table.
* @var DataModelBuilder
*/
private $interfaceBuilder;
/**
* Stub child object for current table.
* @var DataModelBuilder
*/
private $multiExtendObjectBuilder;
/**
* Node object builder for current table.
* @var DataModelBuilder
*/
private $nodeBuilder;
/**
* Node peer builder for current table.
* @var DataModelBuilder
*/
private $nodePeerBuilder;
/**
* Stub node object builder for current table.
* @var DataModelBuilder
*/
private $stubNodeBuilder;
/**
* Stub node peer builder for current table.
* @var DataModelBuilder
*/
private $stubNodePeerBuilder;
/**
* Returns new or existing Peer builder class for this table.
* @return DataModelBuilder
*/
public function getPeerBuilder()
{
if (!isset($this->peerBuilder)) {
$this->peerBuilder = DataModelBuilder::builderFactory($this->getTable(), 'peer');
}
return $this->peerBuilder;
}
/**
* Returns new or existing stub Peer builder class for this table.
* @return DataModelBuilder
*/
public function getStubPeerBuilder()
{
if (!isset($this->stubPeerBuilder)) {
$this->stubPeerBuilder = DataModelBuilder::builderFactory($this->getTable(), 'peerstub');
}
return $this->stubPeerBuilder;
}
/**
* Returns new or existing Object builder class for this table.
* @return DataModelBuilder
*/
public function getObjectBuilder()
{
if (!isset($this->objectBuilder)) {
$this->objectBuilder = DataModelBuilder::builderFactory($this->getTable(), 'object');
}
return $this->objectBuilder;
}
/**
* Returns new or existing stub Object builder class for this table.
* @return DataModelBuilder
*/
public function getStubObjectBuilder()
{
if (!isset($this->stubObjectBuilder)) {
$this->stubObjectBuilder = DataModelBuilder::builderFactory($this->getTable(), 'objectstub');
}
return $this->stubObjectBuilder;
}
/**
* Returns new or existing MapBuilder builder class for this table.
* @return DataModelBuilder
*/
public function getMapBuilderBuilder()
{
if (!isset($this->mapBuilderBuilder)) {
$this->mapBuilderBuilder = DataModelBuilder::builderFactory($this->getTable(), 'mapbuilder');
}
return $this->mapBuilderBuilder;
}
/**
* Returns new or existing stub Interface builder class for this table.
* @return DataModelBuilder
*/
public function getInterfaceBuilder()
{
if (!isset($this->interfaceBuilder)) {
$this->interfaceBuilder = DataModelBuilder::builderFactory($this->getTable(), 'interface');
}
return $this->interfaceBuilder;
}
/**
* Returns new or existing stub child object builder class for this table.
* @return DataModelBuilder
*/
public function getMultiExtendObjectBuilder()
{
if (!isset($this->multiExtendObjectBuilder)) {
$this->multiExtendObjectBuilder = DataModelBuilder::builderFactory($this->getTable(), 'objectmultiextend');
}
return $this->multiExtendObjectBuilder;
}
/**
* Returns new or existing node Object builder class for this table.
* @return DataModelBuilder
*/
public function getNodeBuilder()
{
if (!isset($this->nodeBuilder)) {
$this->nodeBuilder = DataModelBuilder::builderFactory($this->getTable(), 'node');
}
return $this->nodeBuilder;
}
/**
* Returns new or existing node Peer builder class for this table.
* @return DataModelBuilder
*/
public function getNodePeerBuilder()
{
if (!isset($this->nodePeerBuilder)) {
$this->nodePeerBuilder = DataModelBuilder::builderFactory($this->getTable(), 'nodepeer');
}
return $this->nodePeerBuilder;
}
/**
* Returns new or existing stub node Object builder class for this table.
* @return DataModelBuilder
*/
public function getStubNodeBuilder()
{
if (!isset($this->stubNodeBuilder)) {
$this->stubNodeBuilder = DataModelBuilder::builderFactory($this->getTable(), 'nodestub');
}
return $this->stubNodeBuilder;
}
/**
* Returns new or existing stub node Peer builder class for this table.
* @return DataModelBuilder
*/
public function getStubNodePeerBuilder()
{
if (!isset($this->stubNodePeerBuilder)) {
$this->stubNodePeerBuilder = DataModelBuilder::builderFactory($this->getTable(), 'nodepeerstub');
}
return $this->stubNodePeerBuilder;
}
/**
* Convenience method to return a NEW Peer class builder instance.
* This is used very frequently from the peer and object builders to get
* a peer builder for a RELATED table.
* @param Table $table
* @return PeerBuilder
*/
public static function getNewPeerBuilder(Table $table)
{
return DataModelBuilder::builderFactory($table, 'peer');
}
/**
* Convenience method to return a NEW Object class builder instance.
* This is used very frequently from the peer and object builders to get
* an object builder for a RELATED table.
* @param Table $table
* @return ObjectBuilder
*/
public static function getNewObjectBuilder(Table $table)
{
return DataModelBuilder::builderFactory($table, 'object');
}
/**
* Builds the PHP source for current class and returns it as a string.
*
* This is the main entry point and defines a basic structure that classes should follow.
* In most cases this method will not need to be overridden by subclasses. This method
* does assume that the output language is PHP code, so it will need to be overridden if
* this is not the case.
*
* @return string The resulting PHP sourcecode.
*/
public function build()
{
$script = "<" . "?php\n"; // intentional concatenation
$this->addIncludes($script);
$this->addClassOpen($script);
$this->addClassBody($script);
$this->addClassClose($script);
return $script;
}
/**
* Returns the name of the current class being built.
* @return string
*/
abstract public function getClassname();
/**
* Gets the dot-path representation of current class being built.
* @return string
*/
public function getClasspath()
{
if ($this->getPackage()) {
$path = $this->getPackage() . '.' . $this->getClassname();
} else {
$path = $this->getClassname();
}
return $path;
}
/**
* Gets the full path to the file for the current class.
* @return string
*/
public function getClassFilePath()
{
return parent::getFilePath($this->getPackage(), $this->getClassname());
}
/**
* Gets package name for this table.
* This is overridden by child classes that have different packages.
* @return string
*/
public function getPackage()
{
$pkg = ($this->getTable()->getPackage() ? $this->getTable()->getPackage() : $this->getDatabase()->getPackage());
if (!$pkg) {
$pkg = $this->getBuildProperty('targetPackage');
}
return $pkg;
}
/**
* Returns filesystem path for current package.
* @return string
*/
public function getPackagePath()
{
return strtr($this->getPackage(), '.', '/');
}
/**
* Shortcut method to return the [stub] peer classname for current table.
* This is the classname that is used whenever object or peer classes want
* to invoke methods of the peer classes.
* @return string (e.g. 'MyPeer')
* @see StubPeerBuilder::getClassname()
*/
public function getPeerClassname() {
return $this->getStubPeerBuilder()->getClassname();
}
/**
* Returns the object classname for current table.
* This is the classname that is used whenever object or peer classes want
* to invoke methods of the object classes.
* @return string (e.g. 'My')
* @see StubPeerBuilder::getClassname()
*/
public function getObjectClassname() {
return $this->getStubObjectBuilder()->getClassname();
}
/**
* Get the column constant name (e.g. PeerName::COLUMN_NAME).
*
* @param Column $col The column we need a name for.
* @param string $phpName The PHP Name of the peer class. The 'Peer' is appended automatically.
*
* @return string If $phpName is provided, then will return {$phpName}Peer::COLUMN_NAME; if not, then uses current table COLUMN_NAME.
*/
public function getColumnConstant($col, $phpName = null)
{
if ($col === null) {
$e = new Exception("No col specified.");
print $e;
throw $e;
}
$classname = $this->getPeerClassname($phpName);
// was it overridden in schema.xml ?
if ($col->getPeerName()) {
$const = strtoupper($col->getPeerName());
} else {
$const = strtoupper($col->getName());
}
return $classname.'::'.$const;
}
/**
* Gets just classname, given a dot-path to class.
* @param string $qualifiedName
* @return string
*/
public function classname($qualifiedName)
{
$pos = strrpos($qualifiedName, '.');
if ($pos === false) {
return $qualifiedName; // there is no '.' in the qualifed name
} else {
return substr($qualifiedName, $pos + 1); // start just after '.'
}
}
/**
* Gets the basePeer path if specified for table/db.
* If not, will return 'propel.util.BasePeer'
* @return string
*/
public function getBasePeer(Table $table) {
$class = $table->getBasePeer();
if ($class === null) {
$class = "propel.util.BasePeer";
}
return $class;
}
}

View File

@ -0,0 +1,148 @@
<?php
/*
* $Id: ObjectBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/OMBuilder.php';
/**
* Base class for Peer-building classes.
*
* This class is designed so that it can be extended by a PHP4PeerBuilder in addition
* to the "standard" PHP5PeerBuilder and PHP5ComplexOMPeerBuilder. Hence, this class
* should not have any actual template code in it -- simply basic logic & utility
* methods.
*
* @author Hans Lellelid <hans@xmpl.org>
*/
abstract class ObjectBuilder extends OMBuilder {
/**
* Constructs a new PeerBuilder subclass.
*/
public function __construct(Table $table) {
parent::__construct($table);
}
/**
* This method adds the contents of the generated class to the script.
*
* This method is abstract and should be overridden by the subclasses.
*
* Hint: Override this method in your subclass if you want to reorganize or
* drastically change the contents of the generated peer class.
*
* @param string &$script The script will be modified in this method.
*/
abstract protected function addClassBody(&$script);
/**
* Adds the getter methods for the column values.
* This is here because it is probably generic enough to apply to templates being generated
* in different langauges (e.g. PHP4 and PHP5).
* @param string &$script The script will be modified in this method.
*/
protected function addColumnAccessorMethods(&$script)
{
$table = $this->getTable();
foreach ($table->getColumns() as $col) {
if ($col->getType() === PropelTypes::DATE || $col->getType() === PropelTypes::TIME || $col->getType() === PropelTypes::TIMESTAMP) {
$this->addTemporalAccessor($script, $col);
} else {
$this->addGenericAccessor($script, $col);
}
if ($col->isLazyLoad()) {
$this->addLazyLoader($script, $col);
}
}
}
/**
* Adds the mutator (setter) methods for setting column values.
* This is here because it is probably generic enough to apply to templates being generated
* in different langauges (e.g. PHP4 and PHP5).
* @param string &$script The script will be modified in this method.
*/
protected function addColumnMutatorMethods(&$script)
{
foreach ($this->getTable()->getColumns() as $col) {
if ($col->isLob()) {
$this->addLobMutator($script, $col);
} elseif ($col->getType() === PropelTypes::DATE || $col->getType() === PropelTypes::TIME || $col->getType() === PropelTypes::TIMESTAMP) {
$this->addTemporalMutator($script, $col);
} else {
$this->addDefaultMutator($script, $col);
}
}
}
/**
* Gets the baseClass path if specified for table/db.
* If not, will return 'propel.om.BaseObject'
* @return string
*/
protected function getBaseClass() {
$class = $this->getTable()->getBaseClass();
if ($class === null) {
$class = "propel.om.BaseObject";
}
return $class;
}
/**
* Gets the interface path if specified for current table.
* If not, will return 'propel.om.Persistent'.
* @return string
*/
protected function getInterface() {
$interface = $this->getTable()->getInterface();
if ($interface === null && !$this->getTable()->isReadOnly()) {
$interface = "propel.om.Persistent";
}
return $interface;
}
/**
* Whether to add the generic mutator methods (setByName(), setByPosition(), fromArray()).
* This is based on the build property propel.addGenericMutators, and also whether the
* table is read-only or an alias.
*/
protected function isAddGenericMutators()
{
$table = $this->getTable();
return (!$table->isAlias() && $this->getBuildProperty('addGenericMutators') && !$table->isReadOnly());
}
/**
* Whether to add the generic accessor methods (getByName(), getByPosition(), toArray()).
* This is based on the build property propel.addGenericAccessors, and also whether the
* table is an alias.
*/
protected function isAddGenericAccessors()
{
$table = $this->getTable();
return (!$table->isAlias() && $this->getBuildProperty('addGenericAccessors'));
}
}

View File

@ -0,0 +1,269 @@
<?php
/*
* $Id: PeerBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/OMBuilder.php';
/**
* Base class for Peer-building classes.
*
* This class is designed so that it can be extended by a PHP4PeerBuilder in addition
* to the "standard" PHP5PeerBuilder and PHP5ComplexOMPeerBuilder. Hence, this class
* should not have any actual template code in it -- simply basic logic & utility
* methods.
*
* @author Hans Lellelid <hans@xmpl.org>
*/
abstract class PeerBuilder extends OMBuilder {
protected $basePeerClass;
protected $basePeerClassname;
/**
* Constructs a new PeerBuilder subclass.
*/
public function __construct(Table $table) {
parent::__construct($table);
$this->basePeerClass = $this->getBasePeer($table);
$this->basePeerClassname = $this->classname($this->basePeerClass);
}
/**
* Adds the addSelectColumns(), doCount(), etc. methods.
* @param string &$script The script will be modified in this method.
*/
protected function addSelectMethods(&$script)
{
$this->addAddSelectColumns($script);
$this->addCountConstants($script);
$this->addDoCount($script);
// consider refactoring the doSelect stuff
// into a top-level method
$this->addDoSelectOne($script);
$this->addDoSelect($script);
$this->addDoSelectRS($script); // <-- there's Creole code in here
$this->addPopulateObjects($script); // <-- there's Creole code in here
}
/**
* Adds the correct getOMClass() method, depending on whether this table uses inheritance.
* @param string &$script The script will be modified in this method.
*/
protected function addGetOMClassMethod(&$script)
{
$table = $this->getTable();
if ($table->getChildrenColumn()) {
if ($table->isAbstract()) {
$this->addGetOMClass_Inheritance_Abstract($script);
} else {
$this->addGetOMClass_Inheritance($script);
}
} else {
if ($table->isAbstract()) {
$this->addGetOMClass_NoInheritance_Abstract($script);
} else {
$this->addGetOMClass_NoInheritance($script);
}
}
}
/**
* Adds the doInsert(), doUpdate(), doDeleteAll(), doValidate(), etc. methods.
* @param string &$script The script will be modified in this method.
*/
protected function addUpdateMethods(&$script)
{
$this->addDoInsert($script);
$this->addDoUpdate($script);
$this->addDoDeleteAll($script);
$this->addDoDelete($script);
if ($this->isDeleteCascadeEmulationNeeded()) {
$this->addDoOnDeleteCascade($script);
}
if ($this->isDeleteSetNullEmulationNeeded()) {
$this->addDoOnDeleteSetNull($script);
}
$this->addDoValidate($script);
}
/**
* Adds the retrieveByPK() (and possibly retrieveByPKs()) method(s) appropriate for this class.
* @param string &$script The script will be modified in this method.
*/
protected function addRetrieveByPKMethods(&$script)
{
if (count($this->getTable()->getPrimaryKey()) === 1) {
$this->addRetrieveByPK_SinglePK($script);
$this->addRetrieveByPKs_SinglePK($script);
} else {
$this->addRetrieveByPK_MultiPK($script);
}
}
/**
* This method adds the contents of the generated class to the script.
*
* This method contains the high-level logic that determines which methods
* get generated.
*
* Hint: Override this method in your subclass if you want to reorganize or
* drastically change the contents of the generated peer class.
*
* @param string &$script The script will be modified in this method.
*/
protected function addClassBody(&$script)
{
$table = $this->getTable();
if (!$table->isAlias()) {
$this->addConstantsAndAttributes($script);
}
$this->addGetMapBuilder($script);
$this->addGetPhpNameMap($script);
$this->addTranslateFieldName($script);
$this->addGetFieldNames($script);
if (!$table->isAlias()) {
$this->addAlias($script); // alias() utility method (deprecated?)
$this->addSelectMethods($script);
$this->addGetTableMap($script);
}
$this->addGetOMClassMethod($script);
// add the insert, update, delete, validate etc. methods
if (!$table->isAlias() && !$table->isReadOnly()) {
$this->addUpdateMethods($script);
}
if (count($table->getPrimaryKey()) > 0) {
$this->addRetrieveByPKMethods($script);
}
}
/**
* Whether the platform in use requires ON DELETE CASCADE emulation and whether there are references to this table.
* @return boolean
*/
protected function isDeleteCascadeEmulationNeeded()
{
$table = $this->getTable();
if ((!$this->getPlatform()->supportsNativeDeleteTrigger() || $this->getBuildProperty('emulateForeignKeyConstraints')) && count($table->getReferrers()) > 0) {
foreach ($table->getReferrers() as $fk) {
if ($fk->getOnDelete() == ForeignKey::CASCADE) {
return true;
}
}
}
return false;
}
/**
* Whether the platform in use requires ON DELETE SETNULL emulation and whether there are references to this table.
* @return boolean
*/
protected function isDeleteSetNullEmulationNeeded()
{
$table = $this->getTable();
if ((!$this->getPlatform()->supportsNativeDeleteTrigger() || $this->getBuildProperty('emulateForeignKeyConstraints')) && count($table->getReferrers()) > 0) {
foreach ($table->getReferrers() as $fk) {
if ($fk->getOnDelete() == ForeignKey::SETNULL) {
return true;
}
}
}
return false;
}
/**
* Whether to add the generic mutator methods (setByName(), setByPosition(), fromArray()).
* This is based on the build property propel.addGenericMutators, and also whether the
* table is read-only or an alias.
* @return boolean
*/
protected function isAddGenericMutators()
{
$table = $this->getTable();
return (!$table->isAlias() && $this->getBuildProperty('addGenericMutators') && !$table->isReadOnly());
}
/**
* Whether to add the generic accessor methods (getByName(), getByPosition(), toArray()).
* This is based on the build property propel.addGenericAccessors, and also whether the
* table is an alias.
* @return boolean
*/
protected function isAddGenericAccessors()
{
$table = $this->getTable();
return (!$table->isAlias() && $this->getBuildProperty('addGenericAccessors'));
}
/**
* Returns the retrieveByPK method name to use for this table.
* If the table is an alias then the method name looks like "retrieveTablenameByPK"
* otherwise simply "retrieveByPK".
* @return string
*/
public function getRetrieveMethodName()
{
if ($this->getTable()->isAlias()) {
$retrieveMethod = "retrieve" . $this->getTable()->getPhpName() . "ByPK";
} else {
$retrieveMethod = "retrieveByPK";
}
return $retrieveMethod;
}
/**
* COMPATIBILITY: Get the column constant name (e.g. PeerName::COLUMN_NAME).
*
* This method exists simply because it belonged to the 'PeerBuilder' that this
* class is replacing (because of name conflict more than actual functionality overlap).
* When the new builder model is finished this method will be removed.
*
* @param Column $col The column we need a name for.
* @param string $phpName The PHP Name of the peer class. The 'Peer' is appended automatically.
*
* @return string If $phpName is provided, then will return {$phpName}Peer::COLUMN_NAME; if not, just COLUMN_NAME.
* @deprecated
*/
public static function getColumnName(Column $col, $phpName = null) {
// was it overridden in schema.xml ?
if ($col->getPeerName()) {
$const = strtoupper($col->getPeerName());
} else {
$const = strtoupper($col->getName());
}
if ($phpName !== null) {
return $phpName . 'Peer::' . $const;
} else {
return $const;
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,866 @@
<?php
/*
* $Id: PHP5ComplexPeerBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/php5/PHP5BasicPeerBuilder.php';
/**
* Generates a PHP5 base Peer class with complex object model methods.
*
* This class extends the basic peer builder by adding on the doSelectJoin*()
* methods and other complex object model methods.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.om.php5
*/
class PHP5ComplexPeerBuilder extends PHP5BasicPeerBuilder {
/**
* Adds the complex OM methods to the base addSelectMethods() function.
* @param string &$script The script will be modified in this method.
* @see PeerBuilder::addSelectMethods()
*/
protected function addSelectMethods(&$script)
{
$table = $this->getTable();
parent::addSelectMethods($script);
$this->addDoCountJoin($script);
$this->addDoSelectJoin($script);
$countFK = count($table->getForeignKeys());
$includeJoinAll = true;
foreach ($this->getTable()->getForeignKeys() as $fk) {
$tblFK = $table->getDatabase()->getTable($fk->getForeignTableName());
if ($tblFK->isForReferenceOnly()) {
$includeJoinAll = false;
}
}
if ($includeJoinAll) {
if($countFK > 0) {
$this->addDoCountJoinAll($script);
$this->addDoSelectJoinAll($script);
}
if ($countFK > 1) {
$this->addDoCountJoinAllExcept($script);
$this->addDoSelectJoinAllExcept($script);
}
}
}
/**
* Adds the doSelectJoin*() methods.
* @param string &$script The script will be modified in this method.
*/
protected function addDoSelectJoin(&$script)
{
$table = $this->getTable();
$className = $table->getPhpName();
$countFK = count($table->getForeignKeys());
if ($countFK >= 1) {
foreach ($table->getForeignKeys() as $fk) {
$joinTable = $table->getDatabase()->getTable($fk->getForeignTableName());
if (!$joinTable->isForReferenceOnly()) {
// FIXME - look into removing this next condition; it may not
// be necessary:
// --- IT is necessary because there needs to be a system for
// aliasing the table if it is the same table.
if ( $fk->getForeignTableName() != $table->getName() ) {
/*
REPLACED BY USING THE ObjectBuilder objects below
// check to see if we need to add something to the method name.
// For example if there are multiple columns that reference the same
// table, then we have to have a methd name like doSelectJoinBooksByBookId
$partJoinName = "";
foreach ($fk->getLocalColumns() as $columnName ) {
$column = $table->getColumn($columnName);
// this second part is not currently ever true (right?)
if ($column->isMultipleFK() || $fk->getForeignTableName() == $table->getName()) {
$partJoinName = $partJoinName . $column->getPhpName();
}
}
$joinClassName = $joinTable->getPhpName();
if ($joinTable->getInterface()) {
$interfaceName = $joinTable->getInterface();
} else {
$interfaceName = $joinTable->getPhpName();
}
if ($partJoinName == "") {
$joinColumnId = $joinClassName;
$joinInterface = $interfaceName;
$collThisTable = $className . "s";
$collThisTableMs = $className;
} else {
$joinColumnId = $joinClassName . "RelatedBy" . $partJoinName;
$joinInterface = $interfaceName . "RelatedBy" . $partJoinName;
$collThisTable = $className . "sRelatedBy" . $partJoinName;
$collThisTableMs = $className . "RelatedBy" . $partJoinName;
}
*/
$joinClassName = $joinTable->getPhpName();
$thisTableObjectBuilder = OMBuilder::getNewObjectBuilder($table);
$joinedTableObjectBuilder = OMBuilder::getNewObjectBuilder($joinTable);
$joinedTablePeerBuilder = OMBuilder::getNewPeerBuilder($joinTable);
$script .= "
/**
* Selects a collection of $className objects pre-filled with their $joinClassName objects.
*
* @return array Array of $className objects.
* @throws PropelException Any exceptions caught during processing will be
* rethrown wrapped into a PropelException.
*/
public static function doSelectJoin".$thisTableObjectBuilder->getFKPhpNameAffix($fk, $plural = false)."(Criteria \$c, \$con = null)
{
\$c = clone \$c;
// Set the correct dbName if it has not been overridden
if (\$c->getDbName() == Propel::getDefaultDB()) {
\$c->setDbName(self::DATABASE_NAME);
}
".$this->getPeerClassname()."::addSelectColumns(\$c);
\$startcol = (".$this->getPeerClassname()."::NUM_COLUMNS - ".$this->getPeerClassname()."::NUM_LAZY_LOAD_COLUMNS) + 1;
".$joinedTablePeerBuilder->getPeerClassname()."::addSelectColumns(\$c);
";
$lfMap = $fk->getLocalForeignMapping();
foreach ($fk->getLocalColumns() as $columnName ) {
$column = $table->getColumn($columnName);
$columnFk = $joinTable->getColumn( $lfMap[$columnName] );
$script .= "
\$c->addJoin(".$this->getColumnConstant($column).", ".$joinedTablePeerBuilder->getColumnConstant($columnFk).");"; //CHECKME
}
$script .= "
\$rs = ".$this->basePeerClassname."::doSelect(\$c, \$con);
\$results = array();
while(\$rs->next()) {
";
if ($table->getChildrenColumn()) {
$script .= "
\$omClass = ".$this->getPeerClassname()."::getOMClass(\$rs, 1);
";
} else {
$script .= "
\$omClass = ".$this->getPeerClassname()."::getOMClass();
";
}
$script .= "
\$cls = Propel::import(\$omClass);
\$obj1 = new \$cls();
\$obj1->hydrate(\$rs);
";
if ($joinTable->getChildrenColumn()) {
$script .= "
\$omClass = ".$joinedTablePeerBuilder->getPeerClassname()."::getOMClass(\$rs, \$startcol);
";
} else {
$script .= "
\$omClass = ".$joinedTablePeerBuilder->getPeerClassname()."::getOMClass();
";
}
$script .= "
\$cls = Propel::import(\$omClass);
\$obj2 = new \$cls();
\$obj2->hydrate(\$rs, \$startcol);
\$newObject = true;
foreach(\$results as \$temp_obj1) {
\$temp_obj2 = \$temp_obj1->get".$thisTableObjectBuilder->getFKPhpNameAffix($fk, $plural = false)."(); //CHECKME
if (\$temp_obj2->getPrimaryKey() === \$obj2->getPrimaryKey()) {
\$newObject = false;
// e.g. \$author->addBookRelatedByBookId()
\$temp_obj2->add".$joinedTableObjectBuilder->getRefFKPhpNameAffix($fk, $plural = false)."(\$obj1); //CHECKME
break;
}
}
if (\$newObject) {
\$obj2->init".$joinedTableObjectBuilder->getRefFKPhpNameAffix($fk, $plural = true)."();
\$obj2->add".$joinedTableObjectBuilder->getRefFKPhpNameAffix($fk, $plural = false)."(\$obj1); //CHECKME
}
\$results[] = \$obj1;
}
return \$results;
}
";
} // if fk table name != this table name
} // if ! is reference only
} // foreach column
} // if count(fk) > 1
} // addDoSelectJoin()
/**
* Adds the doCountJoin*() methods.
* @param string &$script The script will be modified in this method.
*/
protected function addDoCountJoin(&$script)
{
$table = $this->getTable();
$className = $table->getPhpName();
$countFK = count($table->getForeignKeys());
if ($countFK >= 1) {
foreach ($table->getForeignKeys() as $fk) {
$joinTable = $table->getDatabase()->getTable($fk->getForeignTableName());
if (!$joinTable->isForReferenceOnly()) {
if ( $fk->getForeignTableName() != $table->getName() ) {
$joinClassName = $joinTable->getPhpName();
$thisTableObjectBuilder = OMBuilder::getNewObjectBuilder($table);
$joinedTableObjectBuilder = OMBuilder::getNewObjectBuilder($joinTable);
$joinedTablePeerBuilder = OMBuilder::getNewPeerBuilder($joinTable);
$script .= "
/**
* Returns the number of rows matching criteria, joining the related ".$thisTableObjectBuilder->getFKPhpNameAffix($fk, $plural = false)." table
*
* @param Criteria \$c
* @param boolean \$distinct Whether to select only distinct columns (You can also set DISTINCT modifier in Criteria).
* @param Connection \$con
* @return int Number of matching rows.
*/
public static function doCountJoin".$thisTableObjectBuilder->getFKPhpNameAffix($fk, $plural = false)."(Criteria \$criteria, \$distinct = false, \$con = null)
{
// we're going to modify criteria, so copy it first
\$criteria = clone \$criteria;
// clear out anything that might confuse the ORDER BY clause
\$criteria->clearSelectColumns()->clearOrderByColumns();
if (\$distinct || in_array(Criteria::DISTINCT, \$criteria->getSelectModifiers())) {
\$criteria->addSelectColumn(".$this->getPeerClassname()."::COUNT_DISTINCT);
} else {
\$criteria->addSelectColumn(".$this->getPeerClassname()."::COUNT);
}
// just in case we're grouping: add those columns to the select statement
foreach(\$criteria->getGroupByColumns() as \$column)
{
\$criteria->addSelectColumn(\$column);
}
";
$lfMap = $fk->getLocalForeignMapping();
foreach ($fk->getLocalColumns() as $columnName ) {
$column = $table->getColumn($columnName);
$columnFk = $joinTable->getColumn( $lfMap[$columnName] );
$script .= "
\$criteria->addJoin(".$this->getColumnConstant($column).", ".$joinedTablePeerBuilder->getColumnConstant($columnFk).");
";
}
$script .= "
\$rs = ".$this->getPeerClassname()."::doSelectRS(\$criteria, \$con);
if (\$rs->next()) {
return \$rs->getInt(1);
} else {
// no rows returned; we infer that means 0 matches.
return 0;
}
}
";
} // if fk table name != this table name
} // if ! is reference only
} // foreach column
} // if count(fk) > 1
} // addDoCountJoin()
/**
* Adds the doSelectJoinAll() method.
* @param string &$script The script will be modified in this method.
*/
protected function addDoSelectJoinAll(&$script)
{
$table = $this->getTable();
$className = $table->getPhpName();
$script .= "
/**
* Selects a collection of $className objects pre-filled with all related objects.
*
* @return array Array of $className objects.
* @throws PropelException Any exceptions caught during processing will be
* rethrown wrapped into a PropelException.
*/
public static function doSelectJoinAll(Criteria \$c, \$con = null)
{
\$c = clone \$c;
// Set the correct dbName if it has not been overridden
if (\$c->getDbName() == Propel::getDefaultDB()) {
\$c->setDbName(self::DATABASE_NAME);
}
".$this->getPeerClassname()."::addSelectColumns(\$c);
\$startcol2 = (".$this->getPeerClassname()."::NUM_COLUMNS - ".$this->getPeerClassname()."::NUM_LAZY_LOAD_COLUMNS) + 1;
";
$index = 2;
foreach ($table->getForeignKeys() as $fk) {
// want to cover this case, but the code is not there yet.
// FIXME: why "is the code not there yet" ?
if ( $fk->getForeignTableName() != $table->getName() ) {
$joinTable = $table->getDatabase()->getTable($fk->getForeignTableName());
$joinClassName = $joinTable->getPhpName();
$new_index = $index + 1;
$joinedTablePeerBuilder = OMBuilder::getNewPeerBuilder($joinTable);
$script .= "
".$joinedTablePeerBuilder->getPeerClassname()."::addSelectColumns(\$c);
\$startcol$new_index = \$startcol$index + ".$joinedTablePeerBuilder->getPeerClassname()."::NUM_COLUMNS;
";
$index = $new_index;
} // if fk->getForeignTableName != table->getName
} // foreach [sub] foreign keys
foreach ($table->getForeignKeys() as $fk) {
// want to cover this case, but the code is not there yet.
if ( $fk->getForeignTableName() != $table->getName() ) {
$joinTable = $table->getDatabase()->getTable($fk->getForeignTableName());
$joinedTablePeerBuilder = OMBuilder::getNewPeerBuilder($joinTable);
$joinClassName = $joinTable->getPhpName();
$lfMap = $fk->getLocalForeignMapping();
foreach ($fk->getLocalColumns() as $columnName ) {
$column = $table->getColumn($columnName);
$columnFk = $joinTable->getColumn( $lfMap[$columnName]);
$script .= "
\$c->addJoin(".$this->getColumnConstant($column).", ".$joinedTablePeerBuilder->getColumnConstant($columnFk).");
";
}
}
}
$script .= "
\$rs = ".$this->basePeerClassname."::doSelect(\$c, \$con);
\$results = array();
while(\$rs->next()) {
";
if ($table->getChildrenColumn()) {
$script .= "
\$omClass = ".$this->getPeerClassname()."::getOMClass(\$rs, 1);
";
} else {
$script .= "
\$omClass = ".$this->getPeerClassname()."::getOMClass();
";
}
$script .= "
\$cls = Propel::import(\$omClass);
\$obj1 = new \$cls();
\$obj1->hydrate(\$rs);
";
$index = 1;
foreach ($table->getForeignKeys() as $fk ) {
// want to cover this case, but the code is not there yet.
// FIXME -- why not? -because we'd have to alias the tables in the JOIN
if ( $fk->getForeignTableName() != $table->getName() ) {
$joinTable = $table->getDatabase()->getTable($fk->getForeignTableName());
$joinClassName = $joinTable->getPhpName();
$interfaceName = $joinTable->getPhpName();
if($joinTable->getInterface()) {
$interfaceName = $joinTable->getInterface();
}
/*
$partJoinName = "";
foreach ($fk->getLocalColumns() as $columnName ) {
$column = $table->getColumn($columnName);
if ($column->isMultipleFK()) {
$partJoinName .= $column->getPhpName();
}
}
if ($partJoinName == "") {
$joinString = $interfaceName;
$collThisTable = "${className}s";
$collThisTableMs = $className;
} else {
$joinString= $interfaceName."RelatedBy" . $partJoinName;
$collThisTable= $className . "sRelatedBy" . $partJoinName;
$collThisTableMs= $className . "RelatedBy" . $partJoinName;
}
*/
$thisTableObjectBuilder = OMBuilder::getNewObjectBuilder($table);
$joinedTableObjectBuilder = OMBuilder::getNewObjectBuilder($joinTable);
$joinedTablePeerBuilder = OMBuilder::getNewPeerBuilder($joinTable);
$index++;
$script .= "
// Add objects for joined $joinClassName rows
";
if ($joinTable->getChildrenColumn()) {
$script .= "
\$omClass = ".$joinedTablePeerBuilder->getPeerClassname()."::getOMClass(\$rs, \$startcol$index);
";
} else {
$script .= "
\$omClass = ".$joinedTablePeerBuilder->getPeerClassname()."::getOMClass();
";
} /* $joinTable->getChildrenColumn() */
$script .= "
\$cls = Propel::import(\$omClass);
\$obj".$index." = new \$cls();
\$obj".$index."->hydrate(\$rs, \$startcol$index);
\$newObject = true;
for (\$j=0, \$resCount=count(\$results); \$j < \$resCount; \$j++) {
\$temp_obj1 = \$results[\$j];
\$temp_obj$index = \$temp_obj1->get".$thisTableObjectBuilder->getFKPhpNameAffix($fk, $plural = false)."(); // CHECKME
if (\$temp_obj".$index."->getPrimaryKey() === \$obj".$index."->getPrimaryKey()) {
\$newObject = false;
\$temp_obj".$index."->add".$joinedTableObjectBuilder->getRefFKPhpNameAffix($fk, $plural = false)."(\$obj1); // CHECKME
break;
}
}
if (\$newObject) {
\$obj".$index."->init".$joinedTableObjectBuilder->getRefFKPhpNameAffix($fk, $plural = true)."();
\$obj".$index."->add".$joinedTableObjectBuilder->getRefFKPhpNameAffix($fk, $plural = false)."(\$obj1);
}
";
} // $fk->getForeignTableName() != $table->getName()
} //foreach foreign key
$script .= "
\$results[] = \$obj1;
}
return \$results;
}
";
} // end addDoSelectJoinAll()
/**
* Adds the doCountJoinAll() method.
* @param string &$script The script will be modified in this method.
*/
protected function addDoCountJoinAll(&$script)
{
$table = $this->getTable();
$className = $table->getPhpName();
$script .= "
/**
* Returns the number of rows matching criteria, joining all related tables
*
* @param Criteria \$c
* @param boolean \$distinct Whether to select only distinct columns (You can also set DISTINCT modifier in Criteria).
* @param Connection \$con
* @return int Number of matching rows.
*/
public static function doCountJoinAll(Criteria \$criteria, \$distinct = false, \$con = null)
{
\$criteria = clone \$criteria;
// clear out anything that might confuse the ORDER BY clause
\$criteria->clearSelectColumns()->clearOrderByColumns();
if (\$distinct || in_array(Criteria::DISTINCT, \$criteria->getSelectModifiers())) {
\$criteria->addSelectColumn(".$this->getPeerClassname()."::COUNT_DISTINCT);
} else {
\$criteria->addSelectColumn(".$this->getPeerClassname()."::COUNT);
}
// just in case we're grouping: add those columns to the select statement
foreach(\$criteria->getGroupByColumns() as \$column)
{
\$criteria->addSelectColumn(\$column);
}
";
foreach ($table->getForeignKeys() as $fk) {
// want to cover this case, but the code is not there yet.
if ( $fk->getForeignTableName() != $table->getName() ) {
$joinTable = $table->getDatabase()->getTable($fk->getForeignTableName());
$joinedTablePeerBuilder = OMBuilder::getNewPeerBuilder($joinTable);
$joinClassName = $joinTable->getPhpName();
$lfMap = $fk->getLocalForeignMapping();
foreach ($fk->getLocalColumns() as $columnName ) {
$column = $table->getColumn($columnName);
$columnFk = $joinTable->getColumn( $lfMap[$columnName]);
$script .= "
\$criteria->addJoin(".$this->getColumnConstant($column).", ".$joinedTablePeerBuilder->getColumnConstant($columnFk).");
";
}
} // if fk->getForeignTableName != table->getName
} // foreach [sub] foreign keys
$script .= "
\$rs = ".$this->getPeerClassname()."::doSelectRS(\$criteria, \$con);
if (\$rs->next()) {
return \$rs->getInt(1);
} else {
// no rows returned; we infer that means 0 matches.
return 0;
}
}
";
} // end addDoCountJoinAll()
/**
* Adds the doSelectJoinAllExcept*() methods.
* @param string &$script The script will be modified in this method.
*/
protected function addDoSelectJoinAllExcept(&$script)
{
$table = $this->getTable();
// ------------------------------------------------------------------------
// doSelectJoinAllExcept*()
// ------------------------------------------------------------------------
// 2) create a bunch of doSelectJoinAllExcept*() methods
// -- these were existing in original Torque, so we should keep them for compatibility
$fkeys = $table->getForeignKeys(); // this sep assignment is necessary otherwise sub-loops over
// getForeignKeys() will cause this to only execute one time.
foreach ($fkeys as $fk ) {
$tblFK = $table->getDatabase()->getTable($fk->getForeignTableName());
$excludedTable = $table->getDatabase()->getTable($fk->getForeignTableName());
$excludedClassName = $excludedTable->getPhpName();
/*
$relatedByCol = "";
foreach ($fk->getLocalColumns() as $columnName) {
$column = $table->getColumn($columnName);
if ($column->isMultipleFK()) {
$relatedByCol .= $column->getPhpName();
}
}
if ($relatedByCol == "") {
$excludeString = $excludedClassName;
$collThisTable = "${className}s";
$collThisTableMs = $className;
} else {
$excludeString = $excludedClassName . "RelatedBy" . $relatedByCol;
$collThisTable = $className . "sRelatedBy" . $relatedByCol;
$collThisTableMs = $className . "RelatedBy" . $relatedByCol;
}
*/
$thisTableObjectBuilder = OMBuilder::getNewObjectBuilder($table);
$excludedTableObjectBuilder = OMBuilder::getNewObjectBuilder($excludedTable);
$excludedTablePeerBuilder = OMBuilder::getNewPeerBuilder($excludedTable);
$script .= "
/**
* Selects a collection of ".$table->getPhpName()." objects pre-filled with all related objects except ".$thisTableObjectBuilder->getFKPhpNameAffix($fk).".
*
* @return array Array of ".$table->getPhpName()." objects.
* @throws PropelException Any exceptions caught during processing will be
* rethrown wrapped into a PropelException.
*/
public static function doSelectJoinAllExcept".$thisTableObjectBuilder->getFKPhpNameAffix($fk, $plural = false)."(Criteria \$c, \$con = null)
{
\$c = clone \$c;
// Set the correct dbName if it has not been overridden
// \$c->getDbName() will return the same object if not set to another value
// so == check is okay and faster
if (\$c->getDbName() == Propel::getDefaultDB()) {
\$c->setDbName(self::DATABASE_NAME);
}
".$this->getPeerClassname()."::addSelectColumns(\$c);
\$startcol2 = (".$this->getPeerClassname()."::NUM_COLUMNS - ".$this->getPeerClassname()."::NUM_LAZY_LOAD_COLUMNS) + 1;
";
$index = 2;
foreach ($table->getForeignKeys() as $subfk) {
// want to cover this case, but the code is not there yet.
// FIXME - why not?
if ( !($subfk->getForeignTableName() == $table->getName())) {
$joinTable = $table->getDatabase()->getTable($subfk->getForeignTableName());
$joinClassName = $joinTable->getPhpName();
$joinTablePeerBuilder = OMBuilder::getNewPeerBuilder($joinTable);
if ($joinClassName != $excludedClassName) {
$new_index = $index + 1;
$script .= "
".$joinTablePeerBuilder->getPeerClassname()."::addSelectColumns(\$c);
\$startcol$new_index = \$startcol$index + ".$joinTablePeerBuilder->getPeerClassname()."::NUM_COLUMNS;
";
$index = $new_index;
} // if joinClassName not excludeClassName
} // if subfk is not curr table
} // foreach [sub] foreign keys
foreach ($table->getForeignKeys() as $subfk) {
// want to cover this case, but the code is not there yet.
if ( $subfk->getForeignTableName() != $table->getName() ) {
$joinTable = $table->getDatabase()->getTable($subfk->getForeignTableName());
$joinClassName = $joinTable->getPhpName();
$joinTablePeerBuilder = OMBuilder::getNewPeerBuilder($joinTable);
if($joinClassName != $excludedClassName)
{
$lfMap = $subfk->getLocalForeignMapping();
foreach ($subfk->getLocalColumns() as $columnName ) {
$column = $table->getColumn($columnName);
$columnFk = $joinTable->getColumn( $lfMap[$columnName]);
$script .= "
\$c->addJoin(".$this->getColumnConstant($column).", ".$joinTablePeerBuilder->getColumnConstant($columnFk).");
";
}
}
}
} // foreach fkeys
$script .= "
\$rs = ".$this->basePeerClassname ."::doSelect(\$c, \$con);
\$results = array();
while(\$rs->next()) {
";
if ($table->getChildrenColumn()) {
$script .= "
\$omClass = ".$this->getPeerClassname()."::getOMClass(\$rs, 1);
";
} else {
$script .= "
\$omClass = ".$this->getPeerClassname()."::getOMClass();
";
}
$script .= "
\$cls = Propel::import(\$omClass);
\$obj1 = new \$cls();
\$obj1->hydrate(\$rs);
";
$index = 1;
foreach ($table->getForeignKeys() as $subfk ) {
// want to cover this case, but the code is not there yet.
if ( $subfk->getForeignTableName() != $table->getName() ) {
$joinTable = $table->getDatabase()->getTable($subfk->getForeignTableName());
$joinClassName = $joinTable->getPhpName();
$interfaceName = $joinTable->getPhpName();
if($joinTable->getInterface()) {
$interfaceName = $joinTable->getInterface();
}
if ($joinClassName != $excludedClassName) {
/*
$partJoinName = "";
foreach ($subfk->getLocalColumns() as $columnName ) {
$column = $table->getColumn($columnName);
if ($column->isMultipleFK()) {
$partJoinName .= $column->getPhpName();
}
}
if ($partJoinName == "") {
$joinString = $interfaceName;
$collThisTable = "${className}s";
$collThisTableMs = $className;
} else {
$joinString= $interfaceName."RelatedBy" . $partJoinName;
$collThisTable= $className . "sRelatedBy" . $partJoinName;
$collThisTableMs= $className . "RelatedBy" . $partJoinName;
}
*/
$joinedTableObjectBuilder = OMBuilder::getNewObjectBuilder($joinTable);
$joinedTablePeerBuilder = OMBuilder::getNewPeerBuilder($joinTable);
$index++;
if ($joinTable->getChildrenColumn()) {
$script .= "
\$omClass = ".$joinedTablePeerBuilder->getPeerClassname()."::getOMClass(\$rs, \$startcol$index);
";
} else {
$script .= "
\$omClass = ".$joinedTablePeerBuilder->getPeerClassname()."::getOMClass();
";
} /* $joinTable->getChildrenColumn() */
$script .= "
\$cls = Propel::import(\$omClass);
\$obj$index = new \$cls();
\$obj".$index."->hydrate(\$rs, \$startcol$index);
\$newObject = true;
for (\$j=0, \$resCount=count(\$results); \$j < \$resCount; \$j++) {
\$temp_obj1 = \$results[\$j];
\$temp_obj$index = \$temp_obj1->get".$thisTableObjectBuilder->getFKPhpNameAffix($subfk, $plural=false)."(); //CHECKME
if (\$temp_obj".$index."->getPrimaryKey() === \$obj".$index."->getPrimaryKey()) {
\$newObject = false;
\$temp_obj".$index."->add".$joinedTableObjectBuilder->getRefFKPhpNameAffix($subfk, $plural=false)."(\$obj1);
break;
}
}
if (\$newObject) {
\$obj".$index."->init".$joinedTableObjectBuilder->getRefFKPhpNameAffix($subfk, $plural=true)."();
\$obj".$index."->add".$joinedTableObjectBuilder->getRefFKPhpNameAffix($subfk, $plural=false)."(\$obj1);
}
";
} // if ($joinClassName != $excludedClassName) {
} // $subfk->getForeignTableName() != $table->getName()
} // foreach
$script .= "
\$results[] = \$obj1;
}
return \$results;
}
";
} // foreach fk
} // addDoSelectJoinAllExcept
/**
* Adds the doCountJoinAllExcept*() methods.
* @param string &$script The script will be modified in this method.
*/
protected function addDoCountJoinAllExcept(&$script)
{
$table = $this->getTable();
$fkeys = $table->getForeignKeys(); // this sep assignment is necessary otherwise sub-loops over
// getForeignKeys() will cause this to only execute one time.
foreach ($fkeys as $fk ) {
$tblFK = $table->getDatabase()->getTable($fk->getForeignTableName());
$excludedTable = $table->getDatabase()->getTable($fk->getForeignTableName());
$excludedClassName = $excludedTable->getPhpName();
$thisTableObjectBuilder = OMBuilder::getNewObjectBuilder($table);
$excludedTableObjectBuilder = OMBuilder::getNewObjectBuilder($excludedTable);
$excludedTablePeerBuilder = OMBuilder::getNewPeerBuilder($excludedTable);
$script .= "
/**
* Returns the number of rows matching criteria, joining the related ".$thisTableObjectBuilder->getFKPhpNameAffix($fk, $plural = false)." table
*
* @param Criteria \$c
* @param boolean \$distinct Whether to select only distinct columns (You can also set DISTINCT modifier in Criteria).
* @param Connection \$con
* @return int Number of matching rows.
*/
public static function doCountJoinAllExcept".$thisTableObjectBuilder->getFKPhpNameAffix($fk, $plural = false)."(Criteria \$criteria, \$distinct = false, \$con = null)
{
// we're going to modify criteria, so copy it first
\$criteria = clone \$criteria;
// clear out anything that might confuse the ORDER BY clause
\$criteria->clearSelectColumns()->clearOrderByColumns();
if (\$distinct || in_array(Criteria::DISTINCT, \$criteria->getSelectModifiers())) {
\$criteria->addSelectColumn(".$this->getPeerClassname()."::COUNT_DISTINCT);
} else {
\$criteria->addSelectColumn(".$this->getPeerClassname()."::COUNT);
}
// just in case we're grouping: add those columns to the select statement
foreach(\$criteria->getGroupByColumns() as \$column)
{
\$criteria->addSelectColumn(\$column);
}
";
foreach ($table->getForeignKeys() as $subfk) {
// want to cover this case, but the code is not there yet.
if ( $subfk->getForeignTableName() != $table->getName() ) {
$joinTable = $table->getDatabase()->getTable($subfk->getForeignTableName());
$joinClassName = $joinTable->getPhpName();
$joinTablePeerBuilder = OMBuilder::getNewPeerBuilder($joinTable);
if($joinClassName != $excludedClassName)
{
$lfMap = $subfk->getLocalForeignMapping();
foreach ($subfk->getLocalColumns() as $columnName ) {
$column = $table->getColumn($columnName);
$columnFk = $joinTable->getColumn( $lfMap[$columnName]);
$script .= "
\$criteria->addJoin(".$this->getColumnConstant($column).", ".$joinTablePeerBuilder->getColumnConstant($columnFk).");
";
}
}
}
} // foreach fkeys
$script .= "
\$rs = ".$this->getPeerClassname()."::doSelectRS(\$criteria, \$con);
if (\$rs->next()) {
return \$rs->getInt(1);
} else {
// no rows returned; we infer that means 0 matches.
return 0;
}
}
";
} // foreach fk
} // addDoCountJoinAllExcept
} // PHP5ComplexPeerBuilder

View File

@ -0,0 +1,124 @@
<?php
/*
* $Id: PHP5ExtensionNodeBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/ObjectBuilder.php';
/**
* Generates the empty PHP5 stub node object class for user object model (OM).
*
* This class produces the empty stub class that can be customized with application
* business logic, custom behavior, etc.
*
* This class replaces the ExtensionNode.tpl, with the intent of being easier for users
* to customize (through extending & overriding).
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.om.php5
*/
class PHP5ExtensionNodeBuilder extends ObjectBuilder {
/**
* Returns the name of the current class being built.
* @return string
*/
public function getClassname()
{
return $this->getTable()->getPhpName() . 'Node';
}
/**
* Adds the include() statements for files that this class depends on or utilizes.
* @param string &$script The script will be modified in this method.
*/
protected function addIncludes(&$script)
{
$script .= "
require_once '".$this->getNodeBuilder()->getClassFilePath()."';
";
} // addIncludes()
/**
* Adds class phpdoc comment and openning of class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassOpen(&$script)
{
$table = $this->getTable();
$tableName = $table->getName();
$tableDesc = $table->getDescription();
$baseClassname = $this->getNodeBuilder()->getClassname();
$script .= "
/**
* Skeleton subclass for representing a node from the '$tableName' table.
*
* $tableDesc
*";
if ($this->getBuildProperty('addTimeStamp')) {
$now = strftime('%c');
$script .= "
* This class was autogenerated by Propel on:
*
* $now
*";
}
$script .= "
* You should add additional methods to this class to meet the
* application requirements. This class will only be generated as
* long as it does not already exist in the output directory.
*
* @package ".$this->getPackage()."
*/
class ".$this->getClassname()." extends $baseClassname {
";
}
/**
* Specifies the methods that are added as part of the stub object class.
*
* By default there are no methods for the empty stub classes; override this method
* if you want to change that behavior.
*
* @see ObjectBuilder::addClassBody()
*/
protected function addClassBody(&$script)
{
// there is no class body
}
/**
* Closes class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassClose(&$script)
{
$script .= "
} // " . $this->getClassname() . "
";
}
} // PHP5ExtensionObjectBuilder

View File

@ -0,0 +1,127 @@
<?php
/*
* $Id: PHP5ExtensionNodePeerBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/PeerBuilder.php';
/**
* Generates the empty PHP5 stub node peer class for user object model (OM).
*
* This class produces the empty stub class that can be customized with application
* business logic, custom behavior, etc.
*
* This class replaces the ExtensionNodePeer.tpl, with the intent of being easier for users
* to customize (through extending & overriding).
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.om.php5
*/
class PHP5ExtensionNodePeerBuilder extends PeerBuilder {
/**
* Returns the name of the current class being built.
* @return string
*/
public function getClassname()
{
return $this->getStubNodeBuilder()->getClassname() . 'Peer';
}
/**
* Adds the include() statements for files that this class depends on or utilizes.
* @param string &$script The script will be modified in this method.
*/
protected function addIncludes(&$script)
{
$script .= "
// include base nodepeer class
require_once '".$this->getNodePeerBuilder()->getClassFilePath()."';
// include node class
include_once '".$this->getStubNodeBuilder()->getClassFilePath()."';
";
} // addIncludes()
/**
* Adds class phpdoc comment and openning of class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassOpen(&$script)
{
$table = $this->getTable();
$tableName = $table->getName();
$tableDesc = $table->getDescription();
$baseClassname = $this->getNodePeerBuilder()->getClassname();
$script .= "
/**
* Skeleton subclass for performing query and update operations on nodes of the '$tableName' table.
*
* $tableDesc
*";
if ($this->getBuildProperty('addTimeStamp')) {
$now = strftime('%c');
$script .= "
* This class was autogenerated by Propel on:
*
* $now
*";
}
$script .= "
* You should add additional methods to this class to meet the
* application requirements. This class will only be generated as
* long as it does not already exist in the output directory.
*
* @package ".$this->getPackage()."
*/
class ".$this->getClassname()." extends $baseClassname {
";
}
/**
* Specifies the methods that are added as part of the stub peer class.
*
* By default there are no methods for the empty stub classes; override this method
* if you want to change that behavior.
*
* @see ObjectBuilder::addClassBody()
*/
protected function addClassBody(&$script)
{
// there is no class body
}
/**
* Closes class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassClose(&$script)
{
$script .= "
} // " . $this->getClassname() . "
";
}
} // PHP5ExtensionPeerBuilder

View File

@ -0,0 +1,123 @@
<?php
/*
* $Id: PHP5ExtensionObjectBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/ObjectBuilder.php';
/**
* Generates the empty PHP5 stub object class for user object model (OM).
*
* This class produces the empty stub class that can be customized with application
* business logic, custom behavior, etc.
*
* This class replaces the ExtensionObject.tpl, with the intent of being easier for users
* to customize (through extending & overriding).
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.om.php5
*/
class PHP5ExtensionObjectBuilder extends ObjectBuilder {
/**
* Returns the name of the current class being built.
* @return string
*/
public function getClassname()
{
return $this->getTable()->getPhpName();
}
/**
* Adds the include() statements for files that this class depends on or utilizes.
* @param string &$script The script will be modified in this method.
*/
protected function addIncludes(&$script)
{
$script .= "
require_once '".$this->getObjectBuilder()->getClassFilePath()."';
";
} // addIncludes()
/**
* Adds class phpdoc comment and openning of class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassOpen(&$script)
{
$table = $this->getTable();
$tableName = $table->getName();
$tableDesc = $table->getDescription();
$baseClassname = $this->getObjectBuilder()->getClassname();
$script .= "
/**
* Skeleton subclass for representing a row from the '$tableName' table.
*
* $tableDesc
*";
if ($this->getBuildProperty('addTimeStamp')) {
$now = strftime('%c');
$script .= "
* This class was autogenerated by Propel on:
*
* $now
*";
}
$script .= "
* You should add additional methods to this class to meet the
* application requirements. This class will only be generated as
* long as it does not already exist in the output directory.
*
* @package ".$this->getPackage()."
*/
class ".$this->getClassname()." extends $baseClassname {
";
}
/**
* Specifies the methods that are added as part of the stub object class.
*
* By default there are no methods for the empty stub classes; override this method
* if you want to change that behavior.
*
* @see ObjectBuilder::addClassBody()
*/
protected function addClassBody(&$script)
{
// there is no class body
}
/**
* Closes class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassClose(&$script)
{
$script .= "
} // " . $this->getClassname() . "
";
}
} // PHP5ExtensionObjectBuilder

View File

@ -0,0 +1,127 @@
<?php
/*
* $Id: PHP5ExtensionPeerBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/PeerBuilder.php';
/**
* Generates the empty PHP5 stub peer class for user object model (OM).
*
* This class produces the empty stub class that can be customized with application
* business logic, custom behavior, etc.
*
* This class replaces the ExtensionPeer.tpl, with the intent of being easier for users
* to customize (through extending & overriding).
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.om.php5
*/
class PHP5ExtensionPeerBuilder extends PeerBuilder {
/**
* Returns the name of the current class being built.
* @return string
*/
public function getClassname()
{
return $this->getStubObjectBuilder()->getClassname() . 'Peer';
}
/**
* Adds the include() statements for files that this class depends on or utilizes.
* @param string &$script The script will be modified in this method.
*/
protected function addIncludes(&$script)
{
$script .= "
// include base peer class
require_once '".$this->getPeerBuilder()->getClassFilePath()."';
// include object class
include_once '".$this->getStubObjectBuilder()->getClassFilePath()."';
";
} // addIncludes()
/**
* Adds class phpdoc comment and openning of class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassOpen(&$script)
{
$table = $this->getTable();
$tableName = $table->getName();
$tableDesc = $table->getDescription();
$baseClassname = $this->getPeerBuilder()->getClassname();
$script .= "
/**
* Skeleton subclass for performing query and update operations on the '$tableName' table.
*
* $tableDesc
*";
if ($this->getBuildProperty('addTimeStamp')) {
$now = strftime('%c');
$script .= "
* This class was autogenerated by Propel on:
*
* $now
*";
}
$script .= "
* You should add additional methods to this class to meet the
* application requirements. This class will only be generated as
* long as it does not already exist in the output directory.
*
* @package ".$this->getPackage()."
*/
class ".$this->getClassname()." extends $baseClassname {
";
}
/**
* Specifies the methods that are added as part of the stub peer class.
*
* By default there are no methods for the empty stub classes; override this method
* if you want to change that behavior.
*
* @see ObjectBuilder::addClassBody()
*/
protected function addClassBody(&$script)
{
// there is no class body
}
/**
* Closes class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassClose(&$script)
{
$script .= "
} // " . $this->getClassname() . "
";
}
} // PHP5ExtensionPeerBuilder

View File

@ -0,0 +1,119 @@
<?php
/*
* $Id: PHP5InterfaceBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/ObjectBuilder.php';
/**
* Generates the empty PHP5 stub interface for user object model (OM).
*
* This class produces the empty stub interface when the interface="" attribute is used
* in the the schema xml.
*
* This class replaces the Interface.tpl, with the intent of being easier for users
* to customize (through extending & overriding).
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.om.php5
*/
class PHP5InterfaceBuilder extends ObjectBuilder {
/**
* Returns the name of the current class being built.
* @return string
*/
public function getClassname()
{
return ClassTools::classname($this->getInterface());
}
/**
* Adds the include() statements for files that this class depends on or utilizes.
* @param string &$script The script will be modified in this method.
*/
protected function addIncludes(&$script)
{
} // addIncludes()
/**
* Adds class phpdoc comment and openning of class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassOpen(&$script)
{
$table = $this->getTable();
$tableName = $table->getName();
$tableDesc = $table->getDescription();
$baseClassname = $this->getObjectBuilder()->getClassname();
$script .= "
/**
* This is an interface that should be filled with the public api of the $tableName objects.
*
* $tableDesc
*";
if ($this->getBuildProperty('addTimeStamp')) {
$now = strftime('%c');
$script .= "
* This class was autogenerated by Propel on:
*
* $now
*";
}
$script .= "
* You should add additional method declarations to this interface to meet the
* application requirements. This interface will only be generated as
* long as it does not already exist in the output directory.
*
* @package ".$this->getPackage()."
*/
interface ".$this->getClassname()." {
";
}
/**
* Specifies the methods that are added as part of the stub object class.
*
* By default there are no methods for the empty stub classes; override this method
* if you want to change that behavior.
*
* @see ObjectBuilder::addClassBody()
*/
protected function addClassBody(&$script)
{
// there is no class body
}
/**
* Closes class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassClose(&$script)
{
$script .= "
} // " . $this->getClassname() . "
";
}
} // PHP5ExtensionObjectBuilder

View File

@ -0,0 +1,300 @@
<?php
/*
* $Id: PHP5MapBuilderBuilder.php 562 2007-02-01 02:17:24Z hans $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/OMBuilder.php';
/**
* Generates the PHP5 map builder class for user object model (OM).
*
* This class replaces the MapBuilder.tpl, with the intent of being easier for users
* to customize (through extending & overriding).
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.om.php5
*/
class PHP5MapBuilderBuilder extends OMBuilder {
/**
* Gets the package for the map builder classes.
* @return string
*/
public function getPackage()
{
return parent::getPackage() . '.map';
}
/**
* Returns the name of the current class being built.
* @return string
*/
public function getClassname()
{
return $this->getTable()->getPhpName() . 'MapBuilder';
}
/**
* Adds the include() statements for files that this class depends on or utilizes.
* @param string &$script The script will be modified in this method.
*/
protected function addIncludes(&$script)
{
$script .= "
require_once 'propel/map/MapBuilder.php';
include_once 'creole/CreoleTypes.php';
";
} // addIncludes()
/**
* Adds class phpdoc comment and openning of class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassOpen(&$script)
{
$table = $this->getTable();
$script .= "
/**
* This class adds structure of '".$table->getName()."' table to '".$table->getDatabase()->getName()."' DatabaseMap object.
*
*";
if ($this->getBuildProperty('addTimeStamp')) {
$now = strftime('%c');
$script .= "
* This class was autogenerated by Propel on:
*
* $now
*";
}
$script .= "
*
* These statically-built map classes are used by Propel to do runtime db structure discovery.
* For example, the createSelectSql() method checks the type of a given column used in an
* ORDER BY clause to know whether it needs to apply SQL to make the ORDER BY case-insensitive
* (i.e. if it's a text column type).
*
* @package ".$this->getPackage()."
*/
class ".$this->getClassname()." {
";
}
/**
* Specifies the methods that are added as part of the map builder class.
* This can be overridden by subclasses that wish to add more methods.
* @see ObjectBuilder::addClassBody()
*/
protected function addClassBody(&$script)
{
$this->addConstants($script);
$this->addAttributes($script);
$this->addIsBuilt($script);
$this->addGetDatabaseMap($script);
$this->addDoBuild($script);
}
/**
* Adds any constants needed for this MapBuilder class.
* @param string &$script The script will be modified in this method.
*/
protected function addConstants(&$script)
{
$script .= "
/**
* The (dot-path) name of this class
*/
const CLASS_NAME = '".$this->getClasspath()."';
";
}
/**
* Adds any attributes needed for this MapBuilder class.
* @param string &$script The script will be modified in this method.
*/
protected function addAttributes(&$script)
{
$script .= "
/**
* The database map.
*/
private \$dbMap;
";
}
/**
* Closes class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassClose(&$script)
{
$script .= "
} // " . $this->getClassname() . "
";
}
/**
* Adds the method that indicates whether this map has already been built.
* @param string &$script The script will be modified in this method.
*/
protected function addIsBuilt(&$script)
{
$script .= "
/**
* Tells us if this DatabaseMapBuilder is built so that we
* don't have to re-build it every time.
*
* @return boolean true if this DatabaseMapBuilder is built, false otherwise.
*/
public function isBuilt()
{
return (\$this->dbMap !== null);
}
";
}
/**
* Adds the DatabaseMap accessor method.
* @param string &$script The script will be modified in this method.
*/
protected function addGetDatabaseMap(&$script)
{
$script .= "
/**
* Gets the databasemap this map builder built.
*
* @return the databasemap
*/
public function getDatabaseMap()
{
return \$this->dbMap;
}
";
}
/**
* Adds the main doBuild() method to the map builder class.
* @param string &$script The script will be modified in this method.
*/
protected function addDoBuild(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
$script .= "
/**
* The doBuild() method builds the DatabaseMap
*
* @return void
* @throws PropelException
*/
public function doBuild()
{
\$this->dbMap = Propel::getDatabaseMap('".$table->getDatabase()->getName()."');
\$tMap = \$this->dbMap->addTable('".$table->getName()."');
\$tMap->setPhpName('".$table->getPhpName()."');
";
if ($table->getIdMethod() == "native") {
$script .= "
\$tMap->setUseIdGenerator(true);
";
} else {
$script .= "
\$tMap->setUseIdGenerator(false);
";
}
if ($table->getIdMethodParameters()) {
$params = $table->getIdMethodParameters();
$imp = $params[0];
$script .= "
\$tMap->setPrimaryKeyMethodInfo('".$imp->getValue()."');
";
} elseif ($table->getIdMethod() == "native" && ($platform->getNativeIdMethod() == Platform::SEQUENCE)) {
$script .= "
\$tMap->setPrimaryKeyMethodInfo('".$table->getSequenceName()."');
";
} elseif ($table->getIdMethod() == "native" && ($platform->getNativeIdMethod() == Platform::SEQUENCE)) {
$script .= "
\$tMap->setPrimaryKeyMethodInfo('".$table->getName()."');
";
}
// Add columns to map
foreach ($table->getColumns() as $col) {
$tfc=$table->getPhpName();
$cfc=$col->getPhpName();
$cup=strtoupper($col->getName());
if (!$col->getSize()) {
$size = "null";
} else {
$size = $col->getSize();
}
if($col->isPrimaryKey()) {
if($col->isForeignKey()) {
$script .= "
\$tMap->addForeignPrimaryKey('$cup', '$cfc', '".$col->getPhpType()."' , CreoleTypes::".$col->getType().", '".$col->getRelatedTableName()."', '".strtoupper($col->getRelatedColumnName())."', ".($col->isNotNull() ? 'true' : 'false').", ".$size.");
";
} else {
$script .= "
\$tMap->addPrimaryKey('$cup', '$cfc', '".$col->getPhpType()."', CreoleTypes::".$col->getType().", ".var_export($col->isNotNull(), true).", ".$size.");
";
}
} else {
if($col->isForeignKey()) {
$script .= "
\$tMap->addForeignKey('$cup', '$cfc', '".$col->getPhpType()."', CreoleTypes::".$col->getType().", '".$col->getRelatedTableName()."', '".strtoupper($col->getRelatedColumnName())."', ".($col->isNotNull() ? 'true' : 'false').", ".$size.");
";
} else {
$script .= "
\$tMap->addColumn('$cup', '$cfc', '".$col->getPhpType()."', CreoleTypes::".$col->getType().", ".var_export($col->isNotNull(), true).", ".$size.");
";
}
} // if col-is prim key
} // foreach
foreach($table->getValidators() as $val) {
$col = $val->getColumn();
$cup = strtoupper($col->getName());
foreach($val->getRules() as $rule) {
if ($val->getTranslate() !== Validator::TRANSLATE_NONE) {
$script .= "
\$tMap->addValidator('$cup', '".$rule->getName()."', '".$rule->getClass()."', '".$rule->getValue()."', ".$val->getTranslate()."('".str_replace("'", "\'", $rule->getMessage())."'));
";
} else {
$script .= "
\$tMap->addValidator('$cup', '".$rule->getName()."', '".$rule->getClass()."', '".$rule->getValue()."', '".str_replace("'", "\'", $rule->getMessage())."');
";
} // if ($rule->getTranslation() ...
} // foreach rule
} // foreach validator
$script .= "
} // doBuild()
";
}
} // PHP5ExtensionPeerBuilder

View File

@ -0,0 +1,209 @@
<?php
/*
* $Id: PHP5MultiExtendObjectBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/ObjectBuilder.php';
/**
* Generates the empty PHP5 stub object class for use with inheritance in the user object model (OM).
*
* This class produces the empty stub class that can be customized with application
* business logic, custom behavior, etc.
*
* This class replaces the MultiExtendObject.tpl, with the intent of being easier for users
* to customize (through extending & overriding).
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.om.php5
*/
class PHP5MultiExtendObjectBuilder extends ObjectBuilder {
/**
* The current child "object" we are operating on.
*/
private $child;
/**
* Returns the name of the current class being built.
* @return string
*/
public function getClassname()
{
return $this->getChild()->getClassName();
}
/**
* Override method to return child package, if specified.
* @return string
*/
public function getPackage()
{
return ($this->child->getPackage() ? $this->child->getPackage() : parent::getPackage());
}
/**
* Set the child object that we're operating on currrently.
* @param $child Inheritance
*/
public function setChild(Inheritance $child)
{
$this->child = $child;
}
/**
* Returns the child object we're operating on currently.
* @return Inheritance
* @throws BuildException - if child was not set.
*/
public function getChild()
{
if (!$this->child) {
throw new BuildException("The PHP5MultiExtendObjectBuilder needs to be told which child class to build (via setChild() method) before it can build the stub class.");
}
return $this->child;
}
/**
* Returns classpath to parent class.
* @return string
*/
protected function getParentClasspath()
{
if ($this->getChild()->getAncestor()) {
return $this->getChild()->getAncestor();
} else {
return $this->getObjectBuilder()->getClasspath();
}
}
/**
* Returns classname of parent class.
* @return string
*/
protected function getParentClassname()
{
return ClassTools::classname($this->getParentClasspath());
}
/**
* Gets the file path to the parent class.
* @return string
*/
protected function getParentClassFilePath()
{
return $this->getFilePath($this->getParentClasspath());
}
/**
* Adds the include() statements for files that this class depends on or utilizes.
* @param string &$script The script will be modified in this method.
*/
protected function addIncludes(&$script)
{
$script .= "
require_once '".$this->getParentClassFilePath()."';
";
$script .= "
require_once '".$this->getObjectBuilder()->getClassFilePath()."';
";
} // addIncludes()
/**
* Adds class phpdoc comment and openning of class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassOpen(&$script)
{
$table = $this->getTable();
$tableName = $table->getName();
$tableDesc = $table->getDescription();
$baseClassname = $this->getObjectBuilder()->getClassname();
$script .= "
/**
* Skeleton subclass for representing a row from one of the subclasses of the '$tableName' table.
*
* $tableDesc
*";
if ($this->getBuildProperty('addTimeStamp')) {
$now = strftime('%c');
$script .= "
* This class was autogenerated by Propel on:
*
* $now
*";
}
$script .= "
* You should add additional methods to this class to meet the
* application requirements. This class will only be generated as
* long as it does not already exist in the output directory.
*
* @package ".$this->getPackage()."
*/
class ".$this->getClassname()." extends ".$this->getParentClassname()." {
";
}
/**
* Specifies the methods that are added as part of the stub object class.
*
* By default there are no methods for the empty stub classes; override this method
* if you want to change that behavior.
*
* @see ObjectBuilder::addClassBody()
*/
protected function addClassBody(&$script)
{
$child = $this->getChild();
$col = $child->getColumn();
$cfc = $col->getPhpName();
$const = "CLASSKEY_".strtoupper($child->getKey());
$script .= "
/**
* Constructs a new ".$this->getChild()->getClassName()." class, setting the ".$col->getName()." column to ".$this->getPeerClassname()."::$const.
*/
public function __construct()
{
";
$script .= "
\$this->set$cfc(".$this->getPeerClassname()."::CLASSKEY_".strtoupper($child->getKey()).");
}
";
}
/**
* Closes class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassClose(&$script)
{
$script .= "
} // " . $this->getClassname() . "
";
}
} // PHP5ExtensionObjectBuilder

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,774 @@
<?php
/*
* $Id: PHP5NodePeerBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/PeerBuilder.php';
/**
* Generates a PHP5 tree node Peer class for user object model (OM).
*
* This class produces the base tree node object class (e.g. BaseMyTable) which contains all
* the custom-built accessor and setter methods.
*
* This class replaces the Node.tpl, with the intent of being easier for users
* to customize (through extending & overriding).
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.om.php5
*/
class PHP5NodePeerBuilder extends PeerBuilder {
/**
* Gets the package for the [base] object classes.
* @return string
*/
public function getPackage()
{
return parent::getPackage() . ".om";
}
/**
* Returns the name of the current class being built.
* @return string
*/
public function getClassname()
{
return $this->getBuildProperty('basePrefix') . $this->getStubNodePeerBuilder()->getClassname();
}
/**
* Adds the include() statements for files that this class depends on or utilizes.
* @param string &$script The script will be modified in this method.
*/
protected function addIncludes(&$script)
{
$script .= "
require_once '".$this->getStubObjectBuilder()->getClassFilePath()."';
require_once '".$this->getStubNodeBuilder()->getClassFilePath()."';
";
} // addIncludes()
/**
* Adds class phpdoc comment and openning of class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassOpen(&$script)
{
$table = $this->getTable();
$tableName = $table->getName();
$tableDesc = $table->getDescription();
$script .= "
/**
* Base static class for performing query operations on the tree contained by the '$tableName' table.
*
* $tableDesc
*";
if ($this->getBuildProperty('addTimeStamp')) {
$now = strftime('%c');
$script .= "
* This class was autogenerated by Propel on:
*
* $now
*";
}
$script .= "
* @package ".$this->getPackage()."
*/
abstract class ".$this->getClassname()." {
";
}
/**
* Specifies the methods that are added as part of the basic OM class.
* This can be overridden by subclasses that wish to add more methods.
* @see ObjectBuilder::addClassBody()
*/
protected function addClassBody(&$script)
{
$table = $this->getTable();
// FIXME
// - Probably the build needs to be customized for supporting
// tables that are "aliases". -- definitely a fringe usecase, though.
$this->addConstants($script);
$this->addIsCodeBase($script);
$this->addRetrieveMethods($script);
$this->addCreateNewRootNode($script);
$this->addInsertNewRootNode($script);
$this->addMoveNodeSubTree($script);
$this->addDeleteNodeSubTree($script);
$this->addBuildFamilyCriteria($script);
$this->addBuildTree($script);
$this->addPopulateNodes($script);
}
/**
* Closes class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassClose(&$script)
{
$script .= "
} // " . $this->getClassname() . "
";
}
protected function addConstants(&$script)
{
$table = $this->getTable();
$npath_colname = '';
$npath_phpname = '';
$npath_len = 0;
$npath_sep = '';
foreach ($table->getColumns() as $col) {
if ($col->isNodeKey()) {
$npath_colname = $table->getName() . '.' . strtoupper($col->getName());
$npath_phpname = $col->getPhpName();
$npath_len = $col->getSize();
$npath_sep = $col->getNodeKeySep();
break;
}
}
$script .= "
const NPATH_COLNAME = '$npath_colname';
const NPATH_PHPNAME = '$npath_phpname';
const NPATH_SEP = '$npath_sep';
const NPATH_LEN = $npath_len;
";
}
protected function addIsCodeBase(&$script)
{
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$script .= "
/**
* Temp function for CodeBase hacks that will go away.
*/
public static function isCodeBase(\$con = null)
{
if (\$con === null)
\$con = Propel::getConnection($peerClassname::DATABASE_NAME);
return (get_class(\$con) == 'ODBCConnection' &&
get_class(\$con->getAdapter()) == 'CodeBaseAdapter');
}
";
}
protected function addCreateNewRootNode(&$script)
{
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$objectClassname = $this->getStubObjectBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$nodeObjectClassname = $this->getStubNodeBuilder()->getClassname();
$script .= "
/**
* Create a new Node at the top of tree. This method will destroy any
* existing root node (along with its children).
*
* Use at your own risk!
*
* @param $objectClassname Object wrapped by new node.
* @param Connection Connection to use.
* @return $nodeObjectClassname
* @throws PropelException
*/
public static function createNewRootNode(\$obj, \$con = null)
{
if (\$con === null)
\$con = Propel::getConnection($peerClassname::DATABASE_NAME);
try {
\$con->begin();
self::deleteNodeSubTree('1', \$con);
\$setNodePath = 'set' . self::NPATH_PHPNAME;
\$obj->\$setNodePath('1');
\$obj->save(\$con);
\$con->commit();
} catch (PropelException \$e) {
\$con->rollback();
throw \$e;
}
return new $nodeObjectClassname(\$obj);
}
";
}
protected function addInsertNewRootNode(&$script)
{
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$objectClassname = $this->getStubObjectBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$nodeObjectClassname = $this->getStubNodeBuilder()->getClassname();
$script .= "
/**
* Inserts a new Node at the top of tree. Any existing root node (along with
* its children) will be made a child of the new root node. This is a
* safer alternative to createNewRootNode().
*
* @param $objectClassname Object wrapped by new node.
* @param Connection Connection to use.
* @return $nodeObjectClassname
* @throws PropelException
*/
public static function insertNewRootNode(\$obj, \$con = null)
{
if (\$con === null)
\$con = Propel::getConnection($peerClassname::DATABASE_NAME);
try {
\$con->begin();
// Move root tree to an invalid node path.
$nodePeerClassname::moveNodeSubTree('1', '0', \$con);
\$setNodePath = 'set' . self::NPATH_PHPNAME;
// Insert the new root node.
\$obj->\$setNodePath('1');
\$obj->save(\$con);
// Move the old root tree as a child of the new root.
$nodePeerClassname::moveNodeSubTree('0', '1' . self::NPATH_SEP . '1', \$con);
\$con->commit();
} catch (PropelException \$e) {
\$con->rollback();
throw \$e;
}
return new $nodeObjectClassname(\$obj);
}
";
}
/**
* Adds the methods for retrieving nodes.
*/
protected function addRetrieveMethods(&$script)
{
$this->addRetrieveNodes($script);
$this->addRetrieveNodeByPK($script);
$this->addRetrieveNodeByNP($script);
$this->addRetrieveRootNode($script);
}
protected function addRetrieveNodes(&$script)
{
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$script .= "
/**
* Retrieves an array of tree nodes based on specified criteria. Optionally
* includes all parent and/or child nodes of the matching nodes.
*
* @param Criteria Criteria to use.
* @param boolean True if ancestors should also be retrieved.
* @param boolean True if descendants should also be retrieved.
* @param Connection Connection to use.
* @return array Array of root nodes.
*/
public static function retrieveNodes(\$criteria, \$ancestors = false, \$descendants = false, \$con = null)
{
\$criteria = $nodePeerClassname::buildFamilyCriteria(\$criteria, \$ancestors, \$descendants);
\$rs = ".$this->getStubPeerBuilder()->getClassname()."::doSelectRS(\$criteria, \$con);
return self::populateNodes(\$rs, \$criteria);
}
";
}
protected function addRetrieveNodeByPK(&$script)
{
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$objectClassname = $this->getStubObjectBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$nodeObjectClassname = $this->getStubNodeBuilder()->getClassname();
$script .= "
/**
* Retrieves a tree node based on a primary key. Optionally includes all
* parent and/or child nodes of the matching node.
*
* @param mixed $objectClassname primary key (array for composite keys)
* @param boolean True if ancestors should also be retrieved.
* @param boolean True if descendants should also be retrieved.
* @param Connection Connection to use.
* @return $nodeObjectClassname
*/
public static function retrieveNodeByPK(\$pk, \$ancestors = false, \$descendants = false, \$con = null)
{
throw new PropelException('retrieveNodeByPK() not implemented yet.');
}
";
}
protected function addRetrieveNodeByNP(&$script)
{
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$objectClassname = $this->getStubObjectBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$nodeObjectClassname = $this->getStubNodeBuilder()->getClassname();
$script .= "
/**
* Retrieves a tree node based on a node path. Optionally includes all
* parent and/or child nodes of the matching node.
*
* @param string Node path to retrieve.
* @param boolean True if ancestors should also be retrieved.
* @param boolean True if descendants should also be retrieved.
* @param Connection Connection to use.
* @return $objectClassname
*/
public static function retrieveNodeByNP(\$np, \$ancestors = false, \$descendants = false, \$con = null)
{
\$criteria = new Criteria($peerClassname::DATABASE_NAME);
\$criteria->add(self::NPATH_COLNAME, \$np, Criteria::EQUAL);
\$criteria = self::buildFamilyCriteria(\$criteria, \$ancestors, \$descendants);
\$rs = $peerClassname::doSelectRS(\$criteria, \$con);
\$nodes = self::populateNodes(\$rs, \$criteria);
return (count(\$nodes) == 1 ? \$nodes[0] : null);
}
";
}
protected function addRetrieveRootNode(&$script)
{
$script .= "
/**
* Retrieves the root node.
*
* @param string Node path to retrieve.
* @param boolean True if descendants should also be retrieved.
* @param Connection Connection to use.
* @return ".$this->getStubNodeBuilder()->getClassname()."
*/
public static function retrieveRootNode(\$descendants = false, \$con = null)
{
return self::retrieveNodeByNP('1', false, \$descendants, \$con);
}
";
}
protected function addMoveNodeSubTree(&$script)
{
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$objectClassname = $this->getStubObjectBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$nodeObjectClassname = $this->getStubNodeBuilder()->getClassname();
$script .= "
/**
* Moves the node subtree at srcpath to the dstpath. This method is intended
* for internal use by the BaseNode object. Note that it does not check for
* preexisting nodes at the dstpath. It also does not update the node path
* of any Node objects that might currently be in memory.
*
* Use at your own risk!
*
* @param string Source node path to move (root of the src subtree).
* @param string Destination node path to move to (root of the dst subtree).
* @param Connection Connection to use.
* @return void
* @throws PropelException
* @todo This is currently broken for simulated 'onCascadeDelete's.
* @todo Need to abstract the SQL better. The CONCAT sql function doesn't
* seem to be standardized (i.e. mssql), so maybe it needs to be moved
* to DBAdapter.
*/
public static function moveNodeSubTree(\$srcPath, \$dstPath, \$con = null)
{
if (substr(\$dstPath, 0, strlen(\$srcPath)) == \$srcPath)
throw new PropelException('Cannot move a node subtree within itself.');
if (\$con === null)
\$con = Propel::getConnection($peerClassname::DATABASE_NAME);
/**
* Example:
* UPDATE table
* SET npath = CONCAT('1.3', SUBSTRING(npath, 6, 74))
* WHERE npath = '1.2.2' OR npath LIKE '1.2.2.%'
*/
\$npath = $nodePeerClassname::NPATH_COLNAME;
//the following dot isn`t mean`t a nodeKeySeperator
\$setcol = substr(\$npath, strpos(\$npath, '.')+1);
\$setcollen = $nodePeerClassname::NPATH_LEN;
\$db = Propel::getDb($peerClassname::DATABASE_NAME);
// <hack>
if ($nodePeerClassname::isCodeBase(\$con))
{
// This is a hack to get CodeBase working. It will eventually be removed.
// It is a workaround for the following CodeBase bug:
// -Prepared statement parameters cannot be embedded in SQL functions (i.e. CONCAT)
\$sql = \"UPDATE \" . $peerClassname::TABLE_NAME . \" \" .
\"SET \$setcol=\" . \$db->concatString(\"'\$dstPath'\", \$db->subString(\$npath, strlen(\$srcPath)+1, \$setcollen)) . \" \" .
\"WHERE \$npath = '\$srcPath' OR \$npath LIKE '\" . \$srcPath . $nodePeerClassname::NPATH_SEP . \"%'\";
\$con->executeUpdate(\$sql);
}
else
{
// </hack>
\$sql = \"UPDATE \" . $peerClassname::TABLE_NAME . \" \" .
\"SET \$setcol=\" . \$db->concatString('?', \$db->subString(\$npath, '?', '?')) . \" \" .
\"WHERE \$npath = ? OR \$npath LIKE ?\";
\$stmt = \$con->prepareStatement(\$sql);
\$stmt->setString(1, \$dstPath);
\$stmt->setInt(2, strlen(\$srcPath)+1);
\$stmt->setInt(3, \$setcollen);
\$stmt->setString(4, \$srcPath);
\$stmt->setString(5, \$srcPath . $nodePeerClassname::NPATH_SEP . '%');
\$stmt->executeUpdate();
// <hack>
}
// </hack>
}
";
}
protected function addDeleteNodeSubTree(&$script)
{
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$objectClassname = $this->getStubObjectBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$nodeObjectClassname = $this->getStubNodeBuilder()->getClassname();
$script .= "
/**
* Deletes the node subtree at the specified node path from the database.
*
* @param string Node path to delete
* @param Connection Connection to use.
* @return void
* @throws PropelException
* @todo This is currently broken for simulated 'onCascadeDelete's.
*/
public static function deleteNodeSubTree(\$nodePath, \$con = null)
{
if (\$con === null)
\$con = Propel::getConnection($peerClassname::DATABASE_NAME);
/**
* DELETE FROM table
* WHERE npath = '1.2.2' OR npath LIKE '1.2.2.%'
*/
\$criteria = new Criteria($peerClassname::DATABASE_NAME);
\$criteria->add($nodePeerClassname::NPATH_COLNAME, \$nodePath, Criteria::EQUAL);
\$criteria->addOr($nodePeerClassname::NPATH_COLNAME, \$nodePath . self::NPATH_SEP . '%', Criteria::LIKE);
// For now, we call BasePeer directly since $peerClassname tries to
// do a cascade delete.
// $peerClassname::doDelete(\$criteria, \$con);
BasePeer::doDelete(\$criteria, \$con);
}
";
}
protected function addBuildFamilyCriteria(&$script)
{
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$objectClassname = $this->getStubObjectBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$nodeObjectClassname = $this->getStubNodeBuilder()->getClassname();
$script .= "
/**
* Builds the criteria needed to retrieve node ancestors and/or descendants.
*
* @param Criteria Criteria to start with
* @param boolean True if ancestors should be retrieved.
* @param boolean True if descendants should be retrieved.
* @return Criteria
*/
public static function buildFamilyCriteria(\$criteria, \$ancestors = false, \$descendants = false)
{
/*
Example SQL to retrieve nodepath '1.2.3' with both ancestors and descendants:
SELECT L.NPATH, L.LABEL, test.NPATH, UCASE(L.NPATH)
FROM test L, test
WHERE test.NPATH='1.2.3' AND
(L.NPATH=SUBSTRING(test.NPATH, 1, LENGTH(L.NPATH)) OR
test.NPATH=SUBSTRING(L.NPATH, 1, LENGTH(test.NPATH)))
ORDER BY UCASE(L.NPATH) ASC
*/
if (\$criteria === null)
\$criteria = new Criteria($peerClassname::DATABASE_NAME);
if (!\$criteria->getSelectColumns())
$peerClassname::addSelectColumns(\$criteria);
\$db = Propel::getDb(\$criteria->getDbName());
if ((\$ancestors || \$descendants) && \$criteria->size())
{
// If we are retrieving ancestors/descendants, we need to do a
// self-join to locate them. The exception to this is if no search
// criteria is specified. In this case we're retrieving all nodes
// anyway, so there is no need to do a self-join.
// The left-side of the self-join will contain the columns we'll
// use to build node objects (target node records along with their
// ancestors and/or descendants). The right-side of the join will
// contain the target node records specified by the initial criteria.
// These are used to match the appropriate ancestor/descendant on
// the left.
// Specify an alias for the left-side table to use.
\$criteria->addAlias('L', $peerClassname::TABLE_NAME);
// Make sure we have select columns to begin with.
if (!\$criteria->getSelectColumns())
$peerClassname::addSelectColumns(\$criteria);
// Replace any existing columns for the right-side table with the
// left-side alias.
\$selectColumns = \$criteria->getSelectColumns();
\$criteria->clearSelectColumns();
foreach (\$selectColumns as \$colName)
\$criteria->addSelectColumn(str_replace($peerClassname::TABLE_NAME, 'L', \$colName));
\$a = null;
\$d = null;
\$npathL = $peerClassname::alias('L', $nodePeerClassname::NPATH_COLNAME);
\$npathR = $nodePeerClassname::NPATH_COLNAME;
\$npath_len = $nodePeerClassname::NPATH_LEN;
if (\$ancestors)
{
// For ancestors, match left-side node paths which are contained
// by right-side node paths.
\$a = \$criteria->getNewCriterion(\$npathL,
\"\$npathL=\" . \$db->subString(\$npathR, 1, \$db->strLength(\$npathL), \$npath_len),
Criteria::CUSTOM);
}
if (\$descendants)
{
// For descendants, match left-side node paths which contain
// right-side node paths.
\$d = \$criteria->getNewCriterion(\$npathR,
\"\$npathR=\" . \$db->subString(\$npathL, 1, \$db->strLength(\$npathR), \$npath_len),
Criteria::CUSTOM);
}
if (\$a)
{
if (\$d) \$a->addOr(\$d);
\$criteria->addAnd(\$a);
}
else if (\$d)
{
\$criteria->addAnd(\$d);
}
// Add the target node path column. This is used by populateNodes().
\$criteria->addSelectColumn(\$npathR);
// Sort by node path to speed up tree construction in populateNodes()
\$criteria->addAsColumn('npathlen', \$db->strLength(\$npathL));
\$criteria->addAscendingOrderByColumn('npathlen');
\$criteria->addAscendingOrderByColumn(\$npathL);
}
else
{
// Add the target node path column. This is used by populateNodes().
\$criteria->addSelectColumn($nodePeerClassname::NPATH_COLNAME);
// Sort by node path to speed up tree construction in populateNodes()
\$criteria->addAsColumn('npathlen', \$db->strLength($nodePeerClassname::NPATH_COLNAME));
\$criteria->addAscendingOrderByColumn('npathlen');
\$criteria->addAscendingOrderByColumn($nodePeerClassname::NPATH_COLNAME);
}
return \$criteria;
}
";
}
protected function addBuildTree(&$script)
{
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$objectClassname = $this->getStubObjectBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$nodeObjectClassname = $this->getStubNodeBuilder()->getClassname();
$script .= "
/**
* This method reconstructs as much of the tree structure as possible from
* the given array of objects. Depending on how you execute your query, it
* is possible for the ResultSet to contain multiple tree fragments (i.e.
* subtrees). The array returned by this method will contain one entry
* for each subtree root node it finds. The remaining subtree nodes are
* accessible from the $nodeObjectClassname methods of the
* subtree root nodes.
*
* @param array Array of $nodeObjectClassname objects
* @return array Array of $nodeObjectClassname objects
*/
public static function buildTree(\$nodes)
{
// Subtree root nodes to return
\$rootNodes = array();
// Build the tree relations
foreach (\$nodes as \$node)
{
\$sep = strrpos(\$node->getNodePath(), $nodePeerClassname::NPATH_SEP);
\$parentPath = (\$sep !== false ? substr(\$node->getNodePath(), 0, \$sep) : '');
\$parentNode = null;
// Scan other nodes for parent.
foreach (\$nodes as \$pnode)
{
if (\$pnode->getNodePath() === \$parentPath)
{
\$parentNode = \$pnode;
break;
}
}
// If parent was found, attach as child, otherwise its a subtree root
if (\$parentNode)
\$parentNode->attachChildNode(\$node);
else
\$rootNodes[] = \$node;
}
return \$rootNodes;
}
";
}
protected function addPopulateNodes(&$script)
{
$table = $this->getTable();
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$objectClassname = $this->getStubObjectBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$nodeObjectClassname = $this->getStubNodeBuilder()->getClassname();
$script .= "
/**
* Populates the $objectClassname objects from the
* specified ResultSet, wraps them in $nodeObjectClassname
* objects and build the appropriate node relationships.
* The array returned by this method will only include the initial targets
* of the query, even if ancestors/descendants were also requested.
* The ancestors/descendants will be cached in memory and are accessible via
* the getNode() methods.
*
* @param ResultSet
* @param Criteria
* @return array Array of $nodeObjectClassname objects.
*/
public static function populateNodes(\$rs, \$criteria)
{
\$nodes = array();
\$targets = array();
\$targetfld = count(\$criteria->getSelectColumns());
";
if (!$table->getChildrenColumn()) {
$script .= "
// set the class once to avoid overhead in the loop
\$cls = Propel::import($peerClassname::getOMClass());
";
}
$script .= "
// populate the object(s)
while(\$rs->next())
{
if (!isset(\$nodes[\$rs->getString(1)]))
{
";
if ($table->getChildrenColumn()) {
$script .= "
// class must be set each time from the record row
$cls = Propel::import($peerClassname::getOMClass($rs, 1));
";
}
$script .= "
\$obj = new \$cls();
\$obj->hydrate(\$rs);
\$nodes[\$rs->getString(1)] = new $nodeObjectClassname(\$obj);
}
\$node = \$nodes[\$rs->getString(1)];
if (\$node->getNodePath() === \$rs->getString(\$targetfld))
\$targets[\$node->getNodePath()] = \$node;
}
$nodePeerClassname::buildTree(\$nodes);
return array_values(\$targets);
}
";
}
} // PHP5NodePeerBuilder

View File

@ -0,0 +1,131 @@
<?php
/*
* $Id: DDLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/DataModelBuilder.php';
/**
* Baseclass for SQL DDL-building classes.
*
* DDL-building classes are those that build all the SQL DDL for a single table.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql
*/
abstract class DDLBuilder extends DataModelBuilder {
/**
* Builds the SQL for current table and returns it as a string.
*
* This is the main entry point and defines a basic structure that classes should follow.
* In most cases this method will not need to be overridden by subclasses.
*
* @return string The resulting SQL DDL.
*/
public function build()
{
$script = "";
$this->addTable($script);
$this->addIndices($script);
$this->addForeignKeys($script);
return $script;
}
/**
* Builds the DDL SQL for a Column object.
* @return string
*/
public function getColumnDDL(Column $col)
{
$platform = $this->getPlatform();
$domain = $col->getDomain();
$sb = "";
$sb .= $this->quoteIdentifier($col->getName()) . " ";
$sb .= $domain->getSqlType();
if ($platform->hasSize($domain->getSqlType())) {
$sb .= $domain->printSize();
}
$sb .= " ";
$sb .= $col->getDefaultSetting() . " ";
$sb .= $col->getNotNullString() . " ";
$sb .= $col->getAutoIncrementString();
return trim($sb);
}
/**
* Creates a delimiter-delimited string list of column names, quoted using quoteIdentifier().
* @param array Column[] or string[]
* @param string $delim The delimiter to use in separating the column names.
* @return string
*/
public function getColumnList($columns, $delim=',')
{
$list = array();
foreach($columns as $col) {
if ($col instanceof Column) {
$col = $col->getName();
}
$list[] = $this->quoteIdentifier($col);
}
return implode($delim, $list);
}
/**
* This function adds any _database_ start/initialization SQL.
* This is designed to be called for a database, not a specific table, hence it is static.
* @return string The DDL is returned as astring.
*/
public static function getDatabaseStartDDL()
{
return '';
}
/**
* This function adds any _database_ end/cleanup SQL.
* This is designed to be called for a database, not a specific table, hence it is static.
* @return string The DDL is returned as astring.
*/
public static function getDatabaseEndDDL()
{
return '';
}
/**
* Adds table definition.
* @param string &$script The script will be modified in this method.
*/
abstract protected function addTable(&$script);
/**
* Adds index definitions.
* @param string &$script The script will be modified in this method.
*/
abstract protected function addIndices(&$script);
/**
* Adds foreign key constraint definitions.
* @param string &$script The script will be modified in this method.
*/
abstract protected function addForeignKeys(&$script);
}

View File

@ -0,0 +1,215 @@
<?php
/*
* $Id: DataSQLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/DataModelBuilder.php';
/**
* Baseclass for SQL data dump SQL building classes.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql
*/
abstract class DataSQLBuilder extends DataModelBuilder {
/**
* The main method in this class, returns the SQL for INSERTing data into a row.
* @param DataRow $row The row to process.
* @return string
*/
public function buildRowSql(DataRow $row)
{
$sql = "";
$platform = $this->getPlatform();
$table = $this->getTable();
$sql .= "INSERT INTO ".$this->quoteIdentifier($this->getTable()->getName())." (";
// add column names to SQL
$colNames = array();
foreach ($row->getColumnValues() as $colValue) {
$colNames[] = $this->quoteIdentifier($colValue->getColumn()->getName());
}
$sql .= implode(',', $colNames);
$sql .= ") VALUES (";
$colVals = array();
foreach ($row->getColumnValues() as $colValue) {
$colVals[] = $this->getColumnValueSql($colValue);
}
$sql .= implode(',', $colVals);
$sql .= ");
";
return $sql;
}
/**
* Gets the propertly escaped (and quoted) value for a column.
* @param ColumnValue $colValue
* @return mixed The proper value to be added to the string.
*/
protected function getColumnValueSql(ColumnValue $colValue)
{
$column = $colValue->getColumn();
$creoleTypeString = PropelTypes::getCreoleType($column->getPropelType());
$creoleTypeCode = CreoleTypes::getCreoleCode($creoleTypeString);
$method = 'get' . CreoleTypes::getAffix($creoleTypeCode) . 'Sql';
return $this->$method($colValue->getValue());
}
/**
* Gets a representation of a binary value suitable for use in a SQL statement.
* Default behavior is true = 1, false = 0.
* @param boolean $value
* @return int
*/
protected function getBooleanSql($value)
{
return (int) $value;
}
/**
* Gets a representation of a BLOB/LONGVARBINARY value suitable for use in a SQL statement.
* @param mixed $blob Blob object or string data.
* @return string
*/
protected function getBlobSql($blob)
{
// they took magic __toString() out of PHP5.0.0; this sucks
if (is_object($blob)) {
return "'" . $this->escape($blob->__toString()) . "'";
} else {
return "'" . $this->escape($blob) . "'";
}
}
/**
* Gets a representation of a CLOB/LONGVARCHAR value suitable for use in a SQL statement.
* @param mixed $clob Clob object or string data.
* @return string
*/
protected function getClobSql($clob)
{
// they took magic __toString() out of PHP5.0.0; this sucks
if (is_object($clob)) {
return "'" . $this->escape($clob->__toString()) . "'";
} else {
return "'" . $this->escape($clob) . "'";
}
}
/**
* Gets a representation of a date value suitable for use in a SQL statement.
* @param string $value
* @return string
*/
protected function getDateSql($value)
{
return "'" . date('Y-m-d', strtotime($value)) . "'";
}
/**
* Gets a representation of a decimal value suitable for use in a SQL statement.
* @param double $value
* @return float
*/
protected function getDecimalSql($value)
{
return (float) $value;
}
/**
* Gets a representation of a double value suitable for use in a SQL statement.
* @param double $value
* @return double
*/
protected function getDoubleSql($value)
{
return (double) $value;
}
/**
* Gets a representation of a float value suitable for use in a SQL statement.
* @param float $value
* @return float
*/
protected function getFloatSql($value)
{
return (float) $value;
}
/**
* Gets a representation of an integer value suitable for use in a SQL statement.
* @param int $value
* @return int
*/
protected function getIntSql($value)
{
return (int) $value;
}
/**
* Gets a representation of a NULL value suitable for use in a SQL statement.
* @return null
*/
protected function getNullSql()
{
return 'NULL';
}
/**
* Gets a representation of a string value suitable for use in a SQL statement.
* @param string $value
* @return string
*/
protected function getStringSql($value)
{
return "'" . $this->getPlatform()->escapeText($value) . "'";
}
/**
* Gets a representation of a time value suitable for use in a SQL statement.
* @param string $value
* @return string
*/
protected function getTimeSql($paramIndex, $value)
{
return "'" . date('H:i:s', strtotime($value)) . "'";
}
/**
* Gets a representation of a timestamp value suitable for use in a SQL statement.
* @param string $value
* @return string
*/
function getTimestampSql($value)
{
return "'" . date('Y-m-d H:i:s', strtotime($value)) . "'";
}
}

View File

@ -0,0 +1,185 @@
<?php
/*
* $Id: MssqlDDLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DDLBuilder.php';
/**
* The SQL DDL-building class for MS SQL Server.
*
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.pgsql
*/
class MssqlDDLBuilder extends DDLBuilder {
private static $dropCount = 0;
/**
*
* @see parent::addDropStatement()
*/
protected function addDropStatements(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($table->getForeignKeys() as $fk) {
$script .= "
IF EXISTS (SELECT 1 FROM sysobjects WHERE type ='RI' AND name='".$fk->getName()."')
ALTER TABLE ".$this->quoteIdentifier($table->getName())." DROP CONSTRAINT ".$this->quoteIdentifier($fk->getName()).";
";
}
self::$dropCount++;
$script .= "
IF EXISTS (SELECT 1 FROM sysobjects WHERE type = 'U' AND name = '".$table->getName()."')
BEGIN
DECLARE @reftable_".self::$dropCount." nvarchar(60), @constraintname_".self::$dropCount." nvarchar(60)
DECLARE refcursor CURSOR FOR
select reftables.name tablename, cons.name constraintname
from sysobjects tables,
sysobjects reftables,
sysobjects cons,
sysreferences ref
where tables.id = ref.rkeyid
and cons.id = ref.constid
and reftables.id = ref.fkeyid
and tables.name = '".$table->getName()."'
OPEN refcursor
FETCH NEXT from refcursor into @reftable_".self::$dropCount.", @constraintname_".self::$dropCount."
while @@FETCH_STATUS = 0
BEGIN
exec ('alter table '+@reftable_".self::$dropCount."+' drop constraint '+@constraintname_".self::$dropCount.")
FETCH NEXT from refcursor into @reftable_".self::$dropCount.", @constraintname_".self::$dropCount."
END
CLOSE refcursor
DEALLOCATE refcursor
DROP TABLE ".$this->quoteIdentifier($table->getName())."
END
";
}
/**
* @see parent::addColumns()
*/
protected function addTable(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
$script .= "
/* ---------------------------------------------------------------------- */
/* ".$table->getName()." */
/* ---------------------------------------------------------------------- */
";
$this->addDropStatements($script);
$script .= "
CREATE TABLE ".$this->quoteIdentifier($table->getName())."
(
";
$lines = array();
foreach ($table->getColumns() as $col) {
$lines[] = $this->getColumnDDL($col);
}
if ($table->hasPrimaryKey()) {
$lines[] = "CONSTRAINT ".$this->quoteIdentifier($table->getName())."_PK PRIMARY KEY (".$this->getColumnList($table->getPrimaryKey()).")";
}
foreach ($table->getUnices() as $unique ) {
$lines[] = "UNIQUE (".$this->getColumnList($unique->getColumns()).")";
}
$sep = ",
";
$script .= implode($sep, $lines);
$script .= "
);
";
}
/**
* Adds CREATE INDEX statements for this table.
* @see parent::addIndices()
*/
protected function addIndices(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($table->getIndices() as $index) {
$script .= "
CREATE ";
if($index->getIsUnique()) {
$script .= "UNIQUE";
}
$script .= "INDEX ".$this->quoteIdentifier($index->getName())." ON ".$this->quoteIdentifier($table->getName())." (".$this->getColumnList($index->getColumns()).");
";
}
}
/**
*
* @see parent::addForeignKeys()
*/
protected function addForeignKeys(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($table->getForeignKeys() as $fk) {
$script .= "
BEGIN
ALTER TABLE ".$this->quoteIdentifier($table->getName())." ADD CONSTRAINT ".$this->quoteIdentifier($fk->getName())." FOREIGN KEY (".$this->getColumnList($fk->getLocalColumns()) .") REFERENCES ".$this->quoteIdentifier($fk->getForeignTableName())." (".$this->getColumnList($fk->getForeignColumns()).")";
if ($fk->hasOnUpdate()) {
if ($fk->getOnUpdate() == ForeignKey::SETNULL) { // there may be others that also won't work
// we have to skip this because it's unsupported.
$this->warn("MSSQL doesn't support the 'SET NULL' option for ON UPDATE (ignoring for ".$this->getColumnList($fk->getLocalColumns())." fk).");
} else {
$script .= " ON UPDATE ".$fk->getOnUpdate();
}
}
if ($fk->hasOnDelete()) {
if ($fk->getOnDelete() == ForeignKey::SETNULL) { // there may be others that also won't work
// we have to skip this because it's unsupported.
$this->warn("MSSQL doesn't support the 'SET NULL' option for ON DELETE (ignoring for ".$this->getColumnList($fk->getLocalColumns())." fk).");
} else {
$script .= " ON DELETE ".$fk->getOnDelete();
}
}
$script .= "
END
;
";
}
}
}

View File

@ -0,0 +1,48 @@
<?php
/*
* $Id: MssqlDataSQLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DataSQLBuilder.php';
/**
* MS SQL Server class for building data dump SQL.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.mssql
*/
class MssqlDataSQLBuilder extends DataSQLBuilder {
/**
*
* @param mixed $blob Blob object or string containing data.
* @return string
*/
protected function getBlobSql($blob)
{
// they took magic __toString() out of PHP5.0.0; this sucks
if (is_object($blob)) {
$blob = $blob->__toString();
}
$data = unpack("H*hex", $blob);
return '0x'.$data['hex']; // no surrounding quotes!
}
}

View File

@ -0,0 +1,299 @@
<?php
/*
* $Id: MysqlDDLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DDLBuilder.php';
/**
* DDL Builder class for MySQL.
*
* @author David Z<>lke
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.mysql
*/
class MysqlDDLBuilder extends DDLBuilder {
/**
* Returns some header SQL that disables foreign key checking.
* @return string DDL
*/
public static function getDatabaseStartDDL()
{
$ddl = "
# This is a fix for InnoDB in MySQL >= 4.1.x
# It \"suspends judgement\" for fkey relationships until are tables are set.
SET FOREIGN_KEY_CHECKS = 0;
";
return $ddl;
}
/**
* Returns some footer SQL that re-enables foreign key checking.
* @return string DDL
*/
public static function getDatabaseEndDDL()
{
$ddl = "
# This restores the fkey checks, after having unset them earlier
SET FOREIGN_KEY_CHECKS = 1;
";
return $ddl;
}
/**
*
* @see parent::addDropStatement()
*/
protected function addDropStatements(&$script)
{
$script .= "
DROP TABLE IF EXISTS ".$this->quoteIdentifier($this->getTable()->getName()).";
";
}
/**
* Builds the SQL for current table and returns it as a string.
*
* This is the main entry point and defines a basic structure that classes should follow.
* In most cases this method will not need to be overridden by subclasses.
*
* @return string The resulting SQL DDL.
*/
public function build()
{
$script = "";
$this->addTable($script);
return $script;
}
/**
*
* @see parent::addColumns()
*/
protected function addTable(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
$script .= "
#-----------------------------------------------------------------------------
#-- ".$table->getName()."
#-----------------------------------------------------------------------------
";
$this->addDropStatements($script);
$script .= "
CREATE TABLE ".$this->quoteIdentifier($table->getName())."
(
";
$lines = array();
foreach ($table->getColumns() as $col) {
$entry = $this->getColumnDDL($col);
if ($col->getDescription()) {
$entry .= " COMMENT '".$platform->escapeText($col->getDescription())."'";
}
$lines[] = $entry;
}
if ($table->hasPrimaryKey()) {
$lines[] = "PRIMARY KEY (".$this->getColumnList($table->getPrimaryKey()).")";
}
$this->addIndicesLines($lines);
$this->addForeignKeysLines($lines);
$sep = ",
";
$script .= implode($sep, $lines);
$script .= "
)";
$mysqlTableType = $this->getBuildProperty("mysqlTableType");
if (!$mysqlTableType) {
$vendorSpecific = $table->getVendorSpecificInfo();
if(isset($vendorSpecific['Type'])) {
$mysqlTableType = $vendorSpecific['Type'];
} else {
$mysqlTableType = 'MyISAM';
}
}
$script .= "Type=$mysqlTableType";
if($table->getDescription()) {
$script .= " COMMENT='".$platform->escapeText($table->getDescription())."'";
}
$script .= ";
";
}
/**
* Creates a comma-separated list of column names for the index.
* For MySQL unique indexes there is the option of specifying size, so we cannot simply use
* the getColumnsList() method.
* @param Index $index
* @return string
*/
private function getIndexColumnList(Index $index)
{
$platform = $this->getPlatform();
$cols = $index->getColumns();
$list = array();
foreach($cols as $col) {
$list[] = $this->quoteIdentifier($col) . ($index->hasColumnSize($col) ? '(' . $index->getColumnSize($col) . ')' : '');
}
return implode(', ', $list);
}
/**
* Adds indexes
*/
protected function addIndicesLines(&$lines)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($table->getUnices() as $unique) {
$lines[] = "UNIQUE KEY ".$this->quoteIdentifier($unique->getName())." (".$this->getIndexColumnList($unique).")";
}
foreach ($table->getIndices() as $index ) {
$vendor = $index->getVendorSpecificInfo();
$lines[] .= (($vendor && $vendor['Index_type'] == 'FULLTEXT') ? 'FULLTEXT ' : '') . "KEY " . $this->quoteIdentifier($index->getName()) . "(" . $this->getIndexColumnList($index) . ")";
}
}
/**
* Adds foreign key declarations & necessary indexes for mysql (if they don't exist already).
* @see parent::addForeignKeys()
*/
protected function addForeignKeysLines(&$lines)
{
$table = $this->getTable();
$platform = $this->getPlatform();
$_indices = array();
$_previousColumns = array();
// we're building an array of indices here which is smart about multi-column indices.
// for example, if we have to indices foo(ColA) and bar(ColB, ColC), we have actually three indices already defined:
// ColA, ColB+ColC, and ColB (but not ColC!). This is because of the way SQL multi-column indices work.
// we will later match found, defined foreign key and referenced column definitions against this array to know
// whether we should create a new index for mysql or not
foreach($table->getPrimaryKey() as $_primaryKeyColumn) {
// do the above for primary keys
$_previousColumns[] = $this->quoteIdentifier($_primaryKeyColumn->getName());
$_indices[] = implode(',', $_previousColumns);
}
$_tableIndices = array_merge($table->getIndices(), $table->getUnices());
foreach($_tableIndices as $_index) {
// same procedure, this time for unices and indices
$_previousColumns = array();
$_indexColumns = $_index->getColumns();
foreach($_indexColumns as $_indexColumn) {
$_previousColumns[] = $this->quoteIdentifier($_indexColumn);
$_indices[] = implode(',', $_previousColumns);
}
}
// we're determining which tables have foreign keys that point to this table, since MySQL needs an index on
// any column that is referenced by another table (yep, MySQL _is_ a PITA)
$counter = 0;
$allTables = $table->getDatabase()->getTables();
foreach($allTables as $_table) {
foreach($_table->getForeignKeys() as $_foreignKey) {
if($_foreignKey->getForeignTableName() == $table->getName()) {
if(!in_array($this->getColumnList($_foreignKey->getForeignColumns()), $_indices)) {
// no matching index defined in the schema, so we have to create one
$lines[] = "INDEX ".$this->quoteIdentifier("I_referenced_".$_foreignKey->getName()."_".(++$counter))." (" .$this->getColumnList($_foreignKey->getForeignColumns()).")";
}
}
}
}
foreach ($table->getForeignKeys() as $fk) {
$indexName = $this->quoteIdentifier(substr_replace($fk->getName(), 'FI_', strrpos($fk->getName(), 'FK_'), 3));
if(!in_array($this->getColumnList($fk->getLocalColumns()), $_indices)) {
// no matching index defined in the schema, so we have to create one. MySQL needs indices on any columns that serve as foreign keys. these are not auto-created prior to 4.1.2
$lines[] = "INDEX $indexName (".$this->getColumnList($fk->getLocalColumns()).")";
}
$str = "CONSTRAINT ".$this->quoteIdentifier($fk->getName())."
FOREIGN KEY (".$this->getColumnList($fk->getLocalColumns()).")
REFERENCES ".$this->quoteIdentifier($fk->getForeignTableName()) . " (".$this->getColumnList($fk->getForeignColumns()).")";
if ($fk->hasOnUpdate()) {
$str .= "
ON UPDATE ".$fk->getOnUpdate();
}
if ($fk->hasOnDelete()) {
$str .= "
ON DELETE ".$fk->getOnDelete();
}
$lines[] = $str;
}
}
/**
* Checks whether passed-in array of Column objects contains a column with specified name.
* @param array Column[] or string[]
* @param string $searchcol Column name to search for
*/
private function containsColname($columns, $searchcol)
{
foreach($columns as $col) {
if ($col instanceof Column) {
$col = $col->getName();
}
if ($col == $searchcol) {
return true;
}
}
return false;
}
/**
* Not used for MySQL since foreign keys are declared inside table declaration.
* @see addForeignKeysLines()
*/
protected function addForeignKeys(&$script)
{
}
/**
* Not used for MySQL since indexes are declared inside table declaration.
* @see addIndicesLines()
*/
protected function addIndices(&$script)
{
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
* $Id: MysqlDataSQLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DataSQLBuilder.php';
/**
* MySQL class for building data dump SQL.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.mysql
*/
class MysqlDataSQLBuilder extends DataSQLBuilder {
}

View File

@ -0,0 +1,33 @@
<?php
/*
* $Id: MysqliDDLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/mysql/MysqlDDLBuilder.php';
/**
* DDL Builder class for MySQL, specifically using new mysqli API.
*
* @author Hans Lellelid
* @package propel.engine.builder.sql.mysql
*/
class MysqliDDLBuilder extends MysqlDDLBuilder {
}

View File

@ -0,0 +1,33 @@
<?php
/*
* $Id: MysqliDataSQLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DataSQLBuilder.php';
/**
* MySQL class for building data dump SQL.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.mysql
*/
class MysqliDataSQLBuilder extends DataSQLBuilder {
}

View File

@ -0,0 +1,177 @@
<?php
/*
* $Id: OracleDDLBuilder.php 3754 2007-04-11 09:52:01Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DDLBuilder.php';
/**
* The SQL DDL-building class for Oracle.
*
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.pgsql
*/
class OracleDDLBuilder extends DDLBuilder {
/**
*
* @see parent::addDropStatement()
*/
protected function addDropStatements(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
$script .= "
DROP TABLE ".$this->quoteIdentifier($table->getName())." CASCADE CONSTRAINTS;
";
if ($table->getIdMethod() == "native") {
$script .= "
DROP SEQUENCE ".$this->quoteIdentifier($table->getSequenceName()).";
";
}
}
/**
*
* @see parent::addColumns()
*/
protected function addTable(&$script)
{
$table = $this->getTable();
$script .= "
/* -----------------------------------------------------------------------
".$table->getName()."
----------------------------------------------------------------------- */
";
$this->addDropStatements($script);
$script .= "
CREATE TABLE ".$this->quoteIdentifier($table->getName())."
(
";
$lines = array();
foreach ($table->getColumns() as $col) {
$lines[] = $this->getColumnDDL($col);
}
$sep = ",
";
$script .= implode($sep, $lines);
$script .= "
);
";
$this->addPrimaryKey($script);
$this->addIndices($script);
$this->addSequences($script);
}
/**
*
*
*/
protected function addPrimaryKey(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
$tableName = $table->getName();
$length = strlen($tableName);
if ($length > 27) {
$length = 27;
}
if ( is_array($table->getPrimaryKey()) && count($table->getPrimaryKey()) ) {
$script .= "
ALTER TABLE ".$this->quoteIdentifier($table->getName())."
ADD CONSTRAINT ".$this->quoteIdentifier(substr($tableName,0,$length)."_PK")."
PRIMARY KEY (";
$delim = "";
foreach ($table->getPrimaryKey() as $col) {
$script .= $delim . $this->quoteIdentifier($col->getName());
$delim = ",";
}
$script .= ");
";
}
}
/**
* Adds CREATE SEQUENCE statements for this table.
*
*/
protected function addSequences(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
if ($table->getIdMethod() == "native") {
$script .= "CREATE SEQUENCE ".$this->quoteIdentifier($table->getSequenceName())." INCREMENT BY 1 START WITH 1 NOMAXVALUE NOCYCLE NOCACHE ORDER;
";
}
}
/**
* Adds CREATE INDEX statements for this table.
* @see parent::addIndices()
*/
protected function addIndices(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($table->getIndices() as $index) {
$script .= "CREATE ";
if($index->getIsUnique()) {
$script .= "UNIQUE";
}
$script .= "INDEX ".$this->quoteIdentifier($index->getName()) ." ON ".$this->quoteIdentifier($table->getName())." (".$this->getColumnList($index->getColumns()).");
";
}
}
/**
*
* @see parent::addForeignKeys()
*/
protected function addForeignKeys(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($table->getForeignKeys() as $fk) {
$script .= "
ALTER TABLE ".$this->quoteIdentifier($table->getName())." ADD CONSTRAINT ".$this->quoteIdentifier($fk->getName())." FOREIGN KEY (".$this->getColumnList($fk->getLocalColumns()) .") REFERENCES ".$this->quoteIdentifier($fk->getForeignTableName())." (".$this->getColumnList($fk->getForeignColumns()).")";
if ($fk->hasOnUpdate()) {
$this->warn("ON UPDATE not yet implemented for Oracle builder.(ignoring for ".$this->getColumnList($fk->getLocalColumns())." fk).");
//$script .= " ON UPDATE ".$fk->getOnUpdate();
}
if ($fk->hasOnDelete()) {
$script .= " ON DELETE ".$fk->getOnDelete();
}
$script .= ";
";
}
}
}

View File

@ -0,0 +1,34 @@
<?php
/*
* $Id: OracleDataSQLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DataSQLBuilder.php';
/**
* Oracle class for building data dump SQL.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.oracle
*/
class OracleDataSQLBuilder extends DataSQLBuilder {
}

View File

@ -0,0 +1,248 @@
<?php
/*
* $Id: PgsqlDDLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DDLBuilder.php';
/**
* The SQL DDL-building class for PostgreSQL.
*
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.pgsql
*/
class PgsqlDDLBuilder extends DDLBuilder {
/**
* Array that keeps track of already
* added schema names
*
* @var Array of schema names
*/
protected static $addedSchemas = array();
/**
* Get the schema for the current table
*
* @author Markus Lervik <markus.lervik@necora.fi>
* @access protected
* @return schema name if table has one, else
* null
**/
protected function getSchema()
{
$table = $this->getTable();
$schema = $table->getVendorSpecificInfo();
if (!empty($schema) && isset($schema['schema'])) {
return $schema['schema'];
}
return null;
}
/**
* Add a schema to the generated SQL script
*
* @author Markus Lervik <markus.lervik@necora.fi>
* @access protected
* @return string with CREATE SCHEMA statement if
* applicable, else empty string
**/
protected function addSchema()
{
$schemaName = $this->getSchema();
if ($schemaName !== null) {
if (!in_array($schemaName, self::$addedSchemas)) {
$platform = $this->getPlatform();
self::$addedSchemas[] = $schemaName;
return "\nCREATE SCHEMA " . $this->quoteIdentifier($schemaName) . ";\n";
}
}
return '';
}
/**
*
* @see parent::addDropStatement()
*/
protected function addDropStatements(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
$script .= "
DROP TABLE ".$this->quoteIdentifier($table->getName())." CASCADE;
";
if ($table->getIdMethod() == "native") {
$script .= "
DROP SEQUENCE ".$this->quoteIdentifier(strtolower($table->getSequenceName())).";
";
}
}
/**
*
* @see parent::addColumns()
*/
protected function addTable(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
$script .= "
-----------------------------------------------------------------------------
-- ".$table->getName()."
-----------------------------------------------------------------------------
";
$script .= $this->addSchema();
$schemaName = $this->getSchema();
if ($schemaName !== null) {
$script .= "\nSET search_path TO " . $this->quoteIdentifier($schemaName) . ";\n";
}
$this->addDropStatements($script);
$this->addSequences($script);
$script .= "
CREATE TABLE ".$this->quoteIdentifier($table->getName())."
(
";
$lines = array();
foreach ($table->getColumns() as $col) {
$lines[] = $this->getColumnDDL($col);
}
if ($table->hasPrimaryKey()) {
$lines[] = "PRIMARY KEY (".$this->getColumnList($table->getPrimaryKey()).")";
}
foreach ($table->getUnices() as $unique ) {
$lines[] = "CONSTRAINT ".$this->quoteIdentifier($unique->getName())." UNIQUE (".$this->getColumnList($unique->getColumns()).")";
}
$sep = ",
";
$script .= implode($sep, $lines);
$script .= "
);
COMMENT ON TABLE ".$this->quoteIdentifier($table->getName())." IS '" . $platform->escapeText($table->getDescription())."';
";
$this->addColumnComments($script);
$script .= "\nSET search_path TO public;";
}
/**
* Adds comments for the columns.
*
*/
protected function addColumnComments(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($this->getTable()->getColumns() as $col) {
if( $col->getDescription() != '' ) {
$script .= "
COMMENT ON COLUMN ".$this->quoteIdentifier($table->getName()).".".$this->quoteIdentifier($col->getName())." IS '".$platform->escapeText($col->getDescription()) ."';
";
}
}
}
/**
* Adds CREATE SEQUENCE statements for this table.
*
*/
protected function addSequences(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
if ($table->getIdMethod() == "native") {
$script .= "
CREATE SEQUENCE ".$this->quoteIdentifier(strtolower($table->getSequenceName())).";
";
}
}
/**
* Adds CREATE INDEX statements for this table.
* @see parent::addIndices()
*/
protected function addIndices(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($table->getIndices() as $index) {
$script .= "
CREATE ";
if($index->getIsUnique()) {
$script .= "UNIQUE";
}
$script .= "INDEX ".$this->quoteIdentifier($index->getName())." ON ".$this->quoteIdentifier($table->getName())." (".$this->getColumnList($index->getColumns()).");
";
}
}
/**
*
* @see parent::addForeignKeys()
*/
protected function addForeignKeys(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($table->getForeignKeys() as $fk) {
$script .= "
ALTER TABLE ".$this->quoteIdentifier($table->getName())." ADD CONSTRAINT ".$this->quoteIdentifier($fk->getName())." FOREIGN KEY (".$this->getColumnList($fk->getLocalColumns()) .") REFERENCES ".$this->quoteIdentifier($fk->getForeignTableName())." (".$this->getColumnList($fk->getForeignColumns()).")";
if ($fk->hasOnUpdate()) {
$script .= " ON UPDATE ".$fk->getOnUpdate();
}
if ($fk->hasOnDelete()) {
$script .= " ON DELETE ".$fk->getOnDelete();
}
$script .= ";
";
}
}
}

View File

@ -0,0 +1,60 @@
<?php
/*
* $Id: PgsqlDataSQLBuilder.php 3754 2007-04-11 09:52:01Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DataSQLBuilder.php';
/**
* PostgreSQL class for building data dump SQL.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.pgsql
*/
class PgsqlDataSQLBuilder extends DataSQLBuilder {
/**
* Get SQL value to insert for Postgres BOOLEAN column.
* @param boolean $value
* @return string The representation of boolean for Postgres ('t' or 'f').
*/
protected function getBooleanSql($value)
{
if ($value === 'f' || $value === 'false' || $value === "0") {
$value = false;
}
return ($value ? "'t'" : "'f'");
}
/**
*
* @param mixed $blob Blob object or string containing data.
* @return string
*/
protected function getBlobSql($blob)
{
// they took magic __toString() out of PHP5.0.0; this sucks
if (is_object($blob)) {
$blob = $blob->__toString();
}
return "'" . pg_escape_bytea($blob) . "'";
}
}

View File

@ -0,0 +1,126 @@
<?php
/*
* $Id: SqliteDDLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DDLBuilder.php';
/**
* The SQL DDL-building class for SQLite.
*
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.pgsql
*/
class SqliteDDLBuilder extends DDLBuilder {
/**
*
* @see parent::addDropStatement()
*/
protected function addDropStatements(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
$script .= "
DROP TABLE ".$this->quoteIdentifier($table->getName()).";
";
}
/**
*
* @see parent::addColumns()
*/
protected function addTable(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
$script .= "
-----------------------------------------------------------------------------
-- ".$table->getName()."
-----------------------------------------------------------------------------
";
$this->addDropStatements($script);
$script .= "
CREATE TABLE ".$this->quoteIdentifier($table->getName())."
(
";
$lines = array();
foreach ($table->getColumns() as $col) {
$lines[] = $this->getColumnDDL($col);
}
foreach ($table->getUnices() as $unique ) {
$lines[] = "UNIQUE (".$this->getColumnList($unique->getColumns()).")";
}
$sep = ",
";
$script .= implode($sep, $lines);
$script .= "
);
";
}
/**
* Adds CREATE INDEX statements for this table.
* @see parent::addIndices()
*/
protected function addIndices(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($table->getIndices() as $index) {
$script .= "
CREATE ";
if($index->getIsUnique()) {
$script .= "UNIQUE";
}
$script .= "INDEX ".$this->quoteIdentifier($index->getName())." ON ".$this->quoteIdentifier($table->getName())." (".$this->getColumnList($index->getColumns()).");
";
}
}
/**
*
* @see parent::addForeignKeys()
*/
protected function addForeignKeys(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($table->getForeignKeys() as $fk) {
$script .= "
-- SQLite does not support foreign keys; this is just for reference
-- FOREIGN KEY (".$this->getColumnList($fk->getLocalColumns()).") REFERENCES ".$fk->getForeignTableName()." (".$this->getColumnList($fk->getForeignColumns()).")
";
}
}
}

View File

@ -0,0 +1,47 @@
<?php
/*
* $Id: SqliteDataSQLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DataSQLBuilder.php';
/**
* SQLite class for building data dump SQL.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.sqlite
*/
class SqliteDataSQLBuilder extends DataSQLBuilder {
/**
* Returns string processed by sqlite_udf_encode_binary() to ensure that binary contents will be handled correctly by sqlite.
* @param mixed $blob Blob or string
* @return string encoded text
*/
protected function getBlobSql($blob)
{
// they took magic __toString() out of PHP5.0.0; this sucks
if (is_object($blob)) {
$blob = $blob->__toString();
}
return "'" . sqlite_udf_encode_binary($blob) . "'";
}
}

View File

@ -0,0 +1,206 @@
<?php
/*
* $Id: AppData.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'propel/engine/EngineException.php';
include_once 'propel/engine/database/model/Database.php';
/**
* A class for holding application data structures.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Leon Messerschmidt <leon@opticode.co.za> (Torque)
* @author John McNally <jmcnally@collab.net> (Torque)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class AppData {
/**
* The list of databases for this application.
* @var array Database[]
*/
private $dbList = array();
/**
* The platform class for our database(s).
* @var string
*/
private $platform;
/**
* Name of the database. Only one database definition
* is allowed in one XML descriptor.
*/
private $name;
/**
* Flag to ensure that initialization is performed only once.
* @var boolean
*/
private $isInitialized = false;
/**
* Creates a new instance for the specified database type.
*
* @param Platform $platform The platform class to use for any databases added to this application model.
*/
public function __construct(Platform $platform)
{
$this->platform = $platform;
}
/**
* Set the name of the database.
*
* @param name of the database.
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Get the name of the database.
*
* @return String name
*/
public function getName()
{
return $this->name;
}
/**
* Get the short name of the database (without the '-schema' postfix).
*
* @return String name
*/
public function getShortName()
{
return str_replace("-schema", "", $name);
}
/**
* Return an array of all databases
*
* @return Array of Database objects
*/
public function getDatabases($doFinalInit = true)
{
// this is temporary until we'll have a clean solution
// for packaging datamodels/requiring schemas
if ($doFinalInit) {
$this->doFinalInitialization();
}
return $this->dbList;
}
/**
* Returns whether this application has multiple databases.
*
* @return boolean True if the application has multiple databases
*/
public function hasMultipleDatabases()
{
return (count($this->dbList) > 1);
}
/**
* Return the database with the specified name.
*
* @param name database name
* @return A Database object. If it does not exist it returns null
*/
public function getDatabase($name = null, $doFinalInit = true)
{
// this is temporary until we'll have a clean solution
// for packaging datamodels/requiring schemas
if ($doFinalInit) {
$this->doFinalInitialization();
}
if ($name === null) {
return $this->dbList[0];
}
for($i=0,$size=count($this->dbList); $i < $size; $i++) {
$db = $this->dbList[$i];
if ($db->getName() === $name) {
return $db;
}
}
return null;
}
/**
* Add a database to the list and sets the AppData property to this
* AppData
*
* @param db the database to add
*/
public function addDatabase($db)
{
if ($db instanceof Database) {
$db->setAppData($this);
if ($db->getPlatform() === null) {
$db->setPlatform($this->platform);
}
$this->dbList[] = $db;
return $db;
} else {
// XML attributes array / hash
$d = new Database();
$d->loadFromXML($db);
return $this->addDatabase($d); // calls self w/ different param type
}
}
/**
*
* @return void
*/
private function doFinalInitialization()
{
if (!$this->isInitialized) {
for($i=0, $size=count($this->dbList); $i < $size; $i++) {
$this->dbList[$i]->doFinalInitialization();
}
$this->isInitialized = true;
}
}
/**
* Creats a string representation of this AppData.
* The representation is given in xml format.
*
* @return string Representation in xml format
*/
public function toString()
{
$result = "<app-data>\n";
for ($i=0,$size=count($this->dbList); $i < $size; $i++) {
$result .= $this->dbList[$i]->toString();
}
$result .= "</app-data>";
return $result;
}
}

View File

@ -0,0 +1,921 @@
<?php
/*
* $Id: Column.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/database/model/XMLElement.php';
include_once 'propel/engine/EngineException.php';
include_once 'propel/engine/database/model/PropelTypes.php';
include_once 'propel/engine/database/model/Inheritance.php';
include_once 'propel/engine/database/model/Domain.php';
/**
* A Class for holding data about a column used in an Application.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Leon Messerschmidt <leon@opticode.co.za> (Torque)
* @author Jason van Zyl <jvanzyl@apache.org> (Torque)
* @author Jon S. Stevens <jon@latchkey.com> (Torque)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @author Byron Foster <byron_foster@yahoo.com> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class Column extends XMLElement {
const DEFAULT_TYPE = "VARCHAR";
private $name;
private $description;
private $phpName = null;
private $phpNamingMethod;
private $isNotNull = false;
private $size;
/**
* The name to use for the Peer constant that identifies this column.
* (Will be converted to all-uppercase in the templates.)
* @var string
*/
private $peerName;
/**
* Type as defined in schema.xml
* @var string
*/
private $propelType;
/**
* Type corresponding to Creole type
* @var int
*/
private $creoleType;
/**
* Native PHP type
* @var string "string", "boolean", "int", "double"
*/
private $phpType;
private $parentTable;
private $position;
private $isPrimaryKey = false;
private $isNodeKey = false;
private $nodeKeySep;
private $isUnique = false;
private $isAutoIncrement = false;
private $isLazyLoad = false;
private $defaultValue;
private $referrers;
// only one type is supported currently, which assumes the
// column either contains the classnames or a key to
// classnames specified in the schema. Others may be
// supported later.
private $inheritanceType;
private $isInheritance;
private $isEnumeratedClasses;
private $inheritanceList;
private $needsTransactionInPostgres; //maybe this can be retrieved from vendorSpecificInfo
/** class name to do input validation on this column */
private $inputValidator = null;
private $domain;
/**
* Creates a new column and set the name
*
* @param name column name
*/
public function __construct($name = null)
{
$this->name = $name;
}
/**
* Return a comma delimited string listing the specified columns.
*
* @param columns Either a list of <code>Column</code> objects, or
* a list of <code>String</code> objects with column names.
* @deprecated Use the DDLBuilder->getColumnList() method instead; this will be removed in 1.3
*/
public static function makeList($columns, Platform $platform)
{
$list = array();
foreach($columns as $col) {
if ($col instanceof Column) {
$col = $col->getName();
}
$list[] = $platform->quoteIdentifier($col);
}
return implode(", ", $list);
}
/**
* Sets up the Column object based on the attributes that were passed to loadFromXML().
* @see parent::loadFromXML()
*/
protected function setupObject()
{
try {
$dom = $this->getAttribute("domain");
if ($dom) {
$this->domain = new Domain();
$this->domain->copy($this->getTable()->getDatabase()->getDomain($dom));
} else {
$this->domain = new Domain();
$this->domain->copy($this->getPlatform()->getDomainForType(self::DEFAULT_TYPE));
$this->setType(strtoupper($this->getAttribute("type")));
}
//Name
$this->name = $this->getAttribute("name");
$this->phpName = $this->getAttribute("phpName");
$this->phpType = $this->getAttribute("phpType");
$this->peerName = $this->getAttribute("peerName");
if (empty($this->phpType)) {
$this->phpType = null;
}
// retrieves the method for converting from specified name to
// a PHP name.
$this->phpNamingMethod = $this->getAttribute("phpNamingMethod", $this->parentTable->getDatabase()->getDefaultPhpNamingMethod());
$this->isPrimaryKey = $this->booleanValue($this->getAttribute("primaryKey"));
$this->isNodeKey = $this->booleanValue($this->getAttribute("nodeKey"));
$this->nodeKeySep = $this->getAttribute("nodeKeySep", ".");
$this->isNotNull = $this->booleanValue($this->getAttribute("required"), false);
// Regardless of above, if this column is a primary key then it can't be null.
if ($this->isPrimaryKey) {
$this->isNotNull = true;
}
//AutoIncrement/Sequences
$this->isAutoIncrement = $this->booleanValue($this->getAttribute("autoIncrement"));
$this->isLazyLoad = $this->booleanValue($this->getAttribute("lazyLoad"));
//Default column value.
$this->domain->replaceDefaultValue($this->getAttribute("default"));
$this->domain->replaceSize($this->getAttribute("size"));
$this->domain->replaceScale($this->getAttribute("scale"));
$this->inheritanceType = $this->getAttribute("inheritance");
$this->isInheritance = ($this->inheritanceType !== null
&& $this->inheritanceType !== "false"); // here we are only checking for 'false', so don't
// use boleanValue()
$this->inputValidator = $this->getAttribute("inputValidator");
$this->description = $this->getAttribute("description");
} catch (Exception $e) {
throw new EngineException("Error setting up column " . var_export($this->getAttribute("name"), true) . ": " . $e->getMessage());
}
}
/**
* Gets domain for this column.
* @return Domain
*/
public function getDomain()
{
return $this->domain;
}
/**
* Returns table.column
*/
public function getFullyQualifiedName()
{
return ($this->parentTable->getName() . '.' . name);
}
/**
* Get the name of the column
*/
public function getName()
{
return $this->name;
}
/**
* Set the name of the column
*/
public function setName($newName)
{
$this->name = $newName;
}
/**
* Get the description for the Table
*/
public function getDescription()
{
return $this->description;
}
/**
* Set the description for the Table
*
* @param newDescription description for the Table
*/
public function setDescription($newDescription)
{
$this->description = $newDescription;
}
/**
* Get name to use in PHP sources
* @return string
*/
public function getPhpName()
{
if ($this->phpName === null) {
$inputs = array();
$inputs[] = $this->name;
$inputs[] = $this->phpNamingMethod;
try {
$this->phpName = NameFactory::generateName(NameFactory::PHP_GENERATOR, $inputs);
} catch (EngineException $e) {
print $e->getMessage() . "\n";
print $e->getTraceAsString();
}
}
return $this->phpName;
}
/**
* Set name to use in PHP sources
*/
public function setPhpName($phpName)
{
$this->phpName = $phpName;
}
/**
* Get the Peer constant name that will identify this column.
* @return string
*/
public function getPeerName() {
return $this->peerName;
}
/**
* Set the Peer constant name that will identify this column.
* @param $name string
*/
public function setPeerName($name) {
$this->peerName = $name;
}
/**
* Get type to use in PHP sources.
* If no type has been specified, then uses results
* of getPhpNative().
*
* The distinction between getPhpType() and getPhpNative()
* is not as salient in PHP as it is in Java, but we'd like to leave open the
* option of specifying complex types (objects) in the schema. While we can
* always cast to PHP native types, we can't cast objects (in PHP) -- hence the
* importance of maintaining this distinction.
*
* @return string The type name.
* @see getPhpNative()
*/
public function getPhpType()
{
if ($this->phpType !== null) {
return $this->phpType;
}
return $this->getPhpNative();
}
/**
* Get the location of this column within the table (one-based).
* @return int value of position.
*/
public function getPosition()
{
return $this->position;
}
/**
* Get the location of this column within the table (one-based).
* @param int $v Value to assign to position.
*/
public function setPosition($v)
{
$this->position = $v;
}
/**
* Set the parent Table of the column
*/
public function setTable(Table $parent)
{
$this->parentTable = $parent;
}
/**
* Get the parent Table of the column
*/
public function getTable()
{
return $this->parentTable;
}
/**
* Returns the Name of the table the column is in
*/
public function getTableName()
{
return $this->parentTable->getName();
}
/**
* Adds a new inheritance definition to the inheritance list and set the
* parent column of the inheritance to the current column
* @param mixed $inhdata Inheritance or XML data.
*/
public function addInheritance($inhdata)
{
if ($inhdata instanceof Inheritance) {
$inh = $inhdata;
$inh->setColumn($this);
if ($this->inheritanceList === null) {
$this->inheritanceList = array();
$this->isEnumeratedClasses = true;
}
$this->inheritanceList[] = $inh;
return $inh;
} else {
$inh = new Inheritance();
$inh->loadFromXML($inhdata);
return $this->addInheritance($inh);
}
}
/**
* Get the inheritance definitions.
*/
public function getChildren()
{
return $this->inheritanceList;
}
/**
* Determine if this column is a normal property or specifies a
* the classes that are represented in the table containing this column.
*/
public function isInheritance()
{
return $this->isInheritance;
}
/**
* Determine if possible classes have been enumerated in the xml file.
*/
public function isEnumeratedClasses()
{
return $this->isEnumeratedClasses;
}
/**
* Return the isNotNull property of the column
*/
public function isNotNull()
{
return $this->isNotNull;
}
/**
* Set the isNotNull property of the column
*/
public function setNotNull($status)
{
$this->isNotNull = (boolean) $status;
}
/**
* Return NOT NULL String for this column
*
* @return "NOT NULL" if null values are not allowed or an empty string.
*/
public function getNotNullString()
{
return $this->getTable()->getDatabase()->getPlatform()->getNullString($this->isNotNull());
}
/**
* Set if the column is a primary key or not
*/
public function setPrimaryKey($pk)
{
$this->isPrimaryKey = (boolean) $pk;
}
/**
* Return true if the column is a primary key
*/
public function isPrimaryKey()
{
return $this->isPrimaryKey;
}
/**
* Set if the column is the node key of a tree
*/
public function setNodeKey($nk)
{
$this->isNodeKey = (boolean) $nk;
}
/**
* Return true if the column is a node key of a tree
*/
public function isNodeKey()
{
return $this->isNodeKey;
}
/**
* Set if the column is the node key of a tree
*/
public function setNodeKeySep($sep)
{
$this->nodeKeySep = (string) $sep;
}
/**
* Return true if the column is a node key of a tree
*/
public function getNodeKeySep()
{
return $this->nodeKeySep;
}
/**
* Set true if the column is UNIQUE
*/
public function setUnique($u)
{
$this->isUnique = $u;
}
/**
* Get the UNIQUE property
*/
public function isUnique()
{
return $this->isUnique;
}
/**
* Return true if the column requires a transaction in Postgres
*/
public function requiresTransactionInPostgres()
{
return $this->needsTransactionInPostgres;
}
/**
* Utility method to determine if this column is a foreign key.
*/
public function isForeignKey()
{
return ($this->getForeignKey() !== null);
}
/**
* Determine if this column is a foreign key that refers to the
* same table as another foreign key column in this table.
*/
public function isMultipleFK()
{
$fk = $this->getForeignKey();
if ($fk !== null) {
$fks = $this->parentTable->getForeignKeys();
for ($i=0, $len=count($fks); $i < $len; $i++) {
if ($fks[$i]->getForeignTableName() === $fk->getForeignTableName()
&& !in_array($this->name, $fks[$i]->getLocalColumns()) ) {
return true;
}
}
}
// No multiple foreign keys.
return false;
}
/**
* get the foreign key object for this column
* if it is a foreign key or part of a foreign key
*/
public function getForeignKey()
{
return $this->parentTable->getForeignKey($this->name);
}
/**
* Utility method to get the related table of this column if it is a foreign
* key or part of a foreign key
*/
public function getRelatedTableName()
{
$fk = $this->getForeignKey();
return ($fk === null ? null : $fk->getForeignTableName());
}
/**
* Utility method to get the related column of this local column if this
* column is a foreign key or part of a foreign key.
*/
public function getRelatedColumnName()
{
$fk = $this->getForeignKey();
if ($fk === null) {
return null;
} else {
$m = $fk->getLocalForeignMapping();
$c = @$m[$this->name];
if ($c === null) {
return null;
} else {
return $c;
}
}
}
/**
* Adds the foreign key from another table that refers to this column.
*/
public function addReferrer(ForeignKey $fk)
{
if ($this->referrers === null) {
$this->referrers = array();
}
$this->referrers[] = $fk;
}
/**
* Get list of references to this column.
*/
public function getReferrers()
{
if ($this->referrers === null) {
$this->referrers = array();
}
return $this->referrers;
}
/**
* Returns the colunm type
*/
public function setType($propelType)
{
$this->domain = new Domain();
$this->domain->copy($this->getPlatform()->getDomainForType($propelType));
$this->propelType = $propelType;
if ($propelType == PropelTypes::VARBINARY|| $propelType == PropelTypes::LONGVARBINARY || $propelType == PropelTypes::BLOB) {
$this->needsTransactionInPostgres = true;
}
}
/**
* Returns the column Creole type as a string.
* @return string The constant representing Creole type: e.g. "VARCHAR".
*/
public function getType()
{
return PropelTypes::getCreoleType($this->propelType);
}
/**
* Returns the column type as given in the schema as an object
*/
public function getPropelType()
{
return $this->propelType;
}
/**
* Utility method to know whether column needs Blob/Lob handling.
* @return boolean
*/
public function isLob()
{
return PropelTypes::isLobType($this->propelType);
}
/**
* Utility method to see if the column is a string
*/
public function isString()
{
return PropelTypes::isTextxType($this->propelType);
}
/**
* String representation of the column. This is an xml representation.
*/
public function toString()
{
$result = " <column name=\"" . $this->name . '"';
if ($this->phpName !== null) {
$result .= " phpName=\"" . $this->phpName . '"';
}
if ($this->isPrimaryKey) {
$result .= " primaryKey=\"" . ($this->isPrimaryKey ? "true" : "false"). '"';
}
if ($this->isNotNull) {
$result .= " required=\"true\"";
} else {
$result .= " required=\"false\"";
}
$result .= " type=\"" . $this->propelType . '"';
if ($this->domain->getSize() !== null) {
$result .= " size=\"" . $this->domain->getSize() . '"';
}
if ($this->domain->getScale() !== null) {
$result .= " scale=\"" . $this->domain->getScale() . '"';
}
if ($this->domain->getDefaultValue() !== null) {
$result .= " default=\"" . $this->domain->getDefaultValue() . '"';
}
if ($this->isInheritance()) {
$result .= " inheritance=\"" . $this->inheritanceType
. '"';
}
if ($this->isNodeKey()) {
$result .= " nodeKey=\"true\"";
if ($this->getNodeKeySep() !== null) {
$result .= " nodeKeySep=\"" . $this->nodeKeySep . '"';
}
}
// Close the column.
$result .= " />\n";
return $result;
}
/**
* Returns the size of the column
* @return string
*/
public function getSize()
{
return $this->domain->getSize();
}
/**
* Set the size of the column
* @param string $newSize
*/
public function setSize($newSize)
{
$this->domain->setSize($newSize);
}
/**
* Returns the scale of the column
* @return string
*/
public function getScale()
{
return $this->domain->getScale();
}
/**
* Set the scale of the column
* @param string $newScale
*/
public function setScale($newScale)
{
$this->domain->setScale($newScale);
}
/**
* Return the size in brackets for use in an sql
* schema if the type is String. Otherwise return an empty string
*/
public function printSize()
{
return $this->domain->printSize();
}
/**
* Return a string that will give this column a default value.
* @return string
*/
public function getDefaultSetting()
{
$dflt = "";
if ($this->getDefaultValue() !== null) {
$dflt .= "default ";
if (PropelTypes::isTextType($this->getType())) {
$dflt .= '\'' . $this->getPlatform()->escapeText($this->getDefaultValue()) . '\'';
} elseif ($this->getType() == PropelTypes::BOOLEAN) {
$dflt .= $this->getPlatform()->getBooleanString($this->getDefaultValue());
} else {
$dflt .= $this->getDefaultValue();
}
}
return $dflt;
}
/**
* Set a string that will give this column a default value.
*/
public function setDefaultValue($def)
{
$this->domain->setDefaultValue($def);
}
/**
* Get the raw string that will give this column a default value.
* @return string
* @see Domain::getDefaultValue()
*/
public function getDefaultValue()
{
return $this->domain->getDefaultValue();
}
/**
* Get the default value suitable for use in PHP.
* @return mixed
* @see Domain::getPhpDefaultValue()
*/
public function getPhpDefaultValue()
{
return $this->domain->getPhpDefaultValue();
}
/**
* Returns the class name to do input validation
*/
public function getInputValidator()
{
return $this->inputValidator;
}
/**
* Return auto increment/sequence string for the target database. We need to
* pass in the props for the target database!
*/
public function isAutoIncrement()
{
return $this->isAutoIncrement;
}
/**
* Return auto increment/sequence string for the target database. We need to
* pass in the props for the target database!
*/
public function isLazyLoad()
{
return $this->isLazyLoad;
}
/**
* Gets the auto-increment string.
* @return string
*/
public function getAutoIncrementString()
{
if ($this->isAutoIncrement()&& IDMethod::NATIVE === $this->getTable()->getIdMethod()) {
return $this->getPlatform()->getAutoIncrement();
} elseif ($this->isAutoIncrement()) {
throw new EngineException("You have specified autoIncrement for column '" . $this->name . "' but you have not specified idMethod=\"native\" for table '" . $this->getTable()->getName() . "'.");
}
return "";
}
/**
* Set the auto increment value.
* Use isAutoIncrement() to find out if it is set or not.
*/
public function setAutoIncrement($value)
{
$this->isAutoIncrement = (boolean) $value;
}
/**
* Set the column type from a string property
* (normally a string from an sql input file)
*/
public function setTypeFromString($typeName, $size)
{
$tn = strtoupper($typeName);
$this->setType($tn);
if ($size !== null) {
$this->size = $size;
}
if (strpos($tn, "CHAR") !== false) {
$this->domain->setType(PropelTypes::VARCHAR);
} elseif (strpos($tn, "INT") !== false) {
$this->domain->setType(PropelTypes::INTEGER);
} elseif (strpos($tn, "FLOAT") !== false) {
$this->domain->setType(PropelTypes::FLOAT);
} elseif (strpos($tn, "DATE") !== false) {
$this->domain->setType(PropelTypes::DATE);
} elseif (strpos($tn, "TIME") !== false) {
$this->domain->setType(PropelTypes::TIMESTAMP);
} else if (strpos($tn, "BINARY") !== false) {
$this->domain->setType(PropelTypes::LONGVARBINARY);
} else {
$this->domain->setType(PropelTypes::VARCHAR);
}
}
/**
* Return a string representation of the native PHP type which corresponds
* to the Creole type of this column. Use in the generation of Base objects.
*
* @return string PHP datatype used by propel.
*/
public function getPhpNative()
{
return PropelTypes::getPHPNative($this->propelType);
}
/**
* Returns true if the column's PHP native type is an
* boolean, int, long, float, double, string
*/
public function isPrimitive()
{
$t = $this->getPhpNative();
return in_array($t, array("boolean", "int", "double", "string"));
}
/**
* Return true if column's PHP native type is an
* boolean, int, long, float, double
*/
public function isPrimitiveNumeric()
{
$t = $this->getPhpNative();
return in_array($t, array("boolean", "int", "double"));
}
/**
* Get the platform/adapter impl.
*
* @return Platform
*/
public function getPlatform()
{
return $this->getTable()->getDatabase()->getPlatform();
}
/**
*
* @return string
* @deprecated Use DDLBuilder->getColumnDDL() instead; this will be removed in 1.3
*/
public function getSqlString()
{
$sb = "";
$sb .= $this->getPlatform()->quoteIdentifier($this->getName()) . " ";
$sb .= $this->getDomain()->getSqlType();
if ($this->getPlatform()->hasSize($this->getDomain()->getSqlType())) {
$sb .= $this->getDomain()->printSize();
}
$sb .= " ";
$sb .= $this->getDefaultSetting() . " ";
$sb .= $this->getNotNullString() . " ";
$sb .= $this->getAutoIncrementString();
return trim($sb);
}
}

View File

@ -0,0 +1,84 @@
<?php
/*
* $Id: ConstraintNameGenerator.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
/**
* A <code>NameGenerator</code> implementation for table-specific
* constraints. Conforms to the maximum column name length for the
* type of database in use.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class ConstraintNameGenerator implements NameGenerator {
/**
* Conditional compilation flag.
*/
const DEBUG = false;
/**
* First element of <code>inputs</code> should be of type {@link Database}, second
* should be a table name, third is the type identifier (spared if
* trimming is necessary due to database type length constraints),
* and the fourth is a <code>Integer</code> indicating the number
* of this contraint.
*
* @see NameGenerator
* @throws EngineException
*/
public function generateName($inputs)
{
$db = $inputs[0];
$name = $inputs[1];
$namePostfix = $inputs[2];
$constraintNbr = (string) $inputs[3];
// Calculate maximum RDBMS-specific column character limit.
$maxBodyLength = -1;
try {
$maxColumnNameLength = (int) $db->getPlatform()->getMaxColumnNameLength();
$maxBodyLength = ($maxColumnNameLength - strlen($namePostfix)
- strlen($constraintNbr) - 2);
if (self::DEBUG) {
print("maxColumnNameLength=" . $maxColumnNameLength
. " maxBodyLength=" . $maxBodyLength . "\n");
}
} catch (EngineException $e) {
echo $e;
throw $e;
}
// Do any necessary trimming.
if ($maxBodyLength !== -1 && strlen($name) > $maxBodyLength) {
$name = substr($name, 0, $maxBodyLength);
}
$name .= self::STD_SEPARATOR_CHAR . $namePostfix
. self::STD_SEPARATOR_CHAR . $constraintNbr;
return $name;
}
}

View File

@ -0,0 +1,463 @@
<?php
/*
* $Id: Database.php 576 2007-02-09 19:08:40Z hans $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/database/model/XMLElement.php';
include_once 'propel/engine/database/model/IDMethod.php';
include_once 'propel/engine/database/model/NameGenerator.php';
include_once 'propel/engine/database/model/Table.php';
/**
* A class for holding application data structures.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Leon Messerschmidt <leon@opticode.co.za> (Torque)
* @author John McNally<jmcnally@collab.net> (Torque)
* @author Martin Poeschl<mpoeschl@marmot.at> (Torque)
* @author Daniel Rall<dlr@collab.net> (Torque)
* @author Byron Foster <byron_foster@yahoo.com> (Torque)
* @version $Revision: 576 $
* @package propel.engine.database.model
*/
class Database extends XMLElement {
private $platform;
private $tableList = array();
private $curColumn;
private $name;
private $pkg;
private $baseClass;
private $basePeer;
private $defaultIdMethod;
private $defaultPhpType;
private $defaultPhpNamingMethod;
private $defaultTranslateMethod;
private $dbParent;
private $tablesByName = array();
private $tablesByPhpName = array();
private $heavyIndexing;
private $domainMap = array();
/**
* Sets up the Database object based on the attributes that were passed to loadFromXML().
* @see parent::loadFromXML()
*/
protected function setupObject()
{
$this->name = $this->getAttribute("name");
$this->pkg = $this->getAttribute("package");
$this->baseClass = $this->getAttribute("baseClass");
$this->basePeer = $this->getAttribute("basePeer");
$this->defaultPhpType = $this->getAttribute("defaultPhpType");
$this->defaultIdMethod = $this->getAttribute("defaultIdMethod");
$this->defaultPhpNamingMethod = $this->getAttribute("defaultPhpNamingMethod", NameGenerator::CONV_METHOD_UNDERSCORE);
$this->defaultTranslateMethod = $this->getAttribute("defaultTranslateMethod", Validator::TRANSLATE_NONE);
$this->heavyIndexing = $this->booleanValue($this->getAttribute("heavyIndexing"));
}
/**
* Returns the Platform implementation for this database.
*
* @return Platform a Platform implementation
*/
public function getPlatform()
{
return $this->platform;
}
/**
* Sets the Platform implementation for this database.
*
* @param Platform $platform A Platform implementation
*/
public function setPlatform($platform)
{
$this->platform = $platform;
}
/**
* Get the name of the Database
*/
public function getName()
{
return $this->name;
}
/**
* Set the name of the Database
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Get the value of package.
* @return value of package.
*/
public function getPackage()
{
return $this->pkg;
}
/**
* Set the value of package.
* @param v Value to assign to package.
*/
public function setPackage($v)
{
$this->pkg = $v;
}
/**
* Get the value of baseClass.
* @return value of baseClass.
*/
public function getBaseClass()
{
return $this->baseClass;
}
/**
* Set the value of baseClass.
* @param v Value to assign to baseClass.
*/
public function setBaseClass($v)
{
$this->baseClass = $v;
}
/**
* Get the value of basePeer.
* @return value of basePeer.
*/
public function getBasePeer()
{
return $this->basePeer;
}
/**
* Set the value of basePeer.
* @param v Value to assign to basePeer.
*/
public function setBasePeer($v)
{
$this->basePeer = $v;
}
/**
* Get the value of defaultIdMethod.
* @return value of defaultIdMethod.
*/
public function getDefaultIdMethod()
{
return $this->defaultIdMethod;
}
/**
* Set the value of defaultIdMethod.
* @param v Value to assign to defaultIdMethod.
*/
public function setDefaultIdMethod($v)
{
$this->defaultIdMethod = $v;
}
/**
* Get the value of defaultPHPNamingMethod which specifies the
* method for converting schema names for table and column to PHP names.
* @return string The default naming conversion used by this database.
*/
public function getDefaultPhpNamingMethod()
{
return $this->defaultPhpNamingMethod;
}
/**
* Set the value of defaultPHPNamingMethod.
* @param string $v The default naming conversion for this database to use.
*/
public function setDefaultPhpNamingMethod($v)
{
$this->defaultPhpNamingMethod = $v;
}
/**
* Get the value of defaultTranslateMethod which specifies the
* method for translate validator error messages.
* @return string The default translate method.
*/
public function getDefaultTranslateMethod()
{
return $this->defaultTranslateMethod;
}
/**
* Set the value of defaultTranslateMethod.
* @param string $v The default translate method to use.
*/
public function setDefaultTranslateMethod($v)
{
$this->defaultTranslateMethod = $v;
}
/**
* Get the value of heavyIndexing.
* @return boolean Value of heavyIndexing.
*/
public function isHeavyIndexing()
{
return $this->heavyIndexing;
}
/**
* Set the value of heavyIndexing.
* @param boolean $v Value to assign to heavyIndexing.
*/
public function setHeavyIndexing($v)
{
$this->heavyIndexing = (boolean) $v;
}
/**
* Return an array of all tables
*/
public function getTables()
{
return $this->tableList;
}
/**
* Return the table with the specified name.
* @param string $name The name of the table (e.g. 'my_table')
* @return Table a Table object or null if it doesn't exist
*/
public function getTable($name)
{
if (isset($this->tablesByName[$name])) {
return $this->tablesByName[$name];
}
return null; // just to be explicit
}
/**
* Return the table with the specified phpName.
* @param string $phpName the PHP Name of the table (e.g. 'MyTable')
* @return Table a Table object or null if it doesn't exist
*/
public function getTableByPhpName($phpName)
{
if (isset($this->tablesByPhpName[$phpName])) {
return $this->tablesByPhpName[$phpName];
}
return null; // just to be explicit
}
/**
* An utility method to add a new table from an xml attribute.
*/
public function addTable($data)
{
if ($data instanceof Table) {
$tbl = $data; // alias
$tbl->setDatabase($this);
if (isset($this->tablesByName[$tbl->getName()])) {
throw new EngineException("Duplicate table declared: " . $tbl->getName());
}
$this->tableList[] = $tbl;
$this->tablesByName[ $tbl->getName() ] = $tbl;
$this->tablesByPhpName[ $tbl->getPhpName() ] = $tbl;
if ($tbl->getPackage() === null) {
$tbl->setPackage($this->getPackage());
}
return $tbl;
} else {
$tbl = new Table();
$tbl->setDatabase($this);
$tbl->loadFromXML($data);
return $this->addTable($tbl); // call self w/ different param
}
}
/**
* Set the parent of the database
*/
public function setAppData(AppData $parent)
{
$this->dbParent = $parent;
}
/**
* Get the parent of the table
*/
public function getAppData()
{
return $this->dbParent;
}
/**
* Adds Domain object from <domain> tag.
* @param mixed XML attributes (array) or Domain object.
*/
public function addDomain($data) {
if ($data instanceof Domain) {
$domain = $data; // alias
$domain->setDatabase($this);
$this->domainMap[ $domain->getName() ] = $domain;
return $domain;
} else {
$domain = new Table();
$domain->setDatabase($this);
$domain->loadFromXML($data);
return $this->addDomain($domain); // call self w/ different param
}
}
/**
* Get already configured Domain object by name.
* @return Domain
*/
public function getDomain($domainName) {
if (!isset($this->domainMap[$domainName])) {
return null;
}
return $this->domainMap[$domainName];
}
public function doFinalInitialization()
{
$tables = $this->getTables();
for($i=0,$size=count($tables); $i < $size; $i++) {
$currTable = $tables[$i];
// check schema integrity
// if idMethod="autoincrement", make sure a column is
// specified as autoIncrement="true"
// FIXME: Handle idMethod="native" via DB adapter.
/*
--- REMOVING THIS BECAUSE IT'S ANNOYING
if ($currTable->getIdMethod() == IDMethod::NATIVE ) {
$columns = $currTable->getColumns();
$foundOne = false;
for ($j=0, $cLen=count($columns); $j < $cLen && !$foundOne; $j++) {
$foundOne = $columns[$j]->isAutoIncrement();
}
if (!$foundOne) {
$errorMessage = "Table '" . $currTable->getName()
. "' is set to use native id generation, but it does not "
. "have a column which declared as the one to "
. "auto increment (i.e. autoIncrement=\"true\")";
throw new BuildException($errorMessage);
}
}
*/
$currTable->doFinalInitialization();
// setup reverse fk relations
$fks = $currTable->getForeignKeys();
for ($j=0, $fksLen=count($fks); $j < $fksLen; $j++) {
$currFK = $fks[$j];
$foreignTable = $this->getTable($currFK->getForeignTableName());
if ($foreignTable === null) {
throw new BuildException("ERROR!! Attempt to set foreign"
. " key to nonexistent table, "
. $currFK->getForeignTableName() . "!");
}
$referrers = $foreignTable->getReferrers();
if ($referrers === null || ! in_array($currFK,$referrers) ) {
$foreignTable->addReferrer($currFK);
}
// local column references
$localColumnNames = $currFK->getLocalColumns();
for($k=0,$lcnLen=count($localColumnNames); $k < $lcnLen; $k++) {
$local = $currTable->getColumn($localColumnNames[$k]);
// give notice of a schema inconsistency.
// note we do not prevent the npe as there is nothing
// that we can do, if it is to occur.
if ($local === null) {
throw new BuildException("ERROR!! Attempt to define foreign"
. " key with nonexistent column, "
. $localColumnNames[$k] . ", in table, "
. $currTable->getName() . "!");
}
//check for foreign pk's
if ($local->isPrimaryKey()) {
$currTable->setContainsForeignPK(true);
}
} // for each local col name
// foreign column references
$foreignColumnNames = $currFK->getForeignColumns();
for($k=0,$fcnLen=count($localColumnNames); $k < $fcnLen; $k++) {
$foreign = $foreignTable->getColumn($foreignColumnNames[$k]);
// if the foreign column does not exist, we may have an
// external reference or a misspelling
if ($foreign === null) {
throw new BuildException("ERROR!! Attempt to set foreign"
. " key to nonexistent column, "
. $foreignColumnNames[$k] . ", in table, "
. $foreignTable->getName() . "!");
} else {
$foreign->addReferrer($currFK);
}
} // for each foreign col ref
}
}
}
/**
* Creats a string representation of this Database.
* The representation is given in xml format.
*/
public function toString()
{
$result = "<database name=\"" . $this->getName() . '"'
. " package=\"" . $this->getPackage() . '"'
. " defaultIdMethod=\"" . $this->getDefaultIdMethod()
. '"'
. " baseClass=\"" . $this->getBaseClass() . '"'
. " basePeer=\"" . $this->getBasePeer() . '"'
. ">\n";
for ($i=0, $size=count($this->tableList); $i < $size; $i++) {
$result .= $this->tableList[$i]->toString();
}
$result .= "</database>";
return $result;
}
}

View File

@ -0,0 +1,313 @@
<?php
/*
* $Id: Domain.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/database/model/XMLElement.php';
/**
* A Class for holding data about a column used in an Application.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class Domain extends XMLElement {
private $name;
private $description;
private $size;
private $scale;
/** type as defined in schema.xml */
private $propelType;
private $sqlType;
private $defaultValue;
/** Database object -- in the event this Domain is specified in the XML. */
private $database;
/**
* Creates a new Domain object.
* If this domain needs a name, it must be specified manually.
*
* @param string $type Propel type.
* @param string $sqlType SQL type.
* @param string $size
* @param string $scale
*/
public function __construct($type = null, $sqlType = null, $size = null, $scale = null)
{
$this->propelType = $type;
$this->sqlType = ($sqlType !== null) ? $sqlType : $type;
$this->size = $size;
$this->scale = $scale;
}
public function copy(Domain $domain)
{
$this->defaultValue = $domain->getDefaultValue();
$this->description = $domain->getDescription();
$this->name = $domain->getName();
$this->scale = $domain->getScale();
$this->size = $domain->getSize();
$this->sqlType = $domain->getSqlType();
$this->propelType = $domain->getType();
}
/**
* Sets up the Domain object based on the attributes that were passed to loadFromXML().
* @see parent::loadFromXML()
*/
protected function setupObject()
{
$schemaType = strtoupper($this->getAttribute("type"));
$this->copy($this->getDatabase()->getPlatform()->getDomainForType($schemaType));
//Name
$this->name = $this->getAttribute("name");
//Default column value.
$this->defaultValue = $this->getAttribute("default"); // may need to adjust -- e.g. for boolean values
$this->size = $this->getAttribute("size");
$this->scale = $this->getAttribute("scale");
$this->description = $this->getAttribute("description");
}
/**
* Sets the owning database object (if this domain is being setup via XML).
*/
public function setDatabase(Database $database) {
$this->database = $database;
}
/**
* Gets the owning database object (if this domain was setup via XML).
*/
public function getDatabase() {
return $this->database;
}
/**
* @return Returns the description.
*/
public function getDescription()
{
return $this->description;
}
/**
* @param description The description to set.
*/
public function setDescription($description)
{
$this->description = $description;
}
/**
* @return Returns the name.
*/
public function getName()
{
return $this->name;
}
/**
* @param name The name to set.
*/
public function setName($name)
{
$this->name = $name;
}
/**
* @return Returns the scale.
*/
public function getScale()
{
return $this->scale;
}
/**
* @param scale The scale to set.
*/
public function setScale($scale)
{
$this->scale = $scale;
}
/**
* Replaces the size if the new value is not null.
*
* @param value The size to set.
*/
public function replaceScale($value)
{
if ($value !== null) {
$this->scale = $value;
}
}
/**
* @return Returns the size.
*/
public function getSize()
{
return $this->size;
}
/**
* @param size The size to set.
*/
public function setSize($size)
{
$this->size = $size;
}
/**
* Replaces the size if the new value is not null.
*
* @param value The size to set.
*/
public function replaceSize($value)
{
if ($value !== null) {
$this->size = $value;
}
}
/**
* @return string Returns the propelType.
*/
public function getType()
{
return $this->propelType;
}
/**
* @param string $propelType The PropelTypes type to set.
*/
public function setType($propelType)
{
$this->propelType = $propelType;
}
/**
* Replaces the default value if the new value is not null.
*
* @param value The defaultValue to set.
*/
public function replaceType($value)
{
if ($value !== null) {
$this->propelType = $value;
}
}
/**
* Gets the "raw" default value, suitable for use in SQL.
* @return string Returns the defaultValue.
*/
public function getDefaultValue()
{
if ($this->defaultValue !== null) {
return $this->defaultValue;
}
}
/**
* Gets the default value, type-casted for use in PHP OM.
* @return mixed
* @see getDefaultValue()
*/
public function getPhpDefaultValue()
{
if ($this->defaultValue === null) {
return null;
} elseif ($this->propelType === PropelTypes::BOOLEAN) {
// convert "true" => TRUE
return $this->booleanValue($this->defaultValue);
} elseif ($this->propelType === PropelTypes::DATE || $this->propelType === PropelTypes::TIME || $this->propelType === PropelTypes::TIMESTAMP) {
// DATE/TIME vals need to be converted to integer timestamp
$ts = strtotime($this->defaultValue);
if ($ts === -1 || $ts === false) { // in PHP 5.1 return value changes to FALSE
throw new EngineException("Unable to parse default value as date/time value: " . var_export($this->defaultValue, true));
}
return $ts;
} else {
return $this->defaultValue;
}
}
/**
* @param defaultValue The defaultValue to set.
*/
public function setDefaultValue($defaultValue)
{
$this->defaultValue = $defaultValue;
}
/**
* Replaces the default value if the new value is not null.
*
* @param string $value The defaultValue to set.
*/
public function replaceDefaultValue($value)
{
if ($value !== null) {
$this->defaultValue = $value;
}
}
/**
* @return Returns the sqlType.
*/
public function getSqlType()
{
return $this->sqlType;
}
/**
* @param string $sqlType The sqlType to set.
*/
public function setSqlType($sqlType)
{
$this->sqlType = $sqlType;
}
/**
* Return the size and scale in brackets for use in an sql schema.
*
* @return size and scale or an empty String if there are no values
* available.
*/
public function printSize()
{
if ($this->size !== null && $this->scale !== null) {
return '(' . $this->size . ',' . $this->scale . ')';
} elseif ($this->size !== null) {
return '(' . $this->size . ')';
} else {
return "";
}
}
}

View File

@ -0,0 +1,278 @@
<?php
/*
* $Id: ForeignKey.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/database/model/XMLElement.php';
/**
* A Class for information about foreign keys of a table.
*
* @author Hans Lellelid <hans@xmpl.org>
* @author Fedor <fedor.karpelevitch@home.com>
* @author Daniel Rall <dlr@finemaltcoding.com>
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class ForeignKey extends XMLElement {
private $foreignTableName;
private $name;
private $onUpdate;
private $onDelete;
private $parentTable;
private $localColumns = array();
private $foreignColumns = array();
// the uppercase equivalent of the onDelete/onUpdate values in the dtd
const NONE = ""; // No "ON [ DELETE | UPDATE]" behaviour specified.
const NOACTION = "NO ACTION";
const CASCADE = "CASCADE";
const RESTRICT = "RESTRICT";
const SETDEFAULT = "SET DEFAULT";
const SETNULL = "SET NULL";
/**
* Sets up the ForeignKey object based on the attributes that were passed to loadFromXML().
* @see parent::loadFromXML()
*/
protected function setupObject()
{
$this->foreignTableName = $this->getAttribute("foreignTable");
$this->name = $this->getAttribute("name");
$this->onUpdate = $this->normalizeFKey($this->getAttribute("onUpdate"));
$this->onDelete = $this->normalizeFKey($this->getAttribute("onDelete"));
}
/**
* normalizes the input of onDelete, onUpdate attributes
*/
private function normalizeFKey($attrib)
{
if ($attrib === null || strtoupper($attrib) == "NONE") {
$attrib = self::NONE;
}
$attrib = strtoupper($attrib);
if ($attrib == "SETNULL") {
$attrib = self::SETNULL;
}
return $attrib;
}
/**
* returns whether or not the onUpdate attribute is set
*/
public function hasOnUpdate()
{
return ($this->onUpdate !== self::NONE);
}
/**
* returns whether or not the onDelete attribute is set
*/
public function hasOnDelete()
{
return ($this->onDelete !== self::NONE);
}
/**
* returns the onUpdate attribute
*/
public function getOnUpdate()
{
return $this->onUpdate;
}
/**
* returns the onDelete attribute
*/
public function getOnDelete()
{
return $this->onDelete;
}
/**
* sets the onDelete attribute
*/
public function setOnDelete($value)
{
$this->onDelete = $this->normalizeFKey($value);
}
/**
* sets the onUpdate attribute
*/
public function setOnUpdate($value)
{
$this->onUpdate = $this->normalizeFKey($value);
}
/**
* Returns the name attribute.
*/
public function getName()
{
return $this->name;
}
/**
* Sets the name attribute.
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Get the foreignTableName of the FK
*/
public function getForeignTableName()
{
return $this->foreignTableName;
}
/**
* Set the foreignTableName of the FK
*/
public function setForeignTableName($tableName)
{
$this->foreignTableName = $tableName;
}
/**
* Set the parent Table of the foreign key
*/
public function setTable(Table $parent)
{
$this->parentTable = $parent;
}
/**
* Get the parent Table of the foreign key
*/
public function getTable()
{
return $this->parentTable;
}
/**
* Returns the Name of the table the foreign key is in
*/
public function getTableName()
{
return $this->parentTable->getName();
}
/**
* adds a new reference entry to the foreign key
*/
public function addReference($p1, $p2 = null)
{
if (is_array($p1)) {
$this->addReference(@$p1["local"], @$p1["foreign"]);
} else {
$this->localColumns[] = $p1;
$this->foreignColumns[] = $p2;
}
}
/**
* Return a comma delimited string of local column names
* @deprecated because Column::makeList() is deprecated; use the array-returning getLocalColumns() and DDLBuilder->getColumnList() instead instead.
*/
public function getLocalColumnNames()
{
return Column::makeList($this->getLocalColumns(), $this->getTable()->getDatabase()->getPlatform());
}
/**
* Return a comma delimited string of foreign column names
* @deprecated because Column::makeList() is deprecated; use the array-returning getForeignColumns() and DDLBuilder->getColumnList() instead instead.
*/
public function getForeignColumnNames()
{
return Column::makeList($this->getForeignColumns(), $this->getTable()->getDatabase()->getPlatform());
}
/**
* Return an array of local column names.
* @return array string[]
*/
public function getLocalColumns()
{
return $this->localColumns;
}
/**
* Utility method to get local column to foreign column
* mapping for this foreign key.
*/
public function getLocalForeignMapping()
{
$h = array();
for ($i=0, $size=count($this->localColumns); $i < $size; $i++) {
$h[$this->localColumns[$i]] = $this->foreignColumns[$i];
}
return $h;
}
/**
* Return an array of foreign column names.
* @return array string[]
*/
public function getForeignColumns()
{
return $this->foreignColumns;
}
/**
* Utility method to get local column to foreign column
* mapping for this foreign key.
*/
public function getForeignLocalMapping()
{
$h = array();
for ($i=0, $size=count($this->localColumns); $i < $size; $i++) {
$h[ $this->foreignColumns[$i] ] = $this->localColumns[$i];
}
return $h;
}
/**
* String representation of the foreign key. This is an xml representation.
*/
public function toString()
{
$result = " <foreign-key foreignTable=\""
. $this->getForeignTableName()
. "\" name=\""
. $this->getName()
. "\">\n";
for ($i=0, $size=count($this->localColumns); $i < $size; $i++) {
$result .= " <reference local=\""
. $this->localColumns[$i]
. "\" foreign=\""
. $this->foreignColumns[$i]
. "\"/>\n";
}
$result .= " </foreign-key>\n";
return $result;
}
}

View File

@ -0,0 +1,46 @@
<?php
/*
* $Id: IDMethod.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
/**
* Interface for various ID retrieval method types
* (i.e. auto-increment, sequence, ID broker, etc.).
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Daniel Rall <dlr@collab.net> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
interface IDMethod {
/**
* Key generation via database-specific ID method
* (i.e. auto-increment for MySQL, sequence for Oracle, etc.).
*/
const NATIVE = "native";
/**
* No RDBMS key generation (keys may be generated by the
* application).
*/
const NO_ID_METHOD = "none";
}

View File

@ -0,0 +1,125 @@
<?php
/*
* $Id: IdMethodParameter.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/database/model/XMLElement.php';
/**
* Information related to an ID method.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author John McNally <jmcnally@collab.net> (Torque)
* @author Daniel Rall <dlr@collab.net> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class IdMethodParameter extends XMLElement {
private $name;
private $value;
private $parentTable;
/**
* Sets up the IdMethodParameter object based on the attributes that were passed to loadFromXML().
* @see parent::loadFromXML()
*/
protected function setupObject()
{
$this->name = $this->getAttribute("name");
$this->value = $this->getAttribute("value");
}
/**
* Get the parameter name
*/
public function getName()
{
return $this->name;
}
/**
* Set the parameter name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Get the parameter value
*/
public function getValue()
{
return $this->value;
}
/**
* Set the parameter value
*/
public function setValue($value)
{
$this->value = $value;
}
/**
* Set the parent Table of the id method
*/
public function setTable(Table $parent)
{
$this->parentTable = $parent;
}
/**
* Get the parent Table of the id method
*/
public function getTable()
{
return $this->parentTable;
}
/**
* Returns the Name of the table the id method is in
*/
public function getTableName()
{
return $this->parentTable->getName();
}
/**
* XML representation of the foreign key.
*/
public function toString()
{
$result = " <id-method-parameter";
if ($this->getName() !== null) {
$result .= " name=\""
. $this->getName()
. '"';
}
$result .= " value=\""
. $this->getValue()
. "\">\n";
return $result;
}
}

View File

@ -0,0 +1,276 @@
<?php
/*
* $Id: Index.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/database/model/XMLElement.php';
include_once 'propel/engine/EngineException.php';
/**
* Information about indices of a table.
*
* @author Jason van Zyl <vanzyl@apache.org>
* @author Daniel Rall <dlr@finemaltcoding.com>
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class Index extends XMLElement {
/** enables debug output */
const DEBUG = false;
private $indexName;
private $parentTable;
/** @var array string[] */
private $indexColumns;
/** @var array */
private $indexColumnSizes = array();
/**
* Creates a new instance with default characteristics (no name or
* parent table, small column list size allocation, non-unique).
*
* @param Table $table
* @param array $indexColumns
*/
public function __construct(Table $table, $indexColumns = array())
{
$this->indexColumns = $indexColumns;
$this->setTable($table);
if (!empty($indexColumns)) {
$this->createName();
if (self::DEBUG) {
print("Created Index named " . $this->getName()
. " with " . count($indexColumns) . " columns\n");
}
}
}
private function createName()
{
$table = $this->getTable();
$inputs = array();
$inputs[] = $table->getDatabase();
$inputs[] = $table->getName();
if ($this->isUnique()) {
$inputs[] = "U";
} else {
$inputs[] = "I";
}
// ASSUMPTION: This Index not yet added to the list.
if ($this->isUnique()) {
$inputs[] = count($table->getUnices()) + 1;
} else {
$inputs[] = count($table->getIndices()) + 1;
}
$this->indexName = NameFactory::generateName(
NameFactory::CONSTRAINT_GENERATOR, $inputs);
}
/**
* Sets up the Index object based on the attributes that were passed to loadFromXML().
* @see parent::loadFromXML()
*/
protected function setupObject()
{
$this->indexName = $this->getAttribute("name");
}
/**
* @see #isUnique()
* @deprecated Use isUnique() instead.
*/
public function getIsUnique()
{
return $this->isUnique();
}
/**
* Returns the uniqueness of this index.
*/
public function isUnique()
{
return false;
}
/**
* @see #getName()
* @deprecated Use getName() instead.
*/
public function getIndexName()
{
return $this->getName();
}
/**
* Gets the name of this index.
*/
public function getName()
{
if ($this->indexName === null) {
try {
// generate an index name if we don't have a supplied one
$this->createName();
} catch (EngineException $e) {
// still no name
}
}
return $this->indexName;
}
/**
* @see #setName(String name)
* @deprecated Use setName(String name) instead.
*/
public function setIndexName($name)
{
$this->setName($name);
}
/**
* Set the name of this index.
*/
public function setName($name)
{
$this->indexName = $name;
}
/**
* Set the parent Table of the index
*/
public function setTable(Table $parent)
{
$this->parentTable = $parent;
}
/**
* Get the parent Table of the index
*/
public function getTable()
{
return $this->parentTable;
}
/**
* Returns the Name of the table the index is in
*/
public function getTableName()
{
return $this->parentTable->getName();
}
/**
* Adds a new column to an index.
* @param array $attrib The attribute array from XML parser.
*/
public function addColumn($attrib)
{
$name = $attrib["name"];
$this->indexColumns[] = $name;
if (isset($attrib["size"])) {
$this->indexColumnSizes[$name] = $attrib["size"];
}
}
/**
* Whether there is a size for the specified column.
* @param string $name
* @return boolean
*/
public function hasColumnSize($name)
{
return isset($this->indexColumnSizes[$name]);
}
/**
* Returns the size for the specified column, if given.
* @param string $name
* @return numeric The size or NULL
*/
public function getColumnSize($name)
{
if (isset($this->indexColumnSizes[$name])) {
return $this->indexColumnSizes[$name];
}
return null; // just to be explicit
}
/**
* @see #getColumnList()
* @deprecated Use getColumnList() instead (which is not deprecated too!)
*/
public function getIndexColumnList()
{
return $this->getColumnList();
}
/**
* Return a comma delimited string of the columns which compose this index.
* @deprecated because Column::makeList() is deprecated; use the array-returning getColumns() and DDLBuilder->getColumnList() instead instead.
*/
public function getColumnList()
{
return Column::makeList($this->getColumns(), $this->getTable()->getDatabase()->getPlatform());
}
/**
* @see #getColumns()
* @deprecated Use getColumns() instead.
*/
public function getIndexColumns()
{
return $this->getColumns();
}
/**
* Return the list of local columns. You should not edit this list.
* @return array string[]
*/
public function getColumns()
{
return $this->indexColumns;
}
/**
* String representation of the index. This is an xml representation.
*/
public function toString()
{
$result = " <index name=\""
. $this->getName()
.'"';
$result .= ">\n";
for ($i=0, $size=count($this->indexColumns); $i < $size; $i++) {
$result .= " <index-column name=\""
. $this->indexColumns[$i]
. "\"/>\n";
}
$result .= " </index>\n";
return $result;
}
}

View File

@ -0,0 +1,164 @@
<?php
/*
* $Id: Inheritance.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/database/model/XMLElement.php';
/**
* A Class for information regarding possible objects representing a table
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author John McNally <jmcnally@collab.net> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class Inheritance extends XMLElement {
private $key;
private $className;
private $pkg;
private $ancestor;
private $parent;
/**
* Sets up the Inheritance object based on the attributes that were passed to loadFromXML().
* @see parent::loadFromXML()
*/
protected function setupObject()
{
$this->key = $this->getAttribute("key");
$this->className = $this->getAttribute("class");
$this->pkg = $this->getAttribute("package");
$this->ancestor = $this->getAttribute("extends");
}
/**
* Get the value of key.
* @return value of key.
*/
public function getKey()
{
return $this->key;
}
/**
* Set the value of key.
* @param v Value to assign to key.
*/
public function setKey($v)
{
$this->key = $v;
}
/**
* Get the value of parent.
* @return value of parent.
*/
public function getColumn()
{
return $this->parent;
}
/**
* Set the value of parent.
* @param v Value to assign to parent.
*/
public function setColumn(Column $v)
{
$this->parent = $v;
}
/**
* Get the value of className.
* @return value of className.
*/
public function getClassName()
{
return $this->className;
}
/**
* Set the value of className.
* @param v Value to assign to className.
*/
public function setClassName($v)
{
$this->className = $v;
}
/**
* Get the value of package.
* @return value of package.
*/
public function getPackage()
{
return $this->pkg;
}
/**
* Set the value of package.
* @param v Value to assign to package.
*/
public function setPackage($v)
{
$this->pkg = $v;
}
/**
* Get the value of ancestor.
* @return value of ancestor.
*/
public function getAncestor()
{
return $this->ancestor;
}
/**
* Set the value of ancestor.
* @param v Value to assign to ancestor.
*/
public function setAncestor($v)
{
$this->ancestor = $v;
}
/**
* String representation of the foreign key. This is an xml representation.
*/
public function toString()
{
$result = " <inheritance key=\""
. $this->key
. "\" class=\""
. $this->className
. '"';
if ($this->ancestor !== null) {
$result .= " extends=\""
. $this->ancestor
. '"';
}
$result .= "/>";
return $result;
}
}

View File

@ -0,0 +1,116 @@
<?php
/*
* $Id: NameFactory.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'propel/engine/EngineException.php';
include_once 'propel/engine/database/model/NameGenerator.php';
/**
* A name generation factory.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class NameFactory {
/**
* The class name of the PHP name generator.
*/
const PHP_GENERATOR = 'PhpNameGenerator';
/**
* The fully qualified class name of the constraint name generator.
*/
const CONSTRAINT_GENERATOR = 'ConstraintNameGenerator';
/**
* The single instance of this class.
*/
private static $instance;
/**
* The cache of <code>NameGenerator</code> algorithms in use for
* name generation, keyed by fully qualified class name.
*/
private $algorithms;
/**
* Creates a new instance with storage for algorithm implementations.
*/
protected function __construct()
{
$this->algorithms = array();
}
private static function instance()
{
if (self::$instance === null) {
self::$instance = new NameFactory();
}
return self::$instance;
}
/**
* Factory method which retrieves an instance of the named generator.
*
* @param name The fully qualified class name of the name
* generation algorithm to retrieve.
*/
protected function getAlgorithm($name)
{
$algorithm = isset($this->algorithms[$name]) ? $this->algorithms[$name] : null;
if ($algorithm === null) {
try {
include_once 'propel/engine/database/model/' . $name . '.php';
if (!class_exists($name)) {
throw new Exception("Unable to instantiate class " . $name
. ": Make sure it's in your include_path");
}
$algorithm = new $name();
} catch (BuildException $e) {
print $e->getMessage() . "\n";
print $e->getTraceAsString();
}
$this->algorithms[$name] = $algorithm;
}
return $algorithm;
}
/**
* Given a list of <code>String</code> objects, implements an
* algorithm which produces a name.
*
* @param algorithmName The fully qualified class name of the
* {@link NameGenerator}
* implementation to use to generate names.
* @param array $inputs Inputs used to generate a name.
* @return The generated name.
* @throws EngineException
*/
public static function generateName($algorithmName, $inputs)
{
$algorithm = self::instance()->getAlgorithm($algorithmName);
return $algorithm->generateName($inputs);
}
}

View File

@ -0,0 +1,72 @@
<?php
/*
* $Id: NameGenerator.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
/**
* The generic interface to a name generation algorithm.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @author Byron Foster <byron_foster@yahoo.com> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
interface NameGenerator {
/**
* The character used by most implementations as the separator
* between name elements.
*/
const STD_SEPARATOR_CHAR = '_';
/**
* Traditional method for converting schema table and column names
* to PHP names. The <code>CONV_METHOD_XXX</code> constants
* define how names for columns and tables in the database schema
* will be converted to PHP source names.
*
* @see PhpNameGenerator::underscoreMethod()
*/
const CONV_METHOD_UNDERSCORE = "underscore";
/**
* Similar to {@link #CONV_METHOD_UNDERSCORE} except nothing is
* converted to lowercase.
*
* @see PhpNameGenerator::phpnameMethod()
*/
const CONV_METHOD_PHPNAME = "phpname";
/**
* Specifies no modification when converting from a schema column
* or table name to a PHP name.
*/
const CONV_METHOD_NOCHANGE = "nochange";
/**
* Given a list of <code>String</code> objects, implements an
* algorithm which produces a name.
*
* @param inputs Inputs used to generate a name.
* @return The generated name.
* @throws EngineException
*/
public function generateName($inputs);
}

View File

@ -0,0 +1,131 @@
<?php
/*
* $Id: PhpNameGenerator.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'propel/engine/database/model/NameGenerator.php';
/**
* A <code>NameGenerator</code> implementation for PHP-esque names.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @author Byron Foster <byron_foster@yahoo.com> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class PhpNameGenerator implements NameGenerator {
/**
* <code>inputs</code> should consist of two elements, the
* original name of the database element and the method for
* generating the name. There are currently three methods:
* <code>CONV_METHOD_NOCHANGE</code> - xml names are converted
* directly to php names without modification.
* <code>CONV_METHOD_UNDERSCORE</code> will capitalize the first
* letter, remove underscores, and capitalize each letter before
* an underscore. All other letters are lowercased. "phpname"
* works the same as the <code>CONV_METHOD_PHPNAME</code> method
* but will not lowercase any characters.
*
* @param inputs list expected to contain two parameters, element
* 0 contains name to convert, element 1 contains method for conversion.
* @return The generated name.
* @see NameGenerator
*/
public function generateName($inputs)
{
$schemaName = $inputs[0];
$method = $inputs[1];
$phpName = null;
if ($method == self::CONV_METHOD_UNDERSCORE) {
$phpName = $this->underscoreMethod($schemaName);
} elseif ($method == self::CONV_METHOD_PHPNAME) {
$phpName = $this->phpnameMethod($schemaName);
} else if ($method == self::CONV_METHOD_NOCHANGE) {
$phpName = $this->nochangeMethod($schemaName);
} else {
// if for some reason nothing is defined then we default
// to the traditional method.
$phpName = $this->underscoreMethod($schemaName);
}
return $phpName;
}
/**
* Converts a database schema name to php object name. Removes
* <code>STD_SEPARATOR_CHAR</code>, capitilizes first letter of
* name and each letter after the <code>STD_SEPERATOR</code>,
* converts the rest of the letters to lowercase.
*
* my_CLASS_name -> MyClassName
*
* @param string $schemaName name to be converted.
* @return string Converted name.
* @see NameGenerator
* @see #underscoreMethod()
*/
protected function underscoreMethod($schemaName)
{
$name = "";
$tok = strtok($schemaName, self::STD_SEPARATOR_CHAR);
while($tok) {
$name .= ucfirst(strtolower($tok));
$tok = strtok(self::STD_SEPARATOR_CHAR);
}
return $name;
}
/**
* Converts a database schema name to php object name. Operates
* same as underscoreMethod but does not convert anything to
* lowercase.
*
* my_CLASS_name -> MyCLASSName
*
* @param string $schemaName name to be converted.
* @return string Converted name.
* @see NameGenerator
* @see #underscoreMethod(String)
*/
protected function phpnameMethod($schemaName)
{
$name = "";
$tok = strtok($schemaName, self::STD_SEPARATOR_CHAR);
while($tok) {
$name .= ucfirst($tok);
$tok = strtok(self::STD_SEPARATOR_CHAR);
}
return $name;
}
/**
* Converts a database schema name to PHP object name. In this
* case no conversion is made.
*
* @param string $name name to be converted.
* @return string The <code>name</code> parameter, unchanged.
*/
protected function nochangeMethod($name)
{
return $name;
}
}

View File

@ -0,0 +1,290 @@
<?php
/*
* $Id: PropelTypes.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'creole/CreoleTypes.php';
/**
* A class that maps PropelTypes to CreoleTypes and to native PHP types.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Jason van Zyl <jvanzyl@apache.org> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class PropelTypes {
const CHAR = "CHAR";
const VARCHAR = "VARCHAR";
const LONGVARCHAR = "LONGVARCHAR";
const CLOB = "CLOB";
const NUMERIC = "NUMERIC";
const DECIMAL = "DECIMAL";
const TINYINT = "TINYINT";
const SMALLINT = "SMALLINT";
const INTEGER = "INTEGER";
const BIGINT = "BIGINT";
const REAL = "REAL";
const FLOAT = "FLOAT";
const DOUBLE = "DOUBLE";
const BINARY = "BINARY";
const VARBINARY = "VARBINARY";
const LONGVARBINARY = "LONGVARBINARY";
const BLOB = "BLOB";
const DATE = "DATE";
const TIME = "TIME";
const TIMESTAMP = "TIMESTAMP";
const BU_DATE = "BU_DATE";
const BU_TIMESTAMP = "BU_TIMESTAMP";
const BOOLEAN = "BOOLEAN";
private static $TEXT_TYPES = null;
private static $LOB_TYPES = null;
const CHAR_NATIVE_TYPE = "string";
const VARCHAR_NATIVE_TYPE = "string";
const LONGVARCHAR_NATIVE_TYPE = "string";
const CLOB_NATIVE_TYPE = "string"; // Clob
const NUMERIC_NATIVE_TYPE = "double";
const DECIMAL_NATIVE_TYPE = "double";
const BOOLEAN_NATIVE_TYPE = "boolean";
const TINYINT_NATIVE_TYPE = "int";
const SMALLINT_NATIVE_TYPE = "int";
const INTEGER_NATIVE_TYPE = "int";
const BIGINT_NATIVE_TYPE = "string";
const REAL_NATIVE_TYPE = "double";
const FLOAT_NATIVE_TYPE = "double";
const DOUBLE_NATIVE_TYPE = "double";
const BINARY_NATIVE_TYPE = "string";
const VARBINARY_NATIVE_TYPE = "string";
const LONGVARBINARY_NATIVE_TYPE = "string";
const BLOB_NATIVE_TYPE = "string";
const BU_DATE_NATIVE_TYPE = "string";
const DATE_NATIVE_TYPE = "int";
const TIME_NATIVE_TYPE = "int";
const TIMESTAMP_NATIVE_TYPE = "int";
const BU_TIMESTAMP_NATIVE_TYPE = "string";
private static $propelToPHPNativeMap = null;
private static $propelTypeToCreoleTypeMap = null;
private static $creoleToPropelTypeMap = null;
private static $isInitialized = false;
/**
* Initializes the SQL to PHP map so that it
* can be used by client code.
*/
public static function initialize()
{
if (self::$isInitialized === false) {
self::$TEXT_TYPES = array (
self::CHAR, self::VARCHAR, self::LONGVARCHAR, self::CLOB, self::DATE, self::TIME, self::TIMESTAMP, self::BU_DATE, self::BU_TIMESTAMP
);
self::$LOB_TYPES = array (
self::VARBINARY, self::LONGVARBINARY, self::CLOB, self::BLOB
);
/*
* Create Creole -> native PHP type mappings.
*/
self::$propelToPHPNativeMap = array();
self::$propelToPHPNativeMap[self::CHAR] = self::CHAR_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::VARCHAR] = self::VARCHAR_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::LONGVARCHAR] = self::LONGVARCHAR_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::CLOB] = self::CLOB_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::NUMERIC] = self::NUMERIC_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::DECIMAL] = self::DECIMAL_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::TINYINT] = self::TINYINT_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::SMALLINT] = self::SMALLINT_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::INTEGER] = self::INTEGER_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::BIGINT] = self::BIGINT_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::REAL] = self::REAL_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::FLOAT] = self::FLOAT_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::DOUBLE] = self::DOUBLE_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::BINARY] = self::BINARY_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::VARBINARY] = self::VARBINARY_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::LONGVARBINARY] = self::LONGVARBINARY_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::BLOB] = self::BLOB_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::DATE] = self::DATE_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::BU_DATE] = self::BU_DATE_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::TIME] = self::TIME_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::TIMESTAMP] = self::TIMESTAMP_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::BU_TIMESTAMP] = self::BU_TIMESTAMP_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::BOOLEAN] = self::BOOLEAN_NATIVE_TYPE;
/*
* Create Propel -> Creole _name_ mappings (not CreoleType:: mappings).
* (this is now pretty useless since we've designed them to be the same!)
*/
self::$propelTypeToCreoleTypeMap = array();
self::$propelTypeToCreoleTypeMap[self::CHAR] = self::CHAR;
self::$propelTypeToCreoleTypeMap[self::VARCHAR] = self::VARCHAR;
self::$propelTypeToCreoleTypeMap[self::LONGVARCHAR] = self::LONGVARCHAR;
self::$propelTypeToCreoleTypeMap[self::CLOB] = self::CLOB;
self::$propelTypeToCreoleTypeMap[self::NUMERIC] = self::NUMERIC;
self::$propelTypeToCreoleTypeMap[self::DECIMAL] = self::DECIMAL;
self::$propelTypeToCreoleTypeMap[self::TINYINT] = self::TINYINT;
self::$propelTypeToCreoleTypeMap[self::SMALLINT] = self::SMALLINT;
self::$propelTypeToCreoleTypeMap[self::INTEGER] = self::INTEGER;
self::$propelTypeToCreoleTypeMap[self::BIGINT] = self::BIGINT;
self::$propelTypeToCreoleTypeMap[self::REAL] = self::REAL;
self::$propelTypeToCreoleTypeMap[self::FLOAT] = self::FLOAT;
self::$propelTypeToCreoleTypeMap[self::DOUBLE] = self::DOUBLE;
self::$propelTypeToCreoleTypeMap[self::BINARY] = self::BINARY;
self::$propelTypeToCreoleTypeMap[self::VARBINARY] = self::VARBINARY;
self::$propelTypeToCreoleTypeMap[self::LONGVARBINARY] = self::LONGVARBINARY;
self::$propelTypeToCreoleTypeMap[self::BLOB] = self::BLOB;
self::$propelTypeToCreoleTypeMap[self::DATE] = self::DATE;
self::$propelTypeToCreoleTypeMap[self::TIME] = self::TIME;
self::$propelTypeToCreoleTypeMap[self::TIMESTAMP] = self::TIMESTAMP;
self::$propelTypeToCreoleTypeMap[self::BOOLEAN] = self::BOOLEAN;
// These are pre-epoch dates, which we need to map to String type
// since they cannot be properly handled using strtotime() -- or even numeric
// timestamps on Windows.
self::$propelTypeToCreoleTypeMap[self::BU_DATE] = self::VARCHAR;
self::$propelTypeToCreoleTypeMap[self::BU_TIMESTAMP] = self::VARCHAR;
/*
* Create Creole type code to Propel type map.
*/
self::$creoleToPropelTypeMap = array();
self::$creoleToPropelTypeMap[CreoleTypes::CHAR] = self::CHAR;
self::$creoleToPropelTypeMap[CreoleTypes::VARCHAR] = self::VARCHAR;
self::$creoleToPropelTypeMap[CreoleTypes::LONGVARCHAR] = self::LONGVARCHAR;
self::$creoleToPropelTypeMap[CreoleTypes::CLOB] = self::CLOB;
self::$creoleToPropelTypeMap[CreoleTypes::NUMERIC] = self::NUMERIC;
self::$creoleToPropelTypeMap[CreoleTypes::DECIMAL] = self::DECIMAL;
self::$creoleToPropelTypeMap[CreoleTypes::TINYINT] = self::TINYINT;
self::$creoleToPropelTypeMap[CreoleTypes::SMALLINT] = self::SMALLINT;
self::$creoleToPropelTypeMap[CreoleTypes::INTEGER] = self::INTEGER;
self::$creoleToPropelTypeMap[CreoleTypes::BIGINT] = self::BIGINT;
self::$creoleToPropelTypeMap[CreoleTypes::REAL] = self::REAL;
self::$creoleToPropelTypeMap[CreoleTypes::FLOAT] = self::FLOAT;
self::$creoleToPropelTypeMap[CreoleTypes::DOUBLE] = self::DOUBLE;
self::$creoleToPropelTypeMap[CreoleTypes::BINARY] = self::BINARY;
self::$creoleToPropelTypeMap[CreoleTypes::VARBINARY] = self::VARBINARY;
self::$creoleToPropelTypeMap[CreoleTypes::LONGVARBINARY] = self::LONGVARBINARY;
self::$creoleToPropelTypeMap[CreoleTypes::BLOB] = self::BLOB;
self::$creoleToPropelTypeMap[CreoleTypes::DATE] = self::DATE;
self::$creoleToPropelTypeMap[CreoleTypes::TIME] = self::TIME;
self::$creoleToPropelTypeMap[CreoleTypes::TIMESTAMP] = self::TIMESTAMP;
self::$creoleToPropelTypeMap[CreoleTypes::BOOLEAN] = self::BOOLEAN;
self::$creoleToPropelTypeMap[CreoleTypes::YEAR] = self::INTEGER;
self::$isInitialized = true;
}
}
/**
* Report whether this object has been initialized.
*
* @return true if this object has been initialized
*/
public static function isInitialized()
{
return self::$isInitialized;
}
/**
* Return native PHP type which corresponds to the
* Creole type provided. Use in the base object class generation.
*
* @param $propelType The Propel type name.
* @return string Name of the native PHP type
*/
public static function getPhpNative($propelType)
{
return self::$propelToPHPNativeMap[$propelType];
}
/**
* Returns the correct Creole type _name_ for propel added types
*
* @param $type the propel added type.
* @return string Name of the the correct Creole type (e.g. "VARCHAR").
*/
public static function getCreoleType($type)
{
return self::$propelTypeToCreoleTypeMap[$type];
}
/**
* Returns Propel type constant corresponding to Creole type code.
* Used but Propel Creole task.
*
* @param int $sqlType The Creole SQL type constant.
* @return string The Propel type to use or NULL if none found.
*/
public static function getPropelType($sqlType)
{
if (isset(self::$creoleToPropelTypeMap[$sqlType])) {
return self::$creoleToPropelTypeMap[$sqlType];
}
}
/**
* Get array of Propel types.
*
* @return array string[]
*/
public static function getPropelTypes()
{
return array_keys(self::$propelTypeToCreoleTypeMap);
}
/**
* Returns true if values for the type need to be quoted.
*
* @param string $type The Propel type to check.
* @return true if values for the type need to be quoted.
*/
public static function isTextType($type)
{
// Make sure the we are initialized.
if (self::$isInitialized === false) {
self::initialize();
}
return in_array($type, self::$TEXT_TYPES);
}
/**
* Returns true if type is a LOB type (i.e. would be handled by Blob/Clob class).
* @param string $type Propel type to check.
* @return boolean
*/
public static function isLobType($type)
{
return in_array($type, self::$LOB_TYPES);
}
}
// static
PropelTypes::initialize();

View File

@ -0,0 +1,203 @@
<?php
/*
* $Id: Rule.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/database/model/XMLElement.php';
/**
* Data about a validation rule used in an application.
*
* @author Michael Aichler <aichler@mediacluster.de> (Propel)
* @author John McNally <jmcnally@collab.net> (Intake)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class Rule extends XMLElement {
private $name;
private $value;
private $message;
private $validator;
private $classname;
/**
* Sets up the Rule object based on the attributes that were passed to loadFromXML().
* @see parent::loadFromXML()
*/
protected function setupObject()
{
$this->name = $this->getAttribute("name");
$this->value = $this->getAttribute("value");
$this->classname = $this->getAttribute("class");
/*
* Set some default values if they are not specified.
* This is escpecially useful for maxLength; the size
* is already known by the column and this way it is
* not necessary to manage the same size two times.
*
* Currently there is only one such supported default:
* - maxLength value = column max length
* (this default cannot be easily set at runtime w/o changing
* design of class system in undesired ways)
*/
if ($this->value === null) {
switch($this->name) {
case 'maxLength':
$this->value = $this->validator->getColumn()->getSize();
break;
}
}
$this->message = $this->getAttribute("message");
}
/**
* Sets the owning validator for this rule.
* @param Validator $validator
* @see Validator::addRule()
*/
public function setValidator(Validator $validator)
{
$this->validator = $validator;
}
/**
* Gets the owning validator for this rule.
* @return Validator
*/
public function getValidator()
{
return $this->validator;
}
/**
* Sets the dot-path name of class to use for rule.
* If no class is specified in XML, then a classname will
* be built based on the 'name' attrib.
* @param string $classname dot-path classname (e.g. myapp.propel.MyValidator)
*/
public function setClass($classname)
{
$this->classname = $classname;
}
/**
* Gets the dot-path name of class to use for rule.
* If no class was specified, this method will build a default classname
* based on the 'name' attribute. E.g. 'maxLength' -> 'propel.validator.MaxLengthValidator'
* @return string dot-path classname (e.g. myapp.propel.MyValidator)
*/
public function getClass()
{
if ($this->classname === null && $this->name !== null) {
return "propel.validator." . ucfirst($this->name) . "Validator";
}
return $this->classname;
}
/**
* Sets the name of the validator for this rule.
* This name is used to build the classname if none was specified.
* @param string $name Validator name for this rule (e.g. "maxLength", "required").
* @see getClass()
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Gets the name of the validator for this rule.
* @return string Validator name for this rule (e.g. "maxLength", "required").
*/
public function getName()
{
return $this->name;
}
/**
* Sets the value parameter for this validator rule.
* Note: not all validators need a value parameter (e.g. 'required' validator
* does not).
* @param string $value
*/
public function setValue($value)
{
$this->value = $value;
}
/**
* Gets the value parameter for this validator rule.
* @return string
*/
public function getValue()
{
return $this->value;
}
/**
* Sets the message that will be displayed to the user if validation fails.
* This message may be a Gettext msgid (if translation="gettext") or some other
* id for an alternative not-yet-supported translation system. It may also
* be a simple, single-language string.
* @param string $message
* @see setTranslation()
*/
public function setMessage($message)
{
$this->message = $message;
}
/**
* Gets the message that will be displayed to the user if validation fails.
* This message may be a Gettext msgid (if translation="gettext") or some other
* id for an alternative not-yet-supported translation system. It may also
* be a simple, single-language string.
* @return string
* @see setTranslation()
*/
public function getMessage()
{
$message = str_replace('${value}', $this->getValue(), $this->message);
return $message;
}
/**
* Create XML (string) representation of this object.
* @return string
*/
public function toString()
{
$result = "<rule name=\"" . $this->getName() . "\" ";
if ($this->getValue() !== null) {
$result .= "value=\"" . $this->getValue(). "\" ";
}
if ($this->getClass() !== null) {
$result .= "class=\"".$this->getClass()."\" ";
}
$result .= "message=\"" . $this->getMessage() . "\" ";
$result .= "/>\n";
return $result;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,69 @@
<?php
/*
* $Id: Unique.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'propel/engine/database/model/Index.php';
/**
* Information about unique columns of a table. This class assumes
* that in the underlying RDBMS, unique constraints and unique indices
* are roughly equivalent. For example, adding a unique constraint to
* a column also creates an index on that column (this is known to be
* true for MySQL and Oracle).
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Jason van Zyl <jvanzyl@apache.org> (Torque)
* @author Daniel Rall <dlr@collab.net> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class Unique extends Index {
/**
* Default constructor.
*/
public function __construct(Table $table, $indexColumns = array())
{
}
/**
* Returns <code>true</code>.
*/
public function isUnique()
{
return true;
}
/**
* String representation of the index. This is an xml representation.
*/
public function toString()
{
$result = " <unique name=\"" . $this->getName() . "\">\n";
$columns = $this->getColumns();
for ($i=0, $size=count($columns); $i < $size; $i++) {
$result .= " <unique-column name=\""
. $columns[$i]
. "\"/>\n";
}
$result .= " </unique>\n";
return $result;
}
}

View File

@ -0,0 +1,186 @@
<?php
/*
* $Id: Validator.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/database/model/XMLElement.php';
include_once 'propel/engine/EngineException.php';
include_once 'propel/engine/database/model/PropelTypes.php';
include_once 'propel/engine/database/model/Rule.php';
/**
* Validator.
*
* @author Michael Aichler <aichler@mediacluster.de> (Propel)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class Validator extends XMLElement {
const TRANSLATE_NONE = "none";
const TRANSLATE_GETTEXT = "gettext";
private $columnName;
private $column;
private $ruleList;
private $translate;
private $table;
/**
* Creates a new column and set the name
*
* @param name validator name
*/
public function __construct()
{
$this->ruleList = array();
}
/**
* Sets up the Validator object based on the attributes that were passed to loadFromXML().
* @see parent::loadFromXML()
*/
protected function setupObject()
{
$this->columnName = $this->getAttribute("column");
$this->translate = $this->getAttribute("translate", $this->getTable()->getDatabase()->getDefaultTranslateMethod());;
}
/**
* Add a Rule to this validator.
* Supports two signatures:
* - addRule(Rule $rule)
* - addRule(array $attribs)
* @param mixed $data Rule object or XML attribs (array) from <rule/> element.
* @return Rule The added Rule.
*/
public function addRule($data)
{
if ($data instanceof Rule) {
$rule = $data; // alias
$rule->setValidator($this);
$this->ruleList[] = $rule;
return $rule;
}
else {
$rule = new Rule();
$rule->setValidator($this);
$rule->loadFromXML($data);
return $this->addRule($rule); // call self w/ different param
}
}
/**
* Gets an array of all added rules for this validator.
* @return array Rule[]
*/
public function getRules()
{
return $this->ruleList;
}
/**
* Gets the name of the column that this Validator applies to.
* @return string
*/
public function getColumnName()
{
return $this->columnName;
}
/**
* Sets the Column object that this validator applies to.
* @param Column $column
* @see Table::addValidator()
*/
public function setColumn(Column $column)
{
$this->column = $column;
}
/**
* Gets the Column object that this validator applies to.
* @return Column
*/
public function getColumn()
{
return $this->column;
}
/**
* Set the owning Table.
* @param Table $table
*/
public function setTable(Table $table)
{
$this->table = $table;
}
/**
* Get the owning Table.
* @return Table
*/
public function getTable()
{
return $this->table;
}
/**
* Set the translation mode to use for the message.
* Currently only "gettext" and "none" are supported. The default is "none".
* @param string $method Translation method ("gettext", "none").
*/
public function setTranslate($method)
{
$this->translate = $method;
}
/**
* Get the translation mode to use for the message.
* Currently only "gettext" and "none" are supported. The default is "none".
* @return string Translation method ("gettext", "none").
*/
public function getTranslate()
{
return $this->translate;
}
/**
* Gets XML (string) representation of this Validator.
* @return string
*/
public function toString()
{
$result = "<validator column=\"" . $this->columnName . "\"";
if ($this->translate !== null) {
$result .= " translate=\"".$this->translate."\"";
}
$result .= ">\n";
if ($this->ruleList !== null) {
for($i=0,$_i=count($this->ruleList); $i < $_i; $i++) {
$result .= $this->ruleList[$i]->toString();
}
}
$result .= "</validator>\n";
return $result;
}
}

View File

@ -0,0 +1,141 @@
<?php
/*
* $Id: XMLElement.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
/**
* An abstract class for elements represented by XML tags (e.g. Column, Table).
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
abstract class XMLElement {
protected $attributes = array();
protected $vendorSpecificInfo = array();
/**
* Replaces the old loadFromXML() so that we can use loadFromXML() to load the attribs into the class.
*/
abstract protected function setupObject();
/**
* This is the entry point method for loading data from XML.
* It calls a setupObject() method that must be implemented by the child class.
* @param array $attributes The attributes for the XML tag.
*/
public function loadFromXML($attributes) {
$this->attributes = array_change_key_case($attributes, CASE_LOWER);
$this->setupObject();
}
/**
* Returns the assoc array of attributes.
* All attribute names (keys) are lowercase.
* @return array
*/
public function getAttributes() {
return $this->attributes;
}
/**
* Gets a particular attribute by [case-insensitive] name.
* If attribute is not set then the $defaultValue is returned.
* @param string $name The [case-insensitive] name of the attribute to lookup.
* @param mixed $defaultValue The default value to use in case the attribute is not set.
* @return mixed The value of the attribute or $defaultValue if not set.
*/
public function getAttribute($name, $defaultValue = null) {
$name = strtolower($name);
if (isset($this->attributes[$name])) {
return $this->attributes[$name];
} else {
return $defaultValue;
}
}
/**
* Converts value specified in XML to a boolean value.
* This is to support the default value when used w/ a boolean column.
* @return value
*/
protected function booleanValue($val) {
if (is_numeric($val)) {
return (bool) $val;
} else {
return (in_array(strtolower($val), array('true', 't', 'y', 'yes'), true) ? true : false);
}
}
/**
* Sets vendor specific parameter that applies to this object.
* @param string $name
* @param string $value
*/
public function setVendorParameter($name, $value)
{
$this->vendorSpecificInfo[$name] = $value;
}
/**
* Whether specified vendor specific information is set.
* @param string $name
* @return boolean
*/
public function hasVendorParameter($name)
{
return isset($this->vendorSpecificInfo[$name]);
}
/**
* Returns specified vendor specific information is set.
* @param string $name
* @return string
*/
public function getVendorParameter($name)
{
if (isset($this->vendorSpecificInfo[$name])) {
return $this->vendorSpecificInfo[$name];
}
return null; // just to be explicit
}
/**
* Sets vendor specific information for this object.
* @param array $info
*/
public function setVendorSpecificInfo($info)
{
$this->vendorSpecificInfo = $info;
}
/**
* Retrieves vendor specific information for this object.
* @return array
*/
public function getVendorSpecificInfo()
{
return $this->vendorSpecificInfo;
}
}

View File

@ -0,0 +1,420 @@
<?php
/*
* $Id: XmlToAppData.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'propel/engine/database/model/AppData.php';
// Phing dependencies
require_once 'phing/parser/AbstractHandler.php';
include_once 'phing/system/io/FileReader.php';
/**
* A class that is used to parse an input xml schema file and creates an AppData
* PHP object.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Leon Messerschmidt <leon@opticode.co.za> (Torque)
* @author Jason van Zyl <jvanzyl@apache.org> (Torque)
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @author Daniel Rall <dlr@collab.net> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.transform
*/
class XmlToAppData extends AbstractHandler {
/** enables debug output */
const DEBUG = false;
private $app;
private $platform;
private $currDB;
private $currTable;
private $currColumn;
private $currFK;
private $currIndex;
private $currUnique;
private $currValidator;
private $currVendorObject;
private $isForReferenceOnly;
private $currentPackage;
private $currentXmlFile;
private $defaultPackage;
private $encoding;
/** two-dimensional array,
first dimension is for schemas(key is the path to the schema file),
second is for tags within the schema */
private $schemasTagsStack = array();
public $parser;
/**
* Creates a new instance for the specified database type.
*
* @param Platform $platform The type of database for the application.
* @param string $defaultPackage the default PHP package used for the om
* @param string $encoding The database encoding.
*/
public function __construct(Platform $platform, $defaultPackage, $encoding = 'iso-8859-1')
{
$this->app = new AppData($platform);
$this->platform = $platform;
$this->defaultPackage = $defaultPackage;
$this->firstPass = true;
$this->encoding = $encoding;
}
/**
* Parses a XML input file and returns a newly created and
* populated AppData structure.
*
* @param string $xmlFile The input file to parse.
* @return AppData populated by <code>xmlFile</code>.
*/
public function parseFile($xmlFile)
{
// we don't want infinite recursion
if($this->isAlreadyParsed($xmlFile)) {
return;
}
$domDocument = new DomDocument('1.0', 'UTF-8');
$domDocument->load($xmlFile);
// store current schema file path
$this->schemasTagsStack[$xmlFile] = array();
$this->currentXmlFile = $xmlFile;
try {
$fr = new FileReader($xmlFile);
} catch (Exception $e) {
$f = new PhingFile($xmlFile);
throw new Exception("XML File not found: " . $f->getAbsolutePath());
}
$br = new BufferedReader($fr);
$this->parser = new ExpatParser($br);
$this->parser->parserSetOption(XML_OPTION_CASE_FOLDING, 0);
$this->parser->setHandler($this);
try {
$this->parser->parse();
} catch (Exception $e) {
$br->close();
throw $e;
}
$br->close();
array_pop($this->schemasTagsStack);
return $this->app;
}
/**
* Handles opening elements of the xml file.
*
* @param string $uri
* @param string $localName The local name (without prefix), or the empty string if
* Namespace processing is not being performed.
* @param string $rawName The qualified name (with prefix), or the empty string if
* qualified names are not available.
* @param string $attributes The specified or defaulted attributes
*/
public function startElement($name, $attributes) {
try {
$parentTag = $this->peekCurrentSchemaTag();
if ($parentTag === false) {
switch($name) {
case "database":
if ($this->isExternalSchema()) {
$this->currentPackage = @$attributes["package"];
if ($this->currentPackage === null) {
$this->currentPackage = $this->defaultPackage;
}
} else {
$this->currDB = $this->app->addDatabase($attributes);
}
break;
default:
$this->_throwInvalidTagException($name);
}
} elseif ($parentTag == "database") {
switch($name) {
case "external-schema":
$xmlFile = @$attributes["filename"];
//"referenceOnly" attribute is valid in the main schema XML file only,
//and it's ingnored in the nested external-schemas
if(!$this->isExternalSchema()) {
$isForRefOnly = @$attributes["referenceOnly"];
$this->isForReferenceOnly = ($isForRefOnly !== null ? (strtolower($isForRefOnly) === "true") : true); // defaults to TRUE
}
if ($xmlFile{0} != '/') {
$f = new PhingFile($this->currentXmlFile);
$xf = new PhingFile($f->getParent(), $xmlFile);
$xmlFile = $xf->getPath();
}
$this->parseFile($xmlFile);
break;
case "domain":
$this->currDB->addDomain($attributes);
break;
case "table":
$this->currTable = $this->currDB->addTable($attributes);
if ($this->isExternalSchema()) {
$this->currTable->setForReferenceOnly($this->isForReferenceOnly);
$this->currTable->setPackage($this->currentPackage);
}
break;
case "vendor":
$this->currVendorObject = new ObjectWithVendorSpecificData($this->currDB, $attributes['type']);
break;
default:
$this->_throwInvalidTagException($name);
}
} elseif ($parentTag == "table") {
switch($name) {
case "column":
$this->currColumn = $this->currTable->addColumn($attributes);
break;
case "foreign-key":
$this->currFK = $this->currTable->addForeignKey($attributes);
break;
case "index":
$this->currIndex = $this->currTable->addIndex($attributes);
break;
case "unique":
$this->currUnique = $this->currTable->addUnique($attributes);
break;
case "vendor":
$this->currVendorObject = new ObjectWithVendorSpecificData($this->currTable, $attributes['type']);
break;
case "validator":
$this->currValidator = $this->currTable->addValidator($attributes);
break;
case "id-method-parameter":
$this->currTable->addIdMethodParameter($attributes);
break;
default:
$this->_throwInvalidTagException($name);
}
} elseif ($parentTag == "column") {
switch($name) {
case "inheritance":
$this->currColumn->addInheritance($attributes);
break;
case "vendor":
$this->currVendorObject = new ObjectWithVendorSpecificData($this->currColumn, $attributes['type']);
break;
default:
$this->_throwInvalidTagException($name);
}
} elseif ($parentTag == "foreign-key") {
switch($name) {
case "reference":
$this->currFK->addReference($attributes);
break;
case "vendor":
$this->currVendorObject = new ObjectWithVendorSpecificData($this->currFK, $attributes['type']);
break;
default:
$this->_throwInvalidTagException($name);
}
} elseif ($parentTag == "index") {
switch($name) {
case "index-column":
$this->currIndex->addColumn($attributes);
break;
case "vendor":
$this->currVendorObject = new ObjectWithVendorSpecificData($this->currIndex, $attributes['type']);
break;
default:
$this->_throwInvalidTagException($name);
}
} elseif ($parentTag == "unique") {
switch($name) {
case "unique-column":
$this->currUnique->addColumn($attributes);
break;
case "vendor":
$this->currVendorObject = new ObjectWithVendorSpecificData($this->currUnique, $attributes['type']);
break;
default:
$this->_throwInvalidTagException($name);
}
} elseif ($parentTag == "validator") {
switch($name) {
case "rule":
$this->currValidator->addRule($attributes);
break;
default:
$this->_throwInvalidTagException($name);
}
} elseif ($parentTag == "vendor") {
switch($name) {
case "parameter":
if($this->currVendorObject->isCompatible($this->platform->getDatabaseType())) {
$this->currVendorObject->setVendorParameter($attributes['name'], iconv('utf-8',$this->encoding, $attributes['value']));
}
break;
default:
$this->_throwInvalidTagException($name);
}
} else {
// it must be an invalid tag
$this->_throwInvalidTagException($name);
}
$this->pushCurrentSchemaTag($name);
} catch (BuildException $e) {
throw $e;
} catch (Exception $e) {
echo $e;
echo "\n";
throw $e;
}
}
function _throwInvalidTagException($tag_name)
{
throw new BuildException("Unexpected tag <" . $tag_name . ">", $this->parser->getLocation());
}
/**
* Handles closing elements of the xml file.
*
* @param uri
* @param localName The local name (without prefix), or the empty string if
* Namespace processing is not being performed.
* @param rawName The qualified name (with prefix), or the empty string if
* qualified names are not available.
*/
public function endElement($name)
{
if (self::DEBUG) {
print("endElement(" . $name . ") called\n");
}
$this->popCurrentSchemaTag();
}
protected function peekCurrentSchemaTag()
{
$keys = array_keys($this->schemasTagsStack);
return end($this->schemasTagsStack[end($keys)]);
}
protected function popCurrentSchemaTag()
{
$keys = array_keys($this->schemasTagsStack);
array_pop($this->schemasTagsStack[end($keys)]);
}
protected function pushCurrentSchemaTag($tag)
{
$keys = array_keys($this->schemasTagsStack);
$this->schemasTagsStack[end($keys)][] = $tag;
}
protected function isExternalSchema()
{
return (sizeof($this->schemasTagsStack) > 1);
}
protected function isAlreadyParsed($filePath)
{
return isset($this->schemasTagsStack[$filePath]);
}
}
/**
* Utility class used for objects with vendor data.
*
* @package propel.engine.database.transform
*/
class ObjectWithVendorSpecificData
{
protected $object;
protected $vendorType;
public function __construct($object, $vendorType)
{
$this->object = $object;
$this->vendorType = $vendorType;
}
public function isCompatible($type)
{
return ($this->vendorType == $type);
}
public function setVendorParameter($name, $value)
{
$this->object->setVendorParameter($name, $value);
}
}

View File

@ -0,0 +1,189 @@
<?php
/*
* $Id: XmlToData.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'phing/parser/AbstractHandler.php';
/**
* A Class that is used to parse an input xml schema file and creates an
* AppData object.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Leon Messerschmidt <leon@opticode.co.za> (Torque)
* @author Jason van Zyl <jvanzyl@apache.org> (Torque)
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @author Fedor Karpelevitch <fedor.karpelevitch@home.com> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.transform
*/
class XmlToData extends AbstractHandler {
private $database;
private $data;
private $encoding;
public $parser;
const DEBUG = false;
/**
* Construct new XmlToData class.
*
* This class is passed the Database object so that it knows what to expect from
* the XML file.
*
* @param Database $database
*/
public function __construct(Database $database, $encoding = 'iso-8859-1')
{
$this->database = $database;
$this->encoding = $encoding;
}
/**
*
*/
public function parseFile($xmlFile)
{
try {
$this->data = array();
try {
$fr = new FileReader($xmlFile);
} catch (Exception $e) {
$f = new PhingFile($xmlFile);
throw new BuildException("XML File not found: " . $f->getAbsolutePath());
}
$br = new BufferedReader($fr);
$this->parser = new ExpatParser($br);
$this->parser->parserSetOption(XML_OPTION_CASE_FOLDING, 0);
$this->parser->setHandler($this);
try {
$this->parser->parse();
} catch (Exception $e) {
print $e->getMessage() . "\n";
$br->close();
}
$br->close();
} catch (Exception $e) {
print $e->getMessage() . "\n";
print $e->getTraceAsString();
}
return $this->data;
}
/**
* Handles opening elements of the xml file.
*/
public function startElement($name, $attributes)
{
try {
if ($name == "dataset") {
// we don't do anything w/ <dataset> tag right now.
} else {
$table = $this->database->getTableByPhpName($name);
$this->columnValues = array();
foreach($attributes as $name => $value) {
$col = $table->getColumnByPhpName($name);
$this->columnValues[] = new ColumnValue($col, iconv('utf-8',$this->encoding, $value));
}
$this->data[] = new DataRow($table, $this->columnValues);
}
} catch (Exception $e) {
print $e;
throw $e;
}
}
/**
* Handles closing elements of the xml file.
*
* @param $name The local name (without prefix), or the empty string if
* Namespace processing is not being performed.
*/
public function endElement($name)
{
if (self::DEBUG) {
print("endElement(" . $name . ") called\n");
}
}
} // XmlToData
/**
* "inner class"
* @package propel.engine.database.transform
*/
class DataRow
{
private $table;
private $columnValues;
public function __construct(Table $table, $columnValues)
{
$this->table = $table;
$this->columnValues = $columnValues;
}
public function getTable()
{
return $this->table;
}
public function getColumnValues()
{
return $this->columnValues;
}
}
/**
* "inner" class
* @package propel.engine.database.transform
*/
class ColumnValue {
private $col;
private $val;
public function __construct(Column $col, $val)
{
$this->col = $col;
$this->val = $val;
}
public function getColumn()
{
return $this->col;
}
public function getValue()
{
return $this->val;
}
}

View File

@ -0,0 +1,169 @@
<?php
/*
* $Id: DefaultPlatform.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/platform/Platform.php';
include_once 'propel/engine/database/model/Domain.php';
/**
* Default implementation for the Platform interface.
*
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @version $Revision: 536 $
* @package propel.engine.platform
*/
class DefaultPlatform implements Platform {
private $schemaDomainMap;
/**
* Default constructor.
*/
public function __construct()
{
$this->initialize();
}
protected function initialize()
{
$this->schemaDomainMap = array();
foreach(PropelTypes::getPropelTypes() as $type) {
$this->schemaDomainMap[$type] = new Domain($type);
}
$this->schemaDomainMap[PropelTypes::BU_DATE] = new Domain("DATE");
$this->schemaDomainMap[PropelTypes::BU_TIMESTAMP] = new Domain("TIMESTAMP");
$this->schemaDomainMap[PropelTypes::BOOLEAN] = new Domain("INTEGER");
}
protected function setSchemaDomainMapping(Domain $domain)
{
$this->schemaDomainMap[$domain->getType()] = $domain;
}
/**
* Returns the short name of the database type that this platform represents.
* For example MysqlPlatform->getDatabaseType() returns 'mysql'.
* @return string
*/
public function getDatabaseType()
{
$clazz = get_class($this);
$pos = strpos($clazz, 'Platform');
return strtolower(substr($clazz,0,$pos));
}
/**
* @see Platform::getMaxColumnNameLength()
*/
public function getMaxColumnNameLength()
{
return 64;
}
/**
* @see Platform::getNativeIdMethod()
*/
public function getNativeIdMethod()
{
return Platform::IDENTITY;
}
/**
* @see Platform::getDomainForType()
*/
public function getDomainForType($propelType)
{
if (!isset($this->schemaDomainMap[$propelType])) {
throw new EngineException("Cannot map unknown Propel type " . var_export($propelType, true) . " to native database type.");
}
return $this->schemaDomainMap[$propelType];
}
/**
* @return Only produces a SQL fragment if null values are
* disallowed.
* @see Platform::getNullString(boolean)
*/
public function getNullString($notNull)
{
// TODO: Check whether this is true for all DBs. Also verify
// the old Sybase templates.
return ($notNull ? "NOT NULL" : "");
}
/**
* @see Platform::getAutoIncrement()
*/
public function getAutoIncrement()
{
return "IDENTITY";
}
/**
* @see Platform::hasScale(String)
* TODO collect info for all platforms
*/
public function hasScale($sqlType)
{
return true;
}
/**
* @see Platform::hasSize(String)
* TODO collect info for all platforms
*/
public function hasSize($sqlType)
{
return true;
}
/**
* @see Platform::escapeText()
*/
public function escapeText($text)
{
return str_replace("'", "''", $text);
}
/**
* @see Platform::quoteIdentifier()
*/
public function quoteIdentifier($text)
{
return '"' . $text . '"';
}
/**
* @see Platform::supportsNativeDeleteTrigger()
*/
public function supportsNativeDeleteTrigger()
{
return false;
}
/**
* @see Platform::getBooleanString()
*/
public function getBooleanString($b)
{
$b = ($b === true || strtolower($b) === 'true' || $b === 1 || $b === '1' || strtolower($b) === 'y' || strtolower($b) === 'yes');
return ($b ? '1' : '0');
}
}

View File

@ -0,0 +1,99 @@
<?php
/*
* $Id: MssqlPlatform.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/platform/DefaultPlatform.php';
include_once 'propel/engine/database/model/Domain.php';
/**
* MS SQL Platform implementation.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @version $Revision: 536 $
* @package propel.engine.platform
*/
class MssqlPlatform extends DefaultPlatform {
/**
* Initializes db specific domain mapping.
*/
protected function initialize()
{
parent::initialize();
$this->setSchemaDomainMapping(new Domain(PropelTypes::INTEGER, "INT"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BOOLEAN, "INT"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::DOUBLE, "FLOAT"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARCHAR, "TEXT"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::CLOB, "TEXT"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::DATE, "DATETIME"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BU_DATE, "DATETIME"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::TIME, "DATETIME"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::TIMESTAMP, "DATETIME"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BU_TIMESTAMP, "DATETIME"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BINARY, "BINARY(7132)"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::VARBINARY, "IMAGE"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARBINARY, "IMAGE"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BLOB, "IMAGE"));
}
/**
* @see Platform#getMaxColumnNameLength()
*/
public function getMaxColumnNameLength()
{
return 128;
}
/**
* @return Explicitly returns <code>NULL</code> if null values are
* allowed (as recomended by Microsoft).
* @see Platform#getNullString(boolean)
*/
public function getNullString($notNull)
{
return ($notNull ? "NOT NULL" : "NULL");
}
/**
* @see Platform::supportsNativeDeleteTrigger()
*/
public function supportsNativeDeleteTrigger()
{
return true;
}
/**
* @see Platform::hasSize(String)
*/
public function hasSize($sqlType)
{
return !("INT" == $sqlType || "TEXT" == $sqlType);
}
/**
* @see Platform::quoteIdentifier()
*/
public function quoteIdentifier($text)
{
return '[' . $text . ']';
}
}

View File

@ -0,0 +1,105 @@
<?php
/*
* $Id: MysqlPlatform.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/platform/DefaultPlatform.php';
/**
* MySql Platform implementation.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @version $Revision: 536 $
* @package propel.engine.platform
*/
class MysqlPlatform extends DefaultPlatform {
/**
* Initializes db specific domain mapping.
*/
protected function initialize()
{
parent::initialize();
$this->setSchemaDomainMapping(new Domain(PropelTypes::NUMERIC, "DECIMAL"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARCHAR, "TEXT"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::TIMESTAMP, "DATETIME"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BU_TIMESTAMP, "DATETIME"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BINARY, "BLOB"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::VARBINARY, "MEDIUMBLOB"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARBINARY, "LONGBLOB"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BLOB, "LONGBLOB"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::CLOB, "LONGTEXT"));
}
/**
* @see Platform#getAutoIncrement()
*/
public function getAutoIncrement()
{
return "AUTO_INCREMENT";
}
/**
* @see Platform#getMaxColumnNameLength()
*/
public function getMaxColumnNameLength()
{
return 64;
}
/**
* @see Platform::supportsNativeDeleteTrigger()
*/
public function supportsNativeDeleteTrigger()
{
$usingInnoDB = false;
if(class_exists('DataModelBuilder', false))
{
$usingInnoDB = strtolower(DataModelBuilder::getBuildProperty('mysqlTableType')) == 'innodb';
}
return $usingInnoDB || false;
}
/**
* @see Platform#hasSize(String)
*/
public function hasSize($sqlType) {
return !("MEDIUMTEXT" == $sqlType || "LONGTEXT" == $sqlType
|| "BLOB" == $sqlType || "MEDIUMBLOB" == $sqlType
|| "LONGBLOB" == $sqlType);
}
/**
* Escape the string for RDBMS.
* @param string $text
* @return string
*/
public function escapeText($text) {
return mysql_escape_string($text);
}
/**
* @see Platform::quoteIdentifier()
*/
public function quoteIdentifier($text)
{
return '`' . $text . '`';
}
}

View File

@ -0,0 +1,58 @@
<?php
/*
* $Id: MysqliPlatform.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/platform/MysqlPlatform.php';
/**
* MySql Platform implementation, using new mysqli API.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @version $Revision: 536 $
* @package propel.engine.platform
*/
class MysqliPlatform extends MysqlPlatform {
/**
* Initializes db specific domain mapping.
*/
protected function initialize()
{
parent::initialize();
// HL -- commenting these out, as it turns out that while the date format is fixed
// there is still a special meaning to TIMESTAMP in MySQL 4.1+
// $this->setSchemaDomainMapping(new Domain(PropelTypes::TIMESTAMP, "TIMESTAMP"));
// $this->setSchemaDomainMapping(new Domain(PropelTypes::BU_TIMESTAMP, "TIMESTAMP"));
}
/**
* Escape the string for MySQL.
*
* @param string $text
* @return string
*/
public function escapeText($text) {
// Because mysqli requires open connection, we are using addslashes() here.
// This needs to be fixed in a better way ...
return addslashes($text);
}
}

View File

@ -0,0 +1,89 @@
<?php
/*
* $Id: OraclePlatform.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/platform/DefaultPlatform.php';
/**
* Oracle Platform implementation.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @version $Revision: 536 $
* @package propel.engine.platform
*/
class OraclePlatform extends DefaultPlatform {
/**
* Initializes db specific domain mapping.
*/
protected function initialize()
{
parent::initialize();
$this->setSchemaDomainMapping(new Domain(PropelTypes::BOOLEAN, "NUMBER", "1", "0"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::TINYINT, "NUMBER", "3", "0"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::SMALLINT, "NUMBER", "5", "0"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::INTEGER, "NUMBER"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BIGINT, "NUMBER", "20", "0"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::REAL, "NUMBER"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::DOUBLE, "FLOAT"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::DECIMAL, "NUMBER"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::NUMERIC, "NUMBER"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::VARCHAR, "VARCHAR2"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARCHAR, "VARCHAR2", "2000"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::TIME, "DATE"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::TIMESTAMP, "DATE"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BINARY, "LONG RAW"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::VARBINARY, "BLOB"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARBINARY, "LONG RAW"));
}
/**
* @see Platform#getMaxColumnNameLength()
*/
public function getMaxColumnNameLength()
{
return 30;
}
/**
* @see Platform#getNativeIdMethod()
*/
public function getNativeIdMethod()
{
return Platform::SEQUENCE;
}
/**
* @see Platform#getAutoIncrement()
*/
public function getAutoIncrement()
{
return "";
}
/**
* @see Platform::supportsNativeDeleteTrigger()
*/
public function supportsNativeDeleteTrigger()
{
return true;
}
}

View File

@ -0,0 +1,114 @@
<?php
/*
* $Id: PgsqlPlatform.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/platform/DefaultPlatform.php';
/**
* Postgresql Platform implementation.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @version $Revision: 536 $
* @package propel.engine.platform
*/
class PgsqlPlatform extends DefaultPlatform {
/**
* Initializes db specific domain mapping.
*/
protected function initialize()
{
parent::initialize();
$this->setSchemaDomainMapping(new Domain(PropelTypes::BOOLEAN, "BOOLEAN"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::TINYINT, "INT2"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::SMALLINT, "INT2"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BIGINT, "INT8"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::REAL, "FLOAT"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::DOUBLE, "DOUBLE PRECISION"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARCHAR, "TEXT"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BINARY, "BYTEA"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::VARBINARY, "BYTEA"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARBINARY, "BYTEA"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BLOB, "BYTEA"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::CLOB, "TEXT"));
}
/**
* @see Platform#getNativeIdMethod()
*/
public function getNativeIdMethod()
{
return Platform::SEQUENCE;
}
/**
* @see Platform#getAutoIncrement()
*/
public function getAutoIncrement()
{
return "";
}
/**
* @see Platform#getMaxColumnNameLength()
*/
public function getMaxColumnNameLength()
{
return 32;
}
/**
* Escape the string for RDBMS.
* @param string $text
* @return string
*/
public function escapeText($text) {
return pg_escape_string($text);
}
/**
* @see Platform::getBooleanString()
*/
public function getBooleanString($b)
{
// parent method does the checking for allowes tring
// representations & returns integer
$b = parent::getBooleanString($b);
return ($b ? "'t'" : "'f'");
}
/**
* @see Platform::supportsNativeDeleteTrigger()
*/
public function supportsNativeDeleteTrigger()
{
return true;
}
/**
* @see Platform::hasSize(String)
* TODO collect info for all platforms
*/
public function hasSize($sqlType)
{
return !("BYTEA" == $sqlType || "TEXT" == $sqlType);
}
}

View File

@ -0,0 +1,128 @@
<?php
/*
* $Id: Platform.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
/**
* Interface for RDBMS platform specific behaviour.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @version $Revision: 536 $
* @package propel.engine.platform
*/
interface Platform {
/** constant for native id method */
const IDENTITY = "identity";
/** constant for native id method */
const SEQUENCE = "sequence";
/**
* Returns the short name of the database type that this platform represents.
* For example MysqlPlatform->getDatabaseType() returns 'mysql'.
* @return string
*/
public function getDatabaseType();
/**
* Returns the native IdMethod (sequence|identity)
*
* @return string The native IdMethod (Platform:IDENTITY, Platform::SEQUENCE).
*/
public function getNativeIdMethod();
/**
* Returns the max column length supported by the db.
*
* @return int The max column length
*/
public function getMaxColumnNameLength();
/**
* Returns the db specific domain for a jdbcType.
*
* @param string $creoleType the creole type name.
* @return Domain The db specific domain.
*/
public function getDomainForType($creoleType);
/**
* @return string The RDBMS-specific SQL fragment for <code>NULL</code>
* or <code>NOT NULL</code>.
*/
public function getNullString($notNull);
/**
* @return The RDBMS-specific SQL fragment for autoincrement.
*/
public function getAutoIncrement();
/**
* Returns if the RDBMS-specific SQL type has a size attribute.
*
* @param string $sqlType the SQL type
* @return boolean True if the type has a size attribute
*/
public function hasSize($sqlType);
/**
* Returns if the RDBMS-specific SQL type has a scale attribute.
*
* @param string $sqlType the SQL type
* @return boolean True if the type has a scale attribute
*/
public function hasScale($sqlType);
/**
* Escape the string for RDBMS.
* @param string $text
* @return string
*/
public function escapeText($text);
/**
* Quotes identifiers used in database SQL.
* @param string $text
* @return string Quoted identifier.
*/
public function quoteIdentifier($text);
/**
* Whether RDBMS supports native ON DELETE triggers (e.g. ON DELETE CASCADE).
* @return boolean
*/
public function supportsNativeDeleteTrigger();
/**
* Returns the boolean value for the RDBMS.
*
* This value should match the boolean value that is set
* when using Creole's PreparedStatement::setBoolean().
*
* This function is used to set default column values when building
* SQL.
*
* @param mixed $tf A boolean or string representation of boolean ('y', 'true').
* @return mixed
*/
public function getBooleanString($tf);
}

View File

@ -0,0 +1,92 @@
<?php
/*
* $Id: SqlitePlatform.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/platform/DefaultPlatform.php';
/**
* SQLite Platform implementation.
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 536 $
* @package propel.engine.platform
*/
class SqlitePlatform extends DefaultPlatform {
/**
* Initializes db specific domain mapping.
*/
protected function initialize()
{
parent::initialize();
$this->setSchemaDomainMapping(new Domain(PropelTypes::NUMERIC, "DECIMAL"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARCHAR, "MEDIUMTEXT"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::DATE, "DATETIME"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BINARY, "BLOB"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::VARBINARY, "MEDIUMBLOB"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARBINARY, "LONGBLOB"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BLOB, "LONGBLOB"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::CLOB, "LONGTEXT"));
}
/**
* @see Platform#getAutoIncrement()
* @link http://www.sqlite.org/autoinc.html
*/
public function getAutoIncrement()
{
return "PRIMARY KEY";
}
/**
* @see Platform#getMaxColumnNameLength()
*/
public function getMaxColumnNameLength()
{
return 1024;
}
/**
* @see Platform#hasSize(String)
*/
public function hasSize($sqlType) {
return !("MEDIUMTEXT" == $sqlType || "LONGTEXT" == $sqlType
|| "BLOB" == $sqlType || "MEDIUMBLOB" == $sqlType
|| "LONGBLOB" == $sqlType);
}
/**
* Escape the string for RDBMS.
* @param string $text
* @return string
*/
public function escapeText($text) {
return sqlite_escape_string($text);
}
/**
* @see Platform::quoteIdentifier()
*/
public function quoteIdentifier($text)
{
return '[' . $text . ']';
}
}

View File

@ -0,0 +1,635 @@
<?php
/*
* $Id: AbstractPropelDataModelTask.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
//include_once 'phing/tasks/ext/CapsuleTask.php';
require_once 'phing/Task.php';
include_once 'propel/engine/database/model/AppData.php';
include_once 'propel/engine/database/model/Database.php';
include_once 'propel/engine/database/transform/XmlToAppData.php';
/**
* An abstract base Propel task to perform work related to the XML schema file.
*
* The subclasses invoke templates to do the actual writing of the resulting files.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Jason van Zyl <jvanzyl@zenplex.com> (Torque)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @package propel.phing
*/
abstract class AbstractPropelDataModelTask extends Task {
/**
* Fileset of XML schemas which represent our data models.
* @var array Fileset[]
*/
protected $schemaFilesets = array();
/**
* Data models that we collect. One from each XML schema file.
*/
protected $dataModels = array();
/**
* Have datamodels been initialized?
* @var boolean
*/
private $dataModelsLoaded = false;
/**
* Map of data model name to database name.
* Should probably stick to the convention
* of them being the same but I know right now
* in a lot of cases they won't be.
*/
protected $dataModelDbMap;
/**
* Hashtable containing the names of all the databases
* in our collection of schemas.
*/
protected $databaseNames; // doesn't seem to be used anywhere
/**
* The target database(s) we are generating SQL
* for. Right now we can only deal with a single
* target, but we will support multiple targets
* soon.
*/
protected $targetDatabase;
/**
* DB encoding to use for XmlToAppData object
*/
protected $dbEncoding = 'iso-8859-1';
/**
* Target PHP package to place the generated files in.
*/
protected $targetPackage;
/**
* @var Mapper
*/
protected $mapperElement;
/**
* Destination directory for results of template scripts.
* @var PhingFile
*/
protected $outputDirectory;
/**
* Path where Capsule looks for templates.
* @var PhingFile
*/
protected $templatePath;
/**
* Whether to package the datamodels or not
* @var PhingFile
*/
protected $packageObjectModel;
/**
* Whether to perform validation (XSD) on the schema.xml file(s).
* @var boolean
*/
protected $validate;
/**
* The XSD schema file to use for validation.
* @var PhingFile
*/
protected $xsdFile;
/**
* XSL file to use to normalize (or otherwise transform) schema before validation.
* @var PhingFile
*/
protected $xslFile;
/**
* Return the data models that have been
* processed.
*
* @return List data models
*/
public function getDataModels()
{
if (!$this->dataModelsLoaded) $this->loadDataModels();
return $this->dataModels;
}
/**
* Return the data model to database name map.
*
* @return Hashtable data model name to database name map.
*/
public function getDataModelDbMap()
{
if (!$this->dataModelsLoaded) $this->loadDataModels();
return $this->dataModelDbMap;
}
/**
* Adds a set of xml schema files (nested fileset attribute).
*
* @param set a Set of xml schema files
*/
public function addSchemaFileset(Fileset $set)
{
$this->schemaFilesets[] = $set;
}
/**
* Get the current target database.
*
* @return String target database(s)
*/
public function getTargetDatabase()
{
return $this->targetDatabase;
}
/**
* Set the current target database. (e.g. mysql, oracle, ..)
*
* @param v target database(s)
*/
public function setTargetDatabase($v)
{
$this->targetDatabase = $v;
}
/**
* Get the current target package.
*
* @return string target PHP package.
*/
public function getTargetPackage()
{
return $this->targetPackage;
}
/**
* Set the current target package. This is where generated PHP classes will
* live.
*
* @param string $v target PHP package.
*/
public function setTargetPackage($v)
{
$this->targetPackage = $v;
}
/**
* Set the packageObjectModel switch on/off
*
* @param string $v The build.property packageObjectModel
*/
public function setPackageObjectModel($v)
{
$this->packageObjectModel = ($v === '1' ? true : false);
}
/**
* Set whether to perform validation on the datamodel schema.xml file(s).
* @param boolean $v
*/
public function setValidate($v)
{
$this->validate = $v;
}
/**
* Set the XSD schema to use for validation of any datamodel schema.xml file(s).
* @param $v PhingFile
*/
public function setXsd(PhingFile $v)
{
$this->xsdFile = $v;
}
/**
* Set the normalization XSLT to use to transform datamodel schema.xml file(s) before validation and parsing.
* @param $v PhingFile
*/
public function setXsl(PhingFile $v)
{
$this->xslFile = $v;
}
/**
* [REQUIRED] Set the path where Capsule will look
* for templates using the file template
* loader.
* @return void
* @throws Exception
*/
public function setTemplatePath($templatePath) {
$resolvedPath = "";
$tok = strtok($templatePath, ",");
while ( $tok ) {
// resolve relative path from basedir and leave
// absolute path untouched.
$fullPath = $this->project->resolveFile($tok);
$cpath = $fullPath->getCanonicalPath();
if ($cpath === false) {
$this->log("Template directory does not exist: " . $fullPath->getAbsolutePath());
} else {
$resolvedPath .= $cpath;
}
$tok = strtok(",");
if ( $tok ) {
$resolvedPath .= ",";
}
}
$this->templatePath = $resolvedPath;
}
/**
* Get the path where Velocity will look
* for templates using the file template
* loader.
* @return string
*/
public function getTemplatePath() {
return $this->templatePath;
}
/**
* [REQUIRED] Set the output directory. It will be
* created if it doesn't exist.
* @param PhingFile $outputDirectory
* @return void
* @throws Exception
*/
public function setOutputDirectory(PhingFile $outputDirectory) {
try {
if (!$outputDirectory->exists()) {
$this->log("Output directory does not exist, creating: " . $outputDirectory->getPath(),PROJECT_MSG_VERBOSE);
if (!$outputDirectory->mkdirs()) {
throw new IOException("Unable to create Ouptut directory: " . $outputDirectory->getAbsolutePath());
}
}
$this->outputDirectory = $outputDirectory->getCanonicalPath();
} catch (IOException $ioe) {
throw new BuildException($ioe);
}
}
/**
* Set the current target database encoding.
*
* @param v target database encoding
*/
public function setDbEncoding($v)
{
$this->dbEncoding = $v;
}
/**
* Get the output directory.
* @return string
*/
public function getOutputDirectory() {
return $this->outputDirectory;
}
/**
* Nested creator, creates one Mapper for this task.
*
* @return Mapper The created Mapper type object.
* @throws BuildException
*/
public function createMapper() {
if ($this->mapperElement !== null) {
throw new BuildException("Cannot define more than one mapper.", $this->location);
}
$this->mapperElement = new Mapper($this->project);
return $this->mapperElement;
}
/**
* Maps the passed in name to a new filename & returns resolved File object.
* @param string $from
* @return PhingFile Resolved File object.
* @throws BuilException - if no Mapper element se
* - if unable to map new filename.
*/
protected function getMappedFile($from)
{
if(!$this->mapperElement) {
throw new BuildException("This task requires you to use a <mapper/> element to describe how filename changes should be handled.");
}
$mapper = $this->mapperElement->getImplementation();
$mapped = $mapper->main($from);
if (!$mapped) {
throw new BuildException("Cannot create new filename based on: " . $from);
}
// Mappers always return arrays since it's possible for some mappers to map to multiple names.
$outFilename = array_shift($mapped);
$outFile = new PhingFile($this->getOutputDirectory(), $outFilename);
return $outFile;
}
/**
* Get the Platform class based on the target database type.
* @return Platform Class that implements the Platform interface.
*/
protected function getPlatformForTargetDatabase()
{
$classpath = $this->getPropelProperty("platformClass");
if (empty($classpath)) {
throw new BuildException("Unable to find class path for '$propname' property.");
}
// This is a slight hack to workaround camel case inconsistencies for the DDL classes.
// Basically, we want to turn ?.?.?.sqliteDDLBuilder into ?.?.?.SqliteDDLBuilder
$lastdotpos = strrpos($classpath, '.');
if ($lastdotpos) $classpath{$lastdotpos+1} = strtoupper($classpath{$lastdotpos+1});
else ucfirst($classpath);
if (empty($classpath)) {
throw new BuildException("Unable to find class path for '$propname' property.");
}
$clazz = Phing::import($classpath);
return new $clazz();
}
/**
* Gets all matching XML schema files and loads them into data models for class.
* @return void
*/
protected function loadDataModels()
{
$ads = array();
// Get all matched files from schemaFilesets
foreach($this->schemaFilesets as $fs) {
$ds = $fs->getDirectoryScanner($this->project);
$srcDir = $fs->getDir($this->project);
$dataModelFiles = $ds->getIncludedFiles();
$platform = $this->getPlatformForTargetDatabase();
// Make a transaction for each file
foreach($dataModelFiles as $dmFilename) {
$this->log("Processing: ".$dmFilename);
$xmlFile = new PhingFile($srcDir, $dmFilename);
$dom = new DomDocument('1.0', 'UTF-8');
$dom->load($xmlFile->getAbsolutePath());
// normalize (or transform) the XML document using XSLT
if ($this->xslFile) {
$this->log("Transforming " . $xmlFile->getPath() . " using stylesheet " . $this->xslFile->getPath(), PROJECT_MSG_VERBOSE);
if (!class_exists('XSLTProcessor')) {
$this->log("Could not perform XLST transformation. Make sure PHP has been compiled/configured to support XSLT.", PROJECT_MSG_ERR);
} else {
// normalize the document using normalizer stylesheet
$xsl = new XsltProcessor();
$xsl->importStyleSheet(DomDocument::load($this->xslFile->getAbsolutePath()));
$transformed = $xsl->transformToDoc($dom);
$newXmlFilename = substr($xmlFile->getName(), 0, strrpos($xmlFile->getName(), '.')) . '-transformed.xml';
// now overwrite previous vars to point to newly transformed file
$xmlFile = new PhingFile($srcDir, $newXmlFilename);
$transformed->save($xmlFile->getAbsolutePath());
$this->log("\t- Using new (post-transformation) XML file: " . $xmlFile->getPath(), PROJECT_MSG_VERBOSE);
$dom = new DomDocument('1.0', 'UTF-8');
$dom->load($xmlFile->getAbsolutePath());
}
}
// validate the XML document using XSD schema
if ($this->validate && $this->xsdFile) {
$this->log("Validating XML doc (".$xmlFile->getPath().") using schema file " . $this->xsdFile->getPath(), PROJECT_MSG_VERBOSE);
if (!$dom->schemaValidate($this->xsdFile->getAbsolutePath())) {
throw new BuildException("XML schema file (".$xmlFile->getPath().") does not validate. See warnings above for reasons validation failed (make sure error_reporting is set to show E_WARNING if you don't see any)."); throw new EngineException("XML schema does not validate (using schema file $xsdFile). See warnings above for reasons validation failed (make sure error_reporting is set to show E_WARNING if you don't see any).", $this->getLocation());
}
}
$xmlParser = new XmlToAppData($platform, $this->getTargetPackage(), $this->dbEncoding);
$ad = $xmlParser->parseFile($xmlFile->getAbsolutePath());
$ad->setName($dmFilename); // <-- Important: use the original name, not the -transformed name.
$ads[] = $ad;
}
}
if (empty($ads)) {
throw new BuildException("No schema files were found (matching your schema fileset definition).");
}
if (!$this->packageObjectModel) {
$this->dataModels = $ads;
$this->databaseNames = array(); // doesn't seem to be used anywhere
$this->dataModelDbMap = array();
// Different datamodels may state the same database
// names, we just want the unique names of databases.
foreach($this->dataModels as $dm) {
$database = $dm->getDatabase();
$this->dataModelDbMap[$dm->getName()] = $database->getName();
$this->databaseNames[$database->getName()] = $database->getName(); // making list of *unique* dbnames.
}
} else {
$this->joinDatamodels($ads);
$this->dataModels[0]->getDatabases(); // calls doFinalInitialization()
}
$this->dataModelsLoaded = true;
}
/**
* Joins the datamodels collected from schema.xml files into one big datamodel
*
* This applies only when the the packageObjectModel option is set. We need to
* join the datamodels in this case to allow for foreign keys that point to
* tables in different packages.
*
* @param array $ads The datamodels to join
*/
protected function joinDatamodels($ads) {
foreach($ads as $ad) {
$db = $ad->getDatabase(null, false);
$this->dataModelDbMap[$ad->getName()] = $db->getName();
}
foreach ($ads as $addAd) {
$ad = &$this->dataModels[0];
if (!isset($ad)) {
$addAd->setName('JoinedDataModel');
$ad = $addAd;
continue;
}
foreach ($addAd->getDatabases(false) as $addDb) {
$addDbName = $addDb->getName();
if (!$package = $addDb->getPackage()) {
throw new BuildException('No package found for database "' . $addDbName . '" in ' . $addAd->getName() . '. The propel.packageObjectModel property requires the package attribute to be set for each database.');
}
$db = $ad->getDatabase($addDbName, false);
if (!$db) {
$ad->addDatabase($addDb);
continue;
}
foreach ($addDb->getTables() as $addTable) {
$table = $db->getTable($addTable->getName());
if ($table) {
throw new BuildException('Duplicate table found: ' . $addDbName . '.');
}
$db->addTable($addTable);
}
}
}
}
/**
* Creates a new Capsule context with some basic properties set.
* (Capsule is a simple PHP encapsulation system -- aka a php "template" class.)
* @return Capsule
*/
protected function createContext() {
$context = new Capsule();
// Make sure the output directory exists, if it doesn't
// then create it.
$outputDir = new PhingFile($this->outputDirectory);
if (!$outputDir->exists()) {
$this->log("Output directory does not exist, creating: " . $outputDir->getAbsolutePath());
$outputDir->mkdirs();
}
// Place our set of data models into the context along
// with the names of the databases as a convenience for now.
$context->put("targetDatabase", $this->targetDatabase);
$context->put("targetPackage", $this->targetPackage);
$context->put("now", strftime("%c"));
$this->log("Target database type: " . $this->targetDatabase);
$this->log("Target package: " . $this->targetPackage);
$this->log("Using template path: " . $this->templatePath);
$this->log("Output directory: " . $this->outputDirectory);
$context->setTemplatePath($this->templatePath);
$context->setOutputDirectory($this->outputDirectory);
$this->populateContextProperties($context);
return $context;
}
/**
* Fetches the propel.xxx properties from project, renaming the propel.xxx properties to just xxx.
*
* Also, renames any xxx.yyy properties to xxxYyy as PHP doesn't like the xxx.yyy syntax.
*
* @return array Assoc array of properties.
*/
protected function getPropelProperties()
{
$allProps = $this->getProject()->getProperties();
$renamedPropelProps = array();
foreach ($allProps as $key => $propValue) {
if (strpos($key, "propel.") === 0) {
$newKey = substr($key, strlen("propel."));
$j = strpos($newKey, '.');
while ($j !== false) {
$newKey = substr($newKey, 0, $j) . ucfirst(substr($newKey, $j + 1));
$j = strpos($newKey, '.');
}
$renamedPropelProps[$newKey] = $propValue;
}
}
return $renamedPropelProps;
}
/**
* Fetches a single propel.xxx property from project, using "converted" property names.
* @see getPropelProperties()
* @param string $name Name of property to fetch (in converted CamelCase)
* @return string The value of the property (or NULL if not set)
*/
protected function getPropelProperty($name)
{
$props = $this->getPropelProperties();
if (isset($props[$name])) {
return $props[$name];
}
return null; // just to be explicit
}
/**
* Adds the propel.xxx properties to the passed Capsule context, changing names to just xxx.
*
* Also, move xxx.yyy properties to xxxYyy as PHP doesn't like the xxx.yyy syntax.
*
* @param Capsule $context
* @see getPropelProperties()
*/
public function populateContextProperties(Capsule $context)
{
foreach ($this->getPropelProperties() as $key => $propValue) {
$this->log('Adding property ${' . $key . '} to context', PROJECT_MSG_DEBUG);
$context->put($key, $propValue);
}
}
/**
* Checks this class against Basic requrements of any propel datamodel task.
*
* @throws BuildException - if schema fileset was not defined
* - if no output directory was specified
*/
protected function validate()
{
if (empty($this->schemaFilesets)) {
throw new BuildException("You must specify a fileset of XML schemas.", $this->getLocation());
}
// Make sure the output directory is set.
if ($this->outputDirectory === null) {
throw new BuildException("The output directory needs to be defined!", $this->getLocation());
}
if ($this->validate) {
if (!$this->xsdFile) {
throw new BuildException("'validate' set to TRUE, but no XSD specified (use 'xsd' attribute).", $this->getLocation());
}
}
}
}

View File

@ -0,0 +1,777 @@
<?php
/*
* $Id: PropelCreoleTransformTask.php 538 2007-01-10 14:36:03Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'creole/Connection.php';
require_once 'phing/Task.php';
/**
* This class generates an XML schema of an existing database from
* Creole metadata.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Jason van Zyl <jvanzyl@periapt.com> (Torque)
* @author Fedor Karpelevitch <fedor.karpelevitch@barra.com> (Torque)
* @version $Revision: 538 $
* @package propel.phing
*/
class PropelCreoleTransformTask extends Task {
/** Name of XML database schema produced. */
protected $xmlSchema;
/** Creole URL. */
protected $dbUrl;
/** Creole driver. */
protected $dbDriver;
/** Creole user name. */
protected $dbUser;
/** Creole password. */
protected $dbPassword;
/** DB encoding to use */
protected $dbEncoding = 'iso-8859-1';
/** DB schema to use. */
protected $dbSchema;
/** parsed DB DSN */
protected $dsn;
/** DOM document produced. */
protected $doc;
/** The document root element. */
protected $databaseNode;
/** Hashtable of columns that have primary keys. */
protected $primaryKeys;
/** Hashtable to track what table a column belongs to. */
// doesn't seem to be used
// protected $columnTableMap;
/** whether to use same name for phpName or not */
protected $samePhpName;
/** whether to add vendor info or not */
protected $addVendorInfo;
/**
* Bitfield to switch on/off which validators will be created.
*
* @var int
*/
protected $validatorBits;
/**
* Collect validatorInfos to create validators.
*
* @var int
*/
protected $validatorInfos;
/**
* Zero bit for no validators
*/
const VALIDATORS_NONE = 0;
/**
* Bit for maxLength validator
*/
const VALIDATORS_MAXLENGTH = 1;
/**
* Bit for maxValue validator
*/
const VALIDATORS_MAXVALUE = 2;
/**
* Bit for type validator
*/
const VALIDATORS_TYPE = 4;
/**
* Bit for required validator
*/
const VALIDATORS_REQUIRED = 8;
/**
* Bit for unique validator
*/
const VALIDATORS_UNIQUE = 16;
/**
* Bit for all validators
*/
const VALIDATORS_ALL = 255;
/**
* Maps validator type tokens to bits
*
* The tokens are used in the propel.addValidators property to define
* which validators are to be added
*
* @static
* @var array
*/
static protected $validatorBitMap = array (
'none' => PropelCreoleTransformTask::VALIDATORS_NONE,
'maxlength' => PropelCreoleTransformTask::VALIDATORS_MAXLENGTH,
'maxvalue' => PropelCreoleTransformTask::VALIDATORS_MAXVALUE,
'type' => PropelCreoleTransformTask::VALIDATORS_TYPE,
'required' => PropelCreoleTransformTask::VALIDATORS_REQUIRED,
'unique' => PropelCreoleTransformTask::VALIDATORS_UNIQUE,
'all' => PropelCreoleTransformTask::VALIDATORS_ALL,
);
/**
* Defines messages that are added to validators
*
* @static
* @var array
*/
static protected $validatorMessages = array (
'maxlength' => array (
'msg' => 'The field %s must be not longer than %s characters.',
'var' => array('colName', 'value')
),
'maxvalue' => array (
'msg' => 'The field %s must be not greater than %s.',
'var' => array('colName', 'value')
),
'type' => array (
'msg' => 'The field %s is not a valid value.',
'var' => array('colName')
),
'required' => array (
'msg' => 'The field %s is required.',
'var' => array('colName')
),
'unique' => array (
'msg' => 'This %s already exists in table %s.',
'var' => array('colName', 'tableName')
),
);
public function getDbSchema()
{
return $this->dbSchema;
}
public function setDbSchema($dbSchema)
{
$this->dbSchema = $dbSchema;
}
public function setDbUrl($v)
{
$this->dbUrl = $v;
}
public function setDbDriver($v)
{
$this->dbDriver = $v;
}
public function setDbUser($v)
{
$this->dbUser = $v;
}
public function setDbPassword($v)
{
$this->dbPassword = $v;
}
public function setDbEncoding($v)
{
$this->dbEncoding = $v;
}
public function setOutputFile($v)
{
$this->xmlSchema = $v;
}
public function setSamePhpName($v)
{
$this->samePhpName = $v;
}
public function setAddVendorInfo($v)
{
$this->addVendorInfo = (boolean) $v;
}
/**
* Sets set validator bitfield from propel.addValidators property
*
* @param string $v The propel.addValidators property
* @return void
*/
public function setAddValidators($v)
{
// lowercase input
$v = strtolower($v);
// make it a bit expression
$v = str_replace(
array_keys(self::$validatorBitMap), self::$validatorBitMap, $v);
// check if it's a valid boolean expression
if (!preg_match('/[^\d|&~ ]/', $v)) {
// eval the expression
eval("\$v = $v;");
} else {
$this->log("\n\nERROR: NO VALIDATORS ADDED!\n\nThere is an error in propel.addValidators build property.\n\nAllowed tokens are: " . implode(', ', array_keys(self::$validatorBitMap)) . "\n\nAllowed operators are (like in php.ini):\n\n| bitwise OR\n& bitwise AND\n~ bitwise NOT\n\n", PROJECT_MSG_ERR);
$v = self::VALIDATORS_NONE;
}
$this->validatorBits = $v;
}
public function isSamePhpName()
{
return $this->samePhpName;
}
/**
* Default constructor.
* @return void
* @throws BuildException
*/
public function main()
{
$this->log("Propel - CreoleToXMLSchema starting");
$this->log("Your DB settings are:");
$this->log("driver : " . ($this->dbDriver ? $this->dbDriver : "(default)"));
$this->log("URL : " . $this->dbUrl);
//(not yet supported) $this->log("schema : " . $this->dbSchema);
//DocumentTypeImpl docType = new DocumentTypeImpl(null, "database", null,
// "http://jakarta.apache.org/turbine/dtd/database.dtd");
$this->doc = new DOMDocument('1.0', 'utf-8');
$this->doc->formatOutput = true; // pretty printing
$this->doc->appendChild($this->doc->createComment("Autogenerated by CreoleToXMLSchema!"));
try {
$this->generateXML();
$this->log("Writing XML to file: " . $this->xmlSchema);
$outFile = new PhingFile($this->xmlSchema);
$out = new FileWriter($outFile);
$xmlstr = $this->doc->saveXML();
$out->write($xmlstr);
$out->close();
} catch (Exception $e) {
$this->log("There was an error building XML from metadata: " . $e->getMessage(), PROJECT_MSG_ERR);
}
$this->log("Propel - CreoleToXMLSchema finished");
}
/**
* Generates an XML database schema from Creole metadata.
*
* @return void
* @throws Exception a generic exception.
*/
public function generateXML()
{
// Establish db connection
$con = $this->getConnection();
// Get the database Metadata.
$dbInfo = $con->getDatabaseInfo();
// create and add the database node
$databaseNode = $this->createDatabaseNode($dbInfo);
$this->doc->appendChild($databaseNode);
}
/**
* Establishes a Creole database connection
*
* @return object The connection
*/
protected function getConnection() {
// Attemtp to connect to a database.
$this->dsn = Creole::parseDSN($this->dbUrl);
if($this->dbUser) {
$this->dsn["username"] = $this->dbUser;
}
if ($this->dbPassword) {
$this->dsn["password"] = $this->dbPassword;
}
if ($this->dbDriver) {
Creole::registerDriver($this->dsn['phptype'], $this->dbDriver);
}
$con = Creole::getConnection($this->dsn);
$this->log("DB connection established");
return $con;
}
/**
* Creates a database node
*
* @param object $dbInfo The dbInfo for this db
* @return object The database node instance
*/
protected function createDatabaseNode($dbInfo) {
$this->log("Processing database");
$node = $this->doc->createElement("database");
$node->setAttribute("name", $dbInfo->getName());
if ($vendorNode = $this->createVendorInfoNode($dbInfo->getVendorSpecificInfo())) {
$node->appendChild($vendorNode);
}
// create and add table nodes
foreach($dbInfo->getTables() as $table) {
$tableNode = $this->createTableNode($table);
$node->appendChild($tableNode);
}
return $node;
}
/**
* Creates a table node
*
* @param object $table The table
* @return object The table node instance
*/
protected function createTableNode($table) {
$this->log("Processing table: " . $table->toString());
$node = $this->doc->createElement("table");
$node->setAttribute("name", $table->getName());
if ($this->isSamePhpName()) {
$node->setAttribute("phpName", $table->getName());
}
if ($vendorNode = $this->createVendorInfoNode($table->getVendorSpecificInfo())) {
$node->appendChild($vendorNode);
}
// Create and add column nodes, register column validators
$columns = $table->getColumns();
foreach($columns as $column) {
$columnNode = $this->createColumnNode($column);
$node->appendChild($columnNode);
$this->registerValidatorsForColumn($column);
if ($column->isAutoIncrement()) {
$idMethod = 'native';
}
}
if (isset($idMethod)) {
$node->setAttribute("idMethod", $idMethod);
}
// Create and add foreign key nodes.
$foreignKeys = $table->getForeignKeys();
foreach($foreignKeys as $foreignKey) {
$foreignKeyNode = $this->createForeignKeyNode($foreignKey);
$node->appendChild($foreignKeyNode);
}
// Create and add index nodes.
$indices = $table->getIndices();
foreach($indices as $index) {
$indexNode = $this->createIndexNode($index);
$node->appendChild($indexNode);
}
// add an id-method-parameter if we have a sequence that matches table_colname_seq
//
//
$pkey = $table->getPrimaryKey();
if ($pkey) {
$cols = $pkey->getColumns();
if (count($cols) === 1) {
$col = array_shift($cols);
if ($col->isAutoIncrement()) {
$seq_name = $table->getName().'_'.$col->getName().'_seq';
if ($table->getDatabase()->isSequence($seq_name)) {
$idMethodParameterNode = $this->doc->createElement("id-method-parameter");
$idMethodParameterNode->setAttribute("value", $seq_name);
$node->appendChild($idMethodParameterNode);
}
}
}
}
// Create and add validator and rule nodes.
$nodes = array();
$tableName = $table->getName();
if (isset($this->validatorInfos[$tableName])) {
foreach ($this->validatorInfos[$tableName] as $colName => $rules) {
$column = $table->getColumn($colName);
$colName = $column->getName();
foreach ($rules as $rule) {
if (!isset($nodes[$colName])) {
$nodes[$colName] = $this->createValidator($column, $rule['type']);
$node->appendChild($nodes[$colName]);
}
$ruleNode = $this->createRuleNode($column, $rule);
$nodes[$colName]->appendChild($ruleNode);
}
}
}
return $node;
}
/**
* Creates an column node
*
* @param object $column The Creole column
* @return object The column node instance
*/
protected function createColumnNode($column) {
$node = $this->doc->createElement("column");
$table = $column->getTable();
$colName = $column->getName();
$colType = $column->getType();
$colSize = $column->getSize();
$colScale = $column->getScale();
if ($colType === CreoleTypes::OTHER) {
$this->log("Column [" . $table->getName() . "." . $colName . "] has a column type (".$column->getNativeType().") that Propel does not support.", PROJECT_MSG_WARN);
}
$node->setAttribute("name", $colName);
if ($this->isSamePhpName()) {
$node->setAttribute("phpName", $colName);
}
$node->setAttribute("type", PropelTypes::getPropelType($colType));
if ($colSize > 0 && (
$colType == CreoleTypes::CHAR
|| $colType == CreoleTypes::VARCHAR
|| $colType == CreoleTypes::LONGVARCHAR
|| $colType == CreoleTypes::DECIMAL
|| $colType == CreoleTypes::FLOAT
|| $colType == CreoleTypes::NUMERIC)) {
$node->setAttribute("size", (string) $colSize);
}
if ($colScale > 0 && (
$colType == CreoleTypes::DECIMAL
|| $colType == CreoleTypes::FLOAT
|| $colType == CreoleTypes::NUMERIC)) {
$node->setAttribute("scale", (string) $colScale);
}
if (!$column->isNullable()) {
$node->setAttribute("required", "true");
}
if ($column->isAutoIncrement()) {
$node->setAttribute("autoIncrement", "true");
}
if (in_array($colName, $this->getTablePkCols($table))) {
$node->setAttribute("primaryKey", "true");
}
if (($defValue = $column->getDefaultValue()) !== null) {
$node->setAttribute("default", iconv($this->dbEncoding, 'utf-8', $defValue));
}
if ($vendorNode = $this->createVendorInfoNode($column->getVendorSpecificInfo())) {
$node->appendChild($vendorNode);
}
return $node;
}
/**
* Returns the primary key columns for a table
*
* @param object $table The table
* @return array The primary keys
*/
protected function getTablePkCols($table) {
static $columns = array();
$tableName = $table->getName();
if (!isset($columns[$tableName])) {
$columns[$tableName] = array();
$primaryKey = $table->getPrimaryKey();
if ($primaryKey) {
foreach($primaryKey->getColumns() as $colObject) {
$columns[$tableName][] = $colObject->getName();
}
}
}
return $columns[$tableName];
}
/**
* Creates an foreign key node
*
* @param object $foreignKey The foreign key
* @return object The foreign key node instance
*/
protected function createForeignKeyNode($foreignKey) {
$node = $this->doc->createElement("foreign-key");
if ($vendorNode = $this->createVendorInfoNode($foreignKey->getVendorSpecificInfo())) {
$node->appendChild($vendorNode);
}
$refs = $foreignKey->getReferences();
// all references must be to same table, so we can grab table from the first, foreign column
$node->setAttribute("foreignTable", $refs[0][1]->getTable()->getName());
$node->setAttribute("onDelete", $refs[0][2]);
$node->setAttribute("onUpdate", $refs[0][3]);
for($m = 0, $size = count($refs); $m < $size; $m++) {
$refNode = $this->doc->createElement("reference");
$refData = $refs[$m];
$refNode->setAttribute("local", $refData[0]->getName());
$refNode->setAttribute("foreign", $refData[1]->getName());
$node->appendChild($refNode);
}
return $node;
}
/**
* Creates an index node
*
* @param object $index The index
* @return object The index node instance
*/
protected function createIndexNode($index) {
$indexType = $index->isUnique() ? 'unique' : 'index';
$node = $this->doc->createElement($indexType);
$node->setAttribute("name", $index->getName());
$columns = $index->getColumns();
foreach ($columns as $column) {
$tableName = $column->getTable()->getName();
$colName = $column->getName();
$columnNode = $this->doc->createElement("{$indexType}-column");
$columnNode->setAttribute("name", $colName);
$node->appendChild($columnNode);
if ($indexType == 'unique' && $this->isValidatorRequired('unique')) {
$this->validatorInfos[$tableName][$colName][] = array('type' => 'unique');
}
}
if ($vendorNode = $this->createVendorInfoNode($index->getVendorSpecificInfo())) {
$node->appendChild($vendorNode);
}
return $node;
}
/**
* Checks whether to add validators of specified type or not
*
* @param string $type The validator type
* @return boolean
*/
protected function isValidatorRequired($type) {
$type = strtolower($type);
return ($this->validatorBits & self::$validatorBitMap[$type] ? true : false);
}
/**
* Registers column type specific validators if necessary
*
* We'll first collect the validators/rule infos and add them later on to
* have them appended to the table tag as a block.
*
* CreoleTypes are:
*
* BOOLEAN
* BIGINT, SMALLINT, TINYINT, INTEGER
* FLOAT, DOUBLE, NUMERIC, DECIMAL, REAL
* BIGINT, SMALLINT, TINYINT, INTEGER
* TEXT
* BLOB, CLOB, BINARY, VARBINARY, LONGVARBINARY
* DATE, YEAR, TIME
* TIMESTAMP
*
* We will add the following type specific validators:
*
* for notNull columns: required validator
* for unique indexes: unique validator
* for varchar types: maxLength validators (CHAR, VARCHAR, LONGVARCHAR)
* for numeric types: maxValue validators (BIGINT, SMALLINT, TINYINT, INTEGER, FLOAT, DOUBLE, NUMERIC, DECIMAL, REAL)
* for integer and timestamp types: notMatch validator with [^\d]+ (BIGINT, SMALLINT, TINYINT, INTEGER, TIMESTAMP)
* for float types: notMatch validator with [^\d\.]+ (FLOAT, DOUBLE, NUMERIC, DECIMAL, REAL)
*
* @param object $column The Creole column
* @return void
* @todo find out how to evaluate the appropriate size and adjust maxValue rule values appropriate
* @todo find out if float type column values must always notMatch('[^\d\.]+'), i.e. digits and point for any db vendor, language etc.
*/
protected function registerValidatorsForColumn($column) {
$table = $column->getTable();
$tableName = $table->getName();
$colName = $column->getName();
$colType = $column->getType();
$colSize = $column->getSize();
if ($this->isValidatorRequired('required')) {
$ruleInfo = array('type' => 'required');
$this->validatorInfos[$tableName][$colName][] = $ruleInfo;
}
$isPrimarykeyCol = in_array($colName, $this->getTablePkCols($table));
if ($this->isValidatorRequired('unique') && $isPrimarykeyCol) {
$ruleInfo = array('type' => 'unique');
$this->validatorInfos[$tableName][$colName][] = $ruleInfo;
}
if ($this->isValidatorRequired('maxLength') &&
$colSize > 0 && in_array($colType, array(
CreoleTypes::CHAR,
CreoleTypes::VARCHAR,
CreoleTypes::LONGVARCHAR))) {
$ruleInfo = array('type' => 'maxLength', 'value' => $colSize);
$this->validatorInfos[$tableName][$colName][] = $ruleInfo;
}
if ($this->isValidatorRequired('maxValue') &&
$colSize > 0 && in_array($colType, array(
CreoleTypes::SMALLINT,
CreoleTypes::TINYINT,
CreoleTypes::INTEGER,
CreoleTypes::BIGINT,
CreoleTypes::FLOAT,
CreoleTypes::DOUBLE,
CreoleTypes::NUMERIC,
CreoleTypes::DECIMAL,
CreoleTypes::REAL))) {
// TODO: how to evaluate the appropriate size??
$this->log("WARNING: maxValue validator added for column $colName. You will have to adjust the size value manually.", PROJECT_MSG_WARN);
$ruleInfo = array('type' => 'maxValue', 'value' => $colSize);
$this->validatorInfos[$tableName][$colName][] = $ruleInfo;
}
if ($this->isValidatorRequired('type') &&
$colSize > 0 && in_array($colType, array(
CreoleTypes::SMALLINT,
CreoleTypes::TINYINT,
CreoleTypes::INTEGER,
CreoleTypes::TIMESTAMP))) {
$ruleInfo = array('type' => 'type', 'value' => '[^\d]+');
$this->validatorInfos[$tableName][$colName][] = $ruleInfo;
}
if ($this->isValidatorRequired('type') &&
$colSize > 0 && in_array($colType, array(
CreoleTypes::FLOAT,
CreoleTypes::DOUBLE,
CreoleTypes::NUMERIC,
CreoleTypes::DECIMAL,
CreoleTypes::REAL))) {
// TODO: is this always true??
$ruleInfo = array('type' => 'type', 'value' => '[^\d\.]+');
$this->validatorInfos[$tableName][$colName][] = $ruleInfo;
}
}
/**
* Creates a validator node
*
* @param object $column The Creole column
* @param integer $type The validator type
* @return object The validator node instance
*/
protected function createValidator($column, $type) {
$node = $this->doc->createElement('validator');
$node->setAttribute('column', $column->getName());
return $node;
}
/**
* Creates a rule node
*
* @param object $column The Creole column
* @param array $rule The rule info
* @return object The rule node instance
*/
protected function createRuleNode($column, $rule) {
extract($rule);
// create message
$colName = $column->getName();
$tableName = $column->getTable()->getName();
$msg = self::$validatorMessages[strtolower($rule)];
array_unshift($tmp = compact($msg['var']), $msg['msg']);
$msg = call_user_func_array('sprintf', $tmp);
// add node
$node = $this->doc->createElement('rule');
$node->setAttribute('name', $rule == 'type' ? 'notMatch' : $rule);
$node->setAttribute('message', $msg);
return $node;
}
/**
* Creates a vendor info node
*
* returns false if no vendor info can or has to be added
*
* @param array $vendorInfo The validator info
* @return object|boolean The vendor info instance or false
*/
protected function createVendorInfoNode($vendorInfo)
{
if(!$vendorInfo OR !$this->addVendorInfo) {
return false;
}
$vendorNode = $this->doc->createElement("vendor");
$vendorNode->setAttribute("type", $this->dsn["phptype"]);
foreach($vendorInfo as $key => $value) {
$parameterNode = $this->doc->createElement("parameter");
$value = iconv($this->dbEncoding, "utf-8", $value);
$parameterNode->setAttribute("name", $key);
$parameterNode->setAttribute("value", $value);
$vendorNode->appendChild($parameterNode);
}
return $vendorNode;
}
}

View File

@ -0,0 +1,80 @@
<?php
/*
* $Id: PropelDataDTDTask.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/phing/AbstractPropelDataModelTask.php';
include_once 'propel/engine/builder/om/ClassTools.php';
/**
* This Task creates the OM classes based on the XML schema file.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.phing
*/
class PropelDataDTDTask extends AbstractPropelDataModelTask {
public function main() {
// check to make sure task received all correct params
$this->validate();
if(!$this->mapperElement) {
throw new BuildException("You must use a <mapper/> element to describe how names should be transformed.");
}
$basepath = $this->getOutputDirectory();
// Get new Capsule context
$generator = $this->createContext();
$generator->put("basepath", $basepath); // make available to other templates
// we need some values that were loaded into the template context
$basePrefix = $generator->get('basePrefix');
$project = $generator->get('project');
foreach ($this->getDataModels() as $dataModel) {
$this->log("Processing Datamodel : " . $dataModel->getName());
foreach ($dataModel->getDatabases() as $database) {
$outFile = $this->getMappedFile($dataModel->getName());
$generator->put("tables", $database->getTables());
$generator->parse("data/dtd/dataset.tpl", $outFile->getAbsolutePath());
$this->log("Generating DTD for database: " . $database->getName());
$this->log("Creating DTD file: " . $outFile->getPath());
foreach ($database->getTables() as $tbl) {
$this->log("\t + " . $tbl->getName());
$generator->put("table", $tbl);
$generator->parse("data/dtd/table.tpl", $outFile->getAbsolutePath(), true);
}
} // foreach database
} // foreach dataModel
} // main()
}

View File

@ -0,0 +1,383 @@
<?php
/*
* $Id: PropelDataDumpTask.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'creole/Creole.php';
/**
* Dumps the contenst of selected databases to XML data dump file.
*
* The generated XML files can have corresponding DTD files generated using the
* PropelDataDTDTask. The results of the data dump can be converted to SQL using
* the PropelDataSQLTask class.
*
* The database may be specified (via 'databaseName' attribute) if you only want to dump
* the contents of one database. Otherwise it is assumed that all databases described
* by datamodel schema file(s) will be dumped.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Fedor Karpelevitch <fedor.karpelevitch@home.com> (Torque)
* @author Jason van Zyl <jvanzyl@zenplex.com> (Torque)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @version $Revision: 536 $
* @package propel.phing
*/
class PropelDataDumpTask extends AbstractPropelDataModelTask {
/**
* Database name.
* The database name may be optionally specified in the XML if you only want
* to dump the contents of one database.
*/
private $databaseName;
/**
* Database URL used for Creole connection.
* This is a PEAR-compatible (loosely) DSN URL.
*/
private $databaseUrl;
/**
* Database driver used for Creole connection.
* This should normally be left blank so that default (Creole built-in) driver for database type is used.
*/
private $databaseDriver;
/**
* Database user used for Creole connection.
* @deprecated Put username in databaseUrl.
*/
private $databaseUser;
/**
* Database password used for Creole connection.
* @deprecated Put password in databaseUrl.
*/
private $databasePassword;
/**
* Properties file that maps a data XML file to a particular database.
* @var PhingFile
*/
private $datadbmap;
/**
* The database connection used to retrieve the data to dump.
* Needs to be public so that the TableInfo class can access it.
*/
public $conn;
/**
* The statement used to acquire the data to dump.
*/
private $stmt;
/**
* Set the file that maps between data XML files and databases.
*
* @param PhingFile $sqldbmap the db map
* @return void
*/
public function setDataDbMap(PhingFile $datadbmap)
{
$this->datadbmap = $datadbmap;
}
/**
* Get the file that maps between data XML files and databases.
*
* @return PhingFile $datadbmap.
*/
public function getDataDbMap()
{
return $this->datadbmap;
}
/**
* Get the database name to dump
*
* @return The DatabaseName value
*/
public function getDatabaseName()
{
return $this->databaseName;
}
/**
* Set the database name
*
* @param v The new DatabaseName value
*/
public function setDatabaseName($v)
{
$this->databaseName = $v;
}
/**
* Get the database url
*
* @return The DatabaseUrl value
*/
public function getDatabaseUrl()
{
return $this->databaseUrl;
}
/**
* Set the database url
*
* @param string $v The PEAR-compatible database DSN URL.
*/
public function setDatabaseUrl($v)
{
$this->databaseUrl = $v;
}
/**
* Get the database user
*
* @return string database user
* @deprecated
*/
public function getDatabaseUser()
{
return $this->databaseUser;
}
/**
* Set the database user
*
* @param string $v The new DatabaseUser value
* @deprecated Specify user in DSN URL.
*/
public function setDatabaseUser($v)
{
$this->databaseUser = $v;
}
/**
* Get the database password
*
* @return string database password
*/
public function getDatabasePassword()
{
return $this->databasePassword;
}
/**
* Set the database password
*
* @param string $v The new DatabasePassword value
* @deprecated Specify database password in DSN URL.
*/
public function setDatabasePassword($v)
{
$this->databasePassword = $v;
}
/**
* Get the database driver name
*
* @return string database driver name
*/
public function getDatabaseDriver()
{
return $this->databaseDriver;
}
/**
* Set the database driver name
*
* @param string $v The new DatabaseDriver value
*/
public function setDatabaseDriver($v)
{
$this->databaseDriver = $v;
}
/**
* Create the data XML -> database map.
*
* This is necessary because there is currently no other method of knowing which
* data XML files correspond to which database. This map allows us to convert multiple
* data XML files into SQL.
*
* @throws IOException - if unable to store properties
*/
private function createDataDbMap()
{
if ($this->getDataDbMap() === null) {
return;
}
// Produce the sql -> database map
$datadbmap = new Properties();
// Check to see if the sqldbmap has already been created.
if ($this->getDataDbMap()->exists()) {
$datadbmap->load($this->getDataDbMap());
}
foreach ($this->getDataModels() as $dataModel) { // there is really one 1 db per datamodel
foreach ($dataModel->getDatabases() as $database) {
// if database name is specified, then we only want to dump that one db.
if (empty($this->databaseName) || ($this->databaseName && $database->getName() == $this->databaseName)) {
$outFile = $this->getMappedFile($dataModel->getName());
$datadbmap->setProperty($outFile->getName(), $database->getName());
}
}
}
try {
$datadbmap->store($this->getDataDbMap(), "Data XML file -> Database map");
} catch (IOException $e) {
throw new IOException("Unable to store properties: ". $e->getMessage());
}
}
/**
* Iterates through each datamodel/database, dumps the contents of all tables and creates a DOM XML doc.
*
* @return void
* @throws BuildException
*/
public function main()
{
$this->validate();
$buf = "Database settings:\n"
. " driver: " . ($this->databaseDriver ? $this->databaseDriver : "(default)" ). "\n"
. " URL: " . $this->databaseUrl . "\n"
. ($this->databaseUser ? " user: " . $this->databaseUser . "\n" : "") // deprecated
. ($this->databasePassword ? " password: " . $this->databasePassword . "\n" : ""); // deprecated
$this->log($buf, PROJECT_MSG_VERBOSE);
// 1) First create the Data XML -> database name map.
$this->createDataDbMap();
// 2) Now go create the XML files from teh database(s)
foreach ($this->getDataModels() as $dataModel) { // there is really one 1 db per datamodel
foreach ($dataModel->getDatabases() as $database) {
// if database name is specified, then we only want to dump that one db.
if (empty($this->databaseName) || ($this->databaseName && $database->getName() == $this->databaseName)) {
$outFile = $this->getMappedFile($dataModel->getName());
$this->log("Dumping data to XML for database: " . $database->getName());
$this->log("Writing to XML file: " . $outFile->getName());
try {
$url = str_replace("@DB@", $database->getName(), $this->databaseUrl);
$buf = "Database settings:\n"
. " driver: " . ($this->databaseDriver ? $this->databaseDriver : "(default)" ). "\n"
. " URL: " . $url . "\n"
. ($this->databaseUser ? " user: " . $this->databaseUser . "\n" : "")
. ($this->databasePassword ? " password: " . $this->databasePassword . "\n" : "");
$this->log($buf, PROJECT_MSG_VERBOSE);
$dsn = Creole::parseDSN($url);
// deprecated, but here for BC
if ($this->databaseUser) {
$dsn['username'] = $this->databaseUser;
}
if ($this->databasePassword) {
$dsn['password'] = $this->databasePassword;
}
if ($this->databaseName) {
$dsn['database'] = $this->databaseName;
}
if ($this->databaseDriver) {
Creole::registerDriver($dsn['phptype'], $this->databaseDriver);
}
$this->conn = Creole::getConnection($dsn);
$doc = $this->createXMLDoc($database);
$doc->save($outFile->getAbsolutePath());
} catch (SQLException $se) {
$this->log("SQLException while connecting to DB: ". $se->getMessage(), PROJECT_MSG_ERR);
throw new BuildException($se);
}
} // if databaseName && database->getName == databaseName
} // foreach database
} // foreach datamodel
}
/**
* Gets ResultSet of query to fetch all data from a table.
* @param string $tableName
* @return ResultSet
*/
private function getTableDataRS($tableName) {
// Set Statement object in associated PropelDataDump
// instance.
return $this->conn->createStatement()->executeQuery("SELECT * FROM " . $this->getPlatformForTargetDatabase()->quoteIdentifier ( $tableName ) );
}
/**
* Creates a DOM document containing data for specified database.
* @param Database $database
* @return DOMDocument
*/
private function createXMLDoc(Database $database) {
$doc = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true; // pretty printing
$doc->appendChild($doc->createComment("Created by data/dump/Control.tpl template."));
$dsNode = $doc->createElement("dataset");
$dsNode->setAttribute("name", "all");
$doc->appendChild($dsNode);
$this->log("Building DOM tree containing data from tables:");
foreach ($database->getTables() as $tbl) {
$this->log("\t+ " . $tbl->getName());
$rs = $this->getTableDataRS($tbl->getName());
while ($rs->next()) {
$rowNode = $doc->createElement($tbl->getPhpName());
foreach ($tbl->getColumns() as $col) {
$cval = $rs->get($col->getName());
if ($cval !== null) {
$rowNode->setAttribute($col->getPhpName(), iconv($this->dbEncoding, 'utf-8', $cval));
}
}
$dsNode->appendChild($rowNode);
unset($rowNode);
}
$rs->close();
}
return $doc;
}
}

View File

@ -0,0 +1,131 @@
<?php
/*
* $Id: PropelDataModelTask.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/phing/AbstractPropelDataModelTask.php';
include_once 'propel/engine/database/model/AppData.php';
include_once 'propel/engine/database/model/Database.php';
include_once 'propel/engine/database/transform/XmlToAppData.php';
/**
* A generic class that simply loads the data model and parses a control template.
*
* This class exists largely for compatibility with early Propel where this was
* a CapsuleTask subclass. This class also makes it easy to quickly add some custom
* datamodel-based transformations (by allowing you to put the logic in the templates).
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.phing
* @version $Revision: 536 $
*/
class PropelDataModelTask extends AbstractPropelDataModelTask {
/**
* This is the file where the generated text
* will be placed.
* @var string
*/
protected $outputFile;
/**
* This is the control template that governs the output.
* It may or may not invoke the services of worker
* templates.
* @var string
*/
protected $controlTemplate;
/**
* [REQUIRED] Set the output file for the
* generation process.
* @param string $outputFile (TODO: change this to File)
* @return void
*/
public function setOutputFile($outputFile) {
$this->outputFile = $outputFile;
}
/**
* Get the output file for the
* generation process.
* @return string
*/
public function getOutputFile() {
return $this->outputFile;
}
/**
* [REQUIRED] Set the control template for the
* generating process.
* @param string $controlTemplate
* @return void
*/
public function setControlTemplate ($controlTemplate) {
$this->controlTemplate = $controlTemplate;
}
/**
* Get the control template for the
* generating process.
* @return string
*/
public function getControlTemplate() {
return $this->controlTemplate;
}
protected function validate()
{
parent::validate();
// Make sure the control template is set.
if ($this->controlTemplate === null) {
throw new BuildException("The control template needs to be defined!");
}
// Make sure there is an output file.
if ($this->outputFile === null) {
throw new BuildException("The output file needs to be defined!");
}
}
/**
* Creates Capsule context and parses control template.
* @return void
*/
public function main()
{
$this->validate();
$context = $this->createContext();
$context->put("dataModels", $this->getDataModels());
$path = $this->outputDirectory . DIRECTORY_SEPARATOR . $this->outputFile;
$this->log("Generating to file " . $path);
try {
$this->log("Parsing control template: " . $this->controlTemplate);
$context->parse($this->controlTemplate, $path);
} catch (Exception $ioe) {
throw new BuildException("Cannot write parsed template: ". $ioe->getMessage());
}
}
}

View File

@ -0,0 +1,219 @@
<?php
/*
* $Id: PropelDataSQLTask.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'propel/engine/database/model/AppData.php';
include_once 'propel/engine/database/model/Database.php';
include_once 'propel/engine/database/transform/XmlToAppData.php';
include_once 'propel/engine/database/transform/XmlToData.php';
/**
* Task that transforms XML datadump files into files containing SQL INSERT statements.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Jason van Zyl <jvanzyl@periapt.com> (Torque)
* @author John McNally <jmcnally@collab.net> (Torque)
* @author Fedor Karpelevitch <fedor.karpelevitch@home.com> (Torque)
* @version $Revision: 536 $
* @package propel.phing
*/
class PropelDataSQLTask extends AbstractPropelDataModelTask {
/**
* Properties file that maps an SQL file to a particular database.
* @var PhingFile
*/
private $sqldbmap;
/**
* Properties file that maps a data XML file to a particular database.
* @var PhingFile
*/
private $datadbmap;
/**
* The base directory in which to find data XML files.
* @var PhingFile
*/
private $srcDir;
/**
* Set the file that maps between SQL files and databases.
*
* @param PhingFile $sqldbmap the sql -> db map.
* @return void
*/
public function setSqlDbMap(PhingFile $sqldbmap)
{
$this->sqldbmap = $sqldbmap;
}
/**
* Get the file that maps between SQL files and databases.
*
* @return PhingFile sqldbmap.
*/
public function getSqlDbMap()
{
return $this->sqldbmap;
}
/**
* Set the file that maps between data XML files and databases.
*
* @param PhingFile $sqldbmap the db map
* @return void
*/
public function setDataDbMap(PhingFile $datadbmap)
{
$this->datadbmap = $datadbmap;
}
/**
* Get the file that maps between data XML files and databases.
*
* @return PhingFile $datadbmap.
*/
public function getDataDbMap()
{
return $this->datadbmap;
}
/**
* Set the src directory for the data xml files listed in the datadbmap file.
* @param PhingFile $srcDir data xml source directory
*/
public function setSrcDir(PhingFile $srcDir)
{
$this->srcDir = $srcDir;
}
/**
* Get the src directory for the data xml files listed in the datadbmap file.
*
* @return PhingFile data xml source directory
*/
public function getSrcDir()
{
return $this->srcDir;
}
/**
* Search through all data models looking for matching database.
* @return Database or NULL if none found.
*/
private function getDatabase($name)
{
foreach($this->getDataModels() as $dm) {
foreach($dm->getDatabases() as $db) {
if ($db->getName() == $name) {
return $db;
}
}
}
}
/**
* Main method parses the XML files and creates SQL files.
*
* @return void
* @throws Exception If there is an error parsing the data xml.
*/
public function main()
{
$this->validate();
$targetDatabase = $this->getTargetDatabase();
$platform = $this->getPlatformForTargetDatabase();
// Load the Data XML -> DB Name properties
$map = new Properties();
try {
$map->load($this->getDataDbMap());
} catch (IOException $ioe) {
throw new BuildException("Cannot open and process the datadbmap!", $ioe);
}
DataModelBuilder::setBuildProperties($this->getPropelProperties());
// Parse each file in teh data -> db map
foreach($map->keys() as $dataXMLFilename) {
$dataXMLFile = new PhingFile($this->srcDir, $dataXMLFilename);
// if file exists then proceed
if ($dataXMLFile->exists()) {
$dbname = $map->get($dataXMLFilename);
$db = $this->getDatabase($dbname);
if (!$db) {
throw new BuildException("Cannot find instantiated Database for name '$dbname' from datadbmap file.");
}
$db->setPlatform($platform);
$outFile = $this->getMappedFile($dataXMLFilename);
$this->log("Creating SQL from XML data dump file: " . $dataXMLFile->getAbsolutePath());
try {
$dataXmlParser = new XmlToData($db, $this->dbEncoding);
$data = $dataXmlParser->parseFile($dataXMLFile->getAbsolutePath());
} catch (Exception $e) {
throw new Exception("Exception parsing data XML: " . $e->getMessage());
}
$fp = fopen($outFile->getAbsolutePath(), 'w');
$currTable = null;
foreach ($data as $dataRow) {
if ($currTable !== $dataRow->getTable()) {
$currTable = $dataRow->getTable();
$builder = DataModelBuilder::builderFactory($currTable, 'datasql');
}
$sql = $builder->buildRowSql($dataRow);
fwrite($fp, $sql);
}
fclose($fp);
// Place the generated SQL file(s)
$p = new Properties();
if ($this->getSqlDbMap()->exists()) {
$p->load($this->getSqlDbMap());
}
$p->setProperty($outFile->getName(), $db->getName());
$p->store($this->getSqlDbMap(), "Sqlfile -> Database map");
} else {
$this->log("File '" . $dataXMLFile->getAbsolutePath()
. "' in datadbmap does not exist, so skipping it.", PROJECT_MSG_WARN);
}
} // foreach data xml file
} // main()
}

View File

@ -0,0 +1,177 @@
<?php
/*
* $Id: PropelGraphvizTask.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'propel/engine/database/model/AppData.php';
//require_once 'phing/Task.php';
/**
* A task to generate Graphviz png images from propel datamodel.
*
* @author Mark Kimsal
* @version $Revision: 536 $
* @package propel.phing
*/
class PropelGraphvizTask extends AbstractPropelDataModelTask {
/**
* The properties file that maps an SQL file to a particular database.
* @var PhingFile
*/
private $sqldbmap;
/**
* Name of the database.
*/
private $database;
/**
* Name of the output directory.
*/
private $outDir;
/**
* Set the sqldbmap.
* @param PhingFile $sqldbmap The db map.
*/
public function setOutputDirectory(PhingFile $out)
{
if (!$out->exists()) {
$out->mkdirs();
}
$this->outDir = $out;
}
/**
* Set the sqldbmap.
* @param PhingFile $sqldbmap The db map.
*/
public function setSqlDbMap(PhingFile $sqldbmap)
{
$this->sqldbmap = $sqldbmap;
}
/**
* Get the sqldbmap.
* @return PhingFile $sqldbmap.
*/
public function getSqlDbMap()
{
return $this->sqldbmap;
}
/**
* Set the database name.
* @param string $database
*/
public function setDatabase($database)
{
$this->database = $database;
}
/**
* Get the database name.
* @return string
*/
public function getDatabase()
{
return $this->database;
}
public function main()
{
$count = 0;
$dotSyntax = '';
// file we are going to create
$dbMaps = $this->getDataModelDbMap();
foreach ($this->getDataModels() as $dataModel) {
$dotSyntax .= "digraph G {\n";
foreach ($dataModel->getDatabases() as $database) {
$this->log("db: " . $database->getName());
//print the tables
foreach($database->getTables() as $tbl) {
$this->log("\t+ " . $tbl->getName());
++$count;
$dotSyntax .= 'node'.$tbl->getName().' [label="{<table>'.$tbl->getName().'|<cols>';
foreach ($tbl->getColumns() as $col) {
$dotSyntax .= $col->getName() . ' (' . $col->getType() . ')';
if ($col->getForeignKey() != null ) {
$dotSyntax .= ' [FK]';
} elseif ($col->isPrimaryKey()) {
$dotSyntax .= ' [PK]';
}
$dotSyntax .= '\l';
}
$dotSyntax .= '}", shape=record];';
$dotSyntax .= "\n";
}
//print the relations
$count = 0;
$dotSyntax .= "\n";
foreach($database->getTables() as $tbl) {
++$count;
foreach ($tbl->getColumns() as $col) {
$fk = $col->getForeignKey();
if ( $fk == null ) continue;
$dotSyntax .= 'node'.$tbl->getName() .':cols -> node'.$fk->getForeignTableName() . ':table [label="' . $col->getName() . '=' . implode(',', $fk->getForeignColumns()) . ' "];';
$dotSyntax .= "\n";
}
}
} // foreach database
$dotSyntax .= "}\n";
$this->writeDot($dotSyntax,$this->outDir);
} //foreach datamodels
} // main()
/**
* probably insecure
*/
function writeDot($dotSyntax, PhingFile $outputDir) {
$file = new PhingFile($outputDir, 'schema.dot');
$this->log("Writing dot file to " . $file->getAbsolutePath());
file_put_contents($file->getAbsolutePath(), $dotSyntax);
}
}

View File

@ -0,0 +1,212 @@
<?php
/*
* $Id: PropelOMTask.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/phing/AbstractPropelDataModelTask.php';
include_once 'propel/engine/builder/om/ClassTools.php';
require_once 'propel/engine/builder/om/OMBuilder.php';
/**
* This Task creates the OM classes based on the XML schema file.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.phing
*/
class PropelOMTask extends AbstractPropelDataModelTask {
/**
* The platform (php4, php5, etc.) for which the om is being built.
* @var string
*/
private $targetPlatform;
/**
* Sets the platform (php4, php5, etc.) for which the om is being built.
* @param string $v
*/
public function setTargetPlatform($v) {
$this->targetPlatform = $v;
}
/**
* Gets the platform (php4, php5, etc.) for which the om is being built.
* @return string
*/
public function getTargetPlatform() {
return $this->targetPlatform;
}
/**
* Utility method to create directory for package if it doesn't already exist.
* @param string $path The [relative] package path.
* @throws BuildException - if there is an error creating directories
*/
protected function ensureDirExists($path)
{
$f = new PhingFile($this->getOutputDirectory(), $path);
if (!$f->exists()) {
if (!$f->mkdirs()) {
throw new BuildException("Error creating directories: ". $f->getPath());
}
}
}
/**
* Uses a builder class to create the output class.
* This method assumes that the DataModelBuilder class has been initialized with the build properties.
* @param OMBuilder $builder
* @param boolean $overwrite Whether to overwrite existing files with te new ones (default is YES).
* @todo -cPropelOMTask Consider refactoring build() method into AbstractPropelDataModelTask (would need to be more generic).
*/
protected function build(OMBuilder $builder, $overwrite = true)
{
$path = $builder->getClassFilePath();
$this->ensureDirExists(dirname($path));
$_f = new PhingFile($this->getOutputDirectory(), $path);
if ($overwrite || !$_f->exists()) {
$this->log("\t\t-> " . $builder->getClassname() . " [builder: " . get_class($builder) . "]");
$script = $builder->build();
file_put_contents($_f->getAbsolutePath(), $script);
foreach($builder->getWarnings() as $warning) {
$this->log($warning, PROJECT_MSG_WARN);
}
} else {
$this->log("\t\t-> (exists) " . $builder->getClassname());
}
}
/**
* Main method builds all the targets for a typical propel project.
*/
public function main()
{
// check to make sure task received all correct params
$this->validate();
$basepath = $this->getOutputDirectory();
// Get new Capsule context
$generator = $this->createContext();
$generator->put("basepath", $basepath); // make available to other templates
$targetPlatform = $this->getTargetPlatform(); // convenience for embedding in strings below
// we need some values that were loaded into the template context
$basePrefix = $generator->get('basePrefix');
$project = $generator->get('project');
DataModelBuilder::setBuildProperties($this->getPropelProperties());
foreach ($this->getDataModels() as $dataModel) {
$this->log("Processing Datamodel : " . $dataModel->getName());
foreach ($dataModel->getDatabases() as $database) {
$this->log(" - processing database : " . $database->getName());
$generator->put("platform", $database->getPlatform());
foreach ($database->getTables() as $table) {
if (!$table->isForReferenceOnly()) {
$this->log("\t+ " . $table->getName());
// -----------------------------------------------------------------------------------------
// Create Peer, Object, and MapBuilder classes
// -----------------------------------------------------------------------------------------
// these files are always created / overwrite any existing files
foreach(array('peer', 'object', 'mapbuilder') as $target) {
$builder = DataModelBuilder::builderFactory($table, $target);
$this->build($builder);
}
// -----------------------------------------------------------------------------------------
// Create [empty] stub Peer and Object classes if they don't exist
// -----------------------------------------------------------------------------------------
// these classes are only generated if they don't already exist
foreach(array('peerstub', 'objectstub') as $target) {
$builder = DataModelBuilder::builderFactory($table, $target);
$this->build($builder, $overwrite=false);
}
// -----------------------------------------------------------------------------------------
// Create [empty] stub child Object classes if they don't exist
// -----------------------------------------------------------------------------------------
// If table has enumerated children (uses inheritance) then create the empty child stub classes if they don't already exist.
if ($table->getChildrenColumn()) {
$col = $table->getChildrenColumn();
if ($col->isEnumeratedClasses()) {
foreach ($col->getChildren() as $child) {
$builder = DataModelBuilder::builderFactory($table, 'objectmultiextend');
$builder->setChild($child);
$this->build($builder, $overwrite=false);
} // foreach
} // if col->is enumerated
} // if tbl->getChildrenCol
// -----------------------------------------------------------------------------------------
// Create [empty] Interface if it doesn't exist
// -----------------------------------------------------------------------------------------
// Create [empty] interface if it does not already exist
if ($table->getInterface()) {
$builder = DataModelBuilder::builderFactory($table, 'interface');
$this->build($builder, $overwrite=false);
}
// -----------------------------------------------------------------------------------------
// Create tree Node classes
// -----------------------------------------------------------------------------------------
if ($table->isTree()) {
foreach(array('nodepeer', 'node') as $target) {
$builder = DataModelBuilder::builderFactory($table, $target);
$this->build($builder);
}
foreach(array('nodepeerstub', 'nodestub') as $target) {
$builder = DataModelBuilder::builderFactory($table, $target);
$this->build($builder, $overwrite=false);
}
} // if Table->isTree()
} // if !$table->isForReferenceOnly()
} // foreach table
} // foreach database
} // foreach dataModel
} // main()
}

View File

@ -0,0 +1,236 @@
<?php
/*
* $Id: PropelOldOMTask.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/phing/AbstractPropelDataModelTask.php';
include_once 'propel/engine/builder/om/ClassTools.php';
/**
* This Task creates the OM classes based on the XML schema file using the legacy templates.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.phing
* @deprecated
*/
class PropelOldOMTask extends AbstractPropelDataModelTask {
/**
* The platform (php4, php5, etc.) for which the om is being built.
* @var string
*/
private $targetPlatform;
/**
* Sets the platform (php4, php5, etc.) for which the om is being built.
* @param string $v
*/
public function setTargetPlatform($v) {
$this->targetPlatform = $v;
}
/**
* Gets the platform (php4, php5, etc.) for which the om is being built.
* @return string
*/
public function getTargetPlatform() {
return $this->targetPlatform;
}
public function main() {
// check to make sure task received all correct params
$this->validate();
$basepath = $this->getOutputDirectory();
// Get new Capsule context
$generator = $this->createContext();
$generator->put("basepath", $basepath); // make available to other templates
$targetPlatform = $this->getTargetPlatform(); // convenience for embedding in strings below
// we need some values that were loaded into the template context
$basePrefix = $generator->get('basePrefix');
$project = $generator->get('project');
foreach ($this->getDataModels() as $dataModel) {
$this->log("Processing Datamodel : " . $dataModel->getName());
foreach ($dataModel->getDatabases() as $database) {
$this->log(" - processing database : " . $database->getName());
$generator->put("platform", $database->getPlatform());
foreach ($database->getTables() as $table) {
if (!$table->isForReferenceOnly()) {
if ($table->getPackage()) {
$package = $table->getPackage();
} else {
$package = $this->targetPackage;
}
$pkbase = "$package.om";
$pkpeer = "$package";
$pkmap = "$package.map";
// make these available
$generator->put("package", $package);
$generator->put("pkbase", $pkbase);
//$generator->put("pkpeer", $pkpeer); -- we're not using this yet
$generator->put("pkmap", $pkmap);
foreach(array($pkpeer, $pkmap, $pkbase) as $pk) {
$path = strtr($pk, '.', '/');
$f = new PhingFile($this->getOutputDirectory(), $path);
if (!$f->exists()) {
if (!$f->mkdirs()) {
throw new Exception("Error creating directories: ". $f->getPath());
}
}
} // for each package
$this->log("\t+ " . $table->getName());
$generator->put("table", $table);
// Create the Base Peer class
$this->log("\t\t-> " . $basePrefix . $table->getPhpName() . "Peer");
$path = ClassTools::getFilePath($pkbase, $basePrefix . $table->getPhpName() . "Peer");
$generator->parse("om/$targetPlatform/Peer.tpl", $path);
// Create the Base object class
$this->log("\t\t-> " . $basePrefix . $table->getPhpName());
$path = ClassTools::getFilePath($pkbase, $basePrefix . $table->getPhpName());
$generator->parse("om/$targetPlatform/Object.tpl", $path);
if ($table->isTree()) {
// Create the Base NodePeer class
$this->log("\t\t-> " . $basePrefix . $table->getPhpName() . "NodePeer");
$path = ClassTools::getFilePath($pkbase, $basePrefix . $table->getPhpName() . "NodePeer");
$generator->parse("om/$targetPlatform/NodePeer.tpl", $path);
// Create the Base Node class if the table is a tree
$this->log("\t\t-> " . $basePrefix . $table->getPhpName() . "Node");
$path = ClassTools::getFilePath($pkbase, $basePrefix . $table->getPhpName() . "Node");
$generator->parse("om/$targetPlatform/Node.tpl", $path);
}
// Create MapBuilder class if this table is not an alias
if (!$table->isAlias()) {
$this->log("\t\t-> " . $table->getPhpName() . "MapBuilder");
$path = ClassTools::getFilePath($pkmap, $table->getPhpName() . "MapBuilder");
$generator->parse("om/$targetPlatform/MapBuilder.tpl", $path);
} // if !$table->isAlias()
// Create [empty] stub Peer class if it does not already exist
$path = ClassTools::getFilePath($package, $table->getPhpName() . "Peer");
$_f = new PhingFile($basepath, $path);
if (!$_f->exists()) {
$this->log("\t\t-> " . $table->getPhpName() . "Peer");
$generator->parse("om/$targetPlatform/ExtensionPeer.tpl", $path);
} else {
$this->log("\t\t-> (exists) " . $table->getPhpName() . "Peer");
}
// Create [empty] stub object class if it does not already exist
$path = ClassTools::getFilePath($package, $table->getPhpName());
$_f = new PhingFile($basepath, $path);
if (!$_f->exists()) {
$this->log("\t\t-> " . $table->getPhpName());
$generator->parse("om/$targetPlatform/ExtensionObject.tpl", $path);
} else {
$this->log("\t\t-> (exists) " . $table->getPhpName());
}
if ($table->isTree()) {
// Create [empty] stub Node Peer class if it does not already exist
$path = ClassTools::getFilePath($package, $table->getPhpName() . "NodePeer");
$_f = new PhingFile($basepath, $path);
if (!$_f->exists()) {
$this->log("\t\t-> " . $table->getPhpName() . "NodePeer");
$generator->parse("om/$targetPlatform/ExtensionNodePeer.tpl", $path);
} else {
$this->log("\t\t-> (exists) " . $table->getPhpName() . "NodePeer");
}
// Create [empty] stub Node class if it does not already exist
$path = ClassTools::getFilePath($package, $table->getPhpName() . "Node");
$_f = new PhingFile($basepath, $path);
if (!$_f->exists()) {
$this->log("\t\t-> " . $table->getPhpName() . "Node");
$generator->parse("om/$targetPlatform/ExtensionNode.tpl", $path);
} else {
$this->log("\t\t-> (exists) " . $table->getPhpName() . "Node");
}
}
// Create [empty] interface if it does not already exist
if ($table->getInterface()) {
$path = ClassTools::getFilePath($table->getInterface());
$_f = new PhingFile($basepath, $path);
if (!$_f->exists()) {
$_dir = new PhingFile(dirname($_f->getAbsolutePath()));
$_dir->mkdirs();
$this->log("\t\t-> " . $table->getInterface());
$generator->parse("om/$targetPlatform/Interface.tpl", $path);
} else {
$this->log("\t\t-> (exists) " . $table->getInterface());
}
}
// If table has enumerated children (uses inheritance) then create the empty child stub classes
// if they don't already exist.
if ($table->getChildrenColumn()) {
$col = $table->getChildrenColumn();
if ($col->isEnumeratedClasses()) {
foreach ($col->getChildren() as $child) {
$childpkg = ($child->getPackage() ? $child->getPackage() : $package);
$generator->put("child", $child);
$generator->put("package", $childpkg);
$path = ClassTools::getFilePath($childpkg, $child->getClassName());
$_f = new PhingFile($basepath, $path);
if (!$_f->exists()) {
$this->log("\t\t-> " . $child->getClassName());
$generator->parse("om/$targetPlatform/MultiExtendObject.tpl", $path);
} else {
$this->log("\t\t-> (exists) " . $child->getClassName());
}
} // foreach
} // if col->is enumerated
} // if tbl->getChildrenCol
} // if !$table->isForReferenceOnly()
} // foreach table
} // foreach database
} // foreach dataModel
} // main()
}

View File

@ -0,0 +1,287 @@
<?php
/*
* $Id: PropelOldSQLTask.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'propel/engine/database/model/AppData.php';
/**
* An extended Capsule task used for generating SQL source from an XML schema describing a database structure.
*
* This is deprecated; the new PropelSQLTask should be used instead.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Jason van Zyl <jvanzyl@periapt.com> (Torque)
* @author John McNally <jmcnally@collab.net> (Torque)
* @version $Revision: 536 $
* @package propel.phing
* @deprecated
*/
class PropelOldSQLTask extends AbstractPropelDataModelTask {
/**
* The properties file that maps an SQL file to a particular database.
* @var PhingFile
*/
private $sqldbmap;
/**
* Name of the database.
*/
private $database;
/**
* Set the sqldbmap.
* @param PhingFile $sqldbmap The db map.
*/
public function setSqlDbMap(PhingFile $sqldbmap)
{
$this->sqldbmap = $sqldbmap;
}
/**
* Get the sqldbmap.
* @return PhingFile $sqldbmap.
*/
public function getSqlDbMap()
{
return $this->sqldbmap;
}
/**
* Set the database name.
* @param string $database
*/
public function setDatabase($database)
{
$this->database = $database;
}
/**
* Get the database name.
* @return string
*/
public function getDatabase()
{
return $this->database;
}
/**
* Create the sql -> database map.
*
* @throws IOException - if unable to store properties
*/
private function createSqlDbMap()
{
if ($this->getSqlDbMap() === null) {
return;
}
// Produce the sql -> database map
$sqldbmap = new Properties();
// Check to see if the sqldbmap has already been created.
if ($this->getSqlDbMap()->exists()) {
$sqldbmap->load($this->getSqlDbMap());
}
if ($this->packageObjectModel) {
// in this case we'll get the sql file name from the package attribute
$dataModels = $this->packageDataModels();
foreach ($dataModels as $package => $dataModel) {
foreach ($dataModel->getDatabases() as $database) {
$name = ($package ? $package . '.' : '') . 'schema.xml';
$sqlFile = $this->getMappedFile($name);
$sqldbmap->setProperty($sqlFile->getName(), $database->getName());
}
}
} else {
// the traditional way is to map the schema.xml filenames
$dmMap = $this->getDataModelDbMap();
foreach(array_keys($dmMap) as $dataModelName) {
$sqlFile = $this->getMappedFile($dataModelName);
if ($this->getDatabase() === null) {
$databaseName = $dmMap[$dataModelName];
} else {
$databaseName = $this->getDatabase();
}
$sqldbmap->setProperty($sqlFile->getName(), $databaseName);
}
}
try {
$sqldbmap->store($this->getSqlDbMap(), "Sqlfile -> Database map");
} catch (IOException $e) {
throw new IOException("Unable to store properties: ". $e->getMessage());
}
}
public function main() {
$this->validate();
if(!$this->mapperElement) {
throw new BuildException("You must use a <mapper/> element to describe how names should be transformed.");
}
if ($this->packageObjectModel) {
$dataModels = $this->packageDataModels();
} else {
$dataModels = $this->getDataModels();
}
// 1) first create a map of filenames to databases; this is used by other tasks like
// the SQLExec task.
$this->createSqlDbMap();
// 2) Now actually create the DDL based on the datamodel(s) from XML schema file.
$targetDatabase = $this->getTargetDatabase();
$basepath = "sql/base/$targetDatabase";
$generator = $this->createContext();
$generator->put("basepath", $basepath); // make available to sub-templates
$fname = "sql/base/$targetDatabase/table.tpl" ;
// $generator->put("fname", $fname); // make available to sub-templates
$fnamekeys= "sql/base/$targetDatabase/tablefk.tpl";
//$generator->put("fnamekeys", $fnamekeys); // make available to sub-templates
$ddlStartFile = new PhingFile($this->getTemplatePath(), "sql/base/$targetDatabase/database-start.tpl");
$ddlEndFile = new PhingFile($this->getTemplatePath(), "sql/base/$targetDatabase/database-end.tpl");
foreach ($dataModels as $package => $dataModel) {
foreach ($dataModel->getDatabases() as $database) {
// file we are going to create
if (!$this->packageObjectModel) {
$name = $dataModel->getName();
} else {
$name = ($package ? $package . '.' : '') . 'schema.xml';
}
$outFile = $this->getMappedFile($name);
$generator->put("database", $database); // make available to sub-templates
$generator->put("platform", $database->getPlatform());
$this->log("Generating SQL tables for database: " . $database->getName());
$this->log("Writing to SQL file: " . $outFile->getPath());
// this variable helps us overwrite the first time we write to file
// and then append thereafter
$append=false;
// First check to see if there is a "header" SQL file
if ($ddlStartFile->exists()) {
$generator->parse($ddlStartFile->getAbsolutePath(), $outFile->getAbsolutePath(), false);
$append = true;
}
foreach($database->getTables() as $tbl) {
if (!$tbl->isSkipSql()) {
$this->log("\t + " . $tbl->getName());
$generator->put("table", $tbl);
$generator->parse($fname, $outFile->getAbsolutePath(), $append);
if ($append === false) $append = true;
} else {
$this->log("\t + (skipping) " . $tbl->getName());
}
} // foreach database->getTables()
foreach ($database->getTables() as $tbl) {
if (!$tbl->isSkipSql()) {
$generator->put("tablefk", $tbl);
$generator->parse($fnamekeys, $outFile->getAbsolutePath(), true); // always append
}
}
// Finally check to see if there is a "footer" SQL file
if ($ddlEndFile->exists()) {
$generator->parse($ddlEndFile->getAbsolutePath(), $outFile->getAbsolutePath(), true);
}
} // foreach database
} //foreach datamodels
} // main()
/**
* Packages the datamodels to one datamodel per package
*
* This applies only when the the packageObjectModel option is set. We need to
* re-package the datamodels to allow the database package attribute to control
* which tables go into which SQL file.
*
* @return array The packaged datamodels
*/
protected function packageDataModels() {
static $packagedDataModels;
if (is_null($packagedDataModels)) {
$dataModels = $this->getDataModels();
$dataModel = array_shift($dataModels);
$packagedDataModels = array();
$platform = $this->getPlatformForTargetDatabase();
foreach ($dataModel->getDatabases() as $db) {
foreach ($db->getTables() as $table) {
$package = $table->getPackage();
if (!isset($packagedDataModels[$package])) {
$dbClone = $this->cloneDatabase($db);
$dbClone->setPackage($package);
$ad = new AppData($platform);
$ad->setName($dataModel->getName());
$ad->addDatabase($dbClone);
$packagedDataModels[$package] = $ad;
}
$packagedDataModels[$package]->getDatabase($db->getName())->addTable($table);
}
}
}
return $packagedDataModels;
}
protected function cloneDatabase($db) {
$attributes = array (
'name' => $db->getName(),
'baseClass' => $db->getBaseClass(),
'basePeer' => $db->getBasePeer(),
//'defaultPhpType' => $db->getDefaultPhpType(),
'defaultIdMethod' => $db->getDefaultIdMethod(),
'defaultPhpNamingMethod' => $db->getDefaultPhpNamingMethod(),
'defaultTranslateMethod' => $db->getDefaultTranslateMethod(),
//'heavyIndexing' => $db->getHeavyIndexing(),
);
$clone = new Database();
$clone->loadFromXML($attributes);
return $clone;
}
}

View File

@ -0,0 +1,681 @@
<?php
/*
* $Id: PropelSQLExec.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'phing/Task.php';
include_once 'creole/Connection.php';
/**
* Executes all SQL files referenced in the sqldbmap file against their mapped databases.
*
* This task uses an SQL -> Database map in the form of a properties
* file to insert each SQL file listed into its designated database.
*
* @author Hans Lellelid <hans@xmpl.org>
* @author Dominik del Bondio
* @author Jeff Martin <jeff@custommonkey.org> (Torque)
* @author Michael McCallum <gholam@xtra.co.nz> (Torque)
* @author Tim Stephenson <tim.stephenson@sybase.com> (Torque)
* @author Jason van Zyl <jvanzyl@apache.org> (Torque)
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @version $Revision: 536 $
* @package propel.phing
*/
class PropelSQLExec extends Task {
private $goodSql = 0;
private $totalSql = 0;
const DELIM_ROW = "row";
const DELIM_NORMAL = "normal";
/**
* The delimiter type indicating whether the delimiter will
* only be recognized on a line by itself
*/
private $delimiterType = "normal"; // can't use constant just defined
//private static $delimiterTypes = array(DELIM_NORMAL, DELIM_ROW);
//private static $errorActions = array("continue", "stop", "abort");
/** Database connection */
private $conn = null;
/** Autocommit flag. Default value is false */
private $autocommit = false;
/** SQL statement */
private $statement = null;
/** DB driver. */
private $driver = null;
/** DB url. */
private $url = null;
/** User name. */
private $userId = null;
/** Password */
private $password = null;
/** SQL input command */
private $sqlCommand = "";
/** SQL transactions to perform */
private $transactions = array();
/** SQL Statement delimiter */
private $delimiter = ";";
/** Print SQL results. */
private $print = false;
/** Print header columns. */
private $showheaders = true;
/** Results Output file. */
private $output = null;
/** RDBMS Product needed for this SQL. */
private $rdbms = null;
/** RDBMS Version needed for this SQL. */
private $version = null;
/** Action to perform if an error is found */
private $onError = "abort";
/** Encoding to use when reading SQL statements from a file */
private $encoding = null;
/** Src directory for the files listed in the sqldbmap. */
private $srcDir;
/** Properties file that maps an individual SQL file to a database. */
private $sqldbmap;
/**
* Set the sqldbmap properties file.
*
* @param sqldbmap filename for the sqldbmap
*/
public function setSqlDbMap($sqldbmap)
{
$this->sqldbmap = $this->project->resolveFile($sqldbmap);
}
/**
* Get the sqldbmap properties file.
*
* @return filename for the sqldbmap
*/
public function getSqlDbMap()
{
return $this->sqldbmap;
}
/**
* Set the src directory for the sql files listed in the sqldbmap file.
*
* @param PhingFile $srcDir sql source directory
*/
public function setSrcDir(PhingFile $srcDir)
{
$this->srcDir = $srcDir;
}
/**
* Get the src directory for the sql files listed in the sqldbmap file.
*
* @return PhingFile SQL Source directory
*/
public function getSrcDir()
{
return $this->srcDir;
}
/**
* Set the sql command to execute
*
* @param sql sql command to execute
*/
public function addText($sql)
{
$this->sqlCommand .= $sql;
}
/**
* Set the Creole driver to be used.
*
* @param string $driver driver class name
*/
public function setDriver($driver)
{
$this->driver = $driver;
}
/**
* Set the DB connection url.
*
* @param string $url connection url
*/
public function setUrl($url)
{
$this->url = $url;
}
/**
* Set the user name for the DB connection.
*
* @param string $userId database user
* @deprecated Specify userid in the DSN URL.
*/
public function setUserid($userId)
{
$this->userId = $userId;
}
/**
* Set the password for the DB connection.
*
* @param string $password database password
* @deprecated Specify password in the DSN URL.
*/
public function setPassword($password)
{
$this->password = $password;
}
/**
* Set the autocommit flag for the DB connection.
*
* @param boolean $autocommit the autocommit flag
*/
public function setAutoCommit($autocommit)
{
$this->autocommit = (boolean) $autocommit;
}
/**
* Set the statement delimiter.
*
* <p>For example, set this to "go" and delimitertype to "ROW" for
* Sybase ASE or MS SQL Server.</p>
*
* @param string $delimiter
*/
public function setDelimiter($delimiter)
{
$this->delimiter = $delimiter;
}
/**
* Set the Delimiter type for this sql task. The delimiter type takes two
* values - normal and row. Normal means that any occurence of the delimiter
* terminate the SQL command whereas with row, only a line containing just
* the delimiter is recognized as the end of the command.
*
* @param string $delimiterType
*/
public function setDelimiterType($delimiterType)
{
$this->delimiterType = $delimiterType;
}
/**
* Set the print flag.
*
* @param boolean $print
*/
public function setPrint($print)
{
$this->print = (boolean) $print;
}
/**
* Set the showheaders flag.
*
* @param boolean $showheaders
*/
public function setShowheaders($showheaders)
{
$this->showheaders = (boolean) $showheaders;
}
/**
* Set the output file.
*
* @param PhingFile $output
*/
public function setOutput(PhingFile $output)
{
$this->output = $output;
}
/**
* Set the action to perform onerror
*
* @param string $action
*/
public function setOnerror($action)
{
$this->onError = $action;
}
/**
* Load the sql file and then execute it
*
* @throws BuildException
*/
public function main()
{
$this->sqlCommand = trim($this->sqlCommand);
if ($this->sqldbmap === null || $this->getSqlDbMap()->exists() === false) {
throw new BuildException("You haven't provided an sqldbmap, or "
. "the one you specified doesn't exist: " . $this->sqldbmap->getPath());
}
if ($this->url === null) {
throw new BuildException("DSN url attribute must be set!");
}
$map = new Properties();
try {
$map->load($this->getSqlDbMap());
} catch (IOException $ioe) {
throw new BuildException("Cannot open and process the sqldbmap!");
}
$databases = array();
foreach($map->keys() as $sqlfile) {
$database = $map->getProperty($sqlfile);
// Q: already there?
if (!isset($databases[$database])) {
// A: No.
$databases[$database] = array();
}
// We want to make sure that the base schemas
// are inserted first.
if (strpos($sqlfile, "schema.sql") !== false) {
// add to the beginning of the array
array_unshift($databases[$database], $sqlfile);
} else {
array_push($databases[$database], $sqlfile);
}
}
foreach($databases as $db => $files) {
$transactions = array();
foreach($files as $fileName) {
$file = new PhingFile($this->srcDir, $fileName);
if ($file->exists()) {
$this->log("Executing statements in file: " . $file->__toString());
$transaction = new PropelSQLExecTransaction($this);
$transaction->setSrc($file);
$transactions[] = $transaction;
} else {
$this->log("File '" . $file->__toString()
. "' in sqldbmap does not exist, so skipping it.");
}
}
$this->insertDatabaseSqlFiles($this->url, $db, $transactions);
}
}
/**
* Take the base url, the target database and insert a set of SQL
* files into the target database.
*
* @param string $url
* @param string $database
* @param array $transactions
*/
private function insertDatabaseSqlFiles($url, $database, $transactions)
{
$url = str_replace("@DB@", $database, $url);
$this->log("Our new url -> " . $url);
try {
$buf = "Database settings:\n"
. " driver: " . ($this->driver ? $this->driver : "(default)" ). "\n"
. " URL: " . $url . "\n"
. ($this->userId ? " user: " . $this->userId . "\n" : "")
. ($this->password ? " password: " . $this->password . "\n" : "");
$this->log($buf, PROJECT_MSG_VERBOSE);
$dsn = Creole::parseDSN($url);
if($this->userId) {
$dsn["username"] = $this->userId;
}
if ($this->password) {
$dsn["password"] = $this->password;
}
if ($this->driver) {
Creole::registerDriver($dsn['phptype'], $this->driver);
}
$this->conn = Creole::getConnection($dsn);
$this->conn->setAutoCommit($this->autocommit);
$this->statement = $this->conn->createStatement();
$out = null;
try {
if ($this->output !== null) {
$this->log("Opening PrintStream to output file " . $this->output->__toString(), PROJECT_MSG_VERBOSE);
$out = new FileWriter($this->output);
}
// Process all transactions
for ($i=0,$size=count($transactions); $i < $size; $i++) {
$transactions[$i]->runTransaction($out);
if (!$this->autocommit) {
$this->log("Commiting transaction", PROJECT_MSG_VERBOSE);
$this->conn->commit();
}
}
} catch (Exception $e) {
if ($out) $out->close();
}
} catch (IOException $e) {
if (!$this->autocommit && $this->conn !== null && $this->onError == "abort") {
try {
$this->conn->rollback();
} catch (SQLException $ex) {
// do nothing.
System::println("Rollback failed.");
}
}
if ($this->statement) $this->statement->close();
throw new BuildException($e);
} catch (SQLException $e) {
if (!$this->autocommit && $this->conn !== null && $this->onError == "abort") {
try {
$this->conn->rollback();
} catch (SQLException $ex) {
// do nothing.
System::println("Rollback failed");
}
}
if ($this->statement) $this->statement->close();
throw new BuildException($e);
}
$this->statement->close();
$this->log($this->goodSql . " of " . $this->totalSql
. " SQL statements executed successfully");
}
/**
* Read the statements from the .sql file and execute them.
* Lines starting with '//', '--' or 'REM ' are ignored.
*
* Developer note: must be public in order to be called from
* sudo-"inner" class PropelSQLExecTransaction.
*
* @param Reader $reader
* @param $out Optional output stream.
* @throws SQLException
* @throws IOException
*/
public function runStatements(Reader $reader, $out = null)
{
$sql = "";
$line = "";
$sqlBacklog = "";
$hasQuery = false;
$in = new BufferedReader($reader);
try {
while (($line = $in->readLine()) !== null) {
$line = trim($line);
$line = ProjectConfigurator::replaceProperties($this->project, $line,
$this->project->getProperties());
if (StringHelper::startsWith("//", $line) ||
StringHelper::startsWith("--", $line) ||
StringHelper::startsWith("#", $line)) {
continue;
}
if (strlen($line) > 4
&& strtoupper(substr($line,0, 4)) == "REM ") {
continue;
}
if($sqlBacklog !== "")
{
$sql = $sqlBacklog;
$sqlBacklog = "";
}
$sql .= " " . $line . "\n";
// SQL defines "--" as a comment to EOL
// and in Oracle it may contain a hint
// so we cannot just remove it, instead we must end it
if (strpos($line, "--") !== false) {
$sql .= "\n";
}
// DELIM_ROW doesn't need this (as far as i can tell)
if($this->delimiterType == self::DELIM_NORMAL) {
$reg = "#((?:\"(?:\\\\.|[^\"])*\"?)+|'(?:\\\\.|[^'])*'?|" . preg_quote($this->delimiter) . ")#";
$sqlParts = preg_split($reg, $sql, 0, PREG_SPLIT_DELIM_CAPTURE);
$sqlBacklog = "";
foreach($sqlParts as $sqlPart) {
// we always want to append, even if it's a delim (which will be stripped off later)
$sqlBacklog .= $sqlPart;
// we found a single (not enclosed by ' or ") delimiter, so we can use all stuff before the delim as the actual query
if($sqlPart === $this->delimiter) {
$sql = $sqlBacklog;
$sqlBacklog = "";
$hasQuery = true;
}
}
}
if ($hasQuery || ($this->delimiterType == self::DELIM_ROW && $line == $this->delimiter)) {
// this assumes there is always a delimter on the end of the SQL statement.
$sql = StringHelper::substring($sql, 0, strlen($sql) - 1 - strlen($this->delimiter));
$this->log("SQL: " . $sql, PROJECT_MSG_VERBOSE);
$this->execSQL($sql, $out);
$sql = "";
$hasQuery = false;
}
}
// Catch any statements not followed by ;
if ($sql !== "") {
$this->execSQL($sql, $out);
}
} catch (SQLException $e) {
throw $e;
}
}
/**
* Exec the sql statement.
*
* @param sql
* @param out
* @throws SQLException
*/
protected function execSQL($sql, $out = null)
{
// Check and ignore empty statements
if (trim($sql) == "") {
return;
}
try {
$this->totalSql++;
if (!$this->statement->execute($sql)) {
$this->log($this->statement->getUpdateCount() . " rows affected",
PROJECT_MSG_VERBOSE);
} else {
if ($this->print) {
$this->printResults($out);
}
}
$this->goodSql++;
} catch (SQLException $e) {
$this->log("Failed to execute: " . $sql, PROJECT_MSG_ERR);
if ($this->onError != "continue") {
throw $e;
}
$this->log($e->getMessage(), PROJECT_MSG_ERR);
}
}
/**
* print any results in the statement.
*
* @param out
* @throws SQLException
*/
protected function printResults($out = null)
{
$rs = null;
do {
$rs = $this->statement->getResultSet();
if ($rs !== null) {
$this->log("Processing new result set.", PROJECT_MSG_VERBOSE);
$line = "";
$colsprinted = false;
while ($rs->next()) {
if (!$colsprinted && $this->showheaders) {
$first = true;
foreach($this->fields as $fieldName => $ignore) {
if ($first) $first = false; else $line .= ",";
$line .= $fieldName;
}
} // if show headers
$first = true;
foreach($rs->fields as $columnValue) {
if ($columnValue != null) {
$columnValue = trim($columnValue);
}
if ($first) {
$first = false;
} else {
$line .= ",";
}
$line .= $columnValue;
}
if ($out !== null) {
$out->write($line);
$out->newLine();
}
System::println($line);
$line = "";
} // while rs->next()
}
} while ($this->statement->getMoreResults());
System::println();
if ($out !== null) $out->newLine();
}
}
/**
* "Inner" class that contains the definition of a new transaction element.
* Transactions allow several files or blocks of statements
* to be executed using the same Creole connection and commit
* operation in between.
* @package propel.phing
*/
class PropelSQLExecTransaction {
private $tSrcFile = null;
private $tSqlCommand = "";
private $parent;
function __construct($parent)
{
// Parent is required so that we can log things ...
$this->parent = $parent;
}
public function setSrc(PhingFile $src)
{
$this->tSrcFile = $src;
}
public function addText($sql)
{
$this->tSqlCommand .= $sql;
}
/**
* @throws IOException, SQLException
*/
public function runTransaction($out = null)
{
if (!empty($this->tSqlCommand)) {
$this->parent->log("Executing commands", PROJECT_MSG_INFO);
$this->parent->runStatements($tSqlCommand, $out);
}
if ($this->tSrcFile !== null) {
$this->parent->log("Executing file: " . $this->tSrcFile->getAbsolutePath(),
PROJECT_MSG_INFO);
$reader = new FileReader($this->tSrcFile);
$this->parent->runStatements($reader, $out);
$reader->close();
}
}
}

View File

@ -0,0 +1,258 @@
<?php
/*
* $Id: PropelSQLTask.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'propel/engine/database/model/AppData.php';
/**
* The task for building SQL DDL based on the XML datamodel.
*
* This class uses the new DDLBuilder classes instead of the Capsule PHP templates.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.phing
*/
class PropelSQLTask extends AbstractPropelDataModelTask {
/**
* The properties file that maps an SQL file to a particular database.
* @var PhingFile
*/
private $sqldbmap;
/**
* Name of the database.
*/
private $database;
/**
* Set the sqldbmap.
* @param PhingFile $sqldbmap The db map.
*/
public function setSqlDbMap(PhingFile $sqldbmap)
{
$this->sqldbmap = $sqldbmap;
}
/**
* Get the sqldbmap.
* @return PhingFile $sqldbmap.
*/
public function getSqlDbMap()
{
return $this->sqldbmap;
}
/**
* Set the database name.
* @param string $database
*/
public function setDatabase($database)
{
$this->database = $database;
}
/**
* Get the database name.
* @return string
*/
public function getDatabase()
{
return $this->database;
}
/**
* Create the sql -> database map.
*
* @throws IOException - if unable to store properties
*/
private function createSqlDbMap()
{
if ($this->getSqlDbMap() === null) {
return;
}
// Produce the sql -> database map
$sqldbmap = new Properties();
// Check to see if the sqldbmap has already been created.
if ($this->getSqlDbMap()->exists()) {
$sqldbmap->load($this->getSqlDbMap());
}
if ($this->packageObjectModel) {
// in this case we'll get the sql file name from the package attribute
$dataModels = $this->packageDataModels();
foreach ($dataModels as $package => $dataModel) {
foreach ($dataModel->getDatabases() as $database) {
$name = ($package ? $package . '.' : '') . 'schema.xml';
$sqlFile = $this->getMappedFile($name);
$sqldbmap->setProperty($sqlFile->getName(), $database->getName());
}
}
} else {
// the traditional way is to map the schema.xml filenames
$dmMap = $this->getDataModelDbMap();
foreach(array_keys($dmMap) as $dataModelName) {
$sqlFile = $this->getMappedFile($dataModelName);
if ($this->getDatabase() === null) {
$databaseName = $dmMap[$dataModelName];
} else {
$databaseName = $this->getDatabase();
}
$sqldbmap->setProperty($sqlFile->getName(), $databaseName);
}
}
try {
$sqldbmap->store($this->getSqlDbMap(), "Sqlfile -> Database map");
} catch (IOException $e) {
throw new IOException("Unable to store properties: ". $e->getMessage());
}
}
public function main() {
$this->validate();
if(!$this->mapperElement) {
throw new BuildException("You must use a <mapper/> element to describe how names should be transformed.");
}
if ($this->packageObjectModel) {
$dataModels = $this->packageDataModels();
} else {
$dataModels = $this->getDataModels();
}
// 1) first create a map of filenames to databases; this is used by other tasks like
// the SQLExec task.
$this->createSqlDbMap();
// 2) Now actually create the DDL based on the datamodel(s) from XML schema file.
$targetDatabase = $this->getTargetDatabase();
DataModelBuilder::setBuildProperties($this->getPropelProperties());
$builderClazz = DataModelBuilder::getBuilderClass('ddl');
foreach ($dataModels as $package => $dataModel) {
foreach ($dataModel->getDatabases() as $database) {
// file we are going to create
if (!$this->packageObjectModel) {
$name = $dataModel->getName();
} else {
$name = ($package ? $package . '.' : '') . 'schema.xml';
}
$outFile = $this->getMappedFile($name);
$this->log("Writing to SQL file: " . $outFile->getPath());
// First add any "header" SQL
$ddl = call_user_func(array($builderClazz, 'getDatabaseStartDDL'));
foreach($database->getTables() as $table) {
if (!$table->isSkipSql()) {
$builder = DataModelBuilder::builderFactory($table, 'ddl');
$this->log("\t+ " . $table->getName() . " [builder: " . get_class($builder) . "]");
$ddl .= $builder->build();
foreach($builder->getWarnings() as $warning) {
$this->log($warning, PROJECT_MSG_WARN);
}
} else {
$this->log("\t + (skipping) " . $table->getName());
}
} // foreach database->getTables()
// Finally check to see if there is any "footer" SQL
$ddl .= call_user_func(array($builderClazz, 'getDatabaseEndDDL'));
// Now we're done. Write the file!
file_put_contents($outFile->getAbsolutePath(), $ddl);
} // foreach database
} //foreach datamodels
} // main()
/**
* Packages the datamodels to one datamodel per package
*
* This applies only when the the packageObjectModel option is set. We need to
* re-package the datamodels to allow the database package attribute to control
* which tables go into which SQL file.
*
* @return array The packaged datamodels
*/
protected function packageDataModels() {
static $packagedDataModels;
if (is_null($packagedDataModels)) {
$dataModels = $this->getDataModels();
$dataModel = array_shift($dataModels);
$packagedDataModels = array();
$platform = $this->getPlatformForTargetDatabase();
foreach ($dataModel->getDatabases() as $db) {
foreach ($db->getTables() as $table) {
$package = $table->getPackage();
if (!isset($packagedDataModels[$package])) {
$dbClone = $this->cloneDatabase($db);
$dbClone->setPackage($package);
$ad = new AppData($platform);
$ad->setName($dataModel->getName());
$ad->addDatabase($dbClone);
$packagedDataModels[$package] = $ad;
}
$packagedDataModels[$package]->getDatabase($db->getName())->addTable($table);
}
}
}
return $packagedDataModels;
}
protected function cloneDatabase($db) {
$attributes = array (
'name' => $db->getName(),
'baseClass' => $db->getBaseClass(),
'basePeer' => $db->getBasePeer(),
//'defaultPhpType' => $db->getDefaultPhpType(),
'defaultIdMethod' => $db->getDefaultIdMethod(),
'defaultPhpNamingMethod' => $db->getDefaultPhpNamingMethod(),
'defaultTranslateMethod' => $db->getDefaultTranslateMethod(),
//'heavyIndexing' => $db->getHeavyIndexing(),
);
$clone = new Database();
$clone->loadFromXML($attributes);
return $clone;
}
}

View File

@ -0,0 +1,219 @@
# -------------------------------------------------------------------
#
# D E F A U L T P R O P E R T I E S
#
# -------------------------------------------------------------------
# This file sets default properties. You can override any of these
# by specifying your new value in the build.properties file for your
# project or a top-level build.properties file. Either way, you
# should not need to edit this file.
# -------------------------------------------------------------------
# -------------------------------------------------------------------
#
# B A S I C P R O P E R T I E S
#
# -------------------------------------------------------------------
propel.home = .
propel.project =
propel.database =
propel.targetPackage = ${propel.project}
propel.runOnlyOnSchemaChange = false
propel.targetPlatform = php5
propel.packageObjectModel = false
propel.schema.validate = true
# -------------------------------------------------------------------
#
# D A T A B A S E S E T T I N G S
#
# -------------------------------------------------------------------
propel.database.url =
propel.database.buildUrl = ${propel.database.url}
propel.database.createUrl = ${propel.database.buildUrl}
# by default leave the databaseDriver blank, so that bundled driver is used by Creole
propel.database.driver =
propel.database.schema =
propel.database.encoding =
propel.database.manualCreation = false
# -------------------------------------------------------------------
#
# C R E O L E TO X M L S E T T I N G S
#
# -------------------------------------------------------------------
propel.samePhpName = false
propel.addVendorInfo = true
propel.addValidators = none
# -------------------------------------------------------------------
#
# T E M P L A T E V A R I A B L E S
#
# -------------------------------------------------------------------
propel.addGenericAccessors = false
propel.addGenericMutators = false
propel.addSaveMethod = true
propel.addTimeStamp = true
propel.basePrefix = Base
propel.complexObjectModel = true
propel.saveException = PropelException
propel.emulateForeignKeyConstraints = false
# Identifier quoting is only implemented at the DDL layer at this point.
# Since this may result in undesired behavior (especially in Postgres),
# it can be disabled by setting this property to true in your build.properties file.
propel.disableIdentifierQuoting = false
# These are the default formats that will be used when fetching values
# from temporal columns in Propel. You can always specify these when
# calling the methods directly, but for methods like getByName()
# it is nice to change the defaults.
propel.defaultTimeStampFormat = Y-m-d H:i:s
propel.defaultTimeFormat = H:i:s
propel.defaultDateFormat = Y-m-d
propel.omtar.src.base = false
propel.omtar.src.extension = false
propel.omtar.bin.base = false
propel.omtar.bin.extension = false
propel.omtar.deleteFiles = false
# -------------------------------------------------------------------
#
# C O N T R O L T E M P L A T E S
#
# -------------------------------------------------------------------
#
# This is a deprecated idea, that will almost certainly be completely
# removed in Propel 1.2 and/or 2.0.
#
propel.template.conf = ${propel.home}/templates/conf/Control.tpl
propel.template.sql = ${propel.home}/templates/sql/base/Control.tpl
propel.template.sqlDbInit = ${propel.home}/templates/sql/db-init/Control.tpl
# -------------------------------------------------------------------
#
# D I R E C T O R I E S
#
# -------------------------------------------------------------------
propel.project.dir = ${propel.home}/projects/${propel.project}
propel.output.dir = ${propel.project.dir}/build
propel.schema.dir = ${propel.project.dir}
propel.templatePath = ${propel.home}/templates
propel.conf.dir = ${propel.project.dir}
propel.doc.dir = ${propel.output.dir}/doc
propel.php.dir = ${propel.output.dir}/classes
propel.phpconf.dir = ${propel.output.dir}/conf
propel.phpdoc.dir = ${propel.output.dir}/phpdoc
propel.sql.dir = ${propel.output.dir}/sql
propel.graph.dir = ${propel.output.dir}/graph
propel.omtar.dir = ${propel.output.dir}
# -------------------------------------------------------------------
#
# D E F A U L T F I L E N A M ES
#
# -------------------------------------------------------------------
# propel.sqlfile
propel.runtime.conf.file = runtime-conf.xml
propel.runtime.phpconf.file = ${propel.project}-conf.php
propel.default.schema.basename = schema
# Can't use because of inconsistencies in where the files
# are named (some from build-propel.xml, but some from within templates)
# propel.default.data.basename = ${propel.project}-data
propel.schema.xsd.file = ${propel.home}/resources/xsd/database.xsd
propel.schema.xsl.file = ${propel.home}/resources/xsl/database.xsl
# -------------------------------------------------------------------
#
# I N C L U D E A N D E X C L U D E S E T T I N G S
#
# -------------------------------------------------------------------
propel.schema.sql.includes = *schema.xml
propel.schema.sql.excludes =
propel.schema.doc.includes = *schema.xml
propel.schema.doc.excludes =
propel.schema.create-db.includes = *schema.xml
propel.schema.create-db.excludes =
propel.schema.init-sql.includes = *schema.xml
propel.schema.init-sql.excludes = id-table-schema.xml
propel.schema.om.includes = *schema.xml
propel.schema.om.excludes = id-table-schema.xml
propel.schema.datadtd.includes = *schema.xml
propel.schema.datadtd.excludes = id-table-schema.xml
# -------------------------------------------------------------------
#
# M A P P E R S E T T I N G S
#
# -------------------------------------------------------------------
# (note: data xml files are selected based on datadbmap file)
propel.datasql.mapper.from = *.xml
propel.datasql.mapper.to = *.sql
propel.datadump.mapper.from = *schema.xml
propel.datadump.mapper.to = *data.xml
propel.datadtd.mapper.from = *.xml
propel.datadtd.mapper.to = *.dtd
propel.sql.mapper.from = *.xml
propel.sql.mapper.to = *.sql
# -------------------------------------------------------------------
#
# B U I L D E R S E T T I N G S
#
# -------------------------------------------------------------------
# Object Model builders
propel.builder.peer.class = propel.engine.builder.om.php5.PHP5ComplexPeerBuilder
propel.builder.object.class = propel.engine.builder.om.php5.PHP5ComplexObjectBuilder
propel.builder.objectstub.class = propel.engine.builder.om.php5.PHP5ExtensionObjectBuilder
propel.builder.peerstub.class = propel.engine.builder.om.php5.PHP5ExtensionPeerBuilder
propel.builder.objectmultiextend.class = propel.engine.builder.om.php5.PHP5MultiExtendObjectBuilder
propel.builder.mapbuilder.class = propel.engine.builder.om.php5.PHP5MapBuilderBuilder
propel.builder.interface.class = propel.engine.builder.om.php5.PHP5InterfaceBuilder
propel.builder.node.class = propel.engine.builder.om.php5.PHP5NodeBuilder
propel.builder.nodepeer.class = propel.engine.builder.om.php5.PHP5NodePeerBuilder
propel.builder.nodestub.class = propel.engine.builder.om.php5.PHP5ExtensionNodeBuilder
propel.builder.nodepeerstub.class = propel.engine.builder.om.php5.PHP5ExtensionNodePeerBuilder
# SQL builders
propel.builder.ddl.class = propel.engine.builder.sql.${propel.database}.${propel.database}DDLBuilder
propel.builder.datasql.class = propel.engine.builder.sql.${propel.database}.${propel.database}DataSQLBuilder
# Platform classes
propel.platform.class = propel.engine.platform.${propel.database}Platform

View File

@ -0,0 +1,268 @@
<?php
/*
* $Id: BuildPropelGenPEARPackageTask.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://phing.info>.
*/
require_once 'phing/tasks/system/MatchingTask.php';
include_once 'phing/types/FileSet.php';
include_once 'phing/tasks/ext/pearpackage/Fileset.php';
/**
*
* @author Hans Lellelid <hans@xmpl.org>
* @package phing.tasks.ext
* @version $Revision: 536 $
*/
class BuildPropelGenPEARPackageTask extends MatchingTask {
/** Base directory for reading files. */
private $dir;
private $version;
private $state = 'stable';
private $notes;
private $filesets = array();
/** Package file */
private $packageFile;
public function init() {
include_once 'PEAR/PackageFileManager2.php';
if (!class_exists('PEAR_PackageFileManager2')) {
throw new BuildException("You must have installed PEAR_PackageFileManager2 (PEAR_PackageFileManager >= 1.6.0) in order to create a PEAR package.xml file.");
}
}
private function setOptions($pkg){
$options['baseinstalldir'] = 'propel';
$options['packagedirectory'] = $this->dir->getAbsolutePath();
if (empty($this->filesets)) {
throw new BuildException("You must use a <fileset> tag to specify the files to include in the package.xml");
}
$options['filelistgenerator'] = 'Fileset';
// Some PHING-specific options needed by our Fileset reader
$options['phing_project'] = $this->getProject();
$options['phing_filesets'] = $this->filesets;
if ($this->packageFile !== null) {
// create one w/ full path
$f = new PhingFile($this->packageFile->getAbsolutePath());
$options['packagefile'] = $f->getName();
// must end in trailing slash
$options['outputdirectory'] = $f->getParent() . DIRECTORY_SEPARATOR;
$this->log("Creating package file: " . $f->getPath(), PROJECT_MSG_INFO);
} else {
$this->log("Creating [default] package.xml file in base directory.", PROJECT_MSG_INFO);
}
// add install exceptions
$options['installexceptions'] = array( 'pear/pear-propel-gen' => '/',
'pear/pear-propel-gen.bat' => '/',
'pear/pear-build.xml' => '/',
'pear/build.properties' => '/',
);
$options['dir_roles'] = array( 'projects' => 'data',
'test' => 'test',
'templates' => 'data',
'resources' => 'data');
$options['exceptions'] = array( 'pear/pear-propel-gen.bat' => 'script',
'pear/pear-propel-gen' => 'script',
'pear/pear-build.xml' => 'data',
'build.xml' => 'data',
'build-propel.xml' => 'data',
);
$pkg->setOptions($options);
}
/**
* Main entry point.
* @return void
*/
public function main() {
if ($this->dir === null) {
throw new BuildException("You must specify the \"dir\" attribute for PEAR package task.");
}
if ($this->version === null) {
throw new BuildException("You must specify the \"version\" attribute for PEAR package task.");
}
$package = new PEAR_PackageFileManager2();
$this->setOptions($package);
// the hard-coded stuff
$package->setPackage('propel_generator');
$package->setSummary('Generator component of the Propel PHP object persistence layer');
$package->setDescription('Propel is an object persistence layer for PHP5 based on Apache Torque. This package provides the generator engine that builds PHP classes and SQL DDL based on an XML representation of your data model.');
$package->setChannel('pear.phpdb.org');
$package->setPackageType('php');
$package->setReleaseVersion($this->version);
$package->setAPIVersion($this->version);
$package->setReleaseStability($this->state);
$package->setAPIStability($this->state);
$package->setNotes($this->notes);
$package->setLicense('LGPL', 'http://www.gnu.org/licenses/lgpl.html');
// Add package maintainers
$package->addMaintainer('lead', 'hans', 'Hans Lellelid', 'hans@xmpl.org');
$package->addMaintainer('lead', 'david', 'David Zuelke', 'dz@bitxtender.com');
// (wow ... this is a poor design ...)
//
// note that the order of the method calls below is creating
// sub-"release" sections which have specific rules. This replaces
// the platformexceptions system in the older version of PEAR's package.xml
//
// Programmatically, I feel the need to re-iterate that this API for PEAR_PackageFileManager
// seems really wrong. Sub-sections should be encapsulated in objects instead of having
// a "flat" API that does not represent the structure being created....
// creating a sub-section for 'windows'
$package->addRelease();
$package->setOSInstallCondition('windows');
$package->addInstallAs('pear/pear-propel-gen.bat', 'propel-gen.bat');
$package->addIgnoreToRelease('pear/pear-propel-gen');
// creating a sub-section for non-windows
$package->addRelease();
$package->addInstallAs('pear/pear-propel-gen', 'propel-gen');
$package->addIgnoreToRelease('pear/pear-propel-gen.bat');
// "core" dependencies
$package->setPhpDep('5.0.0');
$package->setPearinstallerDep('1.4.0');
// "package" dependencies
$package->addPackageDepWithChannel( 'required', 'phing', 'pear.phing.info', '2.2.0RC1');
$package->addPackageDepWithChannel( 'required', 'creole', 'pear.phpdb.org', '1.1.0RC1');
// now add the replacements ....
$package->addReplacement('Phing.php', 'pear-config', '@DATA-DIR@', 'data_dir');
$package->addReplacement('pear/pear-propel-gen.bat', 'pear-config', '@PHP-BIN@', 'php_bin');
$package->addReplacement('pear/pear-propel-gen.bat', 'pear-config', '@BIN-DIR@', 'bin_dir');
$package->addReplacement('pear/pear-propel-gen.bat', 'pear-config', '@PEAR-DIR@', 'php_dir');
$package->addReplacement('pear/pear-propel-gen.bat', 'pear-config', '@DATA-DIR@', 'data_dir');
$package->addReplacement('pear/pear-propel-gen', 'pear-config', '@PHP-BIN@', 'php_bin');
$package->addReplacement('pear/pear-propel-gen', 'pear-config', '@BIN-DIR@', 'bin_dir');
$package->addReplacement('pear/pear-propel-gen', 'pear-config', '@PEAR-DIR@', 'php_dir');
$package->addReplacement('pear/pear-propel-gen', 'pear-config', '@DATA-DIR@', 'data_dir');
$package->addReplacement('pear/pear-build.xml', 'pear-config', '@PHP-BIN@', 'php_bin');
$package->addReplacement('pear/pear-build.xml', 'pear-config', '@BIN-DIR@', 'bin_dir');
$package->addReplacement('pear/pear-build.xml', 'pear-config', '@PEAR-DIR@', 'php_dir');
$package->addReplacement('pear/pear-build.xml', 'pear-config', '@DATA-DIR@', 'data_dir');
// now we run this weird generateContents() method that apparently
// is necessary before we can add replacements ... ?
$package->generateContents();
$e = $package->writePackageFile();
if (PEAR::isError($e)) {
throw new BuildException("Unable to write package file.", new Exception($e->getMessage()));
}
}
/**
* Used by the PEAR_PackageFileManager_PhingFileSet lister.
* @return array FileSet[]
*/
public function getFileSets() {
return $this->filesets;
}
// -------------------------------
// Set properties from XML
// -------------------------------
/**
* Nested creator, creates a FileSet for this task
*
* @return FileSet The created fileset object
*/
function createFileSet() {
$num = array_push($this->filesets, new FileSet());
return $this->filesets[$num-1];
}
/**
* Set the version we are building.
* @param string $v
* @return void
*/
public function setVersion($v){
$this->version = $v;
}
/**
* Set the state we are building.
* @param string $v
* @return void
*/
public function setState($v) {
$this->state = $v;
}
/**
* Sets release notes field.
* @param string $v
* @return void
*/
public function setNotes($v) {
$this->notes = $v;
}
/**
* Sets "dir" property from XML.
* @param PhingFile $f
* @return void
*/
public function setDir(PhingFile $f) {
$this->dir = $f;
}
/**
* Sets the file to use for generated package.xml
*/
public function setDestFile(PhingFile $f) {
$this->packageFile = $f;
}
}

View File

@ -0,0 +1,146 @@
<?xml version="1.0"?>
<!--
This build file creates a minimal package of propel-generator files,
builds a package.xml for installation using PEAR and creates the necessary TGZ file.
It's pretty easy to build the PEAR package:
$> cd /path/to/propel-generator
$> phing -Dversion=1.0.0RC1 -f pear\build-pear-package.xml
-->
<project name="propel_generator" basedir="." default="main">
<property name="propelgen.home" value=".."/>
<property name="build.base.dir" value="build"/>
<property name="pkgname" value="${phing.project.name}-${version}"/>
<property name="build.src.dir" value="${build.base.dir}/${pkgname}"/>
<!-- some default properties -->
<property name="notes"><![CDATA[This is the a bugfix release to the 1.2 branch of the Propel Generator.
See: http://propel.phpdb.org/trac/query?status=closed&milestone=1.2.1&resolution=fixed&order=priority for CHANGELOG.
]]></property>
<property name="state" value="devel"/>
<taskdef
name="pear-package"
classname="BuildPropelGenPEARPackageTask" classpath="."/>
<fileset dir="${propelgen.home}/classes/propel" id="classes">
<include name="**"/>
</fileset>
<fileset dir="${propelgen.home}" id="data">
<!--<include name="build.xml"/>-->
<include name="build-propel.xml"/>
<include name="projects/bookstore/*"/>
<include name="projects/treetest/*"/>
<include name="pear/pear-build.xml"/>
<include name="pear/pear-propel*"/>
<include name="pear/build.properties"/>
<include name="default.properties"/>
<include name="templates/**"/>
<include name="resources/**"/>
</fileset>
<!--
==============================================
Main entry point
==============================================
-->
<target name="main" if="version" depends="versioncheck">
<phingcall target="build"/>
<phingcall target="pear-package"/>
<phingcall target="tar"/>
</target>
<!--
===================================================================
Target: checks if language was given, otherwise fail
===================================================================
-->
<target name="versioncheck" unless="version">
<echo message="====================================================="/>
<echo message="Version not specified. You must enter a version. In"/>
<echo message="the future you can add this to build.properties or"/>
<echo message="enter it on the command line: "/>
<echo message=" "/>
<echo message="-Dversion=1.0.0"/>
<echo message="====================================================="/>
<input propertyname="version" promptChar=":">Propel version for package</input>
<property name="pkgname" value="${phing.project.name}-${version}" override="true"/>
<property name="build.src.dir" value="${build.base.dir}/${pkgname}" override="true"/>
</target>
<!--
==============================================
Copy the desired files into the build/ dir
making sure to put them in the directory
structure that will be needed for PEAR install
==============================================
-->
<target name="build">
<echo>-----------------------------</echo>
<echo>| Creating directory layout |</echo>
<echo>-----------------------------</echo>
<delete dir="${build.base.dir}"/>
<mkdir dir="${build.base.dir}"/>
<copy todir="${build.src.dir}">
<fileset refid="classes"/>
<fileset refid="data"/>
</copy>
<!-- some files need to be manually moved here to save headache when
doing the pear package.xml creation -->
<move file="${build.src.dir}/pear/build.properties" todir="${build.src.dir}"/>
<move file="${build.src.dir}/pear/pear-build.xml" todir="${build.src.dir}"/>
<chmod file="${build.src.dir}/pear/pear-propel-gen" mode="755"/>
</target>
<!--
==============================================
Create a PEAR package.xml which will guide the
installation.
==============================================
-->
<target name="pear-package">
<echo>-----------------------------</echo>
<echo>| Creating PEAR package.xml |</echo>
<echo>-----------------------------</echo>
<echo></echo>
<pear-package dir="${build.src.dir}" destFile="${build.base.dir}/package.xml" version="${version}" state="${state}" notes="${notes}">
<fileset dir="${build.src.dir}">
<include name="**"/>
</fileset>
</pear-package>
</target>
<!--
==============================================
Create a tar.gz of the files, which will be
installed by pear package manager.
==============================================
-->
<target name="tar">
<echo>-----------------------------</echo>
<echo>| Creating tar.gz package |</echo>
<echo>-----------------------------</echo>
<property name="tarfile" value="${build.base.dir}/${pkgname}.tgz"/>
<delete file="${tarfile}"/>
<tar destFile="${tarfile}" basedir="${build.base.dir}" />
</target>
</project>

View File

@ -0,0 +1,5 @@
# In this file you can define any properties taht you want to affect
# all projects built using the propel-gen script on this system
#
# See http://propel.phpdb.org/trac/wiki/Users/Documentation/BuildProperties for a
# list of available properties.

View File

@ -0,0 +1,114 @@
<!--
Use this file to faciliate easy per-project building using
PEAR-installed Propel-generator.
This Phing script is invoked via the shell script propel-gen (.bat
for Windows). Normally you should not need to edit this script or
be aware of it in any way.
Normal use:
$> propel-gen /path/to/my/project
Specific target:
$> propel-gen insert-sql /path/to/my/project
-->
<project name="propel-project-builder" default="main" basedir=".">
<!-- set a default target if none provided -->
<property name="target" value="main"/>
<property name="propel.project.dir" value="${project.dir}"/>
<resolvepath propertyName="propel.project.dir" file="${propel.project.dir}" dir="${application.startdir}"/>
<target name="projdircheckExists">
<condition property="projDirExists">
<and>
<not>
<equals arg1="${propel.project.dir}" arg2="" trim="true"/>
</not>
<available file="${propel.project.dir}/build.properties"/>
</and>
</condition>
</target>
<target name="projdircheck" depends="projdircheckExists" unless="projDirExists">
<echo message="====================================================="/>
<echo message="Project directory not specified or invalid. You must "/>
<echo message="specify the path to your project directory and your "/>
<echo message="project directory must contain your build.properties "/>
<echo message="and schema.xml files. "/>
<echo message=" "/>
<echo message="Usage: "/>
<echo message=" "/>
<echo message="$&gt; propel-gen /path/to/projectdir [target]"/>
<echo message=" "/>
<echo message="====================================================="/>
<fail message="No project directory specified."/>
</target>
<target name="configure" depends="projdircheck">
<echo msg="Loading project-specific props from ${project.dir}/build.properties"/>
<property file="${propel.project.dir}/build.properties"/>
</target>
<target name="main" depends="configure"
description="The main target. Includes project-specific build.properties and calls the build-propel.xml script">
<!--<property file="${project.dir}/build.properties"/>-->
<phing phingfile="build-propel.xml" target="${target}"/>
</target>
<!--
Convenience mappings to build-propel.xml main targets
This makes it possible to use this buildfile w/o needing to specify
target as a property, e.g.:
$> phing -Dproject=bookstore insert-sql
The main reason for this is just consistency w/ old build-propel.xml file
(primarily for documentation & user confusion avoidance reasons). There are relatively
few & infrequently changing main targets of build-propel.xml, so it's a non-
issue as far as maintenance is concerned.
-->
<target name="convert-props" depends="configure">
<phing phingfile="build-propel.xml" target="convert-props"/>
</target>
<target name="create-db" depends="configure">
<phing phingfile="build-propel.xml" target="create-db"/>
</target>
<target name="creole" depends="configure">
<phing phingfile="build-propel.xml" target="creole"/>
</target>
<target name="datadtd" depends="configure">
<phing phingfile="build-propel.xml" target="datadtd"/>
</target>
<target name="datadump" depends="configure">
<phing phingfile="build-propel.xml" target="datadump"/>
</target>
<target name="datasql" depends="configure">
<phing phingfile="build-propel.xml" target="datasql"/>
</target>
<target name="insert-sql" depends="configure">
<phing phingfile="build-propel.xml" target="insert-sql"/>
</target>
<target name="om" depends="configure">
<phing phingfile="build-propel.xml" target="om"/>
</target>
<target name="sql" depends="configure">
<phing phingfile="build-propel.xml" target="sql"/>
</target>
</project>

View File

@ -0,0 +1,21 @@
#!/bin/sh
# ------------------------------------------------------------------------
# The phing build script for Unix based systems
# $Id: pear-propel-gen,v 1.2 2004/10/17 13:24:09 hlellelid Exp $
# ------------------------------------------------------------------------
# Change this to reflect your environment if the default value doesn't work
export PHING_COMMAND="phing"
# -------------------------------------------------------------------------
# Do not change anything below this line unless you know what you're doing.
# -------------------------------------------------------------------------
# (currently this is not reached)
if (test -z "$PHING_COMMAND") ; then
echo "WARNING: PHP_COMMAND environment not set. (Assuming phing on PATH)"
export PHING_COMMAND=php
fi
$PHING_COMMAND -f @DATA-DIR@/propel_generator/pear-build.xml -Dproject.dir=$*

View File

@ -0,0 +1,24 @@
@ECHO OFF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: The propel-gen build script for Windows based systems
:: $Id: pear-propel-gen.bat,v 1.2 2004/10/17 13:24:09 hlellelid Exp $
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::----------------------------------------------------------------------------------
:: Please set following to the "phing" script. By default this is expected to be
:: on your path. (You don't need to modify this file if that is the case.)
SET phingScript=phing
::---------------------------------------------------------------------------------
::---------------------------------------------------------------------------------
:: Do not modify below this line!! (Unless you know what your doing :)
::---------------------------------------------------------------------------------
::---------------------------------------------------------------------------------
"%phingScript%" -f @DATA-DIR@\propel_generator\pear-build.xml -Dproject.dir=%*
GOTO :EOF
:PAUSE_END
PAUSE

View File

@ -0,0 +1,164 @@
<!--
Propel XML database schema DTD
$Id: database.dtd,v 1.7 2005/03/30 11:38:18 hlellelid Exp $
This is based very closely on the schema DTD for Torque, but
some differences do exist.
-->
<!--
defaultPhpNamingMethod determines how a table or column name,
from the name attribute in the xml database file, is converted to a
PHP class or method name.
nochange - indicates not change is performed.
underscore - Underscores are removed, First letter is
capitalized, first letter after an underscore
is capitalized, the rest of the letters are
converted to lowercase.
phpname - same as underscore, but no letters are converted
to lowercase.
-->
<!ELEMENT database (external-schema*, table+)>
<!ATTLIST database
name CDATA #IMPLIED
defaultIdMethod (native|none) "none"
defaultTranslateMethode CDATA #IMPLIED
package CDATA #IMPLIED
baseClass CDATA #IMPLIED
basePeer CDATA #IMPLIED
defaultPhpNamingMethod (nochange|underscore|phpname) "underscore"
heavyIndexing (true|false) "false"
>
<!ELEMENT external-schema EMPTY>
<!ATTLIST external-schema
filename CDATA #REQUIRED
>
<!--
note: the interface="true", requires that useManagers=true in the
properties file.
-->
<!ELEMENT table (column+,(foreign-key|index|unique|id-method-parameter|validator|vendor)*)>
<!ATTLIST table
name CDATA #REQUIRED
phpName CDATA #IMPLIED
idMethod (native|autoincrement|sequence|none|null) "null"
skipSql (true|false) "false"
readOnly (true|false) "false"
abstract (true|false) "false"
isTree (true|false) "false"
package CDATA #IMPLIED
baseClass CDATA #IMPLIED
basePeer CDATA #IMPLIED
alias CDATA #IMPLIED
interface CDATA #IMPLIED
phpNamingMethod (nochange|underscore|phpname) #IMPLIED
heavyIndexing (true|false) #IMPLIED
description CDATA #IMPLIED
>
<!ELEMENT id-method-parameter EMPTY>
<!ATTLIST id-method-parameter
name CDATA "default"
value CDATA #REQUIRED
>
<!ELEMENT column ((inheritance|vendor)*)>
<!ATTLIST column
name CDATA #REQUIRED
phpName CDATA #IMPLIED
peerName CDATA #IMPLIED
primaryKey (true|false) "false"
required (true|false) "false"
type
(
BIT | TINYINT | SMALLINT | INTEGER | BIGINT | FLOAT
| REAL | NUMERIC | DECIMAL | CHAR | VARCHAR | LONGVARCHAR
| DATE | TIME | TIMESTAMP | BINARY | VARBINARY | LONGVARBINARY
| NULL | OTHER | PHP_OBJECT | DISTINCT | STRUCT | ARRAY
| BLOB | CLOB | REF | BOOLEANINT | BOOLEANCHAR
| DOUBLE | BOOLEAN
) "VARCHAR"
phpType (object|primitive) #IMPLIED
size CDATA #IMPLIED
scale CDATA #IMPLIED
default CDATA #IMPLIED
autoIncrement (true|false) "false"
inheritance (single|false) "false"
inputValidator CDATA #IMPLIED
phpNamingMethod (nochange|underscore|phpname) #IMPLIED
description CDATA #IMPLIED
lazyLoad (true|false) "false"
>
<!ELEMENT inheritance EMPTY>
<!ATTLIST inheritance
key CDATA #REQUIRED
class CDATA #REQUIRED
package CDATA #IMPLIED
extends CDATA #IMPLIED
>
<!ELEMENT foreign-key (reference+, vendor*)>
<!ATTLIST foreign-key
foreignTable CDATA #REQUIRED
name CDATA #IMPLIED
onUpdate (CASCADE|cascade|SETNULL|setnull|RESTRICT|restrict|NONE|none) "none"
onDelete (CASCADE|cascade|SETNULL|setnull|RESTRICT|restrict|NONE|none) "none"
>
<!ELEMENT reference EMPTY>
<!ATTLIST reference
local CDATA #REQUIRED
foreign CDATA #REQUIRED
>
<!ELEMENT index (index-column+)>
<!ATTLIST index
name CDATA #IMPLIED
>
<!ELEMENT index-column (vendor*)>
<!ATTLIST index-column
name CDATA #REQUIRED
size CDATA #IMPLIED
>
<!ELEMENT unique (unique-column+)>
<!ATTLIST unique
name CDATA #IMPLIED
>
<!ELEMENT unique-column (vendor*)>
<!ATTLIST unique-column
name CDATA #REQUIRED
>
<!ELEMENT validator (rule+)>
<!ATTLIST validator
column CDATA #REQUIRED
translate CDATA #IMPLIED
>
<!ELEMENT rule EMPTY>
<!ATTLIST rule
name (mask|maxLength|maxValue|minLength|minValue|required|unique|validValues) #REQUIRED
value CDATA #IMPLIED
size ID #IMPLIED
message CDATA #IMPLIED
>
<!ELEMENT vendor (parameter+)>
<!ATTLIST validator
type CDATA #REQUIRED
>
<!ELEMENT parameter EMPTY>
<!ATTLIST parameter
name CDATA #REQUIRED
value CDATA #REQUIRED
>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name='custom_datatypes'>
<xs:restriction base='xs:string'>
</xs:restriction>
</xs:simpleType>
</xs:schema>

View File

@ -0,0 +1,346 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- XML Schema for the Propel schema file
This is just the first draft derived from the existing DTD
and some additional restrictions have been included
Comments are a quite rare, I guess most things are pretty
readable. An additional xml schema: custom_datatypes.xsd is
also included. For now this file is unused, but that will
change; don't worry.
Ron -->
<xs:include schemaLocation="custom_datatypes.xsd"/>
<xs:element name="database" type="database"/>
<xs:element name="vendor" type="vendor"/>
<xs:simpleType name="file">
<xs:restriction base="xs:string">
<!-- Match any relative or absolute path and file containing letters, numbers and _ -->
<xs:pattern value="((\.{1,2}|[\w_]*)/)*([\w_]*\.?)+"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="default_datatypes">
<xs:restriction base="xs:string">
<xs:enumeration value="BIT"/>
<xs:enumeration value="TINYINT"/>
<xs:enumeration value="SMALLINT"/>
<xs:enumeration value="INTEGER"/>
<xs:enumeration value="BIGINT"/>
<xs:enumeration value="FLOAT"/>
<xs:enumeration value="REAL"/>
<xs:enumeration value="NUMERIC"/>
<xs:enumeration value="DECIMAL"/>
<xs:enumeration value="CHAR"/>
<xs:enumeration value="VARCHAR"/>
<xs:enumeration value="LONGVARCHAR"/>
<xs:enumeration value="DATE"/>
<xs:enumeration value="TIME"/>
<xs:enumeration value="TIMESTAMP"/>
<xs:enumeration value="BINARY"/>
<xs:enumeration value="VARBINARY"/>
<xs:enumeration value="LONGVARBINARY"/>
<xs:enumeration value="NULL"/>
<xs:enumeration value="OTHER"/>
<xs:enumeration value="PHP_OBJECT"/>
<xs:enumeration value="DISTINCT"/>
<xs:enumeration value="STRUCT"/>
<xs:enumeration value="ARRAY"/>
<xs:enumeration value="BLOB"/>
<xs:enumeration value="CLOB"/>
<xs:enumeration value="REF"/>
<xs:enumeration value="BOOLEANINT"/>
<xs:enumeration value="BOOLEANCHAR"/>
<xs:enumeration value="DOUBLE"/>
<xs:enumeration value="BOOLEAN"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="datatype">
<xs:union memberTypes="default_datatypes custom_datatypes"/>
</xs:simpleType>
<xs:simpleType name="dbidmethod">
<xs:restriction base="xs:string">
<xs:enumeration value="native"/>
<xs:enumeration value="none"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tbidmethod">
<xs:restriction base="xs:string">
<xs:enumeration value="autoincrement"/>
<xs:enumeration value="sequence"/>
<xs:enumeration value="null"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="idmethod">
<xs:union memberTypes="dbidmethod tbidmethod"/>
</xs:simpleType>
<xs:simpleType name="phpnamingmethod">
<xs:restriction base="xs:string">
<xs:enumeration value="nochange"/>
<xs:enumeration value="underscore"/>
<xs:enumeration value="phpname"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="delete">
<xs:restriction base="xs:string">
<xs:enumeration value="cascade"/>
<xs:enumeration value="set null"/>
<xs:enumeration value="setnull"/>
<xs:enumeration value="restrict"/>
<xs:enumeration value="none"/>
<xs:enumeration value=""/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="update">
<xs:restriction base="xs:string">
<xs:enumeration value="cascade"/>
<xs:enumeration value="setnull"/>
<xs:enumeration value="set null"/>
<xs:enumeration value="restrict"/>
<xs:enumeration value="none"/>
<xs:enumeration value=""/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="rulename">
<xs:restriction base="xs:string">
<xs:enumeration value="mask"/>
<xs:enumeration value="maxLength"/>
<xs:enumeration value="maxValue"/>
<xs:enumeration value="minLength"/>
<xs:enumeration value="minValue"/>
<xs:enumeration value="required"/>
<xs:enumeration value="unique"/>
<xs:enumeration value="validValues"/>
<xs:enumeration value="notMatch"/>
<xs:enumeration value="match"/>
<xs:enumeration value="class"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="inh_option">
<xs:restriction base="xs:string">
<xs:enumeration value="single"/>
<xs:enumeration value="false"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="php_type">
<xs:restriction base="xs:string">
<xs:enumeration value="primitive"/>
<xs:enumeration value="object"/>
</xs:restriction>
</xs:simpleType>
<!-- Restrict column name to letters (upper- and lowercase), numbers and the _ -->
<xs:simpleType name="column_name">
<xs:restriction base="xs:string">
<xs:pattern value="[\w_]+"/>
</xs:restriction>
</xs:simpleType>
<!-- Restrict php name to letters (upper- and lowercase), numbers and the _ -->
<xs:simpleType name="php_name">
<xs:restriction base="xs:string">
<xs:pattern value="[\w_]+"/>
</xs:restriction>
</xs:simpleType>
<!-- Restrict php class name to letters (upper- and lowercase), numbers and the _. Dot seperated -->
<xs:simpleType name="php_class">
<xs:restriction base="xs:string">
<xs:pattern value="([\w_]+.?)+"/>
</xs:restriction>
</xs:simpleType>
<!-- Restrict table name to letters (upper- and lowercase), numbers and the _ -->
<xs:simpleType name="table_name">
<xs:restriction base="xs:string">
<xs:pattern value="[\w_]+"/>
</xs:restriction>
</xs:simpleType>
<!-- Restrict index name to letters (upper- and lowercase), numbers and the _ -->
<xs:simpleType name="index_name">
<xs:restriction base="xs:string">
<xs:pattern value="[\w_]+"/>
</xs:restriction>
</xs:simpleType>
<!-- Restrict foreign column name to letters (upper- and lowercase), numbers and the _ -->
<xs:simpleType name="foreign_name">
<xs:restriction base="xs:string">
<xs:pattern value="[\w_]+"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="parameter">
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="value" type="xs:string" use="required"/>
</xs:complexType>
<xs:complexType name="validator">
<xs:sequence>
<xs:element name="rule" type="rule" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="column" type="column_name" use="required"/>
<xs:attribute name="translate" type="xs:string" use="optional"/>
</xs:complexType>
<xs:complexType name="vendor">
<xs:sequence>
<xs:element name="parameter" type="parameter" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="type" use="required"/>
</xs:complexType>
<xs:complexType name="rule">
<xs:attribute name="name" type="rulename" use="required"/>
<xs:attribute name="value" type="xs:string" use="optional"/>
<xs:attribute name="size" type="xs:positiveInteger" use="optional"/>
<xs:attribute name="message" type="xs:string" use="optional"/>
<xs:attribute name="class" type="xs:string" use="optional"/>
</xs:complexType>
<xs:complexType name="id-method-parameter">
<xs:attribute name="name" type="xs:string" use="optional"/>
<xs:attribute name="value" type="xs:string" use="required"/>
</xs:complexType>
<xs:complexType name="index">
<xs:choice maxOccurs="unbounded">
<xs:element name="index-column" type="index-column" minOccurs="1" maxOccurs="unbounded"/>
<xs:element ref="vendor" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
<xs:attribute name="name" type="index_name" use="optional"/>
</xs:complexType>
<xs:complexType name="unique">
<xs:choice maxOccurs="unbounded">
<xs:element name="unique-column" type="unique-column" minOccurs="1" maxOccurs="unbounded"/>
<xs:element ref="vendor" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
<xs:attribute name="name" type="index_name" use="optional"/>
</xs:complexType>
<xs:complexType name="index-column">
<xs:sequence>
<xs:element ref="vendor" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="name" type="column_name" use="required"/>
<xs:attribute name="size" type="xs:positiveInteger" use="optional"/>
</xs:complexType>
<xs:complexType name="unique-column">
<xs:sequence>
<xs:element ref="vendor" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="name" type="column_name" use="required"/>
<xs:attribute name="size" type="xs:positiveInteger" use="optional"/>
</xs:complexType>
<xs:complexType name="inheritance">
<xs:attribute name="key" type="xs:string" use="required"/>
<xs:attribute name="class" type="xs:string" use="required"/>
<xs:attribute name="package" type="xs:string" use="optional"/>
<xs:attribute name="extends" type="xs:string" use="optional"/>
</xs:complexType>
<xs:complexType name="reference">
<xs:attribute name="local" type="column_name" use="required"/>
<xs:attribute name="foreign" type="column_name" use="required"/>
</xs:complexType>
<xs:complexType name="column">
<xs:choice maxOccurs="unbounded">
<xs:element name="inheritance" type="inheritance" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="vendor" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
<xs:attribute name="name" type="column_name" use="required"/>
<xs:attribute name="phpName" type="php_name" use="optional"/>
<xs:attribute name="peerName" type="php_class" use="optional"/>
<xs:attribute name="primaryKey" type="xs:boolean" default="false"/>
<xs:attribute name="required" type="xs:boolean" default="false"/>
<xs:attribute name="type" type="datatype" default="VARCHAR"/>
<xs:attribute name="phpType" type="php_type" use="optional"/>
<xs:attribute name="size" type="xs:nonNegativeInteger" use="optional"/>
<xs:attribute name="scale" type="xs:nonNegativeInteger" use="optional"/>
<xs:attribute name="default" type="xs:string" use="optional"/>
<xs:attribute name="autoIncrement" type="xs:boolean" default="false"/>
<xs:attribute name="inheritance" type="inh_option" default="false"/>
<xs:attribute name="inputValidator" type="xs:string" use="optional"/>
<xs:attribute name="phpNamingMethod" type="phpnamingmethod" use="optional"/>
<xs:attribute name="description" type="xs:string" use="optional"/>
<xs:attribute name="lazyLoad" type="xs:boolean" default="false"/>
<xs:attribute name="nodeKeySep" type="xs:string" use="optional"/> <!-- missing in the old DTD, but required to keep the treetest example working -->
<xs:attribute name="nodeKey" type="xs:string" use="optional"/> <!-- missing in the old DTD, but required to keep the treetest example working -->
<xs:attribute name="require" type="xs:string" use="optional"/>
</xs:complexType>
<xs:complexType name="foreign-key">
<xs:choice maxOccurs="unbounded">
<xs:element name="reference" type="reference" minOccurs="1" maxOccurs="unbounded"/>
<xs:element ref="vendor" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
<xs:attribute name="foreignTable" type="table_name" use="required"/>
<xs:attribute name="name" type="foreign_name" use="optional"/>
<xs:attribute name="onDelete" type="delete" default="none"/>
<xs:attribute name="onUpdate" type="update" default="none"/>
</xs:complexType>
<xs:complexType name="external-schema">
<xs:attribute name="filename" type="file" use="required"/>
</xs:complexType>
<xs:complexType name="table">
<xs:choice maxOccurs="unbounded">
<xs:element name="column" type="column" maxOccurs="unbounded"/>
<xs:element name="foreign-key" type="foreign-key" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="index" type="index" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="unique" type="unique" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="id-method-parameter" type="id-method-parameter" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="validator" type="validator" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="vendor" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
<xs:attribute name="name" type="table_name" use="required"/>
<xs:attribute name="phpName" type="php_class" use="optional"/>
<xs:attribute name="idMethod" type="idmethod" use='optional'/>
<xs:attribute name="skipSql" type="xs:boolean" default="false"/>
<xs:attribute name="readOnly" type="xs:boolean" default="false"/>
<xs:attribute name="abstract" type="xs:boolean" default="false"/>
<xs:attribute name="baseClass" type="php_class" use="optional"/>
<xs:attribute name="basePeer" type="php_class" use="optional"/>
<xs:attribute name="alias" type="table_name" use="optional"/>
<xs:attribute name="package" type="xs:string" use="optional"/>
<xs:attribute name="interface" type="xs:string" use="optional"/>
<xs:attribute name="phpNamingMethod" type="phpnamingmethod" use='optional'/>
<xs:attribute name="heavyIndexing" type="xs:boolean" use="optional"/>
<xs:attribute name="description" type="xs:string"/>
<xs:attribute name="isTree" type="xs:boolean" use="optional"/> <!-- missing in the old DTD, but required to keep the treetest example working -->
</xs:complexType>
<xs:complexType name="database">
<xs:choice maxOccurs="unbounded">
<xs:element name="external-schema" type="external-schema" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="table" type="table" minOccurs="1" maxOccurs="unbounded"/>
</xs:choice>
<xs:attribute name="name" type="xs:string" use="optional"/>
<xs:attribute name="defaultIdMethod" type="dbidmethod" default="none"/>
<xs:attribute name="defaultTranslateMethod" type="xs:string" use="optional"/>
<xs:attribute name="package" type="php_class" use="optional"/>
<xs:attribute name="baseClass" type="php_class" use="optional"/>
<xs:attribute name="basePeer" type="php_class" use="optional"/>
<xs:attribute name="defaultPhpNamingMethod" type="phpnamingmethod" default="underscore"/>
<xs:attribute name="heavyIndexing" type="xs:boolean" default="false"/>
</xs:complexType>
</xs:schema>

View File

@ -0,0 +1,226 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [<!ENTITY nbsp "&#160;">]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="UTF-8" />
<xsl:template match="/">
<xsl:apply-templates select='database'/>
</xsl:template>
<xsl:template match='database'>
<database>
<xsl:if test='not(boolean(@defaultIdMethod))'>
<xsl:attribute name='defaultIdMethod'>none</xsl:attribute>
</xsl:if>
<xsl:if test='not(boolean(@defaultPhpNamingMethod))'>
<xsl:attribute name='defaultPhpNamingMethod'>underscore</xsl:attribute>
</xsl:if>
<xsl:if test='not(boolean(@heavyIndexing))'>
<xsl:attribute name='heavyIndexing'>false</xsl:attribute>
</xsl:if>
<xsl:apply-templates select='@*'/>
<xsl:apply-templates select='external-schema'/>
<xsl:apply-templates select='table'/>
</database>
</xsl:template>
<xsl:template match='@defaultPhPNamingMethod'>
<xsl:attribute name='defaultPhPNamingMethod'><xsl:value-of select='translate(., "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")'/></xsl:attribute>
</xsl:template>
<xsl:template match='@onDelete'>
<xsl:choose>
<xsl:when test='.=""'>
<xsl:attribute name='onDelete'>none</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name='onDelete'><xsl:value-of select='translate(., "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")'/></xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match='@OnDelete'>
<xsl:choose>
<xsl:when test='.=""'>
<xsl:attribute name='onDelete'>none</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name='onDelete'><xsl:value-of select='translate(., "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")'/></xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match='@onUpdate'>
<xsl:choose>
<xsl:when test='.=""'>
<xsl:attribute name='onUpdate'>none</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name='onUpdate'><xsl:value-of select='translate(., "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")'/></xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match='@OnUpdate'>
<xsl:choose>
<xsl:when test='.=""'>
<xsl:attribute name='onUpdate'>none</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name='onUpdate'><xsl:value-of select='translate(., "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")'/></xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match='@IdMethod'>
<xsl:attribute name='idMethod'><xsl:value-of select='.'/></xsl:attribute>
</xsl:template>
<xsl:template match='@*' priority='-1'>
<xsl:copy-of select='.'/>
</xsl:template>
<xsl:template match='external-schema'>
<external-schema>
<xsl:apply-templates select='@*'/>
</external-schema>
</xsl:template>
<xsl:template match='table'>
<table>
<xsl:if test='not(boolean(@skipSql))'>
<xsl:attribute name='skipSql'>false</xsl:attribute>
</xsl:if>
<xsl:if test='not(boolean(@abstract))'>
<xsl:attribute name='abstract'>false</xsl:attribute>
</xsl:if>
<xsl:apply-templates select='@*'/>
<xsl:apply-templates select='column'/>
<xsl:apply-templates select='foreign-key'/>
<xsl:apply-templates select='index'/>
<xsl:apply-templates select='unique'/>
<xsl:apply-templates select='id-method-parameter'/>
<xsl:apply-templates select='validator'/>
<xsl:apply-templates select='vendor'/>
</table>
</xsl:template>
<xsl:template match='foreign-key'>
<foreign-key>
<xsl:if test='not(boolean(@onDelete)) and not(boolean(@OnDelete))'>
<xsl:attribute name='onDelete'>none</xsl:attribute>
</xsl:if>
<xsl:if test='not(boolean(@onUpdate)) and not(boolean(@OnUpdate))'>
<xsl:attribute name='onUpdate'>none</xsl:attribute>
</xsl:if>
<xsl:apply-templates select='@*'/>
<xsl:apply-templates select='reference'/>
<xsl:apply-templates select='vendor'/>
</foreign-key>
</xsl:template>
<xsl:template match='index'>
<index>
<xsl:apply-templates select='@*'/>
<xsl:apply-templates select='index-column'/>
</index>
</xsl:template>
<xsl:template match='unique'>
<unique>
<xsl:apply-templates select='@*'/>
<xsl:apply-templates select='unique-column'/>
</unique>
</xsl:template>
<xsl:template match='unique-column'>
<unique-column>
<xsl:apply-templates select='@*'/>
<xsl:apply-templates select='vendor'/>
</unique-column>
</xsl:template>
<xsl:template match='index-column'>
<index-column>
<xsl:apply-templates select='@*'/>
<xsl:apply-templates select='vendor'/>
</index-column>
</xsl:template>
<xsl:template match='id-method-parameter'>
<id-method-parameter>
<xsl:if test='not(boolean(@name))'>
<xsl:attribute name='name'>default</xsl:attribute>
</xsl:if>
<xsl:apply-templates select='@*'/>
</id-method-parameter>
</xsl:template>
<xsl:template match='validator'>
<validator>
<xsl:apply-templates select='@*'/>
<xsl:apply-templates select='rule'/>
</validator>
</xsl:template>
<xsl:template match='rule'>
<rule>
<xsl:if test='not(boolean(@name))'>
<xsl:attribute name='name'>class</xsl:attribute>
</xsl:if>
<xsl:apply-templates select='@*'/>
</rule>
</xsl:template>
<xsl:template match='parameter'>
<parameter>
<xsl:apply-templates select='@*'/>
</parameter>
</xsl:template>
<xsl:template match='vendor'>
<vendor>
<xsl:apply-templates select='@*'/>
<xsl:apply-templates select='parameter'/>
</vendor>
</xsl:template>
<xsl:template match='inheritance'>
<inheritance>
<xsl:apply-templates select='@*'/>
</inheritance>
</xsl:template>
<xsl:template match='column'>
<column>
<xsl:if test='not(boolean(@primaryKey))'>
<xsl:attribute name='primaryKey'>false</xsl:attribute>
</xsl:if>
<xsl:if test='not(boolean(@required))'>
<xsl:attribute name='required'>false</xsl:attribute>
</xsl:if>
<xsl:if test='not(boolean(@type))'>
<xsl:attribute name='type'>VARCHAR</xsl:attribute>
</xsl:if>
<xsl:if test='not(boolean(@autoIncrement))'>
<xsl:attribute name='autoIncrement'>false</xsl:attribute>
</xsl:if>
<xsl:if test='not(boolean(@lazyLoad))'>
<xsl:attribute name='lazyLoad'>false</xsl:attribute>
</xsl:if>
<xsl:apply-templates select='@*'/>
<xsl:apply-templates select='inheritance'/>
<xsl:apply-templates select='vendor'/>
</column>
</xsl:template>
<xsl:template match='reference'>
<reference>
<xsl:apply-templates select='@*'/>
</reference>
</xsl:template>
</xsl:stylesheet>

View File

@ -0,0 +1,5 @@
This directory contains PHP templates which are used to build SQL files and object
model (OM) classes. The PHP templates are called from the
propel.phing.PropelDataModelTask class. The templates are managed by the Capsule
engine, which simply provides a mechanism for placing values in the template context
and buffering output, etc.

View File

@ -0,0 +1,30 @@
<?php
/**
* Control script which converts a properties file (in XML or INI-style .properties) into PHP array.
*
* This conversion exists for performance reasons only.
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 1.2 $
*/
// we expect to have:
// $propertiesFile - path to xml/ini file.
$pfile = new PhingFile($propertiesFile);
if (!$pfile->exists()) {
throw new BuildException("Property file does not exist: $propertiesFile");
}
$pfileName = explode('.', $pfile->getName());
$format = array_pop($pfileName);
switch($format) {
case 'xml':
include 'xml.tpl';
break;
default:
throw new BuildException("Propel now only supports the XML runtime conf format (expected to find a runtime file with .xml extension).");
}

View File

@ -0,0 +1,83 @@
<?php
/**
* Template that converts XML files into PHP arrays.
*
* See the provided projects/bookstore/runtime-conf.xml file for an example.
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 1.2 $
*/
// --------------------------------------------------------------------------------
// Added function_exists check for ticket:244, allowing multiple calls to convert-props
if (!function_exists('simplexml_to_array')) {
/**
* Converts simplexml object into array, turning attributes into child elements.
*
* From a helpful php.net comment.
* @author Christophe VG
*/
function &simplexml_to_array( $xml ) {
$ar = array();
foreach( $xml->children() as $k => $v ) {
// recurse the child
$child = simplexml_to_array( $v );
//print "Recursed down and found: " . var_export($child, true) . "\n";
// if it's not an array, then it was empty, thus a value/string
if( count($child) == 0 ) {
$child = (string)$v;
}
// add the childs attributes as if they where children
foreach( $v->attributes() as $ak => $av ) {
// if the child is not an array, transform it into one
if( !is_array( $child ) ) {
$child = array( "value" => $child );
}
if ($ak == 'id') {
// special exception: if there is a key named 'id'
// then we will name the current key after that id
$k = (string) $av;
} else {
// otherwise, just add the attribute like a child element
$child[$ak] = (string) $av;
}
}
// if the $k is already in our children list, we need to transform
// it into an array, else we add it as a value
if( !in_array( $k, array_keys($ar) ) ) {
$ar[$k] = $child;
} else {
// if the $ar[$k] element is not already an array, then we need to make it one
if ( !is_array( $ar[$k] ) ) { $ar[$k] = array( $ar[$k] ); }
$ar[$k][] = $child;
}
}
return $ar;
}
} // if (!function_exists...)
// we expect to have:
// $propertiesFile - path to properties file.
$xmlDom = new DOMDocument();
$xmlDom->load($propertiesFile);
$xml = simplexml_load_string($xmlDom->saveXML());
echo '<' . '?' . "php\n";
echo "// This file generated by Propel convert-props target on " . strftime("%c") . "\n";
echo "// from XML runtime conf file " . $pfile->getPath() . "\n";
echo "return ";
var_export(simplexml_to_array( $xml ));
echo ";";

View File

@ -0,0 +1,13 @@
<!ELEMENT dataset (
<?php
$vc = 0;
foreach($tables as $tbl) {
if($vc++) {
echo ",";
}
echo $tbl->getPhpName() ?>*<?php } ?>
)>
<!ATTLIST dataset
name CDATA #REQUIRED
>

View File

@ -0,0 +1,6 @@
<!ELEMENT <?php echo $table->getPhpName() ?> EMPTY>
<!ATTLIST <?php echo $table->getPhpName() ?>
<?php foreach ($table->getColumns() as $col) { ?>
<?php echo $col->getPhpName() ?> CDATA <?php if($col->isNotNull()) { ?>#REQUIRED<?php } else { ?>IMPLIED<?php } ?><?php } ?>
>

View File

@ -0,0 +1 @@
</dataset>

Some files were not shown because too many files have changed in this diff Show More