Merge branch 'master' into files_encryption
Encryption unit tests still failing, needs work Conflicts: 3rdparty/Archive/Tar.php 3rdparty/MDB2/Driver/Datatype/Common.php 3rdparty/MDB2/Driver/mysql.php 3rdparty/Sabre/CalDAV/CalendarQueryValidator.php 3rdparty/Sabre/CalDAV/Plugin.php 3rdparty/Sabre/CalDAV/Version.php 3rdparty/Sabre/CardDAV/AddressBook.php 3rdparty/Sabre/CardDAV/AddressBookQueryParser.php 3rdparty/Sabre/CardDAV/Plugin.php 3rdparty/Sabre/CardDAV/Version.php 3rdparty/Sabre/DAV/Client.php 3rdparty/Sabre/DAV/Locks/Plugin.php 3rdparty/Sabre/DAV/Server.php 3rdparty/Sabre/DAV/Tree/Filesystem.php 3rdparty/Sabre/DAV/Version.php 3rdparty/Sabre/HTTP/BasicAuth.php 3rdparty/Sabre/HTTP/Version.php 3rdparty/Sabre/VObject/Component/VEvent.php 3rdparty/Sabre/VObject/DateTimeParser.php 3rdparty/Sabre/VObject/RecurrenceIterator.php 3rdparty/Sabre/VObject/Version.php 3rdparty/class.phpmailer.php 3rdparty/class.smtp.php 3rdparty/css/chosen-sprite.png 3rdparty/css/chosen.css 3rdparty/css/chosen/chosen.css 3rdparty/fullcalendar/css/fullcalendar.css 3rdparty/fullcalendar/css/fullcalendar.print.css 3rdparty/fullcalendar/js/fullcalendar.js 3rdparty/fullcalendar/js/fullcalendar.min.js 3rdparty/fullcalendar/js/gcal.js 3rdparty/js/chosen/VERSION 3rdparty/js/chosen/chosen.jquery.js 3rdparty/js/chosen/chosen.jquery.min.js 3rdparty/openid/class.openid.v3.php 3rdparty/openid/phpmyid.php 3rdparty/php-cloudfiles/cloudfiles.php 3rdparty/smb4php/smb.php 3rdparty/timepicker/css/jquery.ui.timepicker.css 3rdparty/timepicker/js/i18n/i18n.html 3rdparty/timepicker/js/i18n/jquery.ui.timepicker-de.js 3rdparty/timepicker/js/i18n/jquery.ui.timepicker-ja.js 3rdparty/timepicker/js/jquery.ui.timepicker.js 3rdparty/timepicker/releases.txt README apps/files/admin.php apps/files/ajax/autocomplete.php apps/files/ajax/move.php apps/files/ajax/newfile.php apps/files/ajax/scan.php apps/files/ajax/timezone.php apps/files/ajax/upload.php apps/files/appinfo/filesync.php apps/files/appinfo/update.php apps/files/css/files.css apps/files/index.php apps/files/js/fileactions.js apps/files/js/filelist.js apps/files/js/files.js apps/files/l10n/ar.php apps/files/l10n/bg_BG.php apps/files/l10n/ca.php apps/files/l10n/cs_CZ.php apps/files/l10n/da.php apps/files/l10n/de.php apps/files/l10n/el.php apps/files/l10n/eo.php apps/files/l10n/es.php apps/files/l10n/es_AR.php apps/files/l10n/et_EE.php apps/files/l10n/eu.php apps/files/l10n/fa.php apps/files/l10n/fi_FI.php apps/files/l10n/fr.php apps/files/l10n/gl.php apps/files/l10n/he.php apps/files/l10n/hr.php apps/files/l10n/hu_HU.php apps/files/l10n/ia.php apps/files/l10n/id.php apps/files/l10n/it.php apps/files/l10n/ja_JP.php apps/files/l10n/ko.php apps/files/l10n/lb.php apps/files/l10n/lt_LT.php apps/files/l10n/lv.php apps/files/l10n/mk.php apps/files/l10n/ms_MY.php apps/files/l10n/nb_NO.php apps/files/l10n/nl.php apps/files/l10n/nn_NO.php apps/files/l10n/oc.php apps/files/l10n/pl.php apps/files/l10n/pt_BR.php apps/files/l10n/pt_PT.php apps/files/l10n/ro.php apps/files/l10n/ru.php apps/files/l10n/ru_RU.php apps/files/l10n/si_LK.php apps/files/l10n/sk_SK.php apps/files/l10n/sl.php apps/files/l10n/sr.php apps/files/l10n/sr@latin.php apps/files/l10n/sv.php apps/files/l10n/th_TH.php apps/files/l10n/tr.php apps/files/l10n/uk.php apps/files/l10n/vi.php apps/files/l10n/zh_CN.GB2312.php apps/files/l10n/zh_CN.php apps/files/l10n/zh_TW.php apps/files/templates/admin.php apps/files/templates/index.php apps/files/templates/part.breadcrumb.php apps/files/templates/part.list.php apps/files_encryption/appinfo/app.php apps/files_encryption/appinfo/info.xml apps/files_encryption/js/settings.js apps/files_encryption/l10n/fa.php apps/files_encryption/l10n/sl.php apps/files_encryption/lib/crypt.php apps/files_encryption/lib/cryptstream.php apps/files_encryption/lib/proxy.php apps/files_encryption/settings.php apps/files_encryption/templates/settings.php apps/files_encryption/tests/encryption.php apps/files_encryption/tests/proxy.php apps/files_encryption/tests/stream.php apps/files_external/l10n/cs_CZ.php apps/files_external/l10n/et_EE.php apps/files_external/l10n/lt_LT.php apps/files_external/l10n/nl.php apps/files_external/l10n/ru.php apps/files_external/l10n/sk_SK.php apps/files_external/l10n/sl.php apps/files_external/l10n/vi.php apps/files_external/lib/config.php apps/files_external/lib/ftp.php apps/files_external/lib/smb.php apps/files_external/lib/streamwrapper.php apps/files_external/lib/swift.php apps/files_external/lib/webdav.php apps/files_external/tests/ftp.php apps/files_sharing/appinfo/update.php apps/files_sharing/css/public.css apps/files_sharing/js/share.js apps/files_sharing/l10n/de.php apps/files_sharing/l10n/et_EE.php apps/files_sharing/l10n/ja_JP.php apps/files_sharing/l10n/nb_NO.php apps/files_sharing/l10n/ru.php apps/files_sharing/l10n/sl.php apps/files_sharing/l10n/vi.php apps/files_sharing/lib/share/file.php apps/files_sharing/lib/share/folder.php apps/files_sharing/lib/sharedstorage.php apps/files_sharing/public.php apps/files_sharing/templates/public.php apps/files_versions/l10n/et_EE.php apps/files_versions/l10n/lt_LT.php apps/files_versions/l10n/nb_NO.php apps/files_versions/l10n/nl.php apps/files_versions/l10n/ru.php apps/files_versions/l10n/sl.php apps/files_versions/l10n/vi.php apps/files_versions/lib/hooks.php apps/files_versions/lib/versions.php apps/user_ldap/appinfo/database.xml apps/user_ldap/appinfo/update.php apps/user_ldap/group_ldap.php apps/user_ldap/l10n/da.php apps/user_ldap/l10n/et_EE.php apps/user_ldap/l10n/pt_PT.php apps/user_ldap/l10n/sl.php apps/user_ldap/l10n/vi.php apps/user_ldap/l10n/zh_CN.php apps/user_ldap/lib/access.php apps/user_ldap/lib/connection.php apps/user_ldap/settings.php apps/user_ldap/templates/settings.php apps/user_ldap/tests/group_ldap.php apps/user_ldap/user_ldap.php apps/user_webdavauth/appinfo/app.php apps/user_webdavauth/appinfo/info.xml apps/user_webdavauth/settings.php apps/user_webdavauth/templates/settings.php apps/user_webdavauth/user_webdavauth.php autotest.sh core/ajax/appconfig.php core/ajax/share.php core/ajax/translations.php core/ajax/vcategories/add.php core/ajax/vcategories/delete.php core/ajax/vcategories/edit.php core/css/share.css core/js/eventsource.js core/js/js.js core/js/oc-vcategories.js core/js/share.js core/l10n/ar.php core/l10n/bg_BG.php core/l10n/ca.php core/l10n/cs_CZ.php core/l10n/da.php core/l10n/de.php core/l10n/el.php core/l10n/eo.php core/l10n/es.php core/l10n/es_AR.php core/l10n/et_EE.php core/l10n/eu.php core/l10n/fa.php core/l10n/fi_FI.php core/l10n/fr.php core/l10n/gl.php core/l10n/he.php core/l10n/hi.php core/l10n/hr.php core/l10n/hu_HU.php core/l10n/ia.php core/l10n/id.php core/l10n/it.php core/l10n/ja_JP.php core/l10n/ko.php core/l10n/ku_IQ.php core/l10n/lb.php core/l10n/lt_LT.php core/l10n/lv.php core/l10n/mk.php core/l10n/ms_MY.php core/l10n/nb_NO.php core/l10n/nl.php core/l10n/nn_NO.php core/l10n/oc.php core/l10n/pl.php core/l10n/pt_BR.php core/l10n/pt_PT.php core/l10n/ro.php core/l10n/ru.php core/l10n/ru_RU.php core/l10n/si_LK.php core/l10n/sk_SK.php core/l10n/sl.php core/l10n/sr.php core/l10n/sr@latin.php core/l10n/sv.php core/l10n/th_TH.php core/l10n/tr.php core/l10n/uk.php core/l10n/vi.php core/l10n/zh_CN.GB2312.php core/l10n/zh_CN.php core/l10n/zh_TW.php core/lostpassword/index.php core/lostpassword/resetpassword.php core/templates/layout.base.php core/templates/layout.guest.php core/templates/layout.user.php cron.php db_structure.xml files/webdav.php index.php l10n/.tx/config l10n/af/calendar.po l10n/af/contacts.po l10n/af/core.po l10n/af/files.po l10n/ar/calendar.po l10n/ar/contacts.po l10n/ar/core.po l10n/ar/files.po l10n/ar/files_encryption.po l10n/ar/lib.po l10n/ar/media.po l10n/ar/settings.po l10n/ar_SA/core.po l10n/ar_SA/files.po l10n/bg_BG/calendar.po l10n/bg_BG/contacts.po l10n/bg_BG/core.po l10n/bg_BG/files.po l10n/bg_BG/lib.po l10n/bg_BG/media.po l10n/bg_BG/settings.po l10n/ca/calendar.po l10n/ca/contacts.po l10n/ca/core.po l10n/ca/files.po l10n/ca/gallery.po l10n/ca/lib.po l10n/ca/settings.po l10n/cs_CZ/calendar.po l10n/cs_CZ/contacts.po l10n/cs_CZ/core.po l10n/cs_CZ/files.po l10n/cs_CZ/files_external.po l10n/cs_CZ/gallery.po l10n/cs_CZ/lib.po l10n/cs_CZ/settings.po l10n/da/calendar.po l10n/da/contacts.po l10n/da/core.po l10n/da/files.po l10n/da/lib.po l10n/da/settings.po l10n/da/user_ldap.po l10n/de/calendar.po l10n/de/contacts.po l10n/de/core.po l10n/de/files.po l10n/de/files_sharing.po l10n/de/gallery.po l10n/de/lib.po l10n/de/settings.po l10n/de_DE/core.po l10n/de_DE/files.po l10n/de_DE/settings.po l10n/el/calendar.po l10n/el/contacts.po l10n/el/core.po l10n/el/files.po l10n/el/gallery.po l10n/el/lib.po l10n/el/settings.po l10n/eo/calendar.po l10n/eo/contacts.po l10n/eo/core.po l10n/eo/files.po l10n/eo/lib.po l10n/eo/media.po l10n/eo/settings.po l10n/es/calendar.po l10n/es/contacts.po l10n/es/core.po l10n/es/files.po l10n/es/gallery.po l10n/es/lib.po l10n/es/settings.po l10n/es_AR/core.po l10n/es_AR/files.po l10n/es_AR/lib.po l10n/es_AR/settings.po l10n/et_EE/calendar.po l10n/et_EE/contacts.po l10n/et_EE/core.po l10n/et_EE/files.po l10n/et_EE/files_external.po l10n/et_EE/files_sharing.po l10n/et_EE/files_versions.po l10n/et_EE/lib.po l10n/et_EE/settings.po l10n/et_EE/user_ldap.po l10n/eu/calendar.po l10n/eu/contacts.po l10n/eu/core.po l10n/eu/files.po l10n/eu/lib.po l10n/eu/settings.po l10n/eu_ES/core.po l10n/eu_ES/files.po l10n/fa/calendar.po l10n/fa/contacts.po l10n/fa/core.po l10n/fa/files.po l10n/fa/files_encryption.po l10n/fa/lib.po l10n/fa/settings.po l10n/fi/core.po l10n/fi/files.po l10n/fi_FI/calendar.po l10n/fi_FI/contacts.po l10n/fi_FI/core.po l10n/fi_FI/files.po l10n/fi_FI/gallery.po l10n/fi_FI/lib.po l10n/fi_FI/settings.po l10n/fr/calendar.po l10n/fr/contacts.po l10n/fr/core.po l10n/fr/files.po l10n/fr/gallery.po l10n/fr/lib.po l10n/fr/media.po l10n/fr/settings.po l10n/gl/calendar.po l10n/gl/contacts.po l10n/gl/core.po l10n/gl/files.po l10n/gl/lib.po l10n/gl/settings.po l10n/he/calendar.po l10n/he/contacts.po l10n/he/core.po l10n/he/files.po l10n/he/lib.po l10n/he/settings.po l10n/hi/core.po l10n/hi/files.po l10n/hi/lib.po l10n/hi/settings.po l10n/hr/calendar.po l10n/hr/contacts.po l10n/hr/core.po l10n/hr/files.po l10n/hr/lib.po l10n/hr/settings.po l10n/hu_HU/calendar.po l10n/hu_HU/contacts.po l10n/hu_HU/core.po l10n/hu_HU/files.po l10n/hu_HU/lib.po l10n/hu_HU/settings.po l10n/hy/calendar.po l10n/hy/contacts.po l10n/hy/core.po l10n/hy/files.po l10n/ia/calendar.po l10n/ia/contacts.po l10n/ia/core.po l10n/ia/files.po l10n/ia/lib.po l10n/ia/settings.po l10n/id/calendar.po l10n/id/contacts.po l10n/id/core.po l10n/id/files.po l10n/id/files_encryption.po l10n/id/files_external.po l10n/id/files_sharing.po l10n/id/files_versions.po l10n/id/lib.po l10n/id/settings.po l10n/id/user_ldap.po l10n/id_ID/core.po l10n/id_ID/files.po l10n/it/calendar.po l10n/it/contacts.po l10n/it/core.po l10n/it/files.po l10n/it/gallery.po l10n/it/lib.po l10n/it/settings.po l10n/ja_JP/calendar.po l10n/ja_JP/contacts.po l10n/ja_JP/core.po l10n/ja_JP/files.po l10n/ja_JP/files_sharing.po l10n/ja_JP/lib.po l10n/ja_JP/settings.po l10n/ko/calendar.po l10n/ko/contacts.po l10n/ko/core.po l10n/ko/files.po l10n/ko/lib.po l10n/ko/settings.po l10n/ku_IQ/core.po l10n/ku_IQ/files.po l10n/ku_IQ/lib.po l10n/ku_IQ/settings.po l10n/lb/calendar.po l10n/lb/contacts.po l10n/lb/core.po l10n/lb/files.po l10n/lb/lib.po l10n/lb/settings.po l10n/lt_LT/calendar.po l10n/lt_LT/contacts.po l10n/lt_LT/core.po l10n/lt_LT/files.po l10n/lt_LT/files_external.po l10n/lt_LT/files_versions.po l10n/lt_LT/lib.po l10n/lt_LT/settings.po l10n/lv/core.po l10n/lv/files.po l10n/lv/lib.po l10n/lv/settings.po l10n/mk/calendar.po l10n/mk/contacts.po l10n/mk/core.po l10n/mk/files.po l10n/mk/lib.po l10n/mk/settings.po l10n/ms_MY/calendar.po l10n/ms_MY/contacts.po l10n/ms_MY/core.po l10n/ms_MY/files.po l10n/ms_MY/lib.po l10n/ms_MY/settings.po l10n/nb_NO/calendar.po l10n/nb_NO/contacts.po l10n/nb_NO/core.po l10n/nb_NO/files.po l10n/nb_NO/files_sharing.po l10n/nb_NO/files_versions.po l10n/nb_NO/gallery.po l10n/nb_NO/lib.po l10n/nb_NO/settings.po l10n/nb_NO/user_ldap.po l10n/nl/calendar.po l10n/nl/contacts.po l10n/nl/core.po l10n/nl/files.po l10n/nl/files_external.po l10n/nl/files_versions.po l10n/nl/gallery.po l10n/nl/lib.po l10n/nl/settings.po l10n/nl/user_ldap.po l10n/nn_NO/calendar.po l10n/nn_NO/contacts.po l10n/nn_NO/core.po l10n/nn_NO/files.po l10n/nn_NO/lib.po l10n/nn_NO/settings.po l10n/oc/core.po l10n/oc/files.po l10n/oc/lib.po l10n/oc/settings.po l10n/pl/calendar.po l10n/pl/contacts.po l10n/pl/core.po l10n/pl/files.po l10n/pl/gallery.po l10n/pl/lib.po l10n/pl/settings.po l10n/pl_PL/core.po l10n/pl_PL/files.po l10n/pl_PL/lib.po l10n/pl_PL/settings.po l10n/pt_BR/calendar.po l10n/pt_BR/contacts.po l10n/pt_BR/core.po l10n/pt_BR/files.po l10n/pt_BR/lib.po l10n/pt_BR/settings.po l10n/pt_PT/calendar.po l10n/pt_PT/contacts.po l10n/pt_PT/core.po l10n/pt_PT/files.po l10n/pt_PT/gallery.po l10n/pt_PT/lib.po l10n/pt_PT/settings.po l10n/pt_PT/user_ldap.po l10n/ro/calendar.po l10n/ro/contacts.po l10n/ro/core.po l10n/ro/files.po l10n/ro/lib.po l10n/ro/settings.po l10n/ru/calendar.po l10n/ru/contacts.po l10n/ru/core.po l10n/ru/files.po l10n/ru/files_external.po l10n/ru/files_sharing.po l10n/ru/files_versions.po l10n/ru/gallery.po l10n/ru/lib.po l10n/ru/settings.po l10n/ru_RU/core.po l10n/ru_RU/files.po l10n/ru_RU/lib.po l10n/ru_RU/settings.po l10n/si_LK/core.po l10n/si_LK/files.po l10n/si_LK/files_encryption.po l10n/si_LK/files_external.po l10n/si_LK/files_sharing.po l10n/si_LK/files_versions.po l10n/si_LK/lib.po l10n/si_LK/settings.po l10n/si_LK/user_ldap.po l10n/sk_SK/calendar.po l10n/sk_SK/contacts.po l10n/sk_SK/core.po l10n/sk_SK/files.po l10n/sk_SK/files_external.po l10n/sk_SK/lib.po l10n/sk_SK/settings.po l10n/sk_SK/user_ldap.po l10n/sl/calendar.po l10n/sl/contacts.po l10n/sl/core.po l10n/sl/files.po l10n/sl/files_encryption.po l10n/sl/files_external.po l10n/sl/files_sharing.po l10n/sl/files_versions.po l10n/sl/gallery.po l10n/sl/lib.po l10n/sl/settings.po l10n/sl/user_ldap.po l10n/so/core.po l10n/so/files.po l10n/sr/calendar.po l10n/sr/contacts.po l10n/sr/core.po l10n/sr/files.po l10n/sr/lib.po l10n/sr/settings.po l10n/sr@latin/calendar.po l10n/sr@latin/contacts.po l10n/sr@latin/core.po l10n/sr@latin/files.po l10n/sr@latin/lib.po l10n/sr@latin/settings.po l10n/sv/calendar.po l10n/sv/contacts.po l10n/sv/core.po l10n/sv/files.po l10n/sv/gallery.po l10n/sv/lib.po l10n/sv/media.po l10n/sv/settings.po l10n/ta_LK/core.po l10n/ta_LK/files.po l10n/ta_LK/lib.po l10n/ta_LK/settings.po l10n/templates/core.pot l10n/templates/files.pot l10n/templates/files_encryption.pot l10n/templates/files_external.pot l10n/templates/files_sharing.pot l10n/templates/files_versions.pot l10n/templates/lib.pot l10n/templates/settings.pot l10n/templates/user_ldap.pot l10n/th_TH/calendar.po l10n/th_TH/contacts.po l10n/th_TH/core.po l10n/th_TH/files.po l10n/th_TH/gallery.po l10n/th_TH/lib.po l10n/th_TH/settings.po l10n/tr/calendar.po l10n/tr/contacts.po l10n/tr/core.po l10n/tr/files.po l10n/tr/gallery.po l10n/tr/lib.po l10n/tr/settings.po l10n/uk/calendar.po l10n/uk/contacts.po l10n/uk/core.po l10n/uk/files.po l10n/uk/files_encryption.po l10n/uk/files_versions.po l10n/uk/lib.po l10n/uk/media.po l10n/uk/settings.po l10n/vi/core.po l10n/vi/files.po l10n/vi/files_external.po l10n/vi/files_sharing.po l10n/vi/files_versions.po l10n/vi/lib.po l10n/vi/settings.po l10n/vi/user_ldap.po l10n/zh_CN.GB2312/core.po l10n/zh_CN.GB2312/files.po l10n/zh_CN.GB2312/lib.po l10n/zh_CN.GB2312/settings.po l10n/zh_CN/calendar.po l10n/zh_CN/contacts.po l10n/zh_CN/core.po l10n/zh_CN/files.po l10n/zh_CN/files_external.po l10n/zh_CN/gallery.po l10n/zh_CN/lib.po l10n/zh_CN/settings.po l10n/zh_CN/user_ldap.po l10n/zh_TW/calendar.po l10n/zh_TW/contacts.po l10n/zh_TW/core.po l10n/zh_TW/files.po l10n/zh_TW/lib.po l10n/zh_TW/settings.po lib/MDB2/Driver/sqlite3.php lib/app.php lib/appconfig.php lib/archive.php lib/archive/tar.php lib/archive/zip.php lib/base.php lib/connector/sabre/auth.php lib/connector/sabre/directory.php lib/connector/sabre/file.php lib/connector/sabre/locks.php lib/connector/sabre/node.php lib/db.php lib/eventsource.php lib/filecache.php lib/filecache/cached.php lib/filecache/update.php lib/filechunking.php lib/fileproxy.php lib/fileproxy/fileoperations.php lib/fileproxy/quota.php lib/files.php lib/filestorage.php lib/filestorage/common.php lib/filestorage/commontest.php lib/filestorage/local.php lib/filesystem.php lib/filesystemview.php lib/group.php lib/group/dummy.php lib/group/example.php lib/helper.php lib/image.php lib/installer.php lib/json.php lib/l10n.php lib/l10n/ca.php lib/l10n/cs_CZ.php lib/l10n/da.php lib/l10n/de.php lib/l10n/el.php lib/l10n/eo.php lib/l10n/es.php lib/l10n/es_AR.php lib/l10n/et_EE.php lib/l10n/eu.php lib/l10n/fa.php lib/l10n/fi_FI.php lib/l10n/fr.php lib/l10n/gl.php lib/l10n/he.php lib/l10n/hu_HU.php lib/l10n/it.php lib/l10n/ja_JP.php lib/l10n/lt_LT.php lib/l10n/nb_NO.php lib/l10n/nl.php lib/l10n/oc.php lib/l10n/pl.php lib/l10n/pt_BR.php lib/l10n/pt_PT.php lib/l10n/ro.php lib/l10n/ru.php lib/l10n/ru_RU.php lib/l10n/sk_SK.php lib/l10n/sl.php lib/l10n/sv.php lib/l10n/th_TH.php lib/l10n/uk.php lib/l10n/vi.php lib/l10n/zh_CN.GB2312.php lib/l10n/zh_CN.php lib/l10n/zh_TW.php lib/log.php lib/log/owncloud.php lib/mail.php lib/migrate.php lib/migration/content.php lib/minimizer.php lib/ocs.php lib/ocsclient.php lib/preferences.php lib/public/backgroundjob.php lib/public/db.php lib/public/share.php lib/public/util.php lib/request.php lib/search.php lib/search/provider/file.php lib/search/result.php lib/setup.php lib/streamwrappers.php lib/template.php lib/templatelayout.php lib/updater.php lib/user.php lib/user/database.php lib/user/http.php lib/util.php lib/vcategories.php lib/vobject.php public.php remote.php search/ajax/search.php settings/admin.php settings/ajax/apps/ocs.php settings/ajax/changepassword.php settings/ajax/creategroup.php settings/ajax/createuser.php settings/ajax/disableapp.php settings/ajax/enableapp.php settings/ajax/getlog.php settings/ajax/lostpassword.php settings/ajax/openid.php settings/ajax/removegroup.php settings/ajax/removeuser.php settings/ajax/setlanguage.php settings/ajax/setloglevel.php settings/ajax/setquota.php settings/ajax/togglegroups.php settings/ajax/togglesubadmins.php settings/ajax/userlist.php settings/apps.php settings/css/settings.css settings/help.php settings/js/apps.js settings/js/users.js settings/l10n/ar.php settings/l10n/bg_BG.php settings/l10n/ca.php settings/l10n/cs_CZ.php settings/l10n/da.php settings/l10n/de.php settings/l10n/el.php settings/l10n/eo.php settings/l10n/es.php settings/l10n/es_AR.php settings/l10n/et_EE.php settings/l10n/eu.php settings/l10n/fa.php settings/l10n/fi_FI.php settings/l10n/fr.php settings/l10n/gl.php settings/l10n/hr.php settings/l10n/hu_HU.php settings/l10n/id.php settings/l10n/it.php settings/l10n/ja_JP.php settings/l10n/ko.php settings/l10n/lb.php settings/l10n/lt_LT.php settings/l10n/lv.php settings/l10n/ms_MY.php settings/l10n/nb_NO.php settings/l10n/nl.php settings/l10n/nn_NO.php settings/l10n/oc.php settings/l10n/pl.php settings/l10n/pt_BR.php settings/l10n/pt_PT.php settings/l10n/ro.php settings/l10n/ru.php settings/l10n/ru_RU.php settings/l10n/si_LK.php settings/l10n/sk_SK.php settings/l10n/sl.php settings/l10n/sr.php settings/l10n/sr@latin.php settings/l10n/sv.php settings/l10n/th_TH.php settings/l10n/tr.php settings/l10n/uk.php settings/l10n/vi.php settings/l10n/zh_CN.GB2312.php settings/l10n/zh_CN.php settings/l10n/zh_TW.php settings/personal.php settings/settings.php settings/templates/admin.php settings/templates/apps.php settings/templates/help.php settings/templates/personal.php settings/templates/users.php settings/trans.png settings/users.php tests/bootstrap.php tests/data/db_structure.xml tests/lib/archive.php tests/lib/cache.php tests/lib/cache/apc.php tests/lib/cache/xcache.php tests/lib/db.php tests/lib/filesystem.php tests/lib/geo.php tests/lib/share/share.php tests/lib/streamwrappers.php tests/lib/util.php tests/phpunit.xml
This commit is contained in:
commit
063f225a26
|
@ -4,6 +4,7 @@ owncloud
|
||||||
config/config.php
|
config/config.php
|
||||||
config/mount.php
|
config/mount.php
|
||||||
apps/inc.php
|
apps/inc.php
|
||||||
|
3rdparty
|
||||||
|
|
||||||
# just sane ignores
|
# just sane ignores
|
||||||
.*.sw[po]
|
.*.sw[po]
|
||||||
|
|
13
.htaccess
13
.htaccess
|
@ -1,3 +1,11 @@
|
||||||
|
<IfModule mod_fcgid.c>
|
||||||
|
<IfModule mod_setenvif.c>
|
||||||
|
<IfModule mod_headers.c>
|
||||||
|
SetEnvIfNoCase ^Authorization$ "(.+)" XAUTHORIZATION=$1
|
||||||
|
RequestHeader set XAuthorization %{XAUTHORIZATION}e env=XAUTHORIZATION
|
||||||
|
</IfModule>
|
||||||
|
</IfModule>
|
||||||
|
</IfModule>
|
||||||
ErrorDocument 403 /core/templates/403.php
|
ErrorDocument 403 /core/templates/403.php
|
||||||
ErrorDocument 404 /core/templates/404.php
|
ErrorDocument 404 /core/templates/404.php
|
||||||
<IfModule mod_php5.c>
|
<IfModule mod_php5.c>
|
||||||
|
@ -12,6 +20,7 @@ php_value memory_limit 512M
|
||||||
RewriteEngine on
|
RewriteEngine on
|
||||||
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||||
RewriteRule ^.well-known/host-meta /public.php?service=host-meta [QSA,L]
|
RewriteRule ^.well-known/host-meta /public.php?service=host-meta [QSA,L]
|
||||||
|
RewriteRule ^.well-known/host-meta.json /public.php?service=host-meta-json [QSA,L]
|
||||||
RewriteRule ^.well-known/carddav /remote.php/carddav/ [R]
|
RewriteRule ^.well-known/carddav /remote.php/carddav/ [R]
|
||||||
RewriteRule ^.well-known/caldav /remote.php/caldav/ [R]
|
RewriteRule ^.well-known/caldav /remote.php/caldav/ [R]
|
||||||
RewriteRule ^apps/calendar/caldav.php remote.php/caldav/ [QSA,L]
|
RewriteRule ^apps/calendar/caldav.php remote.php/caldav/ [QSA,L]
|
||||||
|
@ -19,4 +28,8 @@ RewriteRule ^apps/contacts/carddav.php remote.php/carddav/ [QSA,L]
|
||||||
RewriteRule ^apps/([^/]*)/(.*\.(css|php))$ index.php?app=$1&getfile=$2 [QSA,L]
|
RewriteRule ^apps/([^/]*)/(.*\.(css|php))$ index.php?app=$1&getfile=$2 [QSA,L]
|
||||||
RewriteRule ^remote/(.*) remote.php [QSA,L]
|
RewriteRule ^remote/(.*) remote.php [QSA,L]
|
||||||
</IfModule>
|
</IfModule>
|
||||||
|
<IfModule mod_mime.c>
|
||||||
|
AddType image/svg+xml svg svgz
|
||||||
|
AddEncoding gzip svgz
|
||||||
|
</IfModule>
|
||||||
Options -Indexes
|
Options -Indexes
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,251 +0,0 @@
|
||||||
<?php
|
|
||||||
/* vim: set expandtab tabstop=4 shiftwidth=4: */
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP Version 4 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1997-2003 The PHP Group |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | This source file is subject to version 3.0 of the PHP license, |
|
|
||||||
// | that is bundled with this package in the file LICENSE, and is |
|
|
||||||
// | available through the world-wide-web at the following url: |
|
|
||||||
// | http://www.php.net/license/3_0.txt. |
|
|
||||||
// | If you did not receive a copy of the PHP license and are unable to |
|
|
||||||
// | obtain it through the world-wide-web, please send a note to |
|
|
||||||
// | license@php.net so we can mail you a copy immediately. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Andrei Zmievski <andrei@php.net> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id: Getopt.php,v 1.21.4.7 2003/12/05 21:57:01 andrei Exp $
|
|
||||||
|
|
||||||
require_once( 'PEAR.php');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Command-line options parsing class.
|
|
||||||
*
|
|
||||||
* @author Andrei Zmievski <andrei@php.net>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class Console_Getopt {
|
|
||||||
/**
|
|
||||||
* Parses the command-line options.
|
|
||||||
*
|
|
||||||
* The first parameter to this function should be the list of command-line
|
|
||||||
* arguments without the leading reference to the running program.
|
|
||||||
*
|
|
||||||
* The second parameter is a string of allowed short options. Each of the
|
|
||||||
* option letters can be followed by a colon ':' to specify that the option
|
|
||||||
* requires an argument, or a double colon '::' to specify that the option
|
|
||||||
* takes an optional argument.
|
|
||||||
*
|
|
||||||
* The third argument is an optional array of allowed long options. The
|
|
||||||
* leading '--' should not be included in the option name. Options that
|
|
||||||
* require an argument should be followed by '=', and options that take an
|
|
||||||
* option argument should be followed by '=='.
|
|
||||||
*
|
|
||||||
* The return value is an array of two elements: the list of parsed
|
|
||||||
* options and the list of non-option command-line arguments. Each entry in
|
|
||||||
* the list of parsed options is a pair of elements - the first one
|
|
||||||
* specifies the option, and the second one specifies the option argument,
|
|
||||||
* if there was one.
|
|
||||||
*
|
|
||||||
* Long and short options can be mixed.
|
|
||||||
*
|
|
||||||
* Most of the semantics of this function are based on GNU getopt_long().
|
|
||||||
*
|
|
||||||
* @param array $args an array of command-line arguments
|
|
||||||
* @param string $short_options specifies the list of allowed short options
|
|
||||||
* @param array $long_options specifies the list of allowed long options
|
|
||||||
*
|
|
||||||
* @return array two-element array containing the list of parsed options and
|
|
||||||
* the non-option arguments
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function getopt2($args, $short_options, $long_options = null)
|
|
||||||
{
|
|
||||||
return Console_Getopt::doGetopt(2, $args, $short_options, $long_options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function expects $args to start with the script name (POSIX-style).
|
|
||||||
* Preserved for backwards compatibility.
|
|
||||||
* @see getopt2()
|
|
||||||
*/
|
|
||||||
function getopt($args, $short_options, $long_options = null)
|
|
||||||
{
|
|
||||||
return Console_Getopt::doGetopt(1, $args, $short_options, $long_options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The actual implementation of the argument parsing code.
|
|
||||||
*/
|
|
||||||
function doGetopt($version, $args, $short_options, $long_options = null)
|
|
||||||
{
|
|
||||||
// in case you pass directly readPHPArgv() as the first arg
|
|
||||||
if (PEAR::isError($args)) {
|
|
||||||
return $args;
|
|
||||||
}
|
|
||||||
if (empty($args)) {
|
|
||||||
return array(array(), array());
|
|
||||||
}
|
|
||||||
$opts = array();
|
|
||||||
$non_opts = array();
|
|
||||||
|
|
||||||
settype($args, 'array');
|
|
||||||
|
|
||||||
if ($long_options) {
|
|
||||||
sort($long_options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Preserve backwards compatibility with callers that relied on
|
|
||||||
* erroneous POSIX fix.
|
|
||||||
*/
|
|
||||||
if ($version < 2) {
|
|
||||||
if (isset($args[0]{0}) && $args[0]{0} != '-') {
|
|
||||||
array_shift($args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reset($args);
|
|
||||||
while (list($i, $arg) = each($args)) {
|
|
||||||
|
|
||||||
/* The special element '--' means explicit end of
|
|
||||||
options. Treat the rest of the arguments as non-options
|
|
||||||
and end the loop. */
|
|
||||||
if ($arg == '--') {
|
|
||||||
$non_opts = array_merge($non_opts, array_slice($args, $i + 1));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($arg{0} != '-' || (strlen($arg) > 1 && $arg{1} == '-' && !$long_options)) {
|
|
||||||
$non_opts = array_merge($non_opts, array_slice($args, $i));
|
|
||||||
break;
|
|
||||||
} elseif (strlen($arg) > 1 && $arg{1} == '-') {
|
|
||||||
$error = Console_Getopt::_parseLongOption(substr($arg, 2), $long_options, $opts, $args);
|
|
||||||
if (PEAR::isError($error))
|
|
||||||
return $error;
|
|
||||||
} else {
|
|
||||||
$error = Console_Getopt::_parseShortOption(substr($arg, 1), $short_options, $opts, $args);
|
|
||||||
if (PEAR::isError($error))
|
|
||||||
return $error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return array($opts, $non_opts);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @access private
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function _parseShortOption($arg, $short_options, &$opts, &$args)
|
|
||||||
{
|
|
||||||
for ($i = 0; $i < strlen($arg); $i++) {
|
|
||||||
$opt = $arg{$i};
|
|
||||||
$opt_arg = null;
|
|
||||||
|
|
||||||
/* Try to find the short option in the specifier string. */
|
|
||||||
if (($spec = strstr($short_options, $opt)) === false || $arg{$i} == ':')
|
|
||||||
{
|
|
||||||
return PEAR::raiseError("Console_Getopt: unrecognized option -- $opt");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strlen($spec) > 1 && $spec{1} == ':') {
|
|
||||||
if (strlen($spec) > 2 && $spec{2} == ':') {
|
|
||||||
if ($i + 1 < strlen($arg)) {
|
|
||||||
/* Option takes an optional argument. Use the remainder of
|
|
||||||
the arg string if there is anything left. */
|
|
||||||
$opts[] = array($opt, substr($arg, $i + 1));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Option requires an argument. Use the remainder of the arg
|
|
||||||
string if there is anything left. */
|
|
||||||
if ($i + 1 < strlen($arg)) {
|
|
||||||
$opts[] = array($opt, substr($arg, $i + 1));
|
|
||||||
break;
|
|
||||||
} else if (list(, $opt_arg) = each($args))
|
|
||||||
/* Else use the next argument. */;
|
|
||||||
else
|
|
||||||
return PEAR::raiseError("Console_Getopt: option requires an argument -- $opt");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$opts[] = array($opt, $opt_arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @access private
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function _parseLongOption($arg, $long_options, &$opts, &$args)
|
|
||||||
{
|
|
||||||
@list($opt, $opt_arg) = explode('=', $arg);
|
|
||||||
$opt_len = strlen($opt);
|
|
||||||
|
|
||||||
for ($i = 0; $i < count($long_options); $i++) {
|
|
||||||
$long_opt = $long_options[$i];
|
|
||||||
$opt_start = substr($long_opt, 0, $opt_len);
|
|
||||||
|
|
||||||
/* Option doesn't match. Go on to the next one. */
|
|
||||||
if ($opt_start != $opt)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
$opt_rest = substr($long_opt, $opt_len);
|
|
||||||
|
|
||||||
/* Check that the options uniquely matches one of the allowed
|
|
||||||
options. */
|
|
||||||
if ($opt_rest != '' && $opt{0} != '=' &&
|
|
||||||
$i + 1 < count($long_options) &&
|
|
||||||
$opt == substr($long_options[$i+1], 0, $opt_len)) {
|
|
||||||
return PEAR::raiseError("Console_Getopt: option --$opt is ambiguous");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (substr($long_opt, -1) == '=') {
|
|
||||||
if (substr($long_opt, -2) != '==') {
|
|
||||||
/* Long option requires an argument.
|
|
||||||
Take the next argument if one wasn't specified. */;
|
|
||||||
if (!strlen($opt_arg) && !(list(, $opt_arg) = each($args))) {
|
|
||||||
return PEAR::raiseError("Console_Getopt: option --$opt requires an argument");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ($opt_arg) {
|
|
||||||
return PEAR::raiseError("Console_Getopt: option --$opt doesn't allow an argument");
|
|
||||||
}
|
|
||||||
|
|
||||||
$opts[] = array('--' . $opt, $opt_arg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return PEAR::raiseError("Console_Getopt: unrecognized option --$opt");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Safely read the $argv PHP array across different PHP configurations.
|
|
||||||
* Will take care on register_globals and register_argc_argv ini directives
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @return mixed the $argv PHP array or PEAR error if not registered
|
|
||||||
*/
|
|
||||||
function readPHPArgv()
|
|
||||||
{
|
|
||||||
global $argv;
|
|
||||||
if (!is_array($argv)) {
|
|
||||||
if (!@is_array($_SERVER['argv'])) {
|
|
||||||
if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) {
|
|
||||||
return PEAR::raiseError("Console_Getopt: Could not read cmd args (register_argc_argv=Off?)");
|
|
||||||
}
|
|
||||||
return $GLOBALS['HTTP_SERVER_VARS']['argv'];
|
|
||||||
}
|
|
||||||
return $_SERVER['argv'];
|
|
||||||
}
|
|
||||||
return $argv;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
|
@ -1,317 +0,0 @@
|
||||||
<?php
|
|
||||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Crypt_Blowfish allows for encryption and decryption on the fly using
|
|
||||||
* the Blowfish algorithm. Crypt_Blowfish does not require the mcrypt
|
|
||||||
* PHP extension, it uses only PHP.
|
|
||||||
* Crypt_Blowfish support encryption/decryption with or without a secret key.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* PHP versions 4 and 5
|
|
||||||
*
|
|
||||||
* LICENSE: This source file is subject to version 3.0 of the PHP license
|
|
||||||
* that is available through the world-wide-web at the following URI:
|
|
||||||
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
|
||||||
* the PHP License and are unable to obtain it through the web, please
|
|
||||||
* send a note to license@php.net so we can mail you a copy immediately.
|
|
||||||
*
|
|
||||||
* @category Encryption
|
|
||||||
* @package Crypt_Blowfish
|
|
||||||
* @author Matthew Fonda <mfonda@php.net>
|
|
||||||
* @copyright 2005 Matthew Fonda
|
|
||||||
* @license http://www.php.net/license/3_0.txt PHP License 3.0
|
|
||||||
* @version CVS: $Id: Blowfish.php,v 1.81 2005/05/30 18:40:36 mfonda Exp $
|
|
||||||
* @link http://pear.php.net/package/Crypt_Blowfish
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
require_once 'PEAR.php';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Example usage:
|
|
||||||
* $bf = new Crypt_Blowfish('some secret key!');
|
|
||||||
* $encrypted = $bf->encrypt('this is some example plain text');
|
|
||||||
* $plaintext = $bf->decrypt($encrypted);
|
|
||||||
* echo "plain text: $plaintext";
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @category Encryption
|
|
||||||
* @package Crypt_Blowfish
|
|
||||||
* @author Matthew Fonda <mfonda@php.net>
|
|
||||||
* @copyright 2005 Matthew Fonda
|
|
||||||
* @license http://www.php.net/license/3_0.txt PHP License 3.0
|
|
||||||
* @link http://pear.php.net/package/Crypt_Blowfish
|
|
||||||
* @version @package_version@
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
class Crypt_Blowfish
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* P-Array contains 18 32-bit subkeys
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
var $_P = array();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Array of four S-Blocks each containing 256 32-bit entries
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
var $_S = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mcrypt td resource
|
|
||||||
*
|
|
||||||
* @var resource
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
var $_td = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialization vector
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
var $_iv = null;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Crypt_Blowfish Constructor
|
|
||||||
* Initializes the Crypt_Blowfish object, and gives a sets
|
|
||||||
* the secret key
|
|
||||||
*
|
|
||||||
* @param string $key
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function Crypt_Blowfish($key)
|
|
||||||
{
|
|
||||||
if (extension_loaded('mcrypt')) {
|
|
||||||
$this->_td = mcrypt_module_open(MCRYPT_BLOWFISH, '', 'ecb', '');
|
|
||||||
$this->_iv = mcrypt_create_iv(8, MCRYPT_RAND);
|
|
||||||
}
|
|
||||||
$this->setKey($key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated isReady method
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
* @access public
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
function isReady()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated init method - init is now a private
|
|
||||||
* method and has been replaced with _init
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
* @access public
|
|
||||||
* @deprecated
|
|
||||||
* @see Crypt_Blowfish::_init()
|
|
||||||
*/
|
|
||||||
function init()
|
|
||||||
{
|
|
||||||
$this->_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the Crypt_Blowfish object
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
function _init()
|
|
||||||
{
|
|
||||||
$defaults = new Crypt_Blowfish_DefaultKey();
|
|
||||||
$this->_P = $defaults->P;
|
|
||||||
$this->_S = $defaults->S;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enciphers a single 64 bit block
|
|
||||||
*
|
|
||||||
* @param int &$Xl
|
|
||||||
* @param int &$Xr
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
function _encipher(&$Xl, &$Xr)
|
|
||||||
{
|
|
||||||
for ($i = 0; $i < 16; $i++) {
|
|
||||||
$temp = $Xl ^ $this->_P[$i];
|
|
||||||
$Xl = ((($this->_S[0][($temp>>24) & 255] +
|
|
||||||
$this->_S[1][($temp>>16) & 255]) ^
|
|
||||||
$this->_S[2][($temp>>8) & 255]) +
|
|
||||||
$this->_S[3][$temp & 255]) ^ $Xr;
|
|
||||||
$Xr = $temp;
|
|
||||||
}
|
|
||||||
$Xr = $Xl ^ $this->_P[16];
|
|
||||||
$Xl = $temp ^ $this->_P[17];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deciphers a single 64 bit block
|
|
||||||
*
|
|
||||||
* @param int &$Xl
|
|
||||||
* @param int &$Xr
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
function _decipher(&$Xl, &$Xr)
|
|
||||||
{
|
|
||||||
for ($i = 17; $i > 1; $i--) {
|
|
||||||
$temp = $Xl ^ $this->_P[$i];
|
|
||||||
$Xl = ((($this->_S[0][($temp>>24) & 255] +
|
|
||||||
$this->_S[1][($temp>>16) & 255]) ^
|
|
||||||
$this->_S[2][($temp>>8) & 255]) +
|
|
||||||
$this->_S[3][$temp & 255]) ^ $Xr;
|
|
||||||
$Xr = $temp;
|
|
||||||
}
|
|
||||||
$Xr = $Xl ^ $this->_P[1];
|
|
||||||
$Xl = $temp ^ $this->_P[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encrypts a string
|
|
||||||
*
|
|
||||||
* @param string $plainText
|
|
||||||
* @return string Returns cipher text on success, PEAR_Error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function encrypt($plainText)
|
|
||||||
{
|
|
||||||
if (!is_string($plainText)) {
|
|
||||||
PEAR::raiseError('Plain text must be a string', 0, PEAR_ERROR_DIE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extension_loaded('mcrypt')) {
|
|
||||||
return mcrypt_generic($this->_td, $plainText);
|
|
||||||
}
|
|
||||||
|
|
||||||
$cipherText = '';
|
|
||||||
$len = strlen($plainText);
|
|
||||||
$plainText .= str_repeat(chr(0),(8 - ($len%8))%8);
|
|
||||||
for ($i = 0; $i < $len; $i += 8) {
|
|
||||||
list(,$Xl,$Xr) = unpack("N2",substr($plainText,$i,8));
|
|
||||||
$this->_encipher($Xl, $Xr);
|
|
||||||
$cipherText .= pack("N2", $Xl, $Xr);
|
|
||||||
}
|
|
||||||
return $cipherText;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decrypts an encrypted string
|
|
||||||
*
|
|
||||||
* @param string $cipherText
|
|
||||||
* @return string Returns plain text on success, PEAR_Error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function decrypt($cipherText)
|
|
||||||
{
|
|
||||||
if (!is_string($cipherText)) {
|
|
||||||
PEAR::raiseError('Cipher text must be a string', 1, PEAR_ERROR_DIE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extension_loaded('mcrypt')) {
|
|
||||||
return mdecrypt_generic($this->_td, $cipherText);
|
|
||||||
}
|
|
||||||
|
|
||||||
$plainText = '';
|
|
||||||
$len = strlen($cipherText);
|
|
||||||
$cipherText .= str_repeat(chr(0),(8 - ($len%8))%8);
|
|
||||||
for ($i = 0; $i < $len; $i += 8) {
|
|
||||||
list(,$Xl,$Xr) = unpack("N2",substr($cipherText,$i,8));
|
|
||||||
$this->_decipher($Xl, $Xr);
|
|
||||||
$plainText .= pack("N2", $Xl, $Xr);
|
|
||||||
}
|
|
||||||
return $plainText;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the secret key
|
|
||||||
* The key must be non-zero, and less than or equal to
|
|
||||||
* 56 characters in length.
|
|
||||||
*
|
|
||||||
* @param string $key
|
|
||||||
* @return bool Returns true on success, PEAR_Error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function setKey($key)
|
|
||||||
{
|
|
||||||
if (!is_string($key)) {
|
|
||||||
PEAR::raiseError('Key must be a string', 2, PEAR_ERROR_DIE);
|
|
||||||
}
|
|
||||||
|
|
||||||
$len = strlen($key);
|
|
||||||
|
|
||||||
if ($len > 56 || $len == 0) {
|
|
||||||
PEAR::raiseError('Key must be less than 56 characters and non-zero. Supplied key length: ' . $len, 3, PEAR_ERROR_DIE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extension_loaded('mcrypt')) {
|
|
||||||
mcrypt_generic_init($this->_td, $key, $this->_iv);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once 'Blowfish/DefaultKey.php';
|
|
||||||
$this->_init();
|
|
||||||
|
|
||||||
$k = 0;
|
|
||||||
$data = 0;
|
|
||||||
$datal = 0;
|
|
||||||
$datar = 0;
|
|
||||||
|
|
||||||
for ($i = 0; $i < 18; $i++) {
|
|
||||||
$data = 0;
|
|
||||||
for ($j = 4; $j > 0; $j--) {
|
|
||||||
$data = $data << 8 | ord($key{$k});
|
|
||||||
$k = ($k+1) % $len;
|
|
||||||
}
|
|
||||||
$this->_P[$i] ^= $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
for ($i = 0; $i <= 16; $i += 2) {
|
|
||||||
$this->_encipher($datal, $datar);
|
|
||||||
$this->_P[$i] = $datal;
|
|
||||||
$this->_P[$i+1] = $datar;
|
|
||||||
}
|
|
||||||
for ($i = 0; $i < 256; $i += 2) {
|
|
||||||
$this->_encipher($datal, $datar);
|
|
||||||
$this->_S[0][$i] = $datal;
|
|
||||||
$this->_S[0][$i+1] = $datar;
|
|
||||||
}
|
|
||||||
for ($i = 0; $i < 256; $i += 2) {
|
|
||||||
$this->_encipher($datal, $datar);
|
|
||||||
$this->_S[1][$i] = $datal;
|
|
||||||
$this->_S[1][$i+1] = $datar;
|
|
||||||
}
|
|
||||||
for ($i = 0; $i < 256; $i += 2) {
|
|
||||||
$this->_encipher($datal, $datar);
|
|
||||||
$this->_S[2][$i] = $datal;
|
|
||||||
$this->_S[2][$i+1] = $datar;
|
|
||||||
}
|
|
||||||
for ($i = 0; $i < 256; $i += 2) {
|
|
||||||
$this->_encipher($datal, $datar);
|
|
||||||
$this->_S[3][$i] = $datal;
|
|
||||||
$this->_S[3][$i+1] = $datar;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
|
@ -1,327 +0,0 @@
|
||||||
<?php
|
|
||||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Crypt_Blowfish allows for encryption and decryption on the fly using
|
|
||||||
* the Blowfish algorithm. Crypt_Blowfish does not require the mcrypt
|
|
||||||
* PHP extension, it uses only PHP.
|
|
||||||
* Crypt_Blowfish support encryption/decryption with or without a secret key.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* PHP versions 4 and 5
|
|
||||||
*
|
|
||||||
* LICENSE: This source file is subject to version 3.0 of the PHP license
|
|
||||||
* that is available through the world-wide-web at the following URI:
|
|
||||||
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
|
||||||
* the PHP License and are unable to obtain it through the web, please
|
|
||||||
* send a note to license@php.net so we can mail you a copy immediately.
|
|
||||||
*
|
|
||||||
* @category Encryption
|
|
||||||
* @package Crypt_Blowfish
|
|
||||||
* @author Matthew Fonda <mfonda@php.net>
|
|
||||||
* @copyright 2005 Matthew Fonda
|
|
||||||
* @license http://www.php.net/license/3_0.txt PHP License 3.0
|
|
||||||
* @version CVS: $Id: DefaultKey.php,v 1.81 2005/05/30 18:40:37 mfonda Exp $
|
|
||||||
* @link http://pear.php.net/package/Crypt_Blowfish
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class containing default key
|
|
||||||
*
|
|
||||||
* @category Encryption
|
|
||||||
* @package Crypt_Blowfish
|
|
||||||
* @author Matthew Fonda <mfonda@php.net>
|
|
||||||
* @copyright 2005 Matthew Fonda
|
|
||||||
* @license http://www.php.net/license/3_0.txt PHP License 3.0
|
|
||||||
* @link http://pear.php.net/package/Crypt_Blowfish
|
|
||||||
* @version @package_version@
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
class Crypt_Blowfish_DefaultKey
|
|
||||||
{
|
|
||||||
var $P = array();
|
|
||||||
|
|
||||||
var $S = array();
|
|
||||||
|
|
||||||
function Crypt_Blowfish_DefaultKey()
|
|
||||||
{
|
|
||||||
$this->P = array(
|
|
||||||
0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344,
|
|
||||||
0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89,
|
|
||||||
0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
|
|
||||||
0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917,
|
|
||||||
0x9216D5D9, 0x8979FB1B
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->S = array(
|
|
||||||
array(
|
|
||||||
0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7,
|
|
||||||
0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99,
|
|
||||||
0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16,
|
|
||||||
0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E,
|
|
||||||
0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE,
|
|
||||||
0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013,
|
|
||||||
0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF,
|
|
||||||
0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E,
|
|
||||||
0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60,
|
|
||||||
0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440,
|
|
||||||
0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE,
|
|
||||||
0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A,
|
|
||||||
0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E,
|
|
||||||
0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677,
|
|
||||||
0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193,
|
|
||||||
0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032,
|
|
||||||
0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88,
|
|
||||||
0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239,
|
|
||||||
0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E,
|
|
||||||
0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0,
|
|
||||||
0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3,
|
|
||||||
0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98,
|
|
||||||
0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88,
|
|
||||||
0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE,
|
|
||||||
0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6,
|
|
||||||
0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D,
|
|
||||||
0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B,
|
|
||||||
0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7,
|
|
||||||
0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA,
|
|
||||||
0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463,
|
|
||||||
0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F,
|
|
||||||
0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09,
|
|
||||||
0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3,
|
|
||||||
0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB,
|
|
||||||
0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279,
|
|
||||||
0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8,
|
|
||||||
0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB,
|
|
||||||
0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82,
|
|
||||||
0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB,
|
|
||||||
0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573,
|
|
||||||
0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0,
|
|
||||||
0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B,
|
|
||||||
0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790,
|
|
||||||
0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8,
|
|
||||||
0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4,
|
|
||||||
0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0,
|
|
||||||
0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7,
|
|
||||||
0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C,
|
|
||||||
0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD,
|
|
||||||
0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1,
|
|
||||||
0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299,
|
|
||||||
0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9,
|
|
||||||
0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477,
|
|
||||||
0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF,
|
|
||||||
0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49,
|
|
||||||
0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF,
|
|
||||||
0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA,
|
|
||||||
0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5,
|
|
||||||
0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41,
|
|
||||||
0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915,
|
|
||||||
0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400,
|
|
||||||
0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915,
|
|
||||||
0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
|
|
||||||
0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623,
|
|
||||||
0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266,
|
|
||||||
0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1,
|
|
||||||
0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E,
|
|
||||||
0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6,
|
|
||||||
0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1,
|
|
||||||
0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E,
|
|
||||||
0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1,
|
|
||||||
0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737,
|
|
||||||
0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8,
|
|
||||||
0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF,
|
|
||||||
0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD,
|
|
||||||
0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701,
|
|
||||||
0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7,
|
|
||||||
0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41,
|
|
||||||
0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331,
|
|
||||||
0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF,
|
|
||||||
0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF,
|
|
||||||
0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E,
|
|
||||||
0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87,
|
|
||||||
0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C,
|
|
||||||
0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2,
|
|
||||||
0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16,
|
|
||||||
0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD,
|
|
||||||
0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B,
|
|
||||||
0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509,
|
|
||||||
0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E,
|
|
||||||
0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3,
|
|
||||||
0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F,
|
|
||||||
0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A,
|
|
||||||
0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4,
|
|
||||||
0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960,
|
|
||||||
0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66,
|
|
||||||
0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28,
|
|
||||||
0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802,
|
|
||||||
0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84,
|
|
||||||
0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510,
|
|
||||||
0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF,
|
|
||||||
0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14,
|
|
||||||
0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E,
|
|
||||||
0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50,
|
|
||||||
0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7,
|
|
||||||
0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8,
|
|
||||||
0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281,
|
|
||||||
0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99,
|
|
||||||
0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696,
|
|
||||||
0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128,
|
|
||||||
0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73,
|
|
||||||
0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0,
|
|
||||||
0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0,
|
|
||||||
0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105,
|
|
||||||
0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250,
|
|
||||||
0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3,
|
|
||||||
0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285,
|
|
||||||
0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00,
|
|
||||||
0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061,
|
|
||||||
0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB,
|
|
||||||
0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E,
|
|
||||||
0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735,
|
|
||||||
0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC,
|
|
||||||
0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9,
|
|
||||||
0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340,
|
|
||||||
0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
|
|
||||||
0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934,
|
|
||||||
0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068,
|
|
||||||
0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF,
|
|
||||||
0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840,
|
|
||||||
0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45,
|
|
||||||
0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504,
|
|
||||||
0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A,
|
|
||||||
0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB,
|
|
||||||
0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE,
|
|
||||||
0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6,
|
|
||||||
0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42,
|
|
||||||
0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B,
|
|
||||||
0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2,
|
|
||||||
0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB,
|
|
||||||
0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527,
|
|
||||||
0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B,
|
|
||||||
0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33,
|
|
||||||
0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C,
|
|
||||||
0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3,
|
|
||||||
0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC,
|
|
||||||
0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17,
|
|
||||||
0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564,
|
|
||||||
0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B,
|
|
||||||
0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115,
|
|
||||||
0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922,
|
|
||||||
0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728,
|
|
||||||
0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0,
|
|
||||||
0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E,
|
|
||||||
0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37,
|
|
||||||
0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D,
|
|
||||||
0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804,
|
|
||||||
0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B,
|
|
||||||
0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3,
|
|
||||||
0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB,
|
|
||||||
0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D,
|
|
||||||
0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C,
|
|
||||||
0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350,
|
|
||||||
0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9,
|
|
||||||
0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A,
|
|
||||||
0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE,
|
|
||||||
0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D,
|
|
||||||
0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC,
|
|
||||||
0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F,
|
|
||||||
0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61,
|
|
||||||
0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2,
|
|
||||||
0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9,
|
|
||||||
0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2,
|
|
||||||
0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C,
|
|
||||||
0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E,
|
|
||||||
0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633,
|
|
||||||
0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10,
|
|
||||||
0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169,
|
|
||||||
0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52,
|
|
||||||
0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027,
|
|
||||||
0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5,
|
|
||||||
0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62,
|
|
||||||
0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634,
|
|
||||||
0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76,
|
|
||||||
0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24,
|
|
||||||
0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC,
|
|
||||||
0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4,
|
|
||||||
0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C,
|
|
||||||
0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
|
|
||||||
0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B,
|
|
||||||
0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE,
|
|
||||||
0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B,
|
|
||||||
0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4,
|
|
||||||
0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8,
|
|
||||||
0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6,
|
|
||||||
0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304,
|
|
||||||
0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22,
|
|
||||||
0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4,
|
|
||||||
0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6,
|
|
||||||
0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9,
|
|
||||||
0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59,
|
|
||||||
0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593,
|
|
||||||
0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51,
|
|
||||||
0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28,
|
|
||||||
0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C,
|
|
||||||
0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B,
|
|
||||||
0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28,
|
|
||||||
0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C,
|
|
||||||
0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD,
|
|
||||||
0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A,
|
|
||||||
0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319,
|
|
||||||
0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB,
|
|
||||||
0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F,
|
|
||||||
0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991,
|
|
||||||
0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32,
|
|
||||||
0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680,
|
|
||||||
0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166,
|
|
||||||
0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE,
|
|
||||||
0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB,
|
|
||||||
0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5,
|
|
||||||
0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47,
|
|
||||||
0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370,
|
|
||||||
0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D,
|
|
||||||
0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84,
|
|
||||||
0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048,
|
|
||||||
0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8,
|
|
||||||
0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD,
|
|
||||||
0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9,
|
|
||||||
0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7,
|
|
||||||
0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38,
|
|
||||||
0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F,
|
|
||||||
0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C,
|
|
||||||
0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525,
|
|
||||||
0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1,
|
|
||||||
0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442,
|
|
||||||
0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964,
|
|
||||||
0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E,
|
|
||||||
0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8,
|
|
||||||
0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D,
|
|
||||||
0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F,
|
|
||||||
0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299,
|
|
||||||
0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02,
|
|
||||||
0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC,
|
|
||||||
0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614,
|
|
||||||
0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A,
|
|
||||||
0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6,
|
|
||||||
0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B,
|
|
||||||
0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0,
|
|
||||||
0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060,
|
|
||||||
0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E,
|
|
||||||
0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9,
|
|
||||||
0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F,
|
|
||||||
0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
|
@ -1,380 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dropbox API class
|
|
||||||
*
|
|
||||||
* @package Dropbox
|
|
||||||
* @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
|
|
||||||
* @author Evert Pot (http://www.rooftopsolutions.nl/)
|
|
||||||
* @license http://code.google.com/p/dropbox-php/wiki/License MIT
|
|
||||||
*/
|
|
||||||
class Dropbox_API {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sandbox root-path
|
|
||||||
*/
|
|
||||||
const ROOT_SANDBOX = 'sandbox';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dropbox root-path
|
|
||||||
*/
|
|
||||||
const ROOT_DROPBOX = 'dropbox';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* API URl
|
|
||||||
*/
|
|
||||||
protected $api_url = 'https://api.dropbox.com/1/';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Content API URl
|
|
||||||
*/
|
|
||||||
protected $api_content_url = 'https://api-content.dropbox.com/1/';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* OAuth object
|
|
||||||
*
|
|
||||||
* @var Dropbox_OAuth
|
|
||||||
*/
|
|
||||||
protected $oauth;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default root-path, this will most likely be 'sandbox' or 'dropbox'
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $root;
|
|
||||||
protected $useSSL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* @param Dropbox_OAuth Dropbox_Auth object
|
|
||||||
* @param string $root default root path (sandbox or dropbox)
|
|
||||||
*/
|
|
||||||
public function __construct(Dropbox_OAuth $oauth, $root = self::ROOT_DROPBOX, $useSSL = true) {
|
|
||||||
|
|
||||||
$this->oauth = $oauth;
|
|
||||||
$this->root = $root;
|
|
||||||
$this->useSSL = $useSSL;
|
|
||||||
if (!$this->useSSL)
|
|
||||||
{
|
|
||||||
throw new Dropbox_Exception('Dropbox REST API now requires that all requests use SSL');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns information about the current dropbox account
|
|
||||||
*
|
|
||||||
* @return stdclass
|
|
||||||
*/
|
|
||||||
public function getAccountInfo() {
|
|
||||||
|
|
||||||
$data = $this->oauth->fetch($this->api_url . 'account/info');
|
|
||||||
return json_decode($data['body'],true);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a file's contents
|
|
||||||
*
|
|
||||||
* @param string $path path
|
|
||||||
* @param string $root Use this to override the default root path (sandbox/dropbox)
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getFile($path = '', $root = null) {
|
|
||||||
|
|
||||||
if (is_null($root)) $root = $this->root;
|
|
||||||
$path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
|
|
||||||
$result = $this->oauth->fetch($this->api_content_url . 'files/' . $root . '/' . ltrim($path,'/'));
|
|
||||||
return $result['body'];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uploads a new file
|
|
||||||
*
|
|
||||||
* @param string $path Target path (including filename)
|
|
||||||
* @param string $file Either a path to a file or a stream resource
|
|
||||||
* @param string $root Use this to override the default root path (sandbox/dropbox)
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function putFile($path, $file, $root = null) {
|
|
||||||
|
|
||||||
$directory = dirname($path);
|
|
||||||
$filename = basename($path);
|
|
||||||
|
|
||||||
if($directory==='.') $directory = '';
|
|
||||||
$directory = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($directory));
|
|
||||||
// $filename = str_replace('~', '%7E', rawurlencode($filename));
|
|
||||||
if (is_null($root)) $root = $this->root;
|
|
||||||
|
|
||||||
if (is_string($file)) {
|
|
||||||
|
|
||||||
$file = fopen($file,'rb');
|
|
||||||
|
|
||||||
} elseif (!is_resource($file)) {
|
|
||||||
throw new Dropbox_Exception('File must be a file-resource or a string');
|
|
||||||
}
|
|
||||||
$result=$this->multipartFetch($this->api_content_url . 'files/' .
|
|
||||||
$root . '/' . trim($directory,'/'), $file, $filename);
|
|
||||||
|
|
||||||
if(!isset($result["httpStatus"]) || $result["httpStatus"] != 200)
|
|
||||||
throw new Dropbox_Exception("Uploading file to Dropbox failed");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copies a file or directory from one location to another
|
|
||||||
*
|
|
||||||
* This method returns the file information of the newly created file.
|
|
||||||
*
|
|
||||||
* @param string $from source path
|
|
||||||
* @param string $to destination path
|
|
||||||
* @param string $root Use this to override the default root path (sandbox/dropbox)
|
|
||||||
* @return stdclass
|
|
||||||
*/
|
|
||||||
public function copy($from, $to, $root = null) {
|
|
||||||
|
|
||||||
if (is_null($root)) $root = $this->root;
|
|
||||||
$response = $this->oauth->fetch($this->api_url . 'fileops/copy', array('from_path' => $from, 'to_path' => $to, 'root' => $root), 'POST');
|
|
||||||
|
|
||||||
return json_decode($response['body'],true);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new folder
|
|
||||||
*
|
|
||||||
* This method returns the information from the newly created directory
|
|
||||||
*
|
|
||||||
* @param string $path
|
|
||||||
* @param string $root Use this to override the default root path (sandbox/dropbox)
|
|
||||||
* @return stdclass
|
|
||||||
*/
|
|
||||||
public function createFolder($path, $root = null) {
|
|
||||||
|
|
||||||
if (is_null($root)) $root = $this->root;
|
|
||||||
|
|
||||||
// Making sure the path starts with a /
|
|
||||||
// $path = '/' . ltrim($path,'/');
|
|
||||||
|
|
||||||
$response = $this->oauth->fetch($this->api_url . 'fileops/create_folder', array('path' => $path, 'root' => $root),'POST');
|
|
||||||
return json_decode($response['body'],true);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes a file or folder.
|
|
||||||
*
|
|
||||||
* This method will return the metadata information from the deleted file or folder, if successful.
|
|
||||||
*
|
|
||||||
* @param string $path Path to new folder
|
|
||||||
* @param string $root Use this to override the default root path (sandbox/dropbox)
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function delete($path, $root = null) {
|
|
||||||
|
|
||||||
if (is_null($root)) $root = $this->root;
|
|
||||||
$response = $this->oauth->fetch($this->api_url . 'fileops/delete', array('path' => $path, 'root' => $root), 'POST');
|
|
||||||
return json_decode($response['body']);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Moves a file or directory to a new location
|
|
||||||
*
|
|
||||||
* This method returns the information from the newly created directory
|
|
||||||
*
|
|
||||||
* @param mixed $from Source path
|
|
||||||
* @param mixed $to destination path
|
|
||||||
* @param string $root Use this to override the default root path (sandbox/dropbox)
|
|
||||||
* @return stdclass
|
|
||||||
*/
|
|
||||||
public function move($from, $to, $root = null) {
|
|
||||||
|
|
||||||
if (is_null($root)) $root = $this->root;
|
|
||||||
$response = $this->oauth->fetch($this->api_url . 'fileops/move', array('from_path' => rawurldecode($from), 'to_path' => rawurldecode($to), 'root' => $root), 'POST');
|
|
||||||
|
|
||||||
return json_decode($response['body'],true);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns file and directory information
|
|
||||||
*
|
|
||||||
* @param string $path Path to receive information from
|
|
||||||
* @param bool $list When set to true, this method returns information from all files in a directory. When set to false it will only return infromation from the specified directory.
|
|
||||||
* @param string $hash If a hash is supplied, this method simply returns true if nothing has changed since the last request. Good for caching.
|
|
||||||
* @param int $fileLimit Maximum number of file-information to receive
|
|
||||||
* @param string $root Use this to override the default root path (sandbox/dropbox)
|
|
||||||
* @return array|true
|
|
||||||
*/
|
|
||||||
public function getMetaData($path, $list = true, $hash = null, $fileLimit = null, $root = null) {
|
|
||||||
|
|
||||||
if (is_null($root)) $root = $this->root;
|
|
||||||
|
|
||||||
$args = array(
|
|
||||||
'list' => $list,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!is_null($hash)) $args['hash'] = $hash;
|
|
||||||
if (!is_null($fileLimit)) $args['file_limit'] = $fileLimit;
|
|
||||||
|
|
||||||
$path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
|
|
||||||
$response = $this->oauth->fetch($this->api_url . 'metadata/' . $root . '/' . ltrim($path,'/'), $args);
|
|
||||||
|
|
||||||
/* 304 is not modified */
|
|
||||||
if ($response['httpStatus']==304) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return json_decode($response['body'],true);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A way of letting you keep up with changes to files and folders in a user's Dropbox. You can periodically call /delta to get a list of "delta entries", which are instructions on how to update your local state to match the server's state.
|
|
||||||
*
|
|
||||||
* This method returns the information from the newly created directory
|
|
||||||
*
|
|
||||||
* @param string $cursor A string that is used to keep track of your current state. On the next call pass in this value to return delta entries that have been recorded since the cursor was returned.
|
|
||||||
* @return stdclass
|
|
||||||
*/
|
|
||||||
public function delta($cursor) {
|
|
||||||
|
|
||||||
$arg['cursor'] = $cursor;
|
|
||||||
|
|
||||||
$response = $this->oauth->fetch($this->api_url . 'delta', $arg, 'POST');
|
|
||||||
return json_decode($response['body'],true);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a thumbnail (as a string) for a file path.
|
|
||||||
*
|
|
||||||
* @param string $path Path to file
|
|
||||||
* @param string $size small, medium or large
|
|
||||||
* @param string $root Use this to override the default root path (sandbox/dropbox)
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getThumbnail($path, $size = 'small', $root = null) {
|
|
||||||
|
|
||||||
if (is_null($root)) $root = $this->root;
|
|
||||||
$path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
|
|
||||||
$response = $this->oauth->fetch($this->api_content_url . 'thumbnails/' . $root . '/' . ltrim($path,'/'),array('size' => $size));
|
|
||||||
|
|
||||||
return $response['body'];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is used to generate multipart POST requests for file upload
|
|
||||||
*
|
|
||||||
* @param string $uri
|
|
||||||
* @param array $arguments
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
protected function multipartFetch($uri, $file, $filename) {
|
|
||||||
|
|
||||||
/* random string */
|
|
||||||
$boundary = 'R50hrfBj5JYyfR3vF3wR96GPCC9Fd2q2pVMERvEaOE3D8LZTgLLbRpNwXek3';
|
|
||||||
|
|
||||||
$headers = array(
|
|
||||||
'Content-Type' => 'multipart/form-data; boundary=' . $boundary,
|
|
||||||
);
|
|
||||||
|
|
||||||
$body="--" . $boundary . "\r\n";
|
|
||||||
$body.="Content-Disposition: form-data; name=file; filename=".rawurldecode($filename)."\r\n";
|
|
||||||
$body.="Content-type: application/octet-stream\r\n";
|
|
||||||
$body.="\r\n";
|
|
||||||
$body.=stream_get_contents($file);
|
|
||||||
$body.="\r\n";
|
|
||||||
$body.="--" . $boundary . "--";
|
|
||||||
|
|
||||||
// Dropbox requires the filename to also be part of the regular arguments, so it becomes
|
|
||||||
// part of the signature.
|
|
||||||
$uri.='?file=' . $filename;
|
|
||||||
|
|
||||||
return $this->oauth->fetch($uri, $body, 'POST', $headers);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search
|
|
||||||
*
|
|
||||||
* Returns metadata for all files and folders that match the search query.
|
|
||||||
*
|
|
||||||
* @added by: diszo.sasil
|
|
||||||
*
|
|
||||||
* @param string $query
|
|
||||||
* @param string $root Use this to override the default root path (sandbox/dropbox)
|
|
||||||
* @param string $path
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function search($query = '', $root = null, $path = ''){
|
|
||||||
if (is_null($root)) $root = $this->root;
|
|
||||||
if(!empty($path)){
|
|
||||||
$path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
|
|
||||||
}
|
|
||||||
$response = $this->oauth->fetch($this->api_url . 'search/' . $root . '/' . ltrim($path,'/'),array('query' => $query));
|
|
||||||
return json_decode($response['body'],true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and returns a shareable link to files or folders.
|
|
||||||
*
|
|
||||||
* Note: Links created by the /shares API call expire after thirty days.
|
|
||||||
*
|
|
||||||
* @param type $path
|
|
||||||
* @param type $root
|
|
||||||
* @return type
|
|
||||||
*/
|
|
||||||
public function share($path, $root = null) {
|
|
||||||
if (is_null($root)) $root = $this->root;
|
|
||||||
$path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
|
|
||||||
$response = $this->oauth->fetch($this->api_url. 'shares/'. $root . '/' . ltrim($path, '/'), array(), 'POST');
|
|
||||||
return json_decode($response['body'],true);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a link directly to a file.
|
|
||||||
* Similar to /shares. The difference is that this bypasses the Dropbox webserver, used to provide a preview of the file, so that you can effectively stream the contents of your media.
|
|
||||||
*
|
|
||||||
* Note: The /media link expires after four hours, allotting enough time to stream files, but not enough to leave a connection open indefinitely.
|
|
||||||
*
|
|
||||||
* @param type $path
|
|
||||||
* @param type $root
|
|
||||||
* @return type
|
|
||||||
*/
|
|
||||||
public function media($path, $root = null) {
|
|
||||||
|
|
||||||
if (is_null($root)) $root = $this->root;
|
|
||||||
$path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
|
|
||||||
$response = $this->oauth->fetch($this->api_url. 'media/'. $root . '/' . ltrim($path, '/'), array(), 'POST');
|
|
||||||
return json_decode($response['body'],true);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and returns a copy_ref to a file. This reference string can be used to copy that file to another user's Dropbox by passing it in as the from_copy_ref parameter on /fileops/copy.
|
|
||||||
*
|
|
||||||
* @param type $path
|
|
||||||
* @param type $root
|
|
||||||
* @return type
|
|
||||||
*/
|
|
||||||
public function copy_ref($path, $root = null) {
|
|
||||||
|
|
||||||
if (is_null($root)) $root = $this->root;
|
|
||||||
$path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
|
|
||||||
$response = $this->oauth->fetch($this->api_url. 'copy_ref/'. $root . '/' . ltrim($path, '/'));
|
|
||||||
return json_decode($response['body'],true);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dropbox base exception
|
|
||||||
*
|
|
||||||
* @package Dropbox
|
|
||||||
* @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
|
|
||||||
* @author Evert Pot (http://www.rooftopsolutions.nl/)
|
|
||||||
* @license http://code.google.com/p/dropbox-php/wiki/License MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base exception class
|
|
||||||
*/
|
|
||||||
class Dropbox_Exception extends Exception { }
|
|
|
@ -1,18 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dropbox Forbidden exception
|
|
||||||
*
|
|
||||||
* @package Dropbox
|
|
||||||
* @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
|
|
||||||
* @author Evert Pot (http://www.rooftopsolutions.nl/)
|
|
||||||
* @license http://code.google.com/p/dropbox-php/wiki/License MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This exception is thrown when we receive the 403 forbidden response
|
|
||||||
*/
|
|
||||||
class Dropbox_Exception_Forbidden extends Dropbox_Exception {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dropbox Not Found exception
|
|
||||||
*
|
|
||||||
* @package Dropbox
|
|
||||||
* @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
|
|
||||||
* @author Evert Pot (http://www.rooftopsolutions.nl/)
|
|
||||||
* @license http://code.google.com/p/dropbox-php/wiki/License MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This exception is thrown when a non-existant uri is accessed.
|
|
||||||
*
|
|
||||||
* Basically, this exception is used when we get back a 404.
|
|
||||||
*/
|
|
||||||
class Dropbox_Exception_NotFound extends Dropbox_Exception {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dropbox Over Quota exception
|
|
||||||
*
|
|
||||||
* @package Dropbox
|
|
||||||
* @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
|
|
||||||
* @author Evert Pot (http://www.rooftopsolutions.nl/)
|
|
||||||
* @license http://code.google.com/p/dropbox-php/wiki/License MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This exception is thrown when the operation required more space than the available quota.
|
|
||||||
*
|
|
||||||
* Basically, this exception is used when we get back a 507.
|
|
||||||
*/
|
|
||||||
class Dropbox_Exception_OverQuota extends Dropbox_Exception {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dropbox RequestToken exception
|
|
||||||
*
|
|
||||||
* @package Dropbox
|
|
||||||
* @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
|
|
||||||
* @author Evert Pot (http://www.rooftopsolutions.nl/)
|
|
||||||
* @license http://code.google.com/p/dropbox-php/wiki/License MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This exception is thrown when an error occured during the request_token process.
|
|
||||||
*/
|
|
||||||
class Dropbox_Exception_RequestToken extends Dropbox_Exception {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
Copyright (c) 2010 Rooftop Solutions
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
|
@ -1,151 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dropbox OAuth
|
|
||||||
*
|
|
||||||
* @package Dropbox
|
|
||||||
* @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
|
|
||||||
* @author Evert Pot (http://www.rooftopsolutions.nl/)
|
|
||||||
* @license http://code.google.com/p/dropbox-php/wiki/License MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is an abstract OAuth class.
|
|
||||||
*
|
|
||||||
* It must be extended by classes who wish to provide OAuth functionality
|
|
||||||
* using different libraries.
|
|
||||||
*/
|
|
||||||
abstract class Dropbox_OAuth {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* After a user has authorized access, dropbox can redirect the user back
|
|
||||||
* to this url.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public $authorizeCallbackUrl = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uri used to fetch request tokens
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
const URI_REQUEST_TOKEN = 'https://api.dropbox.com/1/oauth/request_token';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uri used to redirect the user to for authorization.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
const URI_AUTHORIZE = 'https://www.dropbox.com/1/oauth/authorize';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uri used to
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
const URI_ACCESS_TOKEN = 'https://api.dropbox.com/1/oauth/access_token';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An OAuth request token.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $oauth_token = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* OAuth token secret
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $oauth_token_secret = null;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* @param string $consumerKey
|
|
||||||
* @param string $consumerSecret
|
|
||||||
*/
|
|
||||||
abstract public function __construct($consumerKey, $consumerSecret);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the request token and secret.
|
|
||||||
*
|
|
||||||
* The tokens can also be passed as an array into the first argument.
|
|
||||||
* The array must have the elements token and token_secret.
|
|
||||||
*
|
|
||||||
* @param string|array $token
|
|
||||||
* @param string $token_secret
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function setToken($token, $token_secret = null) {
|
|
||||||
|
|
||||||
if (is_array($token)) {
|
|
||||||
$this->oauth_token = $token['token'];
|
|
||||||
$this->oauth_token_secret = $token['token_secret'];
|
|
||||||
} else {
|
|
||||||
$this->oauth_token = $token;
|
|
||||||
$this->oauth_token_secret = $token_secret;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the oauth request tokens as an associative array.
|
|
||||||
*
|
|
||||||
* The array will contain the elements 'token' and 'token_secret'.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getToken() {
|
|
||||||
|
|
||||||
return array(
|
|
||||||
'token' => $this->oauth_token,
|
|
||||||
'token_secret' => $this->oauth_token_secret,
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the authorization url
|
|
||||||
*
|
|
||||||
* @param string $callBack Specify a callback url to automatically redirect the user back
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getAuthorizeUrl($callBack = null) {
|
|
||||||
|
|
||||||
// Building the redirect uri
|
|
||||||
$token = $this->getToken();
|
|
||||||
$uri = self::URI_AUTHORIZE . '?oauth_token=' . $token['token'];
|
|
||||||
if ($callBack) $uri.='&oauth_callback=' . $callBack;
|
|
||||||
return $uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches a secured oauth url and returns the response body.
|
|
||||||
*
|
|
||||||
* @param string $uri
|
|
||||||
* @param mixed $arguments
|
|
||||||
* @param string $method
|
|
||||||
* @param array $httpHeaders
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public abstract function fetch($uri, $arguments = array(), $method = 'GET', $httpHeaders = array());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests the OAuth request token.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
abstract public function getRequestToken();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests the OAuth access tokens.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
abstract public function getAccessToken();
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* HTTP OAuth Consumer
|
|
||||||
*
|
|
||||||
* Adapted from halldirector's code in
|
|
||||||
* http://code.google.com/p/dropbox-php/issues/detail?id=36#c5
|
|
||||||
*
|
|
||||||
* @package Dropbox
|
|
||||||
* @copyright Copyright (C) 2011 Joe Constant / halldirector. All rights reserved.
|
|
||||||
* @author Joe Constant / halldirector
|
|
||||||
* @license http://code.google.com/p/dropbox-php/wiki/License MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once 'HTTP/OAuth.php';
|
|
||||||
require_once 'HTTP/OAuth/Consumer.php';
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This class is to help work around aomw ssl issues.
|
|
||||||
*/
|
|
||||||
class Dropbox_OAuth_Consumer_Dropbox extends HTTP_OAuth_Consumer
|
|
||||||
{
|
|
||||||
public function getOAuthConsumerRequest()
|
|
||||||
{
|
|
||||||
if (!$this->consumerRequest instanceof HTTP_OAuth_Consumer_Request) {
|
|
||||||
$this->consumerRequest = new HTTP_OAuth_Consumer_Request;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Change this and add in code to validate the SSL cert.
|
|
||||||
// see https://github.com/bagder/curl/blob/master/lib/mk-ca-bundle.pl
|
|
||||||
$this->consumerRequest->setConfig(array(
|
|
||||||
'ssl_verify_peer' => false,
|
|
||||||
'ssl_verify_host' => false
|
|
||||||
));
|
|
||||||
|
|
||||||
return $this->consumerRequest;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,282 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dropbox OAuth
|
|
||||||
*
|
|
||||||
* @package Dropbox
|
|
||||||
* @copyright Copyright (C) 2011 Daniel Huesken
|
|
||||||
* @author Daniel Huesken (http://www.danielhuesken.de/)
|
|
||||||
* @license MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is used to sign all requests to dropbox.
|
|
||||||
*
|
|
||||||
* This specific class uses WordPress WP_Http to authenticate.
|
|
||||||
*/
|
|
||||||
class Dropbox_OAuth_Curl extends Dropbox_OAuth {
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @var string ConsumerKey
|
|
||||||
*/
|
|
||||||
protected $consumerKey = null;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @var string ConsumerSecret
|
|
||||||
*/
|
|
||||||
protected $consumerSecret = null;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @var string ProzessCallBack
|
|
||||||
*/
|
|
||||||
public $ProgressFunction = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* @param string $consumerKey
|
|
||||||
* @param string $consumerSecret
|
|
||||||
*/
|
|
||||||
public function __construct($consumerKey, $consumerSecret) {
|
|
||||||
if (!function_exists('curl_exec'))
|
|
||||||
throw new Dropbox_Exception('The PHP curl functions not available!');
|
|
||||||
|
|
||||||
$this->consumerKey = $consumerKey;
|
|
||||||
$this->consumerSecret = $consumerSecret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches a secured oauth url and returns the response body.
|
|
||||||
*
|
|
||||||
* @param string $uri
|
|
||||||
* @param mixed $arguments
|
|
||||||
* @param string $method
|
|
||||||
* @param array $httpHeaders
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function fetch($uri, $arguments = array(), $method = 'GET', $httpHeaders = array()) {
|
|
||||||
|
|
||||||
$uri=str_replace('http://', 'https://', $uri); // all https, upload makes problems if not
|
|
||||||
if (is_string($arguments) and strtoupper($method) == 'POST') {
|
|
||||||
preg_match("/\?file=(.*)$/i", $uri, $matches);
|
|
||||||
if (isset($matches[1])) {
|
|
||||||
$uri = str_replace($matches[0], "", $uri);
|
|
||||||
$filename = $matches[1];
|
|
||||||
$httpHeaders=array_merge($httpHeaders,$this->getOAuthHeader($uri, array("file" => $filename), $method));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$httpHeaders=array_merge($httpHeaders,$this->getOAuthHeader($uri, $arguments, $method));
|
|
||||||
}
|
|
||||||
$ch = curl_init();
|
|
||||||
if (strtoupper($method) == 'POST') {
|
|
||||||
curl_setopt($ch, CURLOPT_URL, $uri);
|
|
||||||
curl_setopt($ch, CURLOPT_POST, true);
|
|
||||||
// if (is_array($arguments))
|
|
||||||
// $arguments=http_build_query($arguments);
|
|
||||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $arguments);
|
|
||||||
// $httpHeaders['Content-Length']=strlen($arguments);
|
|
||||||
} else {
|
|
||||||
curl_setopt($ch, CURLOPT_URL, $uri.'?'.http_build_query($arguments));
|
|
||||||
curl_setopt($ch, CURLOPT_POST, false);
|
|
||||||
}
|
|
||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
||||||
curl_setopt($ch, CURLOPT_TIMEOUT, 300);
|
|
||||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
|
|
||||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
|
|
||||||
// curl_setopt($ch, CURLOPT_CAINFO, "rootca");
|
|
||||||
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
|
|
||||||
//Build header
|
|
||||||
$headers = array();
|
|
||||||
foreach ($httpHeaders as $name => $value) {
|
|
||||||
$headers[] = "{$name}: $value";
|
|
||||||
}
|
|
||||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
|
||||||
if (!ini_get('safe_mode') && !ini_get('open_basedir'))
|
|
||||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true );
|
|
||||||
if (function_exists($this->ProgressFunction) and defined('CURLOPT_PROGRESSFUNCTION')) {
|
|
||||||
curl_setopt($ch, CURLOPT_NOPROGRESS, false);
|
|
||||||
curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, $this->ProgressFunction);
|
|
||||||
curl_setopt($ch, CURLOPT_BUFFERSIZE, 512);
|
|
||||||
}
|
|
||||||
$response=curl_exec($ch);
|
|
||||||
$errorno=curl_errno($ch);
|
|
||||||
$error=curl_error($ch);
|
|
||||||
$status=curl_getinfo($ch,CURLINFO_HTTP_CODE);
|
|
||||||
curl_close($ch);
|
|
||||||
|
|
||||||
|
|
||||||
if (!empty($errorno))
|
|
||||||
throw new Dropbox_Exception_NotFound('Curl error: ('.$errorno.') '.$error."\n");
|
|
||||||
|
|
||||||
if ($status>=300) {
|
|
||||||
$body = json_decode($response,true);
|
|
||||||
switch ($status) {
|
|
||||||
// Not modified
|
|
||||||
case 304 :
|
|
||||||
return array(
|
|
||||||
'httpStatus' => 304,
|
|
||||||
'body' => null,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 403 :
|
|
||||||
throw new Dropbox_Exception_Forbidden('Forbidden.
|
|
||||||
This could mean a bad OAuth request, or a file or folder already existing at the target location.
|
|
||||||
' . $body["error"] . "\n");
|
|
||||||
case 404 :
|
|
||||||
throw new Dropbox_Exception_NotFound('Resource at uri: ' . $uri . ' could not be found. ' .
|
|
||||||
$body["error"] . "\n");
|
|
||||||
case 507 :
|
|
||||||
throw new Dropbox_Exception_OverQuota('This dropbox is full. ' .
|
|
||||||
$body["error"] . "\n");
|
|
||||||
}
|
|
||||||
if (!empty($body["error"]))
|
|
||||||
throw new Dropbox_Exception_RequestToken('Error: ('.$status.') '.$body["error"]."\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return array(
|
|
||||||
'body' => $response,
|
|
||||||
'httpStatus' => $status
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns named array with oauth parameters for further use
|
|
||||||
* @return array Array with oauth_ parameters
|
|
||||||
*/
|
|
||||||
private function getOAuthBaseParams() {
|
|
||||||
$params['oauth_version'] = '1.0';
|
|
||||||
$params['oauth_signature_method'] = 'HMAC-SHA1';
|
|
||||||
|
|
||||||
$params['oauth_consumer_key'] = $this->consumerKey;
|
|
||||||
$tokens = $this->getToken();
|
|
||||||
if (isset($tokens['token']) && $tokens['token']) {
|
|
||||||
$params['oauth_token'] = $tokens['token'];
|
|
||||||
}
|
|
||||||
$params['oauth_timestamp'] = time();
|
|
||||||
$params['oauth_nonce'] = md5(microtime() . mt_rand());
|
|
||||||
return $params;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates valid Authorization header for OAuth, based on URI and Params
|
|
||||||
*
|
|
||||||
* @param string $uri
|
|
||||||
* @param array $params
|
|
||||||
* @param string $method GET or POST, standard is GET
|
|
||||||
* @param array $oAuthParams optional, pass your own oauth_params here
|
|
||||||
* @return array Array for request's headers section like
|
|
||||||
* array('Authorization' => 'OAuth ...');
|
|
||||||
*/
|
|
||||||
private function getOAuthHeader($uri, $params, $method = 'GET', $oAuthParams = null) {
|
|
||||||
$oAuthParams = $oAuthParams ? $oAuthParams : $this->getOAuthBaseParams();
|
|
||||||
|
|
||||||
// create baseString to encode for the sent parameters
|
|
||||||
$baseString = $method . '&';
|
|
||||||
$baseString .= $this->oauth_urlencode($uri) . "&";
|
|
||||||
|
|
||||||
// OAuth header does not include GET-Parameters
|
|
||||||
$signatureParams = array_merge($params, $oAuthParams);
|
|
||||||
|
|
||||||
// sorting the parameters
|
|
||||||
ksort($signatureParams);
|
|
||||||
|
|
||||||
$encodedParams = array();
|
|
||||||
foreach ($signatureParams as $key => $value) {
|
|
||||||
$encodedParams[] = $this->oauth_urlencode($key) . '=' . $this->oauth_urlencode($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
$baseString .= $this->oauth_urlencode(implode('&', $encodedParams));
|
|
||||||
|
|
||||||
// encode the signature
|
|
||||||
$tokens = $this->getToken();
|
|
||||||
$hash = $this->hash_hmac_sha1($this->consumerSecret.'&'.$tokens['token_secret'], $baseString);
|
|
||||||
$signature = base64_encode($hash);
|
|
||||||
|
|
||||||
// add signature to oAuthParams
|
|
||||||
$oAuthParams['oauth_signature'] = $signature;
|
|
||||||
|
|
||||||
$oAuthEncoded = array();
|
|
||||||
foreach ($oAuthParams as $key => $value) {
|
|
||||||
$oAuthEncoded[] = $key . '="' . $this->oauth_urlencode($value) . '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return array('Authorization' => 'OAuth ' . implode(', ', $oAuthEncoded));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests the OAuth request token.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function getRequestToken() {
|
|
||||||
$result = $this->fetch(self::URI_REQUEST_TOKEN, array(), 'POST');
|
|
||||||
if ($result['httpStatus'] == "200") {
|
|
||||||
$tokens = array();
|
|
||||||
parse_str($result['body'], $tokens);
|
|
||||||
$this->setToken($tokens['oauth_token'], $tokens['oauth_token_secret']);
|
|
||||||
return $this->getToken();
|
|
||||||
} else {
|
|
||||||
throw new Dropbox_Exception_RequestToken('We were unable to fetch request tokens. This likely means that your consumer key and/or secret are incorrect.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests the OAuth access tokens.
|
|
||||||
*
|
|
||||||
* This method requires the 'unauthorized' request tokens
|
|
||||||
* and, if successful will set the authorized request tokens.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function getAccessToken() {
|
|
||||||
$result = $this->fetch(self::URI_ACCESS_TOKEN, array(), 'POST');
|
|
||||||
if ($result['httpStatus'] == "200") {
|
|
||||||
$tokens = array();
|
|
||||||
parse_str($result['body'], $tokens);
|
|
||||||
$this->setToken($tokens['oauth_token'], $tokens['oauth_token_secret']);
|
|
||||||
return $this->getToken();
|
|
||||||
} else {
|
|
||||||
throw new Dropbox_Exception_RequestToken('We were unable to fetch request tokens. This likely means that your consumer key and/or secret are incorrect.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function to properly urlencode parameters.
|
|
||||||
* See http://php.net/manual/en/function.oauth-urlencode.php
|
|
||||||
*
|
|
||||||
* @param string $string
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private function oauth_urlencode($string) {
|
|
||||||
return str_replace('%E7', '~', rawurlencode($string));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hash function for hmac_sha1; uses native function if available.
|
|
||||||
*
|
|
||||||
* @param string $key
|
|
||||||
* @param string $data
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private function hash_hmac_sha1($key, $data) {
|
|
||||||
if (function_exists('hash_hmac') && in_array('sha1', hash_algos())) {
|
|
||||||
return hash_hmac('sha1', $data, $key, true);
|
|
||||||
} else {
|
|
||||||
$blocksize = 64;
|
|
||||||
$hashfunc = 'sha1';
|
|
||||||
if (strlen($key) > $blocksize) {
|
|
||||||
$key = pack('H*', $hashfunc($key));
|
|
||||||
}
|
|
||||||
|
|
||||||
$key = str_pad($key, $blocksize, chr(0x00));
|
|
||||||
$ipad = str_repeat(chr(0x36), $blocksize);
|
|
||||||
$opad = str_repeat(chr(0x5c), $blocksize);
|
|
||||||
$hash = pack('H*', $hashfunc(( $key ^ $opad ) . pack('H*', $hashfunc(($key ^ $ipad) . $data))));
|
|
||||||
|
|
||||||
return $hash;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
Dropbox-php
|
|
||||||
===========
|
|
||||||
|
|
||||||
This PHP library allows you to easily integrate dropbox with PHP.
|
|
||||||
|
|
||||||
The following PHP extension is required:
|
|
||||||
|
|
||||||
* json
|
|
||||||
|
|
||||||
The library makes use of OAuth. At the moment you can use either of these libraries:
|
|
||||||
|
|
||||||
[PHP OAuth extension](http://pecl.php.net/package/oauth)
|
|
||||||
[PEAR's HTTP_OAUTH package](http://pear.php.net/package/http_oauth)
|
|
||||||
|
|
||||||
The extension is recommended, but if you can't install php extensions you should go for the pear package.
|
|
||||||
Installing
|
|
||||||
----------
|
|
||||||
|
|
||||||
pear channel-discover pear.dropbox-php.com
|
|
||||||
pear install dropbox-php/Dropbox-alpha
|
|
||||||
|
|
||||||
Documentation
|
|
||||||
-------------
|
|
||||||
Check out the [documentation](http://www.dropbox-php.com/docs).
|
|
||||||
|
|
||||||
Questions?
|
|
||||||
----------
|
|
||||||
|
|
||||||
[Dropbox-php Mailing list](http://groups.google.com/group/dropbox-php)
|
|
||||||
[Official Dropbox developer forum](http://forums.dropbox.com/forum.php?id=5)
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This file registers a new autoload function using spl_autoload_register.
|
|
||||||
*
|
|
||||||
* @package Dropbox
|
|
||||||
* @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
|
|
||||||
* @author Evert Pot (http://www.rooftopsolutions.nl/)
|
|
||||||
* @license http://code.google.com/p/dropbox-php/wiki/License MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Autoloader function
|
|
||||||
*
|
|
||||||
* @param $className string
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function Dropbox_autoload($className) {
|
|
||||||
|
|
||||||
if(strpos($className,'Dropbox_')===0) {
|
|
||||||
|
|
||||||
include dirname(__FILE__) . '/' . str_replace('_','/',substr($className,8)) . '.php';
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
spl_autoload_register('Dropbox_autoload');
|
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
The MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2007 Andy Smith
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
|
@ -1,751 +0,0 @@
|
||||||
<?php
|
|
||||||
// vim: foldmethod=marker
|
|
||||||
|
|
||||||
/* Generic exception class
|
|
||||||
*/
|
|
||||||
class OAuthException extends Exception {/*{{{*/
|
|
||||||
// pass
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
class OAuthConsumer {/*{{{*/
|
|
||||||
public $key;
|
|
||||||
public $secret;
|
|
||||||
|
|
||||||
public function __construct($key, $secret, $callback_url=NULL) {/*{{{*/
|
|
||||||
$this->key = $key;
|
|
||||||
$this->secret = $secret;
|
|
||||||
$this->callback_url = $callback_url;
|
|
||||||
}/*}}}*/
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
class OAuthToken {/*{{{*/
|
|
||||||
// access tokens and request tokens
|
|
||||||
public $key;
|
|
||||||
public $secret;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* key = the token
|
|
||||||
* secret = the token secret
|
|
||||||
*/
|
|
||||||
function __construct($key, $secret) {/*{{{*/
|
|
||||||
$this->key = $key;
|
|
||||||
$this->secret = $secret;
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* generates the basic string serialization of a token that a server
|
|
||||||
* would respond to request_token and access_token calls with
|
|
||||||
*/
|
|
||||||
function to_string() {/*{{{*/
|
|
||||||
return "oauth_token=" . OAuthUtil::urlencodeRFC3986($this->key) .
|
|
||||||
"&oauth_token_secret=" . OAuthUtil::urlencodeRFC3986($this->secret);
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
function __toString() {/*{{{*/
|
|
||||||
return $this->to_string();
|
|
||||||
}/*}}}*/
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
class OAuthSignatureMethod {/*{{{*/
|
|
||||||
public function check_signature(&$request, $consumer, $token, $signature) {
|
|
||||||
$built = $this->build_signature($request, $consumer, $token);
|
|
||||||
return $built == $signature;
|
|
||||||
}
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod {/*{{{*/
|
|
||||||
function get_name() {/*{{{*/
|
|
||||||
return "HMAC-SHA1";
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
public function build_signature($request, $consumer, $token, $privKey=NULL) {/*{{{*/
|
|
||||||
$base_string = $request->get_signature_base_string();
|
|
||||||
$request->base_string = $base_string;
|
|
||||||
|
|
||||||
$key_parts = array(
|
|
||||||
$consumer->secret,
|
|
||||||
($token) ? $token->secret : ""
|
|
||||||
);
|
|
||||||
|
|
||||||
$key_parts = array_map(array('OAuthUtil','urlencodeRFC3986'), $key_parts);
|
|
||||||
$key = implode('&', $key_parts);
|
|
||||||
|
|
||||||
return base64_encode( hash_hmac('sha1', $base_string, $key, true));
|
|
||||||
}/*}}}*/
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod {/*{{{*/
|
|
||||||
public function get_name() {/*{{{*/
|
|
||||||
return "RSA-SHA1";
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
protected function fetch_public_cert(&$request) {/*{{{*/
|
|
||||||
// not implemented yet, ideas are:
|
|
||||||
// (1) do a lookup in a table of trusted certs keyed off of consumer
|
|
||||||
// (2) fetch via http using a url provided by the requester
|
|
||||||
// (3) some sort of specific discovery code based on request
|
|
||||||
//
|
|
||||||
// either way should return a string representation of the certificate
|
|
||||||
throw Exception("fetch_public_cert not implemented");
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
protected function fetch_private_cert($privKey) {//&$request) {/*{{{*/
|
|
||||||
// not implemented yet, ideas are:
|
|
||||||
// (1) do a lookup in a table of trusted certs keyed off of consumer
|
|
||||||
//
|
|
||||||
// either way should return a string representation of the certificate
|
|
||||||
throw Exception("fetch_private_cert not implemented");
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
public function build_signature(&$request, $consumer, $token, $privKey) {/*{{{*/
|
|
||||||
$base_string = $request->get_signature_base_string();
|
|
||||||
|
|
||||||
// Fetch the private key cert based on the request
|
|
||||||
//$cert = $this->fetch_private_cert($consumer->privKey);
|
|
||||||
|
|
||||||
//Pull the private key ID from the certificate
|
|
||||||
//$privatekeyid = openssl_get_privatekey($cert);
|
|
||||||
|
|
||||||
// hacked in
|
|
||||||
if ($privKey == '') {
|
|
||||||
$fp = fopen($GLOBALS['PRIV_KEY_FILE'], "r");
|
|
||||||
$privKey = fread($fp, 8192);
|
|
||||||
fclose($fp);
|
|
||||||
}
|
|
||||||
$privatekeyid = openssl_get_privatekey($privKey);
|
|
||||||
|
|
||||||
//Check the computer signature against the one passed in the query
|
|
||||||
$ok = openssl_sign($base_string, $signature, $privatekeyid);
|
|
||||||
|
|
||||||
//Release the key resource
|
|
||||||
openssl_free_key($privatekeyid);
|
|
||||||
|
|
||||||
return base64_encode($signature);
|
|
||||||
} /*}}}*/
|
|
||||||
|
|
||||||
public function check_signature(&$request, $consumer, $token, $signature) {/*{{{*/
|
|
||||||
$decoded_sig = base64_decode($signature);
|
|
||||||
|
|
||||||
$base_string = $request->get_signature_base_string();
|
|
||||||
|
|
||||||
// Fetch the public key cert based on the request
|
|
||||||
$cert = $this->fetch_public_cert($request);
|
|
||||||
|
|
||||||
//Pull the public key ID from the certificate
|
|
||||||
$publickeyid = openssl_get_publickey($cert);
|
|
||||||
|
|
||||||
//Check the computer signature against the one passed in the query
|
|
||||||
$ok = openssl_verify($base_string, $decoded_sig, $publickeyid);
|
|
||||||
|
|
||||||
//Release the key resource
|
|
||||||
openssl_free_key($publickeyid);
|
|
||||||
|
|
||||||
return $ok == 1;
|
|
||||||
} /*}}}*/
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
class OAuthRequest {/*{{{*/
|
|
||||||
private $parameters;
|
|
||||||
private $http_method;
|
|
||||||
private $http_url;
|
|
||||||
// for debug purposes
|
|
||||||
public $base_string;
|
|
||||||
public static $version = '1.0';
|
|
||||||
|
|
||||||
function __construct($http_method, $http_url, $parameters=NULL) {/*{{{*/
|
|
||||||
@$parameters or $parameters = array();
|
|
||||||
$this->parameters = $parameters;
|
|
||||||
$this->http_method = $http_method;
|
|
||||||
$this->http_url = $http_url;
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* attempt to build up a request from what was passed to the server
|
|
||||||
*/
|
|
||||||
public static function from_request($http_method=NULL, $http_url=NULL, $parameters=NULL) {/*{{{*/
|
|
||||||
$scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") ? 'http' : 'https';
|
|
||||||
@$http_url or $http_url = $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
|
||||||
@$http_method or $http_method = $_SERVER['REQUEST_METHOD'];
|
|
||||||
|
|
||||||
$request_headers = OAuthRequest::get_headers();
|
|
||||||
|
|
||||||
// let the library user override things however they'd like, if they know
|
|
||||||
// which parameters to use then go for it, for example XMLRPC might want to
|
|
||||||
// do this
|
|
||||||
if ($parameters) {
|
|
||||||
$req = new OAuthRequest($http_method, $http_url, $parameters);
|
|
||||||
}
|
|
||||||
// next check for the auth header, we need to do some extra stuff
|
|
||||||
// if that is the case, namely suck in the parameters from GET or POST
|
|
||||||
// so that we can include them in the signature
|
|
||||||
else if (@substr($request_headers['Authorization'], 0, 5) == "OAuth") {
|
|
||||||
$header_parameters = OAuthRequest::split_header($request_headers['Authorization']);
|
|
||||||
if ($http_method == "GET") {
|
|
||||||
$req_parameters = $_GET;
|
|
||||||
}
|
|
||||||
else if ($http_method = "POST") {
|
|
||||||
$req_parameters = $_POST;
|
|
||||||
}
|
|
||||||
$parameters = array_merge($header_parameters, $req_parameters);
|
|
||||||
$req = new OAuthRequest($http_method, $http_url, $parameters);
|
|
||||||
}
|
|
||||||
else if ($http_method == "GET") {
|
|
||||||
$req = new OAuthRequest($http_method, $http_url, $_GET);
|
|
||||||
}
|
|
||||||
else if ($http_method == "POST") {
|
|
||||||
$req = new OAuthRequest($http_method, $http_url, $_POST);
|
|
||||||
}
|
|
||||||
return $req;
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* pretty much a helper function to set up the request
|
|
||||||
*/
|
|
||||||
public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) {/*{{{*/
|
|
||||||
@$parameters or $parameters = array();
|
|
||||||
$defaults = array("oauth_version" => OAuthRequest::$version,
|
|
||||||
"oauth_nonce" => OAuthRequest::generate_nonce(),
|
|
||||||
"oauth_timestamp" => OAuthRequest::generate_timestamp(),
|
|
||||||
"oauth_consumer_key" => $consumer->key);
|
|
||||||
$parameters = array_merge($defaults, $parameters);
|
|
||||||
|
|
||||||
if ($token) {
|
|
||||||
$parameters['oauth_token'] = $token->key;
|
|
||||||
}
|
|
||||||
|
|
||||||
// oauth v1.0a
|
|
||||||
/*if (isset($_REQUEST['oauth_verifier'])) {
|
|
||||||
$parameters['oauth_verifier'] = $_REQUEST['oauth_verifier'];
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
return new OAuthRequest($http_method, $http_url, $parameters);
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
public function set_parameter($name, $value) {/*{{{*/
|
|
||||||
$this->parameters[$name] = $value;
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
public function get_parameter($name) {/*{{{*/
|
|
||||||
return $this->parameters[$name];
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
public function get_parameters() {/*{{{*/
|
|
||||||
return $this->parameters;
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the normalized parameters of the request
|
|
||||||
*
|
|
||||||
* This will be all (except oauth_signature) parameters,
|
|
||||||
* sorted first by key, and if duplicate keys, then by
|
|
||||||
* value.
|
|
||||||
*
|
|
||||||
* The returned string will be all the key=value pairs
|
|
||||||
* concated by &.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function get_signable_parameters() {/*{{{*/
|
|
||||||
// Grab all parameters
|
|
||||||
$params = $this->parameters;
|
|
||||||
|
|
||||||
// Remove oauth_signature if present
|
|
||||||
if (isset($params['oauth_signature'])) {
|
|
||||||
unset($params['oauth_signature']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Urlencode both keys and values
|
|
||||||
$keys = array_map(array('OAuthUtil', 'urlencodeRFC3986'), array_keys($params));
|
|
||||||
$values = array_map(array('OAuthUtil', 'urlencodeRFC3986'), array_values($params));
|
|
||||||
$params = array_combine($keys, $values);
|
|
||||||
|
|
||||||
// Sort by keys (natsort)
|
|
||||||
uksort($params, 'strnatcmp');
|
|
||||||
|
|
||||||
if(isset($params['title']) && isset($params['title-exact'])) {
|
|
||||||
$temp = $params['title-exact'];
|
|
||||||
$title = $params['title'];
|
|
||||||
|
|
||||||
unset($params['title']);
|
|
||||||
unset($params['title-exact']);
|
|
||||||
|
|
||||||
$params['title-exact'] = $temp;
|
|
||||||
$params['title'] = $title;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate key=value pairs
|
|
||||||
$pairs = array();
|
|
||||||
foreach ($params as $key=>$value ) {
|
|
||||||
if (is_array($value)) {
|
|
||||||
// If the value is an array, it's because there are multiple
|
|
||||||
// with the same key, sort them, then add all the pairs
|
|
||||||
natsort($value);
|
|
||||||
foreach ($value as $v2) {
|
|
||||||
$pairs[] = $key . '=' . $v2;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$pairs[] = $key . '=' . $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the pairs, concated with &
|
|
||||||
return implode('&', $pairs);
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the base string of this request
|
|
||||||
*
|
|
||||||
* The base string defined as the method, the url
|
|
||||||
* and the parameters (normalized), each urlencoded
|
|
||||||
* and the concated with &.
|
|
||||||
*/
|
|
||||||
public function get_signature_base_string() {/*{{{*/
|
|
||||||
$parts = array(
|
|
||||||
$this->get_normalized_http_method(),
|
|
||||||
$this->get_normalized_http_url(),
|
|
||||||
$this->get_signable_parameters()
|
|
||||||
);
|
|
||||||
|
|
||||||
$parts = array_map(array('OAuthUtil', 'urlencodeRFC3986'), $parts);
|
|
||||||
|
|
||||||
return implode('&', $parts);
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* just uppercases the http method
|
|
||||||
*/
|
|
||||||
public function get_normalized_http_method() {/*{{{*/
|
|
||||||
return strtoupper($this->http_method);
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* parses the url and rebuilds it to be
|
|
||||||
* scheme://host/path
|
|
||||||
*/
|
|
||||||
public function get_normalized_http_url() {
|
|
||||||
$parts = parse_url($this->http_url);
|
|
||||||
|
|
||||||
$scheme = (isset($parts['scheme'])) ? $parts['scheme'] : 'http';
|
|
||||||
$port = (isset($parts['port'])) ? $parts['port'] : (($scheme == 'https') ? '443' : '80');
|
|
||||||
$host = (isset($parts['host'])) ? strtolower($parts['host']) : '';
|
|
||||||
$path = (isset($parts['path'])) ? $parts['path'] : '';
|
|
||||||
|
|
||||||
if (($scheme == 'https' && $port != '443')
|
|
||||||
|| ($scheme == 'http' && $port != '80')) {
|
|
||||||
$host = "$host:$port";
|
|
||||||
}
|
|
||||||
return "$scheme://$host$path";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* builds a url usable for a GET request
|
|
||||||
*/
|
|
||||||
public function to_url() {/*{{{*/
|
|
||||||
$out = $this->get_normalized_http_url() . "?";
|
|
||||||
$out .= $this->to_postdata();
|
|
||||||
return $out;
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* builds the data one would send in a POST request
|
|
||||||
*/
|
|
||||||
public function to_postdata() {/*{{{*/
|
|
||||||
$total = array();
|
|
||||||
foreach ($this->parameters as $k => $v) {
|
|
||||||
$total[] = OAuthUtil::urlencodeRFC3986($k) . "=" . OAuthUtil::urlencodeRFC3986($v);
|
|
||||||
}
|
|
||||||
$out = implode("&", $total);
|
|
||||||
return $out;
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* builds the Authorization: header
|
|
||||||
*/
|
|
||||||
public function to_header() {/*{{{*/
|
|
||||||
$out ='Authorization: OAuth ';
|
|
||||||
$total = array();
|
|
||||||
|
|
||||||
/*
|
|
||||||
$sig = $this->parameters['oauth_signature'];
|
|
||||||
unset($this->parameters['oauth_signature']);
|
|
||||||
uksort($this->parameters, 'strnatcmp');
|
|
||||||
$this->parameters['oauth_signature'] = $sig;
|
|
||||||
*/
|
|
||||||
|
|
||||||
foreach ($this->parameters as $k => $v) {
|
|
||||||
if (substr($k, 0, 5) != "oauth") continue;
|
|
||||||
$out .= OAuthUtil::urlencodeRFC3986($k) . '="' . OAuthUtil::urlencodeRFC3986($v) . '", ';
|
|
||||||
}
|
|
||||||
$out = substr_replace($out, '', strlen($out) - 2);
|
|
||||||
|
|
||||||
return $out;
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
public function __toString() {/*{{{*/
|
|
||||||
return $this->to_url();
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
|
|
||||||
public function sign_request($signature_method, $consumer, $token, $privKey=NULL) {/*{{{*/
|
|
||||||
$this->set_parameter("oauth_signature_method", $signature_method->get_name());
|
|
||||||
$signature = $this->build_signature($signature_method, $consumer, $token, $privKey);
|
|
||||||
$this->set_parameter("oauth_signature", $signature);
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
public function build_signature($signature_method, $consumer, $token, $privKey=NULL) {/*{{{*/
|
|
||||||
$signature = $signature_method->build_signature($this, $consumer, $token, $privKey);
|
|
||||||
return $signature;
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* util function: current timestamp
|
|
||||||
*/
|
|
||||||
private static function generate_timestamp() {/*{{{*/
|
|
||||||
return time();
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* util function: current nonce
|
|
||||||
*/
|
|
||||||
private static function generate_nonce() {/*{{{*/
|
|
||||||
$mt = microtime();
|
|
||||||
$rand = mt_rand();
|
|
||||||
|
|
||||||
return md5($mt . $rand); // md5s look nicer than numbers
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* util function for turning the Authorization: header into
|
|
||||||
* parameters, has to do some unescaping
|
|
||||||
*/
|
|
||||||
private static function split_header($header) {/*{{{*/
|
|
||||||
// this should be a regex
|
|
||||||
// error cases: commas in parameter values
|
|
||||||
$parts = explode(",", $header);
|
|
||||||
$out = array();
|
|
||||||
foreach ($parts as $param) {
|
|
||||||
$param = ltrim($param);
|
|
||||||
// skip the "realm" param, nobody ever uses it anyway
|
|
||||||
if (substr($param, 0, 5) != "oauth") continue;
|
|
||||||
|
|
||||||
$param_parts = explode("=", $param);
|
|
||||||
|
|
||||||
// rawurldecode() used because urldecode() will turn a "+" in the
|
|
||||||
// value into a space
|
|
||||||
$out[$param_parts[0]] = rawurldecode(substr($param_parts[1], 1, -1));
|
|
||||||
}
|
|
||||||
return $out;
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* helper to try to sort out headers for people who aren't running apache
|
|
||||||
*/
|
|
||||||
private static function get_headers() {/*{{{*/
|
|
||||||
if (function_exists('apache_request_headers')) {
|
|
||||||
// we need this to get the actual Authorization: header
|
|
||||||
// because apache tends to tell us it doesn't exist
|
|
||||||
return apache_request_headers();
|
|
||||||
}
|
|
||||||
// otherwise we don't have apache and are just going to have to hope
|
|
||||||
// that $_SERVER actually contains what we need
|
|
||||||
$out = array();
|
|
||||||
foreach ($_SERVER as $key => $value) {
|
|
||||||
if (substr($key, 0, 5) == "HTTP_") {
|
|
||||||
// this is chaos, basically it is just there to capitalize the first
|
|
||||||
// letter of every word that is not an initial HTTP and strip HTTP
|
|
||||||
// code from przemek
|
|
||||||
$key = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5)))));
|
|
||||||
$out[$key] = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $out;
|
|
||||||
}/*}}}*/
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
class OAuthServer {/*{{{*/
|
|
||||||
protected $timestamp_threshold = 300; // in seconds, five minutes
|
|
||||||
protected $version = 1.0; // hi blaine
|
|
||||||
protected $signature_methods = array();
|
|
||||||
|
|
||||||
protected $data_store;
|
|
||||||
|
|
||||||
function __construct($data_store) {/*{{{*/
|
|
||||||
$this->data_store = $data_store;
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
public function add_signature_method($signature_method) {/*{{{*/
|
|
||||||
$this->signature_methods[$signature_method->get_name()] =
|
|
||||||
$signature_method;
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
// high level functions
|
|
||||||
|
|
||||||
/**
|
|
||||||
* process a request_token request
|
|
||||||
* returns the request token on success
|
|
||||||
*/
|
|
||||||
public function fetch_request_token(&$request) {/*{{{*/
|
|
||||||
$this->get_version($request);
|
|
||||||
|
|
||||||
$consumer = $this->get_consumer($request);
|
|
||||||
|
|
||||||
// no token required for the initial token request
|
|
||||||
$token = NULL;
|
|
||||||
|
|
||||||
$this->check_signature($request, $consumer, $token);
|
|
||||||
|
|
||||||
$new_token = $this->data_store->new_request_token($consumer);
|
|
||||||
|
|
||||||
return $new_token;
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* process an access_token request
|
|
||||||
* returns the access token on success
|
|
||||||
*/
|
|
||||||
public function fetch_access_token(&$request) {/*{{{*/
|
|
||||||
$this->get_version($request);
|
|
||||||
|
|
||||||
$consumer = $this->get_consumer($request);
|
|
||||||
|
|
||||||
// requires authorized request token
|
|
||||||
$token = $this->get_token($request, $consumer, "request");
|
|
||||||
|
|
||||||
$this->check_signature($request, $consumer, $token);
|
|
||||||
|
|
||||||
$new_token = $this->data_store->new_access_token($token, $consumer);
|
|
||||||
|
|
||||||
return $new_token;
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* verify an api call, checks all the parameters
|
|
||||||
*/
|
|
||||||
public function verify_request(&$request) {/*{{{*/
|
|
||||||
$this->get_version($request);
|
|
||||||
$consumer = $this->get_consumer($request);
|
|
||||||
$token = $this->get_token($request, $consumer, "access");
|
|
||||||
$this->check_signature($request, $consumer, $token);
|
|
||||||
return array($consumer, $token);
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
// Internals from here
|
|
||||||
/**
|
|
||||||
* version 1
|
|
||||||
*/
|
|
||||||
private function get_version(&$request) {/*{{{*/
|
|
||||||
$version = $request->get_parameter("oauth_version");
|
|
||||||
if (!$version) {
|
|
||||||
$version = 1.0;
|
|
||||||
}
|
|
||||||
if ($version && $version != $this->version) {
|
|
||||||
throw new OAuthException("OAuth version '$version' not supported");
|
|
||||||
}
|
|
||||||
return $version;
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* figure out the signature with some defaults
|
|
||||||
*/
|
|
||||||
private function get_signature_method(&$request) {/*{{{*/
|
|
||||||
$signature_method =
|
|
||||||
@$request->get_parameter("oauth_signature_method");
|
|
||||||
if (!$signature_method) {
|
|
||||||
$signature_method = "PLAINTEXT";
|
|
||||||
}
|
|
||||||
if (!in_array($signature_method,
|
|
||||||
array_keys($this->signature_methods))) {
|
|
||||||
throw new OAuthException(
|
|
||||||
"Signature method '$signature_method' not supported try one of the following: " . implode(", ", array_keys($this->signature_methods))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return $this->signature_methods[$signature_method];
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* try to find the consumer for the provided request's consumer key
|
|
||||||
*/
|
|
||||||
private function get_consumer(&$request) {/*{{{*/
|
|
||||||
$consumer_key = @$request->get_parameter("oauth_consumer_key");
|
|
||||||
if (!$consumer_key) {
|
|
||||||
throw new OAuthException("Invalid consumer key");
|
|
||||||
}
|
|
||||||
|
|
||||||
$consumer = $this->data_store->lookup_consumer($consumer_key);
|
|
||||||
if (!$consumer) {
|
|
||||||
throw new OAuthException("Invalid consumer");
|
|
||||||
}
|
|
||||||
|
|
||||||
return $consumer;
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* try to find the token for the provided request's token key
|
|
||||||
*/
|
|
||||||
private function get_token(&$request, $consumer, $token_type="access") {/*{{{*/
|
|
||||||
$token_field = @$request->get_parameter('oauth_token');
|
|
||||||
$token = $this->data_store->lookup_token(
|
|
||||||
$consumer, $token_type, $token_field
|
|
||||||
);
|
|
||||||
if (!$token) {
|
|
||||||
throw new OAuthException("Invalid $token_type token: $token_field");
|
|
||||||
}
|
|
||||||
return $token;
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* all-in-one function to check the signature on a request
|
|
||||||
* should guess the signature method appropriately
|
|
||||||
*/
|
|
||||||
private function check_signature(&$request, $consumer, $token) {/*{{{*/
|
|
||||||
// this should probably be in a different method
|
|
||||||
$timestamp = @$request->get_parameter('oauth_timestamp');
|
|
||||||
$nonce = @$request->get_parameter('oauth_nonce');
|
|
||||||
|
|
||||||
$this->check_timestamp($timestamp);
|
|
||||||
$this->check_nonce($consumer, $token, $nonce, $timestamp);
|
|
||||||
|
|
||||||
$signature_method = $this->get_signature_method($request);
|
|
||||||
|
|
||||||
$signature = $request->get_parameter('oauth_signature');
|
|
||||||
$valid_sig = $signature_method->check_signature(
|
|
||||||
$request,
|
|
||||||
$consumer,
|
|
||||||
$token,
|
|
||||||
$signature
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!$valid_sig) {
|
|
||||||
throw new OAuthException("Invalid signature");
|
|
||||||
}
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* check that the timestamp is new enough
|
|
||||||
*/
|
|
||||||
private function check_timestamp($timestamp) {/*{{{*/
|
|
||||||
// verify that timestamp is recentish
|
|
||||||
$now = time();
|
|
||||||
if ($now - $timestamp > $this->timestamp_threshold) {
|
|
||||||
throw new OAuthException("Expired timestamp, yours $timestamp, ours $now");
|
|
||||||
}
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* check that the nonce is not repeated
|
|
||||||
*/
|
|
||||||
private function check_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/
|
|
||||||
// verify that the nonce is uniqueish
|
|
||||||
$found = $this->data_store->lookup_nonce($consumer, $token, $nonce, $timestamp);
|
|
||||||
if ($found) {
|
|
||||||
throw new OAuthException("Nonce already used: $nonce");
|
|
||||||
}
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
class OAuthDataStore {/*{{{*/
|
|
||||||
function lookup_consumer($consumer_key) {/*{{{*/
|
|
||||||
// implement me
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
function lookup_token($consumer, $token_type, $token) {/*{{{*/
|
|
||||||
// implement me
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
function lookup_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/
|
|
||||||
// implement me
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
function fetch_request_token($consumer) {/*{{{*/
|
|
||||||
// return a new token attached to this consumer
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
function fetch_access_token($token, $consumer) {/*{{{*/
|
|
||||||
// return a new access token attached to this consumer
|
|
||||||
// for the user associated with this token if the request token
|
|
||||||
// is authorized
|
|
||||||
// should also invalidate the request token
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
|
|
||||||
/* A very naive dbm-based oauth storage
|
|
||||||
*/
|
|
||||||
class SimpleOAuthDataStore extends OAuthDataStore {/*{{{*/
|
|
||||||
private $dbh;
|
|
||||||
|
|
||||||
function __construct($path = "oauth.gdbm") {/*{{{*/
|
|
||||||
$this->dbh = dba_popen($path, 'c', 'gdbm');
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
function __destruct() {/*{{{*/
|
|
||||||
dba_close($this->dbh);
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
function lookup_consumer($consumer_key) {/*{{{*/
|
|
||||||
$rv = dba_fetch("consumer_$consumer_key", $this->dbh);
|
|
||||||
if ($rv === FALSE) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
$obj = unserialize($rv);
|
|
||||||
if (!($obj instanceof OAuthConsumer)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return $obj;
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
function lookup_token($consumer, $token_type, $token) {/*{{{*/
|
|
||||||
$rv = dba_fetch("${token_type}_${token}", $this->dbh);
|
|
||||||
if ($rv === FALSE) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
$obj = unserialize($rv);
|
|
||||||
if (!($obj instanceof OAuthToken)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return $obj;
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
function lookup_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/
|
|
||||||
return dba_exists("nonce_$nonce", $this->dbh);
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
function new_token($consumer, $type="request") {/*{{{*/
|
|
||||||
$key = md5(time());
|
|
||||||
$secret = time() + time();
|
|
||||||
$token = new OAuthToken($key, md5(md5($secret)));
|
|
||||||
if (!dba_insert("${type}_$key", serialize($token), $this->dbh)) {
|
|
||||||
throw new OAuthException("doooom!");
|
|
||||||
}
|
|
||||||
return $token;
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
function new_request_token($consumer) {/*{{{*/
|
|
||||||
return $this->new_token($consumer, "request");
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
function new_access_token($token, $consumer) {/*{{{*/
|
|
||||||
|
|
||||||
$token = $this->new_token($consumer, 'access');
|
|
||||||
dba_delete("request_" . $token->key, $this->dbh);
|
|
||||||
return $token;
|
|
||||||
}/*}}}*/
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
class OAuthUtil {/*{{{*/
|
|
||||||
public static function urlencodeRFC3986($string) {/*{{{*/
|
|
||||||
return str_replace('%7E', '~', rawurlencode($string));
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
public static function urldecodeRFC3986($string) {/*{{{*/
|
|
||||||
return rawurldecode($string);
|
|
||||||
}/*}}}*/
|
|
||||||
}/*}}}*/
|
|
||||||
|
|
||||||
?>
|
|
|
@ -1,185 +0,0 @@
|
||||||
<?php
|
|
||||||
/* Copyright (c) 2009 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Author: Eric Bidelman <e.bidelman@google.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
$PRIV_KEY_FILE = '/path/to/your/rsa_private_key.pem';
|
|
||||||
|
|
||||||
// OAuth library - http://oauth.googlecode.com/svn/code/php/
|
|
||||||
require_once('OAuth.php');
|
|
||||||
|
|
||||||
// Google's accepted signature methods
|
|
||||||
$hmac_method = new OAuthSignatureMethod_HMAC_SHA1();
|
|
||||||
$rsa_method = new OAuthSignatureMethod_RSA_SHA1();
|
|
||||||
$SIG_METHODS = array($rsa_method->get_name() => $rsa_method,
|
|
||||||
$hmac_method->get_name() => $hmac_method);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes an HTTP request to the specified URL
|
|
||||||
*
|
|
||||||
* @param string $http_method The HTTP method (GET, POST, PUT, DELETE)
|
|
||||||
* @param string $url Full URL of the resource to access
|
|
||||||
* @param array $extraHeaders (optional) Additional headers to include in each
|
|
||||||
* request. Elements are header/value pair strings ('Host: example.com')
|
|
||||||
* @param string $postData (optional) POST/PUT request body
|
|
||||||
* @param bool $returnResponseHeaders True if resp. headers should be returned.
|
|
||||||
* @return string Response body from the server
|
|
||||||
*/
|
|
||||||
function send_signed_request($http_method, $url, $extraHeaders=null,
|
|
||||||
$postData=null, $returnResponseHeaders=true) {
|
|
||||||
$curl = curl_init($url);
|
|
||||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
|
||||||
curl_setopt($curl, CURLOPT_FAILONERROR, false);
|
|
||||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
|
|
||||||
|
|
||||||
// Return request headers in the reponse
|
|
||||||
// curl_setopt($curl, CURLINFO_HEADER_OUT, true);
|
|
||||||
|
|
||||||
// Return response headers ni the response?
|
|
||||||
if ($returnResponseHeaders) {
|
|
||||||
curl_setopt($curl, CURLOPT_HEADER, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
$headers = array();
|
|
||||||
//$headers[] = 'GData-Version: 2.0'; // use GData v2 by default
|
|
||||||
if (is_array($extraHeaders)) {
|
|
||||||
$headers = array_merge($headers, $extraHeaders);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup default curl options for each type of HTTP request.
|
|
||||||
// This is also a great place to add additional headers for each request.
|
|
||||||
switch($http_method) {
|
|
||||||
case 'GET':
|
|
||||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
|
||||||
break;
|
|
||||||
case 'POST':
|
|
||||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
|
||||||
curl_setopt($curl, CURLOPT_POST, 1);
|
|
||||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
|
|
||||||
break;
|
|
||||||
case 'PUT':
|
|
||||||
$headers[] = 'If-Match: *';
|
|
||||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
|
||||||
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $http_method);
|
|
||||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
|
|
||||||
break;
|
|
||||||
case 'DELETE':
|
|
||||||
$headers[] = 'If-Match: *';
|
|
||||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
|
||||||
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $http_method);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute the request. If an error occures, fill the response body with it.
|
|
||||||
$response = curl_exec($curl);
|
|
||||||
if (!$response) {
|
|
||||||
$response = curl_error($curl);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add server's response headers to our response body
|
|
||||||
$response = curl_getinfo($curl, CURLINFO_HEADER_OUT) . $response;
|
|
||||||
|
|
||||||
curl_close($curl);
|
|
||||||
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes XML as a string and returns it nicely indented
|
|
||||||
*
|
|
||||||
* @param string $xml The xml to beautify
|
|
||||||
* @param boolean $html_output True if returned XML should be escaped for HTML.
|
|
||||||
* @return string The beautified xml
|
|
||||||
*/
|
|
||||||
function xml_pretty_printer($xml, $html_output=false) {
|
|
||||||
$xml_obj = new SimpleXMLElement($xml);
|
|
||||||
$level = 2;
|
|
||||||
|
|
||||||
// Get an array containing each XML element
|
|
||||||
$xml = explode("\n", preg_replace('/>\s*</', ">\n<", $xml_obj->asXML()));
|
|
||||||
|
|
||||||
// Hold current indentation level
|
|
||||||
$indent = 0;
|
|
||||||
|
|
||||||
$pretty = array();
|
|
||||||
|
|
||||||
// Shift off opening XML tag if present
|
|
||||||
if (count($xml) && preg_match('/^<\?\s*xml/', $xml[0])) {
|
|
||||||
$pretty[] = array_shift($xml);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($xml as $el) {
|
|
||||||
if (preg_match('/^<([\w])+[^>\/]*>$/U', $el)) {
|
|
||||||
// opening tag, increase indent
|
|
||||||
$pretty[] = str_repeat(' ', $indent) . $el;
|
|
||||||
$indent += $level;
|
|
||||||
} else {
|
|
||||||
if (preg_match('/^<\/.+>$/', $el)) {
|
|
||||||
$indent -= $level; // closing tag, decrease indent
|
|
||||||
}
|
|
||||||
if ($indent < 0) {
|
|
||||||
$indent += $level;
|
|
||||||
}
|
|
||||||
$pretty[] = str_repeat(' ', $indent) . $el;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$xml = implode("\n", $pretty);
|
|
||||||
return $html_output ? htmlentities($xml) : $xml;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Joins key/value pairs by $inner_glue and each pair together by $outer_glue.
|
|
||||||
*
|
|
||||||
* Example: implode_assoc('=', '&', array('a' => 1, 'b' => 2)) === 'a=1&b=2'
|
|
||||||
*
|
|
||||||
* @param string $inner_glue What to implode each key/value pair with
|
|
||||||
* @param string $outer_glue What to impode each key/value string subset with
|
|
||||||
* @param array $array Associative array of query parameters
|
|
||||||
* @return string Urlencoded string of query parameters
|
|
||||||
*/
|
|
||||||
function implode_assoc($inner_glue, $outer_glue, $array) {
|
|
||||||
$output = array();
|
|
||||||
foreach($array as $key => $item) {
|
|
||||||
$output[] = $key . $inner_glue . urlencode($item);
|
|
||||||
}
|
|
||||||
return implode($outer_glue, $output);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Explodes a string of key/value url parameters into an associative array.
|
|
||||||
* This method performs the compliment operations of implode_assoc().
|
|
||||||
*
|
|
||||||
* Example: explode_assoc('=', '&', 'a=1&b=2') === array('a' => 1, 'b' => 2)
|
|
||||||
*
|
|
||||||
* @param string $inner_glue What each key/value pair is joined with
|
|
||||||
* @param string $outer_glue What each set of key/value pairs is joined with.
|
|
||||||
* @param array $array Associative array of query parameters
|
|
||||||
* @return array Urlencoded string of query parameters
|
|
||||||
*/
|
|
||||||
function explode_assoc($inner_glue, $outer_glue, $params) {
|
|
||||||
$tempArr = explode($outer_glue, $params);
|
|
||||||
foreach($tempArr as $val) {
|
|
||||||
$pos = strpos($val, $inner_glue);
|
|
||||||
$key = substr($val, 0, $pos);
|
|
||||||
$array2[$key] = substr($val, $pos + 1, strlen($val));
|
|
||||||
}
|
|
||||||
return $array2;
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,183 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Lukas Smith <smith@pooteeweet.org> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Several methods to convert the MDB2 native timestamp format (ISO based)
|
|
||||||
* to and from data structures that are convenient to worth with in side of php.
|
|
||||||
* For more complex date arithmetic please take a look at the Date package in PEAR
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
class MDB2_Date
|
|
||||||
{
|
|
||||||
// {{{ mdbNow()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return the current datetime
|
|
||||||
*
|
|
||||||
* @return string current datetime in the MDB2 format
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function mdbNow()
|
|
||||||
{
|
|
||||||
return date('Y-m-d H:i:s');
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ mdbToday()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return the current date
|
|
||||||
*
|
|
||||||
* @return string current date in the MDB2 format
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function mdbToday()
|
|
||||||
{
|
|
||||||
return date('Y-m-d');
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ mdbTime()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return the current time
|
|
||||||
*
|
|
||||||
* @return string current time in the MDB2 format
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function mdbTime()
|
|
||||||
{
|
|
||||||
return date('H:i:s');
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ date2Mdbstamp()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* convert a date into a MDB2 timestamp
|
|
||||||
*
|
|
||||||
* @param int hour of the date
|
|
||||||
* @param int minute of the date
|
|
||||||
* @param int second of the date
|
|
||||||
* @param int month of the date
|
|
||||||
* @param int day of the date
|
|
||||||
* @param int year of the date
|
|
||||||
*
|
|
||||||
* @return string a valid MDB2 timestamp
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function date2Mdbstamp($hour = null, $minute = null, $second = null,
|
|
||||||
$month = null, $day = null, $year = null)
|
|
||||||
{
|
|
||||||
return MDB2_Date::unix2Mdbstamp(mktime($hour, $minute, $second, $month, $day, $year, -1));
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ unix2Mdbstamp()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* convert a unix timestamp into a MDB2 timestamp
|
|
||||||
*
|
|
||||||
* @param int a valid unix timestamp
|
|
||||||
*
|
|
||||||
* @return string a valid MDB2 timestamp
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function unix2Mdbstamp($unix_timestamp)
|
|
||||||
{
|
|
||||||
return date('Y-m-d H:i:s', $unix_timestamp);
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ mdbstamp2Unix()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* convert a MDB2 timestamp into a unix timestamp
|
|
||||||
*
|
|
||||||
* @param int a valid MDB2 timestamp
|
|
||||||
* @return string unix timestamp with the time stored in the MDB2 format
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function mdbstamp2Unix($mdb_timestamp)
|
|
||||||
{
|
|
||||||
$arr = MDB2_Date::mdbstamp2Date($mdb_timestamp);
|
|
||||||
|
|
||||||
return mktime($arr['hour'], $arr['minute'], $arr['second'], $arr['month'], $arr['day'], $arr['year'], -1);
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ mdbstamp2Date()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* convert a MDB2 timestamp into an array containing all
|
|
||||||
* values necessary to pass to php's date() function
|
|
||||||
*
|
|
||||||
* @param int a valid MDB2 timestamp
|
|
||||||
*
|
|
||||||
* @return array with the time split
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function mdbstamp2Date($mdb_timestamp)
|
|
||||||
{
|
|
||||||
list($arr['year'], $arr['month'], $arr['day'], $arr['hour'], $arr['minute'], $arr['second']) =
|
|
||||||
sscanf($mdb_timestamp, "%04u-%02u-%02u %02u:%02u:%02u");
|
|
||||||
return $arr;
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,602 +0,0 @@
|
||||||
<?php
|
|
||||||
// vim: set et ts=4 sw=4 fdm=marker:
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Lukas Smith <smith@pooteeweet.org> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
|
|
||||||
require_once 'MDB2/Driver/Datatype/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MDB2 MySQL driver
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
class MDB2_Driver_Datatype_mysql extends MDB2_Driver_Datatype_Common
|
|
||||||
{
|
|
||||||
// {{{ _getCharsetFieldDeclaration()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain DBMS specific SQL code portion needed to set the CHARACTER SET
|
|
||||||
* of a field declaration to be used in statements like CREATE TABLE.
|
|
||||||
*
|
|
||||||
* @param string $charset name of the charset
|
|
||||||
* @return string DBMS specific SQL code portion needed to set the CHARACTER SET
|
|
||||||
* of a field declaration.
|
|
||||||
*/
|
|
||||||
function _getCharsetFieldDeclaration($charset)
|
|
||||||
{
|
|
||||||
return 'CHARACTER SET '.$charset;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _getCollationFieldDeclaration()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain DBMS specific SQL code portion needed to set the COLLATION
|
|
||||||
* of a field declaration to be used in statements like CREATE TABLE.
|
|
||||||
*
|
|
||||||
* @param string $collation name of the collation
|
|
||||||
* @return string DBMS specific SQL code portion needed to set the COLLATION
|
|
||||||
* of a field declaration.
|
|
||||||
*/
|
|
||||||
function _getCollationFieldDeclaration($collation)
|
|
||||||
{
|
|
||||||
return 'COLLATE '.$collation;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getDeclaration()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain DBMS specific SQL code portion needed to declare
|
|
||||||
* of the given type
|
|
||||||
*
|
|
||||||
* @param string $type type to which the value should be converted to
|
|
||||||
* @param string $name name the field to be declared.
|
|
||||||
* @param string $field definition of the field
|
|
||||||
*
|
|
||||||
* @return string DBMS-specific SQL code portion that should be used to
|
|
||||||
* declare the specified field.
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getDeclaration($type, $name, $field)
|
|
||||||
{
|
|
||||||
// MySQL DDL syntax forbids combining NOT NULL with DEFAULT NULL.
|
|
||||||
// To get a default of NULL for NOT NULL columns, omit it.
|
|
||||||
if ( isset($field['notnull'])
|
|
||||||
&& !empty($field['notnull'])
|
|
||||||
&& array_key_exists('default', $field) // do not use isset() here!
|
|
||||||
&& null === $field['default']
|
|
||||||
) {
|
|
||||||
unset($field['default']);
|
|
||||||
}
|
|
||||||
return parent::getDeclaration($type, $name, $field);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getTypeDeclaration()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain DBMS specific SQL code portion needed to declare an text type
|
|
||||||
* field to be used in statements like CREATE TABLE.
|
|
||||||
*
|
|
||||||
* @param array $field associative array with the name of the properties
|
|
||||||
* of the field being declared as array indexes. Currently, the types
|
|
||||||
* of supported field properties are as follows:
|
|
||||||
*
|
|
||||||
* length
|
|
||||||
* Integer value that determines the maximum length of the text
|
|
||||||
* field. If this argument is missing the field should be
|
|
||||||
* declared to have the longest length allowed by the DBMS.
|
|
||||||
*
|
|
||||||
* default
|
|
||||||
* Text value to be used as default for this field.
|
|
||||||
*
|
|
||||||
* notnull
|
|
||||||
* Boolean flag that indicates whether this field is constrained
|
|
||||||
* to not be set to null.
|
|
||||||
* @return string DBMS specific SQL code portion that should be used to
|
|
||||||
* declare the specified field.
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTypeDeclaration($field)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($field['type']) {
|
|
||||||
case 'text':
|
|
||||||
if (empty($field['length']) && array_key_exists('default', $field)) {
|
|
||||||
$field['length'] = $db->varchar_max_length;
|
|
||||||
}
|
|
||||||
$length = !empty($field['length']) ? $field['length'] : false;
|
|
||||||
$fixed = !empty($field['fixed']) ? $field['fixed'] : false;
|
|
||||||
return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR(255)')
|
|
||||||
: ($length ? 'VARCHAR('.$length.')' : 'TEXT');
|
|
||||||
case 'clob':
|
|
||||||
if (!empty($field['length'])) {
|
|
||||||
$length = $field['length'];
|
|
||||||
if ($length <= 255) {
|
|
||||||
return 'TINYTEXT';
|
|
||||||
} elseif ($length <= 65532) {
|
|
||||||
return 'TEXT';
|
|
||||||
} elseif ($length <= 16777215) {
|
|
||||||
return 'MEDIUMTEXT';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 'LONGTEXT';
|
|
||||||
case 'blob':
|
|
||||||
if (!empty($field['length'])) {
|
|
||||||
$length = $field['length'];
|
|
||||||
if ($length <= 255) {
|
|
||||||
return 'TINYBLOB';
|
|
||||||
} elseif ($length <= 65532) {
|
|
||||||
return 'BLOB';
|
|
||||||
} elseif ($length <= 16777215) {
|
|
||||||
return 'MEDIUMBLOB';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 'LONGBLOB';
|
|
||||||
case 'integer':
|
|
||||||
if (!empty($field['length'])) {
|
|
||||||
$length = $field['length'];
|
|
||||||
if ($length <= 1) {
|
|
||||||
return 'TINYINT';
|
|
||||||
} elseif ($length == 2) {
|
|
||||||
return 'SMALLINT';
|
|
||||||
} elseif ($length == 3) {
|
|
||||||
return 'MEDIUMINT';
|
|
||||||
} elseif ($length == 4) {
|
|
||||||
return 'INT';
|
|
||||||
} elseif ($length > 4) {
|
|
||||||
return 'BIGINT';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 'INT';
|
|
||||||
case 'boolean':
|
|
||||||
return 'TINYINT(1)';
|
|
||||||
case 'date':
|
|
||||||
return 'DATE';
|
|
||||||
case 'time':
|
|
||||||
return 'TIME';
|
|
||||||
case 'timestamp':
|
|
||||||
return 'DATETIME';
|
|
||||||
case 'float':
|
|
||||||
$l = '';
|
|
||||||
if (!empty($field['length'])) {
|
|
||||||
$l = '(' . $field['length'];
|
|
||||||
if (!empty($field['scale'])) {
|
|
||||||
$l .= ',' . $field['scale'];
|
|
||||||
}
|
|
||||||
$l .= ')';
|
|
||||||
}
|
|
||||||
return 'DOUBLE' . $l;
|
|
||||||
case 'decimal':
|
|
||||||
$length = !empty($field['length']) ? $field['length'] : 18;
|
|
||||||
$scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
|
|
||||||
return 'DECIMAL('.$length.','.$scale.')';
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _getIntegerDeclaration()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain DBMS specific SQL code portion needed to declare an integer type
|
|
||||||
* field to be used in statements like CREATE TABLE.
|
|
||||||
*
|
|
||||||
* @param string $name name the field to be declared.
|
|
||||||
* @param string $field associative array with the name of the properties
|
|
||||||
* of the field being declared as array indexes.
|
|
||||||
* Currently, the types of supported field
|
|
||||||
* properties are as follows:
|
|
||||||
*
|
|
||||||
* unsigned
|
|
||||||
* Boolean flag that indicates whether the field
|
|
||||||
* should be declared as unsigned integer if
|
|
||||||
* possible.
|
|
||||||
*
|
|
||||||
* default
|
|
||||||
* Integer value to be used as default for this
|
|
||||||
* field.
|
|
||||||
*
|
|
||||||
* notnull
|
|
||||||
* Boolean flag that indicates whether this field is
|
|
||||||
* constrained to not be set to null.
|
|
||||||
* @return string DBMS specific SQL code portion that should be used to
|
|
||||||
* declare the specified field.
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
function _getIntegerDeclaration($name, $field)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$default = $autoinc = '';
|
|
||||||
if (!empty($field['autoincrement'])) {
|
|
||||||
$autoinc = ' AUTO_INCREMENT PRIMARY KEY';
|
|
||||||
} elseif (array_key_exists('default', $field)) {
|
|
||||||
if ($field['default'] === '') {
|
|
||||||
$field['default'] = empty($field['notnull']) ? null : 0;
|
|
||||||
}
|
|
||||||
$default = ' DEFAULT '.$this->quote($field['default'], 'integer');
|
|
||||||
}
|
|
||||||
|
|
||||||
$notnull = empty($field['notnull']) ? '' : ' NOT NULL';
|
|
||||||
$unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED';
|
|
||||||
if (empty($default) && empty($notnull)) {
|
|
||||||
$default = ' DEFAULT NULL';
|
|
||||||
}
|
|
||||||
$name = $db->quoteIdentifier($name, true);
|
|
||||||
return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull.$autoinc;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _getFloatDeclaration()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain DBMS specific SQL code portion needed to declare an float type
|
|
||||||
* field to be used in statements like CREATE TABLE.
|
|
||||||
*
|
|
||||||
* @param string $name name the field to be declared.
|
|
||||||
* @param string $field associative array with the name of the properties
|
|
||||||
* of the field being declared as array indexes.
|
|
||||||
* Currently, the types of supported field
|
|
||||||
* properties are as follows:
|
|
||||||
*
|
|
||||||
* unsigned
|
|
||||||
* Boolean flag that indicates whether the field
|
|
||||||
* should be declared as unsigned float if
|
|
||||||
* possible.
|
|
||||||
*
|
|
||||||
* default
|
|
||||||
* float value to be used as default for this
|
|
||||||
* field.
|
|
||||||
*
|
|
||||||
* notnull
|
|
||||||
* Boolean flag that indicates whether this field is
|
|
||||||
* constrained to not be set to null.
|
|
||||||
* @return string DBMS specific SQL code portion that should be used to
|
|
||||||
* declare the specified field.
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
function _getFloatDeclaration($name, $field)
|
|
||||||
{
|
|
||||||
// Since AUTO_INCREMENT can be used for integer or floating-point types,
|
|
||||||
// reuse the INTEGER declaration
|
|
||||||
// @see http://bugs.mysql.com/bug.php?id=31032
|
|
||||||
return $this->_getIntegerDeclaration($name, $field);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _getDecimalDeclaration()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain DBMS specific SQL code portion needed to declare an decimal type
|
|
||||||
* field to be used in statements like CREATE TABLE.
|
|
||||||
*
|
|
||||||
* @param string $name name the field to be declared.
|
|
||||||
* @param string $field associative array with the name of the properties
|
|
||||||
* of the field being declared as array indexes.
|
|
||||||
* Currently, the types of supported field
|
|
||||||
* properties are as follows:
|
|
||||||
*
|
|
||||||
* unsigned
|
|
||||||
* Boolean flag that indicates whether the field
|
|
||||||
* should be declared as unsigned integer if
|
|
||||||
* possible.
|
|
||||||
*
|
|
||||||
* default
|
|
||||||
* Decimal value to be used as default for this
|
|
||||||
* field.
|
|
||||||
*
|
|
||||||
* notnull
|
|
||||||
* Boolean flag that indicates whether this field is
|
|
||||||
* constrained to not be set to null.
|
|
||||||
* @return string DBMS specific SQL code portion that should be used to
|
|
||||||
* declare the specified field.
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
function _getDecimalDeclaration($name, $field)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$default = '';
|
|
||||||
if (array_key_exists('default', $field)) {
|
|
||||||
if ($field['default'] === '') {
|
|
||||||
$field['default'] = empty($field['notnull']) ? null : 0;
|
|
||||||
}
|
|
||||||
$default = ' DEFAULT '.$this->quote($field['default'], 'integer');
|
|
||||||
} elseif (empty($field['notnull'])) {
|
|
||||||
$default = ' DEFAULT NULL';
|
|
||||||
}
|
|
||||||
|
|
||||||
$notnull = empty($field['notnull']) ? '' : ' NOT NULL';
|
|
||||||
$unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED';
|
|
||||||
$name = $db->quoteIdentifier($name, true);
|
|
||||||
return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ matchPattern()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* build a pattern matching string
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*
|
|
||||||
* @param array $pattern even keys are strings, odd are patterns (% and _)
|
|
||||||
* @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
|
|
||||||
* @param string $field optional field name that is being matched against
|
|
||||||
* (might be required when emulating ILIKE)
|
|
||||||
*
|
|
||||||
* @return string SQL pattern
|
|
||||||
*/
|
|
||||||
function matchPattern($pattern, $operator = null, $field = null)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$match = '';
|
|
||||||
if (null !== $operator) {
|
|
||||||
$field = (null === $field) ? '' : $field.' ';
|
|
||||||
$operator = strtoupper($operator);
|
|
||||||
switch ($operator) {
|
|
||||||
// case insensitive
|
|
||||||
case 'ILIKE':
|
|
||||||
$match = $field.'LIKE ';
|
|
||||||
break;
|
|
||||||
case 'NOT ILIKE':
|
|
||||||
$match = $field.'NOT LIKE ';
|
|
||||||
break;
|
|
||||||
// case sensitive
|
|
||||||
case 'LIKE':
|
|
||||||
$match = $field.'LIKE BINARY ';
|
|
||||||
break;
|
|
||||||
case 'NOT LIKE':
|
|
||||||
$match = $field.'NOT LIKE BINARY ';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
|
||||||
'not a supported operator type:'. $operator, __FUNCTION__);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$match.= "'";
|
|
||||||
foreach ($pattern as $key => $value) {
|
|
||||||
if ($key % 2) {
|
|
||||||
$match.= $value;
|
|
||||||
} else {
|
|
||||||
$match.= $db->escapePattern($db->escape($value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$match.= "'";
|
|
||||||
$match.= $this->patternEscapeString();
|
|
||||||
return $match;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _mapNativeDatatype()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps a native array description of a field to a MDB2 datatype and length
|
|
||||||
*
|
|
||||||
* @param array $field native field description
|
|
||||||
* @return array containing the various possible types, length, sign, fixed
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function _mapNativeDatatype($field)
|
|
||||||
{
|
|
||||||
$db_type = strtolower($field['type']);
|
|
||||||
$db_type = strtok($db_type, '(), ');
|
|
||||||
if ($db_type == 'national') {
|
|
||||||
$db_type = strtok('(), ');
|
|
||||||
}
|
|
||||||
if (!empty($field['length'])) {
|
|
||||||
$length = strtok($field['length'], ', ');
|
|
||||||
$decimal = strtok(', ');
|
|
||||||
} else {
|
|
||||||
$length = strtok('(), ');
|
|
||||||
$decimal = strtok('(), ');
|
|
||||||
}
|
|
||||||
$type = array();
|
|
||||||
$unsigned = $fixed = null;
|
|
||||||
switch ($db_type) {
|
|
||||||
case 'tinyint':
|
|
||||||
$type[] = 'integer';
|
|
||||||
$type[] = 'boolean';
|
|
||||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
|
||||||
$type = array_reverse($type);
|
|
||||||
}
|
|
||||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
|
||||||
$length = 1;
|
|
||||||
break;
|
|
||||||
case 'smallint':
|
|
||||||
$type[] = 'integer';
|
|
||||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
|
||||||
$length = 2;
|
|
||||||
break;
|
|
||||||
case 'mediumint':
|
|
||||||
$type[] = 'integer';
|
|
||||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
|
||||||
$length = 3;
|
|
||||||
break;
|
|
||||||
case 'int':
|
|
||||||
case 'integer':
|
|
||||||
$type[] = 'integer';
|
|
||||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
|
||||||
$length = 4;
|
|
||||||
break;
|
|
||||||
case 'bigint':
|
|
||||||
$type[] = 'integer';
|
|
||||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
|
||||||
$length = 8;
|
|
||||||
break;
|
|
||||||
case 'tinytext':
|
|
||||||
case 'mediumtext':
|
|
||||||
case 'longtext':
|
|
||||||
case 'text':
|
|
||||||
case 'varchar':
|
|
||||||
$fixed = false;
|
|
||||||
case 'string':
|
|
||||||
case 'char':
|
|
||||||
$type[] = 'text';
|
|
||||||
if ($length == '1') {
|
|
||||||
$type[] = 'boolean';
|
|
||||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
|
||||||
$type = array_reverse($type);
|
|
||||||
}
|
|
||||||
} elseif (strstr($db_type, 'text')) {
|
|
||||||
$type[] = 'clob';
|
|
||||||
if ($decimal == 'binary') {
|
|
||||||
$type[] = 'blob';
|
|
||||||
}
|
|
||||||
$type = array_reverse($type);
|
|
||||||
}
|
|
||||||
if ($fixed !== false) {
|
|
||||||
$fixed = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'enum':
|
|
||||||
$type[] = 'text';
|
|
||||||
preg_match_all('/\'.+\'/U', $field['type'], $matches);
|
|
||||||
$length = 0;
|
|
||||||
$fixed = false;
|
|
||||||
if (is_array($matches)) {
|
|
||||||
foreach ($matches[0] as $value) {
|
|
||||||
$length = max($length, strlen($value)-2);
|
|
||||||
}
|
|
||||||
if ($length == '1' && count($matches[0]) == 2) {
|
|
||||||
$type[] = 'boolean';
|
|
||||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
|
||||||
$type = array_reverse($type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$type[] = 'integer';
|
|
||||||
case 'set':
|
|
||||||
$fixed = false;
|
|
||||||
$type[] = 'text';
|
|
||||||
$type[] = 'integer';
|
|
||||||
break;
|
|
||||||
case 'date':
|
|
||||||
$type[] = 'date';
|
|
||||||
$length = null;
|
|
||||||
break;
|
|
||||||
case 'datetime':
|
|
||||||
case 'timestamp':
|
|
||||||
$type[] = 'timestamp';
|
|
||||||
$length = null;
|
|
||||||
break;
|
|
||||||
case 'time':
|
|
||||||
$type[] = 'time';
|
|
||||||
$length = null;
|
|
||||||
break;
|
|
||||||
case 'float':
|
|
||||||
case 'double':
|
|
||||||
case 'real':
|
|
||||||
$type[] = 'float';
|
|
||||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
|
||||||
if ($decimal !== false) {
|
|
||||||
$length = $length.','.$decimal;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'unknown':
|
|
||||||
case 'decimal':
|
|
||||||
case 'numeric':
|
|
||||||
$type[] = 'decimal';
|
|
||||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
|
||||||
if ($decimal !== false) {
|
|
||||||
$length = $length.','.$decimal;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'tinyblob':
|
|
||||||
case 'mediumblob':
|
|
||||||
case 'longblob':
|
|
||||||
case 'blob':
|
|
||||||
$type[] = 'blob';
|
|
||||||
$length = null;
|
|
||||||
break;
|
|
||||||
case 'binary':
|
|
||||||
case 'varbinary':
|
|
||||||
$type[] = 'blob';
|
|
||||||
break;
|
|
||||||
case 'year':
|
|
||||||
$type[] = 'integer';
|
|
||||||
$type[] = 'date';
|
|
||||||
$length = null;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
|
||||||
'unknown database attribute type: '.$db_type, __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((int)$length <= 0) {
|
|
||||||
$length = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return array($type, $length, $unsigned, $fixed);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
|
@ -1,499 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Lukas Smith <smith@pooteeweet.org> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
|
|
||||||
// $Id: oci8.php 295587 2010-02-28 17:16:38Z quipo $
|
|
||||||
|
|
||||||
require_once 'MDB2/Driver/Datatype/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MDB2 OCI8 driver
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
class MDB2_Driver_Datatype_oci8 extends MDB2_Driver_Datatype_Common
|
|
||||||
{
|
|
||||||
// {{{ _baseConvertResult()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* general type conversion method
|
|
||||||
*
|
|
||||||
* @param mixed $value refernce to a value to be converted
|
|
||||||
* @param string $type specifies which type to convert to
|
|
||||||
* @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
|
|
||||||
* @return object a MDB2 error on failure
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
function _baseConvertResult($value, $type, $rtrim = true)
|
|
||||||
{
|
|
||||||
if (null === $value) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
switch ($type) {
|
|
||||||
case 'text':
|
|
||||||
if (is_object($value) && is_a($value, 'OCI-Lob')) {
|
|
||||||
//LOB => fetch into variable
|
|
||||||
$clob = $this->_baseConvertResult($value, 'clob', $rtrim);
|
|
||||||
if (!PEAR::isError($clob) && is_resource($clob)) {
|
|
||||||
$clob_value = '';
|
|
||||||
while (!feof($clob)) {
|
|
||||||
$clob_value .= fread($clob, 8192);
|
|
||||||
}
|
|
||||||
$this->destroyLOB($clob);
|
|
||||||
}
|
|
||||||
$value = $clob_value;
|
|
||||||
}
|
|
||||||
if ($rtrim) {
|
|
||||||
$value = rtrim($value);
|
|
||||||
}
|
|
||||||
return $value;
|
|
||||||
case 'date':
|
|
||||||
return substr($value, 0, strlen('YYYY-MM-DD'));
|
|
||||||
case 'time':
|
|
||||||
return substr($value, strlen('YYYY-MM-DD '), strlen('HH:MI:SS'));
|
|
||||||
}
|
|
||||||
return parent::_baseConvertResult($value, $type, $rtrim);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getTypeDeclaration()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain DBMS specific SQL code portion needed to declare an text type
|
|
||||||
* field to be used in statements like CREATE TABLE.
|
|
||||||
*
|
|
||||||
* @param array $field associative array with the name of the properties
|
|
||||||
* of the field being declared as array indexes. Currently, the types
|
|
||||||
* of supported field properties are as follows:
|
|
||||||
*
|
|
||||||
* length
|
|
||||||
* Integer value that determines the maximum length of the text
|
|
||||||
* field. If this argument is missing the field should be
|
|
||||||
* declared to have the longest length allowed by the DBMS.
|
|
||||||
*
|
|
||||||
* default
|
|
||||||
* Text value to be used as default for this field.
|
|
||||||
*
|
|
||||||
* notnull
|
|
||||||
* Boolean flag that indicates whether this field is constrained
|
|
||||||
* to not be set to null.
|
|
||||||
* @return string DBMS specific SQL code portion that should be used to
|
|
||||||
* declare the specified field.
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTypeDeclaration($field)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($field['type']) {
|
|
||||||
case 'text':
|
|
||||||
$length = !empty($field['length'])
|
|
||||||
? $field['length'] : $db->options['default_text_field_length'];
|
|
||||||
$fixed = !empty($field['fixed']) ? $field['fixed'] : false;
|
|
||||||
return $fixed ? 'CHAR('.$length.')' : 'VARCHAR2('.$length.')';
|
|
||||||
case 'clob':
|
|
||||||
return 'CLOB';
|
|
||||||
case 'blob':
|
|
||||||
return 'BLOB';
|
|
||||||
case 'integer':
|
|
||||||
if (!empty($field['length'])) {
|
|
||||||
switch((int)$field['length']) {
|
|
||||||
case 1: $digit = 3; break;
|
|
||||||
case 2: $digit = 5; break;
|
|
||||||
case 3: $digit = 8; break;
|
|
||||||
case 4: $digit = 10; break;
|
|
||||||
case 5: $digit = 13; break;
|
|
||||||
case 6: $digit = 15; break;
|
|
||||||
case 7: $digit = 17; break;
|
|
||||||
case 8: $digit = 20; break;
|
|
||||||
default: $digit = 10;
|
|
||||||
}
|
|
||||||
return 'NUMBER('.$digit.')';
|
|
||||||
}
|
|
||||||
return 'INT';
|
|
||||||
case 'boolean':
|
|
||||||
return 'NUMBER(1)';
|
|
||||||
case 'date':
|
|
||||||
case 'time':
|
|
||||||
case 'timestamp':
|
|
||||||
return 'DATE';
|
|
||||||
case 'float':
|
|
||||||
return 'NUMBER';
|
|
||||||
case 'decimal':
|
|
||||||
$scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
|
|
||||||
return 'NUMBER(*,'.$scale.')';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _quoteCLOB()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a text value into a DBMS specific format that is suitable to
|
|
||||||
* compose query statements.
|
|
||||||
*
|
|
||||||
* @param string $value text string value that is intended to be converted.
|
|
||||||
* @param bool $quote determines if the value should be quoted and escaped
|
|
||||||
* @param bool $escape_wildcards if to escape escape wildcards
|
|
||||||
* @return string text string that represents the given argument value in
|
|
||||||
* a DBMS specific format.
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
function _quoteCLOB($value, $quote, $escape_wildcards)
|
|
||||||
{
|
|
||||||
return 'EMPTY_CLOB()';
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _quoteBLOB()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a text value into a DBMS specific format that is suitable to
|
|
||||||
* compose query statements.
|
|
||||||
*
|
|
||||||
* @param string $value text string value that is intended to be converted.
|
|
||||||
* @param bool $quote determines if the value should be quoted and escaped
|
|
||||||
* @param bool $escape_wildcards if to escape escape wildcards
|
|
||||||
* @return string text string that represents the given argument value in
|
|
||||||
* a DBMS specific format.
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
function _quoteBLOB($value, $quote, $escape_wildcards)
|
|
||||||
{
|
|
||||||
return 'EMPTY_BLOB()';
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _quoteDate()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a text value into a DBMS specific format that is suitable to
|
|
||||||
* compose query statements.
|
|
||||||
*
|
|
||||||
* @param string $value text string value that is intended to be converted.
|
|
||||||
* @param bool $quote determines if the value should be quoted and escaped
|
|
||||||
* @param bool $escape_wildcards if to escape escape wildcards
|
|
||||||
* @return string text string that represents the given argument value in
|
|
||||||
* a DBMS specific format.
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
function _quoteDate($value, $quote, $escape_wildcards)
|
|
||||||
{
|
|
||||||
return $this->_quoteText("$value 00:00:00", $quote, $escape_wildcards);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _quoteTimestamp()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a text value into a DBMS specific format that is suitable to
|
|
||||||
* compose query statements.
|
|
||||||
*
|
|
||||||
* @param string $value text string value that is intended to be converted.
|
|
||||||
* @param bool $quote determines if the value should be quoted and escaped
|
|
||||||
* @param bool $escape_wildcards if to escape escape wildcards
|
|
||||||
* @return string text string that represents the given argument value in
|
|
||||||
* a DBMS specific format.
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
//function _quoteTimestamp($value, $quote, $escape_wildcards)
|
|
||||||
//{
|
|
||||||
// return $this->_quoteText($value, $quote, $escape_wildcards);
|
|
||||||
//}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _quoteTime()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a text value into a DBMS specific format that is suitable to
|
|
||||||
* compose query statements.
|
|
||||||
*
|
|
||||||
* @param string $value text string value that is intended to be converted.
|
|
||||||
* @param bool $quote determines if the value should be quoted and escaped
|
|
||||||
* @param bool $escape_wildcards if to escape escape wildcards
|
|
||||||
* @return string text string that represents the given argument value in
|
|
||||||
* a DBMS specific format.
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
function _quoteTime($value, $quote, $escape_wildcards)
|
|
||||||
{
|
|
||||||
return $this->_quoteText("0001-01-01 $value", $quote, $escape_wildcards);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ writeLOBToFile()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* retrieve LOB from the database
|
|
||||||
*
|
|
||||||
* @param array $lob array
|
|
||||||
* @param string $file name of the file into which the LOb should be fetched
|
|
||||||
* @return mixed MDB2_OK on success, a MDB2 error on failure
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
function writeLOBToFile($lob, $file)
|
|
||||||
{
|
|
||||||
if (preg_match('/^(\w+:\/\/)(.*)$/', $file, $match)) {
|
|
||||||
if ($match[1] == 'file://') {
|
|
||||||
$file = $match[2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$lob_data = stream_get_meta_data($lob);
|
|
||||||
$lob_index = $lob_data['wrapper_data']->lob_index;
|
|
||||||
$result = $this->lobs[$lob_index]['resource']->writetofile($file);
|
|
||||||
$this->lobs[$lob_index]['resource']->seek(0);
|
|
||||||
if (!$result) {
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $db->raiseError(null, null, null,
|
|
||||||
'Unable to write LOB to file', __FUNCTION__);
|
|
||||||
}
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _retrieveLOB()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* retrieve LOB from the database
|
|
||||||
*
|
|
||||||
* @param array $lob array
|
|
||||||
* @return mixed MDB2_OK on success, a MDB2 error on failure
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
function _retrieveLOB(&$lob)
|
|
||||||
{
|
|
||||||
if (!is_object($lob['resource'])) {
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
'attemped to retrieve LOB from non existing or NULL column', __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$lob['loaded']
|
|
||||||
# && !method_exists($lob['resource'], 'read')
|
|
||||||
) {
|
|
||||||
$lob['value'] = $lob['resource']->load();
|
|
||||||
$lob['resource']->seek(0);
|
|
||||||
}
|
|
||||||
$lob['loaded'] = true;
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _readLOB()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read data from large object input stream.
|
|
||||||
*
|
|
||||||
* @param array $lob array
|
|
||||||
* @param blob $data reference to a variable that will hold data to be
|
|
||||||
* read from the large object input stream
|
|
||||||
* @param int $length integer value that indicates the largest ammount of
|
|
||||||
* data to be read from the large object input stream.
|
|
||||||
* @return mixed length on success, a MDB2 error on failure
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
function _readLOB($lob, $length)
|
|
||||||
{
|
|
||||||
if ($lob['loaded']) {
|
|
||||||
return parent::_readLOB($lob, $length);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_object($lob['resource'])) {
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
'attemped to retrieve LOB from non existing or NULL column', __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = $lob['resource']->read($length);
|
|
||||||
if (!is_string($data)) {
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $db->raiseError(null, null, null,
|
|
||||||
'Unable to read LOB', __FUNCTION__);
|
|
||||||
}
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ patternEscapeString()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* build string to define escape pattern string
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return string define escape pattern
|
|
||||||
*/
|
|
||||||
function patternEscapeString()
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
return " ESCAPE '". $db->string_quoting['escape_pattern'] ."'";
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _mapNativeDatatype()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps a native array description of a field to a MDB2 datatype and length
|
|
||||||
*
|
|
||||||
* @param array $field native field description
|
|
||||||
* @return array containing the various possible types, length, sign, fixed
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function _mapNativeDatatype($field)
|
|
||||||
{
|
|
||||||
$db_type = strtolower($field['type']);
|
|
||||||
$type = array();
|
|
||||||
$length = $unsigned = $fixed = null;
|
|
||||||
if (!empty($field['length'])) {
|
|
||||||
$length = $field['length'];
|
|
||||||
}
|
|
||||||
switch ($db_type) {
|
|
||||||
case 'integer':
|
|
||||||
case 'pls_integer':
|
|
||||||
case 'binary_integer':
|
|
||||||
$type[] = 'integer';
|
|
||||||
if ($length == '1') {
|
|
||||||
$type[] = 'boolean';
|
|
||||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
|
||||||
$type = array_reverse($type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'varchar':
|
|
||||||
case 'varchar2':
|
|
||||||
case 'nvarchar2':
|
|
||||||
$fixed = false;
|
|
||||||
case 'char':
|
|
||||||
case 'nchar':
|
|
||||||
$type[] = 'text';
|
|
||||||
if ($length == '1') {
|
|
||||||
$type[] = 'boolean';
|
|
||||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
|
||||||
$type = array_reverse($type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($fixed !== false) {
|
|
||||||
$fixed = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'date':
|
|
||||||
case 'timestamp':
|
|
||||||
$type[] = 'timestamp';
|
|
||||||
$length = null;
|
|
||||||
break;
|
|
||||||
case 'float':
|
|
||||||
$type[] = 'float';
|
|
||||||
break;
|
|
||||||
case 'number':
|
|
||||||
if (!empty($field['scale'])) {
|
|
||||||
$type[] = 'decimal';
|
|
||||||
$length = $length.','.$field['scale'];
|
|
||||||
} else {
|
|
||||||
$type[] = 'integer';
|
|
||||||
if ($length == '1') {
|
|
||||||
$type[] = 'boolean';
|
|
||||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
|
||||||
$type = array_reverse($type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'long':
|
|
||||||
$type[] = 'text';
|
|
||||||
case 'clob':
|
|
||||||
case 'nclob':
|
|
||||||
$type[] = 'clob';
|
|
||||||
break;
|
|
||||||
case 'blob':
|
|
||||||
case 'raw':
|
|
||||||
case 'long raw':
|
|
||||||
case 'bfile':
|
|
||||||
$type[] = 'blob';
|
|
||||||
$length = null;
|
|
||||||
break;
|
|
||||||
case 'rowid':
|
|
||||||
case 'urowid':
|
|
||||||
default:
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
|
||||||
'unknown database attribute type: '.$db_type, __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((int)$length <= 0) {
|
|
||||||
$length = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return array($type, $length, $unsigned, $fixed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
|
@ -1,579 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Paul Cooper <pgc@ucecom.com> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
require_once 'MDB2/Driver/Datatype/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MDB2 PostGreSQL driver
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Paul Cooper <pgc@ucecom.com>
|
|
||||||
*/
|
|
||||||
class MDB2_Driver_Datatype_pgsql extends MDB2_Driver_Datatype_Common
|
|
||||||
{
|
|
||||||
// {{{ _baseConvertResult()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* General type conversion method
|
|
||||||
*
|
|
||||||
* @param mixed $value refernce to a value to be converted
|
|
||||||
* @param string $type specifies which type to convert to
|
|
||||||
* @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
|
|
||||||
* @return object a MDB2 error on failure
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
function _baseConvertResult($value, $type, $rtrim = true)
|
|
||||||
{
|
|
||||||
if (null === $value) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
switch ($type) {
|
|
||||||
case 'boolean':
|
|
||||||
return $value == 't';
|
|
||||||
case 'float':
|
|
||||||
return doubleval($value);
|
|
||||||
case 'date':
|
|
||||||
return $value;
|
|
||||||
case 'time':
|
|
||||||
return substr($value, 0, strlen('HH:MM:SS'));
|
|
||||||
case 'timestamp':
|
|
||||||
return substr($value, 0, strlen('YYYY-MM-DD HH:MM:SS'));
|
|
||||||
case 'blob':
|
|
||||||
$value = pg_unescape_bytea($value);
|
|
||||||
return parent::_baseConvertResult($value, $type, $rtrim);
|
|
||||||
}
|
|
||||||
return parent::_baseConvertResult($value, $type, $rtrim);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getTypeDeclaration()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain DBMS specific SQL code portion needed to declare an text type
|
|
||||||
* field to be used in statements like CREATE TABLE.
|
|
||||||
*
|
|
||||||
* @param array $field associative array with the name of the properties
|
|
||||||
* of the field being declared as array indexes. Currently, the types
|
|
||||||
* of supported field properties are as follows:
|
|
||||||
*
|
|
||||||
* length
|
|
||||||
* Integer value that determines the maximum length of the text
|
|
||||||
* field. If this argument is missing the field should be
|
|
||||||
* declared to have the longest length allowed by the DBMS.
|
|
||||||
*
|
|
||||||
* default
|
|
||||||
* Text value to be used as default for this field.
|
|
||||||
*
|
|
||||||
* notnull
|
|
||||||
* Boolean flag that indicates whether this field is constrained
|
|
||||||
* to not be set to null.
|
|
||||||
* @return string DBMS specific SQL code portion that should be used to
|
|
||||||
* declare the specified field.
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTypeDeclaration($field)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($field['type']) {
|
|
||||||
case 'text':
|
|
||||||
$length = !empty($field['length']) ? $field['length'] : false;
|
|
||||||
$fixed = !empty($field['fixed']) ? $field['fixed'] : false;
|
|
||||||
return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
|
|
||||||
: ($length ? 'VARCHAR('.$length.')' : 'TEXT');
|
|
||||||
case 'clob':
|
|
||||||
return 'TEXT';
|
|
||||||
case 'blob':
|
|
||||||
return 'BYTEA';
|
|
||||||
case 'integer':
|
|
||||||
if (!empty($field['autoincrement'])) {
|
|
||||||
if (!empty($field['length'])) {
|
|
||||||
$length = $field['length'];
|
|
||||||
if ($length > 4) {
|
|
||||||
return 'BIGSERIAL PRIMARY KEY';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 'SERIAL PRIMARY KEY';
|
|
||||||
}
|
|
||||||
if (!empty($field['length'])) {
|
|
||||||
$length = $field['length'];
|
|
||||||
if ($length <= 2) {
|
|
||||||
return 'SMALLINT';
|
|
||||||
} elseif ($length == 3 || $length == 4) {
|
|
||||||
return 'INT';
|
|
||||||
} elseif ($length > 4) {
|
|
||||||
return 'BIGINT';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 'INT';
|
|
||||||
case 'boolean':
|
|
||||||
return 'BOOLEAN';
|
|
||||||
case 'date':
|
|
||||||
return 'DATE';
|
|
||||||
case 'time':
|
|
||||||
return 'TIME without time zone';
|
|
||||||
case 'timestamp':
|
|
||||||
return 'TIMESTAMP without time zone';
|
|
||||||
case 'float':
|
|
||||||
return 'FLOAT8';
|
|
||||||
case 'decimal':
|
|
||||||
$length = !empty($field['length']) ? $field['length'] : 18;
|
|
||||||
$scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
|
|
||||||
return 'NUMERIC('.$length.','.$scale.')';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _getIntegerDeclaration()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain DBMS specific SQL code portion needed to declare an integer type
|
|
||||||
* field to be used in statements like CREATE TABLE.
|
|
||||||
*
|
|
||||||
* @param string $name name the field to be declared.
|
|
||||||
* @param array $field associative array with the name of the properties
|
|
||||||
* of the field being declared as array indexes. Currently, the types
|
|
||||||
* of supported field properties are as follows:
|
|
||||||
*
|
|
||||||
* unsigned
|
|
||||||
* Boolean flag that indicates whether the field should be
|
|
||||||
* declared as unsigned integer if possible.
|
|
||||||
*
|
|
||||||
* default
|
|
||||||
* Integer value to be used as default for this field.
|
|
||||||
*
|
|
||||||
* notnull
|
|
||||||
* Boolean flag that indicates whether this field is constrained
|
|
||||||
* to not be set to null.
|
|
||||||
* @return string DBMS specific SQL code portion that should be used to
|
|
||||||
* declare the specified field.
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
function _getIntegerDeclaration($name, $field)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($field['unsigned'])) {
|
|
||||||
$db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer";
|
|
||||||
}
|
|
||||||
if (!empty($field['autoincrement'])) {
|
|
||||||
$name = $db->quoteIdentifier($name, true);
|
|
||||||
return $name.' '.$this->getTypeDeclaration($field);
|
|
||||||
}
|
|
||||||
$default = '';
|
|
||||||
if (array_key_exists('default', $field)) {
|
|
||||||
if ($field['default'] === '') {
|
|
||||||
$field['default'] = empty($field['notnull']) ? null : 0;
|
|
||||||
}
|
|
||||||
$default = ' DEFAULT '.$this->quote($field['default'], 'integer');
|
|
||||||
}
|
|
||||||
|
|
||||||
$notnull = empty($field['notnull']) ? '' : ' NOT NULL';
|
|
||||||
if (empty($default) && empty($notnull)) {
|
|
||||||
$default = ' DEFAULT NULL';
|
|
||||||
}
|
|
||||||
$name = $db->quoteIdentifier($name, true);
|
|
||||||
return $name.' '.$this->getTypeDeclaration($field).$default.$notnull;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _quoteCLOB()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a text value into a DBMS specific format that is suitable to
|
|
||||||
* compose query statements.
|
|
||||||
*
|
|
||||||
* @param string $value text string value that is intended to be converted.
|
|
||||||
* @param bool $quote determines if the value should be quoted and escaped
|
|
||||||
* @param bool $escape_wildcards if to escape escape wildcards
|
|
||||||
* @return string text string that represents the given argument value in
|
|
||||||
* a DBMS specific format.
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
function _quoteCLOB($value, $quote, $escape_wildcards)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
if ($db->options['lob_allow_url_include']) {
|
|
||||||
$value = $this->_readFile($value);
|
|
||||||
if (PEAR::isError($value)) {
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $this->_quoteText($value, $quote, $escape_wildcards);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _quoteBLOB()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a text value into a DBMS specific format that is suitable to
|
|
||||||
* compose query statements.
|
|
||||||
*
|
|
||||||
* @param string $value text string value that is intended to be converted.
|
|
||||||
* @param bool $quote determines if the value should be quoted and escaped
|
|
||||||
* @param bool $escape_wildcards if to escape escape wildcards
|
|
||||||
* @return string text string that represents the given argument value in
|
|
||||||
* a DBMS specific format.
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
function _quoteBLOB($value, $quote, $escape_wildcards)
|
|
||||||
{
|
|
||||||
if (!$quote) {
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
if ($db->options['lob_allow_url_include']) {
|
|
||||||
$value = $this->_readFile($value);
|
|
||||||
if (PEAR::isError($value)) {
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (version_compare(PHP_VERSION, '5.2.0RC6', '>=')) {
|
|
||||||
$connection = $db->getConnection();
|
|
||||||
if (PEAR::isError($connection)) {
|
|
||||||
return $connection;
|
|
||||||
}
|
|
||||||
$value = @pg_escape_bytea($connection, $value);
|
|
||||||
} else {
|
|
||||||
$value = @pg_escape_bytea($value);
|
|
||||||
}
|
|
||||||
return "'".$value."'";
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _quoteBoolean()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a text value into a DBMS specific format that is suitable to
|
|
||||||
* compose query statements.
|
|
||||||
*
|
|
||||||
* @param string $value text string value that is intended to be converted.
|
|
||||||
* @param bool $quote determines if the value should be quoted and escaped
|
|
||||||
* @param bool $escape_wildcards if to escape escape wildcards
|
|
||||||
* @return string text string that represents the given argument value in
|
|
||||||
* a DBMS specific format.
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
function _quoteBoolean($value, $quote, $escape_wildcards)
|
|
||||||
{
|
|
||||||
$value = $value ? 't' : 'f';
|
|
||||||
if (!$quote) {
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
return "'".$value."'";
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ matchPattern()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* build a pattern matching string
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*
|
|
||||||
* @param array $pattern even keys are strings, odd are patterns (% and _)
|
|
||||||
* @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
|
|
||||||
* @param string $field optional field name that is being matched against
|
|
||||||
* (might be required when emulating ILIKE)
|
|
||||||
*
|
|
||||||
* @return string SQL pattern
|
|
||||||
*/
|
|
||||||
function matchPattern($pattern, $operator = null, $field = null)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$match = '';
|
|
||||||
if (null !== $operator) {
|
|
||||||
$field = (null === $field) ? '' : $field.' ';
|
|
||||||
$operator = strtoupper($operator);
|
|
||||||
switch ($operator) {
|
|
||||||
// case insensitive
|
|
||||||
case 'ILIKE':
|
|
||||||
$match = $field.'ILIKE ';
|
|
||||||
break;
|
|
||||||
case 'NOT ILIKE':
|
|
||||||
$match = $field.'NOT ILIKE ';
|
|
||||||
break;
|
|
||||||
// case sensitive
|
|
||||||
case 'LIKE':
|
|
||||||
$match = $field.'LIKE ';
|
|
||||||
break;
|
|
||||||
case 'NOT LIKE':
|
|
||||||
$match = $field.'NOT LIKE ';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
|
||||||
'not a supported operator type:'. $operator, __FUNCTION__);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$match.= "'";
|
|
||||||
foreach ($pattern as $key => $value) {
|
|
||||||
if ($key % 2) {
|
|
||||||
$match.= $value;
|
|
||||||
} else {
|
|
||||||
$match.= $db->escapePattern($db->escape($value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$match.= "'";
|
|
||||||
$match.= $this->patternEscapeString();
|
|
||||||
return $match;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ patternEscapeString()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* build string to define escape pattern string
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return string define escape pattern
|
|
||||||
*/
|
|
||||||
function patternEscapeString()
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
return ' ESCAPE '.$this->quote($db->string_quoting['escape_pattern']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _mapNativeDatatype()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps a native array description of a field to a MDB2 datatype and length
|
|
||||||
*
|
|
||||||
* @param array $field native field description
|
|
||||||
* @return array containing the various possible types, length, sign, fixed
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function _mapNativeDatatype($field)
|
|
||||||
{
|
|
||||||
$db_type = strtolower($field['type']);
|
|
||||||
$length = $field['length'];
|
|
||||||
$type = array();
|
|
||||||
$unsigned = $fixed = null;
|
|
||||||
switch ($db_type) {
|
|
||||||
case 'smallint':
|
|
||||||
case 'int2':
|
|
||||||
$type[] = 'integer';
|
|
||||||
$unsigned = false;
|
|
||||||
$length = 2;
|
|
||||||
if ($length == '2') {
|
|
||||||
$type[] = 'boolean';
|
|
||||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
|
||||||
$type = array_reverse($type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'int':
|
|
||||||
case 'int4':
|
|
||||||
case 'integer':
|
|
||||||
case 'serial':
|
|
||||||
case 'serial4':
|
|
||||||
$type[] = 'integer';
|
|
||||||
$unsigned = false;
|
|
||||||
$length = 4;
|
|
||||||
break;
|
|
||||||
case 'bigint':
|
|
||||||
case 'int8':
|
|
||||||
case 'bigserial':
|
|
||||||
case 'serial8':
|
|
||||||
$type[] = 'integer';
|
|
||||||
$unsigned = false;
|
|
||||||
$length = 8;
|
|
||||||
break;
|
|
||||||
case 'bool':
|
|
||||||
case 'boolean':
|
|
||||||
$type[] = 'boolean';
|
|
||||||
$length = null;
|
|
||||||
break;
|
|
||||||
case 'text':
|
|
||||||
case 'varchar':
|
|
||||||
$fixed = false;
|
|
||||||
case 'unknown':
|
|
||||||
case 'char':
|
|
||||||
case 'bpchar':
|
|
||||||
$type[] = 'text';
|
|
||||||
if ($length == '1') {
|
|
||||||
$type[] = 'boolean';
|
|
||||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
|
||||||
$type = array_reverse($type);
|
|
||||||
}
|
|
||||||
} elseif (strstr($db_type, 'text')) {
|
|
||||||
$type[] = 'clob';
|
|
||||||
$type = array_reverse($type);
|
|
||||||
}
|
|
||||||
if ($fixed !== false) {
|
|
||||||
$fixed = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'date':
|
|
||||||
$type[] = 'date';
|
|
||||||
$length = null;
|
|
||||||
break;
|
|
||||||
case 'datetime':
|
|
||||||
case 'timestamp':
|
|
||||||
case 'timestamptz':
|
|
||||||
$type[] = 'timestamp';
|
|
||||||
$length = null;
|
|
||||||
break;
|
|
||||||
case 'time':
|
|
||||||
$type[] = 'time';
|
|
||||||
$length = null;
|
|
||||||
break;
|
|
||||||
case 'float':
|
|
||||||
case 'float4':
|
|
||||||
case 'float8':
|
|
||||||
case 'double':
|
|
||||||
case 'real':
|
|
||||||
$type[] = 'float';
|
|
||||||
break;
|
|
||||||
case 'decimal':
|
|
||||||
case 'money':
|
|
||||||
case 'numeric':
|
|
||||||
$type[] = 'decimal';
|
|
||||||
if (isset($field['scale'])) {
|
|
||||||
$length = $length.','.$field['scale'];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'tinyblob':
|
|
||||||
case 'mediumblob':
|
|
||||||
case 'longblob':
|
|
||||||
case 'blob':
|
|
||||||
case 'bytea':
|
|
||||||
$type[] = 'blob';
|
|
||||||
$length = null;
|
|
||||||
break;
|
|
||||||
case 'oid':
|
|
||||||
$type[] = 'blob';
|
|
||||||
$type[] = 'clob';
|
|
||||||
$length = null;
|
|
||||||
break;
|
|
||||||
case 'year':
|
|
||||||
$type[] = 'integer';
|
|
||||||
$type[] = 'date';
|
|
||||||
$length = null;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
|
||||||
'unknown database attribute type: '.$db_type, __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((int)$length <= 0) {
|
|
||||||
$length = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return array($type, $length, $unsigned, $fixed);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ mapPrepareDatatype()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps an mdb2 datatype to native prepare type
|
|
||||||
*
|
|
||||||
* @param string $type
|
|
||||||
* @return string
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function mapPrepareDatatype($type)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($db->options['datatype_map'][$type])) {
|
|
||||||
$type = $db->options['datatype_map'][$type];
|
|
||||||
if (!empty($db->options['datatype_map_callback'][$type])) {
|
|
||||||
$parameter = array('type' => $type);
|
|
||||||
return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($type) {
|
|
||||||
case 'integer':
|
|
||||||
return 'int';
|
|
||||||
case 'boolean':
|
|
||||||
return 'bool';
|
|
||||||
case 'decimal':
|
|
||||||
case 'float':
|
|
||||||
return 'numeric';
|
|
||||||
case 'clob':
|
|
||||||
return 'text';
|
|
||||||
case 'blob':
|
|
||||||
return 'bytea';
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return $type;
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
}
|
|
||||||
?>
|
|
|
@ -1,418 +0,0 @@
|
||||||
<?php
|
|
||||||
// vim: set et ts=4 sw=4 fdm=marker:
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Lukas Smith <smith@pooteeweet.org> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
|
|
||||||
require_once 'MDB2/Driver/Datatype/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MDB2 SQLite driver
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
class MDB2_Driver_Datatype_sqlite extends MDB2_Driver_Datatype_Common
|
|
||||||
{
|
|
||||||
// {{{ _getCollationFieldDeclaration()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain DBMS specific SQL code portion needed to set the COLLATION
|
|
||||||
* of a field declaration to be used in statements like CREATE TABLE.
|
|
||||||
*
|
|
||||||
* @param string $collation name of the collation
|
|
||||||
*
|
|
||||||
* @return string DBMS specific SQL code portion needed to set the COLLATION
|
|
||||||
* of a field declaration.
|
|
||||||
*/
|
|
||||||
function _getCollationFieldDeclaration($collation)
|
|
||||||
{
|
|
||||||
return 'COLLATE '.$collation;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getTypeDeclaration()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain DBMS specific SQL code portion needed to declare an text type
|
|
||||||
* field to be used in statements like CREATE TABLE.
|
|
||||||
*
|
|
||||||
* @param array $field associative array with the name of the properties
|
|
||||||
* of the field being declared as array indexes. Currently, the types
|
|
||||||
* of supported field properties are as follows:
|
|
||||||
*
|
|
||||||
* length
|
|
||||||
* Integer value that determines the maximum length of the text
|
|
||||||
* field. If this argument is missing the field should be
|
|
||||||
* declared to have the longest length allowed by the DBMS.
|
|
||||||
*
|
|
||||||
* default
|
|
||||||
* Text value to be used as default for this field.
|
|
||||||
*
|
|
||||||
* notnull
|
|
||||||
* Boolean flag that indicates whether this field is constrained
|
|
||||||
* to not be set to null.
|
|
||||||
* @return string DBMS specific SQL code portion that should be used to
|
|
||||||
* declare the specified field.
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTypeDeclaration($field)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($field['type']) {
|
|
||||||
case 'text':
|
|
||||||
$length = !empty($field['length'])
|
|
||||||
? $field['length'] : false;
|
|
||||||
$fixed = !empty($field['fixed']) ? $field['fixed'] : false;
|
|
||||||
return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
|
|
||||||
: ($length ? 'VARCHAR('.$length.')' : 'TEXT');
|
|
||||||
case 'clob':
|
|
||||||
if (!empty($field['length'])) {
|
|
||||||
$length = $field['length'];
|
|
||||||
if ($length <= 255) {
|
|
||||||
return 'TINYTEXT';
|
|
||||||
} elseif ($length <= 65532) {
|
|
||||||
return 'TEXT';
|
|
||||||
} elseif ($length <= 16777215) {
|
|
||||||
return 'MEDIUMTEXT';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 'LONGTEXT';
|
|
||||||
case 'blob':
|
|
||||||
if (!empty($field['length'])) {
|
|
||||||
$length = $field['length'];
|
|
||||||
if ($length <= 255) {
|
|
||||||
return 'TINYBLOB';
|
|
||||||
} elseif ($length <= 65532) {
|
|
||||||
return 'BLOB';
|
|
||||||
} elseif ($length <= 16777215) {
|
|
||||||
return 'MEDIUMBLOB';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 'LONGBLOB';
|
|
||||||
case 'integer':
|
|
||||||
if (!empty($field['length'])) {
|
|
||||||
$length = $field['length'];
|
|
||||||
if ($length <= 2) {
|
|
||||||
return 'SMALLINT';
|
|
||||||
} elseif ($length == 3 || $length == 4) {
|
|
||||||
return 'INTEGER';
|
|
||||||
} elseif ($length > 4) {
|
|
||||||
return 'BIGINT';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 'INTEGER';
|
|
||||||
case 'boolean':
|
|
||||||
return 'BOOLEAN';
|
|
||||||
case 'date':
|
|
||||||
return 'DATE';
|
|
||||||
case 'time':
|
|
||||||
return 'TIME';
|
|
||||||
case 'timestamp':
|
|
||||||
return 'DATETIME';
|
|
||||||
case 'float':
|
|
||||||
return 'DOUBLE'.($db->options['fixed_float'] ? '('.
|
|
||||||
($db->options['fixed_float']+2).','.$db->options['fixed_float'].')' : '');
|
|
||||||
case 'decimal':
|
|
||||||
$length = !empty($field['length']) ? $field['length'] : 18;
|
|
||||||
$scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
|
|
||||||
return 'DECIMAL('.$length.','.$scale.')';
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _getIntegerDeclaration()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain DBMS specific SQL code portion needed to declare an integer type
|
|
||||||
* field to be used in statements like CREATE TABLE.
|
|
||||||
*
|
|
||||||
* @param string $name name the field to be declared.
|
|
||||||
* @param string $field associative array with the name of the properties
|
|
||||||
* of the field being declared as array indexes.
|
|
||||||
* Currently, the types of supported field
|
|
||||||
* properties are as follows:
|
|
||||||
*
|
|
||||||
* unsigned
|
|
||||||
* Boolean flag that indicates whether the field
|
|
||||||
* should be declared as unsigned integer if
|
|
||||||
* possible.
|
|
||||||
*
|
|
||||||
* default
|
|
||||||
* Integer value to be used as default for this
|
|
||||||
* field.
|
|
||||||
*
|
|
||||||
* notnull
|
|
||||||
* Boolean flag that indicates whether this field is
|
|
||||||
* constrained to not be set to null.
|
|
||||||
* @return string DBMS specific SQL code portion that should be used to
|
|
||||||
* declare the specified field.
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
function _getIntegerDeclaration($name, $field)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$default = $autoinc = '';
|
|
||||||
if (!empty($field['autoincrement'])) {
|
|
||||||
$autoinc = ' PRIMARY KEY';
|
|
||||||
} elseif (array_key_exists('default', $field)) {
|
|
||||||
if ($field['default'] === '') {
|
|
||||||
$field['default'] = empty($field['notnull']) ? null : 0;
|
|
||||||
}
|
|
||||||
$default = ' DEFAULT '.$this->quote($field['default'], 'integer');
|
|
||||||
}
|
|
||||||
|
|
||||||
$notnull = empty($field['notnull']) ? '' : ' NOT NULL';
|
|
||||||
$unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED';
|
|
||||||
if (empty($default) && empty($notnull)) {
|
|
||||||
$default = ' DEFAULT NULL';
|
|
||||||
}
|
|
||||||
$name = $db->quoteIdentifier($name, true);
|
|
||||||
return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull.$autoinc;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ matchPattern()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* build a pattern matching string
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*
|
|
||||||
* @param array $pattern even keys are strings, odd are patterns (% and _)
|
|
||||||
* @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
|
|
||||||
* @param string $field optional field name that is being matched against
|
|
||||||
* (might be required when emulating ILIKE)
|
|
||||||
*
|
|
||||||
* @return string SQL pattern
|
|
||||||
*/
|
|
||||||
function matchPattern($pattern, $operator = null, $field = null)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$match = '';
|
|
||||||
if (null !== $operator) {
|
|
||||||
$field = (null === $field) ? '' : $field.' ';
|
|
||||||
$operator = strtoupper($operator);
|
|
||||||
switch ($operator) {
|
|
||||||
// case insensitive
|
|
||||||
case 'ILIKE':
|
|
||||||
$match = $field.'LIKE ';
|
|
||||||
break;
|
|
||||||
case 'NOT ILIKE':
|
|
||||||
$match = $field.'NOT LIKE ';
|
|
||||||
break;
|
|
||||||
// case sensitive
|
|
||||||
case 'LIKE':
|
|
||||||
$match = $field.'LIKE ';
|
|
||||||
break;
|
|
||||||
case 'NOT LIKE':
|
|
||||||
$match = $field.'NOT LIKE ';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
|
||||||
'not a supported operator type:'. $operator, __FUNCTION__);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$match.= "'";
|
|
||||||
foreach ($pattern as $key => $value) {
|
|
||||||
if ($key % 2) {
|
|
||||||
$match.= $value;
|
|
||||||
} else {
|
|
||||||
$match.= $db->escapePattern($db->escape($value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$match.= "'";
|
|
||||||
$match.= $this->patternEscapeString();
|
|
||||||
return $match;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _mapNativeDatatype()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps a native array description of a field to a MDB2 datatype and length
|
|
||||||
*
|
|
||||||
* @param array $field native field description
|
|
||||||
* @return array containing the various possible types, length, sign, fixed
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function _mapNativeDatatype($field)
|
|
||||||
{
|
|
||||||
$db_type = strtolower($field['type']);
|
|
||||||
$length = !empty($field['length']) ? $field['length'] : null;
|
|
||||||
$unsigned = !empty($field['unsigned']) ? $field['unsigned'] : null;
|
|
||||||
$fixed = null;
|
|
||||||
$type = array();
|
|
||||||
switch ($db_type) {
|
|
||||||
case 'boolean':
|
|
||||||
$type[] = 'boolean';
|
|
||||||
break;
|
|
||||||
case 'tinyint':
|
|
||||||
$type[] = 'integer';
|
|
||||||
$type[] = 'boolean';
|
|
||||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
|
||||||
$type = array_reverse($type);
|
|
||||||
}
|
|
||||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
|
||||||
$length = 1;
|
|
||||||
break;
|
|
||||||
case 'smallint':
|
|
||||||
$type[] = 'integer';
|
|
||||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
|
||||||
$length = 2;
|
|
||||||
break;
|
|
||||||
case 'mediumint':
|
|
||||||
$type[] = 'integer';
|
|
||||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
|
||||||
$length = 3;
|
|
||||||
break;
|
|
||||||
case 'int':
|
|
||||||
case 'integer':
|
|
||||||
case 'serial':
|
|
||||||
$type[] = 'integer';
|
|
||||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
|
||||||
$length = 4;
|
|
||||||
break;
|
|
||||||
case 'bigint':
|
|
||||||
case 'bigserial':
|
|
||||||
$type[] = 'integer';
|
|
||||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
|
||||||
$length = 8;
|
|
||||||
break;
|
|
||||||
case 'clob':
|
|
||||||
$type[] = 'clob';
|
|
||||||
$fixed = false;
|
|
||||||
break;
|
|
||||||
case 'tinytext':
|
|
||||||
case 'mediumtext':
|
|
||||||
case 'longtext':
|
|
||||||
case 'text':
|
|
||||||
case 'varchar':
|
|
||||||
case 'varchar2':
|
|
||||||
$fixed = false;
|
|
||||||
case 'char':
|
|
||||||
$type[] = 'text';
|
|
||||||
if ($length == '1') {
|
|
||||||
$type[] = 'boolean';
|
|
||||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
|
||||||
$type = array_reverse($type);
|
|
||||||
}
|
|
||||||
} elseif (strstr($db_type, 'text')) {
|
|
||||||
$type[] = 'clob';
|
|
||||||
$type = array_reverse($type);
|
|
||||||
}
|
|
||||||
if ($fixed !== false) {
|
|
||||||
$fixed = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'date':
|
|
||||||
$type[] = 'date';
|
|
||||||
$length = null;
|
|
||||||
break;
|
|
||||||
case 'datetime':
|
|
||||||
case 'timestamp':
|
|
||||||
$type[] = 'timestamp';
|
|
||||||
$length = null;
|
|
||||||
break;
|
|
||||||
case 'time':
|
|
||||||
$type[] = 'time';
|
|
||||||
$length = null;
|
|
||||||
break;
|
|
||||||
case 'float':
|
|
||||||
case 'double':
|
|
||||||
case 'real':
|
|
||||||
$type[] = 'float';
|
|
||||||
break;
|
|
||||||
case 'decimal':
|
|
||||||
case 'numeric':
|
|
||||||
$type[] = 'decimal';
|
|
||||||
$length = $length.','.$field['decimal'];
|
|
||||||
break;
|
|
||||||
case 'tinyblob':
|
|
||||||
case 'mediumblob':
|
|
||||||
case 'longblob':
|
|
||||||
case 'blob':
|
|
||||||
$type[] = 'blob';
|
|
||||||
$length = null;
|
|
||||||
break;
|
|
||||||
case 'year':
|
|
||||||
$type[] = 'integer';
|
|
||||||
$type[] = 'date';
|
|
||||||
$length = null;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
|
||||||
'unknown database attribute type: '.$db_type, __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((int)$length <= 0) {
|
|
||||||
$length = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return array($type, $length, $unsigned, $fixed);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
|
@ -1,293 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Lukas Smith <smith@pooteeweet.org> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for the function modules that is extended by each MDB2 driver
|
|
||||||
*
|
|
||||||
* To load this module in the MDB2 object:
|
|
||||||
* $mdb->loadModule('Function');
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
class MDB2_Driver_Function_Common extends MDB2_Module_Common
|
|
||||||
{
|
|
||||||
// {{{ executeStoredProc()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute a stored procedure and return any results
|
|
||||||
*
|
|
||||||
* @param string $name string that identifies the function to execute
|
|
||||||
* @param mixed $params array that contains the paramaters to pass the stored proc
|
|
||||||
* @param mixed $types array that contains the types of the columns in
|
|
||||||
* the result set
|
|
||||||
* @param mixed $result_class string which specifies which result class to use
|
|
||||||
* @param mixed $result_wrap_class string which specifies which class to wrap results in
|
|
||||||
*
|
|
||||||
* @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$error = $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
|
||||||
'method not implemented', __FUNCTION__);
|
|
||||||
return $error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ functionTable()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return string for internal table used when calling only a function
|
|
||||||
*
|
|
||||||
* @return string for internal table used when calling only a function
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function functionTable()
|
|
||||||
{
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ now()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return string to call a variable with the current timestamp inside an SQL statement
|
|
||||||
* There are three special variables for current date and time:
|
|
||||||
* - CURRENT_TIMESTAMP (date and time, TIMESTAMP type)
|
|
||||||
* - CURRENT_DATE (date, DATE type)
|
|
||||||
* - CURRENT_TIME (time, TIME type)
|
|
||||||
*
|
|
||||||
* @param string $type 'timestamp' | 'time' | 'date'
|
|
||||||
*
|
|
||||||
* @return string to call a variable with the current timestamp
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function now($type = 'timestamp')
|
|
||||||
{
|
|
||||||
switch ($type) {
|
|
||||||
case 'time':
|
|
||||||
return 'CURRENT_TIME';
|
|
||||||
case 'date':
|
|
||||||
return 'CURRENT_DATE';
|
|
||||||
case 'timestamp':
|
|
||||||
default:
|
|
||||||
return 'CURRENT_TIMESTAMP';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ unixtimestamp()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return string to call a function to get the unix timestamp from a iso timestamp
|
|
||||||
*
|
|
||||||
* @param string $expression
|
|
||||||
*
|
|
||||||
* @return string to call a variable with the timestamp
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function unixtimestamp($expression)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$error = $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
|
||||||
'method not implemented', __FUNCTION__);
|
|
||||||
return $error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ substring()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return string to call a function to get a substring inside an SQL statement
|
|
||||||
*
|
|
||||||
* @return string to call a function to get a substring
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function substring($value, $position = 1, $length = null)
|
|
||||||
{
|
|
||||||
if (null !== $length) {
|
|
||||||
return "SUBSTRING($value FROM $position FOR $length)";
|
|
||||||
}
|
|
||||||
return "SUBSTRING($value FROM $position)";
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ replace()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return string to call a function to get replace inside an SQL statement.
|
|
||||||
*
|
|
||||||
* @return string to call a function to get a replace
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function replace($str, $from_str, $to_str)
|
|
||||||
{
|
|
||||||
return "REPLACE($str, $from_str , $to_str)";
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ concat()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns string to concatenate two or more string parameters
|
|
||||||
*
|
|
||||||
* @param string $value1
|
|
||||||
* @param string $value2
|
|
||||||
* @param string $values...
|
|
||||||
*
|
|
||||||
* @return string to concatenate two strings
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function concat($value1, $value2)
|
|
||||||
{
|
|
||||||
$args = func_get_args();
|
|
||||||
return "(".implode(' || ', $args).")";
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ random()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return string to call a function to get random value inside an SQL statement
|
|
||||||
*
|
|
||||||
* @return return string to generate float between 0 and 1
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function random()
|
|
||||||
{
|
|
||||||
return 'RAND()';
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ lower()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return string to call a function to lower the case of an expression
|
|
||||||
*
|
|
||||||
* @param string $expression
|
|
||||||
*
|
|
||||||
* @return return string to lower case of an expression
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function lower($expression)
|
|
||||||
{
|
|
||||||
return "LOWER($expression)";
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ upper()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return string to call a function to upper the case of an expression
|
|
||||||
*
|
|
||||||
* @param string $expression
|
|
||||||
*
|
|
||||||
* @return return string to upper case of an expression
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function upper($expression)
|
|
||||||
{
|
|
||||||
return "UPPER($expression)";
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ length()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return string to call a function to get the length of a string expression
|
|
||||||
*
|
|
||||||
* @param string $expression
|
|
||||||
*
|
|
||||||
* @return return string to get the string expression length
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function length($expression)
|
|
||||||
{
|
|
||||||
return "LENGTH($expression)";
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ guid()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns global unique identifier
|
|
||||||
*
|
|
||||||
* @return string to get global unique identifier
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function guid()
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$error = $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
|
||||||
'method not implemented', __FUNCTION__);
|
|
||||||
return $error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
}
|
|
||||||
?>
|
|
|
@ -1,136 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Lukas Smith <smith@pooteeweet.org> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
|
|
||||||
require_once 'MDB2/Driver/Function/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MDB2 MySQL driver for the function modules
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
class MDB2_Driver_Function_mysql extends MDB2_Driver_Function_Common
|
|
||||||
{
|
|
||||||
// }}}
|
|
||||||
// {{{ executeStoredProc()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute a stored procedure and return any results
|
|
||||||
*
|
|
||||||
* @param string $name string that identifies the function to execute
|
|
||||||
* @param mixed $params array that contains the paramaters to pass the stored proc
|
|
||||||
* @param mixed $types array that contains the types of the columns in
|
|
||||||
* the result set
|
|
||||||
* @param mixed $result_class string which specifies which result class to use
|
|
||||||
* @param mixed $result_wrap_class string which specifies which class to wrap results in
|
|
||||||
* @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = 'CALL '.$name;
|
|
||||||
$query .= $params ? '('.implode(', ', $params).')' : '()';
|
|
||||||
return $db->query($query, $types, $result_class, $result_wrap_class);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ unixtimestamp()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return string to call a function to get the unix timestamp from a iso timestamp
|
|
||||||
*
|
|
||||||
* @param string $expression
|
|
||||||
*
|
|
||||||
* @return string to call a variable with the timestamp
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function unixtimestamp($expression)
|
|
||||||
{
|
|
||||||
return 'UNIX_TIMESTAMP('. $expression.')';
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ concat()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns string to concatenate two or more string parameters
|
|
||||||
*
|
|
||||||
* @param string $value1
|
|
||||||
* @param string $value2
|
|
||||||
* @param string $values...
|
|
||||||
* @return string to concatenate two strings
|
|
||||||
* @access public
|
|
||||||
**/
|
|
||||||
function concat($value1, $value2)
|
|
||||||
{
|
|
||||||
$args = func_get_args();
|
|
||||||
return "CONCAT(".implode(', ', $args).")";
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ guid()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns global unique identifier
|
|
||||||
*
|
|
||||||
* @return string to get global unique identifier
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function guid()
|
|
||||||
{
|
|
||||||
return 'UUID()';
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
}
|
|
||||||
?>
|
|
|
@ -1,187 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Lukas Smith <smith@pooteeweet.org> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
|
|
||||||
// $Id: oci8.php 295587 2010-02-28 17:16:38Z quipo $
|
|
||||||
|
|
||||||
require_once 'MDB2/Driver/Function/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MDB2 oci8 driver for the function modules
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
class MDB2_Driver_Function_oci8 extends MDB2_Driver_Function_Common
|
|
||||||
{
|
|
||||||
// {{{ executeStoredProc()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute a stored procedure and return any results
|
|
||||||
*
|
|
||||||
* @param string $name string that identifies the function to execute
|
|
||||||
* @param mixed $params array that contains the paramaters to pass the stored proc
|
|
||||||
* @param mixed $types array that contains the types of the columns in
|
|
||||||
* the result set
|
|
||||||
* @param mixed $result_class string which specifies which result class to use
|
|
||||||
* @param mixed $result_wrap_class string which specifies which class to wrap results in
|
|
||||||
* @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = 'EXEC '.$name;
|
|
||||||
$query .= $params ? '('.implode(', ', $params).')' : '()';
|
|
||||||
return $db->query($query, $types, $result_class, $result_wrap_class);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ functionTable()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return string for internal table used when calling only a function
|
|
||||||
*
|
|
||||||
* @return string for internal table used when calling only a function
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function functionTable()
|
|
||||||
{
|
|
||||||
return ' FROM dual';
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ now()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return string to call a variable with the current timestamp inside an SQL statement
|
|
||||||
* There are three special variables for current date and time:
|
|
||||||
* - CURRENT_TIMESTAMP (date and time, TIMESTAMP type)
|
|
||||||
* - CURRENT_DATE (date, DATE type)
|
|
||||||
* - CURRENT_TIME (time, TIME type)
|
|
||||||
*
|
|
||||||
* @return string to call a variable with the current timestamp
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function now($type = 'timestamp')
|
|
||||||
{
|
|
||||||
switch ($type) {
|
|
||||||
case 'date':
|
|
||||||
case 'time':
|
|
||||||
case 'timestamp':
|
|
||||||
default:
|
|
||||||
return 'TO_CHAR(CURRENT_TIMESTAMP, \'YYYY-MM-DD HH24:MI:SS\')';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ unixtimestamp()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return string to call a function to get the unix timestamp from a iso timestamp
|
|
||||||
*
|
|
||||||
* @param string $expression
|
|
||||||
*
|
|
||||||
* @return string to call a variable with the timestamp
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function unixtimestamp($expression)
|
|
||||||
{
|
|
||||||
$utc_offset = 'CAST(SYS_EXTRACT_UTC(SYSTIMESTAMP) AS DATE) - CAST(SYSTIMESTAMP AS DATE)';
|
|
||||||
$epoch_date = 'to_date(\'19700101\', \'YYYYMMDD\')';
|
|
||||||
return '(CAST('.$expression.' AS DATE) - '.$epoch_date.' + '.$utc_offset.') * 86400 seconds';
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ substring()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return string to call a function to get a substring inside an SQL statement
|
|
||||||
*
|
|
||||||
* @return string to call a function to get a substring
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function substring($value, $position = 1, $length = null)
|
|
||||||
{
|
|
||||||
if (null !== $length) {
|
|
||||||
return "SUBSTR($value, $position, $length)";
|
|
||||||
}
|
|
||||||
return "SUBSTR($value, $position)";
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ random()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return string to call a function to get random value inside an SQL statement
|
|
||||||
*
|
|
||||||
* @return return string to generate float between 0 and 1
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function random()
|
|
||||||
{
|
|
||||||
return 'dbms_random.value';
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}}
|
|
||||||
// {{{ guid()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns global unique identifier
|
|
||||||
*
|
|
||||||
* @return string to get global unique identifier
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function guid()
|
|
||||||
{
|
|
||||||
return 'SYS_GUID()';
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}}
|
|
||||||
}
|
|
||||||
?>
|
|
|
@ -1,132 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Paul Cooper <pgc@ucecom.com> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
require_once 'MDB2/Driver/Function/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MDB2 MySQL driver for the function modules
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
class MDB2_Driver_Function_pgsql extends MDB2_Driver_Function_Common
|
|
||||||
{
|
|
||||||
// {{{ executeStoredProc()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute a stored procedure and return any results
|
|
||||||
*
|
|
||||||
* @param string $name string that identifies the function to execute
|
|
||||||
* @param mixed $params array that contains the paramaters to pass the stored proc
|
|
||||||
* @param mixed $types array that contains the types of the columns in
|
|
||||||
* the result set
|
|
||||||
* @param mixed $result_class string which specifies which result class to use
|
|
||||||
* @param mixed $result_wrap_class string which specifies which class to wrap results in
|
|
||||||
* @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = 'SELECT * FROM '.$name;
|
|
||||||
$query .= $params ? '('.implode(', ', $params).')' : '()';
|
|
||||||
return $db->query($query, $types, $result_class, $result_wrap_class);
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
// {{{ unixtimestamp()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return string to call a function to get the unix timestamp from a iso timestamp
|
|
||||||
*
|
|
||||||
* @param string $expression
|
|
||||||
*
|
|
||||||
* @return string to call a variable with the timestamp
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function unixtimestamp($expression)
|
|
||||||
{
|
|
||||||
return 'EXTRACT(EPOCH FROM DATE_TRUNC(\'seconds\', CAST ((' . $expression . ') AS TIMESTAMP)))';
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ substring()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return string to call a function to get a substring inside an SQL statement
|
|
||||||
*
|
|
||||||
* @return string to call a function to get a substring
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function substring($value, $position = 1, $length = null)
|
|
||||||
{
|
|
||||||
if (null !== $length) {
|
|
||||||
return "SUBSTRING(CAST($value AS VARCHAR) FROM $position FOR $length)";
|
|
||||||
}
|
|
||||||
return "SUBSTRING(CAST($value AS VARCHAR) FROM $position)";
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ random()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return string to call a function to get random value inside an SQL statement
|
|
||||||
*
|
|
||||||
* @return return string to generate float between 0 and 1
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function random()
|
|
||||||
{
|
|
||||||
return 'RANDOM()';
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
}
|
|
||||||
?>
|
|
|
@ -1,162 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Lukas Smith <smith@pooteeweet.org> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
|
|
||||||
require_once 'MDB2/Driver/Function/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MDB2 SQLite driver for the function modules
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
class MDB2_Driver_Function_sqlite extends MDB2_Driver_Function_Common
|
|
||||||
{
|
|
||||||
// {{{ constructor
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
function __construct($db_index)
|
|
||||||
{
|
|
||||||
parent::__construct($db_index);
|
|
||||||
// create all sorts of UDFs
|
|
||||||
}
|
|
||||||
|
|
||||||
// {{{ now()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return string to call a variable with the current timestamp inside an SQL statement
|
|
||||||
* There are three special variables for current date and time.
|
|
||||||
*
|
|
||||||
* @return string to call a variable with the current timestamp
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function now($type = 'timestamp')
|
|
||||||
{
|
|
||||||
switch ($type) {
|
|
||||||
case 'time':
|
|
||||||
return 'time(\'now\')';
|
|
||||||
case 'date':
|
|
||||||
return 'date(\'now\')';
|
|
||||||
case 'timestamp':
|
|
||||||
default:
|
|
||||||
return 'datetime(\'now\')';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ unixtimestamp()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return string to call a function to get the unix timestamp from a iso timestamp
|
|
||||||
*
|
|
||||||
* @param string $expression
|
|
||||||
*
|
|
||||||
* @return string to call a variable with the timestamp
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function unixtimestamp($expression)
|
|
||||||
{
|
|
||||||
return 'strftime("%s",'. $expression.', "utc")';
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ substring()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return string to call a function to get a substring inside an SQL statement
|
|
||||||
*
|
|
||||||
* @return string to call a function to get a substring
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function substring($value, $position = 1, $length = null)
|
|
||||||
{
|
|
||||||
if (null !== $length) {
|
|
||||||
return "substr($value, $position, $length)";
|
|
||||||
}
|
|
||||||
return "substr($value, $position, length($value))";
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ random()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return string to call a function to get random value inside an SQL statement
|
|
||||||
*
|
|
||||||
* @return return string to generate float between 0 and 1
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function random()
|
|
||||||
{
|
|
||||||
return '((RANDOM()+2147483648)/4294967296)';
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ replace()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return string to call a function to get a replacement inside an SQL statement.
|
|
||||||
*
|
|
||||||
* @return string to call a function to get a replace
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function replace($str, $from_str, $to_str)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$error = $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
|
||||||
'method not implemented', __FUNCTION__);
|
|
||||||
return $error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
}
|
|
||||||
?>
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,981 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Paul Cooper <pgc@ucecom.com> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
require_once 'MDB2/Driver/Manager/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MDB2 MySQL driver for the management modules
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Paul Cooper <pgc@ucecom.com>
|
|
||||||
*/
|
|
||||||
class MDB2_Driver_Manager_pgsql extends MDB2_Driver_Manager_Common
|
|
||||||
{
|
|
||||||
// {{{ createDatabase()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create a new database
|
|
||||||
*
|
|
||||||
* @param string $name name of the database that should be created
|
|
||||||
* @param array $options array with charset info
|
|
||||||
*
|
|
||||||
* @return mixed MDB2_OK on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function createDatabase($name, $options = array())
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$name = $db->quoteIdentifier($name, true);
|
|
||||||
$query = 'CREATE DATABASE ' . $name;
|
|
||||||
if (!empty($options['charset'])) {
|
|
||||||
$query .= ' WITH ENCODING ' . $db->quote($options['charset'], 'text');
|
|
||||||
}
|
|
||||||
return $db->standaloneQuery($query, null, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ alterDatabase()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* alter an existing database
|
|
||||||
*
|
|
||||||
* @param string $name name of the database that is intended to be changed
|
|
||||||
* @param array $options array with name, owner info
|
|
||||||
*
|
|
||||||
* @return mixed MDB2_OK on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function alterDatabase($name, $options = array())
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = '';
|
|
||||||
if (!empty($options['name'])) {
|
|
||||||
$query .= ' RENAME TO ' . $options['name'];
|
|
||||||
}
|
|
||||||
if (!empty($options['owner'])) {
|
|
||||||
$query .= ' OWNER TO ' . $options['owner'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($query)) {
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = 'ALTER DATABASE '. $db->quoteIdentifier($name, true) . $query;
|
|
||||||
return $db->standaloneQuery($query, null, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ dropDatabase()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* drop an existing database
|
|
||||||
*
|
|
||||||
* @param string $name name of the database that should be dropped
|
|
||||||
* @return mixed MDB2_OK on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function dropDatabase($name)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$name = $db->quoteIdentifier($name, true);
|
|
||||||
$query = "DROP DATABASE $name";
|
|
||||||
return $db->standaloneQuery($query, null, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _getAdvancedFKOptions()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the FOREIGN KEY query section dealing with non-standard options
|
|
||||||
* as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
|
|
||||||
*
|
|
||||||
* @param array $definition
|
|
||||||
* @return string
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
function _getAdvancedFKOptions($definition)
|
|
||||||
{
|
|
||||||
$query = '';
|
|
||||||
if (!empty($definition['match'])) {
|
|
||||||
$query .= ' MATCH '.$definition['match'];
|
|
||||||
}
|
|
||||||
if (!empty($definition['onupdate'])) {
|
|
||||||
$query .= ' ON UPDATE '.$definition['onupdate'];
|
|
||||||
}
|
|
||||||
if (!empty($definition['ondelete'])) {
|
|
||||||
$query .= ' ON DELETE '.$definition['ondelete'];
|
|
||||||
}
|
|
||||||
if (!empty($definition['deferrable'])) {
|
|
||||||
$query .= ' DEFERRABLE';
|
|
||||||
} else {
|
|
||||||
$query .= ' NOT DEFERRABLE';
|
|
||||||
}
|
|
||||||
if (!empty($definition['initiallydeferred'])) {
|
|
||||||
$query .= ' INITIALLY DEFERRED';
|
|
||||||
} else {
|
|
||||||
$query .= ' INITIALLY IMMEDIATE';
|
|
||||||
}
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ truncateTable()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Truncate an existing table (if the TRUNCATE TABLE syntax is not supported,
|
|
||||||
* it falls back to a DELETE FROM TABLE query)
|
|
||||||
*
|
|
||||||
* @param string $name name of the table that should be truncated
|
|
||||||
* @return mixed MDB2_OK on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function truncateTable($name)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$name = $db->quoteIdentifier($name, true);
|
|
||||||
$result = $db->exec("TRUNCATE TABLE $name");
|
|
||||||
if (MDB2::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ vacuum()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Optimize (vacuum) all the tables in the db (or only the specified table)
|
|
||||||
* and optionally run ANALYZE.
|
|
||||||
*
|
|
||||||
* @param string $table table name (all the tables if empty)
|
|
||||||
* @param array $options an array with driver-specific options:
|
|
||||||
* - timeout [int] (in seconds) [mssql-only]
|
|
||||||
* - analyze [boolean] [pgsql and mysql]
|
|
||||||
* - full [boolean] [pgsql-only]
|
|
||||||
* - freeze [boolean] [pgsql-only]
|
|
||||||
*
|
|
||||||
* @return mixed MDB2_OK success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function vacuum($table = null, $options = array())
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
$query = 'VACUUM';
|
|
||||||
|
|
||||||
if (!empty($options['full'])) {
|
|
||||||
$query .= ' FULL';
|
|
||||||
}
|
|
||||||
if (!empty($options['freeze'])) {
|
|
||||||
$query .= ' FREEZE';
|
|
||||||
}
|
|
||||||
if (!empty($options['analyze'])) {
|
|
||||||
$query .= ' ANALYZE';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($table)) {
|
|
||||||
$query .= ' '.$db->quoteIdentifier($table, true);
|
|
||||||
}
|
|
||||||
$result = $db->exec($query);
|
|
||||||
if (MDB2::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ alterTable()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* alter an existing table
|
|
||||||
*
|
|
||||||
* @param string $name name of the table that is intended to be changed.
|
|
||||||
* @param array $changes associative array that contains the details of each type
|
|
||||||
* of change that is intended to be performed. The types of
|
|
||||||
* changes that are currently supported are defined as follows:
|
|
||||||
*
|
|
||||||
* name
|
|
||||||
*
|
|
||||||
* New name for the table.
|
|
||||||
*
|
|
||||||
* add
|
|
||||||
*
|
|
||||||
* Associative array with the names of fields to be added as
|
|
||||||
* indexes of the array. The value of each entry of the array
|
|
||||||
* should be set to another associative array with the properties
|
|
||||||
* of the fields to be added. The properties of the fields should
|
|
||||||
* be the same as defined by the MDB2 parser.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* remove
|
|
||||||
*
|
|
||||||
* Associative array with the names of fields to be removed as indexes
|
|
||||||
* of the array. Currently the values assigned to each entry are ignored.
|
|
||||||
* An empty array should be used for future compatibility.
|
|
||||||
*
|
|
||||||
* rename
|
|
||||||
*
|
|
||||||
* Associative array with the names of fields to be renamed as indexes
|
|
||||||
* of the array. The value of each entry of the array should be set to
|
|
||||||
* another associative array with the entry named name with the new
|
|
||||||
* field name and the entry named Declaration that is expected to contain
|
|
||||||
* the portion of the field declaration already in DBMS specific SQL code
|
|
||||||
* as it is used in the CREATE TABLE statement.
|
|
||||||
*
|
|
||||||
* change
|
|
||||||
*
|
|
||||||
* Associative array with the names of the fields to be changed as indexes
|
|
||||||
* of the array. Keep in mind that if it is intended to change either the
|
|
||||||
* name of a field and any other properties, the change array entries
|
|
||||||
* should have the new names of the fields as array indexes.
|
|
||||||
*
|
|
||||||
* The value of each entry of the array should be set to another associative
|
|
||||||
* array with the properties of the fields to that are meant to be changed as
|
|
||||||
* array entries. These entries should be assigned to the new values of the
|
|
||||||
* respective properties. The properties of the fields should be the same
|
|
||||||
* as defined by the MDB2 parser.
|
|
||||||
*
|
|
||||||
* Example
|
|
||||||
* array(
|
|
||||||
* 'name' => 'userlist',
|
|
||||||
* 'add' => array(
|
|
||||||
* 'quota' => array(
|
|
||||||
* 'type' => 'integer',
|
|
||||||
* 'unsigned' => 1
|
|
||||||
* )
|
|
||||||
* ),
|
|
||||||
* 'remove' => array(
|
|
||||||
* 'file_limit' => array(),
|
|
||||||
* 'time_limit' => array()
|
|
||||||
* ),
|
|
||||||
* 'change' => array(
|
|
||||||
* 'name' => array(
|
|
||||||
* 'length' => '20',
|
|
||||||
* 'definition' => array(
|
|
||||||
* 'type' => 'text',
|
|
||||||
* 'length' => 20,
|
|
||||||
* ),
|
|
||||||
* )
|
|
||||||
* ),
|
|
||||||
* 'rename' => array(
|
|
||||||
* 'sex' => array(
|
|
||||||
* 'name' => 'gender',
|
|
||||||
* 'definition' => array(
|
|
||||||
* 'type' => 'text',
|
|
||||||
* 'length' => 1,
|
|
||||||
* 'default' => 'M',
|
|
||||||
* ),
|
|
||||||
* )
|
|
||||||
* )
|
|
||||||
* )
|
|
||||||
*
|
|
||||||
* @param boolean $check indicates whether the function should just check if the DBMS driver
|
|
||||||
* can perform the requested table alterations if the value is true or
|
|
||||||
* actually perform them otherwise.
|
|
||||||
* @access public
|
|
||||||
*
|
|
||||||
* @return mixed MDB2_OK on success, a MDB2 error on failure
|
|
||||||
*/
|
|
||||||
function alterTable($name, $changes, $check)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($changes as $change_name => $change) {
|
|
||||||
switch ($change_name) {
|
|
||||||
case 'add':
|
|
||||||
case 'remove':
|
|
||||||
case 'change':
|
|
||||||
case 'name':
|
|
||||||
case 'rename':
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null,
|
|
||||||
'change type "'.$change_name.'\" not yet supported', __FUNCTION__);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($check) {
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
$name = $db->quoteIdentifier($name, true);
|
|
||||||
|
|
||||||
if (!empty($changes['remove']) && is_array($changes['remove'])) {
|
|
||||||
foreach ($changes['remove'] as $field_name => $field) {
|
|
||||||
$field_name = $db->quoteIdentifier($field_name, true);
|
|
||||||
$query = 'DROP ' . $field_name;
|
|
||||||
$result = $db->exec("ALTER TABLE $name $query");
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($changes['rename']) && is_array($changes['rename'])) {
|
|
||||||
foreach ($changes['rename'] as $field_name => $field) {
|
|
||||||
$field_name = $db->quoteIdentifier($field_name, true);
|
|
||||||
$result = $db->exec("ALTER TABLE $name RENAME COLUMN $field_name TO ".$db->quoteIdentifier($field['name'], true));
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($changes['add']) && is_array($changes['add'])) {
|
|
||||||
foreach ($changes['add'] as $field_name => $field) {
|
|
||||||
$query = 'ADD ' . $db->getDeclaration($field['type'], $field_name, $field);
|
|
||||||
$result = $db->exec("ALTER TABLE $name $query");
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($changes['change']) && is_array($changes['change'])) {
|
|
||||||
foreach ($changes['change'] as $field_name => $field) {
|
|
||||||
$field_name = $db->quoteIdentifier($field_name, true);
|
|
||||||
if (!empty($field['definition']['type'])) {
|
|
||||||
$server_info = $db->getServerVersion();
|
|
||||||
if (PEAR::isError($server_info)) {
|
|
||||||
return $server_info;
|
|
||||||
}
|
|
||||||
if (is_array($server_info) && $server_info['major'] < 8) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null,
|
|
||||||
'changing column type for "'.$change_name.'\" requires PostgreSQL 8.0 or above', __FUNCTION__);
|
|
||||||
}
|
|
||||||
$db->loadModule('Datatype', null, true);
|
|
||||||
$type = $db->datatype->getTypeDeclaration($field['definition']);
|
|
||||||
if($type=='SERIAL PRIMARY KEY'){//not correct when altering a table, since serials arent a real type
|
|
||||||
$type='INTEGER';//use integer instead
|
|
||||||
}
|
|
||||||
$query = "ALTER $field_name TYPE $type USING CAST($field_name AS $type)";
|
|
||||||
$result = $db->exec("ALTER TABLE $name $query");
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (array_key_exists('default', $field['definition'])) {
|
|
||||||
$query = "ALTER $field_name SET DEFAULT ".$db->quote($field['definition']['default'], $field['definition']['type']);
|
|
||||||
$result = $db->exec("ALTER TABLE $name $query");
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (array_key_exists('notnull', $field['definition'])) {
|
|
||||||
$query = "ALTER $field_name ".($field['definition']['notnull'] ? 'SET' : 'DROP').' NOT NULL';
|
|
||||||
$result = $db->exec("ALTER TABLE $name $query");
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($changes['name'])) {
|
|
||||||
$change_name = $db->quoteIdentifier($changes['name'], true);
|
|
||||||
$result = $db->exec("ALTER TABLE $name RENAME TO ".$change_name);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ listDatabases()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list all databases
|
|
||||||
*
|
|
||||||
* @return mixed array of database names on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function listDatabases()
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = 'SELECT datname FROM pg_database';
|
|
||||||
$result2 = $db->standaloneQuery($query, array('text'), false);
|
|
||||||
if (!MDB2::isResultCommon($result2)) {
|
|
||||||
return $result2;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $result2->fetchCol();
|
|
||||||
$result2->free();
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ listUsers()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list all users
|
|
||||||
*
|
|
||||||
* @return mixed array of user names on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function listUsers()
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = 'SELECT usename FROM pg_user';
|
|
||||||
$result2 = $db->standaloneQuery($query, array('text'), false);
|
|
||||||
if (!MDB2::isResultCommon($result2)) {
|
|
||||||
return $result2;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $result2->fetchCol();
|
|
||||||
$result2->free();
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ listViews()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list all views in the current database
|
|
||||||
*
|
|
||||||
* @return mixed array of view names on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function listViews($database = null)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = "SELECT viewname
|
|
||||||
FROM pg_views
|
|
||||||
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
|
|
||||||
AND viewname !~ '^pg_'";
|
|
||||||
$result = $db->queryCol($query);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ listTableViews()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list the views in the database that reference a given table
|
|
||||||
*
|
|
||||||
* @param string table for which all referenced views should be found
|
|
||||||
* @return mixed array of view names on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function listTableViews($table)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = 'SELECT viewname FROM pg_views NATURAL JOIN pg_tables';
|
|
||||||
$query.= ' WHERE tablename ='.$db->quote($table, 'text');
|
|
||||||
$result = $db->queryCol($query);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ listFunctions()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list all functions in the current database
|
|
||||||
*
|
|
||||||
* @return mixed array of function names on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function listFunctions()
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = "
|
|
||||||
SELECT
|
|
||||||
proname
|
|
||||||
FROM
|
|
||||||
pg_proc pr,
|
|
||||||
pg_type tp
|
|
||||||
WHERE
|
|
||||||
tp.oid = pr.prorettype
|
|
||||||
AND pr.proisagg = FALSE
|
|
||||||
AND tp.typname <> 'trigger'
|
|
||||||
AND pr.pronamespace IN
|
|
||||||
(SELECT oid FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema')";
|
|
||||||
$result = $db->queryCol($query);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ listTableTriggers()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list all triggers in the database that reference a given table
|
|
||||||
*
|
|
||||||
* @param string table for which all referenced triggers should be found
|
|
||||||
* @return mixed array of trigger names on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function listTableTriggers($table = null)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = 'SELECT trg.tgname AS trigger_name
|
|
||||||
FROM pg_trigger trg,
|
|
||||||
pg_class tbl
|
|
||||||
WHERE trg.tgrelid = tbl.oid';
|
|
||||||
if (null !== $table) {
|
|
||||||
$table = $db->quote(strtoupper($table), 'text');
|
|
||||||
$query .= " AND UPPER(tbl.relname) = $table";
|
|
||||||
}
|
|
||||||
$result = $db->queryCol($query);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ listTables()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list all tables in the current database
|
|
||||||
*
|
|
||||||
* @return mixed array of table names on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function listTables($database = null)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
// gratuitously stolen from PEAR DB _getSpecialQuery in pgsql.php
|
|
||||||
$query = 'SELECT c.relname AS "Name"'
|
|
||||||
. ' FROM pg_class c, pg_user u'
|
|
||||||
. ' WHERE c.relowner = u.usesysid'
|
|
||||||
. " AND c.relkind = 'r'"
|
|
||||||
. ' AND NOT EXISTS'
|
|
||||||
. ' (SELECT 1 FROM pg_views'
|
|
||||||
. ' WHERE viewname = c.relname)'
|
|
||||||
. " AND c.relname !~ '^(pg_|sql_)'"
|
|
||||||
. ' UNION'
|
|
||||||
. ' SELECT c.relname AS "Name"'
|
|
||||||
. ' FROM pg_class c'
|
|
||||||
. " WHERE c.relkind = 'r'"
|
|
||||||
. ' AND NOT EXISTS'
|
|
||||||
. ' (SELECT 1 FROM pg_views'
|
|
||||||
. ' WHERE viewname = c.relname)'
|
|
||||||
. ' AND NOT EXISTS'
|
|
||||||
. ' (SELECT 1 FROM pg_user'
|
|
||||||
. ' WHERE usesysid = c.relowner)'
|
|
||||||
. " AND c.relname !~ '^pg_'";
|
|
||||||
$result = $db->queryCol($query);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ listTableFields()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list all fields in a table in the current database
|
|
||||||
*
|
|
||||||
* @param string $table name of table that should be used in method
|
|
||||||
* @return mixed array of field names on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function listTableFields($table)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
list($schema, $table) = $this->splitTableSchema($table);
|
|
||||||
|
|
||||||
$table = $db->quoteIdentifier($table, true);
|
|
||||||
if (!empty($schema)) {
|
|
||||||
$table = $db->quoteIdentifier($schema, true) . '.' .$table;
|
|
||||||
}
|
|
||||||
$db->setLimit(1);
|
|
||||||
$result2 = $db->query("SELECT * FROM $table");
|
|
||||||
if (PEAR::isError($result2)) {
|
|
||||||
return $result2;
|
|
||||||
}
|
|
||||||
$result = $result2->getColumnNames();
|
|
||||||
$result2->free();
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
return array_flip($result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ listTableIndexes()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list all indexes in a table
|
|
||||||
*
|
|
||||||
* @param string $table name of table that should be used in method
|
|
||||||
* @return mixed array of index names on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function listTableIndexes($table)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
list($schema, $table) = $this->splitTableSchema($table);
|
|
||||||
|
|
||||||
$table = $db->quote($table, 'text');
|
|
||||||
$subquery = "SELECT indexrelid
|
|
||||||
FROM pg_index
|
|
||||||
LEFT JOIN pg_class ON pg_class.oid = pg_index.indrelid
|
|
||||||
LEFT JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
|
|
||||||
WHERE pg_class.relname = $table
|
|
||||||
AND indisunique != 't'
|
|
||||||
AND indisprimary != 't'";
|
|
||||||
if (!empty($schema)) {
|
|
||||||
$subquery .= ' AND pg_namespace.nspname = '.$db->quote($schema, 'text');
|
|
||||||
}
|
|
||||||
$query = "SELECT relname FROM pg_class WHERE oid IN ($subquery)";
|
|
||||||
$indexes = $db->queryCol($query, 'text');
|
|
||||||
if (PEAR::isError($indexes)) {
|
|
||||||
return $indexes;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = array();
|
|
||||||
foreach ($indexes as $index) {
|
|
||||||
$index = $this->_fixIndexName($index);
|
|
||||||
if (!empty($index)) {
|
|
||||||
$result[$index] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
$result = array_change_key_case($result, $db->options['field_case']);
|
|
||||||
}
|
|
||||||
return array_keys($result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ dropConstraint()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* drop existing constraint
|
|
||||||
*
|
|
||||||
* @param string $table name of table that should be used in method
|
|
||||||
* @param string $name name of the constraint to be dropped
|
|
||||||
* @param string $primary hint if the constraint is primary
|
|
||||||
*
|
|
||||||
* @return mixed MDB2_OK on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function dropConstraint($table, $name, $primary = false)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
// is it an UNIQUE index?
|
|
||||||
$query = 'SELECT relname
|
|
||||||
FROM pg_class
|
|
||||||
WHERE oid IN (
|
|
||||||
SELECT indexrelid
|
|
||||||
FROM pg_index, pg_class
|
|
||||||
WHERE pg_class.relname = '.$db->quote($table, 'text').'
|
|
||||||
AND pg_class.oid = pg_index.indrelid
|
|
||||||
AND indisunique = \'t\')
|
|
||||||
EXCEPT
|
|
||||||
SELECT conname
|
|
||||||
FROM pg_constraint, pg_class
|
|
||||||
WHERE pg_constraint.conrelid = pg_class.oid
|
|
||||||
AND relname = '. $db->quote($table, 'text');
|
|
||||||
$unique = $db->queryCol($query, 'text');
|
|
||||||
if (PEAR::isError($unique) || empty($unique)) {
|
|
||||||
// not an UNIQUE index, maybe a CONSTRAINT
|
|
||||||
return parent::dropConstraint($table, $name, $primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_array($name, $unique)) {
|
|
||||||
$result = $db->exec('DROP INDEX '.$db->quoteIdentifier($name, true));
|
|
||||||
if (MDB2::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
$idxname = $db->getIndexName($name);
|
|
||||||
if (in_array($idxname, $unique)) {
|
|
||||||
$result = $db->exec('DROP INDEX '.$db->quoteIdentifier($idxname, true));
|
|
||||||
if (MDB2::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
$name . ' is not an existing constraint for table ' . $table, __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ listTableConstraints()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list all constraints in a table
|
|
||||||
*
|
|
||||||
* @param string $table name of table that should be used in method
|
|
||||||
* @return mixed array of constraint names on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function listTableConstraints($table)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
list($schema, $table) = $this->splitTableSchema($table);
|
|
||||||
|
|
||||||
$table = $db->quote($table, 'text');
|
|
||||||
$query = 'SELECT conname
|
|
||||||
FROM pg_constraint
|
|
||||||
LEFT JOIN pg_class ON pg_constraint.conrelid = pg_class.oid
|
|
||||||
LEFT JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
|
|
||||||
WHERE relname = ' .$table;
|
|
||||||
if (!empty($schema)) {
|
|
||||||
$query .= ' AND pg_namespace.nspname = ' . $db->quote($schema, 'text');
|
|
||||||
}
|
|
||||||
$query .= '
|
|
||||||
UNION DISTINCT
|
|
||||||
SELECT relname
|
|
||||||
FROM pg_class
|
|
||||||
WHERE oid IN (
|
|
||||||
SELECT indexrelid
|
|
||||||
FROM pg_index
|
|
||||||
LEFT JOIN pg_class ON pg_class.oid = pg_index.indrelid
|
|
||||||
LEFT JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
|
|
||||||
WHERE pg_class.relname = '.$table.'
|
|
||||||
AND indisunique = \'t\'';
|
|
||||||
if (!empty($schema)) {
|
|
||||||
$query .= ' AND pg_namespace.nspname = ' . $db->quote($schema, 'text');
|
|
||||||
}
|
|
||||||
$query .= ')';
|
|
||||||
$constraints = $db->queryCol($query);
|
|
||||||
if (PEAR::isError($constraints)) {
|
|
||||||
return $constraints;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = array();
|
|
||||||
foreach ($constraints as $constraint) {
|
|
||||||
$constraint = $this->_fixIndexName($constraint);
|
|
||||||
if (!empty($constraint)) {
|
|
||||||
$result[$constraint] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE
|
|
||||||
&& $db->options['field_case'] == CASE_LOWER
|
|
||||||
) {
|
|
||||||
$result = array_change_key_case($result, $db->options['field_case']);
|
|
||||||
}
|
|
||||||
return array_keys($result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ createSequence()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create sequence
|
|
||||||
*
|
|
||||||
* @param string $seq_name name of the sequence to be created
|
|
||||||
* @param string $start start value of the sequence; default is 1
|
|
||||||
* @return mixed MDB2_OK on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function createSequence($seq_name, $start = 1)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
|
|
||||||
$result = $db->exec("CREATE SEQUENCE $sequence_name INCREMENT 1".
|
|
||||||
($start < 1 ? " MINVALUE $start" : '')." START $start");
|
|
||||||
if (MDB2::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ dropSequence()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* drop existing sequence
|
|
||||||
*
|
|
||||||
* @param string $seq_name name of the sequence to be dropped
|
|
||||||
* @return mixed MDB2_OK on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function dropSequence($seq_name)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
|
|
||||||
$result = $db->exec("DROP SEQUENCE $sequence_name");
|
|
||||||
if (MDB2::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ listSequences()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list all sequences in the current database
|
|
||||||
*
|
|
||||||
* @return mixed array of sequence names on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function listSequences($database = null)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = "SELECT relname FROM pg_class WHERE relkind = 'S' AND relnamespace IN";
|
|
||||||
$query.= "(SELECT oid FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema')";
|
|
||||||
$table_names = $db->queryCol($query);
|
|
||||||
if (PEAR::isError($table_names)) {
|
|
||||||
return $table_names;
|
|
||||||
}
|
|
||||||
$result = array();
|
|
||||||
foreach ($table_names as $table_name) {
|
|
||||||
$result[] = $this->_fixSequenceName($table_name);
|
|
||||||
}
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,61 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Lukas Smith <smith@pooteeweet.org> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for the natuve modules that is extended by each MDB2 driver
|
|
||||||
*
|
|
||||||
* To load this module in the MDB2 object:
|
|
||||||
* $mdb->loadModule('Native');
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
class MDB2_Driver_Native_Common extends MDB2_Module_Common
|
|
||||||
{
|
|
||||||
}
|
|
||||||
?>
|
|
|
@ -1,60 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Lukas Smith <smith@pooteeweet.org> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
|
|
||||||
require_once 'MDB2/Driver/Native/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MDB2 MySQL driver for the native module
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
class MDB2_Driver_Native_mysql extends MDB2_Driver_Native_Common
|
|
||||||
{
|
|
||||||
}
|
|
||||||
?>
|
|
|
@ -1,60 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith, Frank M. Kromann |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Lukas Smith <smith@pooteeweet.org> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id: oci8.php 215004 2006-06-18 21:59:05Z lsmith $
|
|
||||||
//
|
|
||||||
|
|
||||||
require_once 'MDB2/Driver/Native/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MDB2 Oracle driver for the native module
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@dybnet.de>
|
|
||||||
*/
|
|
||||||
class MDB2_Driver_Native_oci8 extends MDB2_Driver_Native_Common
|
|
||||||
{
|
|
||||||
}
|
|
||||||
?>
|
|
|
@ -1,88 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Paul Cooper <pgc@ucecom.com> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
require_once 'MDB2/Driver/Native/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MDB2 PostGreSQL driver for the native module
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Paul Cooper <pgc@ucecom.com>
|
|
||||||
*/
|
|
||||||
class MDB2_Driver_Native_pgsql extends MDB2_Driver_Native_Common
|
|
||||||
{
|
|
||||||
// }}}
|
|
||||||
// {{{ deleteOID()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* delete an OID
|
|
||||||
*
|
|
||||||
* @param integer $OID
|
|
||||||
* @return mixed MDB2_OK on success or MDB2 Error Object on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function deleteOID($OID)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$connection = $db->getConnection();
|
|
||||||
if (PEAR::isError($connection)) {
|
|
||||||
return $connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!@pg_lo_unlink($connection, $OID)) {
|
|
||||||
return $db->raiseError(null, null, null,
|
|
||||||
'Unable to unlink OID: '.$OID, __FUNCTION__);
|
|
||||||
}
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
?>
|
|
|
@ -1,60 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Lukas Smith <smith@pooteeweet.org> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
|
|
||||||
require_once 'MDB2/Driver/Native/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MDB2 SQLite driver for the native module
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
class MDB2_Driver_Native_sqlite extends MDB2_Driver_Native_Common
|
|
||||||
{
|
|
||||||
}
|
|
||||||
?>
|
|
|
@ -1,517 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Lukas Smith <smith@pooteeweet.org> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* These are constants for the tableInfo-function
|
|
||||||
* they are bitwised or'ed. so if there are more constants to be defined
|
|
||||||
* in the future, adjust MDB2_TABLEINFO_FULL accordingly
|
|
||||||
*/
|
|
||||||
|
|
||||||
define('MDB2_TABLEINFO_ORDER', 1);
|
|
||||||
define('MDB2_TABLEINFO_ORDERTABLE', 2);
|
|
||||||
define('MDB2_TABLEINFO_FULL', 3);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for the schema reverse engineering module that is extended by each MDB2 driver
|
|
||||||
*
|
|
||||||
* To load this module in the MDB2 object:
|
|
||||||
* $mdb->loadModule('Reverse');
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
class MDB2_Driver_Reverse_Common extends MDB2_Module_Common
|
|
||||||
{
|
|
||||||
// {{{ splitTableSchema()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Split the "[owner|schema].table" notation into an array
|
|
||||||
*
|
|
||||||
* @param string $table [schema and] table name
|
|
||||||
*
|
|
||||||
* @return array array(schema, table)
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
function splitTableSchema($table)
|
|
||||||
{
|
|
||||||
$ret = array();
|
|
||||||
if (strpos($table, '.') !== false) {
|
|
||||||
return explode('.', $table);
|
|
||||||
}
|
|
||||||
return array(null, $table);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getTableFieldDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the structure of a field into an array
|
|
||||||
*
|
|
||||||
* @param string $table name of table that should be used in method
|
|
||||||
* @param string $field name of field that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure.
|
|
||||||
* The returned array contains an array for each field definition,
|
|
||||||
* with all or some of these indices, depending on the field data type:
|
|
||||||
* [notnull] [nativetype] [length] [fixed] [default] [type] [mdb2type]
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTableFieldDefinition($table, $field)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
|
||||||
'method not implemented', __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getTableIndexDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the structure of an index into an array
|
|
||||||
*
|
|
||||||
* @param string $table name of table that should be used in method
|
|
||||||
* @param string $index name of index that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure
|
|
||||||
* The returned array has this structure:
|
|
||||||
* </pre>
|
|
||||||
* array (
|
|
||||||
* [fields] => array (
|
|
||||||
* [field1name] => array() // one entry per each field covered
|
|
||||||
* [field2name] => array() // by the index
|
|
||||||
* [field3name] => array(
|
|
||||||
* [sorting] => ascending
|
|
||||||
* )
|
|
||||||
* )
|
|
||||||
* );
|
|
||||||
* </pre>
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTableIndexDefinition($table, $index)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
|
||||||
'method not implemented', __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getTableConstraintDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the structure of an constraints into an array
|
|
||||||
*
|
|
||||||
* @param string $table name of table that should be used in method
|
|
||||||
* @param string $index name of index that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure
|
|
||||||
* The returned array has this structure:
|
|
||||||
* <pre>
|
|
||||||
* array (
|
|
||||||
* [primary] => 0
|
|
||||||
* [unique] => 0
|
|
||||||
* [foreign] => 1
|
|
||||||
* [check] => 0
|
|
||||||
* [fields] => array (
|
|
||||||
* [field1name] => array() // one entry per each field covered
|
|
||||||
* [field2name] => array() // by the index
|
|
||||||
* [field3name] => array(
|
|
||||||
* [sorting] => ascending
|
|
||||||
* [position] => 3
|
|
||||||
* )
|
|
||||||
* )
|
|
||||||
* [references] => array(
|
|
||||||
* [table] => name
|
|
||||||
* [fields] => array(
|
|
||||||
* [field1name] => array( //one entry per each referenced field
|
|
||||||
* [position] => 1
|
|
||||||
* )
|
|
||||||
* )
|
|
||||||
* )
|
|
||||||
* [deferrable] => 0
|
|
||||||
* [initiallydeferred] => 0
|
|
||||||
* [onupdate] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION
|
|
||||||
* [ondelete] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION
|
|
||||||
* [match] => SIMPLE|PARTIAL|FULL
|
|
||||||
* );
|
|
||||||
* </pre>
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTableConstraintDefinition($table, $index)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
|
||||||
'method not implemented', __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getSequenceDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the structure of a sequence into an array
|
|
||||||
*
|
|
||||||
* @param string $sequence name of sequence that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure
|
|
||||||
* The returned array has this structure:
|
|
||||||
* <pre>
|
|
||||||
* array (
|
|
||||||
* [start] => n
|
|
||||||
* );
|
|
||||||
* </pre>
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getSequenceDefinition($sequence)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$start = $db->currId($sequence);
|
|
||||||
if (PEAR::isError($start)) {
|
|
||||||
return $start;
|
|
||||||
}
|
|
||||||
if ($db->supports('current_id')) {
|
|
||||||
$start++;
|
|
||||||
} else {
|
|
||||||
$db->warnings[] = 'database does not support getting current
|
|
||||||
sequence value, the sequence value was incremented';
|
|
||||||
}
|
|
||||||
$definition = array();
|
|
||||||
if ($start != 1) {
|
|
||||||
$definition = array('start' => $start);
|
|
||||||
}
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getTriggerDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the structure of a trigger into an array
|
|
||||||
*
|
|
||||||
* EXPERIMENTAL
|
|
||||||
*
|
|
||||||
* WARNING: this function is experimental and may change the returned value
|
|
||||||
* at any time until labelled as non-experimental
|
|
||||||
*
|
|
||||||
* @param string $trigger name of trigger that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure
|
|
||||||
* The returned array has this structure:
|
|
||||||
* <pre>
|
|
||||||
* array (
|
|
||||||
* [trigger_name] => 'trigger name',
|
|
||||||
* [table_name] => 'table name',
|
|
||||||
* [trigger_body] => 'trigger body definition',
|
|
||||||
* [trigger_type] => 'BEFORE' | 'AFTER',
|
|
||||||
* [trigger_event] => 'INSERT' | 'UPDATE' | 'DELETE'
|
|
||||||
* //or comma separated list of multiple events, when supported
|
|
||||||
* [trigger_enabled] => true|false
|
|
||||||
* [trigger_comment] => 'trigger comment',
|
|
||||||
* );
|
|
||||||
* </pre>
|
|
||||||
* The oci8 driver also returns a [when_clause] index.
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTriggerDefinition($trigger)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
|
||||||
'method not implemented', __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ tableInfo()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns information about a table or a result set
|
|
||||||
*
|
|
||||||
* The format of the resulting array depends on which <var>$mode</var>
|
|
||||||
* you select. The sample output below is based on this query:
|
|
||||||
* <pre>
|
|
||||||
* SELECT tblFoo.fldID, tblFoo.fldPhone, tblBar.fldId
|
|
||||||
* FROM tblFoo
|
|
||||||
* JOIN tblBar ON tblFoo.fldId = tblBar.fldId
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* <ul>
|
|
||||||
* <li>
|
|
||||||
*
|
|
||||||
* <kbd>null</kbd> (default)
|
|
||||||
* <pre>
|
|
||||||
* [0] => Array (
|
|
||||||
* [table] => tblFoo
|
|
||||||
* [name] => fldId
|
|
||||||
* [type] => int
|
|
||||||
* [len] => 11
|
|
||||||
* [flags] => primary_key not_null
|
|
||||||
* )
|
|
||||||
* [1] => Array (
|
|
||||||
* [table] => tblFoo
|
|
||||||
* [name] => fldPhone
|
|
||||||
* [type] => string
|
|
||||||
* [len] => 20
|
|
||||||
* [flags] =>
|
|
||||||
* )
|
|
||||||
* [2] => Array (
|
|
||||||
* [table] => tblBar
|
|
||||||
* [name] => fldId
|
|
||||||
* [type] => int
|
|
||||||
* [len] => 11
|
|
||||||
* [flags] => primary_key not_null
|
|
||||||
* )
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* </li><li>
|
|
||||||
*
|
|
||||||
* <kbd>MDB2_TABLEINFO_ORDER</kbd>
|
|
||||||
*
|
|
||||||
* <p>In addition to the information found in the default output,
|
|
||||||
* a notation of the number of columns is provided by the
|
|
||||||
* <samp>num_fields</samp> element while the <samp>order</samp>
|
|
||||||
* element provides an array with the column names as the keys and
|
|
||||||
* their location index number (corresponding to the keys in the
|
|
||||||
* the default output) as the values.</p>
|
|
||||||
*
|
|
||||||
* <p>If a result set has identical field names, the last one is
|
|
||||||
* used.</p>
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* [num_fields] => 3
|
|
||||||
* [order] => Array (
|
|
||||||
* [fldId] => 2
|
|
||||||
* [fldTrans] => 1
|
|
||||||
* )
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* </li><li>
|
|
||||||
*
|
|
||||||
* <kbd>MDB2_TABLEINFO_ORDERTABLE</kbd>
|
|
||||||
*
|
|
||||||
* <p>Similar to <kbd>MDB2_TABLEINFO_ORDER</kbd> but adds more
|
|
||||||
* dimensions to the array in which the table names are keys and
|
|
||||||
* the field names are sub-keys. This is helpful for queries that
|
|
||||||
* join tables which have identical field names.</p>
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* [num_fields] => 3
|
|
||||||
* [ordertable] => Array (
|
|
||||||
* [tblFoo] => Array (
|
|
||||||
* [fldId] => 0
|
|
||||||
* [fldPhone] => 1
|
|
||||||
* )
|
|
||||||
* [tblBar] => Array (
|
|
||||||
* [fldId] => 2
|
|
||||||
* )
|
|
||||||
* )
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* </li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* The <samp>flags</samp> element contains a space separated list
|
|
||||||
* of extra information about the field. This data is inconsistent
|
|
||||||
* between DBMS's due to the way each DBMS works.
|
|
||||||
* + <samp>primary_key</samp>
|
|
||||||
* + <samp>unique_key</samp>
|
|
||||||
* + <samp>multiple_key</samp>
|
|
||||||
* + <samp>not_null</samp>
|
|
||||||
*
|
|
||||||
* Most DBMS's only provide the <samp>table</samp> and <samp>flags</samp>
|
|
||||||
* elements if <var>$result</var> is a table name. The following DBMS's
|
|
||||||
* provide full information from queries:
|
|
||||||
* + fbsql
|
|
||||||
* + mysql
|
|
||||||
*
|
|
||||||
* If the 'portability' option has <samp>MDB2_PORTABILITY_FIX_CASE</samp>
|
|
||||||
* turned on, the names of tables and fields will be lower or upper cased.
|
|
||||||
*
|
|
||||||
* @param object|string $result MDB2_result object from a query or a
|
|
||||||
* string containing the name of a table.
|
|
||||||
* While this also accepts a query result
|
|
||||||
* resource identifier, this behavior is
|
|
||||||
* deprecated.
|
|
||||||
* @param int $mode either unused or one of the tableInfo modes:
|
|
||||||
* <kbd>MDB2_TABLEINFO_ORDERTABLE</kbd>,
|
|
||||||
* <kbd>MDB2_TABLEINFO_ORDER</kbd> or
|
|
||||||
* <kbd>MDB2_TABLEINFO_FULL</kbd> (which does both).
|
|
||||||
* These are bitwise, so the first two can be
|
|
||||||
* combined using <kbd>|</kbd>.
|
|
||||||
*
|
|
||||||
* @return array an associative array with the information requested.
|
|
||||||
* A MDB2_Error object on failure.
|
|
||||||
*
|
|
||||||
* @see MDB2_Driver_Common::setOption()
|
|
||||||
*/
|
|
||||||
function tableInfo($result, $mode = null)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_string($result)) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
|
||||||
'method not implemented', __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
$db->loadModule('Manager', null, true);
|
|
||||||
$fields = $db->manager->listTableFields($result);
|
|
||||||
if (PEAR::isError($fields)) {
|
|
||||||
return $fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
$flags = array();
|
|
||||||
|
|
||||||
$idxname_format = $db->getOption('idxname_format');
|
|
||||||
$db->setOption('idxname_format', '%s');
|
|
||||||
|
|
||||||
$indexes = $db->manager->listTableIndexes($result);
|
|
||||||
if (PEAR::isError($indexes)) {
|
|
||||||
$db->setOption('idxname_format', $idxname_format);
|
|
||||||
return $indexes;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($indexes as $index) {
|
|
||||||
$definition = $this->getTableIndexDefinition($result, $index);
|
|
||||||
if (PEAR::isError($definition)) {
|
|
||||||
$db->setOption('idxname_format', $idxname_format);
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
if (count($definition['fields']) > 1) {
|
|
||||||
foreach ($definition['fields'] as $field => $sort) {
|
|
||||||
$flags[$field] = 'multiple_key';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$constraints = $db->manager->listTableConstraints($result);
|
|
||||||
if (PEAR::isError($constraints)) {
|
|
||||||
return $constraints;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($constraints as $constraint) {
|
|
||||||
$definition = $this->getTableConstraintDefinition($result, $constraint);
|
|
||||||
if (PEAR::isError($definition)) {
|
|
||||||
$db->setOption('idxname_format', $idxname_format);
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
$flag = !empty($definition['primary'])
|
|
||||||
? 'primary_key' : (!empty($definition['unique'])
|
|
||||||
? 'unique_key' : false);
|
|
||||||
if ($flag) {
|
|
||||||
foreach ($definition['fields'] as $field => $sort) {
|
|
||||||
if (empty($flags[$field]) || $flags[$field] != 'primary_key') {
|
|
||||||
$flags[$field] = $flag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$res = array();
|
|
||||||
|
|
||||||
if ($mode) {
|
|
||||||
$res['num_fields'] = count($fields);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($fields as $i => $field) {
|
|
||||||
$definition = $this->getTableFieldDefinition($result, $field);
|
|
||||||
if (PEAR::isError($definition)) {
|
|
||||||
$db->setOption('idxname_format', $idxname_format);
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
$res[$i] = $definition[0];
|
|
||||||
$res[$i]['name'] = $field;
|
|
||||||
$res[$i]['table'] = $result;
|
|
||||||
$res[$i]['type'] = preg_replace('/^([a-z]+).*$/i', '\\1', trim($definition[0]['nativetype']));
|
|
||||||
// 'primary_key', 'unique_key', 'multiple_key'
|
|
||||||
$res[$i]['flags'] = empty($flags[$field]) ? '' : $flags[$field];
|
|
||||||
// not_null', 'unsigned', 'auto_increment', 'default_[rawencodedvalue]'
|
|
||||||
if (!empty($res[$i]['notnull'])) {
|
|
||||||
$res[$i]['flags'].= ' not_null';
|
|
||||||
}
|
|
||||||
if (!empty($res[$i]['unsigned'])) {
|
|
||||||
$res[$i]['flags'].= ' unsigned';
|
|
||||||
}
|
|
||||||
if (!empty($res[$i]['auto_increment'])) {
|
|
||||||
$res[$i]['flags'].= ' autoincrement';
|
|
||||||
}
|
|
||||||
if (!empty($res[$i]['default'])) {
|
|
||||||
$res[$i]['flags'].= ' default_'.rawurlencode($res[$i]['default']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($mode & MDB2_TABLEINFO_ORDER) {
|
|
||||||
$res['order'][$res[$i]['name']] = $i;
|
|
||||||
}
|
|
||||||
if ($mode & MDB2_TABLEINFO_ORDERTABLE) {
|
|
||||||
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$db->setOption('idxname_format', $idxname_format);
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
|
@ -1,546 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Lukas Smith <smith@pooteeweet.org> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
|
|
||||||
require_once 'MDB2/Driver/Reverse/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MDB2 MySQL driver for the schema reverse engineering module
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
* @author Lorenzo Alberton <l.alberton@quipo.it>
|
|
||||||
*/
|
|
||||||
class MDB2_Driver_Reverse_mysql extends MDB2_Driver_Reverse_Common
|
|
||||||
{
|
|
||||||
// {{{ getTableFieldDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the structure of a field into an array
|
|
||||||
*
|
|
||||||
* @param string $table_name name of table that should be used in method
|
|
||||||
* @param string $field_name name of field that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTableFieldDefinition($table_name, $field_name)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $db->loadModule('Datatype', null, true);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
list($schema, $table) = $this->splitTableSchema($table_name);
|
|
||||||
|
|
||||||
$table = $db->quoteIdentifier($table, true);
|
|
||||||
$query = "SHOW FULL COLUMNS FROM $table LIKE ".$db->quote($field_name);
|
|
||||||
$columns = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC);
|
|
||||||
if (PEAR::isError($columns)) {
|
|
||||||
return $columns;
|
|
||||||
}
|
|
||||||
foreach ($columns as $column) {
|
|
||||||
$column = array_change_key_case($column, CASE_LOWER);
|
|
||||||
$column['name'] = $column['field'];
|
|
||||||
unset($column['field']);
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
if ($db->options['field_case'] == CASE_LOWER) {
|
|
||||||
$column['name'] = strtolower($column['name']);
|
|
||||||
} else {
|
|
||||||
$column['name'] = strtoupper($column['name']);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$column = array_change_key_case($column, $db->options['field_case']);
|
|
||||||
}
|
|
||||||
if ($field_name == $column['name']) {
|
|
||||||
$mapped_datatype = $db->datatype->mapNativeDatatype($column);
|
|
||||||
if (PEAR::isError($mapped_datatype)) {
|
|
||||||
return $mapped_datatype;
|
|
||||||
}
|
|
||||||
list($types, $length, $unsigned, $fixed) = $mapped_datatype;
|
|
||||||
$notnull = false;
|
|
||||||
if (empty($column['null']) || $column['null'] !== 'YES') {
|
|
||||||
$notnull = true;
|
|
||||||
}
|
|
||||||
$default = false;
|
|
||||||
if (array_key_exists('default', $column)) {
|
|
||||||
$default = $column['default'];
|
|
||||||
if ((null === $default) && $notnull) {
|
|
||||||
$default = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$definition[0] = array(
|
|
||||||
'notnull' => $notnull,
|
|
||||||
'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type'])
|
|
||||||
);
|
|
||||||
$autoincrement = false;
|
|
||||||
if (!empty($column['extra'])) {
|
|
||||||
if ($column['extra'] == 'auto_increment') {
|
|
||||||
$autoincrement = true;
|
|
||||||
} else {
|
|
||||||
$definition[0]['extra'] = $column['extra'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$collate = null;
|
|
||||||
if (!empty($column['collation'])) {
|
|
||||||
$collate = $column['collation'];
|
|
||||||
$charset = preg_replace('/(.+?)(_.+)?/', '$1', $collate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null !== $length) {
|
|
||||||
$definition[0]['length'] = $length;
|
|
||||||
}
|
|
||||||
if (null !== $unsigned) {
|
|
||||||
$definition[0]['unsigned'] = $unsigned;
|
|
||||||
}
|
|
||||||
if (null !== $fixed) {
|
|
||||||
$definition[0]['fixed'] = $fixed;
|
|
||||||
}
|
|
||||||
if ($default !== false) {
|
|
||||||
$definition[0]['default'] = $default;
|
|
||||||
}
|
|
||||||
if ($autoincrement !== false) {
|
|
||||||
$definition[0]['autoincrement'] = $autoincrement;
|
|
||||||
}
|
|
||||||
if (null !== $collate) {
|
|
||||||
$definition[0]['collate'] = $collate;
|
|
||||||
$definition[0]['charset'] = $charset;
|
|
||||||
}
|
|
||||||
foreach ($types as $key => $type) {
|
|
||||||
$definition[$key] = $definition[0];
|
|
||||||
if ($type == 'clob' || $type == 'blob') {
|
|
||||||
unset($definition[$key]['default']);
|
|
||||||
} elseif ($type == 'timestamp' && $notnull && empty($definition[$key]['default'])) {
|
|
||||||
$definition[$key]['default'] = '0000-00-00 00:00:00';
|
|
||||||
}
|
|
||||||
$definition[$key]['type'] = $type;
|
|
||||||
$definition[$key]['mdb2type'] = $type;
|
|
||||||
}
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
'it was not specified an existing table column', __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getTableIndexDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the structure of an index into an array
|
|
||||||
*
|
|
||||||
* @param string $table_name name of table that should be used in method
|
|
||||||
* @param string $index_name name of index that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTableIndexDefinition($table_name, $index_name)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
list($schema, $table) = $this->splitTableSchema($table_name);
|
|
||||||
|
|
||||||
$table = $db->quoteIdentifier($table, true);
|
|
||||||
$query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */";
|
|
||||||
$index_name_mdb2 = $db->getIndexName($index_name);
|
|
||||||
$result = $db->queryRow(sprintf($query, $db->quote($index_name_mdb2)));
|
|
||||||
if (!PEAR::isError($result) && (null !== $result)) {
|
|
||||||
// apply 'idxname_format' only if the query succeeded, otherwise
|
|
||||||
// fallback to the given $index_name, without transformation
|
|
||||||
$index_name = $index_name_mdb2;
|
|
||||||
}
|
|
||||||
$result = $db->query(sprintf($query, $db->quote($index_name)));
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
$colpos = 1;
|
|
||||||
$definition = array();
|
|
||||||
while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) {
|
|
||||||
$row = array_change_key_case($row, CASE_LOWER);
|
|
||||||
$key_name = $row['key_name'];
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
if ($db->options['field_case'] == CASE_LOWER) {
|
|
||||||
$key_name = strtolower($key_name);
|
|
||||||
} else {
|
|
||||||
$key_name = strtoupper($key_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($index_name == $key_name) {
|
|
||||||
if (!$row['non_unique']) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
$index_name . ' is not an existing table index', __FUNCTION__);
|
|
||||||
}
|
|
||||||
$column_name = $row['column_name'];
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
if ($db->options['field_case'] == CASE_LOWER) {
|
|
||||||
$column_name = strtolower($column_name);
|
|
||||||
} else {
|
|
||||||
$column_name = strtoupper($column_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$definition['fields'][$column_name] = array(
|
|
||||||
'position' => $colpos++
|
|
||||||
);
|
|
||||||
if (!empty($row['collation'])) {
|
|
||||||
$definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A'
|
|
||||||
? 'ascending' : 'descending');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$result->free();
|
|
||||||
if (empty($definition['fields'])) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
$index_name . ' is not an existing table index', __FUNCTION__);
|
|
||||||
}
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getTableConstraintDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the structure of a constraint into an array
|
|
||||||
*
|
|
||||||
* @param string $table_name name of table that should be used in method
|
|
||||||
* @param string $constraint_name name of constraint that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTableConstraintDefinition($table_name, $constraint_name)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
list($schema, $table) = $this->splitTableSchema($table_name);
|
|
||||||
$constraint_name_original = $constraint_name;
|
|
||||||
|
|
||||||
$table = $db->quoteIdentifier($table, true);
|
|
||||||
$query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */";
|
|
||||||
if (strtolower($constraint_name) != 'primary') {
|
|
||||||
$constraint_name_mdb2 = $db->getIndexName($constraint_name);
|
|
||||||
$result = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2)));
|
|
||||||
if (!PEAR::isError($result) && (null !== $result)) {
|
|
||||||
// apply 'idxname_format' only if the query succeeded, otherwise
|
|
||||||
// fallback to the given $index_name, without transformation
|
|
||||||
$constraint_name = $constraint_name_mdb2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$result = $db->query(sprintf($query, $db->quote($constraint_name)));
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
$colpos = 1;
|
|
||||||
//default values, eventually overridden
|
|
||||||
$definition = array(
|
|
||||||
'primary' => false,
|
|
||||||
'unique' => false,
|
|
||||||
'foreign' => false,
|
|
||||||
'check' => false,
|
|
||||||
'fields' => array(),
|
|
||||||
'references' => array(
|
|
||||||
'table' => '',
|
|
||||||
'fields' => array(),
|
|
||||||
),
|
|
||||||
'onupdate' => '',
|
|
||||||
'ondelete' => '',
|
|
||||||
'match' => '',
|
|
||||||
'deferrable' => false,
|
|
||||||
'initiallydeferred' => false,
|
|
||||||
);
|
|
||||||
while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) {
|
|
||||||
$row = array_change_key_case($row, CASE_LOWER);
|
|
||||||
$key_name = $row['key_name'];
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
if ($db->options['field_case'] == CASE_LOWER) {
|
|
||||||
$key_name = strtolower($key_name);
|
|
||||||
} else {
|
|
||||||
$key_name = strtoupper($key_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($constraint_name == $key_name) {
|
|
||||||
if ($row['non_unique']) {
|
|
||||||
//FOREIGN KEY?
|
|
||||||
return $this->_getTableFKConstraintDefinition($table, $constraint_name_original, $definition);
|
|
||||||
}
|
|
||||||
if ($row['key_name'] == 'PRIMARY') {
|
|
||||||
$definition['primary'] = true;
|
|
||||||
} elseif (!$row['non_unique']) {
|
|
||||||
$definition['unique'] = true;
|
|
||||||
}
|
|
||||||
$column_name = $row['column_name'];
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
if ($db->options['field_case'] == CASE_LOWER) {
|
|
||||||
$column_name = strtolower($column_name);
|
|
||||||
} else {
|
|
||||||
$column_name = strtoupper($column_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$definition['fields'][$column_name] = array(
|
|
||||||
'position' => $colpos++
|
|
||||||
);
|
|
||||||
if (!empty($row['collation'])) {
|
|
||||||
$definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A'
|
|
||||||
? 'ascending' : 'descending');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$result->free();
|
|
||||||
if (empty($definition['fields'])) {
|
|
||||||
return $this->_getTableFKConstraintDefinition($table, $constraint_name_original, $definition);
|
|
||||||
}
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _getTableFKConstraintDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the FK definition from the CREATE TABLE statement
|
|
||||||
*
|
|
||||||
* @param string $table table name
|
|
||||||
* @param string $constraint_name constraint name
|
|
||||||
* @param array $definition default values for constraint definition
|
|
||||||
*
|
|
||||||
* @return array|PEAR_Error
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
function _getTableFKConstraintDefinition($table, $constraint_name, $definition)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
//Use INFORMATION_SCHEMA instead?
|
|
||||||
//SELECT *
|
|
||||||
// FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
|
|
||||||
// WHERE CONSTRAINT_SCHEMA = '$dbname'
|
|
||||||
// AND TABLE_NAME = '$table'
|
|
||||||
// AND CONSTRAINT_NAME = '$constraint_name';
|
|
||||||
$query = 'SHOW CREATE TABLE '. $db->escape($table);
|
|
||||||
$constraint = $db->queryOne($query, 'text', 1);
|
|
||||||
if (!PEAR::isError($constraint) && !empty($constraint)) {
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
if ($db->options['field_case'] == CASE_LOWER) {
|
|
||||||
$constraint = strtolower($constraint);
|
|
||||||
} else {
|
|
||||||
$constraint = strtoupper($constraint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$constraint_name_original = $constraint_name;
|
|
||||||
$constraint_name = $db->getIndexName($constraint_name);
|
|
||||||
$pattern = '/\bCONSTRAINT\s+'.$constraint_name.'\s+FOREIGN KEY\s+\(([^\)]+)\) \bREFERENCES\b ([^\s]+) \(([^\)]+)\)(?: ON DELETE ([^\s]+))?(?: ON UPDATE ([^\s]+))?/i';
|
|
||||||
if (!preg_match($pattern, str_replace('`', '', $constraint), $matches)) {
|
|
||||||
//fallback to original constraint name
|
|
||||||
$pattern = '/\bCONSTRAINT\s+'.$constraint_name_original.'\s+FOREIGN KEY\s+\(([^\)]+)\) \bREFERENCES\b ([^\s]+) \(([^\)]+)\)(?: ON DELETE ([^\s]+))?(?: ON UPDATE ([^\s]+))?/i';
|
|
||||||
}
|
|
||||||
if (preg_match($pattern, str_replace('`', '', $constraint), $matches)) {
|
|
||||||
$definition['foreign'] = true;
|
|
||||||
$column_names = explode(',', $matches[1]);
|
|
||||||
$referenced_cols = explode(',', $matches[3]);
|
|
||||||
$definition['references'] = array(
|
|
||||||
'table' => $matches[2],
|
|
||||||
'fields' => array(),
|
|
||||||
);
|
|
||||||
$colpos = 1;
|
|
||||||
foreach ($column_names as $column_name) {
|
|
||||||
$definition['fields'][trim($column_name)] = array(
|
|
||||||
'position' => $colpos++
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$colpos = 1;
|
|
||||||
foreach ($referenced_cols as $column_name) {
|
|
||||||
$definition['references']['fields'][trim($column_name)] = array(
|
|
||||||
'position' => $colpos++
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$definition['ondelete'] = empty($matches[4]) ? 'RESTRICT' : strtoupper($matches[4]);
|
|
||||||
$definition['onupdate'] = empty($matches[5]) ? 'RESTRICT' : strtoupper($matches[5]);
|
|
||||||
$definition['match'] = 'SIMPLE';
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
$constraint_name . ' is not an existing table constraint', __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getTriggerDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the structure of a trigger into an array
|
|
||||||
*
|
|
||||||
* EXPERIMENTAL
|
|
||||||
*
|
|
||||||
* WARNING: this function is experimental and may change the returned value
|
|
||||||
* at any time until labelled as non-experimental
|
|
||||||
*
|
|
||||||
* @param string $trigger name of trigger that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTriggerDefinition($trigger)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = 'SELECT trigger_name,
|
|
||||||
event_object_table AS table_name,
|
|
||||||
action_statement AS trigger_body,
|
|
||||||
action_timing AS trigger_type,
|
|
||||||
event_manipulation AS trigger_event
|
|
||||||
FROM information_schema.triggers
|
|
||||||
WHERE trigger_name = '. $db->quote($trigger, 'text');
|
|
||||||
$types = array(
|
|
||||||
'trigger_name' => 'text',
|
|
||||||
'table_name' => 'text',
|
|
||||||
'trigger_body' => 'text',
|
|
||||||
'trigger_type' => 'text',
|
|
||||||
'trigger_event' => 'text',
|
|
||||||
);
|
|
||||||
$def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC);
|
|
||||||
if (PEAR::isError($def)) {
|
|
||||||
return $def;
|
|
||||||
}
|
|
||||||
$def['trigger_comment'] = '';
|
|
||||||
$def['trigger_enabled'] = true;
|
|
||||||
return $def;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ tableInfo()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns information about a table or a result set
|
|
||||||
*
|
|
||||||
* @param object|string $result MDB2_result object from a query or a
|
|
||||||
* string containing the name of a table.
|
|
||||||
* While this also accepts a query result
|
|
||||||
* resource identifier, this behavior is
|
|
||||||
* deprecated.
|
|
||||||
* @param int $mode a valid tableInfo mode
|
|
||||||
*
|
|
||||||
* @return array an associative array with the information requested.
|
|
||||||
* A MDB2_Error object on failure.
|
|
||||||
*
|
|
||||||
* @see MDB2_Driver_Common::setOption()
|
|
||||||
*/
|
|
||||||
function tableInfo($result, $mode = null)
|
|
||||||
{
|
|
||||||
if (is_string($result)) {
|
|
||||||
return parent::tableInfo($result, $mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$resource = MDB2::isResultCommon($result) ? $result->getResource() : $result;
|
|
||||||
if (!is_resource($resource)) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
|
|
||||||
'Could not generate result resource', __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
if ($db->options['field_case'] == CASE_LOWER) {
|
|
||||||
$case_func = 'strtolower';
|
|
||||||
} else {
|
|
||||||
$case_func = 'strtoupper';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$case_func = 'strval';
|
|
||||||
}
|
|
||||||
|
|
||||||
$count = @mysql_num_fields($resource);
|
|
||||||
$res = array();
|
|
||||||
if ($mode) {
|
|
||||||
$res['num_fields'] = $count;
|
|
||||||
}
|
|
||||||
|
|
||||||
$db->loadModule('Datatype', null, true);
|
|
||||||
for ($i = 0; $i < $count; $i++) {
|
|
||||||
$res[$i] = array(
|
|
||||||
'table' => $case_func(@mysql_field_table($resource, $i)),
|
|
||||||
'name' => $case_func(@mysql_field_name($resource, $i)),
|
|
||||||
'type' => @mysql_field_type($resource, $i),
|
|
||||||
'length' => @mysql_field_len($resource, $i),
|
|
||||||
'flags' => @mysql_field_flags($resource, $i),
|
|
||||||
);
|
|
||||||
if ($res[$i]['type'] == 'string') {
|
|
||||||
$res[$i]['type'] = 'char';
|
|
||||||
} elseif ($res[$i]['type'] == 'unknown') {
|
|
||||||
$res[$i]['type'] = 'decimal';
|
|
||||||
}
|
|
||||||
$mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]);
|
|
||||||
if (PEAR::isError($mdb2type_info)) {
|
|
||||||
return $mdb2type_info;
|
|
||||||
}
|
|
||||||
$res[$i]['mdb2type'] = $mdb2type_info[0][0];
|
|
||||||
if ($mode & MDB2_TABLEINFO_ORDER) {
|
|
||||||
$res['order'][$res[$i]['name']] = $i;
|
|
||||||
}
|
|
||||||
if ($mode & MDB2_TABLEINFO_ORDERTABLE) {
|
|
||||||
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
|
@ -1,625 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith, Frank M. Kromann, Lorenzo Alberton |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Authors: Lukas Smith <smith@pooteeweet.org> |
|
|
||||||
// | Lorenzo Alberton <l.alberton@quipo.it> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id: oci8.php 295587 2010-02-28 17:16:38Z quipo $
|
|
||||||
//
|
|
||||||
|
|
||||||
require_once 'MDB2/Driver/Reverse/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MDB2 Oracle driver for the schema reverse engineering module
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@dybnet.de>
|
|
||||||
*/
|
|
||||||
class MDB2_Driver_Reverse_oci8 extends MDB2_Driver_Reverse_Common
|
|
||||||
{
|
|
||||||
// {{{ getTableFieldDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the structure of a field into an array
|
|
||||||
*
|
|
||||||
* @param string $table_name name of table that should be used in method
|
|
||||||
* @param string $field_name name of field that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTableFieldDefinition($table_name, $field_name)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $db->loadModule('Datatype', null, true);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
list($owner, $table) = $this->splitTableSchema($table_name);
|
|
||||||
if (empty($owner)) {
|
|
||||||
$owner = $db->dsn['username'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = 'SELECT column_name AS "name",
|
|
||||||
data_type AS "type",
|
|
||||||
nullable AS "nullable",
|
|
||||||
data_default AS "default",
|
|
||||||
COALESCE(data_precision, data_length) AS "length",
|
|
||||||
data_scale AS "scale"
|
|
||||||
FROM all_tab_columns
|
|
||||||
WHERE (table_name=? OR table_name=?)
|
|
||||||
AND (owner=? OR owner=?)
|
|
||||||
AND (column_name=? OR column_name=?)
|
|
||||||
ORDER BY column_id';
|
|
||||||
$stmt = $db->prepare($query);
|
|
||||||
if (PEAR::isError($stmt)) {
|
|
||||||
return $stmt;
|
|
||||||
}
|
|
||||||
$args = array(
|
|
||||||
$table,
|
|
||||||
strtoupper($table),
|
|
||||||
$owner,
|
|
||||||
strtoupper($owner),
|
|
||||||
$field_name,
|
|
||||||
strtoupper($field_name)
|
|
||||||
);
|
|
||||||
$result = $stmt->execute($args);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
$column = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
|
|
||||||
if (PEAR::isError($column)) {
|
|
||||||
return $column;
|
|
||||||
}
|
|
||||||
$stmt->free();
|
|
||||||
$result->free();
|
|
||||||
|
|
||||||
if (empty($column)) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
$field_name . ' is not a column in table ' . $table_name, __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
$column = array_change_key_case($column, CASE_LOWER);
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
if ($db->options['field_case'] == CASE_LOWER) {
|
|
||||||
$column['name'] = strtolower($column['name']);
|
|
||||||
} else {
|
|
||||||
$column['name'] = strtoupper($column['name']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$mapped_datatype = $db->datatype->mapNativeDatatype($column);
|
|
||||||
if (PEAR::isError($mapped_datatype)) {
|
|
||||||
return $mapped_datatype;
|
|
||||||
}
|
|
||||||
list($types, $length, $unsigned, $fixed) = $mapped_datatype;
|
|
||||||
$notnull = false;
|
|
||||||
if (!empty($column['nullable']) && $column['nullable'] == 'N') {
|
|
||||||
$notnull = true;
|
|
||||||
}
|
|
||||||
$default = false;
|
|
||||||
if (array_key_exists('default', $column)) {
|
|
||||||
$default = $column['default'];
|
|
||||||
if ($default === 'NULL') {
|
|
||||||
$default = null;
|
|
||||||
}
|
|
||||||
//ugly hack, but works for the reverse direction
|
|
||||||
if ($default == "''") {
|
|
||||||
$default = '';
|
|
||||||
}
|
|
||||||
if ((null === $default) && $notnull) {
|
|
||||||
$default = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$definition[0] = array('notnull' => $notnull, 'nativetype' => $column['type']);
|
|
||||||
if (null !== $length) {
|
|
||||||
$definition[0]['length'] = $length;
|
|
||||||
}
|
|
||||||
if (null !== $unsigned) {
|
|
||||||
$definition[0]['unsigned'] = $unsigned;
|
|
||||||
}
|
|
||||||
if (null !== $fixed) {
|
|
||||||
$definition[0]['fixed'] = $fixed;
|
|
||||||
}
|
|
||||||
if ($default !== false) {
|
|
||||||
$definition[0]['default'] = $default;
|
|
||||||
}
|
|
||||||
foreach ($types as $key => $type) {
|
|
||||||
$definition[$key] = $definition[0];
|
|
||||||
if ($type == 'clob' || $type == 'blob') {
|
|
||||||
unset($definition[$key]['default']);
|
|
||||||
}
|
|
||||||
$definition[$key]['type'] = $type;
|
|
||||||
$definition[$key]['mdb2type'] = $type;
|
|
||||||
}
|
|
||||||
if ($type == 'integer') {
|
|
||||||
$query= "SELECT trigger_body
|
|
||||||
FROM all_triggers
|
|
||||||
WHERE table_name=?
|
|
||||||
AND triggering_event='INSERT'
|
|
||||||
AND trigger_type='BEFORE EACH ROW'";
|
|
||||||
// ^^ pretty reasonable mimic for "auto_increment" in oracle?
|
|
||||||
$stmt = $db->prepare($query);
|
|
||||||
if (PEAR::isError($stmt)) {
|
|
||||||
return $stmt;
|
|
||||||
}
|
|
||||||
$result = $stmt->execute(strtoupper($table));
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
while ($triggerstr = $result->fetchOne()) {
|
|
||||||
if (preg_match('/.*SELECT\W+(.+)\.nextval +into +\:NEW\.'.$field_name.' +FROM +dual/im', $triggerstr, $matches)) {
|
|
||||||
$definition[0]['autoincrement'] = $matches[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$stmt->free();
|
|
||||||
$result->free();
|
|
||||||
}
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getTableIndexDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the structure of an index into an array
|
|
||||||
*
|
|
||||||
* @param string $table_name name of table that should be used in method
|
|
||||||
* @param string $index_name name of index that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTableIndexDefinition($table_name, $index_name)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
list($owner, $table) = $this->splitTableSchema($table_name);
|
|
||||||
if (empty($owner)) {
|
|
||||||
$owner = $db->dsn['username'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = 'SELECT aic.column_name AS "column_name",
|
|
||||||
aic.column_position AS "column_position",
|
|
||||||
aic.descend AS "descend",
|
|
||||||
aic.table_owner AS "table_owner",
|
|
||||||
alc.constraint_type AS "constraint_type"
|
|
||||||
FROM all_ind_columns aic
|
|
||||||
LEFT JOIN all_constraints alc
|
|
||||||
ON aic.index_name = alc.constraint_name
|
|
||||||
AND aic.table_name = alc.table_name
|
|
||||||
AND aic.table_owner = alc.owner
|
|
||||||
WHERE (aic.table_name=? OR aic.table_name=?)
|
|
||||||
AND (aic.index_name=? OR aic.index_name=?)
|
|
||||||
AND (aic.table_owner=? OR aic.table_owner=?)
|
|
||||||
ORDER BY column_position';
|
|
||||||
$stmt = $db->prepare($query);
|
|
||||||
if (PEAR::isError($stmt)) {
|
|
||||||
return $stmt;
|
|
||||||
}
|
|
||||||
$indexnames = array_unique(array($db->getIndexName($index_name), $index_name));
|
|
||||||
$i = 0;
|
|
||||||
$row = null;
|
|
||||||
while ((null === $row) && array_key_exists($i, $indexnames)) {
|
|
||||||
$args = array(
|
|
||||||
$table,
|
|
||||||
strtoupper($table),
|
|
||||||
$indexnames[$i],
|
|
||||||
strtoupper($indexnames[$i]),
|
|
||||||
$owner,
|
|
||||||
strtoupper($owner)
|
|
||||||
);
|
|
||||||
$result = $stmt->execute($args);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
$row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
|
|
||||||
if (PEAR::isError($row)) {
|
|
||||||
return $row;
|
|
||||||
}
|
|
||||||
$i++;
|
|
||||||
}
|
|
||||||
if (null === $row) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
$index_name. ' is not an index on table '. $table_name, __FUNCTION__);
|
|
||||||
}
|
|
||||||
if ($row['constraint_type'] == 'U' || $row['constraint_type'] == 'P') {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
$index_name. ' is a constraint, not an index on table '. $table_name, __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
$definition = array();
|
|
||||||
while (null !== $row) {
|
|
||||||
$row = array_change_key_case($row, CASE_LOWER);
|
|
||||||
$column_name = $row['column_name'];
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
if ($db->options['field_case'] == CASE_LOWER) {
|
|
||||||
$column_name = strtolower($column_name);
|
|
||||||
} else {
|
|
||||||
$column_name = strtoupper($column_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$definition['fields'][$column_name] = array(
|
|
||||||
'position' => (int)$row['column_position'],
|
|
||||||
);
|
|
||||||
if (!empty($row['descend'])) {
|
|
||||||
$definition['fields'][$column_name]['sorting'] =
|
|
||||||
($row['descend'] == 'ASC' ? 'ascending' : 'descending');
|
|
||||||
}
|
|
||||||
$row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
|
|
||||||
}
|
|
||||||
$result->free();
|
|
||||||
if (empty($definition['fields'])) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
$index_name. ' is not an index on table '. $table_name, __FUNCTION__);
|
|
||||||
}
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getTableConstraintDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the structure of a constraint into an array
|
|
||||||
*
|
|
||||||
* @param string $table_name name of table that should be used in method
|
|
||||||
* @param string $constraint_name name of constraint that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTableConstraintDefinition($table_name, $constraint_name)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
list($owner, $table) = $this->splitTableSchema($table_name);
|
|
||||||
if (empty($owner)) {
|
|
||||||
$owner = $db->dsn['username'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = 'SELECT alc.constraint_name,
|
|
||||||
CASE alc.constraint_type WHEN \'P\' THEN 1 ELSE 0 END "primary",
|
|
||||||
CASE alc.constraint_type WHEN \'R\' THEN 1 ELSE 0 END "foreign",
|
|
||||||
CASE alc.constraint_type WHEN \'U\' THEN 1 ELSE 0 END "unique",
|
|
||||||
CASE alc.constraint_type WHEN \'C\' THEN 1 ELSE 0 END "check",
|
|
||||||
alc.DELETE_RULE "ondelete",
|
|
||||||
\'NO ACTION\' "onupdate",
|
|
||||||
\'SIMPLE\' "match",
|
|
||||||
CASE alc.deferrable WHEN \'NOT DEFERRABLE\' THEN 0 ELSE 1 END "deferrable",
|
|
||||||
CASE alc.deferred WHEN \'IMMEDIATE\' THEN 0 ELSE 1 END "initiallydeferred",
|
|
||||||
alc.search_condition AS "search_condition",
|
|
||||||
alc.table_name,
|
|
||||||
cols.column_name AS "column_name",
|
|
||||||
cols.position,
|
|
||||||
r_alc.table_name "references_table",
|
|
||||||
r_cols.column_name "references_field",
|
|
||||||
r_cols.position "references_field_position"
|
|
||||||
FROM all_cons_columns cols
|
|
||||||
LEFT JOIN all_constraints alc
|
|
||||||
ON alc.constraint_name = cols.constraint_name
|
|
||||||
AND alc.owner = cols.owner
|
|
||||||
LEFT JOIN all_constraints r_alc
|
|
||||||
ON alc.r_constraint_name = r_alc.constraint_name
|
|
||||||
AND alc.r_owner = r_alc.owner
|
|
||||||
LEFT JOIN all_cons_columns r_cols
|
|
||||||
ON r_alc.constraint_name = r_cols.constraint_name
|
|
||||||
AND r_alc.owner = r_cols.owner
|
|
||||||
AND cols.position = r_cols.position
|
|
||||||
WHERE (alc.constraint_name=? OR alc.constraint_name=?)
|
|
||||||
AND alc.constraint_name = cols.constraint_name
|
|
||||||
AND (alc.owner=? OR alc.owner=?)';
|
|
||||||
$tablenames = array();
|
|
||||||
if (!empty($table)) {
|
|
||||||
$query.= ' AND (alc.table_name=? OR alc.table_name=?)';
|
|
||||||
$tablenames = array($table, strtoupper($table));
|
|
||||||
}
|
|
||||||
$stmt = $db->prepare($query);
|
|
||||||
if (PEAR::isError($stmt)) {
|
|
||||||
return $stmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
$constraintnames = array_unique(array($db->getIndexName($constraint_name), $constraint_name));
|
|
||||||
$c = 0;
|
|
||||||
$row = null;
|
|
||||||
while ((null === $row) && array_key_exists($c, $constraintnames)) {
|
|
||||||
$args = array(
|
|
||||||
$constraintnames[$c],
|
|
||||||
strtoupper($constraintnames[$c]),
|
|
||||||
$owner,
|
|
||||||
strtoupper($owner)
|
|
||||||
);
|
|
||||||
if (!empty($table)) {
|
|
||||||
$args = array_merge($args, $tablenames);
|
|
||||||
}
|
|
||||||
$result = $stmt->execute($args);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
$row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
|
|
||||||
if (PEAR::isError($row)) {
|
|
||||||
return $row;
|
|
||||||
}
|
|
||||||
$c++;
|
|
||||||
}
|
|
||||||
|
|
||||||
$definition = array(
|
|
||||||
'primary' => (boolean)$row['primary'],
|
|
||||||
'unique' => (boolean)$row['unique'],
|
|
||||||
'foreign' => (boolean)$row['foreign'],
|
|
||||||
'check' => (boolean)$row['check'],
|
|
||||||
'deferrable' => (boolean)$row['deferrable'],
|
|
||||||
'initiallydeferred' => (boolean)$row['initiallydeferred'],
|
|
||||||
'ondelete' => $row['ondelete'],
|
|
||||||
'onupdate' => $row['onupdate'],
|
|
||||||
'match' => $row['match'],
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($definition['check']) {
|
|
||||||
// pattern match constraint for check constraint values into enum-style output:
|
|
||||||
$enumregex = '/'.$row['column_name'].' in \((.+?)\)/i';
|
|
||||||
if (preg_match($enumregex, $row['search_condition'], $rangestr)) {
|
|
||||||
$definition['fields'][$column_name] = array();
|
|
||||||
$allowed = explode(',', $rangestr[1]);
|
|
||||||
foreach ($allowed as $val) {
|
|
||||||
$val = trim($val);
|
|
||||||
$val = preg_replace('/^\'/', '', $val);
|
|
||||||
$val = preg_replace('/\'$/', '', $val);
|
|
||||||
array_push($definition['fields'][$column_name], $val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (null !== $row) {
|
|
||||||
$row = array_change_key_case($row, CASE_LOWER);
|
|
||||||
$column_name = $row['column_name'];
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
if ($db->options['field_case'] == CASE_LOWER) {
|
|
||||||
$column_name = strtolower($column_name);
|
|
||||||
} else {
|
|
||||||
$column_name = strtoupper($column_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$definition['fields'][$column_name] = array(
|
|
||||||
'position' => (int)$row['position']
|
|
||||||
);
|
|
||||||
if ($row['foreign']) {
|
|
||||||
$ref_column_name = $row['references_field'];
|
|
||||||
$ref_table_name = $row['references_table'];
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
if ($db->options['field_case'] == CASE_LOWER) {
|
|
||||||
$ref_column_name = strtolower($ref_column_name);
|
|
||||||
$ref_table_name = strtolower($ref_table_name);
|
|
||||||
} else {
|
|
||||||
$ref_column_name = strtoupper($ref_column_name);
|
|
||||||
$ref_table_name = strtoupper($ref_table_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$definition['references']['table'] = $ref_table_name;
|
|
||||||
$definition['references']['fields'][$ref_column_name] = array(
|
|
||||||
'position' => (int)$row['references_field_position']
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$lastrow = $row;
|
|
||||||
$row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
|
|
||||||
}
|
|
||||||
$result->free();
|
|
||||||
if (empty($definition['fields'])) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
$constraint_name . ' is not a constraint on table '. $table_name, __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getSequenceDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the structure of a sequence into an array
|
|
||||||
*
|
|
||||||
* @param string $sequence name of sequence that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getSequenceDefinition($sequence)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$sequence_name = $db->getSequenceName($sequence);
|
|
||||||
$query = 'SELECT last_number FROM user_sequences';
|
|
||||||
$query.= ' WHERE sequence_name='.$db->quote($sequence_name, 'text');
|
|
||||||
$query.= ' OR sequence_name='.$db->quote(strtoupper($sequence_name), 'text');
|
|
||||||
$start = $db->queryOne($query, 'integer');
|
|
||||||
if (PEAR::isError($start)) {
|
|
||||||
return $start;
|
|
||||||
}
|
|
||||||
$definition = array();
|
|
||||||
if ($start != 1) {
|
|
||||||
$definition = array('start' => $start);
|
|
||||||
}
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getTriggerDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the structure of a trigger into an array
|
|
||||||
*
|
|
||||||
* EXPERIMENTAL
|
|
||||||
*
|
|
||||||
* WARNING: this function is experimental and may change the returned value
|
|
||||||
* at any time until labelled as non-experimental
|
|
||||||
*
|
|
||||||
* @param string $trigger name of trigger that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTriggerDefinition($trigger)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = 'SELECT trigger_name AS "trigger_name",
|
|
||||||
table_name AS "table_name",
|
|
||||||
trigger_body AS "trigger_body",
|
|
||||||
trigger_type AS "trigger_type",
|
|
||||||
triggering_event AS "trigger_event",
|
|
||||||
description AS "trigger_comment",
|
|
||||||
1 AS "trigger_enabled",
|
|
||||||
when_clause AS "when_clause"
|
|
||||||
FROM user_triggers
|
|
||||||
WHERE trigger_name = \''. strtoupper($trigger).'\'';
|
|
||||||
$types = array(
|
|
||||||
'trigger_name' => 'text',
|
|
||||||
'table_name' => 'text',
|
|
||||||
'trigger_body' => 'text',
|
|
||||||
'trigger_type' => 'text',
|
|
||||||
'trigger_event' => 'text',
|
|
||||||
'trigger_comment' => 'text',
|
|
||||||
'trigger_enabled' => 'boolean',
|
|
||||||
'when_clause' => 'text',
|
|
||||||
);
|
|
||||||
$result = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
if (!empty($result['trigger_type'])) {
|
|
||||||
//$result['trigger_type'] = array_shift(explode(' ', $result['trigger_type']));
|
|
||||||
$result['trigger_type'] = preg_replace('/(\S+).*/', '\\1', $result['trigger_type']);
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ tableInfo()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns information about a table or a result set
|
|
||||||
*
|
|
||||||
* NOTE: only supports 'table' and 'flags' if <var>$result</var>
|
|
||||||
* is a table name.
|
|
||||||
*
|
|
||||||
* NOTE: flags won't contain index information.
|
|
||||||
*
|
|
||||||
* @param object|string $result MDB2_result object from a query or a
|
|
||||||
* string containing the name of a table.
|
|
||||||
* While this also accepts a query result
|
|
||||||
* resource identifier, this behavior is
|
|
||||||
* deprecated.
|
|
||||||
* @param int $mode a valid tableInfo mode
|
|
||||||
*
|
|
||||||
* @return array an associative array with the information requested.
|
|
||||||
* A MDB2_Error object on failure.
|
|
||||||
*
|
|
||||||
* @see MDB2_Driver_Common::tableInfo()
|
|
||||||
*/
|
|
||||||
function tableInfo($result, $mode = null)
|
|
||||||
{
|
|
||||||
if (is_string($result)) {
|
|
||||||
return parent::tableInfo($result, $mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$resource = MDB2::isResultCommon($result) ? $result->getResource() : $result;
|
|
||||||
if (!is_resource($resource)) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
|
|
||||||
'Could not generate result resource', __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
if ($db->options['field_case'] == CASE_LOWER) {
|
|
||||||
$case_func = 'strtolower';
|
|
||||||
} else {
|
|
||||||
$case_func = 'strtoupper';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$case_func = 'strval';
|
|
||||||
}
|
|
||||||
|
|
||||||
$count = @OCINumCols($resource);
|
|
||||||
$res = array();
|
|
||||||
|
|
||||||
if ($mode) {
|
|
||||||
$res['num_fields'] = $count;
|
|
||||||
}
|
|
||||||
|
|
||||||
$db->loadModule('Datatype', null, true);
|
|
||||||
for ($i = 0; $i < $count; $i++) {
|
|
||||||
$column = array(
|
|
||||||
'table' => '',
|
|
||||||
'name' => $case_func(@OCIColumnName($resource, $i+1)),
|
|
||||||
'type' => @OCIColumnType($resource, $i+1),
|
|
||||||
'length' => @OCIColumnSize($resource, $i+1),
|
|
||||||
'flags' => '',
|
|
||||||
);
|
|
||||||
$res[$i] = $column;
|
|
||||||
$res[$i]['mdb2type'] = $db->datatype->mapNativeDatatype($res[$i]);
|
|
||||||
if ($mode & MDB2_TABLEINFO_ORDER) {
|
|
||||||
$res['order'][$res[$i]['name']] = $i;
|
|
||||||
}
|
|
||||||
if ($mode & MDB2_TABLEINFO_ORDERTABLE) {
|
|
||||||
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
|
@ -1,574 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Authors: Paul Cooper <pgc@ucecom.com> |
|
|
||||||
// | Lorenzo Alberton <l.alberton@quipo.it> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
require_once 'MDB2/Driver/Reverse/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MDB2 PostGreSQL driver for the schema reverse engineering module
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Paul Cooper <pgc@ucecom.com>
|
|
||||||
* @author Lorenzo Alberton <l.alberton@quipo.it>
|
|
||||||
*/
|
|
||||||
class MDB2_Driver_Reverse_pgsql extends MDB2_Driver_Reverse_Common
|
|
||||||
{
|
|
||||||
// {{{ getTableFieldDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the structure of a field into an array
|
|
||||||
*
|
|
||||||
* @param string $table_name name of table that should be used in method
|
|
||||||
* @param string $field_name name of field that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTableFieldDefinition($table_name, $field_name)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $db->loadModule('Datatype', null, true);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
list($schema, $table) = $this->splitTableSchema($table_name);
|
|
||||||
|
|
||||||
$query = "SELECT a.attname AS name,
|
|
||||||
t.typname AS type,
|
|
||||||
CASE a.attlen
|
|
||||||
WHEN -1 THEN
|
|
||||||
CASE t.typname
|
|
||||||
WHEN 'numeric' THEN (a.atttypmod / 65536)
|
|
||||||
WHEN 'decimal' THEN (a.atttypmod / 65536)
|
|
||||||
WHEN 'money' THEN (a.atttypmod / 65536)
|
|
||||||
ELSE CASE a.atttypmod
|
|
||||||
WHEN -1 THEN NULL
|
|
||||||
ELSE a.atttypmod - 4
|
|
||||||
END
|
|
||||||
END
|
|
||||||
ELSE a.attlen
|
|
||||||
END AS length,
|
|
||||||
CASE t.typname
|
|
||||||
WHEN 'numeric' THEN (a.atttypmod % 65536) - 4
|
|
||||||
WHEN 'decimal' THEN (a.atttypmod % 65536) - 4
|
|
||||||
WHEN 'money' THEN (a.atttypmod % 65536) - 4
|
|
||||||
ELSE 0
|
|
||||||
END AS scale,
|
|
||||||
a.attnotnull,
|
|
||||||
a.atttypmod,
|
|
||||||
a.atthasdef,
|
|
||||||
(SELECT substring(pg_get_expr(d.adbin, d.adrelid) for 128)
|
|
||||||
FROM pg_attrdef d
|
|
||||||
WHERE d.adrelid = a.attrelid
|
|
||||||
AND d.adnum = a.attnum
|
|
||||||
AND a.atthasdef
|
|
||||||
) as default
|
|
||||||
FROM pg_attribute a,
|
|
||||||
pg_class c,
|
|
||||||
pg_type t
|
|
||||||
WHERE c.relname = ".$db->quote($table, 'text')."
|
|
||||||
AND a.atttypid = t.oid
|
|
||||||
AND c.oid = a.attrelid
|
|
||||||
AND NOT a.attisdropped
|
|
||||||
AND a.attnum > 0
|
|
||||||
AND a.attname = ".$db->quote($field_name, 'text')."
|
|
||||||
ORDER BY a.attnum";
|
|
||||||
$column = $db->queryRow($query, null, MDB2_FETCHMODE_ASSOC);
|
|
||||||
if (PEAR::isError($column)) {
|
|
||||||
return $column;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($column)) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
'it was not specified an existing table column', __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
$column = array_change_key_case($column, CASE_LOWER);
|
|
||||||
$mapped_datatype = $db->datatype->mapNativeDatatype($column);
|
|
||||||
if (PEAR::isError($mapped_datatype)) {
|
|
||||||
return $mapped_datatype;
|
|
||||||
}
|
|
||||||
list($types, $length, $unsigned, $fixed) = $mapped_datatype;
|
|
||||||
$notnull = false;
|
|
||||||
if (!empty($column['attnotnull']) && $column['attnotnull'] == 't') {
|
|
||||||
$notnull = true;
|
|
||||||
}
|
|
||||||
$default = null;
|
|
||||||
if ($column['atthasdef'] === 't'
|
|
||||||
&& strpos($column['default'], 'NULL') !== 0
|
|
||||||
&& !preg_match("/nextval\('([^']+)'/", $column['default'])
|
|
||||||
) {
|
|
||||||
$pattern = '/^\'(.*)\'::[\w ]+$/i';
|
|
||||||
$default = $column['default'];#substr($column['adsrc'], 1, -1);
|
|
||||||
if ((null === $default) && $notnull) {
|
|
||||||
$default = '';
|
|
||||||
} elseif (!empty($default) && preg_match($pattern, $default)) {
|
|
||||||
//remove data type cast
|
|
||||||
$default = preg_replace ($pattern, '\\1', $default);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$autoincrement = false;
|
|
||||||
if (preg_match("/nextval\('([^']+)'/", $column['default'], $nextvals)) {
|
|
||||||
$autoincrement = true;
|
|
||||||
}
|
|
||||||
$definition[0] = array('notnull' => $notnull, 'nativetype' => $column['type']);
|
|
||||||
if (null !== $length) {
|
|
||||||
$definition[0]['length'] = $length;
|
|
||||||
}
|
|
||||||
if (null !== $unsigned) {
|
|
||||||
$definition[0]['unsigned'] = $unsigned;
|
|
||||||
}
|
|
||||||
if (null !== $fixed) {
|
|
||||||
$definition[0]['fixed'] = $fixed;
|
|
||||||
}
|
|
||||||
if ($default !== false) {
|
|
||||||
$definition[0]['default'] = $default;
|
|
||||||
}
|
|
||||||
if ($autoincrement !== false) {
|
|
||||||
$definition[0]['autoincrement'] = $autoincrement;
|
|
||||||
}
|
|
||||||
foreach ($types as $key => $type) {
|
|
||||||
$definition[$key] = $definition[0];
|
|
||||||
if ($type == 'clob' || $type == 'blob') {
|
|
||||||
unset($definition[$key]['default']);
|
|
||||||
}
|
|
||||||
$definition[$key]['type'] = $type;
|
|
||||||
$definition[$key]['mdb2type'] = $type;
|
|
||||||
}
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getTableIndexDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the structure of an index into an array
|
|
||||||
*
|
|
||||||
* @param string $table_name name of table that should be used in method
|
|
||||||
* @param string $index_name name of index that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTableIndexDefinition($table_name, $index_name)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
list($schema, $table) = $this->splitTableSchema($table_name);
|
|
||||||
|
|
||||||
$query = 'SELECT relname, indkey FROM pg_index, pg_class';
|
|
||||||
$query.= ' WHERE pg_class.oid = pg_index.indexrelid';
|
|
||||||
$query.= " AND indisunique != 't' AND indisprimary != 't'";
|
|
||||||
$query.= ' AND pg_class.relname = %s';
|
|
||||||
$index_name_mdb2 = $db->getIndexName($index_name);
|
|
||||||
$row = $db->queryRow(sprintf($query, $db->quote($index_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC);
|
|
||||||
if (PEAR::isError($row) || empty($row)) {
|
|
||||||
// fallback to the given $index_name, without transformation
|
|
||||||
$row = $db->queryRow(sprintf($query, $db->quote($index_name, 'text')), null, MDB2_FETCHMODE_ASSOC);
|
|
||||||
}
|
|
||||||
if (PEAR::isError($row)) {
|
|
||||||
return $row;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($row)) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
'it was not specified an existing table index', __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
$row = array_change_key_case($row, CASE_LOWER);
|
|
||||||
|
|
||||||
$db->loadModule('Manager', null, true);
|
|
||||||
$columns = $db->manager->listTableFields($table_name);
|
|
||||||
|
|
||||||
$definition = array();
|
|
||||||
|
|
||||||
$index_column_numbers = explode(' ', $row['indkey']);
|
|
||||||
|
|
||||||
$colpos = 1;
|
|
||||||
foreach ($index_column_numbers as $number) {
|
|
||||||
$definition['fields'][$columns[($number - 1)]] = array(
|
|
||||||
'position' => $colpos++,
|
|
||||||
'sorting' => 'ascending',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getTableConstraintDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the structure of a constraint into an array
|
|
||||||
*
|
|
||||||
* @param string $table_name name of table that should be used in method
|
|
||||||
* @param string $constraint_name name of constraint that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTableConstraintDefinition($table_name, $constraint_name)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
list($schema, $table) = $this->splitTableSchema($table_name);
|
|
||||||
|
|
||||||
$query = "SELECT c.oid,
|
|
||||||
c.conname AS constraint_name,
|
|
||||||
CASE WHEN c.contype = 'c' THEN 1 ELSE 0 END AS \"check\",
|
|
||||||
CASE WHEN c.contype = 'f' THEN 1 ELSE 0 END AS \"foreign\",
|
|
||||||
CASE WHEN c.contype = 'p' THEN 1 ELSE 0 END AS \"primary\",
|
|
||||||
CASE WHEN c.contype = 'u' THEN 1 ELSE 0 END AS \"unique\",
|
|
||||||
CASE WHEN c.condeferrable = 'f' THEN 0 ELSE 1 END AS deferrable,
|
|
||||||
CASE WHEN c.condeferred = 'f' THEN 0 ELSE 1 END AS initiallydeferred,
|
|
||||||
--array_to_string(c.conkey, ' ') AS constraint_key,
|
|
||||||
t.relname AS table_name,
|
|
||||||
t2.relname AS references_table,
|
|
||||||
CASE confupdtype
|
|
||||||
WHEN 'a' THEN 'NO ACTION'
|
|
||||||
WHEN 'r' THEN 'RESTRICT'
|
|
||||||
WHEN 'c' THEN 'CASCADE'
|
|
||||||
WHEN 'n' THEN 'SET NULL'
|
|
||||||
WHEN 'd' THEN 'SET DEFAULT'
|
|
||||||
END AS onupdate,
|
|
||||||
CASE confdeltype
|
|
||||||
WHEN 'a' THEN 'NO ACTION'
|
|
||||||
WHEN 'r' THEN 'RESTRICT'
|
|
||||||
WHEN 'c' THEN 'CASCADE'
|
|
||||||
WHEN 'n' THEN 'SET NULL'
|
|
||||||
WHEN 'd' THEN 'SET DEFAULT'
|
|
||||||
END AS ondelete,
|
|
||||||
CASE confmatchtype
|
|
||||||
WHEN 'u' THEN 'UNSPECIFIED'
|
|
||||||
WHEN 'f' THEN 'FULL'
|
|
||||||
WHEN 'p' THEN 'PARTIAL'
|
|
||||||
END AS match,
|
|
||||||
--array_to_string(c.confkey, ' ') AS fk_constraint_key,
|
|
||||||
consrc
|
|
||||||
FROM pg_constraint c
|
|
||||||
LEFT JOIN pg_class t ON c.conrelid = t.oid
|
|
||||||
LEFT JOIN pg_class t2 ON c.confrelid = t2.oid
|
|
||||||
WHERE c.conname = %s
|
|
||||||
AND t.relname = " . $db->quote($table, 'text');
|
|
||||||
$constraint_name_mdb2 = $db->getIndexName($constraint_name);
|
|
||||||
$row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC);
|
|
||||||
if (PEAR::isError($row) || empty($row)) {
|
|
||||||
// fallback to the given $index_name, without transformation
|
|
||||||
$constraint_name_mdb2 = $constraint_name;
|
|
||||||
$row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC);
|
|
||||||
}
|
|
||||||
if (PEAR::isError($row)) {
|
|
||||||
return $row;
|
|
||||||
}
|
|
||||||
$uniqueIndex = false;
|
|
||||||
if (empty($row)) {
|
|
||||||
// We might be looking for a UNIQUE index that was not created
|
|
||||||
// as a constraint but should be treated as such.
|
|
||||||
$query = 'SELECT relname AS constraint_name,
|
|
||||||
indkey,
|
|
||||||
0 AS "check",
|
|
||||||
0 AS "foreign",
|
|
||||||
0 AS "primary",
|
|
||||||
1 AS "unique",
|
|
||||||
0 AS deferrable,
|
|
||||||
0 AS initiallydeferred,
|
|
||||||
NULL AS references_table,
|
|
||||||
NULL AS onupdate,
|
|
||||||
NULL AS ondelete,
|
|
||||||
NULL AS match
|
|
||||||
FROM pg_index, pg_class
|
|
||||||
WHERE pg_class.oid = pg_index.indexrelid
|
|
||||||
AND indisunique = \'t\'
|
|
||||||
AND pg_class.relname = %s';
|
|
||||||
$constraint_name_mdb2 = $db->getIndexName($constraint_name);
|
|
||||||
$row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC);
|
|
||||||
if (PEAR::isError($row) || empty($row)) {
|
|
||||||
// fallback to the given $index_name, without transformation
|
|
||||||
$constraint_name_mdb2 = $constraint_name;
|
|
||||||
$row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC);
|
|
||||||
}
|
|
||||||
if (PEAR::isError($row)) {
|
|
||||||
return $row;
|
|
||||||
}
|
|
||||||
if (empty($row)) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
$constraint_name . ' is not an existing table constraint', __FUNCTION__);
|
|
||||||
}
|
|
||||||
$uniqueIndex = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$row = array_change_key_case($row, CASE_LOWER);
|
|
||||||
|
|
||||||
$definition = array(
|
|
||||||
'primary' => (boolean)$row['primary'],
|
|
||||||
'unique' => (boolean)$row['unique'],
|
|
||||||
'foreign' => (boolean)$row['foreign'],
|
|
||||||
'check' => (boolean)$row['check'],
|
|
||||||
'fields' => array(),
|
|
||||||
'references' => array(
|
|
||||||
'table' => $row['references_table'],
|
|
||||||
'fields' => array(),
|
|
||||||
),
|
|
||||||
'deferrable' => (boolean)$row['deferrable'],
|
|
||||||
'initiallydeferred' => (boolean)$row['initiallydeferred'],
|
|
||||||
'onupdate' => $row['onupdate'],
|
|
||||||
'ondelete' => $row['ondelete'],
|
|
||||||
'match' => $row['match'],
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($uniqueIndex) {
|
|
||||||
$db->loadModule('Manager', null, true);
|
|
||||||
$columns = $db->manager->listTableFields($table_name);
|
|
||||||
$index_column_numbers = explode(' ', $row['indkey']);
|
|
||||||
$colpos = 1;
|
|
||||||
foreach ($index_column_numbers as $number) {
|
|
||||||
$definition['fields'][$columns[($number - 1)]] = array(
|
|
||||||
'position' => $colpos++,
|
|
||||||
'sorting' => 'ascending',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = 'SELECT a.attname
|
|
||||||
FROM pg_constraint c
|
|
||||||
LEFT JOIN pg_class t ON c.conrelid = t.oid
|
|
||||||
LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.conkey)
|
|
||||||
WHERE c.conname = %s
|
|
||||||
AND t.relname = ' . $db->quote($table, 'text');
|
|
||||||
$fields = $db->queryCol(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null);
|
|
||||||
if (PEAR::isError($fields)) {
|
|
||||||
return $fields;
|
|
||||||
}
|
|
||||||
$colpos = 1;
|
|
||||||
foreach ($fields as $field) {
|
|
||||||
$definition['fields'][$field] = array(
|
|
||||||
'position' => $colpos++,
|
|
||||||
'sorting' => 'ascending',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($definition['foreign']) {
|
|
||||||
$query = 'SELECT a.attname
|
|
||||||
FROM pg_constraint c
|
|
||||||
LEFT JOIN pg_class t ON c.confrelid = t.oid
|
|
||||||
LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.confkey)
|
|
||||||
WHERE c.conname = %s
|
|
||||||
AND t.relname = ' . $db->quote($definition['references']['table'], 'text');
|
|
||||||
$foreign_fields = $db->queryCol(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null);
|
|
||||||
if (PEAR::isError($foreign_fields)) {
|
|
||||||
return $foreign_fields;
|
|
||||||
}
|
|
||||||
$colpos = 1;
|
|
||||||
foreach ($foreign_fields as $foreign_field) {
|
|
||||||
$definition['references']['fields'][$foreign_field] = array(
|
|
||||||
'position' => $colpos++,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($definition['check']) {
|
|
||||||
$check_def = $db->queryOne("SELECT pg_get_constraintdef(" . $row['oid'] . ", 't')");
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getTriggerDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the structure of a trigger into an array
|
|
||||||
*
|
|
||||||
* EXPERIMENTAL
|
|
||||||
*
|
|
||||||
* WARNING: this function is experimental and may change the returned value
|
|
||||||
* at any time until labelled as non-experimental
|
|
||||||
*
|
|
||||||
* @param string $trigger name of trigger that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*
|
|
||||||
* @TODO: add support for plsql functions and functions with args
|
|
||||||
*/
|
|
||||||
function getTriggerDefinition($trigger)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = "SELECT trg.tgname AS trigger_name,
|
|
||||||
tbl.relname AS table_name,
|
|
||||||
CASE
|
|
||||||
WHEN p.proname IS NOT NULL THEN 'EXECUTE PROCEDURE ' || p.proname || '();'
|
|
||||||
ELSE ''
|
|
||||||
END AS trigger_body,
|
|
||||||
CASE trg.tgtype & cast(2 as int2)
|
|
||||||
WHEN 0 THEN 'AFTER'
|
|
||||||
ELSE 'BEFORE'
|
|
||||||
END AS trigger_type,
|
|
||||||
CASE trg.tgtype & cast(28 as int2)
|
|
||||||
WHEN 16 THEN 'UPDATE'
|
|
||||||
WHEN 8 THEN 'DELETE'
|
|
||||||
WHEN 4 THEN 'INSERT'
|
|
||||||
WHEN 20 THEN 'INSERT, UPDATE'
|
|
||||||
WHEN 28 THEN 'INSERT, UPDATE, DELETE'
|
|
||||||
WHEN 24 THEN 'UPDATE, DELETE'
|
|
||||||
WHEN 12 THEN 'INSERT, DELETE'
|
|
||||||
END AS trigger_event,
|
|
||||||
CASE trg.tgenabled
|
|
||||||
WHEN 'O' THEN 't'
|
|
||||||
ELSE trg.tgenabled
|
|
||||||
END AS trigger_enabled,
|
|
||||||
obj_description(trg.oid, 'pg_trigger') AS trigger_comment
|
|
||||||
FROM pg_trigger trg,
|
|
||||||
pg_class tbl,
|
|
||||||
pg_proc p
|
|
||||||
WHERE trg.tgrelid = tbl.oid
|
|
||||||
AND trg.tgfoid = p.oid
|
|
||||||
AND trg.tgname = ". $db->quote($trigger, 'text');
|
|
||||||
$types = array(
|
|
||||||
'trigger_name' => 'text',
|
|
||||||
'table_name' => 'text',
|
|
||||||
'trigger_body' => 'text',
|
|
||||||
'trigger_type' => 'text',
|
|
||||||
'trigger_event' => 'text',
|
|
||||||
'trigger_comment' => 'text',
|
|
||||||
'trigger_enabled' => 'boolean',
|
|
||||||
);
|
|
||||||
return $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ tableInfo()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns information about a table or a result set
|
|
||||||
*
|
|
||||||
* NOTE: only supports 'table' and 'flags' if <var>$result</var>
|
|
||||||
* is a table name.
|
|
||||||
*
|
|
||||||
* @param object|string $result MDB2_result object from a query or a
|
|
||||||
* string containing the name of a table.
|
|
||||||
* While this also accepts a query result
|
|
||||||
* resource identifier, this behavior is
|
|
||||||
* deprecated.
|
|
||||||
* @param int $mode a valid tableInfo mode
|
|
||||||
*
|
|
||||||
* @return array an associative array with the information requested.
|
|
||||||
* A MDB2_Error object on failure.
|
|
||||||
*
|
|
||||||
* @see MDB2_Driver_Common::tableInfo()
|
|
||||||
*/
|
|
||||||
function tableInfo($result, $mode = null)
|
|
||||||
{
|
|
||||||
if (is_string($result)) {
|
|
||||||
return parent::tableInfo($result, $mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$resource = MDB2::isResultCommon($result) ? $result->getResource() : $result;
|
|
||||||
if (!is_resource($resource)) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
|
|
||||||
'Could not generate result resource', __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
if ($db->options['field_case'] == CASE_LOWER) {
|
|
||||||
$case_func = 'strtolower';
|
|
||||||
} else {
|
|
||||||
$case_func = 'strtoupper';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$case_func = 'strval';
|
|
||||||
}
|
|
||||||
|
|
||||||
$count = @pg_num_fields($resource);
|
|
||||||
$res = array();
|
|
||||||
|
|
||||||
if ($mode) {
|
|
||||||
$res['num_fields'] = $count;
|
|
||||||
}
|
|
||||||
|
|
||||||
$db->loadModule('Datatype', null, true);
|
|
||||||
for ($i = 0; $i < $count; $i++) {
|
|
||||||
$res[$i] = array(
|
|
||||||
'table' => function_exists('pg_field_table') ? @pg_field_table($resource, $i) : '',
|
|
||||||
'name' => $case_func(@pg_field_name($resource, $i)),
|
|
||||||
'type' => @pg_field_type($resource, $i),
|
|
||||||
'length' => @pg_field_size($resource, $i),
|
|
||||||
'flags' => '',
|
|
||||||
);
|
|
||||||
$mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]);
|
|
||||||
if (PEAR::isError($mdb2type_info)) {
|
|
||||||
return $mdb2type_info;
|
|
||||||
}
|
|
||||||
$res[$i]['mdb2type'] = $mdb2type_info[0][0];
|
|
||||||
if ($mode & MDB2_TABLEINFO_ORDER) {
|
|
||||||
$res['order'][$res[$i]['name']] = $i;
|
|
||||||
}
|
|
||||||
if ($mode & MDB2_TABLEINFO_ORDERTABLE) {
|
|
||||||
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
|
@ -1,611 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith, Lorenzo Alberton |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Authors: Lukas Smith <smith@pooteeweet.org> |
|
|
||||||
// | Lorenzo Alberton <l.alberton@quipo.it> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
|
|
||||||
require_once 'MDB2/Driver/Reverse/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MDB2 SQlite driver for the schema reverse engineering module
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
class MDB2_Driver_Reverse_sqlite extends MDB2_Driver_Reverse_Common
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Remove SQL comments from the field definition
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
function _removeComments($sql) {
|
|
||||||
$lines = explode("\n", $sql);
|
|
||||||
foreach ($lines as $k => $line) {
|
|
||||||
$pieces = explode('--', $line);
|
|
||||||
if (count($pieces) > 1 && (substr_count($pieces[0], '\'') % 2) == 0) {
|
|
||||||
$lines[$k] = substr($line, 0, strpos($line, '--'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return implode("\n", $lines);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function _getTableColumns($sql)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
$start_pos = strpos($sql, '(');
|
|
||||||
$end_pos = strrpos($sql, ')');
|
|
||||||
$column_def = substr($sql, $start_pos+1, $end_pos-$start_pos-1);
|
|
||||||
// replace the decimal length-places-separator with a colon
|
|
||||||
$column_def = preg_replace('/(\d),(\d)/', '\1:\2', $column_def);
|
|
||||||
$column_def = $this->_removeComments($column_def);
|
|
||||||
$column_sql = explode(',', $column_def);
|
|
||||||
$columns = array();
|
|
||||||
$count = count($column_sql);
|
|
||||||
if ($count == 0) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
|
||||||
'unexpected empty table column definition list', __FUNCTION__);
|
|
||||||
}
|
|
||||||
$regexp = '/^\s*([^\s]+) +(CHAR|VARCHAR|VARCHAR2|TEXT|BOOLEAN|SMALLINT|INT|INTEGER|DECIMAL|TINYINT|BIGINT|DOUBLE|FLOAT|DATETIME|DATE|TIME|LONGTEXT|LONGBLOB)( ?\(([1-9][0-9]*)(:([1-9][0-9]*))?\))?( NULL| NOT NULL)?( UNSIGNED)?( NULL| NOT NULL)?( PRIMARY KEY)?( DEFAULT (\'[^\']*\'|[^ ]+))?( NULL| NOT NULL)?( PRIMARY KEY)?(\s*\-\-.*)?$/i';
|
|
||||||
$regexp2 = '/^\s*([^ ]+) +(PRIMARY|UNIQUE|CHECK)$/i';
|
|
||||||
for ($i=0, $j=0; $i<$count; ++$i) {
|
|
||||||
if (!preg_match($regexp, trim($column_sql[$i]), $matches)) {
|
|
||||||
if (!preg_match($regexp2, trim($column_sql[$i]))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
|
||||||
'unexpected table column SQL definition: "'.$column_sql[$i].'"', __FUNCTION__);
|
|
||||||
}
|
|
||||||
$columns[$j]['name'] = trim($matches[1], implode('', $db->identifier_quoting));
|
|
||||||
$columns[$j]['type'] = strtolower($matches[2]);
|
|
||||||
if (isset($matches[4]) && strlen($matches[4])) {
|
|
||||||
$columns[$j]['length'] = $matches[4];
|
|
||||||
}
|
|
||||||
if (isset($matches[6]) && strlen($matches[6])) {
|
|
||||||
$columns[$j]['decimal'] = $matches[6];
|
|
||||||
}
|
|
||||||
if (isset($matches[8]) && strlen($matches[8])) {
|
|
||||||
$columns[$j]['unsigned'] = true;
|
|
||||||
}
|
|
||||||
if (isset($matches[9]) && strlen($matches[9])) {
|
|
||||||
$columns[$j]['autoincrement'] = true;
|
|
||||||
}
|
|
||||||
if (isset($matches[12]) && strlen($matches[12])) {
|
|
||||||
$default = $matches[12];
|
|
||||||
if (strlen($default) && $default[0]=="'") {
|
|
||||||
$default = str_replace("''", "'", substr($default, 1, strlen($default)-2));
|
|
||||||
}
|
|
||||||
if ($default === 'NULL') {
|
|
||||||
$default = null;
|
|
||||||
}
|
|
||||||
$columns[$j]['default'] = $default;
|
|
||||||
} else {
|
|
||||||
$columns[$j]['default'] = null;
|
|
||||||
}
|
|
||||||
if (isset($matches[7]) && strlen($matches[7])) {
|
|
||||||
$columns[$j]['notnull'] = ($matches[7] === ' NOT NULL');
|
|
||||||
} else if (isset($matches[9]) && strlen($matches[9])) {
|
|
||||||
$columns[$j]['notnull'] = ($matches[9] === ' NOT NULL');
|
|
||||||
} else if (isset($matches[13]) && strlen($matches[13])) {
|
|
||||||
$columns[$j]['notnull'] = ($matches[13] === ' NOT NULL');
|
|
||||||
}
|
|
||||||
++$j;
|
|
||||||
}
|
|
||||||
return $columns;
|
|
||||||
}
|
|
||||||
|
|
||||||
// {{{ getTableFieldDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the stucture of a field into an array
|
|
||||||
*
|
|
||||||
* @param string $table_name name of table that should be used in method
|
|
||||||
* @param string $field_name name of field that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure.
|
|
||||||
* The returned array contains an array for each field definition,
|
|
||||||
* with (some of) these indices:
|
|
||||||
* [notnull] [nativetype] [length] [fixed] [default] [type] [mdb2type]
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTableFieldDefinition($table_name, $field_name)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
list($schema, $table) = $this->splitTableSchema($table_name);
|
|
||||||
|
|
||||||
$result = $db->loadModule('Datatype', null, true);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
$query = "SELECT sql FROM sqlite_master WHERE type='table' AND ";
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
$query.= 'LOWER(name)='.$db->quote(strtolower($table), 'text');
|
|
||||||
} else {
|
|
||||||
$query.= 'name='.$db->quote($table, 'text');
|
|
||||||
}
|
|
||||||
$sql = $db->queryOne($query);
|
|
||||||
if (PEAR::isError($sql)) {
|
|
||||||
return $sql;
|
|
||||||
}
|
|
||||||
$columns = $this->_getTableColumns($sql);
|
|
||||||
foreach ($columns as $column) {
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
if ($db->options['field_case'] == CASE_LOWER) {
|
|
||||||
$column['name'] = strtolower($column['name']);
|
|
||||||
} else {
|
|
||||||
$column['name'] = strtoupper($column['name']);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$column = array_change_key_case($column, $db->options['field_case']);
|
|
||||||
}
|
|
||||||
if ($field_name == $column['name']) {
|
|
||||||
$mapped_datatype = $db->datatype->mapNativeDatatype($column);
|
|
||||||
if (PEAR::isError($mapped_datatype)) {
|
|
||||||
return $mapped_datatype;
|
|
||||||
}
|
|
||||||
list($types, $length, $unsigned, $fixed) = $mapped_datatype;
|
|
||||||
$notnull = false;
|
|
||||||
if (!empty($column['notnull'])) {
|
|
||||||
$notnull = $column['notnull'];
|
|
||||||
}
|
|
||||||
$default = false;
|
|
||||||
if (array_key_exists('default', $column)) {
|
|
||||||
$default = $column['default'];
|
|
||||||
if ((null === $default) && $notnull) {
|
|
||||||
$default = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$autoincrement = false;
|
|
||||||
if (!empty($column['autoincrement'])) {
|
|
||||||
$autoincrement = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$definition[0] = array(
|
|
||||||
'notnull' => $notnull,
|
|
||||||
'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type'])
|
|
||||||
);
|
|
||||||
if (null !== $length) {
|
|
||||||
$definition[0]['length'] = $length;
|
|
||||||
}
|
|
||||||
if (null !== $unsigned) {
|
|
||||||
$definition[0]['unsigned'] = $unsigned;
|
|
||||||
}
|
|
||||||
if (null !== $fixed) {
|
|
||||||
$definition[0]['fixed'] = $fixed;
|
|
||||||
}
|
|
||||||
if ($default !== false) {
|
|
||||||
$definition[0]['default'] = $default;
|
|
||||||
}
|
|
||||||
if ($autoincrement !== false) {
|
|
||||||
$definition[0]['autoincrement'] = $autoincrement;
|
|
||||||
}
|
|
||||||
foreach ($types as $key => $type) {
|
|
||||||
$definition[$key] = $definition[0];
|
|
||||||
if ($type == 'clob' || $type == 'blob') {
|
|
||||||
unset($definition[$key]['default']);
|
|
||||||
}
|
|
||||||
$definition[$key]['type'] = $type;
|
|
||||||
$definition[$key]['mdb2type'] = $type;
|
|
||||||
}
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
'it was not specified an existing table column', __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getTableIndexDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the stucture of an index into an array
|
|
||||||
*
|
|
||||||
* @param string $table_name name of table that should be used in method
|
|
||||||
* @param string $index_name name of index that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTableIndexDefinition($table_name, $index_name)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
list($schema, $table) = $this->splitTableSchema($table_name);
|
|
||||||
|
|
||||||
$query = "SELECT sql FROM sqlite_master WHERE type='index' AND ";
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
$query.= 'LOWER(name)=%s AND LOWER(tbl_name)=' . $db->quote(strtolower($table), 'text');
|
|
||||||
} else {
|
|
||||||
$query.= 'name=%s AND tbl_name=' . $db->quote($table, 'text');
|
|
||||||
}
|
|
||||||
$query.= ' AND sql NOT NULL ORDER BY name';
|
|
||||||
$index_name_mdb2 = $db->getIndexName($index_name);
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
$qry = sprintf($query, $db->quote(strtolower($index_name_mdb2), 'text'));
|
|
||||||
} else {
|
|
||||||
$qry = sprintf($query, $db->quote($index_name_mdb2, 'text'));
|
|
||||||
}
|
|
||||||
$sql = $db->queryOne($qry, 'text');
|
|
||||||
if (PEAR::isError($sql) || empty($sql)) {
|
|
||||||
// fallback to the given $index_name, without transformation
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
$qry = sprintf($query, $db->quote(strtolower($index_name), 'text'));
|
|
||||||
} else {
|
|
||||||
$qry = sprintf($query, $db->quote($index_name, 'text'));
|
|
||||||
}
|
|
||||||
$sql = $db->queryOne($qry, 'text');
|
|
||||||
}
|
|
||||||
if (PEAR::isError($sql)) {
|
|
||||||
return $sql;
|
|
||||||
}
|
|
||||||
if (!$sql) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
'it was not specified an existing table index', __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
$sql = strtolower($sql);
|
|
||||||
$start_pos = strpos($sql, '(');
|
|
||||||
$end_pos = strrpos($sql, ')');
|
|
||||||
$column_names = substr($sql, $start_pos+1, $end_pos-$start_pos-1);
|
|
||||||
$column_names = explode(',', $column_names);
|
|
||||||
|
|
||||||
if (preg_match("/^create unique/", $sql)) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
'it was not specified an existing table index', __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
$definition = array();
|
|
||||||
$count = count($column_names);
|
|
||||||
for ($i=0; $i<$count; ++$i) {
|
|
||||||
$column_name = strtok($column_names[$i], ' ');
|
|
||||||
$collation = strtok(' ');
|
|
||||||
$definition['fields'][$column_name] = array(
|
|
||||||
'position' => $i+1
|
|
||||||
);
|
|
||||||
if (!empty($collation)) {
|
|
||||||
$definition['fields'][$column_name]['sorting'] =
|
|
||||||
($collation=='ASC' ? 'ascending' : 'descending');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($definition['fields'])) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
'it was not specified an existing table index', __FUNCTION__);
|
|
||||||
}
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getTableConstraintDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the stucture of a constraint into an array
|
|
||||||
*
|
|
||||||
* @param string $table_name name of table that should be used in method
|
|
||||||
* @param string $constraint_name name of constraint that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTableConstraintDefinition($table_name, $constraint_name)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
list($schema, $table) = $this->splitTableSchema($table_name);
|
|
||||||
|
|
||||||
$query = "SELECT sql FROM sqlite_master WHERE type='index' AND ";
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
$query.= 'LOWER(name)=%s AND LOWER(tbl_name)=' . $db->quote(strtolower($table), 'text');
|
|
||||||
} else {
|
|
||||||
$query.= 'name=%s AND tbl_name=' . $db->quote($table, 'text');
|
|
||||||
}
|
|
||||||
$query.= ' AND sql NOT NULL ORDER BY name';
|
|
||||||
$constraint_name_mdb2 = $db->getIndexName($constraint_name);
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
$qry = sprintf($query, $db->quote(strtolower($constraint_name_mdb2), 'text'));
|
|
||||||
} else {
|
|
||||||
$qry = sprintf($query, $db->quote($constraint_name_mdb2, 'text'));
|
|
||||||
}
|
|
||||||
$sql = $db->queryOne($qry, 'text');
|
|
||||||
if (PEAR::isError($sql) || empty($sql)) {
|
|
||||||
// fallback to the given $index_name, without transformation
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
$qry = sprintf($query, $db->quote(strtolower($constraint_name), 'text'));
|
|
||||||
} else {
|
|
||||||
$qry = sprintf($query, $db->quote($constraint_name, 'text'));
|
|
||||||
}
|
|
||||||
$sql = $db->queryOne($qry, 'text');
|
|
||||||
}
|
|
||||||
if (PEAR::isError($sql)) {
|
|
||||||
return $sql;
|
|
||||||
}
|
|
||||||
//default values, eventually overridden
|
|
||||||
$definition = array(
|
|
||||||
'primary' => false,
|
|
||||||
'unique' => false,
|
|
||||||
'foreign' => false,
|
|
||||||
'check' => false,
|
|
||||||
'fields' => array(),
|
|
||||||
'references' => array(
|
|
||||||
'table' => '',
|
|
||||||
'fields' => array(),
|
|
||||||
),
|
|
||||||
'onupdate' => '',
|
|
||||||
'ondelete' => '',
|
|
||||||
'match' => '',
|
|
||||||
'deferrable' => false,
|
|
||||||
'initiallydeferred' => false,
|
|
||||||
);
|
|
||||||
if (!$sql) {
|
|
||||||
$query = "SELECT sql FROM sqlite_master WHERE type='table' AND ";
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
$query.= 'LOWER(name)='.$db->quote(strtolower($table), 'text');
|
|
||||||
} else {
|
|
||||||
$query.= 'name='.$db->quote($table, 'text');
|
|
||||||
}
|
|
||||||
$query.= " AND sql NOT NULL ORDER BY name";
|
|
||||||
$sql = $db->queryOne($query, 'text');
|
|
||||||
if (PEAR::isError($sql)) {
|
|
||||||
return $sql;
|
|
||||||
}
|
|
||||||
if ($constraint_name == 'primary') {
|
|
||||||
// search in table definition for PRIMARY KEYs
|
|
||||||
if (preg_match("/\bPRIMARY\s+KEY\b\s*\(([^)]+)/i", $sql, $tmp)) {
|
|
||||||
$definition['primary'] = true;
|
|
||||||
$definition['fields'] = array();
|
|
||||||
$column_names = explode(',', $tmp[1]);
|
|
||||||
$colpos = 1;
|
|
||||||
foreach ($column_names as $column_name) {
|
|
||||||
$definition['fields'][trim($column_name)] = array(
|
|
||||||
'position' => $colpos++
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
if (preg_match("/\"([^\"]+)\"[^\,\"]+\bPRIMARY\s+KEY\b[^\,\)]*/i", $sql, $tmp)) {
|
|
||||||
$definition['primary'] = true;
|
|
||||||
$definition['fields'] = array();
|
|
||||||
$column_names = explode(',', $tmp[1]);
|
|
||||||
$colpos = 1;
|
|
||||||
foreach ($column_names as $column_name) {
|
|
||||||
$definition['fields'][trim($column_name)] = array(
|
|
||||||
'position' => $colpos++
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// search in table definition for FOREIGN KEYs
|
|
||||||
$pattern = "/\bCONSTRAINT\b\s+%s\s+
|
|
||||||
\bFOREIGN\s+KEY\b\s*\(([^\)]+)\)\s*
|
|
||||||
\bREFERENCES\b\s+([^\s]+)\s*\(([^\)]+)\)\s*
|
|
||||||
(?:\bMATCH\s*([^\s]+))?\s*
|
|
||||||
(?:\bON\s+UPDATE\s+([^\s,\)]+))?\s*
|
|
||||||
(?:\bON\s+DELETE\s+([^\s,\)]+))?\s*
|
|
||||||
/imsx";
|
|
||||||
$found_fk = false;
|
|
||||||
if (preg_match(sprintf($pattern, $constraint_name_mdb2), $sql, $tmp)) {
|
|
||||||
$found_fk = true;
|
|
||||||
} elseif (preg_match(sprintf($pattern, $constraint_name), $sql, $tmp)) {
|
|
||||||
$found_fk = true;
|
|
||||||
}
|
|
||||||
if ($found_fk) {
|
|
||||||
$definition['foreign'] = true;
|
|
||||||
$definition['match'] = 'SIMPLE';
|
|
||||||
$definition['onupdate'] = 'NO ACTION';
|
|
||||||
$definition['ondelete'] = 'NO ACTION';
|
|
||||||
$definition['references']['table'] = $tmp[2];
|
|
||||||
$column_names = explode(',', $tmp[1]);
|
|
||||||
$colpos = 1;
|
|
||||||
foreach ($column_names as $column_name) {
|
|
||||||
$definition['fields'][trim($column_name)] = array(
|
|
||||||
'position' => $colpos++
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$referenced_cols = explode(',', $tmp[3]);
|
|
||||||
$colpos = 1;
|
|
||||||
foreach ($referenced_cols as $column_name) {
|
|
||||||
$definition['references']['fields'][trim($column_name)] = array(
|
|
||||||
'position' => $colpos++
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (isset($tmp[4])) {
|
|
||||||
$definition['match'] = $tmp[4];
|
|
||||||
}
|
|
||||||
if (isset($tmp[5])) {
|
|
||||||
$definition['onupdate'] = $tmp[5];
|
|
||||||
}
|
|
||||||
if (isset($tmp[6])) {
|
|
||||||
$definition['ondelete'] = $tmp[6];
|
|
||||||
}
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$sql = false;
|
|
||||||
}
|
|
||||||
if (!$sql) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
$constraint_name . ' is not an existing table constraint', __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
$sql = strtolower($sql);
|
|
||||||
$start_pos = strpos($sql, '(');
|
|
||||||
$end_pos = strrpos($sql, ')');
|
|
||||||
$column_names = substr($sql, $start_pos+1, $end_pos-$start_pos-1);
|
|
||||||
$column_names = explode(',', $column_names);
|
|
||||||
|
|
||||||
if (!preg_match("/^create unique/", $sql)) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
$constraint_name . ' is not an existing table constraint', __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
$definition['unique'] = true;
|
|
||||||
$count = count($column_names);
|
|
||||||
for ($i=0; $i<$count; ++$i) {
|
|
||||||
$column_name = strtok($column_names[$i]," ");
|
|
||||||
$collation = strtok(" ");
|
|
||||||
$definition['fields'][$column_name] = array(
|
|
||||||
'position' => $i+1
|
|
||||||
);
|
|
||||||
if (!empty($collation)) {
|
|
||||||
$definition['fields'][$column_name]['sorting'] =
|
|
||||||
($collation=='ASC' ? 'ascending' : 'descending');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($definition['fields'])) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
$constraint_name . ' is not an existing table constraint', __FUNCTION__);
|
|
||||||
}
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getTriggerDefinition()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the structure of a trigger into an array
|
|
||||||
*
|
|
||||||
* EXPERIMENTAL
|
|
||||||
*
|
|
||||||
* WARNING: this function is experimental and may change the returned value
|
|
||||||
* at any time until labelled as non-experimental
|
|
||||||
*
|
|
||||||
* @param string $trigger name of trigger that should be used in method
|
|
||||||
* @return mixed data array on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getTriggerDefinition($trigger)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = "SELECT name as trigger_name,
|
|
||||||
tbl_name AS table_name,
|
|
||||||
sql AS trigger_body,
|
|
||||||
NULL AS trigger_type,
|
|
||||||
NULL AS trigger_event,
|
|
||||||
NULL AS trigger_comment,
|
|
||||||
1 AS trigger_enabled
|
|
||||||
FROM sqlite_master
|
|
||||||
WHERE type='trigger'";
|
|
||||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
|
|
||||||
$query.= ' AND LOWER(name)='.$db->quote(strtolower($trigger), 'text');
|
|
||||||
} else {
|
|
||||||
$query.= ' AND name='.$db->quote($trigger, 'text');
|
|
||||||
}
|
|
||||||
$types = array(
|
|
||||||
'trigger_name' => 'text',
|
|
||||||
'table_name' => 'text',
|
|
||||||
'trigger_body' => 'text',
|
|
||||||
'trigger_type' => 'text',
|
|
||||||
'trigger_event' => 'text',
|
|
||||||
'trigger_comment' => 'text',
|
|
||||||
'trigger_enabled' => 'boolean',
|
|
||||||
);
|
|
||||||
$def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC);
|
|
||||||
if (PEAR::isError($def)) {
|
|
||||||
return $def;
|
|
||||||
}
|
|
||||||
if (empty($def)) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
|
||||||
'it was not specified an existing trigger', __FUNCTION__);
|
|
||||||
}
|
|
||||||
if (preg_match("/^create\s+(?:temp|temporary)?trigger\s+(?:if\s+not\s+exists\s+)?.*(before|after)?\s+(insert|update|delete)/Uims", $def['trigger_body'], $tmp)) {
|
|
||||||
$def['trigger_type'] = strtoupper($tmp[1]);
|
|
||||||
$def['trigger_event'] = strtoupper($tmp[2]);
|
|
||||||
}
|
|
||||||
return $def;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ tableInfo()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns information about a table
|
|
||||||
*
|
|
||||||
* @param string $result a string containing the name of a table
|
|
||||||
* @param int $mode a valid tableInfo mode
|
|
||||||
*
|
|
||||||
* @return array an associative array with the information requested.
|
|
||||||
* A MDB2_Error object on failure.
|
|
||||||
*
|
|
||||||
* @see MDB2_Driver_Common::tableInfo()
|
|
||||||
* @since Method available since Release 1.7.0
|
|
||||||
*/
|
|
||||||
function tableInfo($result, $mode = null)
|
|
||||||
{
|
|
||||||
if (is_string($result)) {
|
|
||||||
return parent::tableInfo($result, $mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $db->raiseError(MDB2_ERROR_NOT_CAPABLE, null, null,
|
|
||||||
'This DBMS can not obtain tableInfo from result sets', __FUNCTION__);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,723 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP versions 4 and 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Lukas Smith <smith@pooteeweet.org> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used by autoPrepare()
|
|
||||||
*/
|
|
||||||
define('MDB2_AUTOQUERY_INSERT', 1);
|
|
||||||
define('MDB2_AUTOQUERY_UPDATE', 2);
|
|
||||||
define('MDB2_AUTOQUERY_DELETE', 3);
|
|
||||||
define('MDB2_AUTOQUERY_SELECT', 4);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MDB2_Extended: class which adds several high level methods to MDB2
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
class MDB2_Extended extends MDB2_Module_Common
|
|
||||||
{
|
|
||||||
// {{{ autoPrepare()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate an insert, update or delete query and call prepare() on it
|
|
||||||
*
|
|
||||||
* @param string table
|
|
||||||
* @param array the fields names
|
|
||||||
* @param int type of query to build
|
|
||||||
* MDB2_AUTOQUERY_INSERT
|
|
||||||
* MDB2_AUTOQUERY_UPDATE
|
|
||||||
* MDB2_AUTOQUERY_DELETE
|
|
||||||
* MDB2_AUTOQUERY_SELECT
|
|
||||||
* @param string (in case of update and delete queries, this string will be put after the sql WHERE statement)
|
|
||||||
* @param array that contains the types of the placeholders
|
|
||||||
* @param mixed array that contains the types of the columns in
|
|
||||||
* the result set or MDB2_PREPARE_RESULT, if set to
|
|
||||||
* MDB2_PREPARE_MANIP the query is handled as a manipulation query
|
|
||||||
*
|
|
||||||
* @return resource handle for the query
|
|
||||||
* @see buildManipSQL
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function autoPrepare($table, $table_fields, $mode = MDB2_AUTOQUERY_INSERT,
|
|
||||||
$where = false, $types = null, $result_types = MDB2_PREPARE_MANIP)
|
|
||||||
{
|
|
||||||
$query = $this->buildManipSQL($table, $table_fields, $mode, $where);
|
|
||||||
if (PEAR::isError($query)) {
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
$lobs = array();
|
|
||||||
foreach ((array)$types as $param => $type) {
|
|
||||||
if (($type == 'clob') || ($type == 'blob')) {
|
|
||||||
$lobs[$param] = $table_fields[$param];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $db->prepare($query, $types, $result_types, $lobs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ autoExecute()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate an insert, update or delete query and call prepare() and execute() on it
|
|
||||||
*
|
|
||||||
* @param string name of the table
|
|
||||||
* @param array assoc ($key=>$value) where $key is a field name and $value its value
|
|
||||||
* @param int type of query to build
|
|
||||||
* MDB2_AUTOQUERY_INSERT
|
|
||||||
* MDB2_AUTOQUERY_UPDATE
|
|
||||||
* MDB2_AUTOQUERY_DELETE
|
|
||||||
* MDB2_AUTOQUERY_SELECT
|
|
||||||
* @param string (in case of update and delete queries, this string will be put after the sql WHERE statement)
|
|
||||||
* @param array that contains the types of the placeholders
|
|
||||||
* @param string which specifies which result class to use
|
|
||||||
* @param mixed array that contains the types of the columns in
|
|
||||||
* the result set or MDB2_PREPARE_RESULT, if set to
|
|
||||||
* MDB2_PREPARE_MANIP the query is handled as a manipulation query
|
|
||||||
*
|
|
||||||
* @return bool|MDB2_Error true on success, a MDB2 error on failure
|
|
||||||
* @see buildManipSQL
|
|
||||||
* @see autoPrepare
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function autoExecute($table, $fields_values, $mode = MDB2_AUTOQUERY_INSERT,
|
|
||||||
$where = false, $types = null, $result_class = true, $result_types = MDB2_PREPARE_MANIP)
|
|
||||||
{
|
|
||||||
$fields_values = (array)$fields_values;
|
|
||||||
if ($mode == MDB2_AUTOQUERY_SELECT) {
|
|
||||||
if (is_array($result_types)) {
|
|
||||||
$keys = array_keys($result_types);
|
|
||||||
} elseif (!empty($fields_values)) {
|
|
||||||
$keys = $fields_values;
|
|
||||||
} else {
|
|
||||||
$keys = array();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$keys = array_keys($fields_values);
|
|
||||||
}
|
|
||||||
$params = array_values($fields_values);
|
|
||||||
if (empty($params)) {
|
|
||||||
$query = $this->buildManipSQL($table, $keys, $mode, $where);
|
|
||||||
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
if ($mode == MDB2_AUTOQUERY_SELECT) {
|
|
||||||
$result = $db->query($query, $result_types, $result_class);
|
|
||||||
} else {
|
|
||||||
$result = $db->exec($query);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$stmt = $this->autoPrepare($table, $keys, $mode, $where, $types, $result_types);
|
|
||||||
if (PEAR::isError($stmt)) {
|
|
||||||
return $stmt;
|
|
||||||
}
|
|
||||||
$result = $stmt->execute($params, $result_class);
|
|
||||||
$stmt->free();
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ buildManipSQL()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make automaticaly an sql query for prepare()
|
|
||||||
*
|
|
||||||
* Example : buildManipSQL('table_sql', array('field1', 'field2', 'field3'), MDB2_AUTOQUERY_INSERT)
|
|
||||||
* will return the string : INSERT INTO table_sql (field1,field2,field3) VALUES (?,?,?)
|
|
||||||
* NB : - This belongs more to a SQL Builder class, but this is a simple facility
|
|
||||||
* - Be carefull ! If you don't give a $where param with an UPDATE/DELETE query, all
|
|
||||||
* the records of the table will be updated/deleted !
|
|
||||||
*
|
|
||||||
* @param string name of the table
|
|
||||||
* @param ordered array containing the fields names
|
|
||||||
* @param int type of query to build
|
|
||||||
* MDB2_AUTOQUERY_INSERT
|
|
||||||
* MDB2_AUTOQUERY_UPDATE
|
|
||||||
* MDB2_AUTOQUERY_DELETE
|
|
||||||
* MDB2_AUTOQUERY_SELECT
|
|
||||||
* @param string (in case of update and delete queries, this string will be put after the sql WHERE statement)
|
|
||||||
*
|
|
||||||
* @return string sql query for prepare()
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function buildManipSQL($table, $table_fields, $mode, $where = false)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($db->options['quote_identifier']) {
|
|
||||||
$table = $db->quoteIdentifier($table);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($table_fields) && $db->options['quote_identifier']) {
|
|
||||||
foreach ($table_fields as $key => $field) {
|
|
||||||
$table_fields[$key] = $db->quoteIdentifier($field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((false !== $where) && (null !== $where)) {
|
|
||||||
if (is_array($where)) {
|
|
||||||
$where = implode(' AND ', $where);
|
|
||||||
}
|
|
||||||
$where = ' WHERE '.$where;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($mode) {
|
|
||||||
case MDB2_AUTOQUERY_INSERT:
|
|
||||||
if (empty($table_fields)) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
|
|
||||||
'Insert requires table fields', __FUNCTION__);
|
|
||||||
}
|
|
||||||
$cols = implode(', ', $table_fields);
|
|
||||||
$values = '?'.str_repeat(', ?', (count($table_fields) - 1));
|
|
||||||
return 'INSERT INTO '.$table.' ('.$cols.') VALUES ('.$values.')';
|
|
||||||
break;
|
|
||||||
case MDB2_AUTOQUERY_UPDATE:
|
|
||||||
if (empty($table_fields)) {
|
|
||||||
return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
|
|
||||||
'Update requires table fields', __FUNCTION__);
|
|
||||||
}
|
|
||||||
$set = implode(' = ?, ', $table_fields).' = ?';
|
|
||||||
$sql = 'UPDATE '.$table.' SET '.$set.$where;
|
|
||||||
return $sql;
|
|
||||||
break;
|
|
||||||
case MDB2_AUTOQUERY_DELETE:
|
|
||||||
$sql = 'DELETE FROM '.$table.$where;
|
|
||||||
return $sql;
|
|
||||||
break;
|
|
||||||
case MDB2_AUTOQUERY_SELECT:
|
|
||||||
$cols = !empty($table_fields) ? implode(', ', $table_fields) : '*';
|
|
||||||
$sql = 'SELECT '.$cols.' FROM '.$table.$where;
|
|
||||||
return $sql;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return $db->raiseError(MDB2_ERROR_SYNTAX, null, null,
|
|
||||||
'Non existant mode', __FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ limitQuery()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a limited query
|
|
||||||
*
|
|
||||||
* @param string query
|
|
||||||
* @param array that contains the types of the columns in the result set
|
|
||||||
* @param integer the numbers of rows to fetch
|
|
||||||
* @param integer the row to start to fetching
|
|
||||||
* @param string which specifies which result class to use
|
|
||||||
* @param mixed string which specifies which class to wrap results in
|
|
||||||
*
|
|
||||||
* @return MDB2_Result|MDB2_Error result set on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function limitQuery($query, $types, $limit, $offset = 0, $result_class = true,
|
|
||||||
$result_wrap_class = false)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $db->setLimit($limit, $offset);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
return $db->query($query, $types, $result_class, $result_wrap_class);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ execParam()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute a parameterized DML statement.
|
|
||||||
*
|
|
||||||
* @param string the SQL query
|
|
||||||
* @param array if supplied, prepare/execute will be used
|
|
||||||
* with this array as execute parameters
|
|
||||||
* @param array that contains the types of the values defined in $params
|
|
||||||
*
|
|
||||||
* @return int|MDB2_Error affected rows on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function execParam($query, $params = array(), $param_types = null)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
settype($params, 'array');
|
|
||||||
if (empty($params)) {
|
|
||||||
return $db->exec($query);
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt = $db->prepare($query, $param_types, MDB2_PREPARE_MANIP);
|
|
||||||
if (PEAR::isError($stmt)) {
|
|
||||||
return $stmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $stmt->execute($params);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt->free();
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getOne()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the first column of the first row of data returned from a query.
|
|
||||||
* Takes care of doing the query and freeing the results when finished.
|
|
||||||
*
|
|
||||||
* @param string the SQL query
|
|
||||||
* @param string that contains the type of the column in the result set
|
|
||||||
* @param array if supplied, prepare/execute will be used
|
|
||||||
* with this array as execute parameters
|
|
||||||
* @param array that contains the types of the values defined in $params
|
|
||||||
* @param int|string which column to return
|
|
||||||
*
|
|
||||||
* @return scalar|MDB2_Error data on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getOne($query, $type = null, $params = array(),
|
|
||||||
$param_types = null, $colnum = 0)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
settype($params, 'array');
|
|
||||||
settype($type, 'array');
|
|
||||||
if (empty($params)) {
|
|
||||||
return $db->queryOne($query, $type, $colnum);
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt = $db->prepare($query, $param_types, $type);
|
|
||||||
if (PEAR::isError($stmt)) {
|
|
||||||
return $stmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $stmt->execute($params);
|
|
||||||
if (!MDB2::isResultCommon($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
$one = $result->fetchOne($colnum);
|
|
||||||
$stmt->free();
|
|
||||||
$result->free();
|
|
||||||
return $one;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getRow()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the first row of data returned from a query. Takes care
|
|
||||||
* of doing the query and freeing the results when finished.
|
|
||||||
*
|
|
||||||
* @param string the SQL query
|
|
||||||
* @param array that contains the types of the columns in the result set
|
|
||||||
* @param array if supplied, prepare/execute will be used
|
|
||||||
* with this array as execute parameters
|
|
||||||
* @param array that contains the types of the values defined in $params
|
|
||||||
* @param int the fetch mode to use
|
|
||||||
*
|
|
||||||
* @return array|MDB2_Error data on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getRow($query, $types = null, $params = array(),
|
|
||||||
$param_types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
settype($params, 'array');
|
|
||||||
if (empty($params)) {
|
|
||||||
return $db->queryRow($query, $types, $fetchmode);
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt = $db->prepare($query, $param_types, $types);
|
|
||||||
if (PEAR::isError($stmt)) {
|
|
||||||
return $stmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $stmt->execute($params);
|
|
||||||
if (!MDB2::isResultCommon($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
$row = $result->fetchRow($fetchmode);
|
|
||||||
$stmt->free();
|
|
||||||
$result->free();
|
|
||||||
return $row;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getCol()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch a single column from a result set and return it as an
|
|
||||||
* indexed array.
|
|
||||||
*
|
|
||||||
* @param string the SQL query
|
|
||||||
* @param string that contains the type of the column in the result set
|
|
||||||
* @param array if supplied, prepare/execute will be used
|
|
||||||
* with this array as execute parameters
|
|
||||||
* @param array that contains the types of the values defined in $params
|
|
||||||
* @param int|string which column to return
|
|
||||||
*
|
|
||||||
* @return array|MDB2_Error data on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getCol($query, $type = null, $params = array(),
|
|
||||||
$param_types = null, $colnum = 0)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
settype($params, 'array');
|
|
||||||
settype($type, 'array');
|
|
||||||
if (empty($params)) {
|
|
||||||
return $db->queryCol($query, $type, $colnum);
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt = $db->prepare($query, $param_types, $type);
|
|
||||||
if (PEAR::isError($stmt)) {
|
|
||||||
return $stmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $stmt->execute($params);
|
|
||||||
if (!MDB2::isResultCommon($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
$col = $result->fetchCol($colnum);
|
|
||||||
$stmt->free();
|
|
||||||
$result->free();
|
|
||||||
return $col;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getAll()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch all the rows returned from a query.
|
|
||||||
*
|
|
||||||
* @param string the SQL query
|
|
||||||
* @param array that contains the types of the columns in the result set
|
|
||||||
* @param array if supplied, prepare/execute will be used
|
|
||||||
* with this array as execute parameters
|
|
||||||
* @param array that contains the types of the values defined in $params
|
|
||||||
* @param int the fetch mode to use
|
|
||||||
* @param bool if set to true, the $all will have the first
|
|
||||||
* column as its first dimension
|
|
||||||
* @param bool $force_array used only when the query returns exactly
|
|
||||||
* two columns. If true, the values of the returned array will be
|
|
||||||
* one-element arrays instead of scalars.
|
|
||||||
* @param bool $group if true, the values of the returned array is
|
|
||||||
* wrapped in another array. If the same key value (in the first
|
|
||||||
* column) repeats itself, the values will be appended to this array
|
|
||||||
* instead of overwriting the existing values.
|
|
||||||
*
|
|
||||||
* @return array|MDB2_Error data on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getAll($query, $types = null, $params = array(),
|
|
||||||
$param_types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT,
|
|
||||||
$rekey = false, $force_array = false, $group = false)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
settype($params, 'array');
|
|
||||||
if (empty($params)) {
|
|
||||||
return $db->queryAll($query, $types, $fetchmode, $rekey, $force_array, $group);
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt = $db->prepare($query, $param_types, $types);
|
|
||||||
if (PEAR::isError($stmt)) {
|
|
||||||
return $stmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $stmt->execute($params);
|
|
||||||
if (!MDB2::isResultCommon($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
$all = $result->fetchAll($fetchmode, $rekey, $force_array, $group);
|
|
||||||
$stmt->free();
|
|
||||||
$result->free();
|
|
||||||
return $all;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getAssoc()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the entire result set of a query and return it as an
|
|
||||||
* associative array using the first column as the key.
|
|
||||||
*
|
|
||||||
* If the result set contains more than two columns, the value
|
|
||||||
* will be an array of the values from column 2-n. If the result
|
|
||||||
* set contains only two columns, the returned value will be a
|
|
||||||
* scalar with the value of the second column (unless forced to an
|
|
||||||
* array with the $force_array parameter). A MDB2 error code is
|
|
||||||
* returned on errors. If the result set contains fewer than two
|
|
||||||
* columns, a MDB2_ERROR_TRUNCATED error is returned.
|
|
||||||
*
|
|
||||||
* For example, if the table 'mytable' contains:
|
|
||||||
* <pre>
|
|
||||||
* ID TEXT DATE
|
|
||||||
* --------------------------------
|
|
||||||
* 1 'one' 944679408
|
|
||||||
* 2 'two' 944679408
|
|
||||||
* 3 'three' 944679408
|
|
||||||
* </pre>
|
|
||||||
* Then the call getAssoc('SELECT id,text FROM mytable') returns:
|
|
||||||
* <pre>
|
|
||||||
* array(
|
|
||||||
* '1' => 'one',
|
|
||||||
* '2' => 'two',
|
|
||||||
* '3' => 'three',
|
|
||||||
* )
|
|
||||||
* </pre>
|
|
||||||
* ...while the call getAssoc('SELECT id,text,date FROM mytable') returns:
|
|
||||||
* <pre>
|
|
||||||
* array(
|
|
||||||
* '1' => array('one', '944679408'),
|
|
||||||
* '2' => array('two', '944679408'),
|
|
||||||
* '3' => array('three', '944679408')
|
|
||||||
* )
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* If the more than one row occurs with the same value in the
|
|
||||||
* first column, the last row overwrites all previous ones by
|
|
||||||
* default. Use the $group parameter if you don't want to
|
|
||||||
* overwrite like this. Example:
|
|
||||||
* <pre>
|
|
||||||
* getAssoc('SELECT category,id,name FROM mytable', null, null
|
|
||||||
* MDB2_FETCHMODE_ASSOC, false, true) returns:
|
|
||||||
* array(
|
|
||||||
* '1' => array(array('id' => '4', 'name' => 'number four'),
|
|
||||||
* array('id' => '6', 'name' => 'number six')
|
|
||||||
* ),
|
|
||||||
* '9' => array(array('id' => '4', 'name' => 'number four'),
|
|
||||||
* array('id' => '6', 'name' => 'number six')
|
|
||||||
* )
|
|
||||||
* )
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* Keep in mind that database functions in PHP usually return string
|
|
||||||
* values for results regardless of the database's internal type.
|
|
||||||
*
|
|
||||||
* @param string the SQL query
|
|
||||||
* @param array that contains the types of the columns in the result set
|
|
||||||
* @param array if supplied, prepare/execute will be used
|
|
||||||
* with this array as execute parameters
|
|
||||||
* @param array that contains the types of the values defined in $params
|
|
||||||
* @param bool $force_array used only when the query returns
|
|
||||||
* exactly two columns. If TRUE, the values of the returned array
|
|
||||||
* will be one-element arrays instead of scalars.
|
|
||||||
* @param bool $group if TRUE, the values of the returned array
|
|
||||||
* is wrapped in another array. If the same key value (in the first
|
|
||||||
* column) repeats itself, the values will be appended to this array
|
|
||||||
* instead of overwriting the existing values.
|
|
||||||
*
|
|
||||||
* @return array|MDB2_Error data on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getAssoc($query, $types = null, $params = array(), $param_types = null,
|
|
||||||
$fetchmode = MDB2_FETCHMODE_DEFAULT, $force_array = false, $group = false)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
settype($params, 'array');
|
|
||||||
if (empty($params)) {
|
|
||||||
return $db->queryAll($query, $types, $fetchmode, true, $force_array, $group);
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt = $db->prepare($query, $param_types, $types);
|
|
||||||
if (PEAR::isError($stmt)) {
|
|
||||||
return $stmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $stmt->execute($params);
|
|
||||||
if (!MDB2::isResultCommon($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
$all = $result->fetchAll($fetchmode, true, $force_array, $group);
|
|
||||||
$stmt->free();
|
|
||||||
$result->free();
|
|
||||||
return $all;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ executeMultiple()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function does several execute() calls on the same statement handle.
|
|
||||||
* $params must be an array indexed numerically from 0, one execute call is
|
|
||||||
* done for every 'row' in the array.
|
|
||||||
*
|
|
||||||
* If an error occurs during execute(), executeMultiple() does not execute
|
|
||||||
* the unfinished rows, but rather returns that error.
|
|
||||||
*
|
|
||||||
* @param resource query handle from prepare()
|
|
||||||
* @param array numeric array containing the data to insert into the query
|
|
||||||
*
|
|
||||||
* @return bool|MDB2_Error true on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
* @see prepare(), execute()
|
|
||||||
*/
|
|
||||||
function executeMultiple($stmt, $params = null)
|
|
||||||
{
|
|
||||||
if (MDB2::isError($stmt)) {
|
|
||||||
return $stmt;
|
|
||||||
}
|
|
||||||
for ($i = 0, $j = count($params); $i < $j; $i++) {
|
|
||||||
$result = $stmt->execute($params[$i]);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getBeforeID()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the next free id of a sequence if the RDBMS
|
|
||||||
* does not support auto increment
|
|
||||||
*
|
|
||||||
* @param string name of the table into which a new row was inserted
|
|
||||||
* @param string name of the field into which a new row was inserted
|
|
||||||
* @param bool when true the sequence is automatic created, if it not exists
|
|
||||||
* @param bool if the returned value should be quoted
|
|
||||||
*
|
|
||||||
* @return int|MDB2_Error id on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getBeforeID($table, $field = null, $ondemand = true, $quote = true)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($db->supports('auto_increment') !== true) {
|
|
||||||
$seq = $table.(empty($field) ? '' : '_'.$field);
|
|
||||||
$id = $db->nextID($seq, $ondemand);
|
|
||||||
if (!$quote || PEAR::isError($id)) {
|
|
||||||
return $id;
|
|
||||||
}
|
|
||||||
return $db->quote($id, 'integer');
|
|
||||||
} elseif (!$quote) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return 'NULL';
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getAfterID()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the autoincrement ID if supported or $id
|
|
||||||
*
|
|
||||||
* @param mixed value as returned by getBeforeId()
|
|
||||||
* @param string name of the table into which a new row was inserted
|
|
||||||
* @param string name of the field into which a new row was inserted
|
|
||||||
*
|
|
||||||
* @return int|MDB2_Error id on success, a MDB2 error on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getAfterID($id, $table, $field = null)
|
|
||||||
{
|
|
||||||
$db = $this->getDBInstance();
|
|
||||||
if (PEAR::isError($db)) {
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($db->supports('auto_increment') !== true) {
|
|
||||||
return $id;
|
|
||||||
}
|
|
||||||
return $db->lastInsertID($table, $field);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
}
|
|
||||||
?>
|
|
|
@ -1,262 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP version 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Lukas Smith <smith@pooteeweet.org> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PHP5 Iterator
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
class MDB2_Iterator implements Iterator
|
|
||||||
{
|
|
||||||
protected $fetchmode;
|
|
||||||
/**
|
|
||||||
* @var MDB2_Result_Common
|
|
||||||
*/
|
|
||||||
protected $result;
|
|
||||||
protected $row;
|
|
||||||
|
|
||||||
// {{{ constructor
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
public function __construct(MDB2_Result_Common $result, $fetchmode = MDB2_FETCHMODE_DEFAULT)
|
|
||||||
{
|
|
||||||
$this->result = $result;
|
|
||||||
$this->fetchmode = $fetchmode;
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ seek()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Seek forward to a specific row in a result set
|
|
||||||
*
|
|
||||||
* @param int number of the row where the data can be found
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function seek($rownum)
|
|
||||||
{
|
|
||||||
$this->row = null;
|
|
||||||
if ($this->result) {
|
|
||||||
$this->result->seek($rownum);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ next()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch next row of data
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function next()
|
|
||||||
{
|
|
||||||
$this->row = null;
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ current()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return a row of data
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function current()
|
|
||||||
{
|
|
||||||
if (null === $this->row) {
|
|
||||||
$row = $this->result->fetchRow($this->fetchmode);
|
|
||||||
if (PEAR::isError($row)) {
|
|
||||||
$row = false;
|
|
||||||
}
|
|
||||||
$this->row = $row;
|
|
||||||
}
|
|
||||||
return $this->row;
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ valid()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the end of the result set has been reached
|
|
||||||
*
|
|
||||||
* @return bool true/false, false is also returned on failure
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function valid()
|
|
||||||
{
|
|
||||||
return (bool)$this->current();
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ free()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free the internal resources associated with result.
|
|
||||||
*
|
|
||||||
* @return bool|MDB2_Error true on success, false|MDB2_Error if result is invalid
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function free()
|
|
||||||
{
|
|
||||||
if ($this->result) {
|
|
||||||
return $this->result->free();
|
|
||||||
}
|
|
||||||
$this->result = false;
|
|
||||||
$this->row = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ key()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the row number
|
|
||||||
*
|
|
||||||
* @return int|bool|MDB2_Error true on success, false|MDB2_Error if result is invalid
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function key()
|
|
||||||
{
|
|
||||||
if ($this->result) {
|
|
||||||
return $this->result->rowCount();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ rewind()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Seek to the first row in a result set
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function rewind()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ destructor
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor
|
|
||||||
*/
|
|
||||||
public function __destruct()
|
|
||||||
{
|
|
||||||
$this->free();
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PHP5 buffered Iterator
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
class MDB2_BufferedIterator extends MDB2_Iterator implements SeekableIterator
|
|
||||||
{
|
|
||||||
// {{{ valid()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the end of the result set has been reached
|
|
||||||
*
|
|
||||||
* @return bool|MDB2_Error true on success, false|MDB2_Error if result is invalid
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function valid()
|
|
||||||
{
|
|
||||||
if ($this->result) {
|
|
||||||
return $this->result->valid();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{count()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of rows in a result object
|
|
||||||
*
|
|
||||||
* @return int|MDB2_Error number of rows, false|MDB2_Error if result is invalid
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function count()
|
|
||||||
{
|
|
||||||
if ($this->result) {
|
|
||||||
return $this->result->numRows();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ rewind()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Seek to the first row in a result set
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function rewind()
|
|
||||||
{
|
|
||||||
$this->seek(0);
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
|
@ -1,264 +0,0 @@
|
||||||
<?php
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | PHP version 5 |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
|
|
||||||
// | Stig. S. Bakken, Lukas Smith |
|
|
||||||
// | All rights reserved. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
||||||
// | API as well as database abstraction for PHP applications. |
|
|
||||||
// | This LICENSE is in the BSD license style. |
|
|
||||||
// | |
|
|
||||||
// | Redistribution and use in source and binary forms, with or without |
|
|
||||||
// | modification, are permitted provided that the following conditions |
|
|
||||||
// | are met: |
|
|
||||||
// | |
|
|
||||||
// | Redistributions of source code must retain the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer. |
|
|
||||||
// | |
|
|
||||||
// | Redistributions in binary form must reproduce the above copyright |
|
|
||||||
// | notice, this list of conditions and the following disclaimer in the |
|
|
||||||
// | documentation and/or other materials provided with the distribution. |
|
|
||||||
// | |
|
|
||||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
||||||
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
||||||
// | or promote products derived from this software without specific prior|
|
|
||||||
// | written permission. |
|
|
||||||
// | |
|
|
||||||
// | 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 |
|
|
||||||
// | REGENTS 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. |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
// | Author: Lukas Smith <smith@pooteeweet.org> |
|
|
||||||
// +----------------------------------------------------------------------+
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once 'MDB2.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MDB2_LOB: user land stream wrapper implementation for LOB support
|
|
||||||
*
|
|
||||||
* @package MDB2
|
|
||||||
* @category Database
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
*/
|
|
||||||
class MDB2_LOB
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* contains the key to the global MDB2 instance array of the associated
|
|
||||||
* MDB2 instance
|
|
||||||
*
|
|
||||||
* @var integer
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
var $db_index;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* contains the key to the global MDB2_LOB instance array of the associated
|
|
||||||
* MDB2_LOB instance
|
|
||||||
*
|
|
||||||
* @var integer
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
var $lob_index;
|
|
||||||
|
|
||||||
// {{{ stream_open()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* open stream
|
|
||||||
*
|
|
||||||
* @param string specifies the URL that was passed to fopen()
|
|
||||||
* @param string the mode used to open the file
|
|
||||||
* @param int holds additional flags set by the streams API
|
|
||||||
* @param string not used
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function stream_open($path, $mode, $options, &$opened_path)
|
|
||||||
{
|
|
||||||
if (!preg_match('/^rb?\+?$/', $mode)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$url = parse_url($path);
|
|
||||||
if (empty($url['host'])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$this->db_index = (int)$url['host'];
|
|
||||||
if (!isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$db =& $GLOBALS['_MDB2_databases'][$this->db_index];
|
|
||||||
$this->lob_index = (int)$url['user'];
|
|
||||||
if (!isset($db->datatype->lobs[$this->lob_index])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ stream_read()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* read stream
|
|
||||||
*
|
|
||||||
* @param int number of bytes to read
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function stream_read($count)
|
|
||||||
{
|
|
||||||
if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
|
|
||||||
$db =& $GLOBALS['_MDB2_databases'][$this->db_index];
|
|
||||||
$db->datatype->_retrieveLOB($db->datatype->lobs[$this->lob_index]);
|
|
||||||
|
|
||||||
$data = $db->datatype->_readLOB($db->datatype->lobs[$this->lob_index], $count);
|
|
||||||
$length = strlen($data);
|
|
||||||
if ($length == 0) {
|
|
||||||
$db->datatype->lobs[$this->lob_index]['endOfLOB'] = true;
|
|
||||||
}
|
|
||||||
$db->datatype->lobs[$this->lob_index]['position'] += $length;
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ stream_write()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* write stream, note implemented
|
|
||||||
*
|
|
||||||
* @param string data
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function stream_write($data)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ stream_tell()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return the current position
|
|
||||||
*
|
|
||||||
* @return int current position
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function stream_tell()
|
|
||||||
{
|
|
||||||
if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
|
|
||||||
$db =& $GLOBALS['_MDB2_databases'][$this->db_index];
|
|
||||||
return $db->datatype->lobs[$this->lob_index]['position'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ stream_eof()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if stream reaches EOF
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function stream_eof()
|
|
||||||
{
|
|
||||||
if (!isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$db =& $GLOBALS['_MDB2_databases'][$this->db_index];
|
|
||||||
$result = $db->datatype->_endOfLOB($db->datatype->lobs[$this->lob_index]);
|
|
||||||
if (version_compare(phpversion(), "5.0", ">=")
|
|
||||||
&& version_compare(phpversion(), "5.1", "<")
|
|
||||||
) {
|
|
||||||
return !$result;
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ stream_seek()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Seek stream, not implemented
|
|
||||||
*
|
|
||||||
* @param int offset
|
|
||||||
* @param int whence
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function stream_seek($offset, $whence)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ stream_stat()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return information about stream
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function stream_stat()
|
|
||||||
{
|
|
||||||
if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
|
|
||||||
$db =& $GLOBALS['_MDB2_databases'][$this->db_index];
|
|
||||||
return array(
|
|
||||||
'db_index' => $this->db_index,
|
|
||||||
'lob_index' => $this->lob_index,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ stream_close()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* close stream
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function stream_close()
|
|
||||||
{
|
|
||||||
if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
|
|
||||||
$db =& $GLOBALS['_MDB2_databases'][$this->db_index];
|
|
||||||
if (isset($db->datatype->lobs[$this->lob_index])) {
|
|
||||||
$db->datatype->_destroyLOB($db->datatype->lobs[$this->lob_index]);
|
|
||||||
unset($db->datatype->lobs[$this->lob_index]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
}
|
|
||||||
|
|
||||||
// register streams wrapper
|
|
||||||
if (!stream_wrapper_register("MDB2LOB", "MDB2_LOB")) {
|
|
||||||
MDB2::raiseError();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,876 +0,0 @@
|
||||||
<?php /* vim: se et ts=4 sw=4 sts=4 fdm=marker tw=80: */
|
|
||||||
/**
|
|
||||||
* Copyright (c) 1998-2010 Manuel Lemos, Tomas V.V.Cox,
|
|
||||||
* Stig. S. Bakken, Lukas Smith, Igor Feghali
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* MDB2_Schema enables users to maintain RDBMS independant schema files
|
|
||||||
* in XML that can be used to manipulate both data and database schemas
|
|
||||||
* This LICENSE is in the BSD license style.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,
|
|
||||||
* Lukas Smith, Igor Feghali nor the names of his contributors may be
|
|
||||||
* used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* REGENTS 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.
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* @category Database
|
|
||||||
* @package MDB2_Schema
|
|
||||||
* @author Christian Dickmann <dickmann@php.net>
|
|
||||||
* @author Igor Feghali <ifeghali@php.net>
|
|
||||||
* @license BSD http://www.opensource.org/licenses/bsd-license.php
|
|
||||||
* @version SVN: $Id$
|
|
||||||
* @link http://pear.php.net/packages/MDB2_Schema
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once 'XML/Parser.php';
|
|
||||||
require_once 'MDB2/Schema/Validate.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses an XML schema file
|
|
||||||
*
|
|
||||||
* @category Database
|
|
||||||
* @package MDB2_Schema
|
|
||||||
* @author Christian Dickmann <dickmann@php.net>
|
|
||||||
* @license BSD http://www.opensource.org/licenses/bsd-license.php
|
|
||||||
* @link http://pear.php.net/packages/MDB2_Schema
|
|
||||||
*/
|
|
||||||
class MDB2_Schema_Parser extends XML_Parser
|
|
||||||
{
|
|
||||||
var $database_definition = array();
|
|
||||||
|
|
||||||
var $elements = array();
|
|
||||||
|
|
||||||
var $element = '';
|
|
||||||
|
|
||||||
var $count = 0;
|
|
||||||
|
|
||||||
var $table = array();
|
|
||||||
|
|
||||||
var $table_name = '';
|
|
||||||
|
|
||||||
var $field = array();
|
|
||||||
|
|
||||||
var $field_name = '';
|
|
||||||
|
|
||||||
var $init = array();
|
|
||||||
|
|
||||||
var $init_function = array();
|
|
||||||
|
|
||||||
var $init_expression = array();
|
|
||||||
|
|
||||||
var $init_field = array();
|
|
||||||
|
|
||||||
var $index = array();
|
|
||||||
|
|
||||||
var $index_name = '';
|
|
||||||
|
|
||||||
var $constraint = array();
|
|
||||||
|
|
||||||
var $constraint_name = '';
|
|
||||||
|
|
||||||
var $var_mode = false;
|
|
||||||
|
|
||||||
var $variables = array();
|
|
||||||
|
|
||||||
var $sequence = array();
|
|
||||||
|
|
||||||
var $sequence_name = '';
|
|
||||||
|
|
||||||
var $error;
|
|
||||||
|
|
||||||
var $structure = false;
|
|
||||||
|
|
||||||
var $val;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PHP 5 constructor
|
|
||||||
*
|
|
||||||
* @param array $variables mixed array with user defined schema
|
|
||||||
* variables
|
|
||||||
* @param bool $fail_on_invalid_names array with reserved words per RDBMS
|
|
||||||
* @param array $structure multi dimensional array with
|
|
||||||
* database schema and data
|
|
||||||
* @param array $valid_types information of all valid fields
|
|
||||||
* types
|
|
||||||
* @param bool $force_defaults if true sets a default value to
|
|
||||||
* field when not explicit
|
|
||||||
* @param int $max_identifiers_length maximum allowed size for entities
|
|
||||||
* name
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function __construct($variables, $fail_on_invalid_names = true,
|
|
||||||
$structure = false, $valid_types = array(), $force_defaults = true,
|
|
||||||
$max_identifiers_length = null
|
|
||||||
) {
|
|
||||||
// force ISO-8859-1 due to different defaults for PHP4 and PHP5
|
|
||||||
// todo: this probably needs to be investigated some more andcleaned up
|
|
||||||
parent::__construct('ISO-8859-1');
|
|
||||||
|
|
||||||
$this->variables = $variables;
|
|
||||||
$this->structure = $structure;
|
|
||||||
$this->val = new MDB2_Schema_Validate(
|
|
||||||
$fail_on_invalid_names,
|
|
||||||
$valid_types,
|
|
||||||
$force_defaults,
|
|
||||||
$max_identifiers_length
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Triggered when reading a XML open tag <element>
|
|
||||||
*
|
|
||||||
* @param resource $xp xml parser resource
|
|
||||||
* @param string $element element name
|
|
||||||
* @param array $attribs attributes
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
* @access private
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function startHandler($xp, $element, &$attribs)
|
|
||||||
{
|
|
||||||
if (strtolower($element) == 'variable') {
|
|
||||||
$this->var_mode = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->elements[$this->count++] = strtolower($element);
|
|
||||||
|
|
||||||
$this->element = implode('-', $this->elements);
|
|
||||||
|
|
||||||
switch ($this->element) {
|
|
||||||
/* Initialization */
|
|
||||||
case 'database-table-initialization':
|
|
||||||
$this->table['initialization'] = array();
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Insert */
|
|
||||||
/* insert: field+ */
|
|
||||||
case 'database-table-initialization-insert':
|
|
||||||
$this->init = array('type' => 'insert', 'data' => array('field' => array()));
|
|
||||||
break;
|
|
||||||
/* insert-select: field+, table, where? */
|
|
||||||
case 'database-table-initialization-insert-select':
|
|
||||||
$this->init['data']['table'] = '';
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Update */
|
|
||||||
/* update: field+, where? */
|
|
||||||
case 'database-table-initialization-update':
|
|
||||||
$this->init = array('type' => 'update', 'data' => array('field' => array()));
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Delete */
|
|
||||||
/* delete: where */
|
|
||||||
case 'database-table-initialization-delete':
|
|
||||||
$this->init = array('type' => 'delete', 'data' => array('where' => array()));
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Insert and Update */
|
|
||||||
case 'database-table-initialization-insert-field':
|
|
||||||
case 'database-table-initialization-insert-select-field':
|
|
||||||
case 'database-table-initialization-update-field':
|
|
||||||
$this->init_field = array('name' => '', 'group' => array());
|
|
||||||
break;
|
|
||||||
case 'database-table-initialization-insert-field-value':
|
|
||||||
case 'database-table-initialization-insert-select-field-value':
|
|
||||||
case 'database-table-initialization-update-field-value':
|
|
||||||
/* if value tag is empty cdataHandler is not called so we must force value element creation here */
|
|
||||||
$this->init_field['group'] = array('type' => 'value', 'data' => '');
|
|
||||||
break;
|
|
||||||
case 'database-table-initialization-insert-field-null':
|
|
||||||
case 'database-table-initialization-insert-select-field-null':
|
|
||||||
case 'database-table-initialization-update-field-null':
|
|
||||||
$this->init_field['group'] = array('type' => 'null');
|
|
||||||
break;
|
|
||||||
case 'database-table-initialization-insert-field-function':
|
|
||||||
case 'database-table-initialization-insert-select-field-function':
|
|
||||||
case 'database-table-initialization-update-field-function':
|
|
||||||
$this->init_function = array('name' => '');
|
|
||||||
break;
|
|
||||||
case 'database-table-initialization-insert-field-expression':
|
|
||||||
case 'database-table-initialization-insert-select-field-expression':
|
|
||||||
case 'database-table-initialization-update-field-expression':
|
|
||||||
$this->init_expression = array();
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* All */
|
|
||||||
case 'database-table-initialization-insert-select-where':
|
|
||||||
case 'database-table-initialization-update-where':
|
|
||||||
case 'database-table-initialization-delete-where':
|
|
||||||
$this->init['data']['where'] = array('type' => '', 'data' => array());
|
|
||||||
break;
|
|
||||||
case 'database-table-initialization-insert-select-where-expression':
|
|
||||||
case 'database-table-initialization-update-where-expression':
|
|
||||||
case 'database-table-initialization-delete-where-expression':
|
|
||||||
$this->init_expression = array();
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* One level simulation of expression-function recursion */
|
|
||||||
case 'database-table-initialization-insert-field-expression-function':
|
|
||||||
case 'database-table-initialization-insert-select-field-expression-function':
|
|
||||||
case 'database-table-initialization-insert-select-where-expression-function':
|
|
||||||
case 'database-table-initialization-update-field-expression-function':
|
|
||||||
case 'database-table-initialization-update-where-expression-function':
|
|
||||||
case 'database-table-initialization-delete-where-expression-function':
|
|
||||||
$this->init_function = array('name' => '');
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* One level simulation of function-expression recursion */
|
|
||||||
case 'database-table-initialization-insert-field-function-expression':
|
|
||||||
case 'database-table-initialization-insert-select-field-function-expression':
|
|
||||||
case 'database-table-initialization-insert-select-where-function-expression':
|
|
||||||
case 'database-table-initialization-update-field-function-expression':
|
|
||||||
case 'database-table-initialization-update-where-function-expression':
|
|
||||||
case 'database-table-initialization-delete-where-function-expression':
|
|
||||||
$this->init_expression = array();
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Definition */
|
|
||||||
case 'database':
|
|
||||||
$this->database_definition = array(
|
|
||||||
'name' => '',
|
|
||||||
'create' => '',
|
|
||||||
'overwrite' => '',
|
|
||||||
'charset' => '',
|
|
||||||
'description' => '',
|
|
||||||
'comments' => '',
|
|
||||||
'tables' => array(),
|
|
||||||
'sequences' => array()
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'database-table':
|
|
||||||
$this->table_name = '';
|
|
||||||
|
|
||||||
$this->table = array(
|
|
||||||
'was' => '',
|
|
||||||
'description' => '',
|
|
||||||
'comments' => '',
|
|
||||||
'fields' => array(),
|
|
||||||
'indexes' => array(),
|
|
||||||
'constraints' => array(),
|
|
||||||
'initialization' => array()
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-field':
|
|
||||||
case 'database-table-declaration-foreign-field':
|
|
||||||
case 'database-table-declaration-foreign-references-field':
|
|
||||||
$this->field_name = '';
|
|
||||||
|
|
||||||
$this->field = array();
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-index-field':
|
|
||||||
$this->field_name = '';
|
|
||||||
|
|
||||||
$this->field = array('sorting' => '', 'length' => '');
|
|
||||||
break;
|
|
||||||
/* force field attributes to be initialized when the tag is empty in the XML */
|
|
||||||
case 'database-table-declaration-field-was':
|
|
||||||
$this->field['was'] = '';
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-field-type':
|
|
||||||
$this->field['type'] = '';
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-field-fixed':
|
|
||||||
$this->field['fixed'] = '';
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-field-default':
|
|
||||||
$this->field['default'] = '';
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-field-notnull':
|
|
||||||
$this->field['notnull'] = '';
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-field-autoincrement':
|
|
||||||
$this->field['autoincrement'] = '';
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-field-unsigned':
|
|
||||||
$this->field['unsigned'] = '';
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-field-length':
|
|
||||||
$this->field['length'] = '';
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-field-description':
|
|
||||||
$this->field['description'] = '';
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-field-comments':
|
|
||||||
$this->field['comments'] = '';
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-index':
|
|
||||||
$this->index_name = '';
|
|
||||||
|
|
||||||
$this->index = array(
|
|
||||||
'was' => '',
|
|
||||||
'unique' =>'',
|
|
||||||
'primary' => '',
|
|
||||||
'fields' => array()
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-foreign':
|
|
||||||
$this->constraint_name = '';
|
|
||||||
|
|
||||||
$this->constraint = array(
|
|
||||||
'was' => '',
|
|
||||||
'match' => '',
|
|
||||||
'ondelete' => '',
|
|
||||||
'onupdate' => '',
|
|
||||||
'deferrable' => '',
|
|
||||||
'initiallydeferred' => '',
|
|
||||||
'foreign' => true,
|
|
||||||
'fields' => array(),
|
|
||||||
'references' => array('table' => '', 'fields' => array())
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'database-sequence':
|
|
||||||
$this->sequence_name = '';
|
|
||||||
|
|
||||||
$this->sequence = array(
|
|
||||||
'was' => '',
|
|
||||||
'start' => '',
|
|
||||||
'description' => '',
|
|
||||||
'comments' => '',
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Triggered when reading a XML close tag </element>
|
|
||||||
*
|
|
||||||
* @param resource $xp xml parser resource
|
|
||||||
* @param string $element element name
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
* @access private
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function endHandler($xp, $element)
|
|
||||||
{
|
|
||||||
if (strtolower($element) == 'variable') {
|
|
||||||
$this->var_mode = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($this->element) {
|
|
||||||
/* Initialization */
|
|
||||||
|
|
||||||
/* Insert */
|
|
||||||
case 'database-table-initialization-insert-select':
|
|
||||||
$this->init['data'] = array('select' => $this->init['data']);
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Insert and Delete */
|
|
||||||
case 'database-table-initialization-insert-field':
|
|
||||||
case 'database-table-initialization-insert-select-field':
|
|
||||||
case 'database-table-initialization-update-field':
|
|
||||||
$result = $this->val->validateDataField($this->table['fields'], $this->init['data']['field'], $this->init_field);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
$this->raiseError($result->getUserinfo(), 0, $xp, $result->getCode());
|
|
||||||
} else {
|
|
||||||
$this->init['data']['field'][] = $this->init_field;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'database-table-initialization-insert-field-function':
|
|
||||||
case 'database-table-initialization-insert-select-field-function':
|
|
||||||
case 'database-table-initialization-update-field-function':
|
|
||||||
$this->init_field['group'] = array('type' => 'function', 'data' => $this->init_function);
|
|
||||||
break;
|
|
||||||
case 'database-table-initialization-insert-field-expression':
|
|
||||||
case 'database-table-initialization-insert-select-field-expression':
|
|
||||||
case 'database-table-initialization-update-field-expression':
|
|
||||||
$this->init_field['group'] = array('type' => 'expression', 'data' => $this->init_expression);
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* All */
|
|
||||||
case 'database-table-initialization-insert-select-where-expression':
|
|
||||||
case 'database-table-initialization-update-where-expression':
|
|
||||||
case 'database-table-initialization-delete-where-expression':
|
|
||||||
$this->init['data']['where']['type'] = 'expression';
|
|
||||||
$this->init['data']['where']['data'] = $this->init_expression;
|
|
||||||
break;
|
|
||||||
case 'database-table-initialization-insert':
|
|
||||||
case 'database-table-initialization-delete':
|
|
||||||
case 'database-table-initialization-update':
|
|
||||||
$this->table['initialization'][] = $this->init;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* One level simulation of expression-function recursion */
|
|
||||||
case 'database-table-initialization-insert-field-expression-function':
|
|
||||||
case 'database-table-initialization-insert-select-field-expression-function':
|
|
||||||
case 'database-table-initialization-insert-select-where-expression-function':
|
|
||||||
case 'database-table-initialization-update-field-expression-function':
|
|
||||||
case 'database-table-initialization-update-where-expression-function':
|
|
||||||
case 'database-table-initialization-delete-where-expression-function':
|
|
||||||
$this->init_expression['operants'][] = array('type' => 'function', 'data' => $this->init_function);
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* One level simulation of function-expression recursion */
|
|
||||||
case 'database-table-initialization-insert-field-function-expression':
|
|
||||||
case 'database-table-initialization-insert-select-field-function-expression':
|
|
||||||
case 'database-table-initialization-insert-select-where-function-expression':
|
|
||||||
case 'database-table-initialization-update-field-function-expression':
|
|
||||||
case 'database-table-initialization-update-where-function-expression':
|
|
||||||
case 'database-table-initialization-delete-where-function-expression':
|
|
||||||
$this->init_function['arguments'][] = array('type' => 'expression', 'data' => $this->init_expression);
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Table definition */
|
|
||||||
case 'database-table':
|
|
||||||
$result = $this->val->validateTable($this->database_definition['tables'], $this->table, $this->table_name);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
$this->raiseError($result->getUserinfo(), 0, $xp, $result->getCode());
|
|
||||||
} else {
|
|
||||||
$this->database_definition['tables'][$this->table_name] = $this->table;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'database-table-name':
|
|
||||||
if (isset($this->structure['tables'][$this->table_name])) {
|
|
||||||
$this->table = $this->structure['tables'][$this->table_name];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Field declaration */
|
|
||||||
case 'database-table-declaration-field':
|
|
||||||
$result = $this->val->validateField($this->table['fields'], $this->field, $this->field_name);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
$this->raiseError($result->getUserinfo(), 0, $xp, $result->getCode());
|
|
||||||
} else {
|
|
||||||
$this->table['fields'][$this->field_name] = $this->field;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Index declaration */
|
|
||||||
case 'database-table-declaration-index':
|
|
||||||
$result = $this->val->validateIndex($this->table['indexes'], $this->index, $this->index_name);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
$this->raiseError($result->getUserinfo(), 0, $xp, $result->getCode());
|
|
||||||
} else {
|
|
||||||
$this->table['indexes'][$this->index_name] = $this->index;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-index-field':
|
|
||||||
$result = $this->val->validateIndexField($this->index['fields'], $this->field, $this->field_name);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
$this->raiseError($result->getUserinfo(), 0, $xp, $result->getCode());
|
|
||||||
} else {
|
|
||||||
$this->index['fields'][$this->field_name] = $this->field;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Foreign Key declaration */
|
|
||||||
case 'database-table-declaration-foreign':
|
|
||||||
$result = $this->val->validateConstraint($this->table['constraints'], $this->constraint, $this->constraint_name);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
$this->raiseError($result->getUserinfo(), 0, $xp, $result->getCode());
|
|
||||||
} else {
|
|
||||||
$this->table['constraints'][$this->constraint_name] = $this->constraint;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-foreign-field':
|
|
||||||
$result = $this->val->validateConstraintField($this->constraint['fields'], $this->field_name);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
$this->raiseError($result->getUserinfo(), 0, $xp, $result->getCode());
|
|
||||||
} else {
|
|
||||||
$this->constraint['fields'][$this->field_name] = '';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-foreign-references-field':
|
|
||||||
$result = $this->val->validateConstraintReferencedField($this->constraint['references']['fields'], $this->field_name);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
$this->raiseError($result->getUserinfo(), 0, $xp, $result->getCode());
|
|
||||||
} else {
|
|
||||||
$this->constraint['references']['fields'][$this->field_name] = '';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Sequence declaration */
|
|
||||||
case 'database-sequence':
|
|
||||||
$result = $this->val->validateSequence($this->database_definition['sequences'], $this->sequence, $this->sequence_name);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
$this->raiseError($result->getUserinfo(), 0, $xp, $result->getCode());
|
|
||||||
} else {
|
|
||||||
$this->database_definition['sequences'][$this->sequence_name] = $this->sequence;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* End of File */
|
|
||||||
case 'database':
|
|
||||||
$result = $this->val->validateDatabase($this->database_definition);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
$this->raiseError($result->getUserinfo(), 0, $xp, $result->getCode());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
unset($this->elements[--$this->count]);
|
|
||||||
$this->element = implode('-', $this->elements);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pushes a MDB2_Schema_Error into stack and returns it
|
|
||||||
*
|
|
||||||
* @param string $msg textual message
|
|
||||||
* @param int $xmlecode PHP's XML parser error code
|
|
||||||
* @param resource $xp xml parser resource
|
|
||||||
* @param int $ecode MDB2_Schema's error code
|
|
||||||
*
|
|
||||||
* @return object
|
|
||||||
* @access private
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
static function &raiseError($msg = null, $xmlecode = 0, $xp = null, $ecode = MDB2_SCHEMA_ERROR_PARSE, $userinfo = null,
|
|
||||||
$error_class = null,
|
|
||||||
$skipmsg = false)
|
|
||||||
{
|
|
||||||
if (is_null($this->error)) {
|
|
||||||
$error = '';
|
|
||||||
if (is_resource($msg)) {
|
|
||||||
$error .= 'Parser error: '.xml_error_string(xml_get_error_code($msg));
|
|
||||||
$xp = $msg;
|
|
||||||
} else {
|
|
||||||
$error .= 'Parser error: '.$msg;
|
|
||||||
if (!is_resource($xp)) {
|
|
||||||
$xp = $this->parser;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($error_string = xml_error_string($xmlecode)) {
|
|
||||||
$error .= ' - '.$error_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_resource($xp)) {
|
|
||||||
$byte = @xml_get_current_byte_index($xp);
|
|
||||||
$line = @xml_get_current_line_number($xp);
|
|
||||||
$column = @xml_get_current_column_number($xp);
|
|
||||||
$error .= " - Byte: $byte; Line: $line; Col: $column";
|
|
||||||
}
|
|
||||||
|
|
||||||
$error .= "\n";
|
|
||||||
|
|
||||||
$this->error = MDB2_Schema::raiseError($ecode, null, null, $error);
|
|
||||||
}
|
|
||||||
return $this->error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Triggered when reading data in a XML element (text between tags)
|
|
||||||
*
|
|
||||||
* @param resource $xp xml parser resource
|
|
||||||
* @param string $data text
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
* @access private
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function cdataHandler($xp, $data)
|
|
||||||
{
|
|
||||||
if ($this->var_mode == true) {
|
|
||||||
if (!isset($this->variables[$data])) {
|
|
||||||
$this->raiseError('variable "'.$data.'" not found', null, $xp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$data = $this->variables[$data];
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($this->element) {
|
|
||||||
/* Initialization */
|
|
||||||
|
|
||||||
/* Insert */
|
|
||||||
case 'database-table-initialization-insert-select-table':
|
|
||||||
$this->init['data']['table'] = $data;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Insert and Update */
|
|
||||||
case 'database-table-initialization-insert-field-name':
|
|
||||||
case 'database-table-initialization-insert-select-field-name':
|
|
||||||
case 'database-table-initialization-update-field-name':
|
|
||||||
$this->init_field['name'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-initialization-insert-field-value':
|
|
||||||
case 'database-table-initialization-insert-select-field-value':
|
|
||||||
case 'database-table-initialization-update-field-value':
|
|
||||||
$this->init_field['group']['data'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-initialization-insert-field-function-name':
|
|
||||||
case 'database-table-initialization-insert-select-field-function-name':
|
|
||||||
case 'database-table-initialization-update-field-function-name':
|
|
||||||
$this->init_function['name'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-initialization-insert-field-function-value':
|
|
||||||
case 'database-table-initialization-insert-select-field-function-value':
|
|
||||||
case 'database-table-initialization-update-field-function-value':
|
|
||||||
$this->init_function['arguments'][] = array('type' => 'value', 'data' => $data);
|
|
||||||
break;
|
|
||||||
case 'database-table-initialization-insert-field-function-column':
|
|
||||||
case 'database-table-initialization-insert-select-field-function-column':
|
|
||||||
case 'database-table-initialization-update-field-function-column':
|
|
||||||
$this->init_function['arguments'][] = array('type' => 'column', 'data' => $data);
|
|
||||||
break;
|
|
||||||
case 'database-table-initialization-insert-field-column':
|
|
||||||
case 'database-table-initialization-insert-select-field-column':
|
|
||||||
case 'database-table-initialization-update-field-column':
|
|
||||||
$this->init_field['group'] = array('type' => 'column', 'data' => $data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* All */
|
|
||||||
case 'database-table-initialization-insert-field-expression-operator':
|
|
||||||
case 'database-table-initialization-insert-select-field-expression-operator':
|
|
||||||
case 'database-table-initialization-insert-select-where-expression-operator':
|
|
||||||
case 'database-table-initialization-update-field-expression-operator':
|
|
||||||
case 'database-table-initialization-update-where-expression-operator':
|
|
||||||
case 'database-table-initialization-delete-where-expression-operator':
|
|
||||||
$this->init_expression['operator'] = $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-initialization-insert-field-expression-value':
|
|
||||||
case 'database-table-initialization-insert-select-field-expression-value':
|
|
||||||
case 'database-table-initialization-insert-select-where-expression-value':
|
|
||||||
case 'database-table-initialization-update-field-expression-value':
|
|
||||||
case 'database-table-initialization-update-where-expression-value':
|
|
||||||
case 'database-table-initialization-delete-where-expression-value':
|
|
||||||
$this->init_expression['operants'][] = array('type' => 'value', 'data' => $data);
|
|
||||||
break;
|
|
||||||
case 'database-table-initialization-insert-field-expression-column':
|
|
||||||
case 'database-table-initialization-insert-select-field-expression-column':
|
|
||||||
case 'database-table-initialization-insert-select-where-expression-column':
|
|
||||||
case 'database-table-initialization-update-field-expression-column':
|
|
||||||
case 'database-table-initialization-update-where-expression-column':
|
|
||||||
case 'database-table-initialization-delete-where-expression-column':
|
|
||||||
$this->init_expression['operants'][] = array('type' => 'column', 'data' => $data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'database-table-initialization-insert-field-function-function':
|
|
||||||
case 'database-table-initialization-insert-field-function-expression':
|
|
||||||
case 'database-table-initialization-insert-field-expression-expression':
|
|
||||||
case 'database-table-initialization-update-field-function-function':
|
|
||||||
case 'database-table-initialization-update-field-function-expression':
|
|
||||||
case 'database-table-initialization-update-field-expression-expression':
|
|
||||||
case 'database-table-initialization-update-where-expression-expression':
|
|
||||||
case 'database-table-initialization-delete-where-expression-expression':
|
|
||||||
/* Recursion to be implemented yet */
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* One level simulation of expression-function recursion */
|
|
||||||
case 'database-table-initialization-insert-field-expression-function-name':
|
|
||||||
case 'database-table-initialization-insert-select-field-expression-function-name':
|
|
||||||
case 'database-table-initialization-insert-select-where-expression-function-name':
|
|
||||||
case 'database-table-initialization-update-field-expression-function-name':
|
|
||||||
case 'database-table-initialization-update-where-expression-function-name':
|
|
||||||
case 'database-table-initialization-delete-where-expression-function-name':
|
|
||||||
$this->init_function['name'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-initialization-insert-field-expression-function-value':
|
|
||||||
case 'database-table-initialization-insert-select-field-expression-function-value':
|
|
||||||
case 'database-table-initialization-insert-select-where-expression-function-value':
|
|
||||||
case 'database-table-initialization-update-field-expression-function-value':
|
|
||||||
case 'database-table-initialization-update-where-expression-function-value':
|
|
||||||
case 'database-table-initialization-delete-where-expression-function-value':
|
|
||||||
$this->init_function['arguments'][] = array('type' => 'value', 'data' => $data);
|
|
||||||
break;
|
|
||||||
case 'database-table-initialization-insert-field-expression-function-column':
|
|
||||||
case 'database-table-initialization-insert-select-field-expression-function-column':
|
|
||||||
case 'database-table-initialization-insert-select-where-expression-function-column':
|
|
||||||
case 'database-table-initialization-update-field-expression-function-column':
|
|
||||||
case 'database-table-initialization-update-where-expression-function-column':
|
|
||||||
case 'database-table-initialization-delete-where-expression-function-column':
|
|
||||||
$this->init_function['arguments'][] = array('type' => 'column', 'data' => $data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* One level simulation of function-expression recursion */
|
|
||||||
case 'database-table-initialization-insert-field-function-expression-operator':
|
|
||||||
case 'database-table-initialization-insert-select-field-function-expression-operator':
|
|
||||||
case 'database-table-initialization-update-field-function-expression-operator':
|
|
||||||
$this->init_expression['operator'] = $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-initialization-insert-field-function-expression-value':
|
|
||||||
case 'database-table-initialization-insert-select-field-function-expression-value':
|
|
||||||
case 'database-table-initialization-update-field-function-expression-value':
|
|
||||||
$this->init_expression['operants'][] = array('type' => 'value', 'data' => $data);
|
|
||||||
break;
|
|
||||||
case 'database-table-initialization-insert-field-function-expression-column':
|
|
||||||
case 'database-table-initialization-insert-select-field-function-expression-column':
|
|
||||||
case 'database-table-initialization-update-field-function-expression-column':
|
|
||||||
$this->init_expression['operants'][] = array('type' => 'column', 'data' => $data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Database */
|
|
||||||
case 'database-name':
|
|
||||||
$this->database_definition['name'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-create':
|
|
||||||
$this->database_definition['create'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-overwrite':
|
|
||||||
$this->database_definition['overwrite'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-charset':
|
|
||||||
$this->database_definition['charset'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-description':
|
|
||||||
$this->database_definition['description'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-comments':
|
|
||||||
$this->database_definition['comments'] .= $data;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Table declaration */
|
|
||||||
case 'database-table-name':
|
|
||||||
$this->table_name .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-was':
|
|
||||||
$this->table['was'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-description':
|
|
||||||
$this->table['description'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-comments':
|
|
||||||
$this->table['comments'] .= $data;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Field declaration */
|
|
||||||
case 'database-table-declaration-field-name':
|
|
||||||
$this->field_name .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-field-was':
|
|
||||||
$this->field['was'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-field-type':
|
|
||||||
$this->field['type'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-field-fixed':
|
|
||||||
$this->field['fixed'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-field-default':
|
|
||||||
$this->field['default'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-field-notnull':
|
|
||||||
$this->field['notnull'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-field-autoincrement':
|
|
||||||
$this->field['autoincrement'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-field-unsigned':
|
|
||||||
$this->field['unsigned'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-field-length':
|
|
||||||
$this->field['length'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-field-description':
|
|
||||||
$this->field['description'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-field-comments':
|
|
||||||
$this->field['comments'] .= $data;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Index declaration */
|
|
||||||
case 'database-table-declaration-index-name':
|
|
||||||
$this->index_name .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-index-was':
|
|
||||||
$this->index['was'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-index-unique':
|
|
||||||
$this->index['unique'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-index-primary':
|
|
||||||
$this->index['primary'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-index-field-name':
|
|
||||||
$this->field_name .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-index-field-sorting':
|
|
||||||
$this->field['sorting'] .= $data;
|
|
||||||
break;
|
|
||||||
/* Add by Leoncx */
|
|
||||||
case 'database-table-declaration-index-field-length':
|
|
||||||
$this->field['length'] .= $data;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Foreign Key declaration */
|
|
||||||
case 'database-table-declaration-foreign-name':
|
|
||||||
$this->constraint_name .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-foreign-was':
|
|
||||||
$this->constraint['was'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-foreign-match':
|
|
||||||
$this->constraint['match'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-foreign-ondelete':
|
|
||||||
$this->constraint['ondelete'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-foreign-onupdate':
|
|
||||||
$this->constraint['onupdate'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-foreign-deferrable':
|
|
||||||
$this->constraint['deferrable'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-foreign-initiallydeferred':
|
|
||||||
$this->constraint['initiallydeferred'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-foreign-field':
|
|
||||||
$this->field_name .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-foreign-references-table':
|
|
||||||
$this->constraint['references']['table'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-table-declaration-foreign-references-field':
|
|
||||||
$this->field_name .= $data;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Sequence declaration */
|
|
||||||
case 'database-sequence-name':
|
|
||||||
$this->sequence_name .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-sequence-was':
|
|
||||||
$this->sequence['was'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-sequence-start':
|
|
||||||
$this->sequence['start'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-sequence-description':
|
|
||||||
$this->sequence['description'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-sequence-comments':
|
|
||||||
$this->sequence['comments'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-sequence-on':
|
|
||||||
$this->sequence['on'] = array('table' => '', 'field' => '');
|
|
||||||
break;
|
|
||||||
case 'database-sequence-on-table':
|
|
||||||
$this->sequence['on']['table'] .= $data;
|
|
||||||
break;
|
|
||||||
case 'database-sequence-on-field':
|
|
||||||
$this->sequence['on']['field'] .= $data;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,802 +0,0 @@
|
||||||
<?php /* vim: se et ts=4 sw=4 sts=4 fdm=marker tw=80: */
|
|
||||||
/**
|
|
||||||
* Copyright (c) 1998-2010 Manuel Lemos, Tomas V.V.Cox,
|
|
||||||
* Stig. S. Bakken, Lukas Smith, Igor Feghali
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* MDB2_Schema enables users to maintain RDBMS independant schema files
|
|
||||||
* in XML that can be used to manipulate both data and database schemas
|
|
||||||
* This LICENSE is in the BSD license style.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,
|
|
||||||
* Lukas Smith, Igor Feghali nor the names of his contributors may be
|
|
||||||
* used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* REGENTS 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.
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* @category Database
|
|
||||||
* @package MDB2_Schema
|
|
||||||
* @author Igor Feghali <ifeghali@php.net>
|
|
||||||
* @license BSD http://www.opensource.org/licenses/bsd-license.php
|
|
||||||
* @version SVN: $Id$
|
|
||||||
* @link http://pear.php.net/packages/MDB2_Schema
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once 'XML/Unserializer.php';
|
|
||||||
require_once 'MDB2/Schema/Validate.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses an XML schema file
|
|
||||||
*
|
|
||||||
* @category Database
|
|
||||||
* @package MDB2_Schema
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
* @author Igor Feghali <ifeghali@php.net>
|
|
||||||
* @license BSD http://www.opensource.org/licenses/bsd-license.php
|
|
||||||
* @link http://pear.php.net/packages/MDB2_Schema
|
|
||||||
*/
|
|
||||||
class MDB2_Schema_Parser2 extends XML_Unserializer
|
|
||||||
{
|
|
||||||
var $database_definition = array();
|
|
||||||
|
|
||||||
var $database_loaded = array();
|
|
||||||
|
|
||||||
var $variables = array();
|
|
||||||
|
|
||||||
var $error;
|
|
||||||
|
|
||||||
var $structure = false;
|
|
||||||
|
|
||||||
var $val;
|
|
||||||
|
|
||||||
var $options = array();
|
|
||||||
|
|
||||||
var $table = array();
|
|
||||||
|
|
||||||
var $table_name = '';
|
|
||||||
|
|
||||||
var $field = array();
|
|
||||||
|
|
||||||
var $field_name = '';
|
|
||||||
|
|
||||||
var $index = array();
|
|
||||||
|
|
||||||
var $index_name = '';
|
|
||||||
|
|
||||||
var $constraint = array();
|
|
||||||
|
|
||||||
var $constraint_name = '';
|
|
||||||
|
|
||||||
var $sequence = array();
|
|
||||||
|
|
||||||
var $sequence_name = '';
|
|
||||||
|
|
||||||
var $init = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PHP 5 constructor
|
|
||||||
*
|
|
||||||
* @param array $variables mixed array with user defined schema
|
|
||||||
* variables
|
|
||||||
* @param bool $fail_on_invalid_names array with reserved words per RDBMS
|
|
||||||
* @param array $structure multi dimensional array with
|
|
||||||
* database schema and data
|
|
||||||
* @param array $valid_types information of all valid fields
|
|
||||||
* types
|
|
||||||
* @param bool $force_defaults if true sets a default value to
|
|
||||||
* field when not explicit
|
|
||||||
* @param int $max_identifiers_length maximum allowed size for entities
|
|
||||||
* name
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function __construct($variables, $fail_on_invalid_names = true,
|
|
||||||
$structure = false, $valid_types = array(), $force_defaults = true,
|
|
||||||
$max_identifiers_length = null
|
|
||||||
) {
|
|
||||||
// force ISO-8859-1 due to different defaults for PHP4 and PHP5
|
|
||||||
// todo: this probably needs to be investigated some more and cleaned up
|
|
||||||
$this->options['encoding'] = 'ISO-8859-1';
|
|
||||||
|
|
||||||
$this->options['XML_UNSERIALIZER_OPTION_ATTRIBUTES_PARSE'] = true;
|
|
||||||
$this->options['XML_UNSERIALIZER_OPTION_ATTRIBUTES_ARRAYKEY'] = false;
|
|
||||||
|
|
||||||
$this->options['forceEnum'] = array('table', 'field', 'index', 'foreign', 'insert', 'update', 'delete', 'sequence');
|
|
||||||
|
|
||||||
/*
|
|
||||||
* todo: find a way to force the following items not to be parsed as arrays
|
|
||||||
* as it cause problems in functions with multiple arguments
|
|
||||||
*/
|
|
||||||
//$this->options['forceNEnum'] = array('value', 'column');
|
|
||||||
$this->variables = $variables;
|
|
||||||
$this->structure = $structure;
|
|
||||||
|
|
||||||
$this->val = new MDB2_Schema_Validate($fail_on_invalid_names, $valid_types, $force_defaults);
|
|
||||||
parent::XML_Unserializer($this->options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main method. Parses XML Schema File.
|
|
||||||
*
|
|
||||||
* @return bool|error object
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function parse()
|
|
||||||
{
|
|
||||||
$result = $this->unserialize($this->filename, true);
|
|
||||||
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
} else {
|
|
||||||
$this->database_loaded = $this->getUnserializedData();
|
|
||||||
return $this->fixDatabaseKeys($this->database_loaded);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do the necessary stuff to set the input XML schema file
|
|
||||||
*
|
|
||||||
* @param string $filename full path to schema file
|
|
||||||
*
|
|
||||||
* @return boolean MDB2_OK on success
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function setInputFile($filename)
|
|
||||||
{
|
|
||||||
$this->filename = $filename;
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enforce the default values for mandatory keys and ensure everything goes
|
|
||||||
* always in the same order (simulates the behaviour of the original
|
|
||||||
* parser). Works at database level.
|
|
||||||
*
|
|
||||||
* @param array $database multi dimensional array with database definition
|
|
||||||
* and data.
|
|
||||||
*
|
|
||||||
* @return bool|error MDB2_OK on success or error object
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
function fixDatabaseKeys($database)
|
|
||||||
{
|
|
||||||
$this->database_definition = array(
|
|
||||||
'name' => '',
|
|
||||||
'create' => '',
|
|
||||||
'overwrite' => '',
|
|
||||||
'charset' => '',
|
|
||||||
'description' => '',
|
|
||||||
'comments' => '',
|
|
||||||
'tables' => array(),
|
|
||||||
'sequences' => array()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!empty($database['name'])) {
|
|
||||||
$this->database_definition['name'] = $database['name'];
|
|
||||||
}
|
|
||||||
if (!empty($database['create'])) {
|
|
||||||
$this->database_definition['create'] = $database['create'];
|
|
||||||
}
|
|
||||||
if (!empty($database['overwrite'])) {
|
|
||||||
$this->database_definition['overwrite'] = $database['overwrite'];
|
|
||||||
}
|
|
||||||
if (!empty($database['charset'])) {
|
|
||||||
$this->database_definition['charset'] = $database['charset'];
|
|
||||||
}
|
|
||||||
if (!empty($database['description'])) {
|
|
||||||
$this->database_definition['description'] = $database['description'];
|
|
||||||
}
|
|
||||||
if (!empty($database['comments'])) {
|
|
||||||
$this->database_definition['comments'] = $database['comments'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($database['table']) && is_array($database['table'])) {
|
|
||||||
foreach ($database['table'] as $table) {
|
|
||||||
$this->fixTableKeys($table);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($database['sequence']) && is_array($database['sequence'])) {
|
|
||||||
foreach ($database['sequence'] as $sequence) {
|
|
||||||
$this->fixSequenceKeys($sequence);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $this->val->validateDatabase($this->database_definition);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $this->raiseError($result->getUserinfo());
|
|
||||||
}
|
|
||||||
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enforce the default values for mandatory keys and ensure everything goes
|
|
||||||
* always in the same order (simulates the behaviour of the original
|
|
||||||
* parser). Works at table level.
|
|
||||||
*
|
|
||||||
* @param array $table multi dimensional array with table definition
|
|
||||||
* and data.
|
|
||||||
*
|
|
||||||
* @return bool|error MDB2_OK on success or error object
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
function fixTableKeys($table)
|
|
||||||
{
|
|
||||||
$this->table = array(
|
|
||||||
'was' => '',
|
|
||||||
'description' => '',
|
|
||||||
'comments' => '',
|
|
||||||
'fields' => array(),
|
|
||||||
'indexes' => array(),
|
|
||||||
'constraints' => array(),
|
|
||||||
'initialization' => array()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!empty($table['name'])) {
|
|
||||||
$this->table_name = $table['name'];
|
|
||||||
} else {
|
|
||||||
$this->table_name = '';
|
|
||||||
}
|
|
||||||
if (!empty($table['was'])) {
|
|
||||||
$this->table['was'] = $table['was'];
|
|
||||||
}
|
|
||||||
if (!empty($table['description'])) {
|
|
||||||
$this->table['description'] = $table['description'];
|
|
||||||
}
|
|
||||||
if (!empty($table['comments'])) {
|
|
||||||
$this->table['comments'] = $table['comments'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($table['declaration']) && is_array($table['declaration'])) {
|
|
||||||
if (!empty($table['declaration']['field']) && is_array($table['declaration']['field'])) {
|
|
||||||
foreach ($table['declaration']['field'] as $field) {
|
|
||||||
$this->fixTableFieldKeys($field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($table['declaration']['index']) && is_array($table['declaration']['index'])) {
|
|
||||||
foreach ($table['declaration']['index'] as $index) {
|
|
||||||
$this->fixTableIndexKeys($index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($table['declaration']['foreign']) && is_array($table['declaration']['foreign'])) {
|
|
||||||
foreach ($table['declaration']['foreign'] as $constraint) {
|
|
||||||
$this->fixTableConstraintKeys($constraint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($table['initialization']) && is_array($table['initialization'])) {
|
|
||||||
if (!empty($table['initialization']['insert']) && is_array($table['initialization']['insert'])) {
|
|
||||||
foreach ($table['initialization']['insert'] as $init) {
|
|
||||||
$this->fixTableInitializationKeys($init, 'insert');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!empty($table['initialization']['update']) && is_array($table['initialization']['update'])) {
|
|
||||||
foreach ($table['initialization']['update'] as $init) {
|
|
||||||
$this->fixTableInitializationKeys($init, 'update');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!empty($table['initialization']['delete']) && is_array($table['initialization']['delete'])) {
|
|
||||||
foreach ($table['initialization']['delete'] as $init) {
|
|
||||||
$this->fixTableInitializationKeys($init, 'delete');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $this->val->validateTable($this->database_definition['tables'], $this->table, $this->table_name);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $this->raiseError($result->getUserinfo());
|
|
||||||
} else {
|
|
||||||
$this->database_definition['tables'][$this->table_name] = $this->table;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enforce the default values for mandatory keys and ensure everything goes
|
|
||||||
* always in the same order (simulates the behaviour of the original
|
|
||||||
* parser). Works at table field level.
|
|
||||||
*
|
|
||||||
* @param array $field array with table field definition
|
|
||||||
*
|
|
||||||
* @return bool|error MDB2_OK on success or error object
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
function fixTableFieldKeys($field)
|
|
||||||
{
|
|
||||||
$this->field = array();
|
|
||||||
if (!empty($field['name'])) {
|
|
||||||
$this->field_name = $field['name'];
|
|
||||||
} else {
|
|
||||||
$this->field_name = '';
|
|
||||||
}
|
|
||||||
if (!empty($field['was'])) {
|
|
||||||
$this->field['was'] = $field['was'];
|
|
||||||
}
|
|
||||||
if (!empty($field['type'])) {
|
|
||||||
$this->field['type'] = $field['type'];
|
|
||||||
}
|
|
||||||
if (!empty($field['fixed'])) {
|
|
||||||
$this->field['fixed'] = $field['fixed'];
|
|
||||||
}
|
|
||||||
if (isset($field['default'])) {
|
|
||||||
$this->field['default'] = $field['default'];
|
|
||||||
}
|
|
||||||
if (!empty($field['notnull'])) {
|
|
||||||
$this->field['notnull'] = $field['notnull'];
|
|
||||||
}
|
|
||||||
if (!empty($field['autoincrement'])) {
|
|
||||||
$this->field['autoincrement'] = $field['autoincrement'];
|
|
||||||
}
|
|
||||||
if (!empty($field['unsigned'])) {
|
|
||||||
$this->field['unsigned'] = $field['unsigned'];
|
|
||||||
}
|
|
||||||
if (!empty($field['length'])) {
|
|
||||||
$this->field['length'] = $field['length'];
|
|
||||||
}
|
|
||||||
if (!empty($field['description'])) {
|
|
||||||
$this->field['description'] = $field['description'];
|
|
||||||
}
|
|
||||||
if (!empty($field['comments'])) {
|
|
||||||
$this->field['comments'] = $field['comments'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $this->val->validateField($this->table['fields'], $this->field, $this->field_name);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $this->raiseError($result->getUserinfo());
|
|
||||||
} else {
|
|
||||||
$this->table['fields'][$this->field_name] = $this->field;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enforce the default values for mandatory keys and ensure everything goes
|
|
||||||
* always in the same order (simulates the behaviour of the original
|
|
||||||
* parser). Works at table index level.
|
|
||||||
*
|
|
||||||
* @param array $index array with table index definition
|
|
||||||
*
|
|
||||||
* @return bool|error MDB2_OK on success or error object
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
function fixTableIndexKeys($index)
|
|
||||||
{
|
|
||||||
$this->index = array(
|
|
||||||
'was' => '',
|
|
||||||
'unique' =>'',
|
|
||||||
'primary' => '',
|
|
||||||
'fields' => array()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!empty($index['name'])) {
|
|
||||||
$this->index_name = $index['name'];
|
|
||||||
} else {
|
|
||||||
$this->index_name = '';
|
|
||||||
}
|
|
||||||
if (!empty($index['was'])) {
|
|
||||||
$this->index['was'] = $index['was'];
|
|
||||||
}
|
|
||||||
if (!empty($index['unique'])) {
|
|
||||||
$this->index['unique'] = $index['unique'];
|
|
||||||
}
|
|
||||||
if (!empty($index['primary'])) {
|
|
||||||
$this->index['primary'] = $index['primary'];
|
|
||||||
}
|
|
||||||
if (!empty($index['field'])) {
|
|
||||||
foreach ($index['field'] as $field) {
|
|
||||||
if (!empty($field['name'])) {
|
|
||||||
$this->field_name = $field['name'];
|
|
||||||
} else {
|
|
||||||
$this->field_name = '';
|
|
||||||
}
|
|
||||||
$this->field = array(
|
|
||||||
'sorting' => '',
|
|
||||||
'length' => ''
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!empty($field['sorting'])) {
|
|
||||||
$this->field['sorting'] = $field['sorting'];
|
|
||||||
}
|
|
||||||
if (!empty($field['length'])) {
|
|
||||||
$this->field['length'] = $field['length'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $this->val->validateIndexField($this->index['fields'], $this->field, $this->field_name);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $this->raiseError($result->getUserinfo());
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->index['fields'][$this->field_name] = $this->field;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $this->val->validateIndex($this->table['indexes'], $this->index, $this->index_name);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $this->raiseError($result->getUserinfo());
|
|
||||||
} else {
|
|
||||||
$this->table['indexes'][$this->index_name] = $this->index;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enforce the default values for mandatory keys and ensure everything goes
|
|
||||||
* always in the same order (simulates the behaviour of the original
|
|
||||||
* parser). Works at table constraint level.
|
|
||||||
*
|
|
||||||
* @param array $constraint array with table index definition
|
|
||||||
*
|
|
||||||
* @return bool|error MDB2_OK on success or error object
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
function fixTableConstraintKeys($constraint)
|
|
||||||
{
|
|
||||||
$this->constraint = array(
|
|
||||||
'was' => '',
|
|
||||||
'match' => '',
|
|
||||||
'ondelete' => '',
|
|
||||||
'onupdate' => '',
|
|
||||||
'deferrable' => '',
|
|
||||||
'initiallydeferred' => '',
|
|
||||||
'foreign' => true,
|
|
||||||
'fields' => array(),
|
|
||||||
'references' => array('table' => '', 'fields' => array())
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!empty($constraint['name'])) {
|
|
||||||
$this->constraint_name = $constraint['name'];
|
|
||||||
} else {
|
|
||||||
$this->constraint_name = '';
|
|
||||||
}
|
|
||||||
if (!empty($constraint['was'])) {
|
|
||||||
$this->constraint['was'] = $constraint['was'];
|
|
||||||
}
|
|
||||||
if (!empty($constraint['match'])) {
|
|
||||||
$this->constraint['match'] = $constraint['match'];
|
|
||||||
}
|
|
||||||
if (!empty($constraint['ondelete'])) {
|
|
||||||
$this->constraint['ondelete'] = $constraint['ondelete'];
|
|
||||||
}
|
|
||||||
if (!empty($constraint['onupdate'])) {
|
|
||||||
$this->constraint['onupdate'] = $constraint['onupdate'];
|
|
||||||
}
|
|
||||||
if (!empty($constraint['deferrable'])) {
|
|
||||||
$this->constraint['deferrable'] = $constraint['deferrable'];
|
|
||||||
}
|
|
||||||
if (!empty($constraint['initiallydeferred'])) {
|
|
||||||
$this->constraint['initiallydeferred'] = $constraint['initiallydeferred'];
|
|
||||||
}
|
|
||||||
if (!empty($constraint['field']) && is_array($constraint['field'])) {
|
|
||||||
foreach ($constraint['field'] as $field) {
|
|
||||||
$result = $this->val->validateConstraintField($this->constraint['fields'], $field);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $this->raiseError($result->getUserinfo());
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->constraint['fields'][$field] = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($constraint['references']) && is_array($constraint['references'])) {
|
|
||||||
/**
|
|
||||||
* As we forced 'table' to be enumerated
|
|
||||||
* we have to fix it on the foreign-references-table context
|
|
||||||
*/
|
|
||||||
if (!empty($constraint['references']['table']) && is_array($constraint['references']['table'])) {
|
|
||||||
$this->constraint['references']['table'] = $constraint['references']['table'][0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($constraint['references']['field']) && is_array($constraint['references']['field'])) {
|
|
||||||
foreach ($constraint['references']['field'] as $field) {
|
|
||||||
$result = $this->val->validateConstraintReferencedField($this->constraint['references']['fields'], $field);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $this->raiseError($result->getUserinfo());
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->constraint['references']['fields'][$field] = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $this->val->validateConstraint($this->table['constraints'], $this->constraint, $this->constraint_name);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $this->raiseError($result->getUserinfo());
|
|
||||||
} else {
|
|
||||||
$this->table['constraints'][$this->constraint_name] = $this->constraint;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enforce the default values for mandatory keys and ensure everything goes
|
|
||||||
* always in the same order (simulates the behaviour of the original
|
|
||||||
* parser). Works at table data level.
|
|
||||||
*
|
|
||||||
* @param array $element multi dimensional array with query definition
|
|
||||||
* @param string $type whether its a insert|update|delete query
|
|
||||||
*
|
|
||||||
* @return bool|error MDB2_OK on success or error object
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
function fixTableInitializationKeys($element, $type = '')
|
|
||||||
{
|
|
||||||
if (!empty($element['select']) && is_array($element['select'])) {
|
|
||||||
$this->fixTableInitializationDataKeys($element['select']);
|
|
||||||
$this->init = array( 'select' => $this->init );
|
|
||||||
} else {
|
|
||||||
$this->fixTableInitializationDataKeys($element);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->table['initialization'][] = array( 'type' => $type, 'data' => $this->init );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enforce the default values for mandatory keys and ensure everything goes
|
|
||||||
* always in the same order (simulates the behaviour of the original
|
|
||||||
* parser). Works deeper at the table initialization level (data). At this
|
|
||||||
* point we are look at one of the below:
|
|
||||||
*
|
|
||||||
* <insert>
|
|
||||||
* {field}+
|
|
||||||
* </insert>
|
|
||||||
*
|
|
||||||
* <select> (this is a select extracted off a insert-select query)
|
|
||||||
* <table/>
|
|
||||||
* {field}+
|
|
||||||
* <where>
|
|
||||||
* {expression}
|
|
||||||
* </where>?
|
|
||||||
* </select>
|
|
||||||
*
|
|
||||||
* <update>
|
|
||||||
* {field}+
|
|
||||||
* <where>
|
|
||||||
* {expression}
|
|
||||||
* </where>?
|
|
||||||
* </update>
|
|
||||||
*
|
|
||||||
* <delete>
|
|
||||||
* <where>
|
|
||||||
* {expression}
|
|
||||||
* </where>
|
|
||||||
* </delete>
|
|
||||||
*
|
|
||||||
* @param array $element multi dimensional array with query definition
|
|
||||||
*
|
|
||||||
* @return bool|error MDB2_OK on success or error object
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
function fixTableInitializationDataKeys($element)
|
|
||||||
{
|
|
||||||
$this->init = array();
|
|
||||||
if (!empty($element['field']) && is_array($element['field'])) {
|
|
||||||
foreach ($element['field'] as $field) {
|
|
||||||
$name = $field['name'];
|
|
||||||
unset($field['name']);
|
|
||||||
|
|
||||||
$this->setExpression($field);
|
|
||||||
$this->init['field'][] = array( 'name' => $name, 'group' => $field );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* As we forced 'table' to be enumerated
|
|
||||||
* we have to fix it on the insert-select context
|
|
||||||
*/
|
|
||||||
if (!empty($element['table']) && is_array($element['table'])) {
|
|
||||||
$this->init['table'] = $element['table'][0];
|
|
||||||
}
|
|
||||||
if (!empty($element['where']) && is_array($element['where'])) {
|
|
||||||
$this->init['where'] = $element['where'];
|
|
||||||
$this->setExpression($this->init['where']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursively diggs into an "expression" element. According to our
|
|
||||||
* documentation an "expression" element is of the kind:
|
|
||||||
*
|
|
||||||
* <expression>
|
|
||||||
* <null/> or <value/> or <column/> or {function} or {expression}
|
|
||||||
* <operator/>
|
|
||||||
* <null/> or <value/> or <column/> or {function} or {expression}
|
|
||||||
* </expression>
|
|
||||||
*
|
|
||||||
* @param array &$arr reference to current element definition
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
function setExpression(&$arr)
|
|
||||||
{
|
|
||||||
$element = each($arr);
|
|
||||||
|
|
||||||
$arr = array( 'type' => $element['key'] );
|
|
||||||
|
|
||||||
$element = $element['value'];
|
|
||||||
|
|
||||||
switch ($arr['type']) {
|
|
||||||
case 'null':
|
|
||||||
break;
|
|
||||||
case 'value':
|
|
||||||
case 'column':
|
|
||||||
$arr['data'] = $element;
|
|
||||||
break;
|
|
||||||
case 'function':
|
|
||||||
if (!empty($element)
|
|
||||||
&& is_array($element)
|
|
||||||
) {
|
|
||||||
$arr['data'] = array( 'name' => $element['name'] );
|
|
||||||
unset($element['name']);
|
|
||||||
|
|
||||||
foreach ($element as $type => $value) {
|
|
||||||
if (!empty($value)) {
|
|
||||||
if (is_array($value)) {
|
|
||||||
foreach ($value as $argument) {
|
|
||||||
$argument = array( $type => $argument );
|
|
||||||
$this->setExpression($argument);
|
|
||||||
$arr['data']['arguments'][] = $argument;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$arr['data']['arguments'][] = array( 'type' => $type, 'data' => $value );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'expression':
|
|
||||||
$arr['data'] = array( 'operants' => array(), 'operator' => $element['operator'] );
|
|
||||||
unset($element['operator']);
|
|
||||||
|
|
||||||
foreach ($element as $k => $v) {
|
|
||||||
$argument = array( $k => $v );
|
|
||||||
$this->setExpression($argument);
|
|
||||||
$arr['data']['operants'][] = $argument;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enforce the default values for mandatory keys and ensure everything goes
|
|
||||||
* always in the same order (simulates the behaviour of the original
|
|
||||||
* parser). Works at database sequences level. A "sequence" element looks
|
|
||||||
* like:
|
|
||||||
*
|
|
||||||
* <sequence>
|
|
||||||
* <name/>
|
|
||||||
* <was/>?
|
|
||||||
* <start/>?
|
|
||||||
* <description/>?
|
|
||||||
* <comments/>?
|
|
||||||
* <on>
|
|
||||||
* <table/>
|
|
||||||
* <field/>
|
|
||||||
* </on>?
|
|
||||||
* </sequence>
|
|
||||||
*
|
|
||||||
* @param array $sequence multi dimensional array with sequence definition
|
|
||||||
*
|
|
||||||
* @return bool|error MDB2_OK on success or error object
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
function fixSequenceKeys($sequence)
|
|
||||||
{
|
|
||||||
$this->sequence = array(
|
|
||||||
'was' => '',
|
|
||||||
'start' => '',
|
|
||||||
'description' => '',
|
|
||||||
'comments' => '',
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!empty($sequence['name'])) {
|
|
||||||
$this->sequence_name = $sequence['name'];
|
|
||||||
} else {
|
|
||||||
$this->sequence_name = '';
|
|
||||||
}
|
|
||||||
if (!empty($sequence['was'])) {
|
|
||||||
$this->sequence['was'] = $sequence['was'];
|
|
||||||
}
|
|
||||||
if (!empty($sequence['start'])) {
|
|
||||||
$this->sequence['start'] = $sequence['start'];
|
|
||||||
}
|
|
||||||
if (!empty($sequence['description'])) {
|
|
||||||
$this->sequence['description'] = $sequence['description'];
|
|
||||||
}
|
|
||||||
if (!empty($sequence['comments'])) {
|
|
||||||
$this->sequence['comments'] = $sequence['comments'];
|
|
||||||
}
|
|
||||||
if (!empty($sequence['on']) && is_array($sequence['on'])) {
|
|
||||||
/**
|
|
||||||
* As we forced 'table' to be enumerated
|
|
||||||
* we have to fix it on the sequence-on-table context
|
|
||||||
*/
|
|
||||||
if (!empty($sequence['on']['table']) && is_array($sequence['on']['table'])) {
|
|
||||||
$this->sequence['on']['table'] = $sequence['on']['table'][0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* As we forced 'field' to be enumerated
|
|
||||||
* we have to fix it on the sequence-on-field context
|
|
||||||
*/
|
|
||||||
if (!empty($sequence['on']['field']) && is_array($sequence['on']['field'])) {
|
|
||||||
$this->sequence['on']['field'] = $sequence['on']['field'][0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $this->val->validateSequence($this->database_definition['sequences'], $this->sequence, $this->sequence_name);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $this->raiseError($result->getUserinfo());
|
|
||||||
} else {
|
|
||||||
$this->database_definition['sequences'][$this->sequence_name] = $this->sequence;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pushes a MDB2_Schema_Error into stack and returns it
|
|
||||||
*
|
|
||||||
* @param string $msg textual message
|
|
||||||
* @param int $ecode MDB2_Schema's error code
|
|
||||||
*
|
|
||||||
* @return object
|
|
||||||
* @access private
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function &raiseError($msg = null, $ecode = MDB2_SCHEMA_ERROR_PARSE)
|
|
||||||
{
|
|
||||||
if (is_null($this->error)) {
|
|
||||||
$error = 'Parser error: '.$msg."\n";
|
|
||||||
|
|
||||||
$this->error = MDB2_Schema::raiseError($ecode, null, null, $error);
|
|
||||||
}
|
|
||||||
return $this->error;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,437 +0,0 @@
|
||||||
<?php /* vim: se et ts=4 sw=4 sts=4 fdm=marker tw=80: */
|
|
||||||
/**
|
|
||||||
* Copyright (c) 1998-2010 Manuel Lemos, Tomas V.V.Cox,
|
|
||||||
* Stig. S. Bakken, Lukas Smith, Igor Feghali
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* MDB2_Schema enables users to maintain RDBMS independant schema files
|
|
||||||
* in XML that can be used to manipulate both data and database schemas
|
|
||||||
* This LICENSE is in the BSD license style.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,
|
|
||||||
* Lukas Smith, Igor Feghali nor the names of his contributors may be
|
|
||||||
* used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* REGENTS 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.
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* @category Database
|
|
||||||
* @package MDB2_Schema
|
|
||||||
* @author Lorenzo Alberton <l.alberton@quipo.it>
|
|
||||||
* @license BSD http://www.opensource.org/licenses/bsd-license.php
|
|
||||||
* @version SVN: $Id$
|
|
||||||
* @link http://pear.php.net/packages/MDB2_Schema
|
|
||||||
*/
|
|
||||||
// {{{ $GLOBALS['_MDB2_Schema_Reserved']['ibase']
|
|
||||||
/**
|
|
||||||
* Has a list of reserved words of Interbase/Firebird
|
|
||||||
*
|
|
||||||
* @package MDB2_Schema
|
|
||||||
* @category Database
|
|
||||||
* @access protected
|
|
||||||
* @author Lorenzo Alberton <l.alberton@quipo.it>
|
|
||||||
*/
|
|
||||||
$GLOBALS['_MDB2_Schema_Reserved']['ibase'] = array(
|
|
||||||
'ABS',
|
|
||||||
'ABSOLUTE',
|
|
||||||
'ACTION',
|
|
||||||
'ACTIVE',
|
|
||||||
'ADD',
|
|
||||||
'ADMIN',
|
|
||||||
'AFTER',
|
|
||||||
'ALL',
|
|
||||||
'ALLOCATE',
|
|
||||||
'ALTER',
|
|
||||||
'AND',
|
|
||||||
'ANY',
|
|
||||||
'ARE',
|
|
||||||
'AS',
|
|
||||||
'ASC',
|
|
||||||
'ASCENDING',
|
|
||||||
'ASSERTION',
|
|
||||||
'AT',
|
|
||||||
'AUTHORIZATION',
|
|
||||||
'AUTO',
|
|
||||||
'AUTODDL',
|
|
||||||
'AVG',
|
|
||||||
'BACKUP',
|
|
||||||
'BASE_NAME',
|
|
||||||
'BASED',
|
|
||||||
'BASENAME',
|
|
||||||
'BEFORE',
|
|
||||||
'BEGIN',
|
|
||||||
'BETWEEN',
|
|
||||||
'BIGINT',
|
|
||||||
'BIT',
|
|
||||||
'BIT_LENGTH',
|
|
||||||
'BLOB',
|
|
||||||
'BLOCK',
|
|
||||||
'BLOBEDIT',
|
|
||||||
'BOOLEAN',
|
|
||||||
'BOTH',
|
|
||||||
'BOTH',
|
|
||||||
'BREAK',
|
|
||||||
'BUFFER',
|
|
||||||
'BY',
|
|
||||||
'CACHE',
|
|
||||||
'CASCADE',
|
|
||||||
'CASCADED',
|
|
||||||
'CASE',
|
|
||||||
'CASE',
|
|
||||||
'CAST',
|
|
||||||
'CATALOG',
|
|
||||||
'CHAR',
|
|
||||||
'CHAR_LENGTH',
|
|
||||||
'CHARACTER',
|
|
||||||
'CHARACTER_LENGTH',
|
|
||||||
'CHECK',
|
|
||||||
'CHECK_POINT_LEN',
|
|
||||||
'CHECK_POINT_LENGTH',
|
|
||||||
'CLOSE',
|
|
||||||
'COALESCE',
|
|
||||||
'COLLATE',
|
|
||||||
'COLLATION',
|
|
||||||
'COLUMN',
|
|
||||||
'COMMENT',
|
|
||||||
'COMMIT',
|
|
||||||
'COMMITTED',
|
|
||||||
'COMPILETIME',
|
|
||||||
'COMPUTED',
|
|
||||||
'CONDITIONAL',
|
|
||||||
'CONNECT',
|
|
||||||
'CONNECTION',
|
|
||||||
'CONSTRAINT',
|
|
||||||
'CONSTRAINTS',
|
|
||||||
'CONTAINING',
|
|
||||||
'CONTINUE',
|
|
||||||
'CONVERT',
|
|
||||||
'CORRESPONDING',
|
|
||||||
'COUNT',
|
|
||||||
'CREATE',
|
|
||||||
'CROSS',
|
|
||||||
'CSTRING',
|
|
||||||
'CURRENT',
|
|
||||||
'CURRENT_CONNECTION',
|
|
||||||
'CURRENT_DATE',
|
|
||||||
'CURRENT_ROLE',
|
|
||||||
'CURRENT_TIME',
|
|
||||||
'CURRENT_TIMESTAMP',
|
|
||||||
'CURRENT_TRANSACTION',
|
|
||||||
'CURRENT_USER',
|
|
||||||
'DATABASE',
|
|
||||||
'DATE',
|
|
||||||
'DAY',
|
|
||||||
'DB_KEY',
|
|
||||||
'DEALLOCATE',
|
|
||||||
'DEBUG',
|
|
||||||
'DEC',
|
|
||||||
'DECIMAL',
|
|
||||||
'DECLARE',
|
|
||||||
'DEFAULT',
|
|
||||||
'DEFERRABLE',
|
|
||||||
'DEFERRED',
|
|
||||||
'DELETE',
|
|
||||||
'DELETING',
|
|
||||||
'DESC',
|
|
||||||
'DESCENDING',
|
|
||||||
'DESCRIBE',
|
|
||||||
'DESCRIPTOR',
|
|
||||||
'DIAGNOSTICS',
|
|
||||||
'DIFFERENCE',
|
|
||||||
'DISCONNECT',
|
|
||||||
'DISPLAY',
|
|
||||||
'DISTINCT',
|
|
||||||
'DO',
|
|
||||||
'DOMAIN',
|
|
||||||
'DOUBLE',
|
|
||||||
'DROP',
|
|
||||||
'ECHO',
|
|
||||||
'EDIT',
|
|
||||||
'ELSE',
|
|
||||||
'END',
|
|
||||||
'END-EXEC',
|
|
||||||
'ENTRY_POINT',
|
|
||||||
'ESCAPE',
|
|
||||||
'EVENT',
|
|
||||||
'EXCEPT',
|
|
||||||
'EXCEPTION',
|
|
||||||
'EXEC',
|
|
||||||
'EXECUTE',
|
|
||||||
'EXISTS',
|
|
||||||
'EXIT',
|
|
||||||
'EXTERN',
|
|
||||||
'EXTERNAL',
|
|
||||||
'EXTRACT',
|
|
||||||
'FALSE',
|
|
||||||
'FETCH',
|
|
||||||
'FILE',
|
|
||||||
'FILTER',
|
|
||||||
'FIRST',
|
|
||||||
'FLOAT',
|
|
||||||
'FOR',
|
|
||||||
'FOREIGN',
|
|
||||||
'FOUND',
|
|
||||||
'FREE_IT',
|
|
||||||
'FROM',
|
|
||||||
'FULL',
|
|
||||||
'FUNCTION',
|
|
||||||
'GDSCODE',
|
|
||||||
'GEN_ID',
|
|
||||||
'GENERATOR',
|
|
||||||
'GET',
|
|
||||||
'GLOBAL',
|
|
||||||
'GO',
|
|
||||||
'GOTO',
|
|
||||||
'GRANT',
|
|
||||||
'GROUP',
|
|
||||||
'GROUP_COMMIT_WAIT',
|
|
||||||
'GROUP_COMMIT_WAIT_TIME',
|
|
||||||
'HAVING',
|
|
||||||
'HELP',
|
|
||||||
'HOUR',
|
|
||||||
'IDENTITY',
|
|
||||||
'IF',
|
|
||||||
'IIF',
|
|
||||||
'IMMEDIATE',
|
|
||||||
'IN',
|
|
||||||
'INACTIVE',
|
|
||||||
'INDEX',
|
|
||||||
'INDICATOR',
|
|
||||||
'INIT',
|
|
||||||
'INITIALLY',
|
|
||||||
'INNER',
|
|
||||||
'INPUT',
|
|
||||||
'INPUT_TYPE',
|
|
||||||
'INSENSITIVE',
|
|
||||||
'INSERT',
|
|
||||||
'INSERTING',
|
|
||||||
'INT',
|
|
||||||
'INTEGER',
|
|
||||||
'INTERSECT',
|
|
||||||
'INTERVAL',
|
|
||||||
'INTO',
|
|
||||||
'IS',
|
|
||||||
'ISOLATION',
|
|
||||||
'ISQL',
|
|
||||||
'JOIN',
|
|
||||||
'KEY',
|
|
||||||
'LANGUAGE',
|
|
||||||
'LAST',
|
|
||||||
'LC_MESSAGES',
|
|
||||||
'LC_TYPE',
|
|
||||||
'LEADING',
|
|
||||||
'LEADING',
|
|
||||||
'LEADING',
|
|
||||||
'LEAVE',
|
|
||||||
'LEFT',
|
|
||||||
'LENGTH',
|
|
||||||
'LEV',
|
|
||||||
'LEVEL',
|
|
||||||
'LIKE',
|
|
||||||
'LOCAL',
|
|
||||||
'LOCK',
|
|
||||||
'LOG_BUF_SIZE',
|
|
||||||
'LOG_BUFFER_SIZE',
|
|
||||||
'LOGFILE',
|
|
||||||
'LONG',
|
|
||||||
'LOWER',
|
|
||||||
'MANUAL',
|
|
||||||
'MATCH',
|
|
||||||
'MAX',
|
|
||||||
'MAX_SEGMENT',
|
|
||||||
'MAXIMUM',
|
|
||||||
'MAXIMUM_SEGMENT',
|
|
||||||
'MERGE',
|
|
||||||
'MESSAGE',
|
|
||||||
'MIN',
|
|
||||||
'MINIMUM',
|
|
||||||
'MINUTE',
|
|
||||||
'MODULE',
|
|
||||||
'MODULE_NAME',
|
|
||||||
'MONTH',
|
|
||||||
'NAMES',
|
|
||||||
'NATIONAL',
|
|
||||||
'NATURAL',
|
|
||||||
'NCHAR',
|
|
||||||
'NEXT',
|
|
||||||
'NO',
|
|
||||||
'NOAUTO',
|
|
||||||
'NOT',
|
|
||||||
'NULL',
|
|
||||||
'NULLIF',
|
|
||||||
'NULLS',
|
|
||||||
'NUM_LOG_BUFFERS',
|
|
||||||
'NUM_LOG_BUFS',
|
|
||||||
'NUMERIC',
|
|
||||||
'OCTET_LENGTH',
|
|
||||||
'OF',
|
|
||||||
'ON',
|
|
||||||
'ONLY',
|
|
||||||
'OPEN',
|
|
||||||
'OPTION',
|
|
||||||
'OR',
|
|
||||||
'ORDER',
|
|
||||||
'OUTER',
|
|
||||||
'OUTPUT',
|
|
||||||
'OUTPUT_TYPE',
|
|
||||||
'OVERFLOW',
|
|
||||||
'OVERLAPS',
|
|
||||||
'PAD',
|
|
||||||
'PAGE',
|
|
||||||
'PAGE_SIZE',
|
|
||||||
'PAGELENGTH',
|
|
||||||
'PAGES',
|
|
||||||
'PARAMETER',
|
|
||||||
'PARTIAL',
|
|
||||||
'PASSWORD',
|
|
||||||
'PERCENT',
|
|
||||||
'PLAN',
|
|
||||||
'POSITION',
|
|
||||||
'POST_EVENT',
|
|
||||||
'PRECISION',
|
|
||||||
'PREPARE',
|
|
||||||
'PRESERVE',
|
|
||||||
'PRIMARY',
|
|
||||||
'PRIOR',
|
|
||||||
'PRIVILEGES',
|
|
||||||
'PROCEDURE',
|
|
||||||
'PUBLIC',
|
|
||||||
'QUIT',
|
|
||||||
'RAW_PARTITIONS',
|
|
||||||
'RDB$DB_KEY',
|
|
||||||
'READ',
|
|
||||||
'REAL',
|
|
||||||
'RECORD_VERSION',
|
|
||||||
'RECREATE',
|
|
||||||
'RECREATE ROW_COUNT',
|
|
||||||
'REFERENCES',
|
|
||||||
'RELATIVE',
|
|
||||||
'RELEASE',
|
|
||||||
'RESERV',
|
|
||||||
'RESERVING',
|
|
||||||
'RESTART',
|
|
||||||
'RESTRICT',
|
|
||||||
'RETAIN',
|
|
||||||
'RETURN',
|
|
||||||
'RETURNING',
|
|
||||||
'RETURNING_VALUES',
|
|
||||||
'RETURNS',
|
|
||||||
'REVOKE',
|
|
||||||
'RIGHT',
|
|
||||||
'ROLE',
|
|
||||||
'ROLLBACK',
|
|
||||||
'ROW_COUNT',
|
|
||||||
'ROWS',
|
|
||||||
'RUNTIME',
|
|
||||||
'SAVEPOINT',
|
|
||||||
'SCALAR_ARRAY',
|
|
||||||
'SCHEMA',
|
|
||||||
'SCROLL',
|
|
||||||
'SECOND',
|
|
||||||
'SECTION',
|
|
||||||
'SELECT',
|
|
||||||
'SEQUENCE',
|
|
||||||
'SESSION',
|
|
||||||
'SESSION_USER',
|
|
||||||
'SET',
|
|
||||||
'SHADOW',
|
|
||||||
'SHARED',
|
|
||||||
'SHELL',
|
|
||||||
'SHOW',
|
|
||||||
'SINGULAR',
|
|
||||||
'SIZE',
|
|
||||||
'SKIP',
|
|
||||||
'SMALLINT',
|
|
||||||
'SNAPSHOT',
|
|
||||||
'SOME',
|
|
||||||
'SORT',
|
|
||||||
'SPACE',
|
|
||||||
'SQL',
|
|
||||||
'SQLCODE',
|
|
||||||
'SQLERROR',
|
|
||||||
'SQLSTATE',
|
|
||||||
'SQLWARNING',
|
|
||||||
'STABILITY',
|
|
||||||
'STARTING',
|
|
||||||
'STARTS',
|
|
||||||
'STATEMENT',
|
|
||||||
'STATIC',
|
|
||||||
'STATISTICS',
|
|
||||||
'SUB_TYPE',
|
|
||||||
'SUBSTRING',
|
|
||||||
'SUM',
|
|
||||||
'SUSPEND',
|
|
||||||
'SYSTEM_USER',
|
|
||||||
'TABLE',
|
|
||||||
'TEMPORARY',
|
|
||||||
'TERMINATOR',
|
|
||||||
'THEN',
|
|
||||||
'TIES',
|
|
||||||
'TIME',
|
|
||||||
'TIMESTAMP',
|
|
||||||
'TIMEZONE_HOUR',
|
|
||||||
'TIMEZONE_MINUTE',
|
|
||||||
'TO',
|
|
||||||
'TRAILING',
|
|
||||||
'TRANSACTION',
|
|
||||||
'TRANSLATE',
|
|
||||||
'TRANSLATION',
|
|
||||||
'TRIGGER',
|
|
||||||
'TRIM',
|
|
||||||
'TRUE',
|
|
||||||
'TYPE',
|
|
||||||
'UNCOMMITTED',
|
|
||||||
'UNION',
|
|
||||||
'UNIQUE',
|
|
||||||
'UNKNOWN',
|
|
||||||
'UPDATE',
|
|
||||||
'UPDATING',
|
|
||||||
'UPPER',
|
|
||||||
'USAGE',
|
|
||||||
'USER',
|
|
||||||
'USING',
|
|
||||||
'VALUE',
|
|
||||||
'VALUES',
|
|
||||||
'VARCHAR',
|
|
||||||
'VARIABLE',
|
|
||||||
'VARYING',
|
|
||||||
'VERSION',
|
|
||||||
'VIEW',
|
|
||||||
'WAIT',
|
|
||||||
'WEEKDAY',
|
|
||||||
'WHEN',
|
|
||||||
'WHENEVER',
|
|
||||||
'WHERE',
|
|
||||||
'WHILE',
|
|
||||||
'WITH',
|
|
||||||
'WORK',
|
|
||||||
'WRITE',
|
|
||||||
'YEAR',
|
|
||||||
'YEARDAY',
|
|
||||||
'ZONE',
|
|
||||||
);
|
|
||||||
// }}}
|
|
|
@ -1,260 +0,0 @@
|
||||||
<?php /* vim: se et ts=4 sw=4 sts=4 fdm=marker tw=80: */
|
|
||||||
/**
|
|
||||||
* Copyright (c) 1998-2010 Manuel Lemos, Tomas V.V.Cox,
|
|
||||||
* Stig. S. Bakken, Lukas Smith, Igor Feghali
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* MDB2_Schema enables users to maintain RDBMS independant schema files
|
|
||||||
* in XML that can be used to manipulate both data and database schemas
|
|
||||||
* This LICENSE is in the BSD license style.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,
|
|
||||||
* Lukas Smith, Igor Feghali nor the names of his contributors may be
|
|
||||||
* used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* REGENTS 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.
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* @category Database
|
|
||||||
* @package MDB2_Schema
|
|
||||||
* @author David Coallier <davidc@php.net>
|
|
||||||
* @license BSD http://www.opensource.org/licenses/bsd-license.php
|
|
||||||
* @version SVN: $Id$
|
|
||||||
* @link http://pear.php.net/packages/MDB2_Schema
|
|
||||||
*/
|
|
||||||
|
|
||||||
// {{{ $GLOBALS['_MDB2_Schema_Reserved']['mssql']
|
|
||||||
/**
|
|
||||||
* Has a list of all the reserved words for mssql.
|
|
||||||
*
|
|
||||||
* @package MDB2_Schema
|
|
||||||
* @category Database
|
|
||||||
* @access protected
|
|
||||||
* @author David Coallier <davidc@php.net>
|
|
||||||
*/
|
|
||||||
$GLOBALS['_MDB2_Schema_Reserved']['mssql'] = array(
|
|
||||||
'ADD',
|
|
||||||
'CURRENT_TIMESTAMP',
|
|
||||||
'GROUP',
|
|
||||||
'OPENQUERY',
|
|
||||||
'SERIALIZABLE',
|
|
||||||
'ALL',
|
|
||||||
'CURRENT_USER',
|
|
||||||
'HAVING',
|
|
||||||
'OPENROWSET',
|
|
||||||
'SESSION_USER',
|
|
||||||
'ALTER',
|
|
||||||
'CURSOR',
|
|
||||||
'HOLDLOCK',
|
|
||||||
'OPTION',
|
|
||||||
'SET',
|
|
||||||
'AND',
|
|
||||||
'DATABASE',
|
|
||||||
'IDENTITY',
|
|
||||||
'OR',
|
|
||||||
'SETUSER',
|
|
||||||
'ANY',
|
|
||||||
'DBCC',
|
|
||||||
'IDENTITYCOL',
|
|
||||||
'ORDER',
|
|
||||||
'SHUTDOWN',
|
|
||||||
'AS',
|
|
||||||
'DEALLOCATE',
|
|
||||||
'IDENTITY_INSERT',
|
|
||||||
'OUTER',
|
|
||||||
'SOME',
|
|
||||||
'ASC',
|
|
||||||
'DECLARE',
|
|
||||||
'IF',
|
|
||||||
'OVER',
|
|
||||||
'STATISTICS',
|
|
||||||
'AUTHORIZATION',
|
|
||||||
'DEFAULT',
|
|
||||||
'IN',
|
|
||||||
'PERCENT',
|
|
||||||
'SUM',
|
|
||||||
'AVG',
|
|
||||||
'DELETE',
|
|
||||||
'INDEX',
|
|
||||||
'PERM',
|
|
||||||
'SYSTEM_USER',
|
|
||||||
'BACKUP',
|
|
||||||
'DENY',
|
|
||||||
'INNER',
|
|
||||||
'PERMANENT',
|
|
||||||
'TABLE',
|
|
||||||
'BEGIN',
|
|
||||||
'DESC',
|
|
||||||
'INSERT',
|
|
||||||
'PIPE',
|
|
||||||
'TAPE',
|
|
||||||
'BETWEEN',
|
|
||||||
'DISK',
|
|
||||||
'INTERSECT',
|
|
||||||
'PLAN',
|
|
||||||
'TEMP',
|
|
||||||
'BREAK',
|
|
||||||
'DISTINCT',
|
|
||||||
'INTO',
|
|
||||||
'PRECISION',
|
|
||||||
'TEMPORARY',
|
|
||||||
'BROWSE',
|
|
||||||
'DISTRIBUTED',
|
|
||||||
'IS',
|
|
||||||
'PREPARE',
|
|
||||||
'TEXTSIZE',
|
|
||||||
'BULK',
|
|
||||||
'DOUBLE',
|
|
||||||
'ISOLATION',
|
|
||||||
'PRIMARY',
|
|
||||||
'THEN',
|
|
||||||
'BY',
|
|
||||||
'DROP',
|
|
||||||
'JOIN',
|
|
||||||
'PRINT',
|
|
||||||
'TO',
|
|
||||||
'CASCADE',
|
|
||||||
'DUMMY',
|
|
||||||
'KEY',
|
|
||||||
'PRIVILEGES',
|
|
||||||
'TOP',
|
|
||||||
'CASE',
|
|
||||||
'DUMP',
|
|
||||||
'KILL',
|
|
||||||
'PROC',
|
|
||||||
'TRAN',
|
|
||||||
'CHECK',
|
|
||||||
'ELSE',
|
|
||||||
'LEFT',
|
|
||||||
'PROCEDURE',
|
|
||||||
'TRANSACTION',
|
|
||||||
'CHECKPOINT',
|
|
||||||
'END',
|
|
||||||
'LEVEL',
|
|
||||||
'PROCESSEXIT',
|
|
||||||
'TRIGGER',
|
|
||||||
'CLOSE',
|
|
||||||
'ERRLVL',
|
|
||||||
'LIKE',
|
|
||||||
'PUBLIC',
|
|
||||||
'TRUNCATE',
|
|
||||||
'CLUSTERED',
|
|
||||||
'ERROREXIT',
|
|
||||||
'LINENO',
|
|
||||||
'RAISERROR',
|
|
||||||
'TSEQUAL',
|
|
||||||
'COALESCE',
|
|
||||||
'ESCAPE',
|
|
||||||
'LOAD',
|
|
||||||
'READ',
|
|
||||||
'UNCOMMITTED',
|
|
||||||
'COLUMN',
|
|
||||||
'EXCEPT',
|
|
||||||
'MAX',
|
|
||||||
'READTEXT',
|
|
||||||
'UNION',
|
|
||||||
'COMMIT',
|
|
||||||
'EXEC',
|
|
||||||
'MIN',
|
|
||||||
'RECONFIGURE',
|
|
||||||
'UNIQUE',
|
|
||||||
'COMMITTED',
|
|
||||||
'EXECUTE',
|
|
||||||
'MIRROREXIT',
|
|
||||||
'REFERENCES',
|
|
||||||
'UPDATE',
|
|
||||||
'COMPUTE',
|
|
||||||
'EXISTS',
|
|
||||||
'NATIONAL',
|
|
||||||
'REPEATABLE',
|
|
||||||
'UPDATETEXT',
|
|
||||||
'CONFIRM',
|
|
||||||
'EXIT',
|
|
||||||
'NOCHECK',
|
|
||||||
'REPLICATION',
|
|
||||||
'USE',
|
|
||||||
'CONSTRAINT',
|
|
||||||
'FETCH',
|
|
||||||
'NONCLUSTERED',
|
|
||||||
'RESTORE',
|
|
||||||
'USER',
|
|
||||||
'CONTAINS',
|
|
||||||
'FILE',
|
|
||||||
'NOT',
|
|
||||||
'RESTRICT',
|
|
||||||
'VALUES',
|
|
||||||
'CONTAINSTABLE',
|
|
||||||
'FILLFACTOR',
|
|
||||||
'NULL',
|
|
||||||
'RETURN',
|
|
||||||
'VARYING',
|
|
||||||
'CONTINUE',
|
|
||||||
'FLOPPY',
|
|
||||||
'NULLIF',
|
|
||||||
'REVOKE',
|
|
||||||
'VIEW',
|
|
||||||
'CONTROLROW',
|
|
||||||
'FOR',
|
|
||||||
'OF',
|
|
||||||
'RIGHT',
|
|
||||||
'WAITFOR',
|
|
||||||
'CONVERT',
|
|
||||||
'FOREIGN',
|
|
||||||
'OFF',
|
|
||||||
'ROLLBACK',
|
|
||||||
'WHEN',
|
|
||||||
'COUNT',
|
|
||||||
'FREETEXT',
|
|
||||||
'OFFSETS',
|
|
||||||
'ROWCOUNT',
|
|
||||||
'WHERE',
|
|
||||||
'CREATE',
|
|
||||||
'FREETEXTTABLE',
|
|
||||||
'ON',
|
|
||||||
'ROWGUIDCOL',
|
|
||||||
'WHILE',
|
|
||||||
'CROSS',
|
|
||||||
'FROM',
|
|
||||||
'ONCE',
|
|
||||||
'RULE',
|
|
||||||
'WITH',
|
|
||||||
'CURRENT',
|
|
||||||
'FULL',
|
|
||||||
'ONLY',
|
|
||||||
'SAVE',
|
|
||||||
'WORK',
|
|
||||||
'CURRENT_DATE',
|
|
||||||
'GOTO',
|
|
||||||
'OPEN',
|
|
||||||
'SCHEMA',
|
|
||||||
'WRITETEXT',
|
|
||||||
'CURRENT_TIME',
|
|
||||||
'GRANT',
|
|
||||||
'OPENDATASOURCE',
|
|
||||||
'SELECT',
|
|
||||||
);
|
|
||||||
//}}}
|
|
|
@ -1,285 +0,0 @@
|
||||||
<?php /* vim: se et ts=4 sw=4 sts=4 fdm=marker tw=80: */
|
|
||||||
/**
|
|
||||||
* Copyright (c) 1998-2010 Manuel Lemos, Tomas V.V.Cox,
|
|
||||||
* Stig. S. Bakken, Lukas Smith, Igor Feghali
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* MDB2_Schema enables users to maintain RDBMS independant schema files
|
|
||||||
* in XML that can be used to manipulate both data and database schemas
|
|
||||||
* This LICENSE is in the BSD license style.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,
|
|
||||||
* Lukas Smith, Igor Feghali nor the names of his contributors may be
|
|
||||||
* used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* REGENTS 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.
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* @category Database
|
|
||||||
* @package MDB2_Schema
|
|
||||||
* @author David Coallier <davidc@php.net>
|
|
||||||
* @license BSD http://www.opensource.org/licenses/bsd-license.php
|
|
||||||
* @version SVN: $Id$
|
|
||||||
* @link http://pear.php.net/packages/MDB2_Schema
|
|
||||||
*/
|
|
||||||
|
|
||||||
// {{{ $GLOBALS['_MDB2_Schema_Reserved']['mysql']
|
|
||||||
/**
|
|
||||||
* Has a list of reserved words of mysql
|
|
||||||
*
|
|
||||||
* @package MDB2_Schema
|
|
||||||
* @category Database
|
|
||||||
* @access protected
|
|
||||||
* @author David Coalier <davidc@php.net>
|
|
||||||
*/
|
|
||||||
$GLOBALS['_MDB2_Schema_Reserved']['mysql'] = array(
|
|
||||||
'ADD',
|
|
||||||
'ALL',
|
|
||||||
'ALTER',
|
|
||||||
'ANALYZE',
|
|
||||||
'AND',
|
|
||||||
'AS',
|
|
||||||
'ASC',
|
|
||||||
'ASENSITIVE',
|
|
||||||
'BEFORE',
|
|
||||||
'BETWEEN',
|
|
||||||
'BIGINT',
|
|
||||||
'BINARY',
|
|
||||||
'BLOB',
|
|
||||||
'BOTH',
|
|
||||||
'BY',
|
|
||||||
'CALL',
|
|
||||||
'CASCADE',
|
|
||||||
'CASE',
|
|
||||||
'CHANGE',
|
|
||||||
'CHAR',
|
|
||||||
'CHARACTER',
|
|
||||||
'CHECK',
|
|
||||||
'COLLATE',
|
|
||||||
'COLUMN',
|
|
||||||
'CONDITION',
|
|
||||||
'CONNECTION',
|
|
||||||
'CONSTRAINT',
|
|
||||||
'CONTINUE',
|
|
||||||
'CONVERT',
|
|
||||||
'CREATE',
|
|
||||||
'CROSS',
|
|
||||||
'CURRENT_DATE',
|
|
||||||
'CURRENT_TIME',
|
|
||||||
'CURRENT_TIMESTAMP',
|
|
||||||
'CURRENT_USER',
|
|
||||||
'CURSOR',
|
|
||||||
'DATABASE',
|
|
||||||
'DATABASES',
|
|
||||||
'DAY_HOUR',
|
|
||||||
'DAY_MICROSECOND',
|
|
||||||
'DAY_MINUTE',
|
|
||||||
'DAY_SECOND',
|
|
||||||
'DEC',
|
|
||||||
'DECIMAL',
|
|
||||||
'DECLARE',
|
|
||||||
'DEFAULT',
|
|
||||||
'DELAYED',
|
|
||||||
'DELETE',
|
|
||||||
'DESC',
|
|
||||||
'DESCRIBE',
|
|
||||||
'DETERMINISTIC',
|
|
||||||
'DISTINCT',
|
|
||||||
'DISTINCTROW',
|
|
||||||
'DIV',
|
|
||||||
'DOUBLE',
|
|
||||||
'DROP',
|
|
||||||
'DUAL',
|
|
||||||
'EACH',
|
|
||||||
'ELSE',
|
|
||||||
'ELSEIF',
|
|
||||||
'ENCLOSED',
|
|
||||||
'ESCAPED',
|
|
||||||
'EXISTS',
|
|
||||||
'EXIT',
|
|
||||||
'EXPLAIN',
|
|
||||||
'FALSE',
|
|
||||||
'FETCH',
|
|
||||||
'FLOAT',
|
|
||||||
'FLOAT4',
|
|
||||||
'FLOAT8',
|
|
||||||
'FOR',
|
|
||||||
'FORCE',
|
|
||||||
'FOREIGN',
|
|
||||||
'FROM',
|
|
||||||
'FULLTEXT',
|
|
||||||
'GOTO',
|
|
||||||
'GRANT',
|
|
||||||
'GROUP',
|
|
||||||
'HAVING',
|
|
||||||
'HIGH_PRIORITY',
|
|
||||||
'HOUR_MICROSECOND',
|
|
||||||
'HOUR_MINUTE',
|
|
||||||
'HOUR_SECOND',
|
|
||||||
'IF',
|
|
||||||
'IGNORE',
|
|
||||||
'IN',
|
|
||||||
'INDEX',
|
|
||||||
'INFILE',
|
|
||||||
'INNER',
|
|
||||||
'INOUT',
|
|
||||||
'INSENSITIVE',
|
|
||||||
'INSERT',
|
|
||||||
'INT',
|
|
||||||
'INT1',
|
|
||||||
'INT2',
|
|
||||||
'INT3',
|
|
||||||
'INT4',
|
|
||||||
'INT8',
|
|
||||||
'INTEGER',
|
|
||||||
'INTERVAL',
|
|
||||||
'INTO',
|
|
||||||
'IS',
|
|
||||||
'ITERATE',
|
|
||||||
'JOIN',
|
|
||||||
'KEY',
|
|
||||||
'KEYS',
|
|
||||||
'KILL',
|
|
||||||
'LABEL',
|
|
||||||
'LEADING',
|
|
||||||
'LEAVE',
|
|
||||||
'LEFT',
|
|
||||||
'LIKE',
|
|
||||||
'LIMIT',
|
|
||||||
'LINES',
|
|
||||||
'LOAD',
|
|
||||||
'LOCALTIME',
|
|
||||||
'LOCALTIMESTAMP',
|
|
||||||
'LOCK',
|
|
||||||
'LONG',
|
|
||||||
'LONGBLOB',
|
|
||||||
'LONGTEXT',
|
|
||||||
'LOOP',
|
|
||||||
'LOW_PRIORITY',
|
|
||||||
'MATCH',
|
|
||||||
'MEDIUMBLOB',
|
|
||||||
'MEDIUMINT',
|
|
||||||
'MEDIUMTEXT',
|
|
||||||
'MIDDLEINT',
|
|
||||||
'MINUTE_MICROSECOND',
|
|
||||||
'MINUTE_SECOND',
|
|
||||||
'MOD',
|
|
||||||
'MODIFIES',
|
|
||||||
'NATURAL',
|
|
||||||
'NOT',
|
|
||||||
'NO_WRITE_TO_BINLOG',
|
|
||||||
'NULL',
|
|
||||||
'NUMERIC',
|
|
||||||
'ON',
|
|
||||||
'OPTIMIZE',
|
|
||||||
'OPTION',
|
|
||||||
'OPTIONALLY',
|
|
||||||
'OR',
|
|
||||||
'ORDER',
|
|
||||||
'OUT',
|
|
||||||
'OUTER',
|
|
||||||
'OUTFILE',
|
|
||||||
'PRECISION',
|
|
||||||
'PRIMARY',
|
|
||||||
'PROCEDURE',
|
|
||||||
'PURGE',
|
|
||||||
'RAID0',
|
|
||||||
'READ',
|
|
||||||
'READS',
|
|
||||||
'REAL',
|
|
||||||
'REFERENCES',
|
|
||||||
'REGEXP',
|
|
||||||
'RELEASE',
|
|
||||||
'RENAME',
|
|
||||||
'REPEAT',
|
|
||||||
'REPLACE',
|
|
||||||
'REQUIRE',
|
|
||||||
'RESTRICT',
|
|
||||||
'RETURN',
|
|
||||||
'REVOKE',
|
|
||||||
'RIGHT',
|
|
||||||
'RLIKE',
|
|
||||||
'SCHEMA',
|
|
||||||
'SCHEMAS',
|
|
||||||
'SECOND_MICROSECOND',
|
|
||||||
'SELECT',
|
|
||||||
'SENSITIVE',
|
|
||||||
'SEPARATOR',
|
|
||||||
'SET',
|
|
||||||
'SHOW',
|
|
||||||
'SMALLINT',
|
|
||||||
'SONAME',
|
|
||||||
'SPATIAL',
|
|
||||||
'SPECIFIC',
|
|
||||||
'SQL',
|
|
||||||
'SQLEXCEPTION',
|
|
||||||
'SQLSTATE',
|
|
||||||
'SQLWARNING',
|
|
||||||
'SQL_BIG_RESULT',
|
|
||||||
'SQL_CALC_FOUND_ROWS',
|
|
||||||
'SQL_SMALL_RESULT',
|
|
||||||
'SSL',
|
|
||||||
'STARTING',
|
|
||||||
'STRAIGHT_JOIN',
|
|
||||||
'TABLE',
|
|
||||||
'TERMINATED',
|
|
||||||
'THEN',
|
|
||||||
'TINYBLOB',
|
|
||||||
'TINYINT',
|
|
||||||
'TINYTEXT',
|
|
||||||
'TO',
|
|
||||||
'TRAILING',
|
|
||||||
'TRIGGER',
|
|
||||||
'TRUE',
|
|
||||||
'UNDO',
|
|
||||||
'UNION',
|
|
||||||
'UNIQUE',
|
|
||||||
'UNLOCK',
|
|
||||||
'UNSIGNED',
|
|
||||||
'UPDATE',
|
|
||||||
'USAGE',
|
|
||||||
'USE',
|
|
||||||
'USING',
|
|
||||||
'UTC_DATE',
|
|
||||||
'UTC_TIME',
|
|
||||||
'UTC_TIMESTAMP',
|
|
||||||
'VALUES',
|
|
||||||
'VARBINARY',
|
|
||||||
'VARCHAR',
|
|
||||||
'VARCHARACTER',
|
|
||||||
'VARYING',
|
|
||||||
'WHEN',
|
|
||||||
'WHERE',
|
|
||||||
'WHILE',
|
|
||||||
'WITH',
|
|
||||||
'WRITE',
|
|
||||||
'X509',
|
|
||||||
'XOR',
|
|
||||||
'YEAR_MONTH',
|
|
||||||
'ZEROFILL',
|
|
||||||
);
|
|
||||||
// }}}
|
|
|
@ -1,173 +0,0 @@
|
||||||
<?php /* vim: se et ts=4 sw=4 sts=4 fdm=marker tw=80: */
|
|
||||||
/**
|
|
||||||
* Copyright (c) 1998-2010 Manuel Lemos, Tomas V.V.Cox,
|
|
||||||
* Stig. S. Bakken, Lukas Smith, Igor Feghali
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* MDB2_Schema enables users to maintain RDBMS independant schema files
|
|
||||||
* in XML that can be used to manipulate both data and database schemas
|
|
||||||
* This LICENSE is in the BSD license style.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,
|
|
||||||
* Lukas Smith, Igor Feghali nor the names of his contributors may be
|
|
||||||
* used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* REGENTS 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.
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* @category Database
|
|
||||||
* @package MDB2_Schema
|
|
||||||
* @author David Coallier <davidc@php.net>
|
|
||||||
* @license BSD http://www.opensource.org/licenses/bsd-license.php
|
|
||||||
* @version SVN: $Id$
|
|
||||||
* @link http://pear.php.net/packages/MDB2_Schema
|
|
||||||
*/
|
|
||||||
|
|
||||||
// {{{ $GLOBALS['_MDB2_Schema_Reserved']['oci8']
|
|
||||||
/**
|
|
||||||
* Has a list of all the reserved words for oracle.
|
|
||||||
*
|
|
||||||
* @package MDB2_Schema
|
|
||||||
* @category Database
|
|
||||||
* @access protected
|
|
||||||
* @author David Coallier <davidc@php.net>
|
|
||||||
*/
|
|
||||||
$GLOBALS['_MDB2_Schema_Reserved']['oci8'] = array(
|
|
||||||
'ACCESS',
|
|
||||||
'ELSE',
|
|
||||||
'MODIFY',
|
|
||||||
'START',
|
|
||||||
'ADD',
|
|
||||||
'EXCLUSIVE',
|
|
||||||
'NOAUDIT',
|
|
||||||
'SELECT',
|
|
||||||
'ALL',
|
|
||||||
'EXISTS',
|
|
||||||
'NOCOMPRESS',
|
|
||||||
'SESSION',
|
|
||||||
'ALTER',
|
|
||||||
'FILE',
|
|
||||||
'NOT',
|
|
||||||
'SET',
|
|
||||||
'AND',
|
|
||||||
'FLOAT',
|
|
||||||
'NOTFOUND ',
|
|
||||||
'SHARE',
|
|
||||||
'ANY',
|
|
||||||
'FOR',
|
|
||||||
'NOWAIT',
|
|
||||||
'SIZE',
|
|
||||||
'ARRAYLEN',
|
|
||||||
'FROM',
|
|
||||||
'NULL',
|
|
||||||
'SMALLINT',
|
|
||||||
'AS',
|
|
||||||
'GRANT',
|
|
||||||
'NUMBER',
|
|
||||||
'SQLBUF',
|
|
||||||
'ASC',
|
|
||||||
'GROUP',
|
|
||||||
'OF',
|
|
||||||
'SUCCESSFUL',
|
|
||||||
'AUDIT',
|
|
||||||
'HAVING',
|
|
||||||
'OFFLINE ',
|
|
||||||
'SYNONYM',
|
|
||||||
'BETWEEN',
|
|
||||||
'IDENTIFIED',
|
|
||||||
'ON',
|
|
||||||
'SYSDATE',
|
|
||||||
'BY',
|
|
||||||
'IMMEDIATE',
|
|
||||||
'ONLINE',
|
|
||||||
'TABLE',
|
|
||||||
'CHAR',
|
|
||||||
'IN',
|
|
||||||
'OPTION',
|
|
||||||
'THEN',
|
|
||||||
'CHECK',
|
|
||||||
'INCREMENT',
|
|
||||||
'OR',
|
|
||||||
'TO',
|
|
||||||
'CLUSTER',
|
|
||||||
'INDEX',
|
|
||||||
'ORDER',
|
|
||||||
'TRIGGER',
|
|
||||||
'COLUMN',
|
|
||||||
'INITIAL',
|
|
||||||
'PCTFREE',
|
|
||||||
'UID',
|
|
||||||
'COMMENT',
|
|
||||||
'INSERT',
|
|
||||||
'PRIOR',
|
|
||||||
'UNION',
|
|
||||||
'COMPRESS',
|
|
||||||
'INTEGER',
|
|
||||||
'PRIVILEGES',
|
|
||||||
'UNIQUE',
|
|
||||||
'CONNECT',
|
|
||||||
'INTERSECT',
|
|
||||||
'PUBLIC',
|
|
||||||
'UPDATE',
|
|
||||||
'CREATE',
|
|
||||||
'INTO',
|
|
||||||
'RAW',
|
|
||||||
'USER',
|
|
||||||
'CURRENT',
|
|
||||||
'IS',
|
|
||||||
'RENAME',
|
|
||||||
'VALIDATE',
|
|
||||||
'DATE',
|
|
||||||
'LEVEL',
|
|
||||||
'RESOURCE',
|
|
||||||
'VALUES',
|
|
||||||
'DECIMAL',
|
|
||||||
'LIKE',
|
|
||||||
'REVOKE',
|
|
||||||
'VARCHAR',
|
|
||||||
'DEFAULT',
|
|
||||||
'LOCK',
|
|
||||||
'ROW',
|
|
||||||
'VARCHAR2',
|
|
||||||
'DELETE',
|
|
||||||
'LONG',
|
|
||||||
'ROWID',
|
|
||||||
'VIEW',
|
|
||||||
'DESC',
|
|
||||||
'MAXEXTENTS',
|
|
||||||
'ROWLABEL',
|
|
||||||
'WHENEVER',
|
|
||||||
'DISTINCT',
|
|
||||||
'MINUS',
|
|
||||||
'ROWNUM',
|
|
||||||
'WHERE',
|
|
||||||
'DROP',
|
|
||||||
'MODE',
|
|
||||||
'ROWS',
|
|
||||||
'WITH',
|
|
||||||
);
|
|
||||||
// }}}
|
|
|
@ -1,148 +0,0 @@
|
||||||
<?php /* vim: se et ts=4 sw=4 sts=4 fdm=marker tw=80: */
|
|
||||||
/**
|
|
||||||
* Copyright (c) 1998-2010 Manuel Lemos, Tomas V.V.Cox,
|
|
||||||
* Stig. S. Bakken, Lukas Smith, Igor Feghali
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* MDB2_Schema enables users to maintain RDBMS independant schema files
|
|
||||||
* in XML that can be used to manipulate both data and database schemas
|
|
||||||
* This LICENSE is in the BSD license style.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,
|
|
||||||
* Lukas Smith, Igor Feghali nor the names of his contributors may be
|
|
||||||
* used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* REGENTS 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.
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* @category Database
|
|
||||||
* @package MDB2_Schema
|
|
||||||
* @author Marcelo Santos Araujo <msaraujo@php.net>
|
|
||||||
* @license BSD http://www.opensource.org/licenses/bsd-license.php
|
|
||||||
* @version SVN: $Id$
|
|
||||||
* @link http://pear.php.net/packages/MDB2_Schema
|
|
||||||
*/
|
|
||||||
|
|
||||||
// {{{ $GLOBALS['_MDB2_Schema_Reserved']['pgsql']
|
|
||||||
/**
|
|
||||||
* Has a list of reserved words of pgsql
|
|
||||||
*
|
|
||||||
* @package MDB2_Schema
|
|
||||||
* @category Database
|
|
||||||
* @access protected
|
|
||||||
* @author Marcelo Santos Araujo <msaraujo@php.net>
|
|
||||||
*/
|
|
||||||
$GLOBALS['_MDB2_Schema_Reserved']['pgsql'] = array(
|
|
||||||
'ALL',
|
|
||||||
'ANALYSE',
|
|
||||||
'ANALYZE',
|
|
||||||
'AND',
|
|
||||||
'ANY',
|
|
||||||
'AS',
|
|
||||||
'ASC',
|
|
||||||
'AUTHORIZATION',
|
|
||||||
'BETWEEN',
|
|
||||||
'BINARY',
|
|
||||||
'BOTH',
|
|
||||||
'CASE',
|
|
||||||
'CAST',
|
|
||||||
'CHECK',
|
|
||||||
'COLLATE',
|
|
||||||
'COLUMN',
|
|
||||||
'CONSTRAINT',
|
|
||||||
'CREATE',
|
|
||||||
'CURRENT_DATE',
|
|
||||||
'CURRENT_TIME',
|
|
||||||
'CURRENT_TIMESTAMP',
|
|
||||||
'CURRENT_USER',
|
|
||||||
'DEFAULT',
|
|
||||||
'DEFERRABLE',
|
|
||||||
'DESC',
|
|
||||||
'DISTINCT',
|
|
||||||
'DO',
|
|
||||||
'ELSE',
|
|
||||||
'END',
|
|
||||||
'EXCEPT',
|
|
||||||
'FALSE',
|
|
||||||
'FOR',
|
|
||||||
'FOREIGN',
|
|
||||||
'FREEZE',
|
|
||||||
'FROM',
|
|
||||||
'FULL',
|
|
||||||
'GRANT',
|
|
||||||
'GROUP',
|
|
||||||
'HAVING',
|
|
||||||
'ILIKE',
|
|
||||||
'IN',
|
|
||||||
'INITIALLY',
|
|
||||||
'INNER',
|
|
||||||
'INTERSECT',
|
|
||||||
'INTO',
|
|
||||||
'IS',
|
|
||||||
'ISNULL',
|
|
||||||
'JOIN',
|
|
||||||
'LEADING',
|
|
||||||
'LEFT',
|
|
||||||
'LIKE',
|
|
||||||
'LIMIT',
|
|
||||||
'LOCALTIME',
|
|
||||||
'LOCALTIMESTAMP',
|
|
||||||
'NATURAL',
|
|
||||||
'NEW',
|
|
||||||
'NOT',
|
|
||||||
'NOTNULL',
|
|
||||||
'NULL',
|
|
||||||
'OFF',
|
|
||||||
'OFFSET',
|
|
||||||
'OLD',
|
|
||||||
'ON',
|
|
||||||
'ONLY',
|
|
||||||
'OR',
|
|
||||||
'ORDER',
|
|
||||||
'OUTER',
|
|
||||||
'OVERLAPS',
|
|
||||||
'PLACING',
|
|
||||||
'PRIMARY',
|
|
||||||
'REFERENCES',
|
|
||||||
'SELECT',
|
|
||||||
'SESSION_USER',
|
|
||||||
'SIMILAR',
|
|
||||||
'SOME',
|
|
||||||
'TABLE',
|
|
||||||
'THEN',
|
|
||||||
'TO',
|
|
||||||
'TRAILING',
|
|
||||||
'TRUE',
|
|
||||||
'UNION',
|
|
||||||
'UNIQUE',
|
|
||||||
'USER',
|
|
||||||
'USING',
|
|
||||||
'VERBOSE',
|
|
||||||
'WHEN',
|
|
||||||
'WHERE'
|
|
||||||
);
|
|
||||||
// }}}
|
|
|
@ -1,583 +0,0 @@
|
||||||
<?php /* vim: se et ts=4 sw=4 sts=4 fdm=marker tw=80: */
|
|
||||||
/**
|
|
||||||
* Copyright (c) 1998-2010 Manuel Lemos, Tomas V.V.Cox,
|
|
||||||
* Stig. S. Bakken, Lukas Smith, Igor Feghali
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* MDB2_Schema enables users to maintain RDBMS independant schema files
|
|
||||||
* in XML that can be used to manipulate both data and database schemas
|
|
||||||
* This LICENSE is in the BSD license style.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,
|
|
||||||
* Lukas Smith, Igor Feghali nor the names of his contributors may be
|
|
||||||
* used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* REGENTS 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.
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* @category Database
|
|
||||||
* @package MDB2_Schema
|
|
||||||
* @author Christian Weiske <cweiske@php.net>
|
|
||||||
* @license BSD http://www.opensource.org/licenses/bsd-license.php
|
|
||||||
* @version SVN: $Id$
|
|
||||||
* @link http://pear.php.net/packages/MDB2_Schema
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once 'MDB2/Schema.php';
|
|
||||||
require_once 'MDB2/Schema/Tool/ParameterException.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Command line tool to work with database schemas
|
|
||||||
*
|
|
||||||
* Functionality:
|
|
||||||
* - dump a database schema to stdout
|
|
||||||
* - import schema into database
|
|
||||||
* - create a diff between two schemas
|
|
||||||
* - apply diff to database
|
|
||||||
*
|
|
||||||
* @category Database
|
|
||||||
* @package MDB2_Schema
|
|
||||||
* @author Christian Weiske <cweiske@php.net>
|
|
||||||
* @license BSD http://www.opensource.org/licenses/bsd-license.php
|
|
||||||
* @link http://pear.php.net/packages/MDB2_Schema
|
|
||||||
*/
|
|
||||||
class MDB2_Schema_Tool
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the schema tool
|
|
||||||
*
|
|
||||||
* @param array $args Array of command line arguments
|
|
||||||
*/
|
|
||||||
public function __construct($args)
|
|
||||||
{
|
|
||||||
$strAction = $this->getAction($args);
|
|
||||||
try {
|
|
||||||
$this->{'do' . ucfirst($strAction)}($args);
|
|
||||||
} catch (MDB2_Schema_Tool_ParameterException $e) {
|
|
||||||
$this->{'doHelp' . ucfirst($strAction)}($e->getMessage());
|
|
||||||
}
|
|
||||||
}//public function __construct($args)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs the tool with command line arguments
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public static function run()
|
|
||||||
{
|
|
||||||
$args = $GLOBALS['argv'];
|
|
||||||
array_shift($args);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$tool = new MDB2_Schema_Tool($args);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
self::toStdErr($e->getMessage() . "\n");
|
|
||||||
}
|
|
||||||
}//public static function run()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the first parameter from the argument array and
|
|
||||||
* returns the action.
|
|
||||||
*
|
|
||||||
* @param array &$args Command line parameters
|
|
||||||
*
|
|
||||||
* @return string Action to execute
|
|
||||||
*/
|
|
||||||
protected function getAction(&$args)
|
|
||||||
{
|
|
||||||
if (count($args) == 0) {
|
|
||||||
return 'help';
|
|
||||||
}
|
|
||||||
$arg = array_shift($args);
|
|
||||||
switch ($arg) {
|
|
||||||
case 'h':
|
|
||||||
case 'help':
|
|
||||||
case '-h':
|
|
||||||
case '--help':
|
|
||||||
return 'help';
|
|
||||||
case 'd':
|
|
||||||
case 'dump':
|
|
||||||
case '-d':
|
|
||||||
case '--dump':
|
|
||||||
return 'dump';
|
|
||||||
case 'l':
|
|
||||||
case 'load':
|
|
||||||
case '-l':
|
|
||||||
case '--load':
|
|
||||||
return 'load';
|
|
||||||
case 'i':
|
|
||||||
case 'diff':
|
|
||||||
case '-i':
|
|
||||||
case '--diff':
|
|
||||||
return 'diff';
|
|
||||||
case 'a':
|
|
||||||
case 'apply':
|
|
||||||
case '-a':
|
|
||||||
case '--apply':
|
|
||||||
return 'apply';
|
|
||||||
case 'n':
|
|
||||||
case 'init':
|
|
||||||
case '-i':
|
|
||||||
case '--init':
|
|
||||||
return 'init';
|
|
||||||
default:
|
|
||||||
throw new MDB2_Schema_Tool_ParameterException(
|
|
||||||
"Unknown mode \"$arg\""
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}//protected function getAction(&$args)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the message to stderr
|
|
||||||
*
|
|
||||||
* @param string $msg Message to print
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected static function toStdErr($msg)
|
|
||||||
{
|
|
||||||
file_put_contents('php://stderr', $msg);
|
|
||||||
}//protected static function toStdErr($msg)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays generic help to stdout
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function doHelp()
|
|
||||||
{
|
|
||||||
self::toStdErr(
|
|
||||||
<<<EOH
|
|
||||||
Usage: mdb2_schematool mode parameters
|
|
||||||
|
|
||||||
Works with database schemas
|
|
||||||
|
|
||||||
mode: (- and -- are optional)
|
|
||||||
h, help Show this help screen
|
|
||||||
d, dump Dump a schema to stdout
|
|
||||||
l, load Load a schema into database
|
|
||||||
i, diff Create a diff between two schemas and dump it to stdout
|
|
||||||
a, apply Apply a diff to a database
|
|
||||||
n, init Initialize a database with data
|
|
||||||
|
|
||||||
EOH
|
|
||||||
);
|
|
||||||
}//protected function doHelp()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the help screen for "dump" command
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function doHelpDump()
|
|
||||||
{
|
|
||||||
self::toStdErr(
|
|
||||||
<<<EOH
|
|
||||||
Usage: mdb2_schematool dump [all|data|schema] [-p] DSN
|
|
||||||
|
|
||||||
Dumps a database schema to stdout
|
|
||||||
|
|
||||||
If dump type is not specified, defaults to "schema".
|
|
||||||
|
|
||||||
DSN: Data source name in the form of
|
|
||||||
driver://user:password@host/database
|
|
||||||
|
|
||||||
User and password may be omitted.
|
|
||||||
Using -p reads password from stdin which is more secure than passing it in the
|
|
||||||
parameter.
|
|
||||||
|
|
||||||
EOH
|
|
||||||
);
|
|
||||||
}//protected function doHelpDump()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the help screen for "init" command
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function doHelpInit()
|
|
||||||
{
|
|
||||||
self::toStdErr(
|
|
||||||
<<<EOH
|
|
||||||
Usage: mdb2_schematool init source [-p] destination
|
|
||||||
|
|
||||||
Initializes a database with data
|
|
||||||
(Inserts data on a previous created database at destination)
|
|
||||||
|
|
||||||
source should be a schema file containing data,
|
|
||||||
destination should be a DSN
|
|
||||||
|
|
||||||
DSN: Data source name in the form of
|
|
||||||
driver://user:password@host/database
|
|
||||||
|
|
||||||
User and password may be omitted.
|
|
||||||
Using -p reads password from stdin which is more secure than passing it in the
|
|
||||||
parameter.
|
|
||||||
|
|
||||||
EOH
|
|
||||||
);
|
|
||||||
}//protected function doHelpInit()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the help screen for "load" command
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function doHelpLoad()
|
|
||||||
{
|
|
||||||
self::toStdErr(
|
|
||||||
<<<EOH
|
|
||||||
Usage: mdb2_schematool load [-p] source [-p] destination
|
|
||||||
|
|
||||||
Loads a database schema from source to destination
|
|
||||||
(Creates the database schema at destination)
|
|
||||||
|
|
||||||
source can be a DSN or a schema file,
|
|
||||||
destination should be a DSN
|
|
||||||
|
|
||||||
DSN: Data source name in the form of
|
|
||||||
driver://user:password@host/database
|
|
||||||
|
|
||||||
User and password may be omitted.
|
|
||||||
Using -p reads password from stdin which is more secure than passing it in the
|
|
||||||
parameter.
|
|
||||||
|
|
||||||
EOH
|
|
||||||
);
|
|
||||||
}//protected function doHelpLoad()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an array of options for MDB2_Schema constructor
|
|
||||||
*
|
|
||||||
* @return array Options for MDB2_Schema constructor
|
|
||||||
*/
|
|
||||||
protected function getSchemaOptions()
|
|
||||||
{
|
|
||||||
$options = array(
|
|
||||||
'log_line_break' => '<br>',
|
|
||||||
'idxname_format' => '%s',
|
|
||||||
'debug' => true,
|
|
||||||
'quote_identifier' => true,
|
|
||||||
'force_defaults' => false,
|
|
||||||
'portability' => true,
|
|
||||||
'use_transactions' => false,
|
|
||||||
);
|
|
||||||
return $options;
|
|
||||||
}//protected function getSchemaOptions()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the passed parameter is a PEAR_Error object
|
|
||||||
* and throws an exception in that case.
|
|
||||||
*
|
|
||||||
* @param mixed $object Some variable to check
|
|
||||||
* @param string $location Where the error occured
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function throwExceptionOnError($object, $location = '')
|
|
||||||
{
|
|
||||||
if (PEAR::isError($object)) {
|
|
||||||
//FIXME: exception class
|
|
||||||
//debug_print_backtrace();
|
|
||||||
throw new Exception('Error ' . $location
|
|
||||||
. "\n" . $object->getMessage()
|
|
||||||
. "\n" . $object->getUserInfo()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}//protected function throwExceptionOnError($object, $location = '')
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads a file or a dsn from the arguments
|
|
||||||
*
|
|
||||||
* @param array &$args Array of arguments to the program
|
|
||||||
*
|
|
||||||
* @return array Array of ('file'|'dsn', $value)
|
|
||||||
*/
|
|
||||||
protected function getFileOrDsn(&$args)
|
|
||||||
{
|
|
||||||
if (count($args) == 0) {
|
|
||||||
throw new MDB2_Schema_Tool_ParameterException(
|
|
||||||
'File or DSN expected'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$arg = array_shift($args);
|
|
||||||
if ($arg == '-p') {
|
|
||||||
$bAskPassword = true;
|
|
||||||
$arg = array_shift($args);
|
|
||||||
} else {
|
|
||||||
$bAskPassword = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strpos($arg, '://') === false) {
|
|
||||||
if (file_exists($arg)) {
|
|
||||||
//File
|
|
||||||
return array('file', $arg);
|
|
||||||
} else {
|
|
||||||
throw new Exception('Schema file does not exist');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//read password if necessary
|
|
||||||
if ($bAskPassword) {
|
|
||||||
$password = $this->readPasswordFromStdin($arg);
|
|
||||||
$arg = self::setPasswordIntoDsn($arg, $password);
|
|
||||||
self::toStdErr($arg);
|
|
||||||
}
|
|
||||||
return array('dsn', $arg);
|
|
||||||
}//protected function getFileOrDsn(&$args)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes a DSN data source name and integrates the given
|
|
||||||
* password into it.
|
|
||||||
*
|
|
||||||
* @param string $dsn Data source name
|
|
||||||
* @param string $password Password
|
|
||||||
*
|
|
||||||
* @return string DSN with password
|
|
||||||
*/
|
|
||||||
protected function setPasswordIntoDsn($dsn, $password)
|
|
||||||
{
|
|
||||||
//simple try to integrate password
|
|
||||||
if (strpos($dsn, '@') === false) {
|
|
||||||
//no @ -> no user and no password
|
|
||||||
return str_replace('://', '://:' . $password . '@', $dsn);
|
|
||||||
} else if (preg_match('|://[^:]+@|', $dsn)) {
|
|
||||||
//user only, no password
|
|
||||||
return str_replace('@', ':' . $password . '@', $dsn);
|
|
||||||
} else if (strpos($dsn, ':@') !== false) {
|
|
||||||
//abstract version
|
|
||||||
return str_replace(':@', ':' . $password . '@', $dsn);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $dsn;
|
|
||||||
}//protected function setPasswordIntoDsn($dsn, $password)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads a password from stdin
|
|
||||||
*
|
|
||||||
* @param string $dsn DSN name to put into the message
|
|
||||||
*
|
|
||||||
* @return string Password
|
|
||||||
*/
|
|
||||||
protected function readPasswordFromStdin($dsn)
|
|
||||||
{
|
|
||||||
$stdin = fopen('php://stdin', 'r');
|
|
||||||
self::toStdErr('Please insert password for ' . $dsn . "\n");
|
|
||||||
$password = '';
|
|
||||||
$breakme = false;
|
|
||||||
while (false !== ($char = fgetc($stdin))) {
|
|
||||||
if (ord($char) == 10 || $char == "\n" || $char == "\r") {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$password .= $char;
|
|
||||||
}
|
|
||||||
fclose($stdin);
|
|
||||||
|
|
||||||
return trim($password);
|
|
||||||
}//protected function readPasswordFromStdin()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a database schema dump and sends it to stdout
|
|
||||||
*
|
|
||||||
* @param array $args Command line arguments
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function doDump($args)
|
|
||||||
{
|
|
||||||
$dump_what = MDB2_SCHEMA_DUMP_STRUCTURE;
|
|
||||||
$arg = '';
|
|
||||||
if (count($args)) {
|
|
||||||
$arg = $args[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (strtolower($arg)) {
|
|
||||||
case 'all':
|
|
||||||
$dump_what = MDB2_SCHEMA_DUMP_ALL;
|
|
||||||
array_shift($args);
|
|
||||||
break;
|
|
||||||
case 'data':
|
|
||||||
$dump_what = MDB2_SCHEMA_DUMP_CONTENT;
|
|
||||||
array_shift($args);
|
|
||||||
break;
|
|
||||||
case 'schema':
|
|
||||||
array_shift($args);
|
|
||||||
}
|
|
||||||
|
|
||||||
list($type, $dsn) = $this->getFileOrDsn($args);
|
|
||||||
if ($type == 'file') {
|
|
||||||
throw new MDB2_Schema_Tool_ParameterException(
|
|
||||||
'Dumping a schema file as a schema file does not make much ' .
|
|
||||||
'sense'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$schema = MDB2_Schema::factory($dsn, $this->getSchemaOptions());
|
|
||||||
$this->throwExceptionOnError($schema);
|
|
||||||
|
|
||||||
$definition = $schema->getDefinitionFromDatabase();
|
|
||||||
$this->throwExceptionOnError($definition);
|
|
||||||
|
|
||||||
|
|
||||||
$dump_options = array(
|
|
||||||
'output_mode' => 'file',
|
|
||||||
'output' => 'php://stdout',
|
|
||||||
'end_of_line' => "\r\n"
|
|
||||||
);
|
|
||||||
$op = $schema->dumpDatabase(
|
|
||||||
$definition, $dump_options, $dump_what
|
|
||||||
);
|
|
||||||
$this->throwExceptionOnError($op);
|
|
||||||
|
|
||||||
$schema->disconnect();
|
|
||||||
}//protected function doDump($args)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads a database schema
|
|
||||||
*
|
|
||||||
* @param array $args Command line arguments
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function doLoad($args)
|
|
||||||
{
|
|
||||||
list($typeSource, $dsnSource) = $this->getFileOrDsn($args);
|
|
||||||
list($typeDest, $dsnDest) = $this->getFileOrDsn($args);
|
|
||||||
|
|
||||||
if ($typeDest == 'file') {
|
|
||||||
throw new MDB2_Schema_Tool_ParameterException(
|
|
||||||
'A schema can only be loaded into a database, not a file'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$schemaDest = MDB2_Schema::factory($dsnDest, $this->getSchemaOptions());
|
|
||||||
$this->throwExceptionOnError($schemaDest);
|
|
||||||
|
|
||||||
//load definition
|
|
||||||
if ($typeSource == 'file') {
|
|
||||||
$definition = $schemaDest->parseDatabaseDefinitionFile($dsnSource);
|
|
||||||
$where = 'loading schema file';
|
|
||||||
} else {
|
|
||||||
$schemaSource = MDB2_Schema::factory(
|
|
||||||
$dsnSource,
|
|
||||||
$this->getSchemaOptions()
|
|
||||||
);
|
|
||||||
$this->throwExceptionOnError(
|
|
||||||
$schemaSource,
|
|
||||||
'connecting to source database'
|
|
||||||
);
|
|
||||||
|
|
||||||
$definition = $schemaSource->getDefinitionFromDatabase();
|
|
||||||
$where = 'loading definition from database';
|
|
||||||
}
|
|
||||||
$this->throwExceptionOnError($definition, $where);
|
|
||||||
|
|
||||||
|
|
||||||
//create destination database from definition
|
|
||||||
$simulate = false;
|
|
||||||
$op = $schemaDest->createDatabase(
|
|
||||||
$definition,
|
|
||||||
array(),
|
|
||||||
$simulate
|
|
||||||
);
|
|
||||||
$this->throwExceptionOnError($op, 'creating the database');
|
|
||||||
}//protected function doLoad($args)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes a database with data
|
|
||||||
*
|
|
||||||
* @param array $args Command line arguments
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function doInit($args)
|
|
||||||
{
|
|
||||||
list($typeSource, $dsnSource) = $this->getFileOrDsn($args);
|
|
||||||
list($typeDest, $dsnDest) = $this->getFileOrDsn($args);
|
|
||||||
|
|
||||||
if ($typeSource != 'file') {
|
|
||||||
throw new MDB2_Schema_Tool_ParameterException(
|
|
||||||
'Data must come from a source file'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($typeDest != 'dsn') {
|
|
||||||
throw new MDB2_Schema_Tool_ParameterException(
|
|
||||||
'A schema can only be loaded into a database, not a file'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$schemaDest = MDB2_Schema::factory($dsnDest, $this->getSchemaOptions());
|
|
||||||
$this->throwExceptionOnError(
|
|
||||||
$schemaDest,
|
|
||||||
'connecting to destination database'
|
|
||||||
);
|
|
||||||
|
|
||||||
$definition = $schemaDest->getDefinitionFromDatabase();
|
|
||||||
$this->throwExceptionOnError(
|
|
||||||
$definition,
|
|
||||||
'loading definition from database'
|
|
||||||
);
|
|
||||||
|
|
||||||
$op = $schemaDest->writeInitialization($dsnSource, $definition);
|
|
||||||
$this->throwExceptionOnError($op, 'initializing database');
|
|
||||||
}//protected function doInit($args)
|
|
||||||
|
|
||||||
|
|
||||||
}//class MDB2_Schema_Tool
|
|
|
@ -1,61 +0,0 @@
|
||||||
<?php /* vim: se et ts=4 sw=4 sts=4 fdm=marker tw=80: */
|
|
||||||
/**
|
|
||||||
* Copyright (c) 1998-2010 Manuel Lemos, Tomas V.V.Cox,
|
|
||||||
* Stig. S. Bakken, Lukas Smith, Igor Feghali
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* MDB2_Schema enables users to maintain RDBMS independant schema files
|
|
||||||
* in XML that can be used to manipulate both data and database schemas
|
|
||||||
* This LICENSE is in the BSD license style.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,
|
|
||||||
* Lukas Smith, Igor Feghali nor the names of his contributors may be
|
|
||||||
* used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* REGENTS 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.
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* @category Database
|
|
||||||
* @package MDB2_Schema
|
|
||||||
* @author Christian Weiske <cweiske@php.net>
|
|
||||||
* @license BSD http://www.opensource.org/licenses/bsd-license.php
|
|
||||||
* @version SVN: $Id$
|
|
||||||
* @link http://pear.php.net/packages/MDB2_Schema
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* To be implemented yet
|
|
||||||
*
|
|
||||||
* @category Database
|
|
||||||
* @package MDB2_Schema
|
|
||||||
* @author Christian Weiske <cweiske@php.net>
|
|
||||||
* @license BSD http://www.opensource.org/licenses/bsd-license.php
|
|
||||||
* @link http://pear.php.net/packages/MDB2_Schema
|
|
||||||
*/
|
|
||||||
class MDB2_Schema_Tool_ParameterException extends Exception
|
|
||||||
{
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,586 +0,0 @@
|
||||||
<?php /* vim: se et ts=4 sw=4 sts=4 fdm=marker tw=80: */
|
|
||||||
/**
|
|
||||||
* Copyright (c) 1998-2010 Manuel Lemos, Tomas V.V.Cox,
|
|
||||||
* Stig. S. Bakken, Lukas Smith, Igor Feghali
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* MDB2_Schema enables users to maintain RDBMS independant schema files
|
|
||||||
* in XML that can be used to manipulate both data and database schemas
|
|
||||||
* This LICENSE is in the BSD license style.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,
|
|
||||||
* Lukas Smith, Igor Feghali nor the names of his contributors may be
|
|
||||||
* used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* REGENTS 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.
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* @category Database
|
|
||||||
* @package MDB2_Schema
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
* @author Igor Feghali <ifeghali@php.net>
|
|
||||||
* @license BSD http://www.opensource.org/licenses/bsd-license.php
|
|
||||||
* @version SVN: $Id$
|
|
||||||
* @link http://pear.php.net/packages/MDB2_Schema
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes an XML schema file
|
|
||||||
*
|
|
||||||
* @category Database
|
|
||||||
* @package MDB2_Schema
|
|
||||||
* @author Lukas Smith <smith@pooteeweet.org>
|
|
||||||
* @license BSD http://www.opensource.org/licenses/bsd-license.php
|
|
||||||
* @link http://pear.php.net/packages/MDB2_Schema
|
|
||||||
*/
|
|
||||||
class MDB2_Schema_Writer
|
|
||||||
{
|
|
||||||
// {{{ properties
|
|
||||||
|
|
||||||
var $valid_types = array();
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ constructor
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PHP 5 constructor
|
|
||||||
*
|
|
||||||
* @param array $valid_types information of all valid fields
|
|
||||||
* types
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function __construct($valid_types = array())
|
|
||||||
{
|
|
||||||
$this->valid_types = $valid_types;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ raiseError()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is used to communicate an error and invoke error
|
|
||||||
* callbacks etc. Basically a wrapper for PEAR::raiseError
|
|
||||||
* without the message string.
|
|
||||||
*
|
|
||||||
* @param int|PEAR_Error $code integer error code or and PEAR_Error
|
|
||||||
* instance
|
|
||||||
* @param int $mode error mode, see PEAR_Error docs error
|
|
||||||
* level (E_USER_NOTICE etc). If error mode
|
|
||||||
* is PEAR_ERROR_CALLBACK, this is the
|
|
||||||
* callback function, either as a function
|
|
||||||
* name, or as an array of an object and
|
|
||||||
* method name. For other error modes this
|
|
||||||
* parameter is ignored.
|
|
||||||
* @param string $options Extra debug information. Defaults to the
|
|
||||||
* last query and native error code.
|
|
||||||
* @param string $userinfo User-friendly error message
|
|
||||||
*
|
|
||||||
* @return object a PEAR error object
|
|
||||||
* @access public
|
|
||||||
* @see PEAR_Error
|
|
||||||
*/
|
|
||||||
function &raiseError($code = null, $mode = null, $options = null, $userinfo = null)
|
|
||||||
{
|
|
||||||
$error = MDB2_Schema::raiseError($code, $mode, $options, $userinfo);
|
|
||||||
return $error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _escapeSpecialChars()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* add escapecharacters to all special characters in a string
|
|
||||||
*
|
|
||||||
* @param string $string string that should be escaped
|
|
||||||
*
|
|
||||||
* @return string escaped string
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
function _escapeSpecialChars($string)
|
|
||||||
{
|
|
||||||
if (!is_string($string)) {
|
|
||||||
$string = strval($string);
|
|
||||||
}
|
|
||||||
|
|
||||||
$escaped = '';
|
|
||||||
for ($char = 0, $count = strlen($string); $char < $count; $char++) {
|
|
||||||
switch ($string[$char]) {
|
|
||||||
case '&':
|
|
||||||
$escaped .= '&';
|
|
||||||
break;
|
|
||||||
case '>':
|
|
||||||
$escaped .= '>';
|
|
||||||
break;
|
|
||||||
case '<':
|
|
||||||
$escaped .= '<';
|
|
||||||
break;
|
|
||||||
case '"':
|
|
||||||
$escaped .= '"';
|
|
||||||
break;
|
|
||||||
case '\'':
|
|
||||||
$escaped .= ''';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$code = ord($string[$char]);
|
|
||||||
if ($code < 32 || $code > 127) {
|
|
||||||
$escaped .= "&#$code;";
|
|
||||||
} else {
|
|
||||||
$escaped .= $string[$char];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $escaped;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ _dumpBoolean()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* dump the structure of a sequence
|
|
||||||
*
|
|
||||||
* @param string $boolean boolean value or variable definition
|
|
||||||
*
|
|
||||||
* @return string with xml boolea definition
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
function _dumpBoolean($boolean)
|
|
||||||
{
|
|
||||||
if (is_string($boolean)) {
|
|
||||||
if ($boolean !== 'true' || $boolean !== 'false'
|
|
||||||
|| preg_match('/<variable>.*</variable>/', $boolean)
|
|
||||||
) {
|
|
||||||
return $boolean;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $boolean ? 'true' : 'false';
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ dumpSequence()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* dump the structure of a sequence
|
|
||||||
*
|
|
||||||
* @param string $sequence_definition sequence definition
|
|
||||||
* @param string $sequence_name sequence name
|
|
||||||
* @param string $eol end of line characters
|
|
||||||
* @param integer $dump determines what data to dump
|
|
||||||
* MDB2_SCHEMA_DUMP_ALL : the entire db
|
|
||||||
* MDB2_SCHEMA_DUMP_STRUCTURE : only the structure of the db
|
|
||||||
* MDB2_SCHEMA_DUMP_CONTENT : only the content of the db
|
|
||||||
*
|
|
||||||
* @return mixed string xml sequence definition on success, or a error object
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function dumpSequence($sequence_definition, $sequence_name, $eol, $dump = MDB2_SCHEMA_DUMP_ALL)
|
|
||||||
{
|
|
||||||
$buffer = "$eol <sequence>$eol <name>$sequence_name</name>$eol";
|
|
||||||
if ($dump == MDB2_SCHEMA_DUMP_ALL || $dump == MDB2_SCHEMA_DUMP_CONTENT) {
|
|
||||||
if (!empty($sequence_definition['start'])) {
|
|
||||||
$start = $sequence_definition['start'];
|
|
||||||
$buffer .= " <start>$start</start>$eol";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($sequence_definition['on'])) {
|
|
||||||
$buffer .= " <on>$eol";
|
|
||||||
$buffer .= " <table>".$sequence_definition['on']['table'];
|
|
||||||
$buffer .= "</table>$eol <field>".$sequence_definition['on']['field'];
|
|
||||||
$buffer .= "</field>$eol </on>$eol";
|
|
||||||
}
|
|
||||||
$buffer .= " </sequence>$eol";
|
|
||||||
|
|
||||||
return $buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ dumpDatabase()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dump a previously parsed database structure in the Metabase schema
|
|
||||||
* XML based format suitable for the Metabase parser. This function
|
|
||||||
* may optionally dump the database definition with initialization
|
|
||||||
* commands that specify the data that is currently present in the tables.
|
|
||||||
*
|
|
||||||
* @param array $database_definition unknown
|
|
||||||
* @param array $arguments associative array that takes pairs of tag
|
|
||||||
* names and values that define dump options.
|
|
||||||
* array (
|
|
||||||
* 'output_mode' => String
|
|
||||||
* 'file' : dump into a file
|
|
||||||
* default: dump using a function
|
|
||||||
* 'output' => String
|
|
||||||
* depending on the 'Output_Mode'
|
|
||||||
* name of the file
|
|
||||||
* name of the function
|
|
||||||
* 'end_of_line' => String
|
|
||||||
* end of line delimiter that should be used
|
|
||||||
* default: "\n"
|
|
||||||
* );
|
|
||||||
* @param integer $dump determines what data to dump
|
|
||||||
* MDB2_SCHEMA_DUMP_ALL : the entire db
|
|
||||||
* MDB2_SCHEMA_DUMP_STRUCTURE : only the structure of the db
|
|
||||||
* MDB2_SCHEMA_DUMP_CONTENT : only the content of the db
|
|
||||||
*
|
|
||||||
* @return mixed MDB2_OK on success, or a error object
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function dumpDatabase($database_definition, $arguments, $dump = MDB2_SCHEMA_DUMP_ALL)
|
|
||||||
{
|
|
||||||
if (!empty($arguments['output'])) {
|
|
||||||
if (!empty($arguments['output_mode']) && $arguments['output_mode'] == 'file') {
|
|
||||||
$fp = fopen($arguments['output'], 'w');
|
|
||||||
if ($fp === false) {
|
|
||||||
return $this->raiseError(MDB2_SCHEMA_ERROR_WRITER, null, null,
|
|
||||||
'it was not possible to open output file');
|
|
||||||
}
|
|
||||||
|
|
||||||
$output = false;
|
|
||||||
} elseif (is_callable($arguments['output'])) {
|
|
||||||
$output = $arguments['output'];
|
|
||||||
} else {
|
|
||||||
return $this->raiseError(MDB2_SCHEMA_ERROR_WRITER, null, null,
|
|
||||||
'no valid output function specified');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return $this->raiseError(MDB2_SCHEMA_ERROR_WRITER, null, null,
|
|
||||||
'no output method specified');
|
|
||||||
}
|
|
||||||
|
|
||||||
$eol = isset($arguments['end_of_line']) ? $arguments['end_of_line'] : "\n";
|
|
||||||
|
|
||||||
$sequences = array();
|
|
||||||
if (!empty($database_definition['sequences'])
|
|
||||||
&& is_array($database_definition['sequences'])
|
|
||||||
) {
|
|
||||||
foreach ($database_definition['sequences'] as $sequence_name => $sequence) {
|
|
||||||
$table = !empty($sequence['on']) ? $sequence['on']['table'] :'';
|
|
||||||
|
|
||||||
$sequences[$table][] = $sequence_name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$buffer = '<?xml version="1.0" encoding="ISO-8859-1" ?>'.$eol;
|
|
||||||
$buffer .= "<database>$eol$eol <name>".$database_definition['name']."</name>";
|
|
||||||
$buffer .= "$eol <create>".$this->_dumpBoolean($database_definition['create'])."</create>";
|
|
||||||
$buffer .= "$eol <overwrite>".$this->_dumpBoolean($database_definition['overwrite'])."</overwrite>$eol";
|
|
||||||
$buffer .= "$eol <charset>".$database_definition['charset']."</charset>$eol";
|
|
||||||
|
|
||||||
if ($output) {
|
|
||||||
call_user_func($output, $buffer);
|
|
||||||
} else {
|
|
||||||
fwrite($fp, $buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($database_definition['tables']) && is_array($database_definition['tables'])) {
|
|
||||||
foreach ($database_definition['tables'] as $table_name => $table) {
|
|
||||||
$buffer = "$eol <table>$eol$eol <name>$table_name</name>$eol";
|
|
||||||
if ($dump == MDB2_SCHEMA_DUMP_ALL || $dump == MDB2_SCHEMA_DUMP_STRUCTURE) {
|
|
||||||
$buffer .= "$eol <declaration>$eol";
|
|
||||||
if (!empty($table['fields']) && is_array($table['fields'])) {
|
|
||||||
foreach ($table['fields'] as $field_name => $field) {
|
|
||||||
if (empty($field['type'])) {
|
|
||||||
return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, null, null,
|
|
||||||
'it was not specified the type of the field "'.
|
|
||||||
$field_name.'" of the table "'.$table_name.'"');
|
|
||||||
}
|
|
||||||
if (!empty($this->valid_types) && !array_key_exists($field['type'], $this->valid_types)) {
|
|
||||||
return $this->raiseError(MDB2_SCHEMA_ERROR_UNSUPPORTED, null, null,
|
|
||||||
'type "'.$field['type'].'" is not yet supported');
|
|
||||||
}
|
|
||||||
$buffer .= "$eol <field>$eol <name>$field_name</name>$eol <type>";
|
|
||||||
$buffer .= $field['type']."</type>$eol";
|
|
||||||
if (!empty($field['fixed']) && $field['type'] === 'text') {
|
|
||||||
$buffer .= " <fixed>".$this->_dumpBoolean($field['fixed'])."</fixed>$eol";
|
|
||||||
}
|
|
||||||
if (array_key_exists('default', $field)
|
|
||||||
&& $field['type'] !== 'clob' && $field['type'] !== 'blob'
|
|
||||||
) {
|
|
||||||
$buffer .= ' <default>'.$this->_escapeSpecialChars($field['default'])."</default>$eol";
|
|
||||||
}
|
|
||||||
if (!empty($field['notnull'])) {
|
|
||||||
$buffer .= " <notnull>".$this->_dumpBoolean($field['notnull'])."</notnull>$eol";
|
|
||||||
} else {
|
|
||||||
$buffer .= " <notnull>false</notnull>$eol";
|
|
||||||
}
|
|
||||||
if (!empty($field['autoincrement'])) {
|
|
||||||
$buffer .= " <autoincrement>" . $field['autoincrement'] ."</autoincrement>$eol";
|
|
||||||
}
|
|
||||||
if (!empty($field['unsigned'])) {
|
|
||||||
$buffer .= " <unsigned>".$this->_dumpBoolean($field['unsigned'])."</unsigned>$eol";
|
|
||||||
}
|
|
||||||
if (!empty($field['length'])) {
|
|
||||||
$buffer .= ' <length>'.$field['length']."</length>$eol";
|
|
||||||
}
|
|
||||||
$buffer .= " </field>$eol";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($table['indexes']) && is_array($table['indexes'])) {
|
|
||||||
foreach ($table['indexes'] as $index_name => $index) {
|
|
||||||
if (strtolower($index_name) === 'primary') {
|
|
||||||
$index_name = $table_name . '_pKey';
|
|
||||||
}
|
|
||||||
$buffer .= "$eol <index>$eol <name>$index_name</name>$eol";
|
|
||||||
if (!empty($index['unique'])) {
|
|
||||||
$buffer .= " <unique>".$this->_dumpBoolean($index['unique'])."</unique>$eol";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($index['primary'])) {
|
|
||||||
$buffer .= " <primary>".$this->_dumpBoolean($index['primary'])."</primary>$eol";
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($index['fields'] as $field_name => $field) {
|
|
||||||
$buffer .= " <field>$eol <name>$field_name</name>$eol";
|
|
||||||
if (!empty($field) && is_array($field)) {
|
|
||||||
$buffer .= ' <sorting>'.$field['sorting']."</sorting>$eol";
|
|
||||||
}
|
|
||||||
$buffer .= " </field>$eol";
|
|
||||||
}
|
|
||||||
$buffer .= " </index>$eol";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($table['constraints']) && is_array($table['constraints'])) {
|
|
||||||
foreach ($table['constraints'] as $constraint_name => $constraint) {
|
|
||||||
$buffer .= "$eol <foreign>$eol <name>$constraint_name</name>$eol";
|
|
||||||
if (empty($constraint['fields']) || !is_array($constraint['fields'])) {
|
|
||||||
return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, null, null,
|
|
||||||
'it was not specified a field for the foreign key "'.
|
|
||||||
$constraint_name.'" of the table "'.$table_name.'"');
|
|
||||||
}
|
|
||||||
if (!is_array($constraint['references']) || empty($constraint['references']['table'])) {
|
|
||||||
return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, null, null,
|
|
||||||
'it was not specified the referenced table of the foreign key "'.
|
|
||||||
$constraint_name.'" of the table "'.$table_name.'"');
|
|
||||||
}
|
|
||||||
if (!empty($constraint['match'])) {
|
|
||||||
$buffer .= " <match>".$constraint['match']."</match>$eol";
|
|
||||||
}
|
|
||||||
if (!empty($constraint['ondelete'])) {
|
|
||||||
$buffer .= " <ondelete>".$constraint['ondelete']."</ondelete>$eol";
|
|
||||||
}
|
|
||||||
if (!empty($constraint['onupdate'])) {
|
|
||||||
$buffer .= " <onupdate>".$constraint['onupdate']."</onupdate>$eol";
|
|
||||||
}
|
|
||||||
if (!empty($constraint['deferrable'])) {
|
|
||||||
$buffer .= " <deferrable>".$constraint['deferrable']."</deferrable>$eol";
|
|
||||||
}
|
|
||||||
if (!empty($constraint['initiallydeferred'])) {
|
|
||||||
$buffer .= " <initiallydeferred>".$constraint['initiallydeferred']."</initiallydeferred>$eol";
|
|
||||||
}
|
|
||||||
foreach ($constraint['fields'] as $field_name => $field) {
|
|
||||||
$buffer .= " <field>$field_name</field>$eol";
|
|
||||||
}
|
|
||||||
$buffer .= " <references>$eol <table>".$constraint['references']['table']."</table>$eol";
|
|
||||||
foreach ($constraint['references']['fields'] as $field_name => $field) {
|
|
||||||
$buffer .= " <field>$field_name</field>$eol";
|
|
||||||
}
|
|
||||||
$buffer .= " </references>$eol";
|
|
||||||
|
|
||||||
$buffer .= " </foreign>$eol";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$buffer .= "$eol </declaration>$eol";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($output) {
|
|
||||||
call_user_func($output, $buffer);
|
|
||||||
} else {
|
|
||||||
fwrite($fp, $buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
$buffer = '';
|
|
||||||
if ($dump == MDB2_SCHEMA_DUMP_ALL || $dump == MDB2_SCHEMA_DUMP_CONTENT) {
|
|
||||||
if (!empty($table['initialization']) && is_array($table['initialization'])) {
|
|
||||||
$buffer = "$eol <initialization>$eol";
|
|
||||||
foreach ($table['initialization'] as $instruction) {
|
|
||||||
switch ($instruction['type']) {
|
|
||||||
case 'insert':
|
|
||||||
$buffer .= "$eol <insert>$eol";
|
|
||||||
foreach ($instruction['data']['field'] as $field) {
|
|
||||||
$field_name = $field['name'];
|
|
||||||
|
|
||||||
$buffer .= "$eol <field>$eol <name>$field_name</name>$eol";
|
|
||||||
$buffer .= $this->writeExpression($field['group'], 5, $arguments);
|
|
||||||
$buffer .= " </field>$eol";
|
|
||||||
}
|
|
||||||
$buffer .= "$eol </insert>$eol";
|
|
||||||
break;
|
|
||||||
case 'update':
|
|
||||||
$buffer .= "$eol <update>$eol";
|
|
||||||
foreach ($instruction['data']['field'] as $field) {
|
|
||||||
$field_name = $field['name'];
|
|
||||||
|
|
||||||
$buffer .= "$eol <field>$eol <name>$field_name</name>$eol";
|
|
||||||
$buffer .= $this->writeExpression($field['group'], 5, $arguments);
|
|
||||||
$buffer .= " </field>$eol";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($instruction['data']['where'])
|
|
||||||
&& is_array($instruction['data']['where'])
|
|
||||||
) {
|
|
||||||
$buffer .= " <where>$eol";
|
|
||||||
$buffer .= $this->writeExpression($instruction['data']['where'], 5, $arguments);
|
|
||||||
$buffer .= " </where>$eol";
|
|
||||||
}
|
|
||||||
|
|
||||||
$buffer .= "$eol </update>$eol";
|
|
||||||
break;
|
|
||||||
case 'delete':
|
|
||||||
$buffer .= "$eol <delete>$eol$eol";
|
|
||||||
if (!empty($instruction['data']['where'])
|
|
||||||
&& is_array($instruction['data']['where'])
|
|
||||||
) {
|
|
||||||
$buffer .= " <where>$eol";
|
|
||||||
$buffer .= $this->writeExpression($instruction['data']['where'], 5, $arguments);
|
|
||||||
$buffer .= " </where>$eol";
|
|
||||||
}
|
|
||||||
$buffer .= "$eol </delete>$eol";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$buffer .= "$eol </initialization>$eol";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$buffer .= "$eol </table>$eol";
|
|
||||||
if ($output) {
|
|
||||||
call_user_func($output, $buffer);
|
|
||||||
} else {
|
|
||||||
fwrite($fp, $buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($sequences[$table_name])) {
|
|
||||||
foreach ($sequences[$table_name] as $sequence) {
|
|
||||||
$result = $this->dumpSequence($database_definition['sequences'][$sequence],
|
|
||||||
$sequence, $eol, $dump);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($output) {
|
|
||||||
call_user_func($output, $result);
|
|
||||||
} else {
|
|
||||||
fwrite($fp, $result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($sequences[''])) {
|
|
||||||
foreach ($sequences[''] as $sequence) {
|
|
||||||
$result = $this->dumpSequence($database_definition['sequences'][$sequence],
|
|
||||||
$sequence, $eol, $dump);
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($output) {
|
|
||||||
call_user_func($output, $result);
|
|
||||||
} else {
|
|
||||||
fwrite($fp, $result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$buffer = "$eol</database>$eol";
|
|
||||||
if ($output) {
|
|
||||||
call_user_func($output, $buffer);
|
|
||||||
} else {
|
|
||||||
fwrite($fp, $buffer);
|
|
||||||
fclose($fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return MDB2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ writeExpression()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dumps the structure of an element. Elements can be value, column,
|
|
||||||
* function or expression.
|
|
||||||
*
|
|
||||||
* @param array $element multi dimensional array that represents the parsed element
|
|
||||||
* of a DML instruction.
|
|
||||||
* @param integer $offset base indentation width
|
|
||||||
* @param array $arguments associative array that takes pairs of tag
|
|
||||||
* names and values that define dump options.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @see MDB2_Schema_Writer::dumpDatabase()
|
|
||||||
*/
|
|
||||||
function writeExpression($element, $offset = 0, $arguments = null)
|
|
||||||
{
|
|
||||||
$eol = isset($arguments['end_of_line']) ? $arguments['end_of_line'] : "\n";
|
|
||||||
$str = '';
|
|
||||||
|
|
||||||
$indent = str_repeat(' ', $offset);
|
|
||||||
$noffset = $offset + 1;
|
|
||||||
|
|
||||||
switch ($element['type']) {
|
|
||||||
case 'value':
|
|
||||||
$str .= "$indent<value>".$this->_escapeSpecialChars($element['data'])."</value>$eol";
|
|
||||||
break;
|
|
||||||
case 'column':
|
|
||||||
$str .= "$indent<column>".$this->_escapeSpecialChars($element['data'])."</column>$eol";
|
|
||||||
break;
|
|
||||||
case 'function':
|
|
||||||
$str .= "$indent<function>$eol$indent <name>".$this->_escapeSpecialChars($element['data']['name'])."</name>$eol";
|
|
||||||
|
|
||||||
if (!empty($element['data']['arguments'])
|
|
||||||
&& is_array($element['data']['arguments'])
|
|
||||||
) {
|
|
||||||
foreach ($element['data']['arguments'] as $v) {
|
|
||||||
$str .= $this->writeExpression($v, $noffset, $arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$str .= "$indent</function>$eol";
|
|
||||||
break;
|
|
||||||
case 'expression':
|
|
||||||
$str .= "$indent<expression>$eol";
|
|
||||||
$str .= $this->writeExpression($element['data']['operants'][0], $noffset, $arguments);
|
|
||||||
$str .= "$indent <operator>".$element['data']['operator']."</operator>$eol";
|
|
||||||
$str .= $this->writeExpression($element['data']['operants'][1], $noffset, $arguments);
|
|
||||||
$str .= "$indent</expression>$eol";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return $str;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
}
|
|
|
@ -1,338 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* The OS_Guess class
|
|
||||||
*
|
|
||||||
* PHP versions 4 and 5
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Gregory Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version CVS: $Id: Guess.php 313023 2011-07-06 19:17:11Z dufuz $
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since File available since PEAR 0.1
|
|
||||||
*/
|
|
||||||
|
|
||||||
// {{{ uname examples
|
|
||||||
|
|
||||||
// php_uname() without args returns the same as 'uname -a', or a PHP-custom
|
|
||||||
// string for Windows.
|
|
||||||
// PHP versions prior to 4.3 return the uname of the host where PHP was built,
|
|
||||||
// as of 4.3 it returns the uname of the host running the PHP code.
|
|
||||||
//
|
|
||||||
// PC RedHat Linux 7.1:
|
|
||||||
// Linux host.example.com 2.4.2-2 #1 Sun Apr 8 20:41:30 EDT 2001 i686 unknown
|
|
||||||
//
|
|
||||||
// PC Debian Potato:
|
|
||||||
// Linux host 2.4.17 #2 SMP Tue Feb 12 15:10:04 CET 2002 i686 unknown
|
|
||||||
//
|
|
||||||
// PC FreeBSD 3.3:
|
|
||||||
// FreeBSD host.example.com 3.3-STABLE FreeBSD 3.3-STABLE #0: Mon Feb 21 00:42:31 CET 2000 root@example.com:/usr/src/sys/compile/CONFIG i386
|
|
||||||
//
|
|
||||||
// PC FreeBSD 4.3:
|
|
||||||
// FreeBSD host.example.com 4.3-RELEASE FreeBSD 4.3-RELEASE #1: Mon Jun 25 11:19:43 EDT 2001 root@example.com:/usr/src/sys/compile/CONFIG i386
|
|
||||||
//
|
|
||||||
// PC FreeBSD 4.5:
|
|
||||||
// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb 6 23:59:23 CET 2002 root@example.com:/usr/src/sys/compile/CONFIG i386
|
|
||||||
//
|
|
||||||
// PC FreeBSD 4.5 w/uname from GNU shellutils:
|
|
||||||
// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb i386 unknown
|
|
||||||
//
|
|
||||||
// HP 9000/712 HP-UX 10:
|
|
||||||
// HP-UX iq B.10.10 A 9000/712 2008429113 two-user license
|
|
||||||
//
|
|
||||||
// HP 9000/712 HP-UX 10 w/uname from GNU shellutils:
|
|
||||||
// HP-UX host B.10.10 A 9000/712 unknown
|
|
||||||
//
|
|
||||||
// IBM RS6000/550 AIX 4.3:
|
|
||||||
// AIX host 3 4 000003531C00
|
|
||||||
//
|
|
||||||
// AIX 4.3 w/uname from GNU shellutils:
|
|
||||||
// AIX host 3 4 000003531C00 unknown
|
|
||||||
//
|
|
||||||
// SGI Onyx IRIX 6.5 w/uname from GNU shellutils:
|
|
||||||
// IRIX64 host 6.5 01091820 IP19 mips
|
|
||||||
//
|
|
||||||
// SGI Onyx IRIX 6.5:
|
|
||||||
// IRIX64 host 6.5 01091820 IP19
|
|
||||||
//
|
|
||||||
// SparcStation 20 Solaris 8 w/uname from GNU shellutils:
|
|
||||||
// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc
|
|
||||||
//
|
|
||||||
// SparcStation 20 Solaris 8:
|
|
||||||
// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc SUNW,SPARCstation-20
|
|
||||||
//
|
|
||||||
// Mac OS X (Darwin)
|
|
||||||
// Darwin home-eden.local 7.5.0 Darwin Kernel Version 7.5.0: Thu Aug 5 19:26:16 PDT 2004; root:xnu/xnu-517.7.21.obj~3/RELEASE_PPC Power Macintosh
|
|
||||||
//
|
|
||||||
// Mac OS X early versions
|
|
||||||
//
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
/* TODO:
|
|
||||||
* - define endianness, to allow matchSignature("bigend") etc.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves information about the current operating system
|
|
||||||
*
|
|
||||||
* This class uses php_uname() to grok information about the current OS
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Gregory Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version Release: 1.9.4
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since Class available since Release 0.1
|
|
||||||
*/
|
|
||||||
class OS_Guess
|
|
||||||
{
|
|
||||||
var $sysname;
|
|
||||||
var $nodename;
|
|
||||||
var $cpu;
|
|
||||||
var $release;
|
|
||||||
var $extra;
|
|
||||||
|
|
||||||
function OS_Guess($uname = null)
|
|
||||||
{
|
|
||||||
list($this->sysname,
|
|
||||||
$this->release,
|
|
||||||
$this->cpu,
|
|
||||||
$this->extra,
|
|
||||||
$this->nodename) = $this->parseSignature($uname);
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseSignature($uname = null)
|
|
||||||
{
|
|
||||||
static $sysmap = array(
|
|
||||||
'HP-UX' => 'hpux',
|
|
||||||
'IRIX64' => 'irix',
|
|
||||||
);
|
|
||||||
static $cpumap = array(
|
|
||||||
'i586' => 'i386',
|
|
||||||
'i686' => 'i386',
|
|
||||||
'ppc' => 'powerpc',
|
|
||||||
);
|
|
||||||
if ($uname === null) {
|
|
||||||
$uname = php_uname();
|
|
||||||
}
|
|
||||||
$parts = preg_split('/\s+/', trim($uname));
|
|
||||||
$n = count($parts);
|
|
||||||
|
|
||||||
$release = $machine = $cpu = '';
|
|
||||||
$sysname = $parts[0];
|
|
||||||
$nodename = $parts[1];
|
|
||||||
$cpu = $parts[$n-1];
|
|
||||||
$extra = '';
|
|
||||||
if ($cpu == 'unknown') {
|
|
||||||
$cpu = $parts[$n - 2];
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($sysname) {
|
|
||||||
case 'AIX' :
|
|
||||||
$release = "$parts[3].$parts[2]";
|
|
||||||
break;
|
|
||||||
case 'Windows' :
|
|
||||||
switch ($parts[1]) {
|
|
||||||
case '95/98':
|
|
||||||
$release = '9x';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$release = $parts[1];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$cpu = 'i386';
|
|
||||||
break;
|
|
||||||
case 'Linux' :
|
|
||||||
$extra = $this->_detectGlibcVersion();
|
|
||||||
// use only the first two digits from the kernel version
|
|
||||||
$release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]);
|
|
||||||
break;
|
|
||||||
case 'Mac' :
|
|
||||||
$sysname = 'darwin';
|
|
||||||
$nodename = $parts[2];
|
|
||||||
$release = $parts[3];
|
|
||||||
if ($cpu == 'Macintosh') {
|
|
||||||
if ($parts[$n - 2] == 'Power') {
|
|
||||||
$cpu = 'powerpc';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'Darwin' :
|
|
||||||
if ($cpu == 'Macintosh') {
|
|
||||||
if ($parts[$n - 2] == 'Power') {
|
|
||||||
$cpu = 'powerpc';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$release = preg_replace('/-.*/', '', $parts[2]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($sysmap[$sysname])) {
|
|
||||||
$sysname = $sysmap[$sysname];
|
|
||||||
} else {
|
|
||||||
$sysname = strtolower($sysname);
|
|
||||||
}
|
|
||||||
if (isset($cpumap[$cpu])) {
|
|
||||||
$cpu = $cpumap[$cpu];
|
|
||||||
}
|
|
||||||
return array($sysname, $release, $cpu, $extra, $nodename);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _detectGlibcVersion()
|
|
||||||
{
|
|
||||||
static $glibc = false;
|
|
||||||
if ($glibc !== false) {
|
|
||||||
return $glibc; // no need to run this multiple times
|
|
||||||
}
|
|
||||||
$major = $minor = 0;
|
|
||||||
include_once "System.php";
|
|
||||||
// Use glibc's <features.h> header file to
|
|
||||||
// get major and minor version number:
|
|
||||||
if (@file_exists('/usr/include/features.h') &&
|
|
||||||
@is_readable('/usr/include/features.h')) {
|
|
||||||
if (!@file_exists('/usr/bin/cpp') || !@is_executable('/usr/bin/cpp')) {
|
|
||||||
$features_file = fopen('/usr/include/features.h', 'rb');
|
|
||||||
while (!feof($features_file)) {
|
|
||||||
$line = fgets($features_file, 8192);
|
|
||||||
if (!$line || (strpos($line, '#define') === false)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (strpos($line, '__GLIBC__')) {
|
|
||||||
// major version number #define __GLIBC__ version
|
|
||||||
$line = preg_split('/\s+/', $line);
|
|
||||||
$glibc_major = trim($line[2]);
|
|
||||||
if (isset($glibc_minor)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strpos($line, '__GLIBC_MINOR__')) {
|
|
||||||
// got the minor version number
|
|
||||||
// #define __GLIBC_MINOR__ version
|
|
||||||
$line = preg_split('/\s+/', $line);
|
|
||||||
$glibc_minor = trim($line[2]);
|
|
||||||
if (isset($glibc_major)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose($features_file);
|
|
||||||
if (!isset($glibc_major) || !isset($glibc_minor)) {
|
|
||||||
return $glibc = '';
|
|
||||||
}
|
|
||||||
return $glibc = 'glibc' . trim($glibc_major) . "." . trim($glibc_minor) ;
|
|
||||||
} // no cpp
|
|
||||||
|
|
||||||
$tmpfile = System::mktemp("glibctest");
|
|
||||||
$fp = fopen($tmpfile, "w");
|
|
||||||
fwrite($fp, "#include <features.h>\n__GLIBC__ __GLIBC_MINOR__\n");
|
|
||||||
fclose($fp);
|
|
||||||
$cpp = popen("/usr/bin/cpp $tmpfile", "r");
|
|
||||||
while ($line = fgets($cpp, 1024)) {
|
|
||||||
if ($line{0} == '#' || trim($line) == '') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (list($major, $minor) = explode(' ', trim($line))) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pclose($cpp);
|
|
||||||
unlink($tmpfile);
|
|
||||||
} // features.h
|
|
||||||
|
|
||||||
if (!($major && $minor) && @is_link('/lib/libc.so.6')) {
|
|
||||||
// Let's try reading the libc.so.6 symlink
|
|
||||||
if (preg_match('/^libc-(.*)\.so$/', basename(readlink('/lib/libc.so.6')), $matches)) {
|
|
||||||
list($major, $minor) = explode('.', $matches[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!($major && $minor)) {
|
|
||||||
return $glibc = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $glibc = "glibc{$major}.{$minor}";
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSignature()
|
|
||||||
{
|
|
||||||
if (empty($this->extra)) {
|
|
||||||
return "{$this->sysname}-{$this->release}-{$this->cpu}";
|
|
||||||
}
|
|
||||||
return "{$this->sysname}-{$this->release}-{$this->cpu}-{$this->extra}";
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSysname()
|
|
||||||
{
|
|
||||||
return $this->sysname;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNodename()
|
|
||||||
{
|
|
||||||
return $this->nodename;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCpu()
|
|
||||||
{
|
|
||||||
return $this->cpu;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRelease()
|
|
||||||
{
|
|
||||||
return $this->release;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getExtra()
|
|
||||||
{
|
|
||||||
return $this->extra;
|
|
||||||
}
|
|
||||||
|
|
||||||
function matchSignature($match)
|
|
||||||
{
|
|
||||||
$fragments = is_array($match) ? $match : explode('-', $match);
|
|
||||||
$n = count($fragments);
|
|
||||||
$matches = 0;
|
|
||||||
if ($n > 0) {
|
|
||||||
$matches += $this->_matchFragment($fragments[0], $this->sysname);
|
|
||||||
}
|
|
||||||
if ($n > 1) {
|
|
||||||
$matches += $this->_matchFragment($fragments[1], $this->release);
|
|
||||||
}
|
|
||||||
if ($n > 2) {
|
|
||||||
$matches += $this->_matchFragment($fragments[2], $this->cpu);
|
|
||||||
}
|
|
||||||
if ($n > 3) {
|
|
||||||
$matches += $this->_matchFragment($fragments[3], $this->extra);
|
|
||||||
}
|
|
||||||
return ($matches == $n);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _matchFragment($fragment, $value)
|
|
||||||
{
|
|
||||||
if (strcspn($fragment, '*?') < strlen($fragment)) {
|
|
||||||
$reg = '/^' . str_replace(array('*', '?', '/'), array('.*', '.', '\\/'), $fragment) . '\\z/';
|
|
||||||
return preg_match($reg, $value);
|
|
||||||
}
|
|
||||||
return ($fragment == '*' || !strcasecmp($fragment, $value));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Local Variables:
|
|
||||||
* indent-tabs-mode: nil
|
|
||||||
* c-basic-offset: 4
|
|
||||||
* End:
|
|
||||||
*/
|
|
|
@ -1,27 +0,0 @@
|
||||||
Copyright (c) 1997-2009,
|
|
||||||
Stig Bakken <ssb@php.net>,
|
|
||||||
Gregory Beaver <cellog@php.net>,
|
|
||||||
Helgi Þormar Þorbjörnsson <helgi@php.net>,
|
|
||||||
Tomas V.V.Cox <cox@idecnet.com>,
|
|
||||||
Martin Jansen <mj@php.net>.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
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.
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,218 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Class auto-loader
|
|
||||||
*
|
|
||||||
* PHP versions 4
|
|
||||||
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version CVS: $Id: Autoloader.php 313023 2011-07-06 19:17:11Z dufuz $
|
|
||||||
* @link http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader
|
|
||||||
* @since File available since Release 0.1
|
|
||||||
* @deprecated File deprecated in Release 1.4.0a1
|
|
||||||
*/
|
|
||||||
|
|
||||||
// /* vim: set expandtab tabstop=4 shiftwidth=4: */
|
|
||||||
|
|
||||||
if (!extension_loaded("overload")) {
|
|
||||||
// die hard without ext/overload
|
|
||||||
die("Rebuild PHP with the `overload' extension to use PEAR_Autoloader");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Include for PEAR_Error and PEAR classes
|
|
||||||
*/
|
|
||||||
require_once "PEAR.php";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is for objects where you want to separate the code for
|
|
||||||
* some methods into separate classes. This is useful if you have a
|
|
||||||
* class with not-frequently-used methods that contain lots of code
|
|
||||||
* that you would like to avoid always parsing.
|
|
||||||
*
|
|
||||||
* The PEAR_Autoloader class provides autoloading and aggregation.
|
|
||||||
* The autoloading lets you set up in which classes the separated
|
|
||||||
* methods are found. Aggregation is the technique used to import new
|
|
||||||
* methods, an instance of each class providing separated methods is
|
|
||||||
* stored and called every time the aggregated method is called.
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version Release: 1.9.4
|
|
||||||
* @link http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader
|
|
||||||
* @since File available since Release 0.1
|
|
||||||
* @deprecated File deprecated in Release 1.4.0a1
|
|
||||||
*/
|
|
||||||
class PEAR_Autoloader extends PEAR
|
|
||||||
{
|
|
||||||
// {{{ properties
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map of methods and classes where they are defined
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
var $_autoload_map = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map of methods and aggregate objects
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
var $_method_map = array();
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ addAutoload()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add one or more autoload entries.
|
|
||||||
*
|
|
||||||
* @param string $method which method to autoload
|
|
||||||
*
|
|
||||||
* @param string $classname (optional) which class to find the method in.
|
|
||||||
* If the $method parameter is an array, this
|
|
||||||
* parameter may be omitted (and will be ignored
|
|
||||||
* if not), and the $method parameter will be
|
|
||||||
* treated as an associative array with method
|
|
||||||
* names as keys and class names as values.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function addAutoload($method, $classname = null)
|
|
||||||
{
|
|
||||||
if (is_array($method)) {
|
|
||||||
array_walk($method, create_function('$a,&$b', '$b = strtolower($b);'));
|
|
||||||
$this->_autoload_map = array_merge($this->_autoload_map, $method);
|
|
||||||
} else {
|
|
||||||
$this->_autoload_map[strtolower($method)] = $classname;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ removeAutoload()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove an autoload entry.
|
|
||||||
*
|
|
||||||
* @param string $method which method to remove the autoload entry for
|
|
||||||
*
|
|
||||||
* @return bool TRUE if an entry was removed, FALSE if not
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function removeAutoload($method)
|
|
||||||
{
|
|
||||||
$method = strtolower($method);
|
|
||||||
$ok = isset($this->_autoload_map[$method]);
|
|
||||||
unset($this->_autoload_map[$method]);
|
|
||||||
return $ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ addAggregateObject()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an aggregate object to this object. If the specified class
|
|
||||||
* is not defined, loading it will be attempted following PEAR's
|
|
||||||
* file naming scheme. All the methods in the class will be
|
|
||||||
* aggregated, except private ones (name starting with an
|
|
||||||
* underscore) and constructors.
|
|
||||||
*
|
|
||||||
* @param string $classname what class to instantiate for the object.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function addAggregateObject($classname)
|
|
||||||
{
|
|
||||||
$classname = strtolower($classname);
|
|
||||||
if (!class_exists($classname)) {
|
|
||||||
$include_file = preg_replace('/[^a-z0-9]/i', '_', $classname);
|
|
||||||
include_once $include_file;
|
|
||||||
}
|
|
||||||
$obj = new $classname;
|
|
||||||
$methods = get_class_methods($classname);
|
|
||||||
foreach ($methods as $method) {
|
|
||||||
// don't import priviate methods and constructors
|
|
||||||
if ($method{0} != '_' && $method != $classname) {
|
|
||||||
$this->_method_map[$method] = $obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ removeAggregateObject()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove an aggregate object.
|
|
||||||
*
|
|
||||||
* @param string $classname the class of the object to remove
|
|
||||||
*
|
|
||||||
* @return bool TRUE if an object was removed, FALSE if not
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function removeAggregateObject($classname)
|
|
||||||
{
|
|
||||||
$ok = false;
|
|
||||||
$classname = strtolower($classname);
|
|
||||||
reset($this->_method_map);
|
|
||||||
while (list($method, $obj) = each($this->_method_map)) {
|
|
||||||
if (is_a($obj, $classname)) {
|
|
||||||
unset($this->_method_map[$method]);
|
|
||||||
$ok = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ __call()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overloaded object call handler, called each time an
|
|
||||||
* undefined/aggregated method is invoked. This method repeats
|
|
||||||
* the call in the right aggregate object and passes on the return
|
|
||||||
* value.
|
|
||||||
*
|
|
||||||
* @param string $method which method that was called
|
|
||||||
*
|
|
||||||
* @param string $args An array of the parameters passed in the
|
|
||||||
* original call
|
|
||||||
*
|
|
||||||
* @return mixed The return value from the aggregated method, or a PEAR
|
|
||||||
* error if the called method was unknown.
|
|
||||||
*/
|
|
||||||
function __call($method, $args, &$retval)
|
|
||||||
{
|
|
||||||
$method = strtolower($method);
|
|
||||||
if (empty($this->_method_map[$method]) && isset($this->_autoload_map[$method])) {
|
|
||||||
$this->addAggregateObject($this->_autoload_map[$method]);
|
|
||||||
}
|
|
||||||
if (isset($this->_method_map[$method])) {
|
|
||||||
$retval = call_user_func_array(array($this->_method_map[$method], $method), $args);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
}
|
|
||||||
|
|
||||||
overload("PEAR_Autoloader");
|
|
||||||
|
|
||||||
?>
|
|
|
@ -1,489 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* PEAR_Builder for building PHP extensions (PECL packages)
|
|
||||||
*
|
|
||||||
* PHP versions 4 and 5
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version CVS: $Id: Builder.php 313024 2011-07-06 19:51:24Z dufuz $
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since File available since Release 0.1
|
|
||||||
*
|
|
||||||
* TODO: log output parameters in PECL command line
|
|
||||||
* TODO: msdev path in configuration
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Needed for extending PEAR_Builder
|
|
||||||
*/
|
|
||||||
require_once 'PEAR/Common.php';
|
|
||||||
require_once 'PEAR/PackageFile.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class to handle building (compiling) extensions.
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version Release: 1.9.4
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since Class available since PHP 4.0.2
|
|
||||||
* @see http://pear.php.net/manual/en/core.ppm.pear-builder.php
|
|
||||||
*/
|
|
||||||
class PEAR_Builder extends PEAR_Common
|
|
||||||
{
|
|
||||||
var $php_api_version = 0;
|
|
||||||
var $zend_module_api_no = 0;
|
|
||||||
var $zend_extension_api_no = 0;
|
|
||||||
|
|
||||||
var $extensions_built = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string Used for reporting when it is not possible to pass function
|
|
||||||
* via extra parameter, e.g. log, msdevCallback
|
|
||||||
*/
|
|
||||||
var $current_callback = null;
|
|
||||||
|
|
||||||
// used for msdev builds
|
|
||||||
var $_lastline = null;
|
|
||||||
var $_firstline = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR_Builder constructor.
|
|
||||||
*
|
|
||||||
* @param object $ui user interface object (instance of PEAR_Frontend_*)
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function PEAR_Builder(&$ui)
|
|
||||||
{
|
|
||||||
parent::PEAR_Common();
|
|
||||||
$this->setFrontendObject($ui);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build an extension from source on windows.
|
|
||||||
* requires msdev
|
|
||||||
*/
|
|
||||||
function _build_win32($descfile, $callback = null)
|
|
||||||
{
|
|
||||||
if (is_object($descfile)) {
|
|
||||||
$pkg = $descfile;
|
|
||||||
$descfile = $pkg->getPackageFile();
|
|
||||||
} else {
|
|
||||||
$pf = &new PEAR_PackageFile($this->config, $this->debug);
|
|
||||||
$pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
|
|
||||||
if (PEAR::isError($pkg)) {
|
|
||||||
return $pkg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$dir = dirname($descfile);
|
|
||||||
$old_cwd = getcwd();
|
|
||||||
|
|
||||||
if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) {
|
|
||||||
return $this->raiseError("could not chdir to $dir");
|
|
||||||
}
|
|
||||||
|
|
||||||
// packages that were in a .tar have the packagefile in this directory
|
|
||||||
$vdir = $pkg->getPackage() . '-' . $pkg->getVersion();
|
|
||||||
if (file_exists($dir) && is_dir($vdir)) {
|
|
||||||
if (!chdir($vdir)) {
|
|
||||||
return $this->raiseError("could not chdir to " . realpath($vdir));
|
|
||||||
}
|
|
||||||
|
|
||||||
$dir = getcwd();
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->log(2, "building in $dir");
|
|
||||||
|
|
||||||
$dsp = $pkg->getPackage().'.dsp';
|
|
||||||
if (!file_exists("$dir/$dsp")) {
|
|
||||||
return $this->raiseError("The DSP $dsp does not exist.");
|
|
||||||
}
|
|
||||||
// XXX TODO: make release build type configurable
|
|
||||||
$command = 'msdev '.$dsp.' /MAKE "'.$pkg->getPackage(). ' - Release"';
|
|
||||||
|
|
||||||
$err = $this->_runCommand($command, array(&$this, 'msdevCallback'));
|
|
||||||
if (PEAR::isError($err)) {
|
|
||||||
return $err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// figure out the build platform and type
|
|
||||||
$platform = 'Win32';
|
|
||||||
$buildtype = 'Release';
|
|
||||||
if (preg_match('/.*?'.$pkg->getPackage().'\s-\s(\w+)\s(.*?)-+/i',$this->_firstline,$matches)) {
|
|
||||||
$platform = $matches[1];
|
|
||||||
$buildtype = $matches[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preg_match('/(.*)?\s-\s(\d+).*?(\d+)/', $this->_lastline, $matches)) {
|
|
||||||
if ($matches[2]) {
|
|
||||||
// there were errors in the build
|
|
||||||
return $this->raiseError("There were errors during compilation.");
|
|
||||||
}
|
|
||||||
$out = $matches[1];
|
|
||||||
} else {
|
|
||||||
return $this->raiseError("Did not understand the completion status returned from msdev.exe.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// msdev doesn't tell us the output directory :/
|
|
||||||
// open the dsp, find /out and use that directory
|
|
||||||
$dsptext = join(file($dsp),'');
|
|
||||||
|
|
||||||
// this regex depends on the build platform and type having been
|
|
||||||
// correctly identified above.
|
|
||||||
$regex ='/.*?!IF\s+"\$\(CFG\)"\s+==\s+("'.
|
|
||||||
$pkg->getPackage().'\s-\s'.
|
|
||||||
$platform.'\s'.
|
|
||||||
$buildtype.'").*?'.
|
|
||||||
'\/out:"(.*?)"/is';
|
|
||||||
|
|
||||||
if ($dsptext && preg_match($regex, $dsptext, $matches)) {
|
|
||||||
// what we get back is a relative path to the output file itself.
|
|
||||||
$outfile = realpath($matches[2]);
|
|
||||||
} else {
|
|
||||||
return $this->raiseError("Could not retrieve output information from $dsp.");
|
|
||||||
}
|
|
||||||
// realpath returns false if the file doesn't exist
|
|
||||||
if ($outfile && copy($outfile, "$dir/$out")) {
|
|
||||||
$outfile = "$dir/$out";
|
|
||||||
}
|
|
||||||
|
|
||||||
$built_files[] = array(
|
|
||||||
'file' => "$outfile",
|
|
||||||
'php_api' => $this->php_api_version,
|
|
||||||
'zend_mod_api' => $this->zend_module_api_no,
|
|
||||||
'zend_ext_api' => $this->zend_extension_api_no,
|
|
||||||
);
|
|
||||||
|
|
||||||
return $built_files;
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
// {{{ msdevCallback()
|
|
||||||
function msdevCallback($what, $data)
|
|
||||||
{
|
|
||||||
if (!$this->_firstline)
|
|
||||||
$this->_firstline = $data;
|
|
||||||
$this->_lastline = $data;
|
|
||||||
call_user_func($this->current_callback, $what, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string
|
|
||||||
* @param string
|
|
||||||
* @param array
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
function _harvestInstDir($dest_prefix, $dirname, &$built_files)
|
|
||||||
{
|
|
||||||
$d = opendir($dirname);
|
|
||||||
if (!$d)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$ret = true;
|
|
||||||
while (($ent = readdir($d)) !== false) {
|
|
||||||
if ($ent{0} == '.')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
$full = $dirname . DIRECTORY_SEPARATOR . $ent;
|
|
||||||
if (is_dir($full)) {
|
|
||||||
if (!$this->_harvestInstDir(
|
|
||||||
$dest_prefix . DIRECTORY_SEPARATOR . $ent,
|
|
||||||
$full, $built_files)) {
|
|
||||||
$ret = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$dest = $dest_prefix . DIRECTORY_SEPARATOR . $ent;
|
|
||||||
$built_files[] = array(
|
|
||||||
'file' => $full,
|
|
||||||
'dest' => $dest,
|
|
||||||
'php_api' => $this->php_api_version,
|
|
||||||
'zend_mod_api' => $this->zend_module_api_no,
|
|
||||||
'zend_ext_api' => $this->zend_extension_api_no,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir($d);
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build an extension from source. Runs "phpize" in the source
|
|
||||||
* directory, but compiles in a temporary directory
|
|
||||||
* (TMPDIR/pear-build-USER/PACKAGE-VERSION).
|
|
||||||
*
|
|
||||||
* @param string|PEAR_PackageFile_v* $descfile path to XML package description file, or
|
|
||||||
* a PEAR_PackageFile object
|
|
||||||
*
|
|
||||||
* @param mixed $callback callback function used to report output,
|
|
||||||
* see PEAR_Builder::_runCommand for details
|
|
||||||
*
|
|
||||||
* @return array an array of associative arrays with built files,
|
|
||||||
* format:
|
|
||||||
* array( array( 'file' => '/path/to/ext.so',
|
|
||||||
* 'php_api' => YYYYMMDD,
|
|
||||||
* 'zend_mod_api' => YYYYMMDD,
|
|
||||||
* 'zend_ext_api' => YYYYMMDD ),
|
|
||||||
* ... )
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*
|
|
||||||
* @see PEAR_Builder::_runCommand
|
|
||||||
*/
|
|
||||||
function build($descfile, $callback = null)
|
|
||||||
{
|
|
||||||
if (preg_match('/(\\/|\\\\|^)([^\\/\\\\]+)?php(.+)?$/',
|
|
||||||
$this->config->get('php_bin'), $matches)) {
|
|
||||||
if (isset($matches[2]) && strlen($matches[2]) &&
|
|
||||||
trim($matches[2]) != trim($this->config->get('php_prefix'))) {
|
|
||||||
$this->log(0, 'WARNING: php_bin ' . $this->config->get('php_bin') .
|
|
||||||
' appears to have a prefix ' . $matches[2] . ', but' .
|
|
||||||
' config variable php_prefix does not match');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($matches[3]) && strlen($matches[3]) &&
|
|
||||||
trim($matches[3]) != trim($this->config->get('php_suffix'))) {
|
|
||||||
$this->log(0, 'WARNING: php_bin ' . $this->config->get('php_bin') .
|
|
||||||
' appears to have a suffix ' . $matches[3] . ', but' .
|
|
||||||
' config variable php_suffix does not match');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->current_callback = $callback;
|
|
||||||
if (PEAR_OS == "Windows") {
|
|
||||||
return $this->_build_win32($descfile, $callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PEAR_OS != 'Unix') {
|
|
||||||
return $this->raiseError("building extensions not supported on this platform");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_object($descfile)) {
|
|
||||||
$pkg = $descfile;
|
|
||||||
$descfile = $pkg->getPackageFile();
|
|
||||||
if (is_a($pkg, 'PEAR_PackageFile_v1')) {
|
|
||||||
$dir = dirname($descfile);
|
|
||||||
} else {
|
|
||||||
$dir = $pkg->_config->get('temp_dir') . '/' . $pkg->getName();
|
|
||||||
// automatically delete at session end
|
|
||||||
$this->addTempFile($dir);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$pf = &new PEAR_PackageFile($this->config);
|
|
||||||
$pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
|
|
||||||
if (PEAR::isError($pkg)) {
|
|
||||||
return $pkg;
|
|
||||||
}
|
|
||||||
$dir = dirname($descfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find config. outside of normal path - e.g. config.m4
|
|
||||||
foreach (array_keys($pkg->getInstallationFileList()) as $item) {
|
|
||||||
if (stristr(basename($item), 'config.m4') && dirname($item) != '.') {
|
|
||||||
$dir .= DIRECTORY_SEPARATOR . dirname($item);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$old_cwd = getcwd();
|
|
||||||
if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) {
|
|
||||||
return $this->raiseError("could not chdir to $dir");
|
|
||||||
}
|
|
||||||
|
|
||||||
$vdir = $pkg->getPackage() . '-' . $pkg->getVersion();
|
|
||||||
if (is_dir($vdir)) {
|
|
||||||
chdir($vdir);
|
|
||||||
}
|
|
||||||
|
|
||||||
$dir = getcwd();
|
|
||||||
$this->log(2, "building in $dir");
|
|
||||||
putenv('PATH=' . $this->config->get('bin_dir') . ':' . getenv('PATH'));
|
|
||||||
$err = $this->_runCommand($this->config->get('php_prefix')
|
|
||||||
. "phpize" .
|
|
||||||
$this->config->get('php_suffix'),
|
|
||||||
array(&$this, 'phpizeCallback'));
|
|
||||||
if (PEAR::isError($err)) {
|
|
||||||
return $err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$err) {
|
|
||||||
return $this->raiseError("`phpize' failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
// {{{ start of interactive part
|
|
||||||
$configure_command = "$dir/configure";
|
|
||||||
$configure_options = $pkg->getConfigureOptions();
|
|
||||||
if ($configure_options) {
|
|
||||||
foreach ($configure_options as $o) {
|
|
||||||
$default = array_key_exists('default', $o) ? $o['default'] : null;
|
|
||||||
list($r) = $this->ui->userDialog('build',
|
|
||||||
array($o['prompt']),
|
|
||||||
array('text'),
|
|
||||||
array($default));
|
|
||||||
if (substr($o['name'], 0, 5) == 'with-' &&
|
|
||||||
($r == 'yes' || $r == 'autodetect')) {
|
|
||||||
$configure_command .= " --$o[name]";
|
|
||||||
} else {
|
|
||||||
$configure_command .= " --$o[name]=".trim($r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// }}} end of interactive part
|
|
||||||
|
|
||||||
// FIXME make configurable
|
|
||||||
if (!$user=getenv('USER')) {
|
|
||||||
$user='defaultuser';
|
|
||||||
}
|
|
||||||
|
|
||||||
$tmpdir = $this->config->get('temp_dir');
|
|
||||||
$build_basedir = System::mktemp(' -t "' . $tmpdir . '" -d "pear-build-' . $user . '"');
|
|
||||||
$build_dir = "$build_basedir/$vdir";
|
|
||||||
$inst_dir = "$build_basedir/install-$vdir";
|
|
||||||
$this->log(1, "building in $build_dir");
|
|
||||||
if (is_dir($build_dir)) {
|
|
||||||
System::rm(array('-rf', $build_dir));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!System::mkDir(array('-p', $build_dir))) {
|
|
||||||
return $this->raiseError("could not create build dir: $build_dir");
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->addTempFile($build_dir);
|
|
||||||
if (!System::mkDir(array('-p', $inst_dir))) {
|
|
||||||
return $this->raiseError("could not create temporary install dir: $inst_dir");
|
|
||||||
}
|
|
||||||
$this->addTempFile($inst_dir);
|
|
||||||
|
|
||||||
$make_command = getenv('MAKE') ? getenv('MAKE') : 'make';
|
|
||||||
|
|
||||||
$to_run = array(
|
|
||||||
$configure_command,
|
|
||||||
$make_command,
|
|
||||||
"$make_command INSTALL_ROOT=\"$inst_dir\" install",
|
|
||||||
"find \"$inst_dir\" | xargs ls -dils"
|
|
||||||
);
|
|
||||||
if (!file_exists($build_dir) || !is_dir($build_dir) || !chdir($build_dir)) {
|
|
||||||
return $this->raiseError("could not chdir to $build_dir");
|
|
||||||
}
|
|
||||||
putenv('PHP_PEAR_VERSION=1.9.4');
|
|
||||||
foreach ($to_run as $cmd) {
|
|
||||||
$err = $this->_runCommand($cmd, $callback);
|
|
||||||
if (PEAR::isError($err)) {
|
|
||||||
chdir($old_cwd);
|
|
||||||
return $err;
|
|
||||||
}
|
|
||||||
if (!$err) {
|
|
||||||
chdir($old_cwd);
|
|
||||||
return $this->raiseError("`$cmd' failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!($dp = opendir("modules"))) {
|
|
||||||
chdir($old_cwd);
|
|
||||||
return $this->raiseError("no `modules' directory found");
|
|
||||||
}
|
|
||||||
$built_files = array();
|
|
||||||
$prefix = exec($this->config->get('php_prefix')
|
|
||||||
. "php-config" .
|
|
||||||
$this->config->get('php_suffix') . " --prefix");
|
|
||||||
$this->_harvestInstDir($prefix, $inst_dir . DIRECTORY_SEPARATOR . $prefix, $built_files);
|
|
||||||
chdir($old_cwd);
|
|
||||||
return $built_files;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Message callback function used when running the "phpize"
|
|
||||||
* program. Extracts the API numbers used. Ignores other message
|
|
||||||
* types than "cmdoutput".
|
|
||||||
*
|
|
||||||
* @param string $what the type of message
|
|
||||||
* @param mixed $data the message
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function phpizeCallback($what, $data)
|
|
||||||
{
|
|
||||||
if ($what != 'cmdoutput') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$this->log(1, rtrim($data));
|
|
||||||
if (preg_match('/You should update your .aclocal.m4/', $data)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$matches = array();
|
|
||||||
if (preg_match('/^\s+(\S[^:]+):\s+(\d{8})/', $data, $matches)) {
|
|
||||||
$member = preg_replace('/[^a-z]/', '_', strtolower($matches[1]));
|
|
||||||
$apino = (int)$matches[2];
|
|
||||||
if (isset($this->$member)) {
|
|
||||||
$this->$member = $apino;
|
|
||||||
//$msg = sprintf("%-22s : %d", $matches[1], $apino);
|
|
||||||
//$this->log(1, $msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run an external command, using a message callback to report
|
|
||||||
* output. The command will be run through popen and output is
|
|
||||||
* reported for every line with a "cmdoutput" message with the
|
|
||||||
* line string, including newlines, as payload.
|
|
||||||
*
|
|
||||||
* @param string $command the command to run
|
|
||||||
*
|
|
||||||
* @param mixed $callback (optional) function to use as message
|
|
||||||
* callback
|
|
||||||
*
|
|
||||||
* @return bool whether the command was successful (exit code 0
|
|
||||||
* means success, any other means failure)
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
function _runCommand($command, $callback = null)
|
|
||||||
{
|
|
||||||
$this->log(1, "running: $command");
|
|
||||||
$pp = popen("$command 2>&1", "r");
|
|
||||||
if (!$pp) {
|
|
||||||
return $this->raiseError("failed to run `$command'");
|
|
||||||
}
|
|
||||||
if ($callback && $callback[0]->debug == 1) {
|
|
||||||
$olddbg = $callback[0]->debug;
|
|
||||||
$callback[0]->debug = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ($line = fgets($pp, 1024)) {
|
|
||||||
if ($callback) {
|
|
||||||
call_user_func($callback, 'cmdoutput', $line);
|
|
||||||
} else {
|
|
||||||
$this->log(2, rtrim($line));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($callback && isset($olddbg)) {
|
|
||||||
$callback[0]->debug = $olddbg;
|
|
||||||
}
|
|
||||||
|
|
||||||
$exitcode = is_resource($pp) ? pclose($pp) : -1;
|
|
||||||
return ($exitcode == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function log($level, $msg)
|
|
||||||
{
|
|
||||||
if ($this->current_callback) {
|
|
||||||
if ($this->debug >= $level) {
|
|
||||||
call_user_func($this->current_callback, 'output', $msg);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return PEAR_Common::log($level, $msg);
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,68 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* PEAR_ChannelFile_Parser for parsing channel.xml
|
|
||||||
*
|
|
||||||
* PHP versions 4 and 5
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version CVS: $Id: Parser.php 313023 2011-07-06 19:17:11Z dufuz $
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since File available since Release 1.4.0a1
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* base xml parser class
|
|
||||||
*/
|
|
||||||
require_once 'PEAR/XMLParser.php';
|
|
||||||
require_once 'PEAR/ChannelFile.php';
|
|
||||||
/**
|
|
||||||
* Parser for channel.xml
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version Release: 1.9.4
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since Class available since Release 1.4.0a1
|
|
||||||
*/
|
|
||||||
class PEAR_ChannelFile_Parser extends PEAR_XMLParser
|
|
||||||
{
|
|
||||||
var $_config;
|
|
||||||
var $_logger;
|
|
||||||
var $_registry;
|
|
||||||
|
|
||||||
function setConfig(&$c)
|
|
||||||
{
|
|
||||||
$this->_config = &$c;
|
|
||||||
$this->_registry = &$c->getRegistry();
|
|
||||||
}
|
|
||||||
|
|
||||||
function setLogger(&$l)
|
|
||||||
{
|
|
||||||
$this->_logger = &$l;
|
|
||||||
}
|
|
||||||
|
|
||||||
function parse($data, $file)
|
|
||||||
{
|
|
||||||
if (PEAR::isError($err = parent::parse($data, $file))) {
|
|
||||||
return $err;
|
|
||||||
}
|
|
||||||
|
|
||||||
$ret = new PEAR_ChannelFile;
|
|
||||||
$ret->setConfig($this->_config);
|
|
||||||
if (isset($this->_logger)) {
|
|
||||||
$ret->setLogger($this->_logger);
|
|
||||||
}
|
|
||||||
|
|
||||||
$ret->fromArray($this->_unserializedData);
|
|
||||||
// make sure the filelist is in the easy to read format needed
|
|
||||||
$ret->flattenFilelist();
|
|
||||||
$ret->setPackagefile($file, $archive);
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,414 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* PEAR_Command, command pattern class
|
|
||||||
*
|
|
||||||
* PHP versions 4 and 5
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version CVS: $Id: Command.php 313023 2011-07-06 19:17:11Z dufuz $
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since File available since Release 0.1
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Needed for error handling
|
|
||||||
*/
|
|
||||||
require_once 'PEAR.php';
|
|
||||||
require_once 'PEAR/Frontend.php';
|
|
||||||
require_once 'PEAR/XMLParser.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of commands and what classes they are implemented in.
|
|
||||||
* @var array command => implementing class
|
|
||||||
*/
|
|
||||||
$GLOBALS['_PEAR_Command_commandlist'] = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of commands and their descriptions
|
|
||||||
* @var array command => description
|
|
||||||
*/
|
|
||||||
$GLOBALS['_PEAR_Command_commanddesc'] = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of shortcuts to common commands.
|
|
||||||
* @var array shortcut => command
|
|
||||||
*/
|
|
||||||
$GLOBALS['_PEAR_Command_shortcuts'] = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Array of command objects
|
|
||||||
* @var array class => object
|
|
||||||
*/
|
|
||||||
$GLOBALS['_PEAR_Command_objects'] = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR command class, a simple factory class for administrative
|
|
||||||
* commands.
|
|
||||||
*
|
|
||||||
* How to implement command classes:
|
|
||||||
*
|
|
||||||
* - The class must be called PEAR_Command_Nnn, installed in the
|
|
||||||
* "PEAR/Common" subdir, with a method called getCommands() that
|
|
||||||
* returns an array of the commands implemented by the class (see
|
|
||||||
* PEAR/Command/Install.php for an example).
|
|
||||||
*
|
|
||||||
* - The class must implement a run() function that is called with three
|
|
||||||
* params:
|
|
||||||
*
|
|
||||||
* (string) command name
|
|
||||||
* (array) assoc array with options, freely defined by each
|
|
||||||
* command, for example:
|
|
||||||
* array('force' => true)
|
|
||||||
* (array) list of the other parameters
|
|
||||||
*
|
|
||||||
* The run() function returns a PEAR_CommandResponse object. Use
|
|
||||||
* these methods to get information:
|
|
||||||
*
|
|
||||||
* int getStatus() Returns PEAR_COMMAND_(SUCCESS|FAILURE|PARTIAL)
|
|
||||||
* *_PARTIAL means that you need to issue at least
|
|
||||||
* one more command to complete the operation
|
|
||||||
* (used for example for validation steps).
|
|
||||||
*
|
|
||||||
* string getMessage() Returns a message for the user. Remember,
|
|
||||||
* no HTML or other interface-specific markup.
|
|
||||||
*
|
|
||||||
* If something unexpected happens, run() returns a PEAR error.
|
|
||||||
*
|
|
||||||
* - DON'T OUTPUT ANYTHING! Return text for output instead.
|
|
||||||
*
|
|
||||||
* - DON'T USE HTML! The text you return will be used from both Gtk,
|
|
||||||
* web and command-line interfaces, so for now, keep everything to
|
|
||||||
* plain text.
|
|
||||||
*
|
|
||||||
* - DON'T USE EXIT OR DIE! Always use pear errors. From static
|
|
||||||
* classes do PEAR::raiseError(), from other classes do
|
|
||||||
* $this->raiseError().
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version Release: 1.9.4
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since Class available since Release 0.1
|
|
||||||
*/
|
|
||||||
class PEAR_Command
|
|
||||||
{
|
|
||||||
// {{{ factory()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the right object for executing a command.
|
|
||||||
*
|
|
||||||
* @param string $command The name of the command
|
|
||||||
* @param object $config Instance of PEAR_Config object
|
|
||||||
*
|
|
||||||
* @return object the command object or a PEAR error
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function &factory($command, &$config)
|
|
||||||
{
|
|
||||||
if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
|
|
||||||
PEAR_Command::registerCommands();
|
|
||||||
}
|
|
||||||
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
|
|
||||||
$command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
|
|
||||||
}
|
|
||||||
if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
|
|
||||||
$a = PEAR::raiseError("unknown command `$command'");
|
|
||||||
return $a;
|
|
||||||
}
|
|
||||||
$class = $GLOBALS['_PEAR_Command_commandlist'][$command];
|
|
||||||
if (!class_exists($class)) {
|
|
||||||
require_once $GLOBALS['_PEAR_Command_objects'][$class];
|
|
||||||
}
|
|
||||||
if (!class_exists($class)) {
|
|
||||||
$a = PEAR::raiseError("unknown command `$command'");
|
|
||||||
return $a;
|
|
||||||
}
|
|
||||||
$ui = PEAR_Command::getFrontendObject();
|
|
||||||
$obj = new $class($ui, $config);
|
|
||||||
return $obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ & getObject()
|
|
||||||
function &getObject($command)
|
|
||||||
{
|
|
||||||
$class = $GLOBALS['_PEAR_Command_commandlist'][$command];
|
|
||||||
if (!class_exists($class)) {
|
|
||||||
require_once $GLOBALS['_PEAR_Command_objects'][$class];
|
|
||||||
}
|
|
||||||
if (!class_exists($class)) {
|
|
||||||
return PEAR::raiseError("unknown command `$command'");
|
|
||||||
}
|
|
||||||
$ui = PEAR_Command::getFrontendObject();
|
|
||||||
$config = &PEAR_Config::singleton();
|
|
||||||
$obj = &new $class($ui, $config);
|
|
||||||
return $obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ & getFrontendObject()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get instance of frontend object.
|
|
||||||
*
|
|
||||||
* @return object|PEAR_Error
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function &getFrontendObject()
|
|
||||||
{
|
|
||||||
$a = &PEAR_Frontend::singleton();
|
|
||||||
return $a;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ & setFrontendClass()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load current frontend class.
|
|
||||||
*
|
|
||||||
* @param string $uiclass Name of class implementing the frontend
|
|
||||||
*
|
|
||||||
* @return object the frontend object, or a PEAR error
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function &setFrontendClass($uiclass)
|
|
||||||
{
|
|
||||||
$a = &PEAR_Frontend::setFrontendClass($uiclass);
|
|
||||||
return $a;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ setFrontendType()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set current frontend.
|
|
||||||
*
|
|
||||||
* @param string $uitype Name of the frontend type (for example "CLI")
|
|
||||||
*
|
|
||||||
* @return object the frontend object, or a PEAR error
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function setFrontendType($uitype)
|
|
||||||
{
|
|
||||||
$uiclass = 'PEAR_Frontend_' . $uitype;
|
|
||||||
return PEAR_Command::setFrontendClass($uiclass);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ registerCommands()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Scan through the Command directory looking for classes
|
|
||||||
* and see what commands they implement.
|
|
||||||
*
|
|
||||||
* @param bool (optional) if FALSE (default), the new list of
|
|
||||||
* commands should replace the current one. If TRUE,
|
|
||||||
* new entries will be merged with old.
|
|
||||||
*
|
|
||||||
* @param string (optional) where (what directory) to look for
|
|
||||||
* classes, defaults to the Command subdirectory of
|
|
||||||
* the directory from where this file (__FILE__) is
|
|
||||||
* included.
|
|
||||||
*
|
|
||||||
* @return bool TRUE on success, a PEAR error on failure
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function registerCommands($merge = false, $dir = null)
|
|
||||||
{
|
|
||||||
$parser = new PEAR_XMLParser;
|
|
||||||
if ($dir === null) {
|
|
||||||
$dir = dirname(__FILE__) . '/Command';
|
|
||||||
}
|
|
||||||
if (!is_dir($dir)) {
|
|
||||||
return PEAR::raiseError("registerCommands: opendir($dir) '$dir' does not exist or is not a directory");
|
|
||||||
}
|
|
||||||
$dp = @opendir($dir);
|
|
||||||
if (empty($dp)) {
|
|
||||||
return PEAR::raiseError("registerCommands: opendir($dir) failed");
|
|
||||||
}
|
|
||||||
if (!$merge) {
|
|
||||||
$GLOBALS['_PEAR_Command_commandlist'] = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
while ($file = readdir($dp)) {
|
|
||||||
if ($file{0} == '.' || substr($file, -4) != '.xml') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$f = substr($file, 0, -4);
|
|
||||||
$class = "PEAR_Command_" . $f;
|
|
||||||
// List of commands
|
|
||||||
if (empty($GLOBALS['_PEAR_Command_objects'][$class])) {
|
|
||||||
$GLOBALS['_PEAR_Command_objects'][$class] = "$dir/" . $f . '.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
$parser->parse(file_get_contents("$dir/$file"));
|
|
||||||
$implements = $parser->getData();
|
|
||||||
foreach ($implements as $command => $desc) {
|
|
||||||
if ($command == 'attribs') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
|
|
||||||
return PEAR::raiseError('Command "' . $command . '" already registered in ' .
|
|
||||||
'class "' . $GLOBALS['_PEAR_Command_commandlist'][$command] . '"');
|
|
||||||
}
|
|
||||||
|
|
||||||
$GLOBALS['_PEAR_Command_commandlist'][$command] = $class;
|
|
||||||
$GLOBALS['_PEAR_Command_commanddesc'][$command] = $desc['summary'];
|
|
||||||
if (isset($desc['shortcut'])) {
|
|
||||||
$shortcut = $desc['shortcut'];
|
|
||||||
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$shortcut])) {
|
|
||||||
return PEAR::raiseError('Command shortcut "' . $shortcut . '" already ' .
|
|
||||||
'registered to command "' . $command . '" in class "' .
|
|
||||||
$GLOBALS['_PEAR_Command_commandlist'][$command] . '"');
|
|
||||||
}
|
|
||||||
$GLOBALS['_PEAR_Command_shortcuts'][$shortcut] = $command;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($desc['options']) && $desc['options']) {
|
|
||||||
foreach ($desc['options'] as $oname => $option) {
|
|
||||||
if (isset($option['shortopt']) && strlen($option['shortopt']) > 1) {
|
|
||||||
return PEAR::raiseError('Option "' . $oname . '" short option "' .
|
|
||||||
$option['shortopt'] . '" must be ' .
|
|
||||||
'only 1 character in Command "' . $command . '" in class "' .
|
|
||||||
$class . '"');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ksort($GLOBALS['_PEAR_Command_shortcuts']);
|
|
||||||
ksort($GLOBALS['_PEAR_Command_commandlist']);
|
|
||||||
@closedir($dp);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getCommands()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the list of currently supported commands, and what
|
|
||||||
* classes implement them.
|
|
||||||
*
|
|
||||||
* @return array command => implementing class
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function getCommands()
|
|
||||||
{
|
|
||||||
if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
|
|
||||||
PEAR_Command::registerCommands();
|
|
||||||
}
|
|
||||||
return $GLOBALS['_PEAR_Command_commandlist'];
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getShortcuts()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the list of command shortcuts.
|
|
||||||
*
|
|
||||||
* @return array shortcut => command
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function getShortcuts()
|
|
||||||
{
|
|
||||||
if (empty($GLOBALS['_PEAR_Command_shortcuts'])) {
|
|
||||||
PEAR_Command::registerCommands();
|
|
||||||
}
|
|
||||||
return $GLOBALS['_PEAR_Command_shortcuts'];
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getGetoptArgs()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compiles arguments for getopt.
|
|
||||||
*
|
|
||||||
* @param string $command command to get optstring for
|
|
||||||
* @param string $short_args (reference) short getopt format
|
|
||||||
* @param array $long_args (reference) long getopt format
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function getGetoptArgs($command, &$short_args, &$long_args)
|
|
||||||
{
|
|
||||||
if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
|
|
||||||
PEAR_Command::registerCommands();
|
|
||||||
}
|
|
||||||
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
|
|
||||||
$command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
|
|
||||||
}
|
|
||||||
if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
$obj = &PEAR_Command::getObject($command);
|
|
||||||
return $obj->getGetoptArgs($command, $short_args, $long_args);
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getDescription()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get description for a command.
|
|
||||||
*
|
|
||||||
* @param string $command Name of the command
|
|
||||||
*
|
|
||||||
* @return string command description
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function getDescription($command)
|
|
||||||
{
|
|
||||||
if (!isset($GLOBALS['_PEAR_Command_commanddesc'][$command])) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return $GLOBALS['_PEAR_Command_commanddesc'][$command];
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
// {{{ getHelp()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get help for command.
|
|
||||||
*
|
|
||||||
* @param string $command Name of the command to return help for
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function getHelp($command)
|
|
||||||
{
|
|
||||||
$cmds = PEAR_Command::getCommands();
|
|
||||||
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
|
|
||||||
$command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
|
|
||||||
}
|
|
||||||
if (isset($cmds[$command])) {
|
|
||||||
$obj = &PEAR_Command::getObject($command);
|
|
||||||
return $obj->getHelp($command);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
}
|
|
|
@ -1,81 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* PEAR_Command_Auth (login, logout commands)
|
|
||||||
*
|
|
||||||
* PHP versions 4 and 5
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version CVS: $Id: Auth.php 313023 2011-07-06 19:17:11Z dufuz $
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since File available since Release 0.1
|
|
||||||
* @deprecated since 1.8.0alpha1
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* base class
|
|
||||||
*/
|
|
||||||
require_once 'PEAR/Command/Channels.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR commands for login/logout
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version Release: 1.9.4
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since Class available since Release 0.1
|
|
||||||
* @deprecated since 1.8.0alpha1
|
|
||||||
*/
|
|
||||||
class PEAR_Command_Auth extends PEAR_Command_Channels
|
|
||||||
{
|
|
||||||
var $commands = array(
|
|
||||||
'login' => array(
|
|
||||||
'summary' => 'Connects and authenticates to remote server [Deprecated in favor of channel-login]',
|
|
||||||
'shortcut' => 'li',
|
|
||||||
'function' => 'doLogin',
|
|
||||||
'options' => array(),
|
|
||||||
'doc' => '<channel name>
|
|
||||||
WARNING: This function is deprecated in favor of using channel-login
|
|
||||||
|
|
||||||
Log in to a remote channel server. If <channel name> is not supplied,
|
|
||||||
the default channel is used. To use remote functions in the installer
|
|
||||||
that require any kind of privileges, you need to log in first. The
|
|
||||||
username and password you enter here will be stored in your per-user
|
|
||||||
PEAR configuration (~/.pearrc on Unix-like systems). After logging
|
|
||||||
in, your username and password will be sent along in subsequent
|
|
||||||
operations on the remote server.',
|
|
||||||
),
|
|
||||||
'logout' => array(
|
|
||||||
'summary' => 'Logs out from the remote server [Deprecated in favor of channel-logout]',
|
|
||||||
'shortcut' => 'lo',
|
|
||||||
'function' => 'doLogout',
|
|
||||||
'options' => array(),
|
|
||||||
'doc' => '
|
|
||||||
WARNING: This function is deprecated in favor of using channel-logout
|
|
||||||
|
|
||||||
Logs out from the remote server. This command does not actually
|
|
||||||
connect to the remote server, it only deletes the stored username and
|
|
||||||
password from your user configuration.',
|
|
||||||
)
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR_Command_Auth constructor.
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function PEAR_Command_Auth(&$ui, &$config)
|
|
||||||
{
|
|
||||||
parent::PEAR_Command_Channels($ui, $config);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
<commands version="1.0">
|
|
||||||
<login>
|
|
||||||
<summary>Connects and authenticates to remote server [Deprecated in favor of channel-login]</summary>
|
|
||||||
<function>doLogin</function>
|
|
||||||
<shortcut>li</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc><channel name>
|
|
||||||
WARNING: This function is deprecated in favor of using channel-login
|
|
||||||
|
|
||||||
Log in to a remote channel server. If <channel name> is not supplied,
|
|
||||||
the default channel is used. To use remote functions in the installer
|
|
||||||
that require any kind of privileges, you need to log in first. The
|
|
||||||
username and password you enter here will be stored in your per-user
|
|
||||||
PEAR configuration (~/.pearrc on Unix-like systems). After logging
|
|
||||||
in, your username and password will be sent along in subsequent
|
|
||||||
operations on the remote server.</doc>
|
|
||||||
</login>
|
|
||||||
<logout>
|
|
||||||
<summary>Logs out from the remote server [Deprecated in favor of channel-logout]</summary>
|
|
||||||
<function>doLogout</function>
|
|
||||||
<shortcut>lo</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc>
|
|
||||||
WARNING: This function is deprecated in favor of using channel-logout
|
|
||||||
|
|
||||||
Logs out from the remote server. This command does not actually
|
|
||||||
connect to the remote server, it only deletes the stored username and
|
|
||||||
password from your user configuration.</doc>
|
|
||||||
</logout>
|
|
||||||
</commands>
|
|
|
@ -1,85 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* PEAR_Command_Auth (build command)
|
|
||||||
*
|
|
||||||
* PHP versions 4 and 5
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Tomas V.V.Cox <cox@idecnet.com>
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version CVS: $Id: Build.php 313023 2011-07-06 19:17:11Z dufuz $
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since File available since Release 0.1
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* base class
|
|
||||||
*/
|
|
||||||
require_once 'PEAR/Command/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR commands for building extensions.
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Tomas V.V.Cox <cox@idecnet.com>
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version Release: 1.9.4
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since Class available since Release 0.1
|
|
||||||
*/
|
|
||||||
class PEAR_Command_Build extends PEAR_Command_Common
|
|
||||||
{
|
|
||||||
var $commands = array(
|
|
||||||
'build' => array(
|
|
||||||
'summary' => 'Build an Extension From C Source',
|
|
||||||
'function' => 'doBuild',
|
|
||||||
'shortcut' => 'b',
|
|
||||||
'options' => array(),
|
|
||||||
'doc' => '[package.xml]
|
|
||||||
Builds one or more extensions contained in a package.'
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR_Command_Build constructor.
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function PEAR_Command_Build(&$ui, &$config)
|
|
||||||
{
|
|
||||||
parent::PEAR_Command_Common($ui, $config);
|
|
||||||
}
|
|
||||||
|
|
||||||
function doBuild($command, $options, $params)
|
|
||||||
{
|
|
||||||
require_once 'PEAR/Builder.php';
|
|
||||||
if (sizeof($params) < 1) {
|
|
||||||
$params[0] = 'package.xml';
|
|
||||||
}
|
|
||||||
|
|
||||||
$builder = &new PEAR_Builder($this->ui);
|
|
||||||
$this->debug = $this->config->get('verbose');
|
|
||||||
$err = $builder->build($params[0], array(&$this, 'buildCallback'));
|
|
||||||
if (PEAR::isError($err)) {
|
|
||||||
return $err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildCallback($what, $data)
|
|
||||||
{
|
|
||||||
if (($what == 'cmdoutput' && $this->debug > 1) ||
|
|
||||||
($what == 'output' && $this->debug > 0)) {
|
|
||||||
$this->ui->outputData(rtrim($data), 'build');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
<commands version="1.0">
|
|
||||||
<build>
|
|
||||||
<summary>Build an Extension From C Source</summary>
|
|
||||||
<function>doBuild</function>
|
|
||||||
<shortcut>b</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc>[package.xml]
|
|
||||||
Builds one or more extensions contained in a package.</doc>
|
|
||||||
</build>
|
|
||||||
</commands>
|
|
|
@ -1,883 +0,0 @@
|
||||||
<?php
|
|
||||||
// /* vim: set expandtab tabstop=4 shiftwidth=4: */
|
|
||||||
/**
|
|
||||||
* PEAR_Command_Channels (list-channels, update-channels, channel-delete, channel-add,
|
|
||||||
* channel-update, channel-info, channel-alias, channel-discover commands)
|
|
||||||
*
|
|
||||||
* PHP versions 4 and 5
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version CVS: $Id: Channels.php 313023 2011-07-06 19:17:11Z dufuz $
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since File available since Release 1.4.0a1
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* base class
|
|
||||||
*/
|
|
||||||
require_once 'PEAR/Command/Common.php';
|
|
||||||
|
|
||||||
define('PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS', -500);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR commands for managing channels.
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version Release: 1.9.4
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since Class available since Release 1.4.0a1
|
|
||||||
*/
|
|
||||||
class PEAR_Command_Channels extends PEAR_Command_Common
|
|
||||||
{
|
|
||||||
var $commands = array(
|
|
||||||
'list-channels' => array(
|
|
||||||
'summary' => 'List Available Channels',
|
|
||||||
'function' => 'doList',
|
|
||||||
'shortcut' => 'lc',
|
|
||||||
'options' => array(),
|
|
||||||
'doc' => '
|
|
||||||
List all available channels for installation.
|
|
||||||
',
|
|
||||||
),
|
|
||||||
'update-channels' => array(
|
|
||||||
'summary' => 'Update the Channel List',
|
|
||||||
'function' => 'doUpdateAll',
|
|
||||||
'shortcut' => 'uc',
|
|
||||||
'options' => array(),
|
|
||||||
'doc' => '
|
|
||||||
List all installed packages in all channels.
|
|
||||||
'
|
|
||||||
),
|
|
||||||
'channel-delete' => array(
|
|
||||||
'summary' => 'Remove a Channel From the List',
|
|
||||||
'function' => 'doDelete',
|
|
||||||
'shortcut' => 'cde',
|
|
||||||
'options' => array(),
|
|
||||||
'doc' => '<channel name>
|
|
||||||
Delete a channel from the registry. You may not
|
|
||||||
remove any channel that has installed packages.
|
|
||||||
'
|
|
||||||
),
|
|
||||||
'channel-add' => array(
|
|
||||||
'summary' => 'Add a Channel',
|
|
||||||
'function' => 'doAdd',
|
|
||||||
'shortcut' => 'ca',
|
|
||||||
'options' => array(),
|
|
||||||
'doc' => '<channel.xml>
|
|
||||||
Add a private channel to the channel list. Note that all
|
|
||||||
public channels should be synced using "update-channels".
|
|
||||||
Parameter may be either a local file or remote URL to a
|
|
||||||
channel.xml.
|
|
||||||
'
|
|
||||||
),
|
|
||||||
'channel-update' => array(
|
|
||||||
'summary' => 'Update an Existing Channel',
|
|
||||||
'function' => 'doUpdate',
|
|
||||||
'shortcut' => 'cu',
|
|
||||||
'options' => array(
|
|
||||||
'force' => array(
|
|
||||||
'shortopt' => 'f',
|
|
||||||
'doc' => 'will force download of new channel.xml if an existing channel name is used',
|
|
||||||
),
|
|
||||||
'channel' => array(
|
|
||||||
'shortopt' => 'c',
|
|
||||||
'arg' => 'CHANNEL',
|
|
||||||
'doc' => 'will force download of new channel.xml if an existing channel name is used',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
'doc' => '[<channel.xml>|<channel name>]
|
|
||||||
Update a channel in the channel list directly. Note that all
|
|
||||||
public channels can be synced using "update-channels".
|
|
||||||
Parameter may be a local or remote channel.xml, or the name of
|
|
||||||
an existing channel.
|
|
||||||
'
|
|
||||||
),
|
|
||||||
'channel-info' => array(
|
|
||||||
'summary' => 'Retrieve Information on a Channel',
|
|
||||||
'function' => 'doInfo',
|
|
||||||
'shortcut' => 'ci',
|
|
||||||
'options' => array(),
|
|
||||||
'doc' => '<package>
|
|
||||||
List the files in an installed package.
|
|
||||||
'
|
|
||||||
),
|
|
||||||
'channel-alias' => array(
|
|
||||||
'summary' => 'Specify an alias to a channel name',
|
|
||||||
'function' => 'doAlias',
|
|
||||||
'shortcut' => 'cha',
|
|
||||||
'options' => array(),
|
|
||||||
'doc' => '<channel> <alias>
|
|
||||||
Specify a specific alias to use for a channel name.
|
|
||||||
The alias may not be an existing channel name or
|
|
||||||
alias.
|
|
||||||
'
|
|
||||||
),
|
|
||||||
'channel-discover' => array(
|
|
||||||
'summary' => 'Initialize a Channel from its server',
|
|
||||||
'function' => 'doDiscover',
|
|
||||||
'shortcut' => 'di',
|
|
||||||
'options' => array(),
|
|
||||||
'doc' => '[<channel.xml>|<channel name>]
|
|
||||||
Initialize a channel from its server and create a local channel.xml.
|
|
||||||
If <channel name> is in the format "<username>:<password>@<channel>" then
|
|
||||||
<username> and <password> will be set as the login username/password for
|
|
||||||
<channel>. Use caution when passing the username/password in this way, as
|
|
||||||
it may allow other users on your computer to briefly view your username/
|
|
||||||
password via the system\'s process list.
|
|
||||||
'
|
|
||||||
),
|
|
||||||
'channel-login' => array(
|
|
||||||
'summary' => 'Connects and authenticates to remote channel server',
|
|
||||||
'shortcut' => 'cli',
|
|
||||||
'function' => 'doLogin',
|
|
||||||
'options' => array(),
|
|
||||||
'doc' => '<channel name>
|
|
||||||
Log in to a remote channel server. If <channel name> is not supplied,
|
|
||||||
the default channel is used. To use remote functions in the installer
|
|
||||||
that require any kind of privileges, you need to log in first. The
|
|
||||||
username and password you enter here will be stored in your per-user
|
|
||||||
PEAR configuration (~/.pearrc on Unix-like systems). After logging
|
|
||||||
in, your username and password will be sent along in subsequent
|
|
||||||
operations on the remote server.',
|
|
||||||
),
|
|
||||||
'channel-logout' => array(
|
|
||||||
'summary' => 'Logs out from the remote channel server',
|
|
||||||
'shortcut' => 'clo',
|
|
||||||
'function' => 'doLogout',
|
|
||||||
'options' => array(),
|
|
||||||
'doc' => '<channel name>
|
|
||||||
Logs out from a remote channel server. If <channel name> is not supplied,
|
|
||||||
the default channel is used. This command does not actually connect to the
|
|
||||||
remote server, it only deletes the stored username and password from your user
|
|
||||||
configuration.',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR_Command_Registry constructor.
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function PEAR_Command_Channels(&$ui, &$config)
|
|
||||||
{
|
|
||||||
parent::PEAR_Command_Common($ui, $config);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _sortChannels($a, $b)
|
|
||||||
{
|
|
||||||
return strnatcasecmp($a->getName(), $b->getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
function doList($command, $options, $params)
|
|
||||||
{
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
$registered = $reg->getChannels();
|
|
||||||
usort($registered, array(&$this, '_sortchannels'));
|
|
||||||
$i = $j = 0;
|
|
||||||
$data = array(
|
|
||||||
'caption' => 'Registered Channels:',
|
|
||||||
'border' => true,
|
|
||||||
'headline' => array('Channel', 'Alias', 'Summary')
|
|
||||||
);
|
|
||||||
foreach ($registered as $channel) {
|
|
||||||
$data['data'][] = array($channel->getName(),
|
|
||||||
$channel->getAlias(),
|
|
||||||
$channel->getSummary());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($registered) === 0) {
|
|
||||||
$data = '(no registered channels)';
|
|
||||||
}
|
|
||||||
$this->ui->outputData($data, $command);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function doUpdateAll($command, $options, $params)
|
|
||||||
{
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
$channels = $reg->getChannels();
|
|
||||||
|
|
||||||
$success = true;
|
|
||||||
foreach ($channels as $channel) {
|
|
||||||
if ($channel->getName() != '__uri') {
|
|
||||||
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
|
|
||||||
$err = $this->doUpdate('channel-update',
|
|
||||||
$options,
|
|
||||||
array($channel->getName()));
|
|
||||||
if (PEAR::isError($err)) {
|
|
||||||
$this->ui->outputData($err->getMessage(), $command);
|
|
||||||
$success = false;
|
|
||||||
} else {
|
|
||||||
$success &= $err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $success;
|
|
||||||
}
|
|
||||||
|
|
||||||
function doInfo($command, $options, $params)
|
|
||||||
{
|
|
||||||
if (count($params) !== 1) {
|
|
||||||
return $this->raiseError("No channel specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
$channel = strtolower($params[0]);
|
|
||||||
if ($reg->channelExists($channel)) {
|
|
||||||
$chan = $reg->getChannel($channel);
|
|
||||||
if (PEAR::isError($chan)) {
|
|
||||||
return $this->raiseError($chan);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (strpos($channel, '://')) {
|
|
||||||
$downloader = &$this->getDownloader();
|
|
||||||
$tmpdir = $this->config->get('temp_dir');
|
|
||||||
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
|
|
||||||
$loc = $downloader->downloadHttp($channel, $this->ui, $tmpdir);
|
|
||||||
PEAR::staticPopErrorHandling();
|
|
||||||
if (PEAR::isError($loc)) {
|
|
||||||
return $this->raiseError('Cannot open "' . $channel .
|
|
||||||
'" (' . $loc->getMessage() . ')');
|
|
||||||
} else {
|
|
||||||
$contents = implode('', file($loc));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!file_exists($params[0])) {
|
|
||||||
return $this->raiseError('Unknown channel "' . $channel . '"');
|
|
||||||
}
|
|
||||||
|
|
||||||
$fp = fopen($params[0], 'r');
|
|
||||||
if (!$fp) {
|
|
||||||
return $this->raiseError('Cannot open "' . $params[0] . '"');
|
|
||||||
}
|
|
||||||
|
|
||||||
$contents = '';
|
|
||||||
while (!feof($fp)) {
|
|
||||||
$contents .= fread($fp, 1024);
|
|
||||||
}
|
|
||||||
fclose($fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!class_exists('PEAR_ChannelFile')) {
|
|
||||||
require_once 'PEAR/ChannelFile.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
$chan = new PEAR_ChannelFile;
|
|
||||||
$chan->fromXmlString($contents);
|
|
||||||
$chan->validate();
|
|
||||||
if ($errs = $chan->getErrors(true)) {
|
|
||||||
foreach ($errs as $err) {
|
|
||||||
$this->ui->outputData($err['level'] . ': ' . $err['message']);
|
|
||||||
}
|
|
||||||
return $this->raiseError('Channel file "' . $params[0] . '" is not valid');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$chan) {
|
|
||||||
return $this->raiseError('Serious error: Channel "' . $params[0] .
|
|
||||||
'" has a corrupted registry entry');
|
|
||||||
}
|
|
||||||
|
|
||||||
$channel = $chan->getName();
|
|
||||||
$caption = 'Channel ' . $channel . ' Information:';
|
|
||||||
$data1 = array(
|
|
||||||
'caption' => $caption,
|
|
||||||
'border' => true);
|
|
||||||
$data1['data']['server'] = array('Name and Server', $chan->getName());
|
|
||||||
if ($chan->getAlias() != $chan->getName()) {
|
|
||||||
$data1['data']['alias'] = array('Alias', $chan->getAlias());
|
|
||||||
}
|
|
||||||
|
|
||||||
$data1['data']['summary'] = array('Summary', $chan->getSummary());
|
|
||||||
$validate = $chan->getValidationPackage();
|
|
||||||
$data1['data']['vpackage'] = array('Validation Package Name', $validate['_content']);
|
|
||||||
$data1['data']['vpackageversion'] =
|
|
||||||
array('Validation Package Version', $validate['attribs']['version']);
|
|
||||||
$d = array();
|
|
||||||
$d['main'] = $data1;
|
|
||||||
|
|
||||||
$data['data'] = array();
|
|
||||||
$data['caption'] = 'Server Capabilities';
|
|
||||||
$data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
|
|
||||||
if ($chan->supportsREST()) {
|
|
||||||
if ($chan->supportsREST()) {
|
|
||||||
$funcs = $chan->getFunctions('rest');
|
|
||||||
if (!isset($funcs[0])) {
|
|
||||||
$funcs = array($funcs);
|
|
||||||
}
|
|
||||||
foreach ($funcs as $protocol) {
|
|
||||||
$data['data'][] = array('rest', $protocol['attribs']['type'],
|
|
||||||
$protocol['_content']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$data['data'][] = array('No supported protocols');
|
|
||||||
}
|
|
||||||
|
|
||||||
$d['protocols'] = $data;
|
|
||||||
$data['data'] = array();
|
|
||||||
$mirrors = $chan->getMirrors();
|
|
||||||
if ($mirrors) {
|
|
||||||
$data['caption'] = 'Channel ' . $channel . ' Mirrors:';
|
|
||||||
unset($data['headline']);
|
|
||||||
foreach ($mirrors as $mirror) {
|
|
||||||
$data['data'][] = array($mirror['attribs']['host']);
|
|
||||||
$d['mirrors'] = $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($mirrors as $i => $mirror) {
|
|
||||||
$data['data'] = array();
|
|
||||||
$data['caption'] = 'Mirror ' . $mirror['attribs']['host'] . ' Capabilities';
|
|
||||||
$data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
|
|
||||||
if ($chan->supportsREST($mirror['attribs']['host'])) {
|
|
||||||
if ($chan->supportsREST($mirror['attribs']['host'])) {
|
|
||||||
$funcs = $chan->getFunctions('rest', $mirror['attribs']['host']);
|
|
||||||
if (!isset($funcs[0])) {
|
|
||||||
$funcs = array($funcs);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($funcs as $protocol) {
|
|
||||||
$data['data'][] = array('rest', $protocol['attribs']['type'],
|
|
||||||
$protocol['_content']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$data['data'][] = array('No supported protocols');
|
|
||||||
}
|
|
||||||
$d['mirrorprotocols' . $i] = $data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->ui->outputData($d, 'channel-info');
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
function doDelete($command, $options, $params)
|
|
||||||
{
|
|
||||||
if (count($params) !== 1) {
|
|
||||||
return $this->raiseError('channel-delete: no channel specified');
|
|
||||||
}
|
|
||||||
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
if (!$reg->channelExists($params[0])) {
|
|
||||||
return $this->raiseError('channel-delete: channel "' . $params[0] . '" does not exist');
|
|
||||||
}
|
|
||||||
|
|
||||||
$channel = $reg->channelName($params[0]);
|
|
||||||
if ($channel == 'pear.php.net') {
|
|
||||||
return $this->raiseError('Cannot delete the pear.php.net channel');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($channel == 'pecl.php.net') {
|
|
||||||
return $this->raiseError('Cannot delete the pecl.php.net channel');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($channel == 'doc.php.net') {
|
|
||||||
return $this->raiseError('Cannot delete the doc.php.net channel');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($channel == '__uri') {
|
|
||||||
return $this->raiseError('Cannot delete the __uri pseudo-channel');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PEAR::isError($err = $reg->listPackages($channel))) {
|
|
||||||
return $err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($err)) {
|
|
||||||
return $this->raiseError('Channel "' . $channel .
|
|
||||||
'" has installed packages, cannot delete');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$reg->deleteChannel($channel)) {
|
|
||||||
return $this->raiseError('Channel "' . $channel . '" deletion failed');
|
|
||||||
} else {
|
|
||||||
$this->config->deleteChannel($channel);
|
|
||||||
$this->ui->outputData('Channel "' . $channel . '" deleted', $command);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function doAdd($command, $options, $params)
|
|
||||||
{
|
|
||||||
if (count($params) !== 1) {
|
|
||||||
return $this->raiseError('channel-add: no channel file specified');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strpos($params[0], '://')) {
|
|
||||||
$downloader = &$this->getDownloader();
|
|
||||||
$tmpdir = $this->config->get('temp_dir');
|
|
||||||
if (!file_exists($tmpdir)) {
|
|
||||||
require_once 'System.php';
|
|
||||||
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
|
|
||||||
$err = System::mkdir(array('-p', $tmpdir));
|
|
||||||
PEAR::staticPopErrorHandling();
|
|
||||||
if (PEAR::isError($err)) {
|
|
||||||
return $this->raiseError('channel-add: temp_dir does not exist: "' .
|
|
||||||
$tmpdir .
|
|
||||||
'" - You can change this location with "pear config-set temp_dir"');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_writable($tmpdir)) {
|
|
||||||
return $this->raiseError('channel-add: temp_dir is not writable: "' .
|
|
||||||
$tmpdir .
|
|
||||||
'" - You can change this location with "pear config-set temp_dir"');
|
|
||||||
}
|
|
||||||
|
|
||||||
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
|
|
||||||
$loc = $downloader->downloadHttp($params[0], $this->ui, $tmpdir, null, false);
|
|
||||||
PEAR::staticPopErrorHandling();
|
|
||||||
if (PEAR::isError($loc)) {
|
|
||||||
return $this->raiseError('channel-add: Cannot open "' . $params[0] .
|
|
||||||
'" (' . $loc->getMessage() . ')');
|
|
||||||
}
|
|
||||||
|
|
||||||
list($loc, $lastmodified) = $loc;
|
|
||||||
$contents = implode('', file($loc));
|
|
||||||
} else {
|
|
||||||
$lastmodified = $fp = false;
|
|
||||||
if (file_exists($params[0])) {
|
|
||||||
$fp = fopen($params[0], 'r');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$fp) {
|
|
||||||
return $this->raiseError('channel-add: cannot open "' . $params[0] . '"');
|
|
||||||
}
|
|
||||||
|
|
||||||
$contents = '';
|
|
||||||
while (!feof($fp)) {
|
|
||||||
$contents .= fread($fp, 1024);
|
|
||||||
}
|
|
||||||
fclose($fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!class_exists('PEAR_ChannelFile')) {
|
|
||||||
require_once 'PEAR/ChannelFile.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
$channel = new PEAR_ChannelFile;
|
|
||||||
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
|
|
||||||
$result = $channel->fromXmlString($contents);
|
|
||||||
PEAR::staticPopErrorHandling();
|
|
||||||
if (!$result) {
|
|
||||||
$exit = false;
|
|
||||||
if (count($errors = $channel->getErrors(true))) {
|
|
||||||
foreach ($errors as $error) {
|
|
||||||
$this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
|
|
||||||
if (!$exit) {
|
|
||||||
$exit = $error['level'] == 'error' ? true : false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($exit) {
|
|
||||||
return $this->raiseError('channel-add: invalid channel.xml file');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
if ($reg->channelExists($channel->getName())) {
|
|
||||||
return $this->raiseError('channel-add: Channel "' . $channel->getName() .
|
|
||||||
'" exists, use channel-update to update entry', PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
$ret = $reg->addChannel($channel, $lastmodified);
|
|
||||||
if (PEAR::isError($ret)) {
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$ret) {
|
|
||||||
return $this->raiseError('channel-add: adding Channel "' . $channel->getName() .
|
|
||||||
'" to registry failed');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->config->setChannels($reg->listChannels());
|
|
||||||
$this->config->writeConfigFile();
|
|
||||||
$this->ui->outputData('Adding Channel "' . $channel->getName() . '" succeeded', $command);
|
|
||||||
}
|
|
||||||
|
|
||||||
function doUpdate($command, $options, $params)
|
|
||||||
{
|
|
||||||
if (count($params) !== 1) {
|
|
||||||
return $this->raiseError("No channel file specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
$tmpdir = $this->config->get('temp_dir');
|
|
||||||
if (!file_exists($tmpdir)) {
|
|
||||||
require_once 'System.php';
|
|
||||||
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
|
|
||||||
$err = System::mkdir(array('-p', $tmpdir));
|
|
||||||
PEAR::staticPopErrorHandling();
|
|
||||||
if (PEAR::isError($err)) {
|
|
||||||
return $this->raiseError('channel-add: temp_dir does not exist: "' .
|
|
||||||
$tmpdir .
|
|
||||||
'" - You can change this location with "pear config-set temp_dir"');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_writable($tmpdir)) {
|
|
||||||
return $this->raiseError('channel-add: temp_dir is not writable: "' .
|
|
||||||
$tmpdir .
|
|
||||||
'" - You can change this location with "pear config-set temp_dir"');
|
|
||||||
}
|
|
||||||
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
$lastmodified = false;
|
|
||||||
if ((!file_exists($params[0]) || is_dir($params[0]))
|
|
||||||
&& $reg->channelExists(strtolower($params[0]))) {
|
|
||||||
$c = $reg->getChannel(strtolower($params[0]));
|
|
||||||
if (PEAR::isError($c)) {
|
|
||||||
return $this->raiseError($c);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->ui->outputData("Updating channel \"$params[0]\"", $command);
|
|
||||||
$dl = &$this->getDownloader(array());
|
|
||||||
// if force is specified, use a timestamp of "1" to force retrieval
|
|
||||||
$lastmodified = isset($options['force']) ? false : $c->lastModified();
|
|
||||||
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
|
|
||||||
$contents = $dl->downloadHttp('http://' . $c->getName() . '/channel.xml',
|
|
||||||
$this->ui, $tmpdir, null, $lastmodified);
|
|
||||||
PEAR::staticPopErrorHandling();
|
|
||||||
if (PEAR::isError($contents)) {
|
|
||||||
// Attempt to fall back to https
|
|
||||||
$this->ui->outputData("Channel \"$params[0]\" is not responding over http://, failed with message: " . $contents->getMessage());
|
|
||||||
$this->ui->outputData("Trying channel \"$params[0]\" over https:// instead");
|
|
||||||
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
|
|
||||||
$contents = $dl->downloadHttp('https://' . $c->getName() . '/channel.xml',
|
|
||||||
$this->ui, $tmpdir, null, $lastmodified);
|
|
||||||
PEAR::staticPopErrorHandling();
|
|
||||||
if (PEAR::isError($contents)) {
|
|
||||||
return $this->raiseError('Cannot retrieve channel.xml for channel "' .
|
|
||||||
$c->getName() . '" (' . $contents->getMessage() . ')');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
list($contents, $lastmodified) = $contents;
|
|
||||||
if (!$contents) {
|
|
||||||
$this->ui->outputData("Channel \"$params[0]\" is up to date");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$contents = implode('', file($contents));
|
|
||||||
if (!class_exists('PEAR_ChannelFile')) {
|
|
||||||
require_once 'PEAR/ChannelFile.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
$channel = new PEAR_ChannelFile;
|
|
||||||
$channel->fromXmlString($contents);
|
|
||||||
if (!$channel->getErrors()) {
|
|
||||||
// security check: is the downloaded file for the channel we got it from?
|
|
||||||
if (strtolower($channel->getName()) != strtolower($c->getName())) {
|
|
||||||
if (!isset($options['force'])) {
|
|
||||||
return $this->raiseError('ERROR: downloaded channel definition file' .
|
|
||||||
' for channel "' . $channel->getName() . '" from channel "' .
|
|
||||||
strtolower($c->getName()) . '"');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->ui->log(0, 'WARNING: downloaded channel definition file' .
|
|
||||||
' for channel "' . $channel->getName() . '" from channel "' .
|
|
||||||
strtolower($c->getName()) . '"');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (strpos($params[0], '://')) {
|
|
||||||
$dl = &$this->getDownloader();
|
|
||||||
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
|
|
||||||
$loc = $dl->downloadHttp($params[0],
|
|
||||||
$this->ui, $tmpdir, null, $lastmodified);
|
|
||||||
PEAR::staticPopErrorHandling();
|
|
||||||
if (PEAR::isError($loc)) {
|
|
||||||
return $this->raiseError("Cannot open " . $params[0] .
|
|
||||||
' (' . $loc->getMessage() . ')');
|
|
||||||
}
|
|
||||||
|
|
||||||
list($loc, $lastmodified) = $loc;
|
|
||||||
$contents = implode('', file($loc));
|
|
||||||
} else {
|
|
||||||
$fp = false;
|
|
||||||
if (file_exists($params[0])) {
|
|
||||||
$fp = fopen($params[0], 'r');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$fp) {
|
|
||||||
return $this->raiseError("Cannot open " . $params[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$contents = '';
|
|
||||||
while (!feof($fp)) {
|
|
||||||
$contents .= fread($fp, 1024);
|
|
||||||
}
|
|
||||||
fclose($fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!class_exists('PEAR_ChannelFile')) {
|
|
||||||
require_once 'PEAR/ChannelFile.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
$channel = new PEAR_ChannelFile;
|
|
||||||
$channel->fromXmlString($contents);
|
|
||||||
}
|
|
||||||
|
|
||||||
$exit = false;
|
|
||||||
if (count($errors = $channel->getErrors(true))) {
|
|
||||||
foreach ($errors as $error) {
|
|
||||||
$this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
|
|
||||||
if (!$exit) {
|
|
||||||
$exit = $error['level'] == 'error' ? true : false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($exit) {
|
|
||||||
return $this->raiseError('Invalid channel.xml file');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$reg->channelExists($channel->getName())) {
|
|
||||||
return $this->raiseError('Error: Channel "' . $channel->getName() .
|
|
||||||
'" does not exist, use channel-add to add an entry');
|
|
||||||
}
|
|
||||||
|
|
||||||
$ret = $reg->updateChannel($channel, $lastmodified);
|
|
||||||
if (PEAR::isError($ret)) {
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$ret) {
|
|
||||||
return $this->raiseError('Updating Channel "' . $channel->getName() .
|
|
||||||
'" in registry failed');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->config->setChannels($reg->listChannels());
|
|
||||||
$this->config->writeConfigFile();
|
|
||||||
$this->ui->outputData('Update of Channel "' . $channel->getName() . '" succeeded');
|
|
||||||
}
|
|
||||||
|
|
||||||
function &getDownloader()
|
|
||||||
{
|
|
||||||
if (!class_exists('PEAR_Downloader')) {
|
|
||||||
require_once 'PEAR/Downloader.php';
|
|
||||||
}
|
|
||||||
$a = new PEAR_Downloader($this->ui, array(), $this->config);
|
|
||||||
return $a;
|
|
||||||
}
|
|
||||||
|
|
||||||
function doAlias($command, $options, $params)
|
|
||||||
{
|
|
||||||
if (count($params) === 1) {
|
|
||||||
return $this->raiseError('No channel alias specified');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($params) !== 2 || (!empty($params[1]) && $params[1]{0} == '-')) {
|
|
||||||
return $this->raiseError(
|
|
||||||
'Invalid format, correct is: channel-alias channel alias');
|
|
||||||
}
|
|
||||||
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
if (!$reg->channelExists($params[0], true)) {
|
|
||||||
$extra = '';
|
|
||||||
if ($reg->isAlias($params[0])) {
|
|
||||||
$extra = ' (use "channel-alias ' . $reg->channelName($params[0]) . ' ' .
|
|
||||||
strtolower($params[1]) . '")';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->raiseError('"' . $params[0] . '" is not a valid channel' . $extra);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($reg->isAlias($params[1])) {
|
|
||||||
return $this->raiseError('Channel "' . $reg->channelName($params[1]) . '" is ' .
|
|
||||||
'already aliased to "' . strtolower($params[1]) . '", cannot re-alias');
|
|
||||||
}
|
|
||||||
|
|
||||||
$chan = &$reg->getChannel($params[0]);
|
|
||||||
if (PEAR::isError($chan)) {
|
|
||||||
return $this->raiseError('Corrupt registry? Error retrieving channel "' . $params[0] .
|
|
||||||
'" information (' . $chan->getMessage() . ')');
|
|
||||||
}
|
|
||||||
|
|
||||||
// make it a local alias
|
|
||||||
if (!$chan->setAlias(strtolower($params[1]), true)) {
|
|
||||||
return $this->raiseError('Alias "' . strtolower($params[1]) .
|
|
||||||
'" is not a valid channel alias');
|
|
||||||
}
|
|
||||||
|
|
||||||
$reg->updateChannel($chan);
|
|
||||||
$this->ui->outputData('Channel "' . $chan->getName() . '" aliased successfully to "' .
|
|
||||||
strtolower($params[1]) . '"');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The channel-discover command
|
|
||||||
*
|
|
||||||
* @param string $command command name
|
|
||||||
* @param array $options option_name => value
|
|
||||||
* @param array $params list of additional parameters.
|
|
||||||
* $params[0] should contain a string with either:
|
|
||||||
* - <channel name> or
|
|
||||||
* - <username>:<password>@<channel name>
|
|
||||||
* @return null|PEAR_Error
|
|
||||||
*/
|
|
||||||
function doDiscover($command, $options, $params)
|
|
||||||
{
|
|
||||||
if (count($params) !== 1) {
|
|
||||||
return $this->raiseError("No channel server specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for the possible input format "<username>:<password>@<channel>"
|
|
||||||
if (preg_match('/^(.+):(.+)@(.+)\\z/', $params[0], $matches)) {
|
|
||||||
$username = $matches[1];
|
|
||||||
$password = $matches[2];
|
|
||||||
$channel = $matches[3];
|
|
||||||
} else {
|
|
||||||
$channel = $params[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
if ($reg->channelExists($channel)) {
|
|
||||||
if (!$reg->isAlias($channel)) {
|
|
||||||
return $this->raiseError("Channel \"$channel\" is already initialized", PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->raiseError("A channel alias named \"$channel\" " .
|
|
||||||
'already exists, aliasing channel "' . $reg->channelName($channel)
|
|
||||||
. '"');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->pushErrorHandling(PEAR_ERROR_RETURN);
|
|
||||||
$err = $this->doAdd($command, $options, array('http://' . $channel . '/channel.xml'));
|
|
||||||
$this->popErrorHandling();
|
|
||||||
if (PEAR::isError($err)) {
|
|
||||||
if ($err->getCode() === PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS) {
|
|
||||||
return $this->raiseError("Discovery of channel \"$channel\" failed (" .
|
|
||||||
$err->getMessage() . ')');
|
|
||||||
}
|
|
||||||
// Attempt fetch via https
|
|
||||||
$this->ui->outputData("Discovering channel $channel over http:// failed with message: " . $err->getMessage());
|
|
||||||
$this->ui->outputData("Trying to discover channel $channel over https:// instead");
|
|
||||||
$this->pushErrorHandling(PEAR_ERROR_RETURN);
|
|
||||||
$err = $this->doAdd($command, $options, array('https://' . $channel . '/channel.xml'));
|
|
||||||
$this->popErrorHandling();
|
|
||||||
if (PEAR::isError($err)) {
|
|
||||||
return $this->raiseError("Discovery of channel \"$channel\" failed (" .
|
|
||||||
$err->getMessage() . ')');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store username/password if they were given
|
|
||||||
// Arguably we should do a logintest on the channel here, but since
|
|
||||||
// that's awkward on a REST-based channel (even "pear login" doesn't
|
|
||||||
// do it for those), and XML-RPC is deprecated, it's fairly pointless.
|
|
||||||
if (isset($username)) {
|
|
||||||
$this->config->set('username', $username, 'user', $channel);
|
|
||||||
$this->config->set('password', $password, 'user', $channel);
|
|
||||||
$this->config->store();
|
|
||||||
$this->ui->outputData("Stored login for channel \"$channel\" using username \"$username\"", $command);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->ui->outputData("Discovery of channel \"$channel\" succeeded", $command);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute the 'login' command.
|
|
||||||
*
|
|
||||||
* @param string $command command name
|
|
||||||
* @param array $options option_name => value
|
|
||||||
* @param array $params list of additional parameters
|
|
||||||
*
|
|
||||||
* @return bool TRUE on success or
|
|
||||||
* a PEAR error on failure
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function doLogin($command, $options, $params)
|
|
||||||
{
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
|
|
||||||
// If a parameter is supplied, use that as the channel to log in to
|
|
||||||
$channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel');
|
|
||||||
|
|
||||||
$chan = $reg->getChannel($channel);
|
|
||||||
if (PEAR::isError($chan)) {
|
|
||||||
return $this->raiseError($chan);
|
|
||||||
}
|
|
||||||
|
|
||||||
$server = $this->config->get('preferred_mirror', null, $channel);
|
|
||||||
$username = $this->config->get('username', null, $channel);
|
|
||||||
if (empty($username)) {
|
|
||||||
$username = isset($_ENV['USER']) ? $_ENV['USER'] : null;
|
|
||||||
}
|
|
||||||
$this->ui->outputData("Logging in to $server.", $command);
|
|
||||||
|
|
||||||
list($username, $password) = $this->ui->userDialog(
|
|
||||||
$command,
|
|
||||||
array('Username', 'Password'),
|
|
||||||
array('text', 'password'),
|
|
||||||
array($username, '')
|
|
||||||
);
|
|
||||||
$username = trim($username);
|
|
||||||
$password = trim($password);
|
|
||||||
|
|
||||||
$ourfile = $this->config->getConfFile('user');
|
|
||||||
if (!$ourfile) {
|
|
||||||
$ourfile = $this->config->getConfFile('system');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->config->set('username', $username, 'user', $channel);
|
|
||||||
$this->config->set('password', $password, 'user', $channel);
|
|
||||||
|
|
||||||
if ($chan->supportsREST()) {
|
|
||||||
$ok = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($ok !== true) {
|
|
||||||
return $this->raiseError('Login failed!');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->ui->outputData("Logged in.", $command);
|
|
||||||
// avoid changing any temporary settings changed with -d
|
|
||||||
$ourconfig = new PEAR_Config($ourfile, $ourfile);
|
|
||||||
$ourconfig->set('username', $username, 'user', $channel);
|
|
||||||
$ourconfig->set('password', $password, 'user', $channel);
|
|
||||||
$ourconfig->store();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute the 'logout' command.
|
|
||||||
*
|
|
||||||
* @param string $command command name
|
|
||||||
* @param array $options option_name => value
|
|
||||||
* @param array $params list of additional parameters
|
|
||||||
*
|
|
||||||
* @return bool TRUE on success or
|
|
||||||
* a PEAR error on failure
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function doLogout($command, $options, $params)
|
|
||||||
{
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
|
|
||||||
// If a parameter is supplied, use that as the channel to log in to
|
|
||||||
$channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel');
|
|
||||||
|
|
||||||
$chan = $reg->getChannel($channel);
|
|
||||||
if (PEAR::isError($chan)) {
|
|
||||||
return $this->raiseError($chan);
|
|
||||||
}
|
|
||||||
|
|
||||||
$server = $this->config->get('preferred_mirror', null, $channel);
|
|
||||||
$this->ui->outputData("Logging out from $server.", $command);
|
|
||||||
$this->config->remove('username', 'user', $channel);
|
|
||||||
$this->config->remove('password', 'user', $channel);
|
|
||||||
$this->config->store();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,123 +0,0 @@
|
||||||
<commands version="1.0">
|
|
||||||
<list-channels>
|
|
||||||
<summary>List Available Channels</summary>
|
|
||||||
<function>doList</function>
|
|
||||||
<shortcut>lc</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc>
|
|
||||||
List all available channels for installation.
|
|
||||||
</doc>
|
|
||||||
</list-channels>
|
|
||||||
<update-channels>
|
|
||||||
<summary>Update the Channel List</summary>
|
|
||||||
<function>doUpdateAll</function>
|
|
||||||
<shortcut>uc</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc>
|
|
||||||
List all installed packages in all channels.
|
|
||||||
</doc>
|
|
||||||
</update-channels>
|
|
||||||
<channel-delete>
|
|
||||||
<summary>Remove a Channel From the List</summary>
|
|
||||||
<function>doDelete</function>
|
|
||||||
<shortcut>cde</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc><channel name>
|
|
||||||
Delete a channel from the registry. You may not
|
|
||||||
remove any channel that has installed packages.
|
|
||||||
</doc>
|
|
||||||
</channel-delete>
|
|
||||||
<channel-add>
|
|
||||||
<summary>Add a Channel</summary>
|
|
||||||
<function>doAdd</function>
|
|
||||||
<shortcut>ca</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc><channel.xml>
|
|
||||||
Add a private channel to the channel list. Note that all
|
|
||||||
public channels should be synced using "update-channels".
|
|
||||||
Parameter may be either a local file or remote URL to a
|
|
||||||
channel.xml.
|
|
||||||
</doc>
|
|
||||||
</channel-add>
|
|
||||||
<channel-update>
|
|
||||||
<summary>Update an Existing Channel</summary>
|
|
||||||
<function>doUpdate</function>
|
|
||||||
<shortcut>cu</shortcut>
|
|
||||||
<options>
|
|
||||||
<force>
|
|
||||||
<shortopt>f</shortopt>
|
|
||||||
<doc>will force download of new channel.xml if an existing channel name is used</doc>
|
|
||||||
</force>
|
|
||||||
<channel>
|
|
||||||
<shortopt>c</shortopt>
|
|
||||||
<doc>will force download of new channel.xml if an existing channel name is used</doc>
|
|
||||||
<arg>CHANNEL</arg>
|
|
||||||
</channel>
|
|
||||||
</options>
|
|
||||||
<doc>[<channel.xml>|<channel name>]
|
|
||||||
Update a channel in the channel list directly. Note that all
|
|
||||||
public channels can be synced using "update-channels".
|
|
||||||
Parameter may be a local or remote channel.xml, or the name of
|
|
||||||
an existing channel.
|
|
||||||
</doc>
|
|
||||||
</channel-update>
|
|
||||||
<channel-info>
|
|
||||||
<summary>Retrieve Information on a Channel</summary>
|
|
||||||
<function>doInfo</function>
|
|
||||||
<shortcut>ci</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc><package>
|
|
||||||
List the files in an installed package.
|
|
||||||
</doc>
|
|
||||||
</channel-info>
|
|
||||||
<channel-alias>
|
|
||||||
<summary>Specify an alias to a channel name</summary>
|
|
||||||
<function>doAlias</function>
|
|
||||||
<shortcut>cha</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc><channel> <alias>
|
|
||||||
Specify a specific alias to use for a channel name.
|
|
||||||
The alias may not be an existing channel name or
|
|
||||||
alias.
|
|
||||||
</doc>
|
|
||||||
</channel-alias>
|
|
||||||
<channel-discover>
|
|
||||||
<summary>Initialize a Channel from its server</summary>
|
|
||||||
<function>doDiscover</function>
|
|
||||||
<shortcut>di</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc>[<channel.xml>|<channel name>]
|
|
||||||
Initialize a channel from its server and create a local channel.xml.
|
|
||||||
If <channel name> is in the format "<username>:<password>@<channel>" then
|
|
||||||
<username> and <password> will be set as the login username/password for
|
|
||||||
<channel>. Use caution when passing the username/password in this way, as
|
|
||||||
it may allow other users on your computer to briefly view your username/
|
|
||||||
password via the system's process list.
|
|
||||||
</doc>
|
|
||||||
</channel-discover>
|
|
||||||
<channel-login>
|
|
||||||
<summary>Connects and authenticates to remote channel server</summary>
|
|
||||||
<function>doLogin</function>
|
|
||||||
<shortcut>cli</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc><channel name>
|
|
||||||
Log in to a remote channel server. If <channel name> is not supplied,
|
|
||||||
the default channel is used. To use remote functions in the installer
|
|
||||||
that require any kind of privileges, you need to log in first. The
|
|
||||||
username and password you enter here will be stored in your per-user
|
|
||||||
PEAR configuration (~/.pearrc on Unix-like systems). After logging
|
|
||||||
in, your username and password will be sent along in subsequent
|
|
||||||
operations on the remote server.</doc>
|
|
||||||
</channel-login>
|
|
||||||
<channel-logout>
|
|
||||||
<summary>Logs out from the remote channel server</summary>
|
|
||||||
<function>doLogout</function>
|
|
||||||
<shortcut>clo</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc><channel name>
|
|
||||||
Logs out from a remote channel server. If <channel name> is not supplied,
|
|
||||||
the default channel is used. This command does not actually connect to the
|
|
||||||
remote server, it only deletes the stored username and password from your user
|
|
||||||
configuration.</doc>
|
|
||||||
</channel-logout>
|
|
||||||
</commands>
|
|
|
@ -1,273 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* PEAR_Command_Common base class
|
|
||||||
*
|
|
||||||
* PHP versions 4 and 5
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version CVS: $Id: Common.php 313023 2011-07-06 19:17:11Z dufuz $
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since File available since Release 0.1
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* base class
|
|
||||||
*/
|
|
||||||
require_once 'PEAR.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR commands base class
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version Release: 1.9.4
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since Class available since Release 0.1
|
|
||||||
*/
|
|
||||||
class PEAR_Command_Common extends PEAR
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* PEAR_Config object used to pass user system and configuration
|
|
||||||
* on when executing commands
|
|
||||||
*
|
|
||||||
* @var PEAR_Config
|
|
||||||
*/
|
|
||||||
var $config;
|
|
||||||
/**
|
|
||||||
* @var PEAR_Registry
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
var $_registry;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User Interface object, for all interaction with the user.
|
|
||||||
* @var object
|
|
||||||
*/
|
|
||||||
var $ui;
|
|
||||||
|
|
||||||
var $_deps_rel_trans = array(
|
|
||||||
'lt' => '<',
|
|
||||||
'le' => '<=',
|
|
||||||
'eq' => '=',
|
|
||||||
'ne' => '!=',
|
|
||||||
'gt' => '>',
|
|
||||||
'ge' => '>=',
|
|
||||||
'has' => '=='
|
|
||||||
);
|
|
||||||
|
|
||||||
var $_deps_type_trans = array(
|
|
||||||
'pkg' => 'package',
|
|
||||||
'ext' => 'extension',
|
|
||||||
'php' => 'PHP',
|
|
||||||
'prog' => 'external program',
|
|
||||||
'ldlib' => 'external library for linking',
|
|
||||||
'rtlib' => 'external runtime library',
|
|
||||||
'os' => 'operating system',
|
|
||||||
'websrv' => 'web server',
|
|
||||||
'sapi' => 'SAPI backend'
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR_Command_Common constructor.
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function PEAR_Command_Common(&$ui, &$config)
|
|
||||||
{
|
|
||||||
parent::PEAR();
|
|
||||||
$this->config = &$config;
|
|
||||||
$this->ui = &$ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a list of all the commands defined by this class.
|
|
||||||
* @return array list of commands
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getCommands()
|
|
||||||
{
|
|
||||||
$ret = array();
|
|
||||||
foreach (array_keys($this->commands) as $command) {
|
|
||||||
$ret[$command] = $this->commands[$command]['summary'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a list of all the command shortcuts defined by this class.
|
|
||||||
* @return array shortcut => command
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function getShortcuts()
|
|
||||||
{
|
|
||||||
$ret = array();
|
|
||||||
foreach (array_keys($this->commands) as $command) {
|
|
||||||
if (isset($this->commands[$command]['shortcut'])) {
|
|
||||||
$ret[$this->commands[$command]['shortcut']] = $command;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getOptions($command)
|
|
||||||
{
|
|
||||||
$shortcuts = $this->getShortcuts();
|
|
||||||
if (isset($shortcuts[$command])) {
|
|
||||||
$command = $shortcuts[$command];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($this->commands[$command]) &&
|
|
||||||
isset($this->commands[$command]['options'])) {
|
|
||||||
return $this->commands[$command]['options'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getGetoptArgs($command, &$short_args, &$long_args)
|
|
||||||
{
|
|
||||||
$short_args = '';
|
|
||||||
$long_args = array();
|
|
||||||
if (empty($this->commands[$command]) || empty($this->commands[$command]['options'])) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
reset($this->commands[$command]['options']);
|
|
||||||
while (list($option, $info) = each($this->commands[$command]['options'])) {
|
|
||||||
$larg = $sarg = '';
|
|
||||||
if (isset($info['arg'])) {
|
|
||||||
if ($info['arg']{0} == '(') {
|
|
||||||
$larg = '==';
|
|
||||||
$sarg = '::';
|
|
||||||
$arg = substr($info['arg'], 1, -1);
|
|
||||||
} else {
|
|
||||||
$larg = '=';
|
|
||||||
$sarg = ':';
|
|
||||||
$arg = $info['arg'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($info['shortopt'])) {
|
|
||||||
$short_args .= $info['shortopt'] . $sarg;
|
|
||||||
}
|
|
||||||
|
|
||||||
$long_args[] = $option . $larg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the help message for the given command
|
|
||||||
*
|
|
||||||
* @param string $command The command
|
|
||||||
* @return mixed A fail string if the command does not have help or
|
|
||||||
* a two elements array containing [0]=>help string,
|
|
||||||
* [1]=> help string for the accepted cmd args
|
|
||||||
*/
|
|
||||||
function getHelp($command)
|
|
||||||
{
|
|
||||||
$config = &PEAR_Config::singleton();
|
|
||||||
if (!isset($this->commands[$command])) {
|
|
||||||
return "No such command \"$command\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
$help = null;
|
|
||||||
if (isset($this->commands[$command]['doc'])) {
|
|
||||||
$help = $this->commands[$command]['doc'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($help)) {
|
|
||||||
// XXX (cox) Fallback to summary if there is no doc (show both?)
|
|
||||||
if (!isset($this->commands[$command]['summary'])) {
|
|
||||||
return "No help for command \"$command\"";
|
|
||||||
}
|
|
||||||
$help = $this->commands[$command]['summary'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preg_match_all('/{config\s+([^\}]+)}/e', $help, $matches)) {
|
|
||||||
foreach($matches[0] as $k => $v) {
|
|
||||||
$help = preg_replace("/$v/", $config->get($matches[1][$k]), $help);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return array($help, $this->getHelpArgs($command));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the help for the accepted arguments of a command
|
|
||||||
*
|
|
||||||
* @param string $command
|
|
||||||
* @return string The help string
|
|
||||||
*/
|
|
||||||
function getHelpArgs($command)
|
|
||||||
{
|
|
||||||
if (isset($this->commands[$command]['options']) &&
|
|
||||||
count($this->commands[$command]['options']))
|
|
||||||
{
|
|
||||||
$help = "Options:\n";
|
|
||||||
foreach ($this->commands[$command]['options'] as $k => $v) {
|
|
||||||
if (isset($v['arg'])) {
|
|
||||||
if ($v['arg'][0] == '(') {
|
|
||||||
$arg = substr($v['arg'], 1, -1);
|
|
||||||
$sapp = " [$arg]";
|
|
||||||
$lapp = "[=$arg]";
|
|
||||||
} else {
|
|
||||||
$sapp = " $v[arg]";
|
|
||||||
$lapp = "=$v[arg]";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$sapp = $lapp = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($v['shortopt'])) {
|
|
||||||
$s = $v['shortopt'];
|
|
||||||
$help .= " -$s$sapp, --$k$lapp\n";
|
|
||||||
} else {
|
|
||||||
$help .= " --$k$lapp\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$p = " ";
|
|
||||||
$doc = rtrim(str_replace("\n", "\n$p", $v['doc']));
|
|
||||||
$help .= " $doc\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $help;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function run($command, $options, $params)
|
|
||||||
{
|
|
||||||
if (empty($this->commands[$command]['function'])) {
|
|
||||||
// look for shortcuts
|
|
||||||
foreach (array_keys($this->commands) as $cmd) {
|
|
||||||
if (isset($this->commands[$cmd]['shortcut']) && $this->commands[$cmd]['shortcut'] == $command) {
|
|
||||||
if (empty($this->commands[$cmd]['function'])) {
|
|
||||||
return $this->raiseError("unknown command `$command'");
|
|
||||||
} else {
|
|
||||||
$func = $this->commands[$cmd]['function'];
|
|
||||||
}
|
|
||||||
$command = $cmd;
|
|
||||||
|
|
||||||
//$command = $this->commands[$cmd]['function'];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$func = $this->commands[$command]['function'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->$func($command, $options, $params);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,414 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* PEAR_Command_Config (config-show, config-get, config-set, config-help, config-create commands)
|
|
||||||
*
|
|
||||||
* PHP versions 4 and 5
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version CVS: $Id: Config.php 313024 2011-07-06 19:51:24Z dufuz $
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since File available since Release 0.1
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* base class
|
|
||||||
*/
|
|
||||||
require_once 'PEAR/Command/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR commands for managing configuration data.
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version Release: 1.9.4
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since Class available since Release 0.1
|
|
||||||
*/
|
|
||||||
class PEAR_Command_Config extends PEAR_Command_Common
|
|
||||||
{
|
|
||||||
var $commands = array(
|
|
||||||
'config-show' => array(
|
|
||||||
'summary' => 'Show All Settings',
|
|
||||||
'function' => 'doConfigShow',
|
|
||||||
'shortcut' => 'csh',
|
|
||||||
'options' => array(
|
|
||||||
'channel' => array(
|
|
||||||
'shortopt' => 'c',
|
|
||||||
'doc' => 'show configuration variables for another channel',
|
|
||||||
'arg' => 'CHAN',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
'doc' => '[layer]
|
|
||||||
Displays all configuration values. An optional argument
|
|
||||||
may be used to tell which configuration layer to display. Valid
|
|
||||||
configuration layers are "user", "system" and "default". To display
|
|
||||||
configurations for different channels, set the default_channel
|
|
||||||
configuration variable and run config-show again.
|
|
||||||
',
|
|
||||||
),
|
|
||||||
'config-get' => array(
|
|
||||||
'summary' => 'Show One Setting',
|
|
||||||
'function' => 'doConfigGet',
|
|
||||||
'shortcut' => 'cg',
|
|
||||||
'options' => array(
|
|
||||||
'channel' => array(
|
|
||||||
'shortopt' => 'c',
|
|
||||||
'doc' => 'show configuration variables for another channel',
|
|
||||||
'arg' => 'CHAN',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
'doc' => '<parameter> [layer]
|
|
||||||
Displays the value of one configuration parameter. The
|
|
||||||
first argument is the name of the parameter, an optional second argument
|
|
||||||
may be used to tell which configuration layer to look in. Valid configuration
|
|
||||||
layers are "user", "system" and "default". If no layer is specified, a value
|
|
||||||
will be picked from the first layer that defines the parameter, in the order
|
|
||||||
just specified. The configuration value will be retrieved for the channel
|
|
||||||
specified by the default_channel configuration variable.
|
|
||||||
',
|
|
||||||
),
|
|
||||||
'config-set' => array(
|
|
||||||
'summary' => 'Change Setting',
|
|
||||||
'function' => 'doConfigSet',
|
|
||||||
'shortcut' => 'cs',
|
|
||||||
'options' => array(
|
|
||||||
'channel' => array(
|
|
||||||
'shortopt' => 'c',
|
|
||||||
'doc' => 'show configuration variables for another channel',
|
|
||||||
'arg' => 'CHAN',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
'doc' => '<parameter> <value> [layer]
|
|
||||||
Sets the value of one configuration parameter. The first argument is
|
|
||||||
the name of the parameter, the second argument is the new value. Some
|
|
||||||
parameters are subject to validation, and the command will fail with
|
|
||||||
an error message if the new value does not make sense. An optional
|
|
||||||
third argument may be used to specify in which layer to set the
|
|
||||||
configuration parameter. The default layer is "user". The
|
|
||||||
configuration value will be set for the current channel, which
|
|
||||||
is controlled by the default_channel configuration variable.
|
|
||||||
',
|
|
||||||
),
|
|
||||||
'config-help' => array(
|
|
||||||
'summary' => 'Show Information About Setting',
|
|
||||||
'function' => 'doConfigHelp',
|
|
||||||
'shortcut' => 'ch',
|
|
||||||
'options' => array(),
|
|
||||||
'doc' => '[parameter]
|
|
||||||
Displays help for a configuration parameter. Without arguments it
|
|
||||||
displays help for all configuration parameters.
|
|
||||||
',
|
|
||||||
),
|
|
||||||
'config-create' => array(
|
|
||||||
'summary' => 'Create a Default configuration file',
|
|
||||||
'function' => 'doConfigCreate',
|
|
||||||
'shortcut' => 'coc',
|
|
||||||
'options' => array(
|
|
||||||
'windows' => array(
|
|
||||||
'shortopt' => 'w',
|
|
||||||
'doc' => 'create a config file for a windows install',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
'doc' => '<root path> <filename>
|
|
||||||
Create a default configuration file with all directory configuration
|
|
||||||
variables set to subdirectories of <root path>, and save it as <filename>.
|
|
||||||
This is useful especially for creating a configuration file for a remote
|
|
||||||
PEAR installation (using the --remoteconfig option of install, upgrade,
|
|
||||||
and uninstall).
|
|
||||||
',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR_Command_Config constructor.
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function PEAR_Command_Config(&$ui, &$config)
|
|
||||||
{
|
|
||||||
parent::PEAR_Command_Common($ui, $config);
|
|
||||||
}
|
|
||||||
|
|
||||||
function doConfigShow($command, $options, $params)
|
|
||||||
{
|
|
||||||
$layer = null;
|
|
||||||
if (is_array($params)) {
|
|
||||||
$layer = isset($params[0]) ? $params[0] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// $params[0] -> the layer
|
|
||||||
if ($error = $this->_checkLayer($layer)) {
|
|
||||||
return $this->raiseError("config-show:$error");
|
|
||||||
}
|
|
||||||
|
|
||||||
$keys = $this->config->getKeys();
|
|
||||||
sort($keys);
|
|
||||||
$channel = isset($options['channel']) ? $options['channel'] :
|
|
||||||
$this->config->get('default_channel');
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
if (!$reg->channelExists($channel)) {
|
|
||||||
return $this->raiseError('Channel "' . $channel . '" does not exist');
|
|
||||||
}
|
|
||||||
|
|
||||||
$channel = $reg->channelName($channel);
|
|
||||||
$data = array('caption' => 'Configuration (channel ' . $channel . '):');
|
|
||||||
foreach ($keys as $key) {
|
|
||||||
$type = $this->config->getType($key);
|
|
||||||
$value = $this->config->get($key, $layer, $channel);
|
|
||||||
if ($type == 'password' && $value) {
|
|
||||||
$value = '********';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($value === false) {
|
|
||||||
$value = 'false';
|
|
||||||
} elseif ($value === true) {
|
|
||||||
$value = 'true';
|
|
||||||
}
|
|
||||||
|
|
||||||
$data['data'][$this->config->getGroup($key)][] = array($this->config->getPrompt($key) , $key, $value);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($this->config->getLayers() as $layer) {
|
|
||||||
$data['data']['Config Files'][] = array(ucfirst($layer) . ' Configuration File', 'Filename' , $this->config->getConfFile($layer));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->ui->outputData($data, $command);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function doConfigGet($command, $options, $params)
|
|
||||||
{
|
|
||||||
$args_cnt = is_array($params) ? count($params) : 0;
|
|
||||||
switch ($args_cnt) {
|
|
||||||
case 1:
|
|
||||||
$config_key = $params[0];
|
|
||||||
$layer = null;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
$config_key = $params[0];
|
|
||||||
$layer = $params[1];
|
|
||||||
if ($error = $this->_checkLayer($layer)) {
|
|
||||||
return $this->raiseError("config-get:$error");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
default:
|
|
||||||
return $this->raiseError("config-get expects 1 or 2 parameters");
|
|
||||||
}
|
|
||||||
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
$channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
|
|
||||||
if (!$reg->channelExists($channel)) {
|
|
||||||
return $this->raiseError('Channel "' . $channel . '" does not exist');
|
|
||||||
}
|
|
||||||
|
|
||||||
$channel = $reg->channelName($channel);
|
|
||||||
$this->ui->outputData($this->config->get($config_key, $layer, $channel), $command);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function doConfigSet($command, $options, $params)
|
|
||||||
{
|
|
||||||
// $param[0] -> a parameter to set
|
|
||||||
// $param[1] -> the value for the parameter
|
|
||||||
// $param[2] -> the layer
|
|
||||||
$failmsg = '';
|
|
||||||
if (count($params) < 2 || count($params) > 3) {
|
|
||||||
$failmsg .= "config-set expects 2 or 3 parameters";
|
|
||||||
return PEAR::raiseError($failmsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($params[2]) && ($error = $this->_checkLayer($params[2]))) {
|
|
||||||
$failmsg .= $error;
|
|
||||||
return PEAR::raiseError("config-set:$failmsg");
|
|
||||||
}
|
|
||||||
|
|
||||||
$channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
if (!$reg->channelExists($channel)) {
|
|
||||||
return $this->raiseError('Channel "' . $channel . '" does not exist');
|
|
||||||
}
|
|
||||||
|
|
||||||
$channel = $reg->channelName($channel);
|
|
||||||
if ($params[0] == 'default_channel' && !$reg->channelExists($params[1])) {
|
|
||||||
return $this->raiseError('Channel "' . $params[1] . '" does not exist');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($params[0] == 'preferred_mirror'
|
|
||||||
&& (
|
|
||||||
!$reg->mirrorExists($channel, $params[1]) &&
|
|
||||||
(!$reg->channelExists($params[1]) || $channel != $params[1])
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
$msg = 'Channel Mirror "' . $params[1] . '" does not exist';
|
|
||||||
$msg .= ' in your registry for channel "' . $channel . '".';
|
|
||||||
$msg .= "\n" . 'Attempt to run "pear channel-update ' . $channel .'"';
|
|
||||||
$msg .= ' if you believe this mirror should exist as you may';
|
|
||||||
$msg .= ' have outdated channel information.';
|
|
||||||
return $this->raiseError($msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($params) == 2) {
|
|
||||||
array_push($params, 'user');
|
|
||||||
$layer = 'user';
|
|
||||||
} else {
|
|
||||||
$layer = $params[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
array_push($params, $channel);
|
|
||||||
if (!call_user_func_array(array(&$this->config, 'set'), $params)) {
|
|
||||||
array_pop($params);
|
|
||||||
$failmsg = "config-set (" . implode(", ", $params) . ") failed, channel $channel";
|
|
||||||
} else {
|
|
||||||
$this->config->store($layer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($failmsg) {
|
|
||||||
return $this->raiseError($failmsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->ui->outputData('config-set succeeded', $command);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function doConfigHelp($command, $options, $params)
|
|
||||||
{
|
|
||||||
if (empty($params)) {
|
|
||||||
$params = $this->config->getKeys();
|
|
||||||
}
|
|
||||||
|
|
||||||
$data['caption'] = "Config help" . ((count($params) == 1) ? " for $params[0]" : '');
|
|
||||||
$data['headline'] = array('Name', 'Type', 'Description');
|
|
||||||
$data['border'] = true;
|
|
||||||
foreach ($params as $name) {
|
|
||||||
$type = $this->config->getType($name);
|
|
||||||
$docs = $this->config->getDocs($name);
|
|
||||||
if ($type == 'set') {
|
|
||||||
$docs = rtrim($docs) . "\nValid set: " .
|
|
||||||
implode(' ', $this->config->getSetValues($name));
|
|
||||||
}
|
|
||||||
|
|
||||||
$data['data'][] = array($name, $type, $docs);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->ui->outputData($data, $command);
|
|
||||||
}
|
|
||||||
|
|
||||||
function doConfigCreate($command, $options, $params)
|
|
||||||
{
|
|
||||||
if (count($params) != 2) {
|
|
||||||
return PEAR::raiseError('config-create: must have 2 parameters, root path and ' .
|
|
||||||
'filename to save as');
|
|
||||||
}
|
|
||||||
|
|
||||||
$root = $params[0];
|
|
||||||
// Clean up the DIRECTORY_SEPARATOR mess
|
|
||||||
$ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
|
|
||||||
$root = preg_replace(array('!\\\\+!', '!/+!', "!$ds2+!"),
|
|
||||||
array('/', '/', '/'),
|
|
||||||
$root);
|
|
||||||
if ($root{0} != '/') {
|
|
||||||
if (!isset($options['windows'])) {
|
|
||||||
return PEAR::raiseError('Root directory must be an absolute path beginning ' .
|
|
||||||
'with "/", was: "' . $root . '"');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!preg_match('/^[A-Za-z]:/', $root)) {
|
|
||||||
return PEAR::raiseError('Root directory must be an absolute path beginning ' .
|
|
||||||
'with "\\" or "C:\\", was: "' . $root . '"');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$windows = isset($options['windows']);
|
|
||||||
if ($windows) {
|
|
||||||
$root = str_replace('/', '\\', $root);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!file_exists($params[1]) && !@touch($params[1])) {
|
|
||||||
return PEAR::raiseError('Could not create "' . $params[1] . '"');
|
|
||||||
}
|
|
||||||
|
|
||||||
$params[1] = realpath($params[1]);
|
|
||||||
$config = &new PEAR_Config($params[1], '#no#system#config#', false, false);
|
|
||||||
if ($root{strlen($root) - 1} == '/') {
|
|
||||||
$root = substr($root, 0, strlen($root) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
$config->noRegistry();
|
|
||||||
$config->set('php_dir', $windows ? "$root\\pear\\php" : "$root/pear/php", 'user');
|
|
||||||
$config->set('data_dir', $windows ? "$root\\pear\\data" : "$root/pear/data");
|
|
||||||
$config->set('www_dir', $windows ? "$root\\pear\\www" : "$root/pear/www");
|
|
||||||
$config->set('cfg_dir', $windows ? "$root\\pear\\cfg" : "$root/pear/cfg");
|
|
||||||
$config->set('ext_dir', $windows ? "$root\\pear\\ext" : "$root/pear/ext");
|
|
||||||
$config->set('doc_dir', $windows ? "$root\\pear\\docs" : "$root/pear/docs");
|
|
||||||
$config->set('test_dir', $windows ? "$root\\pear\\tests" : "$root/pear/tests");
|
|
||||||
$config->set('cache_dir', $windows ? "$root\\pear\\cache" : "$root/pear/cache");
|
|
||||||
$config->set('download_dir', $windows ? "$root\\pear\\download" : "$root/pear/download");
|
|
||||||
$config->set('temp_dir', $windows ? "$root\\pear\\temp" : "$root/pear/temp");
|
|
||||||
$config->set('bin_dir', $windows ? "$root\\pear" : "$root/pear");
|
|
||||||
$config->writeConfigFile();
|
|
||||||
$this->_showConfig($config);
|
|
||||||
$this->ui->outputData('Successfully created default configuration file "' . $params[1] . '"',
|
|
||||||
$command);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _showConfig(&$config)
|
|
||||||
{
|
|
||||||
$params = array('user');
|
|
||||||
$keys = $config->getKeys();
|
|
||||||
sort($keys);
|
|
||||||
$channel = 'pear.php.net';
|
|
||||||
$data = array('caption' => 'Configuration (channel ' . $channel . '):');
|
|
||||||
foreach ($keys as $key) {
|
|
||||||
$type = $config->getType($key);
|
|
||||||
$value = $config->get($key, 'user', $channel);
|
|
||||||
if ($type == 'password' && $value) {
|
|
||||||
$value = '********';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($value === false) {
|
|
||||||
$value = 'false';
|
|
||||||
} elseif ($value === true) {
|
|
||||||
$value = 'true';
|
|
||||||
}
|
|
||||||
$data['data'][$config->getGroup($key)][] =
|
|
||||||
array($config->getPrompt($key) , $key, $value);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($config->getLayers() as $layer) {
|
|
||||||
$data['data']['Config Files'][] =
|
|
||||||
array(ucfirst($layer) . ' Configuration File', 'Filename' ,
|
|
||||||
$config->getConfFile($layer));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->ui->outputData($data, 'config-show');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a layer is defined or not
|
|
||||||
*
|
|
||||||
* @param string $layer The layer to search for
|
|
||||||
* @return mixed False on no error or the error message
|
|
||||||
*/
|
|
||||||
function _checkLayer($layer = null)
|
|
||||||
{
|
|
||||||
if (!empty($layer) && $layer != 'default') {
|
|
||||||
$layers = $this->config->getLayers();
|
|
||||||
if (!in_array($layer, $layers)) {
|
|
||||||
return " only the layers: \"" . implode('" or "', $layers) . "\" are supported";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,92 +0,0 @@
|
||||||
<commands version="1.0">
|
|
||||||
<config-show>
|
|
||||||
<summary>Show All Settings</summary>
|
|
||||||
<function>doConfigShow</function>
|
|
||||||
<shortcut>csh</shortcut>
|
|
||||||
<options>
|
|
||||||
<channel>
|
|
||||||
<shortopt>c</shortopt>
|
|
||||||
<doc>show configuration variables for another channel</doc>
|
|
||||||
<arg>CHAN</arg>
|
|
||||||
</channel>
|
|
||||||
</options>
|
|
||||||
<doc>[layer]
|
|
||||||
Displays all configuration values. An optional argument
|
|
||||||
may be used to tell which configuration layer to display. Valid
|
|
||||||
configuration layers are "user", "system" and "default". To display
|
|
||||||
configurations for different channels, set the default_channel
|
|
||||||
configuration variable and run config-show again.
|
|
||||||
</doc>
|
|
||||||
</config-show>
|
|
||||||
<config-get>
|
|
||||||
<summary>Show One Setting</summary>
|
|
||||||
<function>doConfigGet</function>
|
|
||||||
<shortcut>cg</shortcut>
|
|
||||||
<options>
|
|
||||||
<channel>
|
|
||||||
<shortopt>c</shortopt>
|
|
||||||
<doc>show configuration variables for another channel</doc>
|
|
||||||
<arg>CHAN</arg>
|
|
||||||
</channel>
|
|
||||||
</options>
|
|
||||||
<doc><parameter> [layer]
|
|
||||||
Displays the value of one configuration parameter. The
|
|
||||||
first argument is the name of the parameter, an optional second argument
|
|
||||||
may be used to tell which configuration layer to look in. Valid configuration
|
|
||||||
layers are "user", "system" and "default". If no layer is specified, a value
|
|
||||||
will be picked from the first layer that defines the parameter, in the order
|
|
||||||
just specified. The configuration value will be retrieved for the channel
|
|
||||||
specified by the default_channel configuration variable.
|
|
||||||
</doc>
|
|
||||||
</config-get>
|
|
||||||
<config-set>
|
|
||||||
<summary>Change Setting</summary>
|
|
||||||
<function>doConfigSet</function>
|
|
||||||
<shortcut>cs</shortcut>
|
|
||||||
<options>
|
|
||||||
<channel>
|
|
||||||
<shortopt>c</shortopt>
|
|
||||||
<doc>show configuration variables for another channel</doc>
|
|
||||||
<arg>CHAN</arg>
|
|
||||||
</channel>
|
|
||||||
</options>
|
|
||||||
<doc><parameter> <value> [layer]
|
|
||||||
Sets the value of one configuration parameter. The first argument is
|
|
||||||
the name of the parameter, the second argument is the new value. Some
|
|
||||||
parameters are subject to validation, and the command will fail with
|
|
||||||
an error message if the new value does not make sense. An optional
|
|
||||||
third argument may be used to specify in which layer to set the
|
|
||||||
configuration parameter. The default layer is "user". The
|
|
||||||
configuration value will be set for the current channel, which
|
|
||||||
is controlled by the default_channel configuration variable.
|
|
||||||
</doc>
|
|
||||||
</config-set>
|
|
||||||
<config-help>
|
|
||||||
<summary>Show Information About Setting</summary>
|
|
||||||
<function>doConfigHelp</function>
|
|
||||||
<shortcut>ch</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc>[parameter]
|
|
||||||
Displays help for a configuration parameter. Without arguments it
|
|
||||||
displays help for all configuration parameters.
|
|
||||||
</doc>
|
|
||||||
</config-help>
|
|
||||||
<config-create>
|
|
||||||
<summary>Create a Default configuration file</summary>
|
|
||||||
<function>doConfigCreate</function>
|
|
||||||
<shortcut>coc</shortcut>
|
|
||||||
<options>
|
|
||||||
<windows>
|
|
||||||
<shortopt>w</shortopt>
|
|
||||||
<doc>create a config file for a windows install</doc>
|
|
||||||
</windows>
|
|
||||||
</options>
|
|
||||||
<doc><root path> <filename>
|
|
||||||
Create a default configuration file with all directory configuration
|
|
||||||
variables set to subdirectories of <root path>, and save it as <filename>.
|
|
||||||
This is useful especially for creating a configuration file for a remote
|
|
||||||
PEAR installation (using the --remoteconfig option of install, upgrade,
|
|
||||||
and uninstall).
|
|
||||||
</doc>
|
|
||||||
</config-create>
|
|
||||||
</commands>
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,276 +0,0 @@
|
||||||
<commands version="1.0">
|
|
||||||
<install>
|
|
||||||
<summary>Install Package</summary>
|
|
||||||
<function>doInstall</function>
|
|
||||||
<shortcut>i</shortcut>
|
|
||||||
<options>
|
|
||||||
<force>
|
|
||||||
<shortopt>f</shortopt>
|
|
||||||
<doc>will overwrite newer installed packages</doc>
|
|
||||||
</force>
|
|
||||||
<loose>
|
|
||||||
<shortopt>l</shortopt>
|
|
||||||
<doc>do not check for recommended dependency version</doc>
|
|
||||||
</loose>
|
|
||||||
<nodeps>
|
|
||||||
<shortopt>n</shortopt>
|
|
||||||
<doc>ignore dependencies, install anyway</doc>
|
|
||||||
</nodeps>
|
|
||||||
<register-only>
|
|
||||||
<shortopt>r</shortopt>
|
|
||||||
<doc>do not install files, only register the package as installed</doc>
|
|
||||||
</register-only>
|
|
||||||
<soft>
|
|
||||||
<shortopt>s</shortopt>
|
|
||||||
<doc>soft install, fail silently, or upgrade if already installed</doc>
|
|
||||||
</soft>
|
|
||||||
<nobuild>
|
|
||||||
<shortopt>B</shortopt>
|
|
||||||
<doc>don't build C extensions</doc>
|
|
||||||
</nobuild>
|
|
||||||
<nocompress>
|
|
||||||
<shortopt>Z</shortopt>
|
|
||||||
<doc>request uncompressed files when downloading</doc>
|
|
||||||
</nocompress>
|
|
||||||
<installroot>
|
|
||||||
<shortopt>R</shortopt>
|
|
||||||
<doc>root directory used when installing files (ala PHP's INSTALL_ROOT), use packagingroot for RPM</doc>
|
|
||||||
<arg>DIR</arg>
|
|
||||||
</installroot>
|
|
||||||
<packagingroot>
|
|
||||||
<shortopt>P</shortopt>
|
|
||||||
<doc>root directory used when packaging files, like RPM packaging</doc>
|
|
||||||
<arg>DIR</arg>
|
|
||||||
</packagingroot>
|
|
||||||
<ignore-errors>
|
|
||||||
<shortopt></shortopt>
|
|
||||||
<doc>force install even if there were errors</doc>
|
|
||||||
</ignore-errors>
|
|
||||||
<alldeps>
|
|
||||||
<shortopt>a</shortopt>
|
|
||||||
<doc>install all required and optional dependencies</doc>
|
|
||||||
</alldeps>
|
|
||||||
<onlyreqdeps>
|
|
||||||
<shortopt>o</shortopt>
|
|
||||||
<doc>install all required dependencies</doc>
|
|
||||||
</onlyreqdeps>
|
|
||||||
<offline>
|
|
||||||
<shortopt>O</shortopt>
|
|
||||||
<doc>do not attempt to download any urls or contact channels</doc>
|
|
||||||
</offline>
|
|
||||||
<pretend>
|
|
||||||
<shortopt>p</shortopt>
|
|
||||||
<doc>Only list the packages that would be downloaded</doc>
|
|
||||||
</pretend>
|
|
||||||
</options>
|
|
||||||
<doc>[channel/]<package> ...
|
|
||||||
Installs one or more PEAR packages. You can specify a package to
|
|
||||||
install in four ways:
|
|
||||||
|
|
||||||
"Package-1.0.tgz" : installs from a local file
|
|
||||||
|
|
||||||
"http://example.com/Package-1.0.tgz" : installs from
|
|
||||||
anywhere on the net.
|
|
||||||
|
|
||||||
"package.xml" : installs the package described in
|
|
||||||
package.xml. Useful for testing, or for wrapping a PEAR package in
|
|
||||||
another package manager such as RPM.
|
|
||||||
|
|
||||||
"Package[-version/state][.tar]" : queries your default channel's server
|
|
||||||
({config master_server}) and downloads the newest package with
|
|
||||||
the preferred quality/state ({config preferred_state}).
|
|
||||||
|
|
||||||
To retrieve Package version 1.1, use "Package-1.1," to retrieve
|
|
||||||
Package state beta, use "Package-beta." To retrieve an uncompressed
|
|
||||||
file, append .tar (make sure there is no file by the same name first)
|
|
||||||
|
|
||||||
To download a package from another channel, prefix with the channel name like
|
|
||||||
"channel/Package"
|
|
||||||
|
|
||||||
More than one package may be specified at once. It is ok to mix these
|
|
||||||
four ways of specifying packages.
|
|
||||||
</doc>
|
|
||||||
</install>
|
|
||||||
<upgrade>
|
|
||||||
<summary>Upgrade Package</summary>
|
|
||||||
<function>doInstall</function>
|
|
||||||
<shortcut>up</shortcut>
|
|
||||||
<options>
|
|
||||||
<channel>
|
|
||||||
<shortopt>c</shortopt>
|
|
||||||
<doc>upgrade packages from a specific channel</doc>
|
|
||||||
<arg>CHAN</arg>
|
|
||||||
</channel>
|
|
||||||
<force>
|
|
||||||
<shortopt>f</shortopt>
|
|
||||||
<doc>overwrite newer installed packages</doc>
|
|
||||||
</force>
|
|
||||||
<loose>
|
|
||||||
<shortopt>l</shortopt>
|
|
||||||
<doc>do not check for recommended dependency version</doc>
|
|
||||||
</loose>
|
|
||||||
<nodeps>
|
|
||||||
<shortopt>n</shortopt>
|
|
||||||
<doc>ignore dependencies, upgrade anyway</doc>
|
|
||||||
</nodeps>
|
|
||||||
<register-only>
|
|
||||||
<shortopt>r</shortopt>
|
|
||||||
<doc>do not install files, only register the package as upgraded</doc>
|
|
||||||
</register-only>
|
|
||||||
<nobuild>
|
|
||||||
<shortopt>B</shortopt>
|
|
||||||
<doc>don't build C extensions</doc>
|
|
||||||
</nobuild>
|
|
||||||
<nocompress>
|
|
||||||
<shortopt>Z</shortopt>
|
|
||||||
<doc>request uncompressed files when downloading</doc>
|
|
||||||
</nocompress>
|
|
||||||
<installroot>
|
|
||||||
<shortopt>R</shortopt>
|
|
||||||
<doc>root directory used when installing files (ala PHP's INSTALL_ROOT)</doc>
|
|
||||||
<arg>DIR</arg>
|
|
||||||
</installroot>
|
|
||||||
<ignore-errors>
|
|
||||||
<shortopt></shortopt>
|
|
||||||
<doc>force install even if there were errors</doc>
|
|
||||||
</ignore-errors>
|
|
||||||
<alldeps>
|
|
||||||
<shortopt>a</shortopt>
|
|
||||||
<doc>install all required and optional dependencies</doc>
|
|
||||||
</alldeps>
|
|
||||||
<onlyreqdeps>
|
|
||||||
<shortopt>o</shortopt>
|
|
||||||
<doc>install all required dependencies</doc>
|
|
||||||
</onlyreqdeps>
|
|
||||||
<offline>
|
|
||||||
<shortopt>O</shortopt>
|
|
||||||
<doc>do not attempt to download any urls or contact channels</doc>
|
|
||||||
</offline>
|
|
||||||
<pretend>
|
|
||||||
<shortopt>p</shortopt>
|
|
||||||
<doc>Only list the packages that would be downloaded</doc>
|
|
||||||
</pretend>
|
|
||||||
</options>
|
|
||||||
<doc><package> ...
|
|
||||||
Upgrades one or more PEAR packages. See documentation for the
|
|
||||||
"install" command for ways to specify a package.
|
|
||||||
|
|
||||||
When upgrading, your package will be updated if the provided new
|
|
||||||
package has a higher version number (use the -f option if you need to
|
|
||||||
upgrade anyway).
|
|
||||||
|
|
||||||
More than one package may be specified at once.
|
|
||||||
</doc>
|
|
||||||
</upgrade>
|
|
||||||
<upgrade-all>
|
|
||||||
<summary>Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]</summary>
|
|
||||||
<function>doUpgradeAll</function>
|
|
||||||
<shortcut>ua</shortcut>
|
|
||||||
<options>
|
|
||||||
<channel>
|
|
||||||
<shortopt>c</shortopt>
|
|
||||||
<doc>upgrade packages from a specific channel</doc>
|
|
||||||
<arg>CHAN</arg>
|
|
||||||
</channel>
|
|
||||||
<nodeps>
|
|
||||||
<shortopt>n</shortopt>
|
|
||||||
<doc>ignore dependencies, upgrade anyway</doc>
|
|
||||||
</nodeps>
|
|
||||||
<register-only>
|
|
||||||
<shortopt>r</shortopt>
|
|
||||||
<doc>do not install files, only register the package as upgraded</doc>
|
|
||||||
</register-only>
|
|
||||||
<nobuild>
|
|
||||||
<shortopt>B</shortopt>
|
|
||||||
<doc>don't build C extensions</doc>
|
|
||||||
</nobuild>
|
|
||||||
<nocompress>
|
|
||||||
<shortopt>Z</shortopt>
|
|
||||||
<doc>request uncompressed files when downloading</doc>
|
|
||||||
</nocompress>
|
|
||||||
<installroot>
|
|
||||||
<shortopt>R</shortopt>
|
|
||||||
<doc>root directory used when installing files (ala PHP's INSTALL_ROOT), use packagingroot for RPM</doc>
|
|
||||||
<arg>DIR</arg>
|
|
||||||
</installroot>
|
|
||||||
<ignore-errors>
|
|
||||||
<shortopt></shortopt>
|
|
||||||
<doc>force install even if there were errors</doc>
|
|
||||||
</ignore-errors>
|
|
||||||
<loose>
|
|
||||||
<shortopt></shortopt>
|
|
||||||
<doc>do not check for recommended dependency version</doc>
|
|
||||||
</loose>
|
|
||||||
</options>
|
|
||||||
<doc>
|
|
||||||
WARNING: This function is deprecated in favor of using the upgrade command with no params
|
|
||||||
|
|
||||||
Upgrades all packages that have a newer release available. Upgrades are
|
|
||||||
done only if there is a release available of the state specified in
|
|
||||||
"preferred_state" (currently {config preferred_state}), or a state considered
|
|
||||||
more stable.
|
|
||||||
</doc>
|
|
||||||
</upgrade-all>
|
|
||||||
<uninstall>
|
|
||||||
<summary>Un-install Package</summary>
|
|
||||||
<function>doUninstall</function>
|
|
||||||
<shortcut>un</shortcut>
|
|
||||||
<options>
|
|
||||||
<nodeps>
|
|
||||||
<shortopt>n</shortopt>
|
|
||||||
<doc>ignore dependencies, uninstall anyway</doc>
|
|
||||||
</nodeps>
|
|
||||||
<register-only>
|
|
||||||
<shortopt>r</shortopt>
|
|
||||||
<doc>do not remove files, only register the packages as not installed</doc>
|
|
||||||
</register-only>
|
|
||||||
<installroot>
|
|
||||||
<shortopt>R</shortopt>
|
|
||||||
<doc>root directory used when installing files (ala PHP's INSTALL_ROOT)</doc>
|
|
||||||
<arg>DIR</arg>
|
|
||||||
</installroot>
|
|
||||||
<ignore-errors>
|
|
||||||
<shortopt></shortopt>
|
|
||||||
<doc>force install even if there were errors</doc>
|
|
||||||
</ignore-errors>
|
|
||||||
<offline>
|
|
||||||
<shortopt>O</shortopt>
|
|
||||||
<doc>do not attempt to uninstall remotely</doc>
|
|
||||||
</offline>
|
|
||||||
</options>
|
|
||||||
<doc>[channel/]<package> ...
|
|
||||||
Uninstalls one or more PEAR packages. More than one package may be
|
|
||||||
specified at once. Prefix with channel name to uninstall from a
|
|
||||||
channel not in your default channel ({config default_channel})
|
|
||||||
</doc>
|
|
||||||
</uninstall>
|
|
||||||
<bundle>
|
|
||||||
<summary>Unpacks a Pecl Package</summary>
|
|
||||||
<function>doBundle</function>
|
|
||||||
<shortcut>bun</shortcut>
|
|
||||||
<options>
|
|
||||||
<destination>
|
|
||||||
<shortopt>d</shortopt>
|
|
||||||
<doc>Optional destination directory for unpacking (defaults to current path or "ext" if exists)</doc>
|
|
||||||
<arg>DIR</arg>
|
|
||||||
</destination>
|
|
||||||
<force>
|
|
||||||
<shortopt>f</shortopt>
|
|
||||||
<doc>Force the unpacking even if there were errors in the package</doc>
|
|
||||||
</force>
|
|
||||||
</options>
|
|
||||||
<doc><package>
|
|
||||||
Unpacks a Pecl Package into the selected location. It will download the
|
|
||||||
package if needed.
|
|
||||||
</doc>
|
|
||||||
</bundle>
|
|
||||||
<run-scripts>
|
|
||||||
<summary>Run Post-Install Scripts bundled with a package</summary>
|
|
||||||
<function>doRunScripts</function>
|
|
||||||
<shortcut>rs</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc><package>
|
|
||||||
Run post-installation scripts in package <package>, if any exist.
|
|
||||||
</doc>
|
|
||||||
</run-scripts>
|
|
||||||
</commands>
|
|
|
@ -1,139 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* PEAR_Command_Mirror (download-all command)
|
|
||||||
*
|
|
||||||
* PHP versions 4 and 5
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Alexander Merz <alexmerz@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version CVS: $Id: Mirror.php 313023 2011-07-06 19:17:11Z dufuz $
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since File available since Release 1.2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* base class
|
|
||||||
*/
|
|
||||||
require_once 'PEAR/Command/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR commands for providing file mirrors
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Alexander Merz <alexmerz@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version Release: 1.9.4
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since Class available since Release 1.2.0
|
|
||||||
*/
|
|
||||||
class PEAR_Command_Mirror extends PEAR_Command_Common
|
|
||||||
{
|
|
||||||
var $commands = array(
|
|
||||||
'download-all' => array(
|
|
||||||
'summary' => 'Downloads each available package from the default channel',
|
|
||||||
'function' => 'doDownloadAll',
|
|
||||||
'shortcut' => 'da',
|
|
||||||
'options' => array(
|
|
||||||
'channel' =>
|
|
||||||
array(
|
|
||||||
'shortopt' => 'c',
|
|
||||||
'doc' => 'specify a channel other than the default channel',
|
|
||||||
'arg' => 'CHAN',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
'doc' => '
|
|
||||||
Requests a list of available packages from the default channel ({config default_channel})
|
|
||||||
and downloads them to current working directory. Note: only
|
|
||||||
packages within preferred_state ({config preferred_state}) will be downloaded'
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR_Command_Mirror constructor.
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param object PEAR_Frontend a reference to an frontend
|
|
||||||
* @param object PEAR_Config a reference to the configuration data
|
|
||||||
*/
|
|
||||||
function PEAR_Command_Mirror(&$ui, &$config)
|
|
||||||
{
|
|
||||||
parent::PEAR_Command_Common($ui, $config);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For unit-testing
|
|
||||||
*/
|
|
||||||
function &factory($a)
|
|
||||||
{
|
|
||||||
$a = &PEAR_Command::factory($a, $this->config);
|
|
||||||
return $a;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* retrieves a list of avaible Packages from master server
|
|
||||||
* and downloads them
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $command the command
|
|
||||||
* @param array $options the command options before the command
|
|
||||||
* @param array $params the stuff after the command name
|
|
||||||
* @return bool true if succesful
|
|
||||||
* @throw PEAR_Error
|
|
||||||
*/
|
|
||||||
function doDownloadAll($command, $options, $params)
|
|
||||||
{
|
|
||||||
$savechannel = $this->config->get('default_channel');
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
$channel = isset($options['channel']) ? $options['channel'] :
|
|
||||||
$this->config->get('default_channel');
|
|
||||||
if (!$reg->channelExists($channel)) {
|
|
||||||
$this->config->set('default_channel', $savechannel);
|
|
||||||
return $this->raiseError('Channel "' . $channel . '" does not exist');
|
|
||||||
}
|
|
||||||
$this->config->set('default_channel', $channel);
|
|
||||||
|
|
||||||
$this->ui->outputData('Using Channel ' . $this->config->get('default_channel'));
|
|
||||||
$chan = $reg->getChannel($channel);
|
|
||||||
if (PEAR::isError($chan)) {
|
|
||||||
return $this->raiseError($chan);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
|
|
||||||
$base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
|
|
||||||
$rest = &$this->config->getREST('1.0', array());
|
|
||||||
$remoteInfo = array_flip($rest->listPackages($base, $channel));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PEAR::isError($remoteInfo)) {
|
|
||||||
return $remoteInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
$cmd = &$this->factory("download");
|
|
||||||
if (PEAR::isError($cmd)) {
|
|
||||||
return $cmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->ui->outputData('Using Preferred State of ' .
|
|
||||||
$this->config->get('preferred_state'));
|
|
||||||
$this->ui->outputData('Gathering release information, please wait...');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Error handling not necessary, because already done by
|
|
||||||
* the download command
|
|
||||||
*/
|
|
||||||
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
|
|
||||||
$err = $cmd->run('download', array('downloadonly' => true), array_keys($remoteInfo));
|
|
||||||
PEAR::staticPopErrorHandling();
|
|
||||||
$this->config->set('default_channel', $savechannel);
|
|
||||||
if (PEAR::isError($err)) {
|
|
||||||
$this->ui->outputData($err->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
<commands version="1.0">
|
|
||||||
<download-all>
|
|
||||||
<summary>Downloads each available package from the default channel</summary>
|
|
||||||
<function>doDownloadAll</function>
|
|
||||||
<shortcut>da</shortcut>
|
|
||||||
<options>
|
|
||||||
<channel>
|
|
||||||
<shortopt>c</shortopt>
|
|
||||||
<doc>specify a channel other than the default channel</doc>
|
|
||||||
<arg>CHAN</arg>
|
|
||||||
</channel>
|
|
||||||
</options>
|
|
||||||
<doc>
|
|
||||||
Requests a list of available packages from the default channel ({config default_channel})
|
|
||||||
and downloads them to current working directory. Note: only
|
|
||||||
packages within preferred_state ({config preferred_state}) will be downloaded</doc>
|
|
||||||
</download-all>
|
|
||||||
</commands>
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,237 +0,0 @@
|
||||||
<commands version="1.0">
|
|
||||||
<package>
|
|
||||||
<summary>Build Package</summary>
|
|
||||||
<function>doPackage</function>
|
|
||||||
<shortcut>p</shortcut>
|
|
||||||
<options>
|
|
||||||
<nocompress>
|
|
||||||
<shortopt>Z</shortopt>
|
|
||||||
<doc>Do not gzip the package file</doc>
|
|
||||||
</nocompress>
|
|
||||||
<showname>
|
|
||||||
<shortopt>n</shortopt>
|
|
||||||
<doc>Print the name of the packaged file.</doc>
|
|
||||||
</showname>
|
|
||||||
</options>
|
|
||||||
<doc>[descfile] [descfile2]
|
|
||||||
Creates a PEAR package from its description file (usually called
|
|
||||||
package.xml). If a second packagefile is passed in, then
|
|
||||||
the packager will check to make sure that one is a package.xml
|
|
||||||
version 1.0, and the other is a package.xml version 2.0. The
|
|
||||||
package.xml version 1.0 will be saved as "package.xml" in the archive,
|
|
||||||
and the other as "package2.xml" in the archive"
|
|
||||||
</doc>
|
|
||||||
</package>
|
|
||||||
<package-validate>
|
|
||||||
<summary>Validate Package Consistency</summary>
|
|
||||||
<function>doPackageValidate</function>
|
|
||||||
<shortcut>pv</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc>
|
|
||||||
</doc>
|
|
||||||
</package-validate>
|
|
||||||
<cvsdiff>
|
|
||||||
<summary>Run a "cvs diff" for all files in a package</summary>
|
|
||||||
<function>doCvsDiff</function>
|
|
||||||
<shortcut>cd</shortcut>
|
|
||||||
<options>
|
|
||||||
<quiet>
|
|
||||||
<shortopt>q</shortopt>
|
|
||||||
<doc>Be quiet</doc>
|
|
||||||
</quiet>
|
|
||||||
<reallyquiet>
|
|
||||||
<shortopt>Q</shortopt>
|
|
||||||
<doc>Be really quiet</doc>
|
|
||||||
</reallyquiet>
|
|
||||||
<date>
|
|
||||||
<shortopt>D</shortopt>
|
|
||||||
<doc>Diff against revision of DATE</doc>
|
|
||||||
<arg>DATE</arg>
|
|
||||||
</date>
|
|
||||||
<release>
|
|
||||||
<shortopt>R</shortopt>
|
|
||||||
<doc>Diff against tag for package release REL</doc>
|
|
||||||
<arg>REL</arg>
|
|
||||||
</release>
|
|
||||||
<revision>
|
|
||||||
<shortopt>r</shortopt>
|
|
||||||
<doc>Diff against revision REV</doc>
|
|
||||||
<arg>REV</arg>
|
|
||||||
</revision>
|
|
||||||
<context>
|
|
||||||
<shortopt>c</shortopt>
|
|
||||||
<doc>Generate context diff</doc>
|
|
||||||
</context>
|
|
||||||
<unified>
|
|
||||||
<shortopt>u</shortopt>
|
|
||||||
<doc>Generate unified diff</doc>
|
|
||||||
</unified>
|
|
||||||
<ignore-case>
|
|
||||||
<shortopt>i</shortopt>
|
|
||||||
<doc>Ignore case, consider upper- and lower-case letters equivalent</doc>
|
|
||||||
</ignore-case>
|
|
||||||
<ignore-whitespace>
|
|
||||||
<shortopt>b</shortopt>
|
|
||||||
<doc>Ignore changes in amount of white space</doc>
|
|
||||||
</ignore-whitespace>
|
|
||||||
<ignore-blank-lines>
|
|
||||||
<shortopt>B</shortopt>
|
|
||||||
<doc>Ignore changes that insert or delete blank lines</doc>
|
|
||||||
</ignore-blank-lines>
|
|
||||||
<brief>
|
|
||||||
<shortopt></shortopt>
|
|
||||||
<doc>Report only whether the files differ, no details</doc>
|
|
||||||
</brief>
|
|
||||||
<dry-run>
|
|
||||||
<shortopt>n</shortopt>
|
|
||||||
<doc>Don't do anything, just pretend</doc>
|
|
||||||
</dry-run>
|
|
||||||
</options>
|
|
||||||
<doc><package.xml>
|
|
||||||
Compares all the files in a package. Without any options, this
|
|
||||||
command will compare the current code with the last checked-in code.
|
|
||||||
Using the -r or -R option you may compare the current code with that
|
|
||||||
of a specific release.
|
|
||||||
</doc>
|
|
||||||
</cvsdiff>
|
|
||||||
<svntag>
|
|
||||||
<summary>Set SVN Release Tag</summary>
|
|
||||||
<function>doSvnTag</function>
|
|
||||||
<shortcut>sv</shortcut>
|
|
||||||
<options>
|
|
||||||
<quiet>
|
|
||||||
<shortopt>q</shortopt>
|
|
||||||
<doc>Be quiet</doc>
|
|
||||||
</quiet>
|
|
||||||
<slide>
|
|
||||||
<shortopt>F</shortopt>
|
|
||||||
<doc>Move (slide) tag if it exists</doc>
|
|
||||||
</slide>
|
|
||||||
<delete>
|
|
||||||
<shortopt>d</shortopt>
|
|
||||||
<doc>Remove tag</doc>
|
|
||||||
</delete>
|
|
||||||
<dry-run>
|
|
||||||
<shortopt>n</shortopt>
|
|
||||||
<doc>Don't do anything, just pretend</doc>
|
|
||||||
</dry-run>
|
|
||||||
</options>
|
|
||||||
<doc><package.xml> [files...]
|
|
||||||
Sets a SVN tag on all files in a package. Use this command after you have
|
|
||||||
packaged a distribution tarball with the "package" command to tag what
|
|
||||||
revisions of what files were in that release. If need to fix something
|
|
||||||
after running svntag once, but before the tarball is released to the public,
|
|
||||||
use the "slide" option to move the release tag.
|
|
||||||
|
|
||||||
to include files (such as a second package.xml, or tests not included in the
|
|
||||||
release), pass them as additional parameters.
|
|
||||||
</doc>
|
|
||||||
</svntag>
|
|
||||||
<cvstag>
|
|
||||||
<summary>Set CVS Release Tag</summary>
|
|
||||||
<function>doCvsTag</function>
|
|
||||||
<shortcut>ct</shortcut>
|
|
||||||
<options>
|
|
||||||
<quiet>
|
|
||||||
<shortopt>q</shortopt>
|
|
||||||
<doc>Be quiet</doc>
|
|
||||||
</quiet>
|
|
||||||
<reallyquiet>
|
|
||||||
<shortopt>Q</shortopt>
|
|
||||||
<doc>Be really quiet</doc>
|
|
||||||
</reallyquiet>
|
|
||||||
<slide>
|
|
||||||
<shortopt>F</shortopt>
|
|
||||||
<doc>Move (slide) tag if it exists</doc>
|
|
||||||
</slide>
|
|
||||||
<delete>
|
|
||||||
<shortopt>d</shortopt>
|
|
||||||
<doc>Remove tag</doc>
|
|
||||||
</delete>
|
|
||||||
<dry-run>
|
|
||||||
<shortopt>n</shortopt>
|
|
||||||
<doc>Don't do anything, just pretend</doc>
|
|
||||||
</dry-run>
|
|
||||||
</options>
|
|
||||||
<doc><package.xml> [files...]
|
|
||||||
Sets a CVS tag on all files in a package. Use this command after you have
|
|
||||||
packaged a distribution tarball with the "package" command to tag what
|
|
||||||
revisions of what files were in that release. If need to fix something
|
|
||||||
after running cvstag once, but before the tarball is released to the public,
|
|
||||||
use the "slide" option to move the release tag.
|
|
||||||
|
|
||||||
to include files (such as a second package.xml, or tests not included in the
|
|
||||||
release), pass them as additional parameters.
|
|
||||||
</doc>
|
|
||||||
</cvstag>
|
|
||||||
<package-dependencies>
|
|
||||||
<summary>Show package dependencies</summary>
|
|
||||||
<function>doPackageDependencies</function>
|
|
||||||
<shortcut>pd</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc><package-file> or <package.xml> or <install-package-name>
|
|
||||||
List all dependencies the package has.
|
|
||||||
Can take a tgz / tar file, package.xml or a package name of an installed package.</doc>
|
|
||||||
</package-dependencies>
|
|
||||||
<sign>
|
|
||||||
<summary>Sign a package distribution file</summary>
|
|
||||||
<function>doSign</function>
|
|
||||||
<shortcut>si</shortcut>
|
|
||||||
<options>
|
|
||||||
<verbose>
|
|
||||||
<shortopt>v</shortopt>
|
|
||||||
<doc>Display GnuPG output</doc>
|
|
||||||
</verbose>
|
|
||||||
</options>
|
|
||||||
<doc><package-file>
|
|
||||||
Signs a package distribution (.tar or .tgz) file with GnuPG.</doc>
|
|
||||||
</sign>
|
|
||||||
<makerpm>
|
|
||||||
<summary>Builds an RPM spec file from a PEAR package</summary>
|
|
||||||
<function>doMakeRPM</function>
|
|
||||||
<shortcut>rpm</shortcut>
|
|
||||||
<options>
|
|
||||||
<spec-template>
|
|
||||||
<shortopt>t</shortopt>
|
|
||||||
<doc>Use FILE as RPM spec file template</doc>
|
|
||||||
<arg>FILE</arg>
|
|
||||||
</spec-template>
|
|
||||||
<rpm-pkgname>
|
|
||||||
<shortopt>p</shortopt>
|
|
||||||
<doc>Use FORMAT as format string for RPM package name, %s is replaced
|
|
||||||
by the PEAR package name, defaults to "PEAR::%s".</doc>
|
|
||||||
<arg>FORMAT</arg>
|
|
||||||
</rpm-pkgname>
|
|
||||||
</options>
|
|
||||||
<doc><package-file>
|
|
||||||
|
|
||||||
Creates an RPM .spec file for wrapping a PEAR package inside an RPM
|
|
||||||
package. Intended to be used from the SPECS directory, with the PEAR
|
|
||||||
package tarball in the SOURCES directory:
|
|
||||||
|
|
||||||
$ pear makerpm ../SOURCES/Net_Socket-1.0.tgz
|
|
||||||
Wrote RPM spec file PEAR::Net_Geo-1.0.spec
|
|
||||||
$ rpm -bb PEAR::Net_Socket-1.0.spec
|
|
||||||
...
|
|
||||||
Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
|
|
||||||
</doc>
|
|
||||||
</makerpm>
|
|
||||||
<convert>
|
|
||||||
<summary>Convert a package.xml 1.0 to package.xml 2.0 format</summary>
|
|
||||||
<function>doConvert</function>
|
|
||||||
<shortcut>c2</shortcut>
|
|
||||||
<options>
|
|
||||||
<flat>
|
|
||||||
<shortopt>f</shortopt>
|
|
||||||
<doc>do not beautify the filelist.</doc>
|
|
||||||
</flat>
|
|
||||||
</options>
|
|
||||||
<doc>[descfile] [descfile2]
|
|
||||||
Converts a package.xml in 1.0 format into a package.xml
|
|
||||||
in 2.0 format. The new file will be named package2.xml by default,
|
|
||||||
and package.xml will be used as the old file by default.
|
|
||||||
This is not the most intelligent conversion, and should only be
|
|
||||||
used for automated conversion or learning the format.
|
|
||||||
</doc>
|
|
||||||
</convert>
|
|
||||||
</commands>
|
|
|
@ -1,421 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* PEAR_Command_Pickle (pickle command)
|
|
||||||
*
|
|
||||||
* PHP versions 4 and 5
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 2005-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version CVS: $Id: Pickle.php 313023 2011-07-06 19:17:11Z dufuz $
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since File available since Release 1.4.1
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* base class
|
|
||||||
*/
|
|
||||||
require_once 'PEAR/Command/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR commands for login/logout
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 2005-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version Release: 1.9.4
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since Class available since Release 1.4.1
|
|
||||||
*/
|
|
||||||
|
|
||||||
class PEAR_Command_Pickle extends PEAR_Command_Common
|
|
||||||
{
|
|
||||||
var $commands = array(
|
|
||||||
'pickle' => array(
|
|
||||||
'summary' => 'Build PECL Package',
|
|
||||||
'function' => 'doPackage',
|
|
||||||
'shortcut' => 'pi',
|
|
||||||
'options' => array(
|
|
||||||
'nocompress' => array(
|
|
||||||
'shortopt' => 'Z',
|
|
||||||
'doc' => 'Do not gzip the package file'
|
|
||||||
),
|
|
||||||
'showname' => array(
|
|
||||||
'shortopt' => 'n',
|
|
||||||
'doc' => 'Print the name of the packaged file.',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
'doc' => '[descfile]
|
|
||||||
Creates a PECL package from its package2.xml file.
|
|
||||||
|
|
||||||
An automatic conversion will be made to a package.xml 1.0 and written out to
|
|
||||||
disk in the current directory as "package.xml". Note that
|
|
||||||
only simple package.xml 2.0 will be converted. package.xml 2.0 with:
|
|
||||||
|
|
||||||
- dependency types other than required/optional PECL package/ext/php/pearinstaller
|
|
||||||
- more than one extsrcrelease or zendextsrcrelease
|
|
||||||
- zendextbinrelease, extbinrelease, phprelease, or bundle release type
|
|
||||||
- dependency groups
|
|
||||||
- ignore tags in release filelist
|
|
||||||
- tasks other than replace
|
|
||||||
- custom roles
|
|
||||||
|
|
||||||
will cause pickle to fail, and output an error message. If your package2.xml
|
|
||||||
uses any of these features, you are best off using PEAR_PackageFileManager to
|
|
||||||
generate both package.xml.
|
|
||||||
'
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR_Command_Package constructor.
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function PEAR_Command_Pickle(&$ui, &$config)
|
|
||||||
{
|
|
||||||
parent::PEAR_Command_Common($ui, $config);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For unit-testing ease
|
|
||||||
*
|
|
||||||
* @return PEAR_Packager
|
|
||||||
*/
|
|
||||||
function &getPackager()
|
|
||||||
{
|
|
||||||
if (!class_exists('PEAR_Packager')) {
|
|
||||||
require_once 'PEAR/Packager.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
$a = &new PEAR_Packager;
|
|
||||||
return $a;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For unit-testing ease
|
|
||||||
*
|
|
||||||
* @param PEAR_Config $config
|
|
||||||
* @param bool $debug
|
|
||||||
* @param string|null $tmpdir
|
|
||||||
* @return PEAR_PackageFile
|
|
||||||
*/
|
|
||||||
function &getPackageFile($config, $debug = false)
|
|
||||||
{
|
|
||||||
if (!class_exists('PEAR_Common')) {
|
|
||||||
require_once 'PEAR/Common.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!class_exists('PEAR_PackageFile')) {
|
|
||||||
require_once 'PEAR/PackageFile.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
$a = &new PEAR_PackageFile($config, $debug);
|
|
||||||
$common = new PEAR_Common;
|
|
||||||
$common->ui = $this->ui;
|
|
||||||
$a->setLogger($common);
|
|
||||||
return $a;
|
|
||||||
}
|
|
||||||
|
|
||||||
function doPackage($command, $options, $params)
|
|
||||||
{
|
|
||||||
$this->output = '';
|
|
||||||
$pkginfofile = isset($params[0]) ? $params[0] : 'package2.xml';
|
|
||||||
$packager = &$this->getPackager();
|
|
||||||
if (PEAR::isError($err = $this->_convertPackage($pkginfofile))) {
|
|
||||||
return $err;
|
|
||||||
}
|
|
||||||
|
|
||||||
$compress = empty($options['nocompress']) ? true : false;
|
|
||||||
$result = $packager->package($pkginfofile, $compress, 'package.xml');
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
return $this->raiseError($result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't want output, only the package file name just created
|
|
||||||
if (isset($options['showname'])) {
|
|
||||||
$this->ui->outputData($result, $command);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _convertPackage($packagexml)
|
|
||||||
{
|
|
||||||
$pkg = &$this->getPackageFile($this->config);
|
|
||||||
$pf2 = &$pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL);
|
|
||||||
if (!is_a($pf2, 'PEAR_PackageFile_v2')) {
|
|
||||||
return $this->raiseError('Cannot process "' .
|
|
||||||
$packagexml . '", is not a package.xml 2.0');
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once 'PEAR/PackageFile/v1.php';
|
|
||||||
$pf = new PEAR_PackageFile_v1;
|
|
||||||
$pf->setConfig($this->config);
|
|
||||||
if ($pf2->getPackageType() != 'extsrc' && $pf2->getPackageType() != 'zendextsrc') {
|
|
||||||
return $this->raiseError('Cannot safely convert "' . $packagexml .
|
|
||||||
'", is not an extension source package. Using a PEAR_PackageFileManager-based ' .
|
|
||||||
'script is an option');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_array($pf2->getUsesRole())) {
|
|
||||||
return $this->raiseError('Cannot safely convert "' . $packagexml .
|
|
||||||
'", contains custom roles. Using a PEAR_PackageFileManager-based script or ' .
|
|
||||||
'the convert command is an option');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_array($pf2->getUsesTask())) {
|
|
||||||
return $this->raiseError('Cannot safely convert "' . $packagexml .
|
|
||||||
'", contains custom tasks. Using a PEAR_PackageFileManager-based script or ' .
|
|
||||||
'the convert command is an option');
|
|
||||||
}
|
|
||||||
|
|
||||||
$deps = $pf2->getDependencies();
|
|
||||||
if (isset($deps['group'])) {
|
|
||||||
return $this->raiseError('Cannot safely convert "' . $packagexml .
|
|
||||||
'", contains dependency groups. Using a PEAR_PackageFileManager-based script ' .
|
|
||||||
'or the convert command is an option');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($deps['required']['subpackage']) ||
|
|
||||||
isset($deps['optional']['subpackage'])) {
|
|
||||||
return $this->raiseError('Cannot safely convert "' . $packagexml .
|
|
||||||
'", contains subpackage dependencies. Using a PEAR_PackageFileManager-based '.
|
|
||||||
'script is an option');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($deps['required']['os'])) {
|
|
||||||
return $this->raiseError('Cannot safely convert "' . $packagexml .
|
|
||||||
'", contains os dependencies. Using a PEAR_PackageFileManager-based '.
|
|
||||||
'script is an option');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($deps['required']['arch'])) {
|
|
||||||
return $this->raiseError('Cannot safely convert "' . $packagexml .
|
|
||||||
'", contains arch dependencies. Using a PEAR_PackageFileManager-based '.
|
|
||||||
'script is an option');
|
|
||||||
}
|
|
||||||
|
|
||||||
$pf->setPackage($pf2->getPackage());
|
|
||||||
$pf->setSummary($pf2->getSummary());
|
|
||||||
$pf->setDescription($pf2->getDescription());
|
|
||||||
foreach ($pf2->getMaintainers() as $maintainer) {
|
|
||||||
$pf->addMaintainer($maintainer['role'], $maintainer['handle'],
|
|
||||||
$maintainer['name'], $maintainer['email']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$pf->setVersion($pf2->getVersion());
|
|
||||||
$pf->setDate($pf2->getDate());
|
|
||||||
$pf->setLicense($pf2->getLicense());
|
|
||||||
$pf->setState($pf2->getState());
|
|
||||||
$pf->setNotes($pf2->getNotes());
|
|
||||||
$pf->addPhpDep($deps['required']['php']['min'], 'ge');
|
|
||||||
if (isset($deps['required']['php']['max'])) {
|
|
||||||
$pf->addPhpDep($deps['required']['php']['max'], 'le');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($deps['required']['package'])) {
|
|
||||||
if (!isset($deps['required']['package'][0])) {
|
|
||||||
$deps['required']['package'] = array($deps['required']['package']);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($deps['required']['package'] as $dep) {
|
|
||||||
if (!isset($dep['channel'])) {
|
|
||||||
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
|
|
||||||
' contains uri-based dependency on a package. Using a ' .
|
|
||||||
'PEAR_PackageFileManager-based script is an option');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($dep['channel'] != 'pear.php.net'
|
|
||||||
&& $dep['channel'] != 'pecl.php.net'
|
|
||||||
&& $dep['channel'] != 'doc.php.net') {
|
|
||||||
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
|
|
||||||
' contains dependency on a non-standard channel package. Using a ' .
|
|
||||||
'PEAR_PackageFileManager-based script is an option');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($dep['conflicts'])) {
|
|
||||||
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
|
|
||||||
' contains conflicts dependency. Using a ' .
|
|
||||||
'PEAR_PackageFileManager-based script is an option');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($dep['exclude'])) {
|
|
||||||
$this->ui->outputData('WARNING: exclude tags are ignored in conversion');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($dep['min'])) {
|
|
||||||
$pf->addPackageDep($dep['name'], $dep['min'], 'ge');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($dep['max'])) {
|
|
||||||
$pf->addPackageDep($dep['name'], $dep['max'], 'le');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($deps['required']['extension'])) {
|
|
||||||
if (!isset($deps['required']['extension'][0])) {
|
|
||||||
$deps['required']['extension'] = array($deps['required']['extension']);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($deps['required']['extension'] as $dep) {
|
|
||||||
if (isset($dep['conflicts'])) {
|
|
||||||
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
|
|
||||||
' contains conflicts dependency. Using a ' .
|
|
||||||
'PEAR_PackageFileManager-based script is an option');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($dep['exclude'])) {
|
|
||||||
$this->ui->outputData('WARNING: exclude tags are ignored in conversion');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($dep['min'])) {
|
|
||||||
$pf->addExtensionDep($dep['name'], $dep['min'], 'ge');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($dep['max'])) {
|
|
||||||
$pf->addExtensionDep($dep['name'], $dep['max'], 'le');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($deps['optional']['package'])) {
|
|
||||||
if (!isset($deps['optional']['package'][0])) {
|
|
||||||
$deps['optional']['package'] = array($deps['optional']['package']);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($deps['optional']['package'] as $dep) {
|
|
||||||
if (!isset($dep['channel'])) {
|
|
||||||
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
|
|
||||||
' contains uri-based dependency on a package. Using a ' .
|
|
||||||
'PEAR_PackageFileManager-based script is an option');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($dep['channel'] != 'pear.php.net'
|
|
||||||
&& $dep['channel'] != 'pecl.php.net'
|
|
||||||
&& $dep['channel'] != 'doc.php.net') {
|
|
||||||
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
|
|
||||||
' contains dependency on a non-standard channel package. Using a ' .
|
|
||||||
'PEAR_PackageFileManager-based script is an option');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($dep['exclude'])) {
|
|
||||||
$this->ui->outputData('WARNING: exclude tags are ignored in conversion');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($dep['min'])) {
|
|
||||||
$pf->addPackageDep($dep['name'], $dep['min'], 'ge', 'yes');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($dep['max'])) {
|
|
||||||
$pf->addPackageDep($dep['name'], $dep['max'], 'le', 'yes');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($deps['optional']['extension'])) {
|
|
||||||
if (!isset($deps['optional']['extension'][0])) {
|
|
||||||
$deps['optional']['extension'] = array($deps['optional']['extension']);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($deps['optional']['extension'] as $dep) {
|
|
||||||
if (isset($dep['exclude'])) {
|
|
||||||
$this->ui->outputData('WARNING: exclude tags are ignored in conversion');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($dep['min'])) {
|
|
||||||
$pf->addExtensionDep($dep['name'], $dep['min'], 'ge', 'yes');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($dep['max'])) {
|
|
||||||
$pf->addExtensionDep($dep['name'], $dep['max'], 'le', 'yes');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$contents = $pf2->getContents();
|
|
||||||
$release = $pf2->getReleases();
|
|
||||||
if (isset($releases[0])) {
|
|
||||||
return $this->raiseError('Cannot safely process "' . $packagexml . '" contains '
|
|
||||||
. 'multiple extsrcrelease/zendextsrcrelease tags. Using a PEAR_PackageFileManager-based script ' .
|
|
||||||
'or the convert command is an option');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($configoptions = $pf2->getConfigureOptions()) {
|
|
||||||
foreach ($configoptions as $option) {
|
|
||||||
$default = isset($option['default']) ? $option['default'] : false;
|
|
||||||
$pf->addConfigureOption($option['name'], $option['prompt'], $default);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($release['filelist']['ignore'])) {
|
|
||||||
return $this->raiseError('Cannot safely process "' . $packagexml . '" contains '
|
|
||||||
. 'ignore tags. Using a PEAR_PackageFileManager-based script or the convert' .
|
|
||||||
' command is an option');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($release['filelist']['install']) &&
|
|
||||||
!isset($release['filelist']['install'][0])) {
|
|
||||||
$release['filelist']['install'] = array($release['filelist']['install']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($contents['dir']['attribs']['baseinstalldir'])) {
|
|
||||||
$baseinstalldir = $contents['dir']['attribs']['baseinstalldir'];
|
|
||||||
} else {
|
|
||||||
$baseinstalldir = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($contents['dir']['file'][0])) {
|
|
||||||
$contents['dir']['file'] = array($contents['dir']['file']);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($contents['dir']['file'] as $file) {
|
|
||||||
if ($baseinstalldir && !isset($file['attribs']['baseinstalldir'])) {
|
|
||||||
$file['attribs']['baseinstalldir'] = $baseinstalldir;
|
|
||||||
}
|
|
||||||
|
|
||||||
$processFile = $file;
|
|
||||||
unset($processFile['attribs']);
|
|
||||||
if (count($processFile)) {
|
|
||||||
foreach ($processFile as $name => $task) {
|
|
||||||
if ($name != $pf2->getTasksNs() . ':replace') {
|
|
||||||
return $this->raiseError('Cannot safely process "' . $packagexml .
|
|
||||||
'" contains tasks other than replace. Using a ' .
|
|
||||||
'PEAR_PackageFileManager-based script is an option.');
|
|
||||||
}
|
|
||||||
$file['attribs']['replace'][] = $task;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!in_array($file['attribs']['role'], PEAR_Common::getFileRoles())) {
|
|
||||||
return $this->raiseError('Cannot safely convert "' . $packagexml .
|
|
||||||
'", contains custom roles. Using a PEAR_PackageFileManager-based script ' .
|
|
||||||
'or the convert command is an option');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($release['filelist']['install'])) {
|
|
||||||
foreach ($release['filelist']['install'] as $installas) {
|
|
||||||
if ($installas['attribs']['name'] == $file['attribs']['name']) {
|
|
||||||
$file['attribs']['install-as'] = $installas['attribs']['as'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$pf->addFile('/', $file['attribs']['name'], $file['attribs']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($pf2->getChangeLog()) {
|
|
||||||
$this->ui->outputData('WARNING: changelog is not translated to package.xml ' .
|
|
||||||
'1.0, use PEAR_PackageFileManager-based script if you need changelog-' .
|
|
||||||
'translation for package.xml 1.0');
|
|
||||||
}
|
|
||||||
|
|
||||||
$gen = &$pf->getDefaultGenerator();
|
|
||||||
$gen->toPackageFile('.');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
<commands version="1.0">
|
|
||||||
<pickle>
|
|
||||||
<summary>Build PECL Package</summary>
|
|
||||||
<function>doPackage</function>
|
|
||||||
<shortcut>pi</shortcut>
|
|
||||||
<options>
|
|
||||||
<nocompress>
|
|
||||||
<shortopt>Z</shortopt>
|
|
||||||
<doc>Do not gzip the package file</doc>
|
|
||||||
</nocompress>
|
|
||||||
<showname>
|
|
||||||
<shortopt>n</shortopt>
|
|
||||||
<doc>Print the name of the packaged file.</doc>
|
|
||||||
</showname>
|
|
||||||
</options>
|
|
||||||
<doc>[descfile]
|
|
||||||
Creates a PECL package from its package2.xml file.
|
|
||||||
|
|
||||||
An automatic conversion will be made to a package.xml 1.0 and written out to
|
|
||||||
disk in the current directory as "package.xml". Note that
|
|
||||||
only simple package.xml 2.0 will be converted. package.xml 2.0 with:
|
|
||||||
|
|
||||||
- dependency types other than required/optional PECL package/ext/php/pearinstaller
|
|
||||||
- more than one extsrcrelease or zendextsrcrelease
|
|
||||||
- zendextbinrelease, extbinrelease, phprelease, or bundle release type
|
|
||||||
- dependency groups
|
|
||||||
- ignore tags in release filelist
|
|
||||||
- tasks other than replace
|
|
||||||
- custom roles
|
|
||||||
|
|
||||||
will cause pickle to fail, and output an error message. If your package2.xml
|
|
||||||
uses any of these features, you are best off using PEAR_PackageFileManager to
|
|
||||||
generate both package.xml.
|
|
||||||
</doc>
|
|
||||||
</pickle>
|
|
||||||
</commands>
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,58 +0,0 @@
|
||||||
<commands version="1.0">
|
|
||||||
<list>
|
|
||||||
<summary>List Installed Packages In The Default Channel</summary>
|
|
||||||
<function>doList</function>
|
|
||||||
<shortcut>l</shortcut>
|
|
||||||
<options>
|
|
||||||
<channel>
|
|
||||||
<shortopt>c</shortopt>
|
|
||||||
<doc>list installed packages from this channel</doc>
|
|
||||||
<arg>CHAN</arg>
|
|
||||||
</channel>
|
|
||||||
<allchannels>
|
|
||||||
<shortopt>a</shortopt>
|
|
||||||
<doc>list installed packages from all channels</doc>
|
|
||||||
</allchannels>
|
|
||||||
<channelinfo>
|
|
||||||
<shortopt>i</shortopt>
|
|
||||||
<doc>output fully channel-aware data, even on failure</doc>
|
|
||||||
</channelinfo>
|
|
||||||
</options>
|
|
||||||
<doc><package>
|
|
||||||
If invoked without parameters, this command lists the PEAR packages
|
|
||||||
installed in your php_dir ({config php_dir}). With a parameter, it
|
|
||||||
lists the files in a package.
|
|
||||||
</doc>
|
|
||||||
</list>
|
|
||||||
<list-files>
|
|
||||||
<summary>List Files In Installed Package</summary>
|
|
||||||
<function>doFileList</function>
|
|
||||||
<shortcut>fl</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc><package>
|
|
||||||
List the files in an installed package.
|
|
||||||
</doc>
|
|
||||||
</list-files>
|
|
||||||
<shell-test>
|
|
||||||
<summary>Shell Script Test</summary>
|
|
||||||
<function>doShellTest</function>
|
|
||||||
<shortcut>st</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc><package> [[relation] version]
|
|
||||||
Tests if a package is installed in the system. Will exit(1) if it is not.
|
|
||||||
<relation> The version comparison operator. One of:
|
|
||||||
<, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne
|
|
||||||
<version> The version to compare with
|
|
||||||
</doc>
|
|
||||||
</shell-test>
|
|
||||||
<info>
|
|
||||||
<summary>Display information about a package</summary>
|
|
||||||
<function>doInfo</function>
|
|
||||||
<shortcut>in</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc><package>
|
|
||||||
Displays information about a package. The package argument may be a
|
|
||||||
local package file, an URL to a package file, or the name of an
|
|
||||||
installed package.</doc>
|
|
||||||
</info>
|
|
||||||
</commands>
|
|
|
@ -1,810 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* PEAR_Command_Remote (remote-info, list-upgrades, remote-list, search, list-all, download,
|
|
||||||
* clear-cache commands)
|
|
||||||
*
|
|
||||||
* PHP versions 4 and 5
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version CVS: $Id: Remote.php 313023 2011-07-06 19:17:11Z dufuz $
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since File available since Release 0.1
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* base class
|
|
||||||
*/
|
|
||||||
require_once 'PEAR/Command/Common.php';
|
|
||||||
require_once 'PEAR/REST.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR commands for remote server querying
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version Release: 1.9.4
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since Class available since Release 0.1
|
|
||||||
*/
|
|
||||||
class PEAR_Command_Remote extends PEAR_Command_Common
|
|
||||||
{
|
|
||||||
var $commands = array(
|
|
||||||
'remote-info' => array(
|
|
||||||
'summary' => 'Information About Remote Packages',
|
|
||||||
'function' => 'doRemoteInfo',
|
|
||||||
'shortcut' => 'ri',
|
|
||||||
'options' => array(),
|
|
||||||
'doc' => '<package>
|
|
||||||
Get details on a package from the server.',
|
|
||||||
),
|
|
||||||
'list-upgrades' => array(
|
|
||||||
'summary' => 'List Available Upgrades',
|
|
||||||
'function' => 'doListUpgrades',
|
|
||||||
'shortcut' => 'lu',
|
|
||||||
'options' => array(
|
|
||||||
'channelinfo' => array(
|
|
||||||
'shortopt' => 'i',
|
|
||||||
'doc' => 'output fully channel-aware data, even on failure',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
'doc' => '[preferred_state]
|
|
||||||
List releases on the server of packages you have installed where
|
|
||||||
a newer version is available with the same release state (stable etc.)
|
|
||||||
or the state passed as the second parameter.'
|
|
||||||
),
|
|
||||||
'remote-list' => array(
|
|
||||||
'summary' => 'List Remote Packages',
|
|
||||||
'function' => 'doRemoteList',
|
|
||||||
'shortcut' => 'rl',
|
|
||||||
'options' => array(
|
|
||||||
'channel' =>
|
|
||||||
array(
|
|
||||||
'shortopt' => 'c',
|
|
||||||
'doc' => 'specify a channel other than the default channel',
|
|
||||||
'arg' => 'CHAN',
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'doc' => '
|
|
||||||
Lists the packages available on the configured server along with the
|
|
||||||
latest stable release of each package.',
|
|
||||||
),
|
|
||||||
'search' => array(
|
|
||||||
'summary' => 'Search remote package database',
|
|
||||||
'function' => 'doSearch',
|
|
||||||
'shortcut' => 'sp',
|
|
||||||
'options' => array(
|
|
||||||
'channel' =>
|
|
||||||
array(
|
|
||||||
'shortopt' => 'c',
|
|
||||||
'doc' => 'specify a channel other than the default channel',
|
|
||||||
'arg' => 'CHAN',
|
|
||||||
),
|
|
||||||
'allchannels' => array(
|
|
||||||
'shortopt' => 'a',
|
|
||||||
'doc' => 'search packages from all known channels',
|
|
||||||
),
|
|
||||||
'channelinfo' => array(
|
|
||||||
'shortopt' => 'i',
|
|
||||||
'doc' => 'output fully channel-aware data, even on failure',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
'doc' => '[packagename] [packageinfo]
|
|
||||||
Lists all packages which match the search parameters. The first
|
|
||||||
parameter is a fragment of a packagename. The default channel
|
|
||||||
will be used unless explicitly overridden. The second parameter
|
|
||||||
will be used to match any portion of the summary/description',
|
|
||||||
),
|
|
||||||
'list-all' => array(
|
|
||||||
'summary' => 'List All Packages',
|
|
||||||
'function' => 'doListAll',
|
|
||||||
'shortcut' => 'la',
|
|
||||||
'options' => array(
|
|
||||||
'channel' =>
|
|
||||||
array(
|
|
||||||
'shortopt' => 'c',
|
|
||||||
'doc' => 'specify a channel other than the default channel',
|
|
||||||
'arg' => 'CHAN',
|
|
||||||
),
|
|
||||||
'channelinfo' => array(
|
|
||||||
'shortopt' => 'i',
|
|
||||||
'doc' => 'output fully channel-aware data, even on failure',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
'doc' => '
|
|
||||||
Lists the packages available on the configured server along with the
|
|
||||||
latest stable release of each package.',
|
|
||||||
),
|
|
||||||
'download' => array(
|
|
||||||
'summary' => 'Download Package',
|
|
||||||
'function' => 'doDownload',
|
|
||||||
'shortcut' => 'd',
|
|
||||||
'options' => array(
|
|
||||||
'nocompress' => array(
|
|
||||||
'shortopt' => 'Z',
|
|
||||||
'doc' => 'download an uncompressed (.tar) file',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
'doc' => '<package>...
|
|
||||||
Download package tarballs. The files will be named as suggested by the
|
|
||||||
server, for example if you download the DB package and the latest stable
|
|
||||||
version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.',
|
|
||||||
),
|
|
||||||
'clear-cache' => array(
|
|
||||||
'summary' => 'Clear Web Services Cache',
|
|
||||||
'function' => 'doClearCache',
|
|
||||||
'shortcut' => 'cc',
|
|
||||||
'options' => array(),
|
|
||||||
'doc' => '
|
|
||||||
Clear the REST cache. See also the cache_ttl configuration
|
|
||||||
parameter.
|
|
||||||
',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR_Command_Remote constructor.
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function PEAR_Command_Remote(&$ui, &$config)
|
|
||||||
{
|
|
||||||
parent::PEAR_Command_Common($ui, $config);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _checkChannelForStatus($channel, $chan)
|
|
||||||
{
|
|
||||||
if (PEAR::isError($chan)) {
|
|
||||||
$this->raiseError($chan);
|
|
||||||
}
|
|
||||||
if (!is_a($chan, 'PEAR_ChannelFile')) {
|
|
||||||
return $this->raiseError('Internal corruption error: invalid channel "' .
|
|
||||||
$channel . '"');
|
|
||||||
}
|
|
||||||
$rest = new PEAR_REST($this->config);
|
|
||||||
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
|
|
||||||
$mirror = $this->config->get('preferred_mirror', null,
|
|
||||||
$channel);
|
|
||||||
$a = $rest->downloadHttp('http://' . $channel .
|
|
||||||
'/channel.xml', $chan->lastModified());
|
|
||||||
PEAR::staticPopErrorHandling();
|
|
||||||
if (!PEAR::isError($a) && $a) {
|
|
||||||
$this->ui->outputData('WARNING: channel "' . $channel . '" has ' .
|
|
||||||
'updated its protocols, use "' . PEAR_RUNTYPE . ' channel-update ' . $channel .
|
|
||||||
'" to update');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function doRemoteInfo($command, $options, $params)
|
|
||||||
{
|
|
||||||
if (sizeof($params) != 1) {
|
|
||||||
return $this->raiseError("$command expects one param: the remote package name");
|
|
||||||
}
|
|
||||||
$savechannel = $channel = $this->config->get('default_channel');
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
$package = $params[0];
|
|
||||||
$parsed = $reg->parsePackageName($package, $channel);
|
|
||||||
if (PEAR::isError($parsed)) {
|
|
||||||
return $this->raiseError('Invalid package name "' . $package . '"');
|
|
||||||
}
|
|
||||||
|
|
||||||
$channel = $parsed['channel'];
|
|
||||||
$this->config->set('default_channel', $channel);
|
|
||||||
$chan = $reg->getChannel($channel);
|
|
||||||
if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
|
|
||||||
return $e;
|
|
||||||
}
|
|
||||||
|
|
||||||
$mirror = $this->config->get('preferred_mirror');
|
|
||||||
if ($chan->supportsREST($mirror) && $base = $chan->getBaseURL('REST1.0', $mirror)) {
|
|
||||||
$rest = &$this->config->getREST('1.0', array());
|
|
||||||
$info = $rest->packageInfo($base, $parsed['package'], $channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($info)) {
|
|
||||||
return $this->raiseError('No supported protocol was found');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PEAR::isError($info)) {
|
|
||||||
$this->config->set('default_channel', $savechannel);
|
|
||||||
return $this->raiseError($info);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($info['name'])) {
|
|
||||||
return $this->raiseError('No remote package "' . $package . '" was found');
|
|
||||||
}
|
|
||||||
|
|
||||||
$installed = $reg->packageInfo($info['name'], null, $channel);
|
|
||||||
$info['installed'] = $installed['version'] ? $installed['version'] : '- no -';
|
|
||||||
if (is_array($info['installed'])) {
|
|
||||||
$info['installed'] = $info['installed']['release'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->ui->outputData($info, $command);
|
|
||||||
$this->config->set('default_channel', $savechannel);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function doRemoteList($command, $options, $params)
|
|
||||||
{
|
|
||||||
$savechannel = $channel = $this->config->get('default_channel');
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
if (isset($options['channel'])) {
|
|
||||||
$channel = $options['channel'];
|
|
||||||
if (!$reg->channelExists($channel)) {
|
|
||||||
return $this->raiseError('Channel "' . $channel . '" does not exist');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->config->set('default_channel', $channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
$chan = $reg->getChannel($channel);
|
|
||||||
if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
|
|
||||||
return $e;
|
|
||||||
}
|
|
||||||
|
|
||||||
$list_options = false;
|
|
||||||
if ($this->config->get('preferred_state') == 'stable') {
|
|
||||||
$list_options = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$available = array();
|
|
||||||
if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
|
|
||||||
$base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))
|
|
||||||
) {
|
|
||||||
// use faster list-all if available
|
|
||||||
$rest = &$this->config->getREST('1.1', array());
|
|
||||||
$available = $rest->listAll($base, $list_options, true, false, false, $chan->getName());
|
|
||||||
} elseif ($chan->supportsREST($this->config->get('preferred_mirror')) &&
|
|
||||||
$base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
|
|
||||||
$rest = &$this->config->getREST('1.0', array());
|
|
||||||
$available = $rest->listAll($base, $list_options, true, false, false, $chan->getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PEAR::isError($available)) {
|
|
||||||
$this->config->set('default_channel', $savechannel);
|
|
||||||
return $this->raiseError($available);
|
|
||||||
}
|
|
||||||
|
|
||||||
$i = $j = 0;
|
|
||||||
$data = array(
|
|
||||||
'caption' => 'Channel ' . $channel . ' Available packages:',
|
|
||||||
'border' => true,
|
|
||||||
'headline' => array('Package', 'Version'),
|
|
||||||
'channel' => $channel
|
|
||||||
);
|
|
||||||
|
|
||||||
if (count($available) == 0) {
|
|
||||||
$data = '(no packages available yet)';
|
|
||||||
} else {
|
|
||||||
foreach ($available as $name => $info) {
|
|
||||||
$version = (isset($info['stable']) && $info['stable']) ? $info['stable'] : '-n/a-';
|
|
||||||
$data['data'][] = array($name, $version);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->ui->outputData($data, $command);
|
|
||||||
$this->config->set('default_channel', $savechannel);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function doListAll($command, $options, $params)
|
|
||||||
{
|
|
||||||
$savechannel = $channel = $this->config->get('default_channel');
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
if (isset($options['channel'])) {
|
|
||||||
$channel = $options['channel'];
|
|
||||||
if (!$reg->channelExists($channel)) {
|
|
||||||
return $this->raiseError("Channel \"$channel\" does not exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->config->set('default_channel', $channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
$list_options = false;
|
|
||||||
if ($this->config->get('preferred_state') == 'stable') {
|
|
||||||
$list_options = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$chan = $reg->getChannel($channel);
|
|
||||||
if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
|
|
||||||
return $e;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
|
|
||||||
$base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) {
|
|
||||||
// use faster list-all if available
|
|
||||||
$rest = &$this->config->getREST('1.1', array());
|
|
||||||
$available = $rest->listAll($base, $list_options, false, false, false, $chan->getName());
|
|
||||||
} elseif ($chan->supportsREST($this->config->get('preferred_mirror')) &&
|
|
||||||
$base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
|
|
||||||
$rest = &$this->config->getREST('1.0', array());
|
|
||||||
$available = $rest->listAll($base, $list_options, false, false, false, $chan->getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PEAR::isError($available)) {
|
|
||||||
$this->config->set('default_channel', $savechannel);
|
|
||||||
return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "' . $available->getMessage() . '")');
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = array(
|
|
||||||
'caption' => 'All packages [Channel ' . $channel . ']:',
|
|
||||||
'border' => true,
|
|
||||||
'headline' => array('Package', 'Latest', 'Local'),
|
|
||||||
'channel' => $channel,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isset($options['channelinfo'])) {
|
|
||||||
// add full channelinfo
|
|
||||||
$data['caption'] = 'Channel ' . $channel . ' All packages:';
|
|
||||||
$data['headline'] = array('Channel', 'Package', 'Latest', 'Local',
|
|
||||||
'Description', 'Dependencies');
|
|
||||||
}
|
|
||||||
$local_pkgs = $reg->listPackages($channel);
|
|
||||||
|
|
||||||
foreach ($available as $name => $info) {
|
|
||||||
$installed = $reg->packageInfo($name, null, $channel);
|
|
||||||
if (is_array($installed['version'])) {
|
|
||||||
$installed['version'] = $installed['version']['release'];
|
|
||||||
}
|
|
||||||
$desc = $info['summary'];
|
|
||||||
if (isset($params[$name])) {
|
|
||||||
$desc .= "\n\n".$info['description'];
|
|
||||||
}
|
|
||||||
if (isset($options['mode']))
|
|
||||||
{
|
|
||||||
if ($options['mode'] == 'installed' && !isset($installed['version'])) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($options['mode'] == 'notinstalled' && isset($installed['version'])) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($options['mode'] == 'upgrades'
|
|
||||||
&& (!isset($installed['version']) || version_compare($installed['version'],
|
|
||||||
$info['stable'], '>='))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$pos = array_search(strtolower($name), $local_pkgs);
|
|
||||||
if ($pos !== false) {
|
|
||||||
unset($local_pkgs[$pos]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($info['stable']) && !$info['stable']) {
|
|
||||||
$info['stable'] = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['channelinfo'])) {
|
|
||||||
// add full channelinfo
|
|
||||||
if ($info['stable'] === $info['unstable']) {
|
|
||||||
$state = $info['state'];
|
|
||||||
} else {
|
|
||||||
$state = 'stable';
|
|
||||||
}
|
|
||||||
$latest = $info['stable'].' ('.$state.')';
|
|
||||||
$local = '';
|
|
||||||
if (isset($installed['version'])) {
|
|
||||||
$inst_state = $reg->packageInfo($name, 'release_state', $channel);
|
|
||||||
$local = $installed['version'].' ('.$inst_state.')';
|
|
||||||
}
|
|
||||||
|
|
||||||
$packageinfo = array(
|
|
||||||
$channel,
|
|
||||||
$name,
|
|
||||||
$latest,
|
|
||||||
$local,
|
|
||||||
isset($desc) ? $desc : null,
|
|
||||||
isset($info['deps']) ? $info['deps'] : null,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$packageinfo = array(
|
|
||||||
$reg->channelAlias($channel) . '/' . $name,
|
|
||||||
isset($info['stable']) ? $info['stable'] : null,
|
|
||||||
isset($installed['version']) ? $installed['version'] : null,
|
|
||||||
isset($desc) ? $desc : null,
|
|
||||||
isset($info['deps']) ? $info['deps'] : null,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$data['data'][$info['category']][] = $packageinfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['mode']) && in_array($options['mode'], array('notinstalled', 'upgrades'))) {
|
|
||||||
$this->config->set('default_channel', $savechannel);
|
|
||||||
$this->ui->outputData($data, $command);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($local_pkgs as $name) {
|
|
||||||
$info = &$reg->getPackage($name, $channel);
|
|
||||||
$data['data']['Local'][] = array(
|
|
||||||
$reg->channelAlias($channel) . '/' . $info->getPackage(),
|
|
||||||
'',
|
|
||||||
$info->getVersion(),
|
|
||||||
$info->getSummary(),
|
|
||||||
$info->getDeps()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->config->set('default_channel', $savechannel);
|
|
||||||
$this->ui->outputData($data, $command);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function doSearch($command, $options, $params)
|
|
||||||
{
|
|
||||||
if ((!isset($params[0]) || empty($params[0]))
|
|
||||||
&& (!isset($params[1]) || empty($params[1])))
|
|
||||||
{
|
|
||||||
return $this->raiseError('no valid search string supplied');
|
|
||||||
}
|
|
||||||
|
|
||||||
$channelinfo = isset($options['channelinfo']);
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
if (isset($options['allchannels'])) {
|
|
||||||
// search all channels
|
|
||||||
unset($options['allchannels']);
|
|
||||||
$channels = $reg->getChannels();
|
|
||||||
$errors = array();
|
|
||||||
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
|
|
||||||
foreach ($channels as $channel) {
|
|
||||||
if ($channel->getName() != '__uri') {
|
|
||||||
$options['channel'] = $channel->getName();
|
|
||||||
$ret = $this->doSearch($command, $options, $params);
|
|
||||||
if (PEAR::isError($ret)) {
|
|
||||||
$errors[] = $ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PEAR::staticPopErrorHandling();
|
|
||||||
if (count($errors) !== 0) {
|
|
||||||
// for now, only give first error
|
|
||||||
return PEAR::raiseError($errors[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$savechannel = $channel = $this->config->get('default_channel');
|
|
||||||
$package = strtolower($params[0]);
|
|
||||||
$summary = isset($params[1]) ? $params[1] : false;
|
|
||||||
if (isset($options['channel'])) {
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
$channel = $options['channel'];
|
|
||||||
if (!$reg->channelExists($channel)) {
|
|
||||||
return $this->raiseError('Channel "' . $channel . '" does not exist');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->config->set('default_channel', $channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
$chan = $reg->getChannel($channel);
|
|
||||||
if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
|
|
||||||
return $e;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
|
|
||||||
$base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
|
|
||||||
$rest = &$this->config->getREST('1.0', array());
|
|
||||||
$available = $rest->listAll($base, false, false, $package, $summary, $chan->getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PEAR::isError($available)) {
|
|
||||||
$this->config->set('default_channel', $savechannel);
|
|
||||||
return $this->raiseError($available);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$available && !$channelinfo) {
|
|
||||||
// clean exit when not found, no error !
|
|
||||||
$data = 'no packages found that match pattern "' . $package . '", for channel '.$channel.'.';
|
|
||||||
$this->ui->outputData($data);
|
|
||||||
$this->config->set('default_channel', $channel);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($channelinfo) {
|
|
||||||
$data = array(
|
|
||||||
'caption' => 'Matched packages, channel ' . $channel . ':',
|
|
||||||
'border' => true,
|
|
||||||
'headline' => array('Channel', 'Package', 'Stable/(Latest)', 'Local'),
|
|
||||||
'channel' => $channel
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$data = array(
|
|
||||||
'caption' => 'Matched packages, channel ' . $channel . ':',
|
|
||||||
'border' => true,
|
|
||||||
'headline' => array('Package', 'Stable/(Latest)', 'Local'),
|
|
||||||
'channel' => $channel
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$available && $channelinfo) {
|
|
||||||
unset($data['headline']);
|
|
||||||
$data['data'] = 'No packages found that match pattern "' . $package . '".';
|
|
||||||
$available = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($available as $name => $info) {
|
|
||||||
$installed = $reg->packageInfo($name, null, $channel);
|
|
||||||
$desc = $info['summary'];
|
|
||||||
if (isset($params[$name]))
|
|
||||||
$desc .= "\n\n".$info['description'];
|
|
||||||
|
|
||||||
if (!isset($info['stable']) || !$info['stable']) {
|
|
||||||
$version_remote = 'none';
|
|
||||||
} else {
|
|
||||||
if ($info['unstable']) {
|
|
||||||
$version_remote = $info['unstable'];
|
|
||||||
} else {
|
|
||||||
$version_remote = $info['stable'];
|
|
||||||
}
|
|
||||||
$version_remote .= ' ('.$info['state'].')';
|
|
||||||
}
|
|
||||||
$version = is_array($installed['version']) ? $installed['version']['release'] :
|
|
||||||
$installed['version'];
|
|
||||||
if ($channelinfo) {
|
|
||||||
$packageinfo = array(
|
|
||||||
$channel,
|
|
||||||
$name,
|
|
||||||
$version_remote,
|
|
||||||
$version,
|
|
||||||
$desc,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$packageinfo = array(
|
|
||||||
$name,
|
|
||||||
$version_remote,
|
|
||||||
$version,
|
|
||||||
$desc,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$data['data'][$info['category']][] = $packageinfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->ui->outputData($data, $command);
|
|
||||||
$this->config->set('default_channel', $channel);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function &getDownloader($options)
|
|
||||||
{
|
|
||||||
if (!class_exists('PEAR_Downloader')) {
|
|
||||||
require_once 'PEAR/Downloader.php';
|
|
||||||
}
|
|
||||||
$a = &new PEAR_Downloader($this->ui, $options, $this->config);
|
|
||||||
return $a;
|
|
||||||
}
|
|
||||||
|
|
||||||
function doDownload($command, $options, $params)
|
|
||||||
{
|
|
||||||
// make certain that dependencies are ignored
|
|
||||||
$options['downloadonly'] = 1;
|
|
||||||
|
|
||||||
// eliminate error messages for preferred_state-related errors
|
|
||||||
/* TODO: Should be an option, but until now download does respect
|
|
||||||
prefered state */
|
|
||||||
/* $options['ignorepreferred_state'] = 1; */
|
|
||||||
// eliminate error messages for preferred_state-related errors
|
|
||||||
|
|
||||||
$downloader = &$this->getDownloader($options);
|
|
||||||
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
|
|
||||||
$e = $downloader->setDownloadDir(getcwd());
|
|
||||||
PEAR::staticPopErrorHandling();
|
|
||||||
if (PEAR::isError($e)) {
|
|
||||||
return $this->raiseError('Current directory is not writeable, cannot download');
|
|
||||||
}
|
|
||||||
|
|
||||||
$errors = array();
|
|
||||||
$downloaded = array();
|
|
||||||
$err = $downloader->download($params);
|
|
||||||
if (PEAR::isError($err)) {
|
|
||||||
return $err;
|
|
||||||
}
|
|
||||||
|
|
||||||
$errors = $downloader->getErrorMsgs();
|
|
||||||
if (count($errors)) {
|
|
||||||
foreach ($errors as $error) {
|
|
||||||
if ($error !== null) {
|
|
||||||
$this->ui->outputData($error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->raiseError("$command failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
$downloaded = $downloader->getDownloadedPackages();
|
|
||||||
foreach ($downloaded as $pkg) {
|
|
||||||
$this->ui->outputData("File $pkg[file] downloaded", $command);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function downloadCallback($msg, $params = null)
|
|
||||||
{
|
|
||||||
if ($msg == 'done') {
|
|
||||||
$this->bytes_downloaded = $params;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function doListUpgrades($command, $options, $params)
|
|
||||||
{
|
|
||||||
require_once 'PEAR/Common.php';
|
|
||||||
if (isset($params[0]) && !is_array(PEAR_Common::betterStates($params[0]))) {
|
|
||||||
return $this->raiseError($params[0] . ' is not a valid state (stable/beta/alpha/devel/etc.) try "pear help list-upgrades"');
|
|
||||||
}
|
|
||||||
|
|
||||||
$savechannel = $channel = $this->config->get('default_channel');
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
foreach ($reg->listChannels() as $channel) {
|
|
||||||
$inst = array_flip($reg->listPackages($channel));
|
|
||||||
if (!count($inst)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($channel == '__uri') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->config->set('default_channel', $channel);
|
|
||||||
$state = empty($params[0]) ? $this->config->get('preferred_state') : $params[0];
|
|
||||||
|
|
||||||
$caption = $channel . ' Available Upgrades';
|
|
||||||
$chan = $reg->getChannel($channel);
|
|
||||||
if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
|
|
||||||
return $e;
|
|
||||||
}
|
|
||||||
|
|
||||||
$latest = array();
|
|
||||||
$base2 = false;
|
|
||||||
$preferred_mirror = $this->config->get('preferred_mirror');
|
|
||||||
if ($chan->supportsREST($preferred_mirror) &&
|
|
||||||
(
|
|
||||||
//($base2 = $chan->getBaseURL('REST1.4', $preferred_mirror)) ||
|
|
||||||
($base = $chan->getBaseURL('REST1.0', $preferred_mirror))
|
|
||||||
)
|
|
||||||
|
|
||||||
) {
|
|
||||||
if ($base2) {
|
|
||||||
$rest = &$this->config->getREST('1.4', array());
|
|
||||||
$base = $base2;
|
|
||||||
} else {
|
|
||||||
$rest = &$this->config->getREST('1.0', array());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($state) || $state == 'any') {
|
|
||||||
$state = false;
|
|
||||||
} else {
|
|
||||||
$caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')';
|
|
||||||
}
|
|
||||||
|
|
||||||
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
|
|
||||||
$latest = $rest->listLatestUpgrades($base, $state, $inst, $channel, $reg);
|
|
||||||
PEAR::staticPopErrorHandling();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PEAR::isError($latest)) {
|
|
||||||
$this->ui->outputData($latest->getMessage());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$caption .= ':';
|
|
||||||
if (PEAR::isError($latest)) {
|
|
||||||
$this->config->set('default_channel', $savechannel);
|
|
||||||
return $latest;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = array(
|
|
||||||
'caption' => $caption,
|
|
||||||
'border' => 1,
|
|
||||||
'headline' => array('Channel', 'Package', 'Local', 'Remote', 'Size'),
|
|
||||||
'channel' => $channel
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach ((array)$latest as $pkg => $info) {
|
|
||||||
$package = strtolower($pkg);
|
|
||||||
if (!isset($inst[$package])) {
|
|
||||||
// skip packages we don't have installed
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
extract($info);
|
|
||||||
$inst_version = $reg->packageInfo($package, 'version', $channel);
|
|
||||||
$inst_state = $reg->packageInfo($package, 'release_state', $channel);
|
|
||||||
if (version_compare("$version", "$inst_version", "le")) {
|
|
||||||
// installed version is up-to-date
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($filesize >= 20480) {
|
|
||||||
$filesize += 1024 - ($filesize % 1024);
|
|
||||||
$fs = sprintf("%dkB", $filesize / 1024);
|
|
||||||
} elseif ($filesize > 0) {
|
|
||||||
$filesize += 103 - ($filesize % 103);
|
|
||||||
$fs = sprintf("%.1fkB", $filesize / 1024.0);
|
|
||||||
} else {
|
|
||||||
$fs = " -"; // XXX center instead
|
|
||||||
}
|
|
||||||
|
|
||||||
$data['data'][] = array($channel, $pkg, "$inst_version ($inst_state)", "$version ($state)", $fs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['channelinfo'])) {
|
|
||||||
if (empty($data['data'])) {
|
|
||||||
unset($data['headline']);
|
|
||||||
if (count($inst) == 0) {
|
|
||||||
$data['data'] = '(no packages installed)';
|
|
||||||
} else {
|
|
||||||
$data['data'] = '(no upgrades available)';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->ui->outputData($data, $command);
|
|
||||||
} else {
|
|
||||||
if (empty($data['data'])) {
|
|
||||||
$this->ui->outputData('Channel ' . $channel . ': No upgrades available');
|
|
||||||
} else {
|
|
||||||
$this->ui->outputData($data, $command);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->config->set('default_channel', $savechannel);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function doClearCache($command, $options, $params)
|
|
||||||
{
|
|
||||||
$cache_dir = $this->config->get('cache_dir');
|
|
||||||
$verbose = $this->config->get('verbose');
|
|
||||||
$output = '';
|
|
||||||
if (!file_exists($cache_dir) || !is_dir($cache_dir)) {
|
|
||||||
return $this->raiseError("$cache_dir does not exist or is not a directory");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!($dp = @opendir($cache_dir))) {
|
|
||||||
return $this->raiseError("opendir($cache_dir) failed: $php_errormsg");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($verbose >= 1) {
|
|
||||||
$output .= "reading directory $cache_dir\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$num = 0;
|
|
||||||
while ($ent = readdir($dp)) {
|
|
||||||
if (preg_match('/rest.cache(file|id)\\z/', $ent)) {
|
|
||||||
$path = $cache_dir . DIRECTORY_SEPARATOR . $ent;
|
|
||||||
if (file_exists($path)) {
|
|
||||||
$ok = @unlink($path);
|
|
||||||
} else {
|
|
||||||
$ok = false;
|
|
||||||
$php_errormsg = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($ok) {
|
|
||||||
if ($verbose >= 2) {
|
|
||||||
$output .= "deleted $path\n";
|
|
||||||
}
|
|
||||||
$num++;
|
|
||||||
} elseif ($verbose >= 1) {
|
|
||||||
$output .= "failed to delete $path $php_errormsg\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir($dp);
|
|
||||||
if ($verbose >= 1) {
|
|
||||||
$output .= "$num cache entries cleared\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->ui->outputData(rtrim($output), $command);
|
|
||||||
return $num;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,109 +0,0 @@
|
||||||
<commands version="1.0">
|
|
||||||
<remote-info>
|
|
||||||
<summary>Information About Remote Packages</summary>
|
|
||||||
<function>doRemoteInfo</function>
|
|
||||||
<shortcut>ri</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc><package>
|
|
||||||
Get details on a package from the server.</doc>
|
|
||||||
</remote-info>
|
|
||||||
<list-upgrades>
|
|
||||||
<summary>List Available Upgrades</summary>
|
|
||||||
<function>doListUpgrades</function>
|
|
||||||
<shortcut>lu</shortcut>
|
|
||||||
<options>
|
|
||||||
<channelinfo>
|
|
||||||
<shortopt>i</shortopt>
|
|
||||||
<doc>output fully channel-aware data, even on failure</doc>
|
|
||||||
</channelinfo>
|
|
||||||
</options>
|
|
||||||
<doc>[preferred_state]
|
|
||||||
List releases on the server of packages you have installed where
|
|
||||||
a newer version is available with the same release state (stable etc.)
|
|
||||||
or the state passed as the second parameter.</doc>
|
|
||||||
</list-upgrades>
|
|
||||||
<remote-list>
|
|
||||||
<summary>List Remote Packages</summary>
|
|
||||||
<function>doRemoteList</function>
|
|
||||||
<shortcut>rl</shortcut>
|
|
||||||
<options>
|
|
||||||
<channel>
|
|
||||||
<shortopt>c</shortopt>
|
|
||||||
<doc>specify a channel other than the default channel</doc>
|
|
||||||
<arg>CHAN</arg>
|
|
||||||
</channel>
|
|
||||||
</options>
|
|
||||||
<doc>
|
|
||||||
Lists the packages available on the configured server along with the
|
|
||||||
latest stable release of each package.</doc>
|
|
||||||
</remote-list>
|
|
||||||
<search>
|
|
||||||
<summary>Search remote package database</summary>
|
|
||||||
<function>doSearch</function>
|
|
||||||
<shortcut>sp</shortcut>
|
|
||||||
<options>
|
|
||||||
<channel>
|
|
||||||
<shortopt>c</shortopt>
|
|
||||||
<doc>specify a channel other than the default channel</doc>
|
|
||||||
<arg>CHAN</arg>
|
|
||||||
</channel>
|
|
||||||
<allchannels>
|
|
||||||
<shortopt>a</shortopt>
|
|
||||||
<doc>search packages from all known channels</doc>
|
|
||||||
</allchannels>
|
|
||||||
<channelinfo>
|
|
||||||
<shortopt>i</shortopt>
|
|
||||||
<doc>output fully channel-aware data, even on failure</doc>
|
|
||||||
</channelinfo>
|
|
||||||
</options>
|
|
||||||
<doc>[packagename] [packageinfo]
|
|
||||||
Lists all packages which match the search parameters. The first
|
|
||||||
parameter is a fragment of a packagename. The default channel
|
|
||||||
will be used unless explicitly overridden. The second parameter
|
|
||||||
will be used to match any portion of the summary/description</doc>
|
|
||||||
</search>
|
|
||||||
<list-all>
|
|
||||||
<summary>List All Packages</summary>
|
|
||||||
<function>doListAll</function>
|
|
||||||
<shortcut>la</shortcut>
|
|
||||||
<options>
|
|
||||||
<channel>
|
|
||||||
<shortopt>c</shortopt>
|
|
||||||
<doc>specify a channel other than the default channel</doc>
|
|
||||||
<arg>CHAN</arg>
|
|
||||||
</channel>
|
|
||||||
<channelinfo>
|
|
||||||
<shortopt>i</shortopt>
|
|
||||||
<doc>output fully channel-aware data, even on failure</doc>
|
|
||||||
</channelinfo>
|
|
||||||
</options>
|
|
||||||
<doc>
|
|
||||||
Lists the packages available on the configured server along with the
|
|
||||||
latest stable release of each package.</doc>
|
|
||||||
</list-all>
|
|
||||||
<download>
|
|
||||||
<summary>Download Package</summary>
|
|
||||||
<function>doDownload</function>
|
|
||||||
<shortcut>d</shortcut>
|
|
||||||
<options>
|
|
||||||
<nocompress>
|
|
||||||
<shortopt>Z</shortopt>
|
|
||||||
<doc>download an uncompressed (.tar) file</doc>
|
|
||||||
</nocompress>
|
|
||||||
</options>
|
|
||||||
<doc><package>...
|
|
||||||
Download package tarballs. The files will be named as suggested by the
|
|
||||||
server, for example if you download the DB package and the latest stable
|
|
||||||
version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.</doc>
|
|
||||||
</download>
|
|
||||||
<clear-cache>
|
|
||||||
<summary>Clear Web Services Cache</summary>
|
|
||||||
<function>doClearCache</function>
|
|
||||||
<shortcut>cc</shortcut>
|
|
||||||
<options />
|
|
||||||
<doc>
|
|
||||||
Clear the XML-RPC/REST cache. See also the cache_ttl configuration
|
|
||||||
parameter.
|
|
||||||
</doc>
|
|
||||||
</clear-cache>
|
|
||||||
</commands>
|
|
|
@ -1,337 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* PEAR_Command_Test (run-tests)
|
|
||||||
*
|
|
||||||
* PHP versions 4 and 5
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Martin Jansen <mj@php.net>
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version CVS: $Id: Test.php 313023 2011-07-06 19:17:11Z dufuz $
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since File available since Release 0.1
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* base class
|
|
||||||
*/
|
|
||||||
require_once 'PEAR/Command/Common.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR commands for login/logout
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Martin Jansen <mj@php.net>
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version Release: 1.9.4
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since Class available since Release 0.1
|
|
||||||
*/
|
|
||||||
|
|
||||||
class PEAR_Command_Test extends PEAR_Command_Common
|
|
||||||
{
|
|
||||||
var $commands = array(
|
|
||||||
'run-tests' => array(
|
|
||||||
'summary' => 'Run Regression Tests',
|
|
||||||
'function' => 'doRunTests',
|
|
||||||
'shortcut' => 'rt',
|
|
||||||
'options' => array(
|
|
||||||
'recur' => array(
|
|
||||||
'shortopt' => 'r',
|
|
||||||
'doc' => 'Run tests in child directories, recursively. 4 dirs deep maximum',
|
|
||||||
),
|
|
||||||
'ini' => array(
|
|
||||||
'shortopt' => 'i',
|
|
||||||
'doc' => 'actual string of settings to pass to php in format " -d setting=blah"',
|
|
||||||
'arg' => 'SETTINGS'
|
|
||||||
),
|
|
||||||
'realtimelog' => array(
|
|
||||||
'shortopt' => 'l',
|
|
||||||
'doc' => 'Log test runs/results as they are run',
|
|
||||||
),
|
|
||||||
'quiet' => array(
|
|
||||||
'shortopt' => 'q',
|
|
||||||
'doc' => 'Only display detail for failed tests',
|
|
||||||
),
|
|
||||||
'simple' => array(
|
|
||||||
'shortopt' => 's',
|
|
||||||
'doc' => 'Display simple output for all tests',
|
|
||||||
),
|
|
||||||
'package' => array(
|
|
||||||
'shortopt' => 'p',
|
|
||||||
'doc' => 'Treat parameters as installed packages from which to run tests',
|
|
||||||
),
|
|
||||||
'phpunit' => array(
|
|
||||||
'shortopt' => 'u',
|
|
||||||
'doc' => 'Search parameters for AllTests.php, and use that to run phpunit-based tests
|
|
||||||
If none is found, all .phpt tests will be tried instead.',
|
|
||||||
),
|
|
||||||
'tapoutput' => array(
|
|
||||||
'shortopt' => 't',
|
|
||||||
'doc' => 'Output run-tests.log in TAP-compliant format',
|
|
||||||
),
|
|
||||||
'cgi' => array(
|
|
||||||
'shortopt' => 'c',
|
|
||||||
'doc' => 'CGI php executable (needed for tests with POST/GET section)',
|
|
||||||
'arg' => 'PHPCGI',
|
|
||||||
),
|
|
||||||
'coverage' => array(
|
|
||||||
'shortopt' => 'x',
|
|
||||||
'doc' => 'Generate a code coverage report (requires Xdebug 2.0.0+)',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
'doc' => '[testfile|dir ...]
|
|
||||||
Run regression tests with PHP\'s regression testing script (run-tests.php).',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
var $output;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR_Command_Test constructor.
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function PEAR_Command_Test(&$ui, &$config)
|
|
||||||
{
|
|
||||||
parent::PEAR_Command_Common($ui, $config);
|
|
||||||
}
|
|
||||||
|
|
||||||
function doRunTests($command, $options, $params)
|
|
||||||
{
|
|
||||||
if (isset($options['phpunit']) && isset($options['tapoutput'])) {
|
|
||||||
return $this->raiseError('ERROR: cannot use both --phpunit and --tapoutput at the same time');
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once 'PEAR/Common.php';
|
|
||||||
require_once 'System.php';
|
|
||||||
$log = new PEAR_Common;
|
|
||||||
$log->ui = &$this->ui; // slightly hacky, but it will work
|
|
||||||
$tests = array();
|
|
||||||
$depth = isset($options['recur']) ? 14 : 1;
|
|
||||||
|
|
||||||
if (!count($params)) {
|
|
||||||
$params[] = '.';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['package'])) {
|
|
||||||
$oldparams = $params;
|
|
||||||
$params = array();
|
|
||||||
$reg = &$this->config->getRegistry();
|
|
||||||
foreach ($oldparams as $param) {
|
|
||||||
$pname = $reg->parsePackageName($param, $this->config->get('default_channel'));
|
|
||||||
if (PEAR::isError($pname)) {
|
|
||||||
return $this->raiseError($pname);
|
|
||||||
}
|
|
||||||
|
|
||||||
$package = &$reg->getPackage($pname['package'], $pname['channel']);
|
|
||||||
if (!$package) {
|
|
||||||
return PEAR::raiseError('Unknown package "' .
|
|
||||||
$reg->parsedPackageNameToString($pname) . '"');
|
|
||||||
}
|
|
||||||
|
|
||||||
$filelist = $package->getFilelist();
|
|
||||||
foreach ($filelist as $name => $atts) {
|
|
||||||
if (isset($atts['role']) && $atts['role'] != 'test') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['phpunit']) && preg_match('/AllTests\.php\\z/i', $name)) {
|
|
||||||
$params[] = $atts['installed_as'];
|
|
||||||
continue;
|
|
||||||
} elseif (!preg_match('/\.phpt\\z/', $name)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$params[] = $atts['installed_as'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($params as $p) {
|
|
||||||
if (is_dir($p)) {
|
|
||||||
if (isset($options['phpunit'])) {
|
|
||||||
$dir = System::find(array($p, '-type', 'f',
|
|
||||||
'-maxdepth', $depth,
|
|
||||||
'-name', 'AllTests.php'));
|
|
||||||
if (count($dir)) {
|
|
||||||
foreach ($dir as $p) {
|
|
||||||
$p = realpath($p);
|
|
||||||
if (!count($tests) ||
|
|
||||||
(count($tests) && strlen($p) < strlen($tests[0]))) {
|
|
||||||
// this is in a higher-level directory, use this one instead.
|
|
||||||
$tests = array($p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$args = array($p, '-type', 'f', '-name', '*.phpt');
|
|
||||||
} else {
|
|
||||||
if (isset($options['phpunit'])) {
|
|
||||||
if (preg_match('/AllTests\.php\\z/i', $p)) {
|
|
||||||
$p = realpath($p);
|
|
||||||
if (!count($tests) ||
|
|
||||||
(count($tests) && strlen($p) < strlen($tests[0]))) {
|
|
||||||
// this is in a higher-level directory, use this one instead.
|
|
||||||
$tests = array($p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file_exists($p) && preg_match('/\.phpt$/', $p)) {
|
|
||||||
$tests[] = $p;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!preg_match('/\.phpt\\z/', $p)) {
|
|
||||||
$p .= '.phpt';
|
|
||||||
}
|
|
||||||
|
|
||||||
$args = array(dirname($p), '-type', 'f', '-name', $p);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($options['recur'])) {
|
|
||||||
$args[] = '-maxdepth';
|
|
||||||
$args[] = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
$dir = System::find($args);
|
|
||||||
$tests = array_merge($tests, $dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
$ini_settings = '';
|
|
||||||
if (isset($options['ini'])) {
|
|
||||||
$ini_settings .= $options['ini'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($_ENV['TEST_PHP_INCLUDE_PATH'])) {
|
|
||||||
$ini_settings .= " -d include_path={$_ENV['TEST_PHP_INCLUDE_PATH']}";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($ini_settings) {
|
|
||||||
$this->ui->outputData('Using INI settings: "' . $ini_settings . '"');
|
|
||||||
}
|
|
||||||
|
|
||||||
$skipped = $passed = $failed = array();
|
|
||||||
$tests_count = count($tests);
|
|
||||||
$this->ui->outputData('Running ' . $tests_count . ' tests', $command);
|
|
||||||
$start = time();
|
|
||||||
if (isset($options['realtimelog']) && file_exists('run-tests.log')) {
|
|
||||||
unlink('run-tests.log');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['tapoutput'])) {
|
|
||||||
$tap = '1..' . $tests_count . "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once 'PEAR/RunTest.php';
|
|
||||||
$run = new PEAR_RunTest($log, $options);
|
|
||||||
$run->tests_count = $tests_count;
|
|
||||||
|
|
||||||
if (isset($options['coverage']) && extension_loaded('xdebug')){
|
|
||||||
$run->xdebug_loaded = true;
|
|
||||||
} else {
|
|
||||||
$run->xdebug_loaded = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$j = $i = 1;
|
|
||||||
foreach ($tests as $t) {
|
|
||||||
if (isset($options['realtimelog'])) {
|
|
||||||
$fp = @fopen('run-tests.log', 'a');
|
|
||||||
if ($fp) {
|
|
||||||
fwrite($fp, "Running test [$i / $tests_count] $t...");
|
|
||||||
fclose($fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
|
|
||||||
if (isset($options['phpunit'])) {
|
|
||||||
$result = $run->runPHPUnit($t, $ini_settings);
|
|
||||||
} else {
|
|
||||||
$result = $run->run($t, $ini_settings, $j);
|
|
||||||
}
|
|
||||||
PEAR::staticPopErrorHandling();
|
|
||||||
if (PEAR::isError($result)) {
|
|
||||||
$this->ui->log($result->getMessage());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['tapoutput'])) {
|
|
||||||
$tap .= $result[0] . ' ' . $i . $result[1] . "\n";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['realtimelog'])) {
|
|
||||||
$fp = @fopen('run-tests.log', 'a');
|
|
||||||
if ($fp) {
|
|
||||||
fwrite($fp, "$result\n");
|
|
||||||
fclose($fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($result == 'FAILED') {
|
|
||||||
$failed[] = $t;
|
|
||||||
}
|
|
||||||
if ($result == 'PASSED') {
|
|
||||||
$passed[] = $t;
|
|
||||||
}
|
|
||||||
if ($result == 'SKIPPED') {
|
|
||||||
$skipped[] = $t;
|
|
||||||
}
|
|
||||||
|
|
||||||
$j++;
|
|
||||||
}
|
|
||||||
|
|
||||||
$total = date('i:s', time() - $start);
|
|
||||||
if (isset($options['tapoutput'])) {
|
|
||||||
$fp = @fopen('run-tests.log', 'w');
|
|
||||||
if ($fp) {
|
|
||||||
fwrite($fp, $tap, strlen($tap));
|
|
||||||
fclose($fp);
|
|
||||||
$this->ui->outputData('wrote TAP-format log to "' .realpath('run-tests.log') .
|
|
||||||
'"', $command);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (count($failed)) {
|
|
||||||
$output = "TOTAL TIME: $total\n";
|
|
||||||
$output .= count($passed) . " PASSED TESTS\n";
|
|
||||||
$output .= count($skipped) . " SKIPPED TESTS\n";
|
|
||||||
$output .= count($failed) . " FAILED TESTS:\n";
|
|
||||||
foreach ($failed as $failure) {
|
|
||||||
$output .= $failure . "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$mode = isset($options['realtimelog']) ? 'a' : 'w';
|
|
||||||
$fp = @fopen('run-tests.log', $mode);
|
|
||||||
|
|
||||||
if ($fp) {
|
|
||||||
fwrite($fp, $output, strlen($output));
|
|
||||||
fclose($fp);
|
|
||||||
$this->ui->outputData('wrote log to "' . realpath('run-tests.log') . '"', $command);
|
|
||||||
}
|
|
||||||
} elseif (file_exists('run-tests.log') && !is_dir('run-tests.log')) {
|
|
||||||
@unlink('run-tests.log');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->ui->outputData('TOTAL TIME: ' . $total);
|
|
||||||
$this->ui->outputData(count($passed) . ' PASSED TESTS', $command);
|
|
||||||
$this->ui->outputData(count($skipped) . ' SKIPPED TESTS', $command);
|
|
||||||
if (count($failed)) {
|
|
||||||
$this->ui->outputData(count($failed) . ' FAILED TESTS:', $command);
|
|
||||||
foreach ($failed as $failure) {
|
|
||||||
$this->ui->outputData($failure, $command);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
<commands version="1.0">
|
|
||||||
<run-tests>
|
|
||||||
<summary>Run Regression Tests</summary>
|
|
||||||
<function>doRunTests</function>
|
|
||||||
<shortcut>rt</shortcut>
|
|
||||||
<options>
|
|
||||||
<recur>
|
|
||||||
<shortopt>r</shortopt>
|
|
||||||
<doc>Run tests in child directories, recursively. 4 dirs deep maximum</doc>
|
|
||||||
</recur>
|
|
||||||
<ini>
|
|
||||||
<shortopt>i</shortopt>
|
|
||||||
<doc>actual string of settings to pass to php in format " -d setting=blah"</doc>
|
|
||||||
<arg>SETTINGS</arg>
|
|
||||||
</ini>
|
|
||||||
<realtimelog>
|
|
||||||
<shortopt>l</shortopt>
|
|
||||||
<doc>Log test runs/results as they are run</doc>
|
|
||||||
</realtimelog>
|
|
||||||
<quiet>
|
|
||||||
<shortopt>q</shortopt>
|
|
||||||
<doc>Only display detail for failed tests</doc>
|
|
||||||
</quiet>
|
|
||||||
<simple>
|
|
||||||
<shortopt>s</shortopt>
|
|
||||||
<doc>Display simple output for all tests</doc>
|
|
||||||
</simple>
|
|
||||||
<package>
|
|
||||||
<shortopt>p</shortopt>
|
|
||||||
<doc>Treat parameters as installed packages from which to run tests</doc>
|
|
||||||
</package>
|
|
||||||
<phpunit>
|
|
||||||
<shortopt>u</shortopt>
|
|
||||||
<doc>Search parameters for AllTests.php, and use that to run phpunit-based tests
|
|
||||||
If none is found, all .phpt tests will be tried instead.</doc>
|
|
||||||
</phpunit>
|
|
||||||
<tapoutput>
|
|
||||||
<shortopt>t</shortopt>
|
|
||||||
<doc>Output run-tests.log in TAP-compliant format</doc>
|
|
||||||
</tapoutput>
|
|
||||||
<cgi>
|
|
||||||
<shortopt>c</shortopt>
|
|
||||||
<doc>CGI php executable (needed for tests with POST/GET section)</doc>
|
|
||||||
<arg>PHPCGI</arg>
|
|
||||||
</cgi>
|
|
||||||
<coverage>
|
|
||||||
<shortopt>x</shortopt>
|
|
||||||
<doc>Generate a code coverage report (requires Xdebug 2.0.0+)</doc>
|
|
||||||
</coverage>
|
|
||||||
</options>
|
|
||||||
<doc>[testfile|dir ...]
|
|
||||||
Run regression tests with PHP's regression testing script (run-tests.php).</doc>
|
|
||||||
</run-tests>
|
|
||||||
</commands>
|
|
|
@ -1,837 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* PEAR_Common, the base class for the PEAR Installer
|
|
||||||
*
|
|
||||||
* PHP versions 4 and 5
|
|
||||||
*
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Tomas V. V. Cox <cox@idecnet.com>
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version CVS: $Id: Common.php 313023 2011-07-06 19:17:11Z dufuz $
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since File available since Release 0.1.0
|
|
||||||
* @deprecated File deprecated since Release 1.4.0a1
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Include error handling
|
|
||||||
*/
|
|
||||||
require_once 'PEAR.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR_Common error when an invalid PHP file is passed to PEAR_Common::analyzeSourceCode()
|
|
||||||
*/
|
|
||||||
define('PEAR_COMMON_ERROR_INVALIDPHP', 1);
|
|
||||||
define('_PEAR_COMMON_PACKAGE_NAME_PREG', '[A-Za-z][a-zA-Z0-9_]+');
|
|
||||||
define('PEAR_COMMON_PACKAGE_NAME_PREG', '/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/');
|
|
||||||
|
|
||||||
// this should allow: 1, 1.0, 1.0RC1, 1.0dev, 1.0dev123234234234, 1.0a1, 1.0b1, 1.0pl1
|
|
||||||
define('_PEAR_COMMON_PACKAGE_VERSION_PREG', '\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?');
|
|
||||||
define('PEAR_COMMON_PACKAGE_VERSION_PREG', '/^' . _PEAR_COMMON_PACKAGE_VERSION_PREG . '\\z/i');
|
|
||||||
|
|
||||||
// XXX far from perfect :-)
|
|
||||||
define('_PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '(' . _PEAR_COMMON_PACKAGE_NAME_PREG .
|
|
||||||
')(-([.0-9a-zA-Z]+))?');
|
|
||||||
define('PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_PACKAGE_DOWNLOAD_PREG .
|
|
||||||
'\\z/');
|
|
||||||
|
|
||||||
define('_PEAR_CHANNELS_NAME_PREG', '[A-Za-z][a-zA-Z0-9\.]+');
|
|
||||||
define('PEAR_CHANNELS_NAME_PREG', '/^' . _PEAR_CHANNELS_NAME_PREG . '\\z/');
|
|
||||||
|
|
||||||
// this should allow any dns or IP address, plus a path - NO UNDERSCORES ALLOWED
|
|
||||||
define('_PEAR_CHANNELS_SERVER_PREG', '[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*(\/[a-zA-Z0-9\-]+)*');
|
|
||||||
define('PEAR_CHANNELS_SERVER_PREG', '/^' . _PEAR_CHANNELS_SERVER_PREG . '\\z/i');
|
|
||||||
|
|
||||||
define('_PEAR_CHANNELS_PACKAGE_PREG', '(' ._PEAR_CHANNELS_SERVER_PREG . ')\/('
|
|
||||||
. _PEAR_COMMON_PACKAGE_NAME_PREG . ')');
|
|
||||||
define('PEAR_CHANNELS_PACKAGE_PREG', '/^' . _PEAR_CHANNELS_PACKAGE_PREG . '\\z/i');
|
|
||||||
|
|
||||||
define('_PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '(' . _PEAR_CHANNELS_NAME_PREG . ')::('
|
|
||||||
. _PEAR_COMMON_PACKAGE_NAME_PREG . ')(-([.0-9a-zA-Z]+))?');
|
|
||||||
define('PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_CHANNEL_DOWNLOAD_PREG . '\\z/');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of temporary files and directories registered by
|
|
||||||
* PEAR_Common::addTempFile().
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
$GLOBALS['_PEAR_Common_tempfiles'] = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Valid maintainer roles
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
$GLOBALS['_PEAR_Common_maintainer_roles'] = array('lead','developer','contributor','helper');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Valid release states
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
$GLOBALS['_PEAR_Common_release_states'] = array('alpha','beta','stable','snapshot','devel');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Valid dependency types
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
$GLOBALS['_PEAR_Common_dependency_types'] = array('pkg','ext','php','prog','ldlib','rtlib','os','websrv','sapi');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Valid dependency relations
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
$GLOBALS['_PEAR_Common_dependency_relations'] = array('has','eq','lt','le','gt','ge','not', 'ne');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Valid file roles
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
$GLOBALS['_PEAR_Common_file_roles'] = array('php','ext','test','doc','data','src','script');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Valid replacement types
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
$GLOBALS['_PEAR_Common_replacement_types'] = array('php-const', 'pear-config', 'package-info');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Valid "provide" types
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
$GLOBALS['_PEAR_Common_provide_types'] = array('ext', 'prog', 'class', 'function', 'feature', 'api');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Valid "provide" types
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
$GLOBALS['_PEAR_Common_script_phases'] = array('pre-install', 'post-install', 'pre-uninstall', 'post-uninstall', 'pre-build', 'post-build', 'pre-configure', 'post-configure', 'pre-setup', 'post-setup');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class providing common functionality for PEAR administration classes.
|
|
||||||
* @category pear
|
|
||||||
* @package PEAR
|
|
||||||
* @author Stig Bakken <ssb@php.net>
|
|
||||||
* @author Tomas V. V. Cox <cox@idecnet.com>
|
|
||||||
* @author Greg Beaver <cellog@php.net>
|
|
||||||
* @copyright 1997-2009 The Authors
|
|
||||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
|
||||||
* @version Release: 1.9.4
|
|
||||||
* @link http://pear.php.net/package/PEAR
|
|
||||||
* @since Class available since Release 1.4.0a1
|
|
||||||
* @deprecated This class will disappear, and its components will be spread
|
|
||||||
* into smaller classes, like the AT&T breakup, as of Release 1.4.0a1
|
|
||||||
*/
|
|
||||||
class PEAR_Common extends PEAR
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* User Interface object (PEAR_Frontend_* class). If null,
|
|
||||||
* the log() method uses print.
|
|
||||||
* @var object
|
|
||||||
*/
|
|
||||||
var $ui = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration object (PEAR_Config).
|
|
||||||
* @var PEAR_Config
|
|
||||||
*/
|
|
||||||
var $config = null;
|
|
||||||
|
|
||||||
/** stack of elements, gives some sort of XML context */
|
|
||||||
var $element_stack = array();
|
|
||||||
|
|
||||||
/** name of currently parsed XML element */
|
|
||||||
var $current_element;
|
|
||||||
|
|
||||||
/** array of attributes of the currently parsed XML element */
|
|
||||||
var $current_attributes = array();
|
|
||||||
|
|
||||||
/** assoc with information about a package */
|
|
||||||
var $pkginfo = array();
|
|
||||||
|
|
||||||
var $current_path = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flag variable used to mark a valid package file
|
|
||||||
* @var boolean
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
var $_validPackageFile;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR_Common constructor
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function PEAR_Common()
|
|
||||||
{
|
|
||||||
parent::PEAR();
|
|
||||||
$this->config = PEAR_Config::singleton();
|
|
||||||
$this->debug = $this->config->get('verbose');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PEAR_Common destructor
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
function _PEAR_Common()
|
|
||||||
{
|
|
||||||
// doesn't work due to bug #14744
|
|
||||||
//$tempfiles = $this->_tempfiles;
|
|
||||||
$tempfiles =& $GLOBALS['_PEAR_Common_tempfiles'];
|
|
||||||
while ($file = array_shift($tempfiles)) {
|
|
||||||
if (@is_dir($file)) {
|
|
||||||
if (!class_exists('System')) {
|
|
||||||
require_once 'System.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
System::rm(array('-rf', $file));
|
|
||||||
} elseif (file_exists($file)) {
|
|
||||||
unlink($file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a temporary file or directory. When the destructor is
|
|
||||||
* executed, all registered temporary files and directories are
|
|
||||||
* removed.
|
|
||||||
*
|
|
||||||
* @param string $file name of file or directory
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function addTempFile($file)
|
|
||||||
{
|
|
||||||
if (!class_exists('PEAR_Frontend')) {
|
|
||||||
require_once 'PEAR/Frontend.php';
|
|
||||||
}
|
|
||||||
PEAR_Frontend::addTempFile($file);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper to System::mkDir(), creates a directory as well as
|
|
||||||
* any necessary parent directories.
|
|
||||||
*
|
|
||||||
* @param string $dir directory name
|
|
||||||
*
|
|
||||||
* @return bool TRUE on success, or a PEAR error
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function mkDirHier($dir)
|
|
||||||
{
|
|
||||||
// Only used in Installer - move it there ?
|
|
||||||
$this->log(2, "+ create dir $dir");
|
|
||||||
if (!class_exists('System')) {
|
|
||||||
require_once 'System.php';
|
|
||||||
}
|
|
||||||
return System::mkDir(array('-p', $dir));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logging method.
|
|
||||||
*
|
|
||||||
* @param int $level log level (0 is quiet, higher is noisier)
|
|
||||||
* @param string $msg message to write to the log
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function log($level, $msg, $append_crlf = true)
|
|
||||||
{
|
|
||||||
if ($this->debug >= $level) {
|
|
||||||
if (!class_exists('PEAR_Frontend')) {
|
|
||||||
require_once 'PEAR/Frontend.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
$ui = &PEAR_Frontend::singleton();
|
|
||||||
if (is_a($ui, 'PEAR_Frontend')) {
|
|
||||||
$ui->log($msg, $append_crlf);
|
|
||||||
} else {
|
|
||||||
print "$msg\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create and register a temporary directory.
|
|
||||||
*
|
|
||||||
* @param string $tmpdir (optional) Directory to use as tmpdir.
|
|
||||||
* Will use system defaults (for example
|
|
||||||
* /tmp or c:\windows\temp) if not specified
|
|
||||||
*
|
|
||||||
* @return string name of created directory
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function mkTempDir($tmpdir = '')
|
|
||||||
{
|
|
||||||
$topt = $tmpdir ? array('-t', $tmpdir) : array();
|
|
||||||
$topt = array_merge($topt, array('-d', 'pear'));
|
|
||||||
if (!class_exists('System')) {
|
|
||||||
require_once 'System.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$tmpdir = System::mktemp($topt)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->addTempFile($tmpdir);
|
|
||||||
return $tmpdir;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set object that represents the frontend to be used.
|
|
||||||
*
|
|
||||||
* @param object Reference of the frontend object
|
|
||||||
* @return void
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function setFrontendObject(&$ui)
|
|
||||||
{
|
|
||||||
$this->ui = &$ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an array containing all of the states that are more stable than
|
|
||||||
* or equal to the passed in state
|
|
||||||
*
|
|
||||||
* @param string Release state
|
|
||||||
* @param boolean Determines whether to include $state in the list
|
|
||||||
* @return false|array False if $state is not a valid release state
|
|
||||||
*/
|
|
||||||
function betterStates($state, $include = false)
|
|
||||||
{
|
|
||||||
static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
|
|
||||||
$i = array_search($state, $states);
|
|
||||||
if ($i === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ($include) {
|
|
||||||
$i--;
|
|
||||||
}
|
|
||||||
return array_slice($states, $i + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the valid roles for a PEAR package maintainer
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function getUserRoles()
|
|
||||||
{
|
|
||||||
return $GLOBALS['_PEAR_Common_maintainer_roles'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the valid package release states of packages
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function getReleaseStates()
|
|
||||||
{
|
|
||||||
return $GLOBALS['_PEAR_Common_release_states'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the implemented dependency types (php, ext, pkg etc.)
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function getDependencyTypes()
|
|
||||||
{
|
|
||||||
return $GLOBALS['_PEAR_Common_dependency_types'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the implemented dependency relations (has, lt, ge etc.)
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function getDependencyRelations()
|
|
||||||
{
|
|
||||||
return $GLOBALS['_PEAR_Common_dependency_relations'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the implemented file roles
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function getFileRoles()
|
|
||||||
{
|
|
||||||
return $GLOBALS['_PEAR_Common_file_roles'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the implemented file replacement types in
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function getReplacementTypes()
|
|
||||||
{
|
|
||||||
return $GLOBALS['_PEAR_Common_replacement_types'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the implemented file replacement types in
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function getProvideTypes()
|
|
||||||
{
|
|
||||||
return $GLOBALS['_PEAR_Common_provide_types'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the implemented file replacement types in
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function getScriptPhases()
|
|
||||||
{
|
|
||||||
return $GLOBALS['_PEAR_Common_script_phases'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether a string contains a valid package name.
|
|
||||||
*
|
|
||||||
* @param string $name the package name to test
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function validPackageName($name)
|
|
||||||
{
|
|
||||||
return (bool)preg_match(PEAR_COMMON_PACKAGE_NAME_PREG, $name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether a string contains a valid package version.
|
|
||||||
*
|
|
||||||
* @param string $ver the package version to test
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function validPackageVersion($ver)
|
|
||||||
{
|
|
||||||
return (bool)preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $path relative or absolute include path
|
|
||||||
* @return boolean
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
function isIncludeable($path)
|
|
||||||
{
|
|
||||||
if (file_exists($path) && is_readable($path)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$ipath = explode(PATH_SEPARATOR, ini_get('include_path'));
|
|
||||||
foreach ($ipath as $include) {
|
|
||||||
$test = realpath($include . DIRECTORY_SEPARATOR . $path);
|
|
||||||
if (file_exists($test) && is_readable($test)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _postProcessChecks($pf)
|
|
||||||
{
|
|
||||||
if (!PEAR::isError($pf)) {
|
|
||||||
return $this->_postProcessValidPackagexml($pf);
|
|
||||||
}
|
|
||||||
|
|
||||||
$errs = $pf->getUserinfo();
|
|
||||||
if (is_array($errs)) {
|
|
||||||
foreach ($errs as $error) {
|
|
||||||
$e = $this->raiseError($error['message'], $error['code'], null, null, $error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $pf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns information about a package file. Expects the name of
|
|
||||||
* a gzipped tar file as input.
|
|
||||||
*
|
|
||||||
* @param string $file name of .tgz file
|
|
||||||
*
|
|
||||||
* @return array array with package information
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @deprecated use PEAR_PackageFile->fromTgzFile() instead
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function infoFromTgzFile($file)
|
|
||||||
{
|
|
||||||
$packagefile = &new PEAR_PackageFile($this->config);
|
|
||||||
$pf = &$packagefile->fromTgzFile($file, PEAR_VALIDATE_NORMAL);
|
|
||||||
return $this->_postProcessChecks($pf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns information about a package file. Expects the name of
|
|
||||||
* a package xml file as input.
|
|
||||||
*
|
|
||||||
* @param string $descfile name of package xml file
|
|
||||||
*
|
|
||||||
* @return array array with package information
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @deprecated use PEAR_PackageFile->fromPackageFile() instead
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function infoFromDescriptionFile($descfile)
|
|
||||||
{
|
|
||||||
$packagefile = &new PEAR_PackageFile($this->config);
|
|
||||||
$pf = &$packagefile->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
|
|
||||||
return $this->_postProcessChecks($pf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns information about a package file. Expects the contents
|
|
||||||
* of a package xml file as input.
|
|
||||||
*
|
|
||||||
* @param string $data contents of package.xml file
|
|
||||||
*
|
|
||||||
* @return array array with package information
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @deprecated use PEAR_PackageFile->fromXmlstring() instead
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function infoFromString($data)
|
|
||||||
{
|
|
||||||
$packagefile = &new PEAR_PackageFile($this->config);
|
|
||||||
$pf = &$packagefile->fromXmlString($data, PEAR_VALIDATE_NORMAL, false);
|
|
||||||
return $this->_postProcessChecks($pf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
function _postProcessValidPackagexml(&$pf)
|
|
||||||
{
|
|
||||||
if (!is_a($pf, 'PEAR_PackageFile_v2')) {
|
|
||||||
$this->pkginfo = $pf->toArray();
|
|
||||||
return $this->pkginfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort of make this into a package.xml 1.0-style array
|
|
||||||
// changelog is not converted to old format.
|
|
||||||
$arr = $pf->toArray(true);
|
|
||||||
$arr = array_merge($arr, $arr['old']);
|
|
||||||
unset($arr['old'], $arr['xsdversion'], $arr['contents'], $arr['compatible'],
|
|
||||||
$arr['channel'], $arr['uri'], $arr['dependencies'], $arr['phprelease'],
|
|
||||||
$arr['extsrcrelease'], $arr['zendextsrcrelease'], $arr['extbinrelease'],
|
|
||||||
$arr['zendextbinrelease'], $arr['bundle'], $arr['lead'], $arr['developer'],
|
|
||||||
$arr['helper'], $arr['contributor']);
|
|
||||||
$arr['filelist'] = $pf->getFilelist();
|
|
||||||
$this->pkginfo = $arr;
|
|
||||||
return $arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns package information from different sources
|
|
||||||
*
|
|
||||||
* This method is able to extract information about a package
|
|
||||||
* from a .tgz archive or from a XML package definition file.
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string Filename of the source ('package.xml', '<package>.tgz')
|
|
||||||
* @return string
|
|
||||||
* @deprecated use PEAR_PackageFile->fromAnyFile() instead
|
|
||||||
*/
|
|
||||||
function infoFromAny($info)
|
|
||||||
{
|
|
||||||
if (is_string($info) && file_exists($info)) {
|
|
||||||
$packagefile = &new PEAR_PackageFile($this->config);
|
|
||||||
$pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL);
|
|
||||||
if (PEAR::isError($pf)) {
|
|
||||||
$errs = $pf->getUserinfo();
|
|
||||||
if (is_array($errs)) {
|
|
||||||
foreach ($errs as $error) {
|
|
||||||
$e = $this->raiseError($error['message'], $error['code'], null, null, $error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $pf;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->_postProcessValidPackagexml($pf);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $info;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an XML document based on the package info (as returned
|
|
||||||
* by the PEAR_Common::infoFrom* methods).
|
|
||||||
*
|
|
||||||
* @param array $pkginfo package info
|
|
||||||
*
|
|
||||||
* @return string XML data
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @deprecated use a PEAR_PackageFile_v* object's generator instead
|
|
||||||
*/
|
|
||||||
function xmlFromInfo($pkginfo)
|
|
||||||
{
|
|
||||||
$config = &PEAR_Config::singleton();
|
|
||||||
$packagefile = &new PEAR_PackageFile($config);
|
|
||||||
$pf = &$packagefile->fromArray($pkginfo);
|
|
||||||
$gen = &$pf->getDefaultGenerator();
|
|
||||||
return $gen->toXml(PEAR_VALIDATE_PACKAGING);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate XML package definition file.
|
|
||||||
*
|
|
||||||
* @param string $info Filename of the package archive or of the
|
|
||||||
* package definition file
|
|
||||||
* @param array $errors Array that will contain the errors
|
|
||||||
* @param array $warnings Array that will contain the warnings
|
|
||||||
* @param string $dir_prefix (optional) directory where source files
|
|
||||||
* may be found, or empty if they are not available
|
|
||||||
* @access public
|
|
||||||
* @return boolean
|
|
||||||
* @deprecated use the validation of PEAR_PackageFile objects
|
|
||||||
*/
|
|
||||||
function validatePackageInfo($info, &$errors, &$warnings, $dir_prefix = '')
|
|
||||||
{
|
|
||||||
$config = &PEAR_Config::singleton();
|
|
||||||
$packagefile = &new PEAR_PackageFile($config);
|
|
||||||
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
|
|
||||||
if (strpos($info, '<?xml') !== false) {
|
|
||||||
$pf = &$packagefile->fromXmlString($info, PEAR_VALIDATE_NORMAL, '');
|
|
||||||
} else {
|
|
||||||
$pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
PEAR::staticPopErrorHandling();
|
|
||||||
if (PEAR::isError($pf)) {
|
|
||||||
$errs = $pf->getUserinfo();
|
|
||||||
if (is_array($errs)) {
|
|
||||||
foreach ($errs as $error) {
|
|
||||||
if ($error['level'] == 'error') {
|
|
||||||
$errors[] = $error['message'];
|
|
||||||
} else {
|
|
||||||
$warnings[] = $error['message'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build a "provides" array from data returned by
|
|
||||||
* analyzeSourceCode(). The format of the built array is like
|
|
||||||
* this:
|
|
||||||
*
|
|
||||||
* array(
|
|
||||||
* 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
|
|
||||||
* ...
|
|
||||||
* )
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param array $srcinfo array with information about a source file
|
|
||||||
* as returned by the analyzeSourceCode() method.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function buildProvidesArray($srcinfo)
|
|
||||||
{
|
|
||||||
$file = basename($srcinfo['source_file']);
|
|
||||||
$pn = '';
|
|
||||||
if (isset($this->_packageName)) {
|
|
||||||
$pn = $this->_packageName;
|
|
||||||
}
|
|
||||||
|
|
||||||
$pnl = strlen($pn);
|
|
||||||
foreach ($srcinfo['declared_classes'] as $class) {
|
|
||||||
$key = "class;$class";
|
|
||||||
if (isset($this->pkginfo['provides'][$key])) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->pkginfo['provides'][$key] =
|
|
||||||
array('file'=> $file, 'type' => 'class', 'name' => $class);
|
|
||||||
if (isset($srcinfo['inheritance'][$class])) {
|
|
||||||
$this->pkginfo['provides'][$key]['extends'] =
|
|
||||||
$srcinfo['inheritance'][$class];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($srcinfo['declared_methods'] as $class => $methods) {
|
|
||||||
foreach ($methods as $method) {
|
|
||||||
$function = "$class::$method";
|
|
||||||
$key = "function;$function";
|
|
||||||
if ($method{0} == '_' || !strcasecmp($method, $class) ||
|
|
||||||
isset($this->pkginfo['provides'][$key])) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->pkginfo['provides'][$key] =
|
|
||||||
array('file'=> $file, 'type' => 'function', 'name' => $function);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($srcinfo['declared_functions'] as $function) {
|
|
||||||
$key = "function;$function";
|
|
||||||
if ($function{0} == '_' || isset($this->pkginfo['provides'][$key])) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
|
|
||||||
$warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->pkginfo['provides'][$key] =
|
|
||||||
array('file'=> $file, 'type' => 'function', 'name' => $function);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Analyze the source code of the given PHP file
|
|
||||||
*
|
|
||||||
* @param string Filename of the PHP file
|
|
||||||
* @return mixed
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
function analyzeSourceCode($file)
|
|
||||||
{
|
|
||||||
if (!class_exists('PEAR_PackageFile_v2_Validator')) {
|
|
||||||
require_once 'PEAR/PackageFile/v2/Validator.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
$a = new PEAR_PackageFile_v2_Validator;
|
|
||||||
return $a->analyzeSourceCode($file);
|
|
||||||
}
|
|
||||||
|
|
||||||
function detectDependencies($any, $status_callback = null)
|
|
||||||
{
|
|
||||||
if (!function_exists("token_get_all")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PEAR::isError($info = $this->infoFromAny($any))) {
|
|
||||||
return $this->raiseError($info);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_array($info)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$deps = array();
|
|
||||||
$used_c = $decl_c = $decl_f = $decl_m = array();
|
|
||||||
foreach ($info['filelist'] as $file => $fa) {
|
|
||||||
$tmp = $this->analyzeSourceCode($file);
|
|
||||||
$used_c = @array_merge($used_c, $tmp['used_classes']);
|
|
||||||
$decl_c = @array_merge($decl_c, $tmp['declared_classes']);
|
|
||||||
$decl_f = @array_merge($decl_f, $tmp['declared_functions']);
|
|
||||||
$decl_m = @array_merge($decl_m, $tmp['declared_methods']);
|
|
||||||
$inheri = @array_merge($inheri, $tmp['inheritance']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$used_c = array_unique($used_c);
|
|
||||||
$decl_c = array_unique($decl_c);
|
|
||||||
$undecl_c = array_diff($used_c, $decl_c);
|
|
||||||
|
|
||||||
return array('used_classes' => $used_c,
|
|
||||||
'declared_classes' => $decl_c,
|
|
||||||
'declared_methods' => $decl_m,
|
|
||||||
'declared_functions' => $decl_f,
|
|
||||||
'undeclared_classes' => $undecl_c,
|
|
||||||
'inheritance' => $inheri,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Download a file through HTTP. Considers suggested file name in
|
|
||||||
* Content-disposition: header and can run a callback function for
|
|
||||||
* different events. The callback will be called with two
|
|
||||||
* parameters: the callback type, and parameters. The implemented
|
|
||||||
* callback types are:
|
|
||||||
*
|
|
||||||
* 'setup' called at the very beginning, parameter is a UI object
|
|
||||||
* that should be used for all output
|
|
||||||
* 'message' the parameter is a string with an informational message
|
|
||||||
* 'saveas' may be used to save with a different file name, the
|
|
||||||
* parameter is the filename that is about to be used.
|
|
||||||
* If a 'saveas' callback returns a non-empty string,
|
|
||||||
* that file name will be used as the filename instead.
|
|
||||||
* Note that $save_dir will not be affected by this, only
|
|
||||||
* the basename of the file.
|
|
||||||
* 'start' download is starting, parameter is number of bytes
|
|
||||||
* that are expected, or -1 if unknown
|
|
||||||
* 'bytesread' parameter is the number of bytes read so far
|
|
||||||
* 'done' download is complete, parameter is the total number
|
|
||||||
* of bytes read
|
|
||||||
* 'connfailed' if the TCP connection fails, this callback is called
|
|
||||||
* with array(host,port,errno,errmsg)
|
|
||||||
* 'writefailed' if writing to disk fails, this callback is called
|
|
||||||
* with array(destfile,errmsg)
|
|
||||||
*
|
|
||||||
* If an HTTP proxy has been configured (http_proxy PEAR_Config
|
|
||||||
* setting), the proxy will be used.
|
|
||||||
*
|
|
||||||
* @param string $url the URL to download
|
|
||||||
* @param object $ui PEAR_Frontend_* instance
|
|
||||||
* @param object $config PEAR_Config instance
|
|
||||||
* @param string $save_dir (optional) directory to save file in
|
|
||||||
* @param mixed $callback (optional) function/method to call for status
|
|
||||||
* updates
|
|
||||||
*
|
|
||||||
* @return string Returns the full path of the downloaded file or a PEAR
|
|
||||||
* error on failure. If the error is caused by
|
|
||||||
* socket-related errors, the error object will
|
|
||||||
* have the fsockopen error code available through
|
|
||||||
* getCode().
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @deprecated in favor of PEAR_Downloader::downloadHttp()
|
|
||||||
*/
|
|
||||||
function downloadHttp($url, &$ui, $save_dir = '.', $callback = null)
|
|
||||||
{
|
|
||||||
if (!class_exists('PEAR_Downloader')) {
|
|
||||||
require_once 'PEAR/Downloader.php';
|
|
||||||
}
|
|
||||||
return PEAR_Downloader::downloadHttp($url, $ui, $save_dir, $callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once 'PEAR/Config.php';
|
|
||||||
require_once 'PEAR/PackageFile.php';
|
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue