From 2d522b9cd031ba509d57ac1f8c87687842185106 Mon Sep 17 00:00:00 2001 From: Chuck Scott Date: Wed, 14 Jan 2015 11:27:00 -0500 Subject: [PATCH 1/1] initial commit --- activate.php | 304 ++ classes/data/dataMembers.php | 146 + classes/glmPluginSupport.php | 89 + controllers/admin.php | 430 ++ controllers/front.php | 44 + css/admin.css | 56 + deactivate.php | 86 + index.php | 338 ++ js/admin.js | 40 + lib/EasyPassword/EasyPassword.php | 42 + lib/EasyPassword/EasyPassword.words | 828 +++ lib/GeoCalculations.php | 253 + lib/GlmDataAbstract/DataAbstract.php | 2935 +++++++++++ lib/GlmDataAbstract/documentation.txt | 439 ++ lib/Smarty-3.1.21/COPYING.lib | 165 + lib/Smarty-3.1.21/README | 574 +++ lib/Smarty-3.1.21/SMARTY_2_BC_NOTES.txt | 109 + lib/Smarty-3.1.21/SMARTY_3.0_BC_NOTES.txt | 24 + lib/Smarty-3.1.21/SMARTY_3.1_NOTES.txt | 306 ++ lib/Smarty-3.1.21/change_log.txt | 2415 +++++++++ lib/Smarty-3.1.21/demo/configs/test.conf | 5 + lib/Smarty-3.1.21/demo/index.php | 30 + .../demo/plugins/cacheresource.apc.php | 83 + .../demo/plugins/cacheresource.memcache.php | 97 + .../demo/plugins/cacheresource.mysql.php | 162 + .../demo/plugins/resource.extendsall.php | 60 + .../demo/plugins/resource.mysql.php | 81 + .../demo/plugins/resource.mysqls.php | 62 + lib/Smarty-3.1.21/demo/templates/footer.tpl | 2 + lib/Smarty-3.1.21/demo/templates/header.tpl | 5 + lib/Smarty-3.1.21/demo/templates/index.tpl | 87 + lib/Smarty-3.1.21/libs/Smarty.class.php | 1680 ++++++ lib/Smarty-3.1.21/libs/SmartyBC.class.php | 467 ++ lib/Smarty-3.1.21/libs/debug.tpl | 137 + .../libs/plugins/block.textformat.php | 110 + .../libs/plugins/function.counter.php | 78 + .../libs/plugins/function.cycle.php | 107 + .../libs/plugins/function.fetch.php | 221 + .../libs/plugins/function.html_checkboxes.php | 237 + .../libs/plugins/function.html_image.php | 163 + .../libs/plugins/function.html_options.php | 196 + .../libs/plugins/function.html_radios.php | 221 + .../plugins/function.html_select_date.php | 387 ++ .../plugins/function.html_select_time.php | 364 ++ .../libs/plugins/function.html_table.php | 176 + .../libs/plugins/function.mailto.php | 155 + .../libs/plugins/function.math.php | 91 + .../libs/plugins/modifier.capitalize.php | 90 + .../libs/plugins/modifier.date_format.php | 65 + .../libs/plugins/modifier.debug_print_var.php | 104 + .../libs/plugins/modifier.escape.php | 198 + .../libs/plugins/modifier.regex_replace.php | 57 + .../libs/plugins/modifier.replace.php | 34 + .../libs/plugins/modifier.spacify.php | 27 + .../libs/plugins/modifier.truncate.php | 64 + .../libs/plugins/modifiercompiler.cat.php | 29 + .../modifiercompiler.count_characters.php | 32 + .../modifiercompiler.count_paragraphs.php | 27 + .../modifiercompiler.count_sentences.php | 27 + .../plugins/modifiercompiler.count_words.php | 31 + .../libs/plugins/modifiercompiler.default.php | 35 + .../libs/plugins/modifiercompiler.escape.php | 126 + .../plugins/modifiercompiler.from_charset.php | 33 + .../libs/plugins/modifiercompiler.indent.php | 33 + .../libs/plugins/modifiercompiler.lower.php | 31 + .../libs/plugins/modifiercompiler.noprint.php | 21 + .../modifiercompiler.string_format.php | 25 + .../libs/plugins/modifiercompiler.strip.php | 33 + .../plugins/modifiercompiler.strip_tags.php | 29 + .../plugins/modifiercompiler.to_charset.php | 33 + .../plugins/modifiercompiler.unescape.php | 50 + .../libs/plugins/modifiercompiler.upper.php | 29 + .../plugins/modifiercompiler.wordwrap.php | 47 + .../plugins/outputfilter.trimwhitespace.php | 90 + .../plugins/shared.escape_special_chars.php | 53 + .../plugins/shared.literal_compiler_param.php | 35 + .../libs/plugins/shared.make_timestamp.php | 43 + .../libs/plugins/shared.mb_str_replace.php | 55 + .../libs/plugins/shared.mb_unicode.php | 54 + .../libs/plugins/shared.mb_wordwrap.php | 73 + .../variablefilter.htmlspecialchars.php | 19 + .../libs/sysplugins/smarty_cacheresource.php | 442 ++ .../smarty_cacheresource_custom.php | 284 + .../smarty_cacheresource_keyvaluestore.php | 493 ++ .../libs/sysplugins/smarty_config_source.php | 94 + .../smarty_internal_cacheresource_file.php | 297 ++ .../smarty_internal_compile_append.php | 50 + .../smarty_internal_compile_assign.php | 86 + .../smarty_internal_compile_block.php | 444 ++ .../smarty_internal_compile_break.php | 75 + .../smarty_internal_compile_call.php | 127 + .../smarty_internal_compile_capture.php | 96 + .../smarty_internal_compile_config_load.php | 82 + .../smarty_internal_compile_continue.php | 75 + .../smarty_internal_compile_debug.php | 41 + .../smarty_internal_compile_eval.php | 71 + .../smarty_internal_compile_extends.php | 85 + .../smarty_internal_compile_for.php | 145 + .../smarty_internal_compile_foreach.php | 229 + .../smarty_internal_compile_function.php | 162 + .../sysplugins/smarty_internal_compile_if.php | 210 + .../smarty_internal_compile_include.php | 265 + .../smarty_internal_compile_include_php.php | 107 + .../smarty_internal_compile_insert.php | 140 + .../smarty_internal_compile_ldelim.php | 39 + .../smarty_internal_compile_nocache.php | 70 + ..._internal_compile_private_block_plugin.php | 85 + ...ternal_compile_private_function_plugin.php | 71 + ...arty_internal_compile_private_modifier.php | 139 + ..._compile_private_object_block_function.php | 86 + ...ternal_compile_private_object_function.php | 84 + ...ernal_compile_private_print_expression.php | 151 + ...ernal_compile_private_registered_block.php | 111 + ...al_compile_private_registered_function.php | 79 + ...ernal_compile_private_special_variable.php | 114 + .../smarty_internal_compile_rdelim.php | 39 + .../smarty_internal_compile_section.php | 206 + .../smarty_internal_compile_setfilter.php | 70 + .../smarty_internal_compile_while.php | 93 + .../smarty_internal_compilebase.php | 174 + .../sysplugins/smarty_internal_config.php | 306 ++ .../smarty_internal_config_file_compiler.php | 159 + .../smarty_internal_configfilelexer.php | 646 +++ .../smarty_internal_configfileparser.php | 1042 ++++ .../libs/sysplugins/smarty_internal_data.php | 576 +++ .../libs/sysplugins/smarty_internal_debug.php | 254 + .../smarty_internal_filter_handler.php | 67 + .../smarty_internal_function_call_handler.php | 52 + .../smarty_internal_get_include_path.php | 46 + .../smarty_internal_nocache_insert.php | 51 + .../sysplugins/smarty_internal_parsetree.php | 361 ++ .../smarty_internal_resource_eval.php | 96 + .../smarty_internal_resource_extends.php | 112 + .../smarty_internal_resource_file.php | 89 + .../smarty_internal_resource_php.php | 119 + .../smarty_internal_resource_registered.php | 98 + .../smarty_internal_resource_stream.php | 81 + .../smarty_internal_resource_string.php | 97 + ...smarty_internal_smartytemplatecompiler.php | 140 + .../sysplugins/smarty_internal_template.php | 738 +++ .../smarty_internal_templatebase.php | 860 ++++ .../smarty_internal_templatecompilerbase.php | 823 +++ .../smarty_internal_templatelexer.php | 1552 ++++++ .../smarty_internal_templateparser.php | 4568 +++++++++++++++++ .../sysplugins/smarty_internal_utility.php | 837 +++ .../sysplugins/smarty_internal_write_file.php | 86 + .../libs/sysplugins/smarty_resource.php | 912 ++++ .../sysplugins/smarty_resource_custom.php | 95 + .../sysplugins/smarty_resource_recompiled.php | 33 + .../sysplugins/smarty_resource_uncompiled.php | 41 + .../libs/sysplugins/smarty_security.php | 480 ++ lib/smartyTemplateSupport.php | 122 + misc/create_database_V0.1.sql~ | 0 misc/databaseScripts/create_database_V0.1.sql | 411 ++ .../databaseScripts/create_database_V0.1.sql~ | 836 +++ misc/databaseScripts/drop_database_V0.1.sql | 30 + misc/databaseScripts/drop_database_V0.1.sql~ | 1 + ...368556f9c37e2780da.file.badAction.html.php | 31 + ...a1e104c26a275acc180da0.file.index.html.php | 75 + ...23ae1a70b66cefbd681db.file.header.html.php | 42 + ...ac671736867cbab8e7c6.file.headder.html.php | 45 + ...bc6c9474f73121a83d59b.file.header.html.php | 22 + ...645f3c977b0b1dc2a9e718.file.index.html.php | 31 + ...8c737669426ab57397d1d.file.footer.html.php | 50 + ...cc61d6a64ab3f597b245655.file.edit.html.php | 89 + ...bca4d9344f2fd4a4152f52.file.index.html.php | 31 + ...4c071993e263e2ce152e7.file.footer.html.php | 50 + models/admin/configure/index.php | 117 + models/admin/error/badAction.php | 112 + models/admin/error/index.php | 70 + models/admin/members/add.php | 143 + models/admin/members/delete.php | 127 + models/admin/members/display.php | 144 + models/admin/members/edit.php | 349 ++ models/admin/members/index.php | 142 + models/front/NOTHING_HERE_YET | 0 readme.txt | 91 + uninstall.php | 51 + views/admin/configure/headder.html | 10 + views/admin/configure/index.html | 7 + views/admin/error/badAction.html | 9 + views/admin/error/index.html | 9 + views/admin/footer.html | 15 + views/admin/members/edit.html | 51 + views/admin/members/headder.html | 9 + views/admin/members/index.html | 39 + views/front/NOTHING_HERE_YET | 0 views/welcome.html | 10 + 188 files changed, 41318 insertions(+) create mode 100644 activate.php create mode 100644 classes/data/dataMembers.php create mode 100644 classes/glmPluginSupport.php create mode 100644 controllers/admin.php create mode 100644 controllers/front.php create mode 100644 css/admin.css create mode 100644 deactivate.php create mode 100644 index.php create mode 100644 js/admin.js create mode 100644 lib/EasyPassword/EasyPassword.php create mode 100644 lib/EasyPassword/EasyPassword.words create mode 100644 lib/GeoCalculations.php create mode 100755 lib/GlmDataAbstract/DataAbstract.php create mode 100644 lib/GlmDataAbstract/documentation.txt create mode 100644 lib/Smarty-3.1.21/COPYING.lib create mode 100644 lib/Smarty-3.1.21/README create mode 100644 lib/Smarty-3.1.21/SMARTY_2_BC_NOTES.txt create mode 100644 lib/Smarty-3.1.21/SMARTY_3.0_BC_NOTES.txt create mode 100644 lib/Smarty-3.1.21/SMARTY_3.1_NOTES.txt create mode 100644 lib/Smarty-3.1.21/change_log.txt create mode 100644 lib/Smarty-3.1.21/demo/configs/test.conf create mode 100644 lib/Smarty-3.1.21/demo/index.php create mode 100644 lib/Smarty-3.1.21/demo/plugins/cacheresource.apc.php create mode 100644 lib/Smarty-3.1.21/demo/plugins/cacheresource.memcache.php create mode 100644 lib/Smarty-3.1.21/demo/plugins/cacheresource.mysql.php create mode 100644 lib/Smarty-3.1.21/demo/plugins/resource.extendsall.php create mode 100644 lib/Smarty-3.1.21/demo/plugins/resource.mysql.php create mode 100644 lib/Smarty-3.1.21/demo/plugins/resource.mysqls.php create mode 100644 lib/Smarty-3.1.21/demo/templates/footer.tpl create mode 100644 lib/Smarty-3.1.21/demo/templates/header.tpl create mode 100644 lib/Smarty-3.1.21/demo/templates/index.tpl create mode 100644 lib/Smarty-3.1.21/libs/Smarty.class.php create mode 100644 lib/Smarty-3.1.21/libs/SmartyBC.class.php create mode 100644 lib/Smarty-3.1.21/libs/debug.tpl create mode 100644 lib/Smarty-3.1.21/libs/plugins/block.textformat.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/function.counter.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/function.cycle.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/function.fetch.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/function.html_checkboxes.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/function.html_image.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/function.html_options.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/function.html_radios.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/function.html_select_date.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/function.html_select_time.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/function.html_table.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/function.mailto.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/function.math.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifier.capitalize.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifier.date_format.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifier.debug_print_var.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifier.escape.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifier.regex_replace.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifier.replace.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifier.spacify.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifier.truncate.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifiercompiler.cat.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifiercompiler.count_characters.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifiercompiler.count_paragraphs.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifiercompiler.count_sentences.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifiercompiler.count_words.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifiercompiler.default.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifiercompiler.escape.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifiercompiler.from_charset.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifiercompiler.indent.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifiercompiler.lower.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifiercompiler.noprint.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifiercompiler.string_format.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifiercompiler.strip.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifiercompiler.strip_tags.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifiercompiler.to_charset.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifiercompiler.unescape.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifiercompiler.upper.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/modifiercompiler.wordwrap.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/outputfilter.trimwhitespace.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/shared.escape_special_chars.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/shared.literal_compiler_param.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/shared.make_timestamp.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/shared.mb_str_replace.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/shared.mb_unicode.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/shared.mb_wordwrap.php create mode 100644 lib/Smarty-3.1.21/libs/plugins/variablefilter.htmlspecialchars.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_cacheresource.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_cacheresource_custom.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_cacheresource_keyvaluestore.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_config_source.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_cacheresource_file.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_append.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_assign.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_block.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_break.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_call.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_capture.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_config_load.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_continue.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_debug.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_eval.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_extends.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_for.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_foreach.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_function.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_if.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_include.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_include_php.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_insert.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_ldelim.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_nocache.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_private_block_plugin.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_private_function_plugin.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_private_modifier.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_private_object_block_function.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_private_object_function.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_private_print_expression.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_private_registered_block.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_private_registered_function.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_private_special_variable.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_rdelim.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_section.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_setfilter.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compile_while.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_compilebase.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_config.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_config_file_compiler.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_configfilelexer.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_configfileparser.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_data.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_debug.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_filter_handler.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_function_call_handler.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_get_include_path.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_nocache_insert.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_parsetree.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_resource_eval.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_resource_extends.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_resource_file.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_resource_php.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_resource_registered.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_resource_stream.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_resource_string.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_smartytemplatecompiler.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_template.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_templatebase.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_templatecompilerbase.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_templatelexer.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_templateparser.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_utility.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_internal_write_file.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_resource.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_resource_custom.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_resource_recompiled.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_resource_uncompiled.php create mode 100644 lib/Smarty-3.1.21/libs/sysplugins/smarty_security.php create mode 100644 lib/smartyTemplateSupport.php create mode 100644 misc/create_database_V0.1.sql~ create mode 100644 misc/databaseScripts/create_database_V0.1.sql create mode 100644 misc/databaseScripts/create_database_V0.1.sql~ create mode 100644 misc/databaseScripts/drop_database_V0.1.sql create mode 100644 misc/databaseScripts/drop_database_V0.1.sql~ create mode 100644 misc/smarty/templates_c/06926788f51c1a5a54be2a368556f9c37e2780da.file.badAction.html.php create mode 100644 misc/smarty/templates_c/081a36d97cdf30d438a1e104c26a275acc180da0.file.index.html.php create mode 100644 misc/smarty/templates_c/15f83071407dddb0b3c23ae1a70b66cefbd681db.file.header.html.php create mode 100644 misc/smarty/templates_c/26d04a65ccdb3ac3d40bac671736867cbab8e7c6.file.headder.html.php create mode 100644 misc/smarty/templates_c/3ec5bcbe581d6335e06bc6c9474f73121a83d59b.file.header.html.php create mode 100644 misc/smarty/templates_c/47fb9b803e7138d215645f3c977b0b1dc2a9e718.file.index.html.php create mode 100644 misc/smarty/templates_c/50e78f1400d6db96c588c737669426ab57397d1d.file.footer.html.php create mode 100644 misc/smarty/templates_c/5b0b8a17c49dbe822cc61d6a64ab3f597b245655.file.edit.html.php create mode 100644 misc/smarty/templates_c/60cbe99d19bbec013cbca4d9344f2fd4a4152f52.file.index.html.php create mode 100644 misc/smarty/templates_c/8106057c3d809e21acc4c071993e263e2ce152e7.file.footer.html.php create mode 100644 models/admin/configure/index.php create mode 100644 models/admin/error/badAction.php create mode 100644 models/admin/error/index.php create mode 100644 models/admin/members/add.php create mode 100644 models/admin/members/delete.php create mode 100644 models/admin/members/display.php create mode 100644 models/admin/members/edit.php create mode 100644 models/admin/members/index.php create mode 100644 models/front/NOTHING_HERE_YET create mode 100644 readme.txt create mode 100644 uninstall.php create mode 100644 views/admin/configure/headder.html create mode 100644 views/admin/configure/index.html create mode 100644 views/admin/error/badAction.html create mode 100644 views/admin/error/index.html create mode 100644 views/admin/footer.html create mode 100644 views/admin/members/edit.html create mode 100644 views/admin/members/headder.html create mode 100644 views/admin/members/index.html create mode 100644 views/front/NOTHING_HERE_YET create mode 100644 views/welcome.html diff --git a/activate.php b/activate.php new file mode 100644 index 00000000..9b25583f --- /dev/null +++ b/activate.php @@ -0,0 +1,304 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @release admin.php,v 1.0 2014/10/31 19:31:47 cscott Exp $ + * @link http://dev.gaslightmedia.com/ + */ + +// Load glmPluginSupport class +require_once (GLM_MEMBERS_PLUGIN_DIR . '/classes/glmPluginSupport.php'); + +/* + * This class performs all necessary additional work when this + * plugin is activated. + * + * Currently the only actions are to add role capability to display and modify + * prototypes. + */ +class glmMembersPluginActivate extends glmPluginSupport +{ + + /** + * Plugin Versions + * + * An array of past and current Member Database versions. + * Note that Database Versions match plugin versions. + * + * Each entry below uses a key so code can find data on + * a specific version and in the values are the version + * again and the proper number of tables that should + * exist with that version. + * + * @var $Versions + * @access private + */ + private $dbVersions = array( + '0.1' => array('version' => '0.1', 'tables' => 22) + ); + + /** + * WordPress Database Object + * + * @var $wpdb + * @access public + */ + public $wpdb; + + /* + * Constructor + * + * Performs all the work for this model + */ + public function __construct ($wpdb) + { + // This line is for dropping the currrent database version for testing + // delete_option('glmMembersDatabaseDbVersion'); + + // Make sure the current user has this capability + if (! current_user_can('activate_plugins')) { + $this->addNotice("Interesting, you don't have permission to activate plugins."); + die(); + } + + // Save WordPress Database object + $this->wpdb = $wpdb; + + + $this->checkErrorScrape(); + + // Check the database + if (!$this->checkDatabase()) { + + // There was some kind of dataase failure, so die to prevent WordPress from marking plugin as activated. + die(); + + } + + // Add user capabilties + // $this->addRoleCapability('glm_members_edit', false); + + // Set current plugin version + update_option('glmMembersDatbasePluginVersion', GLM_MEMBERS_PLUGIN_VERSION); + + + } + + /* + * Check if database is installed and if it matches the current version + * + * @param string $capability Name of capability to add + * @param string $default Whether capability should be on by default + * + * @return void + * @access private + */ + private function checkDatabase () + { + + $dbVersion = get_option('glmMembersDatabaseDbVersion'); + $db_setup_status = false; + + // Do a quick check for there being a database version but not all the required tables for that version + if ($dbVersion) { + + // Check if the database version set for this plugin is invalid. + if (!isset($this->dbVersions[$dbVersion])) { + $this->addNotice("The last database version set for the ".GLM_MEMBERS_PLUGIN_NAME." (V$dbVersion) isn't valid."); + return false; + } + + // Get the number of tables for this plugin database version that should exist. + $tables = $this->dbVersions[$dbVersion]['tables']; + + // Get the number of tables for this plugin that do currently exist. + $existingTables = $this->wpdb->get_var(" + SELECT COUNT(*) + FROM information_schema.tables + WHERE table_name like '".GLM_MEMBERS_PLUGIN_DB_PREFIX."%'; + "); + + // Check if the number of tables is correct + if ($tables != $existingTables) { + $this->addNotice('We do not have the correct number of tables for the currently set database version (V'.$dbVersion.') for the '.GLM_MEMBERS_PLUGIN_NAME.'.'); + $this->addNotice("There should be $tables but there are currently $existingTables. Please call for support."); + return false; + } + + } + + // If glmMembersDatabaseDbVersion is not set, install current version + if (!$dbVersion) { + + // Get current database version + $dbVersion = GLM_MEMBERS_PLUGIN_DB_VERSION; + + // Read in Database creation script + $sqlFile = GLM_MEMBERS_PLUGIN_DB_SCRIPTS.'/create_database_V'.$dbVersion.'.sql'; + $sql = file_get_contents($sqlFile); + + // Replace {prefix} with table name prefix + $sql = str_replace('{prefix}', GLM_MEMBERS_PLUGIN_DB_PREFIX, $sql); + + // Split script into separate queries by looking for lines with only "---" + $queries = preg_split('/^----$/m', $sql); + + // Try executing all queries to build database + do { + $q = current($queries); + $this->wpdb->query($q); + $queryError = $this->wpdb->last_error; + } while ($queryError == '' && next($queries)); + + // If there were no errors + if (trim($queryError) == '') { + + // Notify the user that the database has been installed + $this->addNotice('New database tables installed for the '.GLM_MEMBERS_PLUGIN_NAME.' plugin.'); + + // Save the version of the installed database + update_option('glmMembersDatabaseDbVersion', $dbVersion); + + // Indicate that we were successfull + $db_setup_status = true; + + } else { + $this->addNotice('Failure installing database tables for the '.GLM_MEMBERS_PLUGIN_NAME.' plugin.'); + $this->addNotice(''.print_r($queryError,1).''); +// $this->addNotice('

'.print_r($q,1).''); + } + + // Otherwise, check if we need to update the database + } elseif ($dbVersion != GLM_MEMBERS_PLUGIN_DB_VERSION) { + + // Include an admin message that we're updating the database + $this->addNotice('The '.GLM_MEMBERS_PLUGIN_NAME.' database tables require updating...'); + + // Check if current glmMembersDatabaseDbVersion is invalid + if (!in_array(GLM_MEMBERS_PLUGIN_DB_VERSION, $this->dbVersions)) { + $this->addNotice('The database version currently installed for this plugin is unknown. ' + .'Unable to install the '.GLM_MEMBERS_PLUGIN_NAME.' plugin.
' + .'This could be due to an option naming conflict.'); + + } + + // Traverse version list to find any required updates + $curVerFound = false; + $db_setup_status = true; + foreach($this->dbVersions as $ver) { + + // Find the current version of the database + if ($ver == $dbVersion) { + $this->addNotice('The database version installed for the '.GLM_MEMBERS_PLUGIN_NAME + .' plugin is current and does not require updating.'); + $db_setup_status = true; + + // Otherwise if it's already been found and $ver is not the new target version + } elseif ($curVerFound && $dbVersion != GLM_MEMBERS_PLUGIN_DB_VERSION) { + + // Build database update script name + $updateScript = $dbVersion.'_'.$ver; + + // Read in Database creation script + $sqlFile = GLM_MEMBERS_PLUGIN_DB_SCRIPTS.'/update_database_V'.$dbVersion.'_V'.$ver.'.sql'; + $sql = file_get_contents($sqlFile); + + // Replace {prefix} with table name prefix + $sql = str_replace('{prefix}', GLM_MEMBERS_PLUGIN_DB_PREFIX, $sql); + + // Split script into separate queries by looking for lines with only "---" + $queries = preg_split('/^----$/m', $sql); + + // Try executing all queries to update database + do { + $q = current($queries); + $this->wpdb->query($q); + $queryError = $this->wpdb->last_error; + } while ($queryError == '' && next($queries)); + + // If there were no errors + if ($queryError == '') { + $this->addNotice('The database for the '.GLM_MEMBERS_PLUGIN_NAME.' plugin has been updated ' + .'from V'.$dbVersion.'_V'.$ver.'.'); + } else { + $this->addNotice('Failure updating the database tables for the '.GLM_MEMBERS_PLUGIN_NAME.' plugin ' + .'from V'.$dbVersion.'_V'.$ver.'.'); + $db_setup_status = false; + $this->addNotice('ERROR: '.$queryError); + } + + } + + $dbVersion = $ver; + + // Save the new version. If we've had a problem updating the database, then stop here. + if ($db_setup_status) { + + // Save the version of the installed database + update_option('glmMembersDatabaseDbVersion', $dbVersion); + + } else { + break; + } + + } + + if ($db_setup_status) { + + // Save the updated version of the installed database +// update_option('glmMembersDatabaseDbVersion', $dbVersion); + + $this->addNotice('Database tables updated.'); + } + + } else { + $this->addNotice('The '.GLM_MEMBERS_PLUGIN_NAME.' has been reactivated using the existing database tables.'); + $db_setup_status = true; + } + + return $db_setup_status; + } + + /* + * Add a role capability to all current roles + * + * @param string $capability Name of capability to add + * @param string $default Whether capability should be on by default + * + * @return void + * @access private + */ + private function addRoleCapability ($capability, $default) + { + // Get list of role objects + $roleObjects = $GLOBALS['wp_roles']->role_objects; + + // Get list of roles we can edit + $roles = get_editable_roles(); + + // For each role object + foreach ($roleObjects as $key => $role) { + + // Check if the role exists in list of editable roles and capability + // does not exist + if (isset($roles[$key]) && ! isset($role->capabilities[$capability])) { + + // Add the role + $role->add_cap($capability, $default); + } + } + } + + + +} + +?> \ No newline at end of file diff --git a/classes/data/dataMembers.php b/classes/data/dataMembers.php new file mode 100644 index 00000000..a201d432 --- /dev/null +++ b/classes/data/dataMembers.php @@ -0,0 +1,146 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @release SVN: $Id: dataMembers.php,v 1.0 2011/01/25 19:31:47 cscott Exp $ + */ + +/** + * EventManagementDataMembers class + * + * PHP version 5 + * + * @category Data + * @package EventManagement + * @author Chuck Scott + * @license http://www.gaslightmedia.com Gaslightmedia + * @release SVN: $Id: dataMembers.php,v 1.0 2011/01/25 19:31:47 cscott + * Exp $ + * @link http://www.visitgreatlakesbay.org/ + */ +abstract class GlmDataMembers extends GlmDataAbstract { + + /** + * Field definitions + * + * @var $ini + * @access public + */ + public $table; + + /** + * Field definitions + * + * 'type' is type of field as defined by the application + * text Regular text field + * pointer Pointer to an entry in another table + * 'filters' is the filter name for a particular filter ID in PHP filter + * functions + * See PHP filter_id() + * + * 'use' is when to use the field + * l = List + * g = Get + * n = New + * i = Insert + * e = Edit + * u = Update + * d = Delete + * a = All + * + * @var $ini + * @access public + */ + public $fields = false; + + /** + * Constructor + * + * @param object $d + * database connection + * + * @return void + * @access public + */ + function __construct($dbh, $config) { + parent::__construct ( $dbh, $config ); + + $this->table = GLM_MEMBERS_PLUGIN_DB_PREFIX . 'members'; + + $this->fields = array ( + + 'id' => array ( + 'field' => 'id', + 'type' => 'integer', + 'view_only' => true, + 'use' => 'lgd' + ), + + // Active + 'active' => array ( + 'field' => 'active', + 'type' => 'checkbox', + 'use' => 'a' + ), + + // Member Name + 'name' => array ( + 'field' => 'name', + 'type' => 'text', + 'required' => true, + 'unique' => true, + 'use' => 'a' + ), + + // Description + 'descr' => array( + 'field' => 'descr', + 'type' => 'text', + 'required' => true, + 'use' => 'gneud' + ), + + // Short description + 'short_descr' => array ( + 'field' => 'short_descr', + 'type' => 'text', + 'required' => true, + 'use' => 'a' + ), + + // Address Line 1 + 'addr1' => array ( + 'field' => 'addr1', + 'type' => 'text', + 'use' => 'a' + ), + + // Address Line 2 + 'addr2' => array ( + 'field' => 'addr2', + 'type' => 'text', + 'use' => 'a' + ), + + // Address Line 1 + 'addr1' => array ( + 'field' => 'addr1', + 'type' => 'text', + 'use' => 'a' + ) + + + ) + // + ; + } +} + +?> \ No newline at end of file diff --git a/classes/glmPluginSupport.php b/classes/glmPluginSupport.php new file mode 100644 index 00000000..bd35635e --- /dev/null +++ b/classes/glmPluginSupport.php @@ -0,0 +1,89 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @release glmPluginSupport.php,v 1.0 2014/10/31 19:31:47 cscott Exp $ + * @link http://dev.gaslightmedia.com/ + */ + +/* + * This class provides some standard methods used by this plugin + */ +class GlmPluginSupport +{ + + /* + * Add a message to the 'glmMembersAdminNotices' option for output later. + * + * @param string $message + * + * @return void + * @access public + */ + public function addNotice ($message, $title = false) + { + $notices = get_option('glmMembersAdminNotices'); + + // If there's a title, include that + $mes = $message; + if ($title) { + $mes = '

'.$title.'
'.$mes."
"; + } + + $notices[] = $mes; + update_option('glmMembersAdminNotices', $notices); + } + + /* + * Check if this is a second call to the activation hook by WordPress to activate this plugin. + * + * (Yea, I know that's stupid behavior, but there's nothing I can do about it.) + * It tells us this is happening by setting the 'action' GET parameter to 'error_scrape', + * which is also stupid. + * + * In this case, we don't want to try again, so output any saved notices from the first pass + * and then exit to tell WordPress the plugin didn't install. + * + * @return void + * @access public + */ + public function checkErrorScrape() + { + + // Check for 'action' = 'error_scrape', which indicates a second call from WordPress due to an error. + if (isset($_GET['action']) && $_GET['action'] == 'error_scrape') { + + // Sleep for a bit to make sure the glmMembersAdminNotices option is set. (seems to need this) + sleep(1); + + // if we have pending messages, display those + if (get_option('glmMembersAdminNotices')) { + + glmMembersAdminNotices(); + + // Otherwise, there must have been some other error. + } else { + + echo 'There has been an unknown error installing the Gaslight Media Members Database plugin.'; + + } + + // Quit here so Wordpress doesn't mark plugin as activated or deactivated + exit; + + } + + } + + +} + +?> \ No newline at end of file diff --git a/controllers/admin.php b/controllers/admin.php new file mode 100644 index 00000000..d1628f64 --- /dev/null +++ b/controllers/admin.php @@ -0,0 +1,430 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @release admin.php,v 1.0 2014/10/31 19:31:47 cscott Exp $ + * @link http://dev.gaslightmedia.com/ + */ + +/** + * Array of valid menu items and actions. + * + * + * The higher level elements are valid menu items. These correlate to + * actual menu or sub menu items that are hooks back to this controller + * class. + * + * The lower level items below each menu item are actions that may be specified + * by a "glmMembersAction" form field. + */ +$GLOBALS['glmMembersAdminValidActions'] = array( + + 'members' => array( + 'index', + 'display', + 'edit', + 'add', + 'delete' + ), + 'configure' => array( + 'index', + 'cities', + 'states', + 'countries', + 'regions' + ), + 'error' => array( + 'badAction' + ) +); + +// Load glmPluginSupport class +require_once (GLM_MEMBERS_PLUGIN_DIR . '/classes/glmPluginSupport.php'); + +/** + * Admin Controller Class + * + * This is one of perhaps multiple controller classes that provide + * controller services for a major portion of this plugin. Typically + * there are such classes for Admin and Front-End functionality, but + * there could be others. + * + * This controller class performs all admin related operations for + * this plugin by calling the appropriate model and merging the resulting + * data with the appropriate view to produce any output. + * + * All requests for this controller class come through WordPress admin + * menus via hooks that "call back" methods in this class for each admin + * menu item in this plugin. Form submissions from an admin page selected + * by a particular menu item are directed to WordPress using the page + * reference of that menu item. Because of this, the callback for a form + * submission is also handled by the callback target method used by that + * menu item. + * + * Admin form submissions must use the URI for one of this plugin's + * menu items. The form post parameters may also provide an "action" name + * in the case where the default menu item behavior is not desired. A + * pathname for the model to execute is then complied using the menu + * item name as the name of a directory under models/admin and the + * requested action as the file name of the model to execute. The name + * "index" would be the default menu item action model. In essence the + * controller locates the model by menu item name and action name. for + * example... + * + * models/admin/members/index.php + * models/admin/members/display.php + * + * Similarly, the view associated with the action would be in a directory + * named the same as the model, and the view file would be named "index" + * or the name of the action. + * + * These hooks are established using the WordPress add_action() + * function and the configureMenus() method below. Other methods in this + * class then recieve any request from a menu item selection or form + * + * submission associated with a menu item by WordPress calling one of the + * "callback" methods below. + * + * The callback methods do nothing other than to call the controller() + * method and passing it the name of the menu item assocaiated with the + * callback. + * + * The controller() method determines which model to execute, executes + * that model, determines which view to merge with the data returned by + * the model, creates output from the result of that merge, and sends + * that output to the user. + * + * In situations where it may be desired to output directly to the browser + * without being contained in the admin Dashboard, the contructor can be + * directed + * to bypass setting up the admin hooks and execute the controller() method + * directly then exit. This results in output from the model/view withing being + * contained in the normal WordPress dashboard context. To trigger this use the + * following two form fields. + * + * glm_display_direct = 'true' + * glm_menu_item = (menu item name associated with the desired model) + * + * (no prameters) + * + * @return void + * @access public + */ +class glmMembersAdmin extends GlmPluginSupport +{ + + /** + * WordPress Database Object + * + * @var $wpdb + * @access public + */ + public $wpdb; + + /** + * Plugin Configuration Data + * + * @var $config + * @access public + */ + public $config; + + /** + * Admin Controller Constructor + * + * This contructor is executed by the main plugin index file when the site + * Dashboard is displayed. It's responsible for setting up any needed hooks + * into WordPress and setting up any support classes required to do admin + * work. + * + * (no prameters) + * + * @return void + * @access public + */ + public function __construct ($wpdb, $config) + { + + // Save WordPress Database object + $this->wpdb = $wpdb; + + // Save plugin configuration object + $this->config = $config; + + /* + * Check if there's a request to bypass the WordPress Dashboard and + * display + * directly to the browser using a specified menuItem/action. + * + */ + if (isset($_REQUEST['glm_display_direct']) && + $_REQUEST['glm_menu_item'] != '') { + + // Get the desired menu item name and call controller() with that. + $menuItem = sanitize_text_field($_REQUEST['glm_menu_item']); + $this->controller($menuItem); + + // Exit at this point to stop all WordPress Dashboard output + exit(); + } + + // Add hooks to WordPress + add_action('admin_menu', array( + $this, + 'configureMenus' + )); + + // Add admin scripts and css + add_action('admin_enqueue_scripts', + array( + $this, + 'glmMembersAdminScripts' + )); + } + + /** + * Setup inclusion of admin scripts and css + * + * This method is called by an add_action() hook setup in the contructor. + * + * (no prameters) + * + * @return void + * @access public + */ + public function glmMembersAdminScripts () + { + wp_enqueue_media(); + wp_register_script('glm-members-admin-js', + GLM_MEMBERS_PLUGIN_URL . 'js/admin.js', array( + 'jquery' + )); + wp_enqueue_script('glm-members-admin-js'); + + // A simple set of styles for things I haven't found as a WordPress + // default yet + wp_register_style('glmMembersAdminStyle', + GLM_MEMBERS_PLUGIN_URL . 'css/admin.css'); + wp_enqueue_style('glmMembersAdminStyle'); + } + + /** + * Configure WordPress Menus for this Plugin + * + * This method is called by an add_action() hook setup in the contructor. We + * do it + * this way so that the menu related functions of WordPress are in scope + * when creating + * the additional menu items. WordPress will execute this call-back method + * when building + * its Dashboard menus. + * + * (no prameters) + * + * @return void + * @access public + */ + public function configureMenus () + { + + // Add a new main menu item for management and display of Members + add_menu_page('Members', 'Members', 'read', + 'glm-members-admin-menu-members', + array( + $this, + 'glmMembersAdminMenuMembers' + )); + + add_submenu_page('glm-members-admin-menu-members', + 'Configure Members Database', 'Configure', + 'glm_members_configure', 'glm-members-admin-menu-configure', + array( + $this, + 'glmMembersAdminMenuConfigure' + )); + } + + /* + * Menu item specific "Callback" methods + * + * These methods are called by WordPress when specific menu items are + * selected by the + * user or a form action is submitted associated with the menu item. + * + * These methods call the controller and pass it the menu item that was + * called + * but perform no other work. + * + */ + + // Main Plugin Menu Item + public function glmMembersAdminMenuMembers () + { + $this->controller('members'); + } + + // Add Sub Menu Items + public function glmMembersAdminMenuConfigure () + { + $this->controller('configure'); + } + + /** + * Admin controller + * + * This method is called by a plugin menu method. It is responsible for + * executing the approriate model, combining model data with a view, and + * outputing the result. It is therefore the core of the controller. + * + * This controller is supplied a menu item name and then determines if + * there is an additional action related to that menu item that needs to be + * executed rather than the default menu action. + * + * All models should return an array containing the following. + * + * 'status' + * + * True if successfull and false if there was a fatal failure. + * + * 'menuItemRedirect' + * + * If not false, provides a menu item the controller should + * execute after this one. Normally if this is used, there would also be a + * modelRedirect value supplied as well. + * + * 'modelRedirect' + * + * If not false, provides an action the controller should execute after + * this one. + * + * 'view' + * + * A suggested view name that the contoller should use instead of the + * default view for this model or false to indicate that the default view + * should be used. + * + * 'data' + * + * Data that the model is returning for use in merging with the view to + * produce output. + * + * For a better explanation of how this all works, see the description for + * this class. + * + * Controller parameters + * + * @param string $menuItem + * Name of the menu item that is being processed + * + * @return void + * @access public + */ + public function controller ($menuItem) + { + + /* + * Determine model to execute + */ + + // Default action is "index" + $action = 'index'; + + // Get any requested "action" from a form submission modify path/name + // accordingly + if (isset($_REQUEST['glm_action']) && $_REQUEST['glm_action'] != '') { + $a = sanitize_text_field($_REQUEST['glm_action']); + if ($a != '') { + $action = $a; + } + } + + // Loop as long as there's a model redirect. + do { + + // Verify Menu item and action using array at top of this file + if (! in_array($action, + $GLOBALS['glmMembersAdminValidActions'][$menuItem])) { + $menuItem = 'error'; + $action = 'badAction'; + } + + /* + * Execute the selected model + */ + + // Build model and path and class names and load the model + $modelName = GLM_MEMBERS_PLUGIN_DIR . '/models/admin/' . $menuItem . + '/' . $action . '.php'; + $className = 'GlmMembersAdmin_' . $menuItem . '_' . $action; + require_once ($modelName); + + // Instantiate the model and ask it to perform the work + $model = new $className($this->wpdb, $this->config); + $results = $model->modelAction(); + + // Check if there's been a model redirect request + $modelRedirect = false; + if ($results['modelRedirect']) { + + // Set the new model action + $action = $results['modelRedirect']; + + // Check if there's also a menu item change + if ($results['menuItemRedirect']) { + $menuItem = $results['menuItemRedirect']; + } + + $modelRedirect = true; + } + + // Loop again if there's a model redirect + } while ($modelRedirect); + + /* + * Check model results + */ + + // Get suggested view + $view = $results['view']; + + // If there's a general model failure use the error view + if (! $results['status']) { + $view = 'admin/error/index.html'; + } + + /* + * Merge data returned from the model with the selected view + */ + + // Load Smarty Template support + require (GLM_MEMBERS_PLUGIN_DIR . '/lib/smartyTemplateSupport.php'); + $smarty = new smartyTemplateSupport(); + + // Add data from model to Smarty template + if (is_array($results['data']) && count($results['data']) > 0) { + foreach ($results['data'] as $k => $d) { + $smarty->templateAssign($k, $d); + } + } + + // If view debug has been requested + if (GLM_MEMBERS_PLUGIN_ADMIN_DEBUG) { + + $x = $smarty->template->getTemplateVars(); + $templateVars = '
' . print_r($x, 1) . '
'; + glmMembersAdmin::addNotice($templateVars, 'Template Parameters'); + } + + // Generate output from model data and view + $smarty->template->display($view); + } +} + + diff --git a/controllers/front.php b/controllers/front.php new file mode 100644 index 00000000..73e63059 --- /dev/null +++ b/controllers/front.php @@ -0,0 +1,44 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @release admin.php,v 1.0 2014/10/31 19:31:47 cscott Exp $ + * @link http://dev.gaslightmedia.com/ + */ + +/* + * This class controls which models are use for front-end functionality + * of this plugin. + */ +class glmMembersFront +{ + + /** + * WordPress Database Object + * + * @var $wpdb + * @access public + */ + public $wpdb; + + public function __construct ($wpdb) + { + + // Save WordPress Database object + $this->wpdb = $wpdb; + + /* + * This plugin does not currently have front-end functionality + */ + } +} + +?> \ No newline at end of file diff --git a/css/admin.css b/css/admin.css new file mode 100644 index 00000000..28766467 --- /dev/null +++ b/css/admin.css @@ -0,0 +1,56 @@ +/* + + Gaslight Media Members Database Admin Styles + +*/ + +.glm-required { + color: red !important; +} + +.glm-error { + color: red; +} + +.glm-copyright { + text-align: center; + margin: 2em; +} + +/* Admin Area - General */ +#glm-admin-content-container { + border: 1px #ccc solid; + padding: 1em; + background-color: #fff; +} + +/* Admin Forms */ +.glm-form-bad-input { + background: #FFaBa9; +} +.glm-form-text-input { + width: 90%; +} +.glm-form-textarea { + width: 90%; +} + +/* Debug Window */ +#glm-debug-header { + font-weight: bold; + font-size: 1.3em; +} +#glm-debug-timestamp { + float: right; + font-weight: bold; + font-size: 1.3em; +} +.glm-debug-section-title { + weight: bold; +} +.glm-debug-section-body { + border: 1px black solid; + padding: 5px; + background-color: #eee; + font-size: .8em; +} diff --git a/deactivate.php b/deactivate.php new file mode 100644 index 00000000..0bb72bd1 --- /dev/null +++ b/deactivate.php @@ -0,0 +1,86 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @release admin.php,v 1.0 2014/10/31 19:31:47 cscott Exp $ + * @link http://dev.gaslightmedia.com/ + */ + +// Load glmPluginSupport class +require_once (GLM_MEMBERS_PLUGIN_DIR . '/classes/glmPluginSupport.php'); + +/* + * This class performs all necessary additional work when this + * plugin is deactivated. + */ +class glmMembersPluginDeactivate extends glmPluginSupport +{ + + /** + * WordPress Database Object + * + * @var $wpdb + * @access public + */ + public $wpdb; + + /* + * Constructor + * + * Performs all the work for this model + */ + public function __construct ($wpdb) + { + + // Make sure the current user has this capability + if (!current_user_can('activate_plugins')) { + die(); + } + + // Save WordPress Database object + $this->wpdb = $wpdb; + + // Remove user capabilties + // $this->removeRoleCapability('glm_members_edit'); + + + } + + /* + * Remove a role capability from all current roles + * + * @param string $capability + * + * @return void + * @access public + */ + public function removeRoleCapability ($capability) + { + // Get list of role objects + $roleObjects = $GLOBALS['wp_roles']->role_objects; + + // Get list of roles we can edit + $roles = get_editable_roles(); + + // For each role object + foreach ($roleObjects as $key => $role) { + // Check if the role exists in list of editable roles and capability + // does not exist + if (isset($roles[$key]) && isset($role->capabilities[$capability])) { + + // Remove role + $role->remove_cap($capability); + } + } + } +} + +?> \ No newline at end of file diff --git a/index.php b/index.php new file mode 100644 index 00000000..6eddbac7 --- /dev/null +++ b/index.php @@ -0,0 +1,338 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @version 1.0 + */ + +/* + * Copyright 2014 Charles Scott (email : cscott@gaslightmedia.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +/* + * + * Set standard parameters + * + */ + +// Debug Options +define('GLM_MEMBERS_PLUGIN_ADMIN_DEBUG', true); + +// Plugin Versions +define('GLM_MEMBERS_PLUGIN_VERSION', 0.1); +define('GLM_MEMBERS_PLUGIN_DB_VERSION', 0.1); + +// Other standard plugin defines +define('GLM_MEMBERS_PLUGIN_NAME', 'Gaslight Media Members Database'); +define('GLM_MEMBERS_PLUGIN_URL', plugin_dir_url(__FILE__)); +define('GLM_MEMBERS_PLUGIN_DIR', dirname(__FILE__)); +define('GLM_MEMBERS_PLUGIN_DB_SCRIPTS', dirname(__FILE__).'/misc/databaseScripts'); +define('GLM_MEMBERS_PLUGIN_CLASS_DIR', GLM_MEMBERS_PLUGIN_DIR.'/classes'); +define('GLM_MEMBERS_PLUGIN_LIB_DIR', GLM_MEMBERS_PLUGIN_DIR.'/lib'); + +// Database table prefixes +global $wpdb; +define('GLM_MEMBERS_PLUGIN_DB_PREFIX', $wpdb->prefix.'glm_members_'); + +// Try to set the DB version option to false (new plugin) - If it's already set this won't do anything. +add_option('glmMembersDatabaseDbVersion', false); + + +/** + * ******************************************************************************* + * + * *** Directory and File Structure *** + * + * index.php + * + * Index file for this plugin. All plugin processing starts here. (See + * "Process Flow" below.) + * + * controllers + * + * Directory containing any controllers. Typically there + * would be admin and front controllers in this directory. + * These controllers do the general setup for the plugin, + * determine and call the appropriate model, determine the + * appropriate view, then merge any data returned by the model + * with the view and output the result as appropriate. + * + * When executed, a model may determine that it cannot handle + * the current request and return such a notice to the controller + * possibly with a suggested model to execute. Models may also + * return a desired view back to the controller based on the + * result of processing, but should do so in a generic way so + * as to permit multi-lingual output and use of multiple "skins" + * (but not to the exception of appropriate use of WordPress + * Themes). + * + * css + * + * Directory containing any css files specific to this plugin. + * The use of additional styling should be kept to a minimum + * so as to not interfere with the application of WordPress + * default styling and Themes. + * + * js + * + * Directory containing any JAVAscript files specific to this + * Plugin. This directory should be reserved for general script + * files that provide functionality that can be used in various + * views. Any JAVAscript that is specific to a view should be + * located along with the associated view as it is logically + * part of the view. + * + * lib + * + * Directory containing any class or function libraries that + * are used generally by this plugin. Any class or other code + * that is specific to a particular model should be located + * in, or along with, that model since it is logically + * associated only with that model. + * + * misc + * + * Directory containing ancillary directories and files. This + * might be used for things like cach directories. An example + * might be the "smarty" directory for Smaarty Templates. + * + * models + * + * Directory containing model files that execute a specific + * process in this plugin. If this is a simple plugin, then + * the model files can be placed directly in this directory. + * If it's a more complex plugin, then there should be sub- + * directories for various groupings of related model files. + * + * An individual model may consist of a grouping of files, + * such as additional class files, that are specific only to + * that model. In that case, these should be located in a + * subdirectory under where the model file called by the + * controller is located and that directory should be named + * so as to be obviously associated with that model. + * + * There are three special files in the models directory. These + * are activate.php, deactivate.php, and uninstall.php. These + * are called via hooks setup in this file and should always + * be here. If they do not provide any real functionality, they + * should at least be a shell that can be called for those + * situations. + * + * views + * + * Directory containing view files for producing output upon + * request of a model file in the models directory. If this + * is a simply plugin, then the view files can be placed + * directly in this directory. If it's a more complex plugin, + * then there should be sub-directories for the various + * groupings of related view files. If using sub-directories, + * those should generally match the associated model directories. + * It may also be wise to use separate front and admin + * directories under views to keep things organized. + * + * Additionally, views may be grouped in such a way that they + * support the selection of various "skins" that output in + * different ways, although any styling should be provided by + * WordPress Themes or use default WordPress styling. + * + * *** Process Flow *** + * + * WordPress calls the plugin index file. All plugin processing starts here. + * + * The plugin index file performs the following operations ... + * - Sets-up any required plugin-wide defines and data + * - Instatiates any plugin-wide classes and objects + * - Sets-up any plugin-wide WordPress hooks + * - Determines which controller is to be executed + * - Executes the selected controller + * + * The selected controller performs the following operations ... + * - Sets-up any controller specific defines and data + * - Instatiates any controller specific classes and objects + * - Sets-up any controller specific WordPress hooks + * - Determines which model process is to be executed + * - Executes the selected model + * + * The selected model performs the following operations ... + * - Sets-up any model specific defines and data + * - Instatiates any model specific classes and objects + * - Sets-up any model specific WordPress hooks + * - Performs any specific processing required of the model + * - Determines which view is to be used to generate output + * - Generates output based on model data and the selected view + * + * WordPress wraps everything up + * + * ******************************************************************************** + */ + +// Get plugin configuration +//** not written yet +$config = false; // Temporary till written + +// Custom plugin post type (for wp_post entries) +// define('GLM_MEMBERS_PLUGIN_POST_TYPE', ''); + +/* + * + * Activate, Deactivate, Uninstall hooks + * + */ + +// Activate +function glmMembersPluginActivate () +{ + global $wpdb; + require_once (GLM_MEMBERS_PLUGIN_DIR . '/activate.php'); + new glmMembersPluginActivate($wpdb); +} +register_activation_hook(__FILE__, 'glmMembersPluginActivate'); + +// Deactivate +function glmMembersPluginDeactivate () +{ + global $wpdb; + require_once (GLM_MEMBERS_PLUGIN_DIR . '/deactivate.php'); + $x = new glmMembersPluginDeactivate($wpdb); + return false; +} +register_deactivation_hook(__FILE__, 'glmMembersPluginDeactivate'); + +// Uninstall - Not using. Using "uninstall.php" in the root directory of this plugin. + +/* + * + * Load any other common files needed + * + */ + +// Load data abstract +require_once(GLM_MEMBERS_PLUGIN_LIB_DIR.'/GlmDataAbstract/DataAbstract.php'); + +/* + * + * Determine which controller to load + * + * The first is for displaying notices in another window, possibly for debug output. + * + */ +if (isset($_REQUEST['glmDebugWindow']) && $_REQUEST['glmDebugWindow'] == true) { + glmMembersAdminNotices(true); + exit; +} elseif (is_admin()) { + require_once (GLM_MEMBERS_PLUGIN_DIR . '/controllers/admin.php'); + new glmMembersAdmin($wpdb, $config); +} else { + require_once (GLM_MEMBERS_PLUGIN_DIR . '/controllers/front.php'); + new glmMembersFront($wpdb, $config); +} + + +/* + * Function to display admin notices. + * + * This function is only called using the add_action('admin_notices','...') function + * in the code below this function. + * + * @return void + * @access public + */ +function glmMembersAdminNotices($windowed = false) +{ + + $output = ''; + + // If windowed, also include HTML header and stylesheet + if ($windowed) { + $output .= ' + + + + + +
'.date('m/d/Y G:i:s A').'
+
'.GLM_MEMBERS_PLUGIN_NAME.' - Debug Data
+ '; + } + + // Start with div class to output in standard admin notice block + $output .= '

'; + + // Get the notice texts + $notices = get_option('glmMembersAdminNotices'); + + if (is_array($notices) && count($notices) > 0) { + + // For each notice retrieved + $br = ''; + foreach($notices as $n) { + + // Add the notice to the output + $output .= $br.$n; + $br = '
'; + } + + } + + // Output the notices + $output .= '

'; + + + // If windowed, also include HTML header and stylesheet + if ($windowed) { + $output .= ' + + + '; + } + + echo $output; + + // Delete the option containing the notices to indicate they have been sent + delete_option('glmMembersAdminNotices'); + +} +// Check if there's admin notices for output +$notices = get_option('glmMembersAdminNotices'); +if (is_admin() && $notices) { + // Add action to output the notices + add_action('admin_notices','glmMembersAdminNotices'); +} + + + + + + +?> \ No newline at end of file diff --git a/js/admin.js b/js/admin.js new file mode 100644 index 00000000..5c614efb --- /dev/null +++ b/js/admin.js @@ -0,0 +1,40 @@ + +// Use media uploaded for all file/image uploads +jQuery(document).ready(function($){ + + var custom_uploader; + + $('.glm-protp-upload-button').click(function(e) { + + e.preventDefault(); + + var id = $(this).attr('data-id'); + + //If the uploader object has already been created, reopen the dialog + if (custom_uploader) { + custom_uploader.open(); + return; + } + + //Extend the wp.media object + var custom_uploader = wp.media.frames.file_frame = wp.media({ + title: 'Choose the desired image below or select "Upload Files" to select a new image.', + button: { + text: 'Choose Image' + }, + multiple: false + }); + + //When a file is selected, grab the URL and set it as the text field's value + custom_uploader.on('select', function() { + attachment = custom_uploader.state().get('selection').first().toJSON(); + $('#' + id).val(attachment.url); + }); + + //Open the uploader dialog + custom_uploader.open(); + + }); + + +}); \ No newline at end of file diff --git a/lib/EasyPassword/EasyPassword.php b/lib/EasyPassword/EasyPassword.php new file mode 100644 index 00000000..d4e19dc9 --- /dev/null +++ b/lib/EasyPassword/EasyPassword.php @@ -0,0 +1,42 @@ + +* Released under the terms of the GNU General Public License +* Based in part on Script released by: Jochen Kupperschmidt +* +* This is a highly modified version of this password generator for this application only. +* For original code please refer to original author. +*/ + + +class EasyPassword +{ + + // Get a random dictionary word from a text file + function dictionaryWord() { + $path = 'EasyPassword.words'; + $fileload = @file($path); + $i = count($fileload)-1; + $random = rtrim($fileload[rand(0,$i)]); + return $random; + } + + // This is the function to produce the password + function generateEasyPassword() + { + $word1 = $this->dictionaryWord(); + $numb = rand(1, 9); // Generate specified amount of numbers + $word2 = $this->dictionaryWord(); + + $keys = array ($word1,$numb,$word2); // Place password components in an array + $rand_keys = array_rand($keys,3); // Randomize the 3 password components + return $keys[$rand_keys[0]].$keys[$rand_keys[1]].$keys[$rand_keys[2]]; // Return the resulting password + } + + +} + + +?> \ No newline at end of file diff --git a/lib/EasyPassword/EasyPassword.words b/lib/EasyPassword/EasyPassword.words new file mode 100644 index 00000000..f03284cd --- /dev/null +++ b/lib/EasyPassword/EasyPassword.words @@ -0,0 +1,828 @@ +able +ABLE +about +account +acid +across +act +addition +after +again +against +agreement +air +all +almost +among +amount +amusement +and +angle +angry +animal +answer +ant +any +apparatus +apple +approval +arch +argument +arm +army +art +as +at +attack +attempt +attention +authority +automatic +awake +baby +back +bad +bag +balance +ball +band +base +basin +basket +bath +be +beautiful +because +bed +bee +before +behaviour +belief +bell +bent +berry +between +bird +birth +bit +black +blade +blood +blow +blue +board +boat +body +boiling +book +boot +bottle +box +boy +brain +brake +branch +brass +bread +breath +brick +bridge +bright +broken +brother +brown +brush +bucket +building +bulb +burn +burst +business +butter +button +by +cake +camera +canvas +card +care +carriage +cart +cat +cause +certain +chain +chalk +chance +change +cheap +cheese +chemical +chest +chief +chin +church +circle +clean +clear +clock +cloth +cloud +coal +coat +cold +collar +colour +comb +come +comfort +committee +common +company +comparison +complete +complex +condition +connection +conscious +control +cook +copper +copy +cord +cork +cotton +cough +country +cover +cow +crack +credit +crime +cruel +crush +cry +cup +cup +current +curtain +curve +cushion +damage +danger +dark +daughter +day +dead +dear +death +debt +decision +deep +degree +delicate +dependent +design +desire +destruction +detail +development +different +digestion +direction +dirty +discovery +discussion +disease +disgust +distance +division +do +dog +door +doubt +down +drain +drawer +dress +drink +driving +drop +dry +dust +ear +early +earth +east +edge +education +effect +egg +elastic +electric +end +engine +enough +equal +error +even +event +ever +every +example +exchange +existence +expansion +experience +expert +eye +face +fact +fall +false +family +far +farm +fat +father +fear +feather +feeble +feeling +female +fertile +fiction +field +fight +finger +fire +first +fish +fixed +flag +flame +flat +flight +floor +flower +fly +fold +food +foolish +foot +for +force +fork +form +forward +fowl +frame +free +frequent +friend +from +front +fruit +full +future +garden +general +get +girl +give +glass +glove +go +goat +gold +good +government +grain +grass +great +green +grey +grip +group +growth +guide +gun +hair +hammer +hand +hanging +happy +harbour +hard +harmony +hat +hate +have +he +healthy +hear +hearing +heart +heat +help +high +history +hole +hollow +hook +hope +horn +horse +hospital +hour +house +how +humour +ice +idea +if +ill +important +impulse +in +increase +industry +ink +insect +instrument +insurance +interest +invention +iron +island +jelly +jewel +join +journey +judge +jump +keep +kettle +key +kick +kind +kiss +knee +knife +knot +knowledge +land +language +last +late +laugh +law +lead +leaf +learning +left +leg +let +letter +level +library +lift +light +like +limit +line +linen +lip +liquid +list +little +living +lock +long +look +loose +loss +loud +love +low +machine +make +male +man +manager +map +mark +market +married +mass +match +material +may +meal +measure +meat +medical +meeting +memory +metal +middle +military +milk +mind +mine +minute +mist +mixed +money +monkey +month +moon +morning +mother +motion +mountain +mouth +move +much +muscle +music +nail +name +narrow +nation +natural +near +necessary +neck +need +needle +nerve +net +new +news +night +no +noise +normal +north +nose +not +note +now +number +nut +of +off +offer +office +oil +old +on +only +open +operation +opinion +opposite +or +orange +order +ornament +other +out +oven +over +owner +page +pain +paint +paper +parallel +parcel +part +past +paste +payment +peace +pen +pencil +person +physical +picture +pig +pin +pipe +place +plane +plant +plate +play +please +pleasure +plough +pocket +point +poison +polish +political +poor +porter +position +possible +pot +potato +powder +power +present +price +print +prison +private +probable +process +produce +profit +property +prose +protest +public +pull +pump +purpose +push +put +quality +question +quick +quiet +quite +rail +rain +range +rat +rate +ray +reaction +reading +ready +reason +receipt +record +red +regret +regular +relation +request +respect +rest +reward +rhythm +rice +right +ring +river +road +rod +roll +roof +room +root +rough +round +rub +rule +run +safe +sail +salt +same +sand +say +scale +school +science +scissors +screw +sea +seat +second +secret +see +seed +seem +self +send +sense +separate +serious +servant +sex +shade +shake +shame +sharp +sheep +shelf +ship +shirt +shock +shoe +short +shut +side +sign +silk +silver +simple +sister +size +skin +skirt +sky +sleep +slip +slope +slow +small +smash +smell +smile +smoke +smooth +snake +sneeze +snow +so +soap +society +sock +soft +solid +some + +son +song +sort +sound +soup +south +space +spade +special +sponge +spoon +spring +square +stage +stamp +star +start +statement +station +steam +steel +stem +step +stick +sticky +stiff +still +stitch +stocking +stomach +stone +stop +store +story +straight +strange +street +stretch +strong +structure +such +sudden +sugar +summer +sun +support +surprise +sweet +swim +system +table +tail +take +talk +tall +taste +tax +teaching +tendency +test +than +that +the +then +theory +there +thick +thin +thing +this +thought +thread +throat +through +through +thumb +thunder +ticket +tight +till +time +tin +tired +to +toe +together +tomorrow +tongue +tooth +top +touch +town +trade +train +transport +tray +tree +trick +trouble +trousers +true +turn +twist +umbrella +under +unit +up +use +value +verse +very +vessel +view +violent +voice +waiting +walk +wall +war +warm +wash +waste +watch +water +wave +wax +way +weather +week +weight +well +west +wet +wheel +when +where +while +whip +whistle +white +who +why +wide +will +wind +window +wine +wing +winter +wire +wise +with +woman +wood +wool +word +work +worm +wound +writing +wrong +year +yellow +yes +yesterday +you +young diff --git a/lib/GeoCalculations.php b/lib/GeoCalculations.php new file mode 100644 index 00000000..bd432651 --- /dev/null +++ b/lib/GeoCalculations.php @@ -0,0 +1,253 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @release SVN: $Id: GeoCalculations.php,v 1.0 2011/01/25 19:31:47 cscott Exp $ + * @link http://housing.gaslightmedia.com/admin/ + */ + +/** + * Geographic Calculations Support + * + * PHP version 5 + * + * @category Support_Services + * @package EventManagement + * @author Chuck Scott + * @license http://www.gaslightmedia.com Gaslightmedia + * @release SVN: $Id: GeoCalculations.php,v 1.0 2011/01/25 19:31:47 cscott Exp $ + * @link http://housing.gaslightmedia.com/admin/ + */ +class EventManagementGeoCalculations +{ + /** + * Database Object + * @var $dbh + * @access public + */ + protected $dbh; + + /** + * Constructor + * + * @param object $d database connection + * + * @return void + * @access public + */ + public function __construct($dbh) + { + $this->dbh = $dbh; + } + + + /* + * Get distance from event for an array of member locations - $sort = true to sort by distance + * + * This method caches the results in the event_prop_dist table and will refer first to that table. + * If there's no entry in that table, the method will get the distance information from Google + * and add it to the cache. + * + */ + function getMemberEventDistance( + $eventID, $members, + $member_lat_field = 'lat', $member_lon_field = 'lon', + $distance_field = 'distance', + $duration_field = 'duration', + $member_id_field = 'id', + $sort = false + ) + { + + // Check for valid Event ID and members table + if (($eventID-0) == 0 || !is_array($members) || count($members) == 0) { + return false; + } + + // Get Event location + $sql = "SELECT name, event_code, lat, lon + FROM eventmgt.event + WHERE id = $eventID;"; + $stmt = $this->dbh->prepare($sql); + $stmt->execute(); + $event_data = $stmt->fetch(PDO::FETCH_ASSOC); + + // Did we get event data + if (!event_data) { + return false; + } + + // Get numeric lat and lon and check if they exist (assume no 0 valuse) + $event_lat = ($event_data['lat'] - 0); + $event_lon = ($event_data['lon'] - 0); + if ($event_lat == 0 || $event_lon == 0) { + return false; + } + + $distances = array(); + $over_query_limit = false; + + while (list($k, $m) = each($members)) { + + $members[$k][$distance_field] = false; + $members[$k][$duration_field] = false; + $members[$k]['member_id_sort_field'] = $m[$member_id_field]; + + // Initialize distance response array entry for this member + $distances[$m[$member_id_field]] = array( + 'id' => $m[$member_id_field], + 'distance' => false + ); + + // If we have lat/lon for this member + $have_latlon = false; + if ($event_lat != 0 && $event_lon != 0 && $m[$member_lat_field] != 0 && $m[$member_lon_field] != 0) { + + $have_latlon = 'YES'; + $have_distance = 'NO'; + $distance = false; + $duration = false; + + // Check for entry in distance cache table + $sql = " + SELECT * + FROM eventmgt.event_prop_dist + WHERE event = $eventID + AND event_lat = $event_lat + AND event_lon = $event_lon + AND member = ".$m[$member_id_field]." + AND memb_lat = ".$m[$member_lat_field]." + AND memb_lon = ".$m[$member_lon_field]." + "; + $stmt = $this->dbh->prepare($sql); + $stmt->execute(); + $dist_data = $stmt->fetch(PDO::FETCH_ASSOC); + if ($dist_data != false && count($dist_data) > 0) { + $distance = $dist_data['distance']; + $duration = $dist_data['duration']; + $have_distance = 'YES'; + } + + // If we don't have distance from the cache and we're not over limit + if ($have_distance == 'NO' && !$over_query_limit) { + + // Request distance from event from Google + $map_request = 'http://maps.googleapis.com/maps/api/directions/xml?' + .'origin='.$m[$member_lat_field].','.$m[$member_lon_field] + .'&destination='.$event_lat + .','.$event_lon + .'&sensor=false&mode=driving'; + + $ch = curl_init(); + $curlOptions = array( + CURLOPT_URL => $map_request, + CURLOPT_HEADER => 0, + CURLOPT_RETURNTRANSFER => 1, + CURLOPT_FAILONERROR => 1 + ); + curl_setopt_array($ch, $curlOptions); + $response = curl_exec($ch); + curl_close($ch); + + if (strstr($response, 'OVER_QUERY_LIMIT')) { + $over_query_limit = true; + } else { + + // if we got a distance and time, then use that + if ($response) { + + $xml = new SimpleXMLElement($response); + if ($xml) { + $summary = addslashes((string) $xml->route[0]->summary); + $distance = (string) $xml->route[0]->leg[0]->distance->text; + $duration = (string) $xml->route[0]->leg[0]->duration->text; + $start_addr = addslashes((string) $xml->route[0]->leg[0]->start_address); + $end_addr = addslashes((string) $xml->route[0]->leg[0]->end_address); + $have_distance = 'YES'; + + // Delete any previous entry for this member/event + $sql = " + DELETE FROM eventmgt.event_prop_dist + WHERE event = $eventID + AND member = ".$m[$member_id_field]." + ;"; + $stmt = $this->dbh->prepare($sql); + $stmt->execute(); + + // Add this result to the event_prop_dist table + $sql = " + INSERT INTO eventmgt.event_prop_dist + ( + event, event_lat, event_lon, + member, memb_lat, memb_lon, + summary, start_addr, end_addr, + distance, duration + ) + VALUES + ( + $eventID, $event_lat, $event_lon, + ".$m[$member_id_field].", ".$m[$member_lat_field].", ".$m[$member_lon_field].", + '$summary', '$start_addr', '$end_addr', + '$distance', '$duration' + ); + "; + $stmt = $this->dbh->prepare($sql); + $stmt->execute(); + + } // If the response contained XML + } // If we got a response from Google + } // If we're not over limit + + } // If we don't have chached distance + } // If we have lat/lon + + $members[$k][$distance_field] = $distance; + $members[$k]['geo_distance_value'] = (0.0 + $distance); + $members[$k][$duration_field] = $duration; + $members[$k]['geo_duration_value'] = (0.0 + $duration); + + } // For each member + + if ($sort) { + + + uasort($members, 'distCmp'); + + } + + return $members; + } +} + + +// Comparison function to sort by distance - Needs to be declared outside of the class (Yuck!) +function distCmp($a, $b) { + + $adist = $a['geo_distance_value']; + $bdist = $b['geo_distance_value']; + + if ($adist == $bdist) { + + // distance is the same, so sub-sort by member_id to keep things consistent + $amemb = $a['member_id_sort_field']; + $bmemb = $b['member_id_sort_field']; + + if ($amemb == $bmemb) { + return 0; + } + + return ($amemb < $bmemb) ? -1 : 1; + } + return ($adist < $bdist) ? -1 : 1; +} + + + +?> \ No newline at end of file diff --git a/lib/GlmDataAbstract/DataAbstract.php b/lib/GlmDataAbstract/DataAbstract.php new file mode 100755 index 00000000..c975706c --- /dev/null +++ b/lib/GlmDataAbstract/DataAbstract.php @@ -0,0 +1,2935 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @release SVN: $Id: dataMembers.php,v 1.0 2011/01/25 19:31:47 cscott Exp $ + */ + +/** + * DataAbstract + * + * Database Abstract for data storage, retrieval, input, and output + * + * @category glmWordPressPlugin + * @package glmMembersDatabase + * @author Chuck Scott + * @copyright 2013 Gaslight Media + * @license Gaslight Media + * @release Release: (0.1) + * @link <> + */ + +abstract class GlmDataAbstract +{ + /** + * Configuration information object + * @var $ini + * @access public + */ + protected $config; + /** + * Wordpress Database Object + * @var $wpdb + * @access public + */ + protected $wpdb; + /** + * Field definitions + * + * @var $ini + * @access public + */ + public $table; + /** + * Array of field specifications + * This is specified for each table in the "data{table}.php" file + * + * @var $fields + * @access public + */ + public $fields; + /** + * Array of field data for use by templates + * + * @var $fieldData + * @access public + */ + public $fieldData; + /** + * String of field names for SELECT statement + * + * @var $select + * @access public + */ + public $select; + /** + * Array of known field types + * + * @access public + */ + public $knownFieldTypes = array( + 'integer', + 'float', + 'money', + 'percent', + 'pointer', + 'list', + 'bitmap', + 'text', + 'password', + 'checkbox', + 'email', + 'date', + 'time', + 'phone', + 'image', + 'latitude', + 'longitude' + ); + /** + * Explanation of input error reason + * + * @access public + */ + public $inputErrorReason = false; + /** + * Status of last input field checked - false indicates problem + * + * @access public + */ + public $inputFieldStatus = false; + /** + * Processing Options + * + * @access public + */ + public $optionIncludeSelectListData = true; + + /** + * Constructor + * + * @param object $d database connection + * + * @return void + * @access public + */ + public function __construct($wpdb, $config) + { + + $this->wpdb = $wpdb; + $this->config = $config; + + } + + /** + * Field processing for various field types + * + * @var $f is field data + * + * @return void + * @access public + */ + + // Integer Field Processing + function integerField($f) + { + return 'T.'.$f['field']; + } + function integerOptions($f) + { + return false; + } + function integerOutput($f, $d) + { + return $d; + } + function integerInput($as, $f, $id, $idfield, $op) + { + // If this is setup for a new entry, then just return default value + if ($op == 'n') { + $in = '0'; + if (isset($f['default'])) { + $in = ($f['default']); + } + return $in; + } + + $this->inputFieldStatus = true; + + $in = $_REQUEST[$as]; + + // Check for required field + if ($f['required'] && trim($in) == '') { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Required input not provided.'; + return $in; + } + + if (trim($in) != '' && !is_numeric($in)) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Input is not numeric.'; + return $in; + } + + // Make darn'd sure it's numeric + $in = ($in - 0); + + // Check min/max limits + if ($f['minValue'] && $in < $f['minValue']) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Input is less than the minimum permitted value of '.$f['minValue'].'.'; + return $in; + } + if ($f['maxValue'] && $in > $f['maxValue']) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Input is greater than the maximum permitted value of '.$f['maxValue'].'.'; + return $in; + + } + + // If the field validated and it's supposed to be unique + if ($this->inputFieldStatus && isset($f['unique']) && $f['unique']) { + + // Query table to see if there's a conflict + $sql = " + SELECT COUNT(" + .$f['field'].") + FROM " + .$this->table." + WHERE " + .$f['field']." = $in; + "; + + // If there's an ID field, then this must be an update rather than an insert + if ($id != false && $idField != false) { + // Add clause to check if not the current record + $sql .= "AND $idField != $id"; + } + + $d = $this->wpdb->get_results($sql, ARRAY_A); + + if ($d['count'] > 0) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'This must unique but it conflicts with another entry.'; + return $in; + } + } + + return $in; + } + function integerStore($in, $f) + { + return $in; + } + + /* + * Float Field Processing + */ + function floatField($f) + { + return 'T.'.$f['field']; + } + function floatOptions($f) + { + return false; + } + function floatOutput($f, $d) + { + // if a format is specified + if ($f['output_format']) { + $d = sprintf('%'.$f['output_format'].'f', ($d - 0)); + } + + return $d; + } + function floatInput($as, $f, $id, $idfield, $op) + { + // If this is setup for a new entry, then just return default value + if ($op == 'n') { + $in = '0.0'; + if (isset($f['default'])) { + $in = ($f['default']); + } + + // if a format is specified + if ($f['output_format']) { + $in = sprintf('%'.$f['output_format'].'f', ($in - 0)); + } + + return $in; + } + + $this->inputFieldStatus = true; + + $in = $_REQUEST[$as]; + + // Check for required field + if ($f['required'] && trim($in) == '') { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Required input not provided.'; + return $in; + } + + if (!is_numeric($in)) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Input is not numeric.'; + return $in; + } + + // Make darn'd sure it's numeric + $in = $in - 0; + + // Check min/max limits + if ($f['minValue'] && $in < $f['minValue']) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Input is less than the minimum permitted value of '.$f['minValue'].'.'; + return $in; + } + if ($f['maxValue'] && $in > $f['maxValue']) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Input is greater than the maximum permitted value of '.$f['maxValue'].'.'; + return $in; + } + + // If the field validated and it's supposed to be unique + if ($this->inputFieldStatus && isset($f['unique']) && $f['unique']) { + + // Query table to see if there's a conflict + $sql = " + SELECT COUNT(" + .$f['field'].") + FROM " + .$this->table." + WHERE " + .$f['field']." = $in; + "; + + // If there's an ID field, then this must be an update rather than an insert + if ($id != false && $idField != false) { + // Add clause to check if not the current record + $sql .= "AND $idField != $id"; + } + + $d = $this->wpdb->get_results($sql, ARRAY_A); + + if ($d['count'] > 0) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'This must unique but it conflicts with another entry.'; + return $in; + } + } + + // if a format is specified + if ($f['output_format']) { + $in = sprintf('%'.$f['output_format'].'f', ($in - 0)); + } + + return $in; + } + function floatStore($in, $f) + { + return $in; + } + + /* + * Money Field Processing + */ + function moneyField($f) + { + return 'T.'.$f['field']; + } + function moneyOptions($f) + { + return false; + } + function moneyOutput($f, $d) + { + return "$".sprintf("%01.2f", $d); + ; + } + function moneyInput($as, $f, $id, $idfield, $op) + { + // If this is setup for a new entry, then just return default value + if ($op == 'n') { + $in = '0.00'; + if (isset($f['default'])) { + $in = ($f['default']); + } + return $in; + } + + $this->inputFieldStatus = true; + + $in = $_REQUEST[$as]; + + // Check for required field + if ($f['required'] && trim($in) == '') { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Required input not provided.'; + return $in; + } + + // Strip any $ signs + $in = str_replace('$', '', $in); + + if (!is_numeric($in)) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Input is not numeric.'; + return $in; + } + + // Make darn'd sure it's numeric + $in = $in - 0; + + // Check min/max limits + if ($f['minValue'] && $in < $f['minValue']) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Input is less than the minimum permitted value of '.$f['minValue'].'.'; + return $in; + } + + if ($f['maxValue'] && $in > $f['maxValue']) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Input is greater than the maximum permitted value of '.$f['maxValue'].'.'; + return $in; + } + + // If the field validated and it's supposed to be unique + if ($this->inputFieldStatus && isset($f['unique']) && $f['unique']) { + + // Query table to see if there's a conflict + $sql = " + SELECT COUNT(" + .$f['field'].") + FROM " + .$this->table." + WHERE " + .$f['field']." = $in; + "; + + // If there's an ID field, then this must be an update rather than an insert + if ($id != false && $idField != false) { + // Add clause to check if not the current record + $sql .= "AND $idField != $id"; + } + + $d = $this->wpdb->get_results($sql, ARRAY_A); + + if ($d['count'] > 0) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'This must unique but it conflicts with another entry.'; + return $in; + } + } + + return $in; + } + function moneyStore($in, $f) + { + return $in; + } + + /* + * Percent Field Processing + */ + function percentField($f) + { + return 'T.'.$f['field']; + } + function percentOptions($f) + { + return false; + } + function percentOutput($f, $d) + { + return $d; + } + function percentInput($as, $f, $id, $idfield, $op) + { + // If this is setup for a new entry, then just return default value + if ($op == 'n') { + $in = '0.0'; + if (isset($f['default'])) { + $in = ($f['default']); + } + return $in; + } + + $this->inputFieldStatus = true; + + $in = $_REQUEST[$as]; + + // Check for required field + if ($f['required'] && trim($in) == '') { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Required input not provided.'; + return $in; + } + + // Strip any % signs + $in = str_replace('%', '', $in); + + if (!is_numeric($in)) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Input is not numeric.'; + return $in; + } + + // Make darn'd sure it's numeric + $in = $in - 0; + + // Check min/max limits + if ($f['minValue'] && $in < $f['minValue']) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Input is less than the minimum permitted value of '.$f['minValue'].'.'; + return $in; + } + + if ($f['maxValue'] && $in > $f['maxValue']) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Input is greater than the maximum permitted value of '.$f['maxValue'].'.'; + return $in; + } + + // If the field validated and it's supposed to be unique + if ($this->inputFieldStatus && isset($f['unique']) && $f['unique']) { + + // Query table to see if there's a conflict + $sql = " + SELECT COUNT(" + .$f['field'].") + FROM " + .$this->table." + WHERE " + .$f['field']." = $in; + "; + + // If there's an ID field, then this must be an update rather than an insert + if ($id != false && $idField != false) { + // Add clause to check if not the current record + $sql .= "AND $idField != $id"; + } + + $d = $this->wpdb->get_results($sql, ARRAY_A); + + if ($d['count'] > 0) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'This must unique but it conflicts with another entry.'; + return $in; + } + } + + return $in; + } + function percentStore($in, $f) + { + return $in; + } + + /* + * Pointer Field Processing + */ + function pointerField($f) + { + // Check if there's a specified WHERE clause + $where = $f['p_id']." = T.".$f['field']; + if ($f['p_where']) { + $where = $f['p_where']; + } + + // Check if there's an addional FROM tables + $from = ''; + if ($f['p_from']) { + $from = ', '.$f['p_from']; + } + + // Check if the results from this pointer is to be summed + $field_val = $f['p_field']; + if ($f['p_sum']) { + $field_val = 'COALESCE(sum('.$field_val.'), 0) '; + } + + $field = "( + SELECT ".$field_val." + FROM ".$f['p_table']." + $from + WHERE $where + ) "; + + return $field; + } + function pointerOptions($f) + { + $sql = " + SELECT " + .$f['p_id'].", ".$f['p_field']." + FROM " + .$f['p_table']." + ORDER BY " + .$f['p_field']."; + "; + $options = $this->wpdb->get_results($sql, ARRAY_A); + + return $options; + } + function pointerOutput($f, $d, $forEdit = false, $id = false, $idfield = 'id') + { + + // If the operation is Edit then we need to also get the options for select (unless it's p_static) + if ($forEdit && !($f['p_static'] === true)) { + + // Get current value of pointer + if ($id) { + $sql = " + SELECT ".$f['field']." AS id + FROM ".$this->table." + WHERE $idfield = $id + "; + $d = $this->wpdb->get_results($sql, ARRAY_A); + $p_value = $d['id']; + } + + // Get pointer options from specified table + $order_by = $f['p_field']; + if ($f['p_orderby']) { + $order_by = $f['p_orderby']; + } + + // Get picklist options from other table + $where = ''; + if ($f['p_where']) { + $where = 'WHERE '.$f['p_where']; + } + $sql = " + SELECT ".$f['p_id']." AS p_id, + ".$f['p_field']." AS p_value + FROM ".$f['p_table']." + $where + ORDER BY $order_by + "; + $p_list = $this->wpdb->get_results($sql, ARRAY_A); + + // Build pick select table + $pick_select = false; + $selected_name = ''; + $pick_list = array(); + + if ($f['p_blank']) { + $pick_list[0] = array( + 'value' => '', + 'name' => '(none selected)', + 'default' => ($p['p_id'] == '') + ); + } + + if (count($p_list) > 0) { + + reset($p_list); + foreach ($p_list as $p) { + + if ($this->optionIncludeSelectListData) { + $pick_list[$p['p_id']] = array( + 'value' => $p['p_id'], + 'name' => $p['p_value'], + 'nameEsc' => addslashes($p['p_value']), + 'default' => ($p['p_id'] == $p_value) + ); + } + + // Check for selected option + if ($p['p_id'] == $p_value) { + $selected_name = $p['p_value']; + } + + } + + } else { + + // There were no results from the + $this->inputFieldStatus = false; + $this->inputErrorReason = 'No options were available for this pick list.'; + + } + + $r = array( + 'value' => $p_value, + 'name' => $selected_name, + 'nameEsc' => addslashes($selected_name), + 'pick_list' => $pick_list + ); + + return $r; + + } + + return $d; + } + function pointerInput($as, $f, $id, $idfield, $op) + { + + $this->inputFieldStatus = true; + + // Get pointer options from specified table + $order_by = $f['p_field']; + if ($f['p_orderby']) { + $order_by = $f['p_orderby']; + } + + // Get picklist options from other table + $where = ''; + if ($f['p_where']) { + $where = 'WHERE '.$f['p_where']; + } + $sql = " + SELECT " + .$f['p_id']." AS p_id, + " + .$f['p_field']." AS p_value + FROM " + .$f['p_table']." + $where + ORDER BY $order_by + "; + $p_list = $this->wpdb->get_results($sql, ARRAY_A); + + // If this is not a "new", then do these things + if ($op != 'n') { + + // Pointers are treated as integers except that there's no min/max + + $in = $_REQUEST[$as]; + + // Check for required field + if ($f['required'] && trim($in) == '') { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Required input not provided.'; + // return $in; + } + + if ($in != '' && !is_numeric($in)) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Selected item is not valid.'; + // return $in; + } + + // Make darn'd sure it's numeric + $in = $in - 0; + + if (!is_int($in)) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Selected item is not valid.'; + return $in; + } + + } else { + + //check if there's a default value + $def = 0; + if (isset($f['default'])) { + $def = $f['default']-0; + } + + if ($def > 0) { + $in = $def; + } else { + $in = false; + } + } + + // Build pick select table + $pick_select = false; + $selected_name = ''; + if (count($p_list) > 0) { + + $pick_list = array(); + reset($p_list); + foreach ($p_list as $p) { + + $pick_list[$p['p_id']] = array( + 'value' => $p['p_id'], + 'name' => $p['p_value'], + 'nameEsc' => addslashes($p['p_value']), + 'default' => ($p['p_id'] == $in) + ); + + // when setting a default value, also set that as a selected name value + if ($p['p_id'] == $in) { + $selected_name = $p['p_value']; + } + + } + + } else { + + // Only worry about no options if the field is required. + if ($f['required']) { + // There were no results from the + $this->inputFieldStatus = false; + $this->inputErrorReason = 'No options were available for this pick list.'; + } + } + + // If this is not a "new", then do these things + if ($op != 'n') { + + // If the field validated and it's supposed to be unique + if ($this->inputFieldStatus && isset($f['unique']) && $f['unique']) { + + // Query table to see if there's a conflict + $sql = " + SELECT COUNT(" + .$f['field'].") + FROM " + .$this->table." + WHERE " + .$f['field']." = $in; + "; + + // If there's an ID field, then this must be an update rather than an insert + if ($id != false && $idField != false) { + // Add clause to check if not the current record + $sql .= "AND $idField != $id"; + } + + $d = $this->wpdb->get_results($sql, ARRAY_A); + + if ($d['count'] > 0) { + + $this->inputFieldStatus = false; + $this->inputErrorReason = 'This must unique but it conflicts with another entry.'; + // Don't exit here, need to fall throug to get pick array + } + } + + } // if $op + + $r = array( + 'value' => $in, + 'name' => $selected_name, + 'nameEsc' => addslashes($selected_name), + 'pick_list' => $pick_list + ); + + return $r; + } + function pointerStore($in, $f) + { + return $in['value']; + } + + /* + * List Field Processing + */ + function listField($f) + { + return 'T.'.$f['field']; + } + function listOptions($f) + { + return false; + } + function listOutput($f, $d, $forEdit, $id, $idfield, $op) + { + + // Check for a list data + if (!isset($f['list']) || !is_array($f['list'])) { + + echo "Field '".$f['name']."' is type list but does not have supplied 'list' data."; + exit; + } + + // Build list array + $list = array(); + while (list($k, $v) = each($f['list'])) { + $list[$k] = array( + 'name' => $v, + 'nameEsc' => addslashes($v), + 'value' => $k, + 'default' => false + ); + } + + // Set default or current value if there's one availale + $value = ''; + $name = ''; + if (isset($list[$d])) { + $list[$d]['default'] = true; + $value = $d; + $name = $list[$d]['name']; + } + + $r = array( + 'list' => $list, + 'value' => $value, + 'name' => $name, + 'nameEsc' => addslashes($name) + ); + + // if the list is not required, dump it now. (List, Get, Delete, Confirm delete) + if (in_array($op, array(l, g, d, c))) { + $r['list'] = false; + } + + return $r; + + } + function listInput($as, $f, $id, $idField, $op) + { + + // Check for a list data + if (!isset($f['list']) || !is_array($f['list'])) { + + echo "Field '".$f['name']."' is type list but does not have supplied 'list' data."; + exit; + } + + // Build list array + $list = array(); + while (list($k, $v) = each($f['list'])) { + $list[$k] = array( + 'name' => $v, + 'nameEsc' => addslashes($v), + 'value' => $k, + 'default' => false + ); + } + + // If this is setup for a new entry, then just return default value + if ($op == 'n') { + $in = ''; + if (isset($f['default'])) { + $in = ($f['default']); + } + + // Otherwise check for input data + } else { + + // Sanitize currently selected value + $in = filter_input(INPUT_POST, $as, FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES); + + // Is it one of the available values + if ($f['required'] && trim($in) == '') { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Required input is not provded.'; + } + + // Is it a valid value + if (trim($in) != '' && !isset($list[$in])) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Value selected is not valid.'; + } + + } + + // Set default or current value if there's one availale + $value = ''; + $name = ''; + if (isset($list[$in])) { + $list[$in]['default'] = true; + $value = $in; + $name = $list[$in]['name']; + } + + $r = array( + 'list' => $list, + 'value' => $value, + 'name' => $name, + 'nameEsc' => addslashes($name) + ); + + return $r; + } + function listStore($in, $f) + { + $keytype = 'text'; + + if (isset($f['list_keytype']) && $f['list_keytype'] == 'int') { + $keytype = 'int'; + } + + if ($keytype == 'text') { + $r = "'".addslashes($in['value'])."'"; + } else { + $v = ($in['value'] - 0); + $r = $v; + } + + return $r; + } + + /* + * Bitmap List Field Processing + */ + function bitmapField($f) + { + return 'T.'.$f['field']; + } + function bitmapOptions($f) + { + return false; + } + function bitmapOutput($f, $d) + { + // Check for a bitmap data + if (!isset($f['bitmap']) || !is_array($f['bitmap'])) { + echo "Field '".$f['name']."' is type bitmap but does not have supplied 'bitmap' data."; + exit; + } + + // Build bitmap array + $bitmap = array(); + $bitmapNames = array(); + while (list($k, $v) = each($f['bitmap'])) { + + $bitmap[$k] = array( + 'name' => $v, + 'nameEsc' => addslashes($v), + 'value' => $k, + 'default' => false + ); + + // Check if this option has been selected + $powVal = pow(2, $k); + if (($powVal & $d) > 0) { + $bitmap[$k]['default'] = true; + $bitmapNames[] = $v; + } + + } + + $r = array( + 'bitmap' => $bitmap, + 'value' => $d, + 'names' => $bitmapNames + ); + + return $r; + + } + function bitmapInput($as, $f, $id, $idField, $op) + { + + // Check for a bitmap data + if (!isset($f['bitmap']) || !is_array($f['bitmap'])) { + echo "Field '".$f['name']."' is type bitmap but does not have supplied 'bitmap' data."; + exit; + } + + // If this is setup for a new entry, then just use default + $in = 0; + if ($op == 'n' && isset($f['default'])) { + $in = $f['default']; + // Otherwise, create bitmap from input selection - multi-pick + } elseif (is_array($_REQUEST[$as]) && count($_REQUEST[$as]) > 0) { + foreach ($_REQUEST[$as] as $bit) { + // Make sure it's a number that's less than 32 - Using integer (32 bits?) + if ($bit == ($bit-0) && $bit < 32) { + $in += pow(2, $bit); + } + } + } + + // Build bitmap array + $bitmap = array(); + $bitmapNames = array(); + while (list($k, $v) = each($f['bitmap'])) { + $bitmap[$k] = array( + 'name' => $v, + 'nameEsc' => addslashes($v), + 'value' => $k, + 'default' => false + ); + + // Check if this option has been selected + $powVal = pow(2, $k); + if (($powVal & $in) > 0) { + $bitmap[$k]['default'] = true; + $bitmapNames[] = $v; + } + } + + $r = array( + 'bitmap' => $bitmap, + 'value' => $in, + 'names' => $bitmapNames + ); + + return $r; + } + function bitmapStore($in, $f) + { + $keytype = 'text'; + + if (isset($f['list_keytype']) && $f['list_keytype'] == 'int') { + $keytype = 'int'; + } + + if ($keytype == 'text') { + $r = "'".addslashes($in['value'])."'"; + } else { + $v = ($in['value'] - 0); + $r = $v; + } + + return $r; + } + + /* + * Text Field Processing + */ + function textField($f) + { + return 'T.'.$f['field']; + } + function textOptions($f) + { + return false; + } + function textOutput($f, $d) + { + return $d; + } + function textInput($as, $f, $id, $idField, $op) + { + // If this is setup for a new entry, then just return default value + if ($op == 'n') { + $in = ''; + if (isset($f['default'])) { + $in = ($f['default']); + } + return $in; + } + + $this->inputFieldStatus = true; + + // Set input filter or use specified filter - see PHP input_filter(); + $filter = FILTER_SANITIZE_STRING; + if (isset($f['filter'])) { + if (!is_numeric($f['filter'])) { + echo "

 

ERROR: Supplied value for option 'filter' in fields array is not a defined filter for PHP filter_input();"; + exit; + } + $filter = $f['filter']; + } + + // Set input filter options or use specified filter options - see PHP input_filter(); + $filter_options = 0; //FILTER_FLAG_NO_ENCODE_QUOTES; + if (isset($f['filter_options'])) { + if (!is_numeric($f['filter_options'])) { + echo "

 

ERROR: Supplied value for 'filter_options' is fields array not a defined filter option for PHP filter_input();"; + exit; + } + $filter_options = $f['filter_options']; + } + + $in = filter_input(INPUT_POST, $as, $filter, $filter_options); + + if ($f['required'] && trim($in) == '') { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Required input not provided.'; + return $in; + } + + // Check for required field + if ($f['required'] && trim($in) == '') { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Required input not provided.'; + return $in; + } + + // Check min/max length + if ($f['minLength'] && strlen($in) < $f['minLength']) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Input is shorter than minimum length of '.$f['minLength'].' characters.'; + return $in; + } + if ($f['maxLength'] && strlen($in) > $f['maxLength']) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Input is longer than maximum length of '.$f['maxLength'].' characters.'; + return $in; + } + + // If the field validated and it's supposed to be unique + if ($this->inputFieldStatus && isset($f['unique']) && $f['unique']) { + + // Query table to see if there's a conflict + $sql = " + SELECT COUNT(" + .$f['field'].") + FROM " + .$this->table." + WHERE " + .$f['field']." = '".addslashes($in)."' + "; + + // If there's an ID field, then this must be an update rather than an insert + if ($id != false && $idField != false) { + // Add clause to check if not the current record + $sql .= "AND $idField != $id"; + } + + $d = $this->wpdb->get_results($sql, ARRAY_A); + + if ($d['count'] > 0) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'This must be unique but it conflicts with another entry.'; + return $in; + } + } + + return $in; + } + function textStore($in, $f) + { + $r = "'".addslashes($in)."'"; + return $r; + } + + /* + * Password Field Processing + */ + function passwordField($f) + { + return 'T.'.$f['field']; + } + function passwordOptions($f) + { + return false; + } + function passwordOutput($f, $d) + { + // No output for a password field + return ''; + } + function passwordInput($as, $f, $id, $idField, $op) + { + // If this is setup for a new entry, then just return default value + if ($op == 'n') { + return ''; + } + + $this->inputFieldStatus = true; + + // No options for input filters or options + $filter = FILTER_SANITIZE_STRING; + $filter_options = FILTER_FLAG_NO_ENCODE_QUOTES; + + $in = filter_input(INPUT_POST, $as, $filter, $filter_options); + if ($f['required'] && trim($in) == '') { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Required input not provided.'; + return $in; + } + + // Check for required field + if ($f['required'] && trim($in) == '') { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Required input not provided.'; + return $in; + } + + // Check min/max length + if (trim($in) != '' && $f['minLength'] && strlen($in) < $f['minLength']) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Input is shorter than minimum length of '.$f['minLength'].' characters.'; + return $in; + } + if (trim($in) != '' && $f['maxLength'] && strlen($in) > $f['maxLength']) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Input is longer than maximum length of '.$f['maxLength'].' characters.'; + return $in; + } + + // Check type of password + if (trim($in) != '' && isset($f['pw_type'])) { + $typeOK = true; + $pwReason = ''; + $sep = ''; + switch ($f['pw_type']) { + case 'strong': + if (!preg_match("/[0-9]+/", $in)) { + $pwReason .= "Password must include at least one number!"; + $typeOK = false; + $sep = "
"; + } + if (!preg_match("/[a-zA-Z]+/", $in)) { + $pwReason .= $sep."Password must include at least one letter!"; + $typeOK = false; + $sep = "
"; + } + if (!preg_match("/[\#\.\-\_\,\$\%\&\!]+/", $in)) { + $pwReason .= $sep."Password must include at least one of these characters!
   # . - _ , $ % & !"; + $typeOK = false; + } + break; + default: + break; + } + + if (!$typeOK) { + $this->inputFieldStatus = false; + $this->inputErrorReason = $pwReason; + return $in; + } + } + + // Don't try to crypt a blank password + $c = ''; + if ($in != '') { + $c = crypt($in); + } + + return $c; + } + function passwordStore($in, $f) + { + $r = "'".addslashes($in)."'"; + return $r; + } + + /* + * Checkbox Field Processing + */ + function checkboxField($f) + { + return 'T.'.$f['field']; + } + function checkboxOptions($f) + { + return false; + } + function checkboxOutput($f, $d) + { + $list = array( + 0 => array( + 'name' => 'Yes', + 'value' => 1, + 'default' => false + ), + 1 => array( + 'name' => 'No', + 'value' => 0, + 'default' => false + ), + ); + + if ($d) { + $list[0]['default'] = true; + $name = 'Yes'; + } else { + $list[1]['default'] = true; + $name = 'No'; + } + + if (!$this->optionIncludeSelectListData) { + $list = false; + } + + $r = array( + 'list' => $list, + 'value' => $d, + 'name' => $name + ); + + return $r; + } + function checkboxInput($as, $f, $x, $y, $op) + { + $list = array( + 0 => array( + 'name' => 'Yes', + 'value' => 1, + 'default' => false + ), + 1 => array( + 'name' => 'No', + 'value' => 0, + 'default' => false + ), + ); + + // If this is setup for a new entry, then just return default value + if ($op == 'n') { + $in = false; + if (isset($f['default'])) { + $in = ($f['default']); + } + + // Otherwise get input + } else { + $valid = array(1, true, 'on', 'yes'); + + $this->inputFieldStatus = true; + $in = false; + if (in_array($_REQUEST[$as], $valid)) { + $in = true; + } + + } + + // Set picklist default + if ($in) { + $list[0]['default'] = true; + $name = 'Yes'; + } else { + $list[1]['default'] = true; + $name = 'No'; + } + + $r = array( + 'list' => $list, + 'value' => $in, + 'name' => $name + ); + + return $r; + } + function checkboxStore($in, $f) + { + if ($in['value']) { + return "true"; + } + + return "false"; + } + + /* + * E-Mail Field Procesing + */ + function emailField($f) + { + return 'T.'.$f['field']; + } + function emailOptions($f) + { + return false; + } + function emailOutput($f, $d) + { + return $d; + } + function emailInput($as, $f, $id, $idfield, $op) + { + // If this is setup for a new entry, then just return default value + if ($op == 'n') { + $in = ''; + if (isset($f['default'])) { + $in = ($f['default']); + } + return $in; + } + + $this->inputFieldStatus = true; + + $in = filter_input(INPUT_POST, $as, FILTER_VALIDATE_EMAIL); + if ($f['required'] && trim($in) == '') { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'E-Mail address does not appear to be valid.'; + return $in; + } + + // Check for required field + if ($f['required'] && trim($in) == '') { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Required input not provided.'; + return $in; + } + + // If the field validated and it's supposed to be unique + if ($this->inputFieldStatus && isset($f['unique']) && $f['unique']) { + + // Query table to see if there's a conflict + $sql = " + SELECT COUNT(" + .$f['field'].") + FROM " + .$this->table." + WHERE " + .$f['field']." = '$in'; + "; + + // If there's an ID field, then this must be an update rather than an insert + if ($id != false && $idField != false) { + // Add clause to check if not the current record + $sql .= "AND $idField != $id"; + } + + $d = $this->wpdb->get_results($sql, ARRAY_A); + + if ($d['count'] > 0) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'This must unique but it conflicts with another entry.'; + return $in; + } + } + + return $in; + } + function emailStore($in, $f) + { + return "'".addslashes($in)."'"; + } + + /* + * Date Field Processing + */ + // Support function to build picklists for Date field + function buildDateFieldLists($min, $max) + { + + if (!$this->optionIncludeSelectListData) { + return false; + } + + // Default date input lists + $month_list = array( + 1 => array('name' => 'Jan', 'value' => 1, 'default' => false), + 2 => array('name' => 'Feb', 'value' => 2, 'default' => false), + 3 => array('name' => 'Mar', 'value' => 3, 'default' => false), + 4 => array('name' => 'Apr', 'value' => 4, 'default' => false), + 5 => array('name' => 'May', 'value' => 5, 'default' => false), + 6 => array('name' => 'Jun', 'value' => 6, 'default' => false), + 7 => array('name' => 'Jul', 'value' => 7, 'default' => false), + 8 => array('name' => 'Aug', 'value' => 8, 'default' => false), + 9 => array('name' => 'Sep', 'value' => 9, 'default' => false), + 10 => array('name' => 'Oct', 'value' => 10, 'default' => false), + 11 => array('name' => 'Nov', 'value' => 11, 'default' => false), + 12 => array('name' => 'Dec', 'value' => 12, 'default' => false), + ); + $day_list = array(); + for ($i = 1; $i <= 31; $i++) { + $day_list[$i] = array('name' => $i, 'value' => $i, 'default' => false); + } + $year_list = array(); + + $min_year = date('Y', $min); + $max_year = date('Y', $max); + for ($i = $min_year; $i <= $max_year; $i++) { + $year_list[$i] = array('name' => $i, 'value' => $i, 'default' => false); + } + + $date_list = array( + 'month' => $month_list, + 'day' => $day_list, + 'year' => $year_list, + 'min' => date('m/d/Y',$min), + 'max' => date('m/d/Y',$max) + ); + + return $date_list; + } + function dateField($f) + { + return 'T.'.$f['field']; + } + function dateOptions($f) + { + return false; + } + function dateOutput($f, $d) + { + + // Check for min/max date values + if (isset($f['minValue']) && ($f['minValue']-0) > 0) { + $min = $f['minValue']-0; + } else { + $min = strtotime('-6 months'); + } + if (isset($f['maxValue']) && ($f['maxValue']-0) > 0) { + $max = $f['maxValue']-0; + } else { + $max = strtotime('+24 months'); + } + + // Get time stamp for retrieved data + $t = strtotime($d); + + // Set text format for return + $format = 'm/d/Y'; + if (isset($f['format']) && $f['format'] != false) { + $format = $f['format']; + } + + // If there was a date stored, then display it, otherwise blank + if ($d != '') { + $text_date = date($format, $t); + } else { + $text_date = ''; + } + + // Build return array + $out = array( + 'date' => $text_date, + 'timestamp' => strtotime($text_date) + ); + + // Build picklists for date input + $date_list = false; + if ($this->optionIncludeSelectListData) { + + $date_list = $this->buildDateFieldLists($min, $max); + + // Get default values for list selection and set in date_list array + $def_month = date('n', $t); + $date_list['month'][$def_month]['default'] = true; + $def_day = date('j', $t); + $date_list['day'][$def_day]['default'] = true; + $def_year = date('Y', $t); + $date_list['year'][$def_year]['default'] = true; + + $out['date_list'] = $date_list; + } + + return $out; + } + function dateInput($as, $f, $id, $idfield, $op) + { + $this->inputFieldStatus = true; + + // Check for min/max date values + if (isset($f['minValue']) && ($f['minValue']-0) > 0) { + $min = $f['minValue']-0; + } else { + $min = strtotime('-6 months'); + } + if (isset($f['maxValue']) && ($f['maxValue']-0) > 0) { + $max = $f['maxValue']-0; + } else { + $max = strtotime('+24 months'); + } + + // Build picklists for date input + $date_list = $this->buildDateFieldLists($min, $max); + + // If this is setup for a new entry, then just return default value + if ($op == 'n') { + $in = time(); // Assume current time + if (isset($f['default']) && $f['default'] != false) { + $in = ($f['default']); + } + + // Otherwise we should be getting input from the user + } else { + + $this->inputErrorReason = false; + + // Check for pick-list date input + $in_type = false; + if (isset($_REQUEST[$as.'_month'])) { + + // Looks like we have picklist input + $in = strtotime($_REQUEST[$as.'_month'].'/'.$_REQUEST[$as.'_day'].'/'.$_REQUEST[$as.'_year']); + $in_type = 'pick'; + + } elseif (isset($_REQUEST[$as])) { + + // Looks like it's plain text input + $in = strtotime($_REQUEST[$as]); + + $in_type = 'text'; + + } + + // check if the input time was invalid + if ($f['required'] && $in == false) { + $this->inputErrorReason = 'Date supplied is invalid.'; + $this->inputFieldStatus = false; + $in = time(); + } + + } // get input from user + + // Force to be numeric - Must be time stamp at this point + $in = ($in - 0); + + // Use default format unless there's a date format spec? + $format = ('m/d/Y'); + if ($f['format']) { + $format = $f['format']; + } + + // Check for required input - Can't be 0 (epoch) + if ($f['required']) { + if ($in == 0) { + $this->inputErrorReason = 'Required date not supplied.'; + $this->inputFieldStatus = false; + // Check for valid date range + } elseif ($f['minValue'] && $in < $f['minValue']) { + $this->inputErrorReason = 'Date earlier than permitted ('.date($format, $f['minValue']).').'; + $this->inputFieldStatus = false; + } elseif ($f['maxValue'] && $in > $f['maxValue']) { + $this->inputErrorReason = 'Date later than permitted ('.date($format, $f['maxValue']).').'; + $this->inputFieldStatus = false; + } + } + + // Use specified format to clean up date + if ($in > 0) { + $text_date = date($format, $in); + } else { + $text_date = ''; + } + + // If the field validated and it's supposed to be unique + if ($this->inputFieldStatus && $this->inputFieldStatus && isset($f['unique']) && $f['unique']) { + + // Query table to see if there's a conflict + $sql = " + SELECT COUNT(" + .$f['field'].") + FROM " + .$this->table." + WHERE " + .$f['field']." = '$text_date'; + "; + + // If there's an ID field, then this must be an update rather than an insert + if ($id != false && $idField != false) { + // Add clause to check if not the current record + $sql .= "AND $idField != $id"; + } + + $d = $this->wpdb->get_results($sql, ARRAY_A); + + if ($d['count'] > 0) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'This must unique but it conflicts with another entry.'; + return $in; + } + } + + // Get default values for list selection and set in date_list array + if ($text_date != '') { + $def_month = date('n', $in); + $date_list['month'][$def_month]['default'] = true; + $def_day = date('j', $in); + $date_list['day'][$def_day]['default'] = true; + $def_year = date('Y', $in); + $date_list['year'][$def_year]['default'] = true; + } + + // Build return array + $v = array( + 'date' => $text_date, + 'timestamp' => $in, + 'date_list' => $date_list, + ); + + return $v; + + } + function dateStore($in, $f) + { + // Check if there's no date then supply null + if ($in['date'] != '') { + return "'".addslashes($in['date'])."'"; + } else { + return "null"; + } + } + + /* + * Time Field Processing + */ + // Support function to build picklists for Time field + function buildTimeFieldLists() + { + // Setup hour and minute pick lists + $hour_list = array(); + for ($i = 1; $i <= 12; $i++) { + $hour_list[$i] = array( + 'name' => ($i < 10 ? '0' : '').$i, + 'value' => $i, + 'default' => false + ); + } + $min_list = array( + 0 => array('name' => '00', value => 0, 'default' => false), + 15 => array('name' => '15', value => 15, 'default' => false), + 30 => array('name' => '30', value => 30, 'default' => false), + 45 => array('name' => '45', value => 45, 'default' => false) + ); + $ampm_list = array( + 'A' => array('name' => 'AM', value => 'A', 'default' => false), + 'P' => array('name' => 'PM', value => 'P', 'default' => false) + ); + + $time_list = array( + 'hour' => $hour_list, + 'min' => $min_list, + 'ampm' => $ampm_list + ); + + return $time_list; + } + function timeField($f) + { + return 'T.'.$f['field']; + } + function timeOptions($f) + { + return false; + } + function timeOutput($f, $d) + { + // Build picklists for time input + $time_list = $this->buildTimeFieldLists(); + + // Get current time value + $t = explode(':', $d); + if (count($t) != 3) { + // No current time value set + $time = ''; + } else { + + // Assemble Text time + $ampm = 'AM'; + $hour = ($t[0] - 0); + if ($hour > 11) { + $ampm = 'PM'; + $time_list['ampm']['P']['default'] = true; + } else { + $time_list['ampm']['A']['default'] = true; + } + if ($hour > 12) { + $hour -= 12; + } + + // We're doing only 15 min intervals so force to that + $min = (floor($t[1] / 15) * 15); + $time_list['hour'][$hour]['default'] = true; + $time_list['min'][$min]['default'] = true; + + $time = sprintf('%2d:%02d %s', $hour, $min, $ampm); + + } + + if (!$this->optionIncludeSelectListData) { + $time_list = false; + } + + $r = array( + 'time' => $time, + 'time_list' => $time_list + ); + + return $r; + } + function timeInput($as, $f, $id, $idfield, $op) + { + $this->inputFieldStatus = true; + $hour = 12; + $min = 00; + $ampm = 'PM'; + + // Build picklists for time input + $time_list = $this->buildTimeFieldLists(); + + // If this is setup for a new entry, then just return default value + if ($op == 'n') { + + $time = ''; + + if (isset($f['default'])) { + $time = $f['default']; + } + + // Otherwise we should be getting input from the user + } else { + + $this->inputErrorReason = false; + + // Check for pick-list date input + $in_type = false; + if (isset($_REQUEST[$as.'_hour'])) { + + // Validate hour input + $hour = ($_REQUEST[$as.'_hour'] - 0); + $min = ($_REQUEST[$as.'_min'] - 0); + $ampm = ($_REQUEST[$as.'_ampm'] == 'P' ? 'PM' : 'AM'); + + } elseif (isset($_REQUEST[$as])) { + + // Looks like it's a plain text input + $t = explode(':', $_REQUEST[$as]); + if (count($t) >= 2) { + + $ampm = 'AM'; + $hour = ($t[0] - 0); + + // Check PM + $isAM = stripos($t[1], 'a'); + if ($hour > 11 || $isAM === false) { + $ampm = 'PM'; + } + if ($hour > 12) { + $hour -= 12; + } + + $min = ($t[1] - 0); + } + + } + + } + + // Do sanity check on time + if ($hour < 0 || $hour > 12 || $min < 0 or $min > 59) { + $this->inputErrorReason = 'Time supplied is invalid.'; + $this->inputFieldStatus = false; + } + + // We have a time value so set Hours Pick + $time_list['hour'][$hour]['default'] = true; + + // We're doing only 15 min intervals so force to that + $min = (floor($min / 15) * 15); + $time_list['min'][$min]['default'] = true; + + if ($ampm == 'PM') { + $time_list['ampm']['P']['default'] = true; + } else { + $time_list['ampm']['A']['default'] = true; + } + + // Build text time output + $time = sprintf('%02d:%02d %s', $hour, $min, $ampm); + + // Build time for storing + $store_hour = $hour; + if ($hour < 12 && $ampm == 'PM') { + $store_hour += 12; + } + $time_store = sprintf('%02d:%02d:00', $store_hour, $min); + + $r = array( + 'time' => $time, + 'time_store' => $time_store, + 'time_list' => $time_list + ); + + return $r; + } + function timeStore($in, $f) + { + + return "'".$in['time_store']."'"; + } + + /* + * Phone Field Processing + */ + function phoneField($f) + { + return 'T.'.$f['field']; + } + function phoneOptions($f) + { + return false; + } + function phoneOutput($f, $d) + { + return $d; + } + function phoneInput($as, $f, $id, $idfield, $op) + { + // If this is setup for a new entry, then just return default value + if ($op == 'n') { + $in = ''; + if (isset($f['default'])) { + $in = ($f['default']); + } + return $in; + } + + $in = $_REQUEST[$as]; + return $in; + } + function phoneStore($in, $f) + { + return "'".addslashes($in)."'"; + } + + /* + * Image Field Processing + */ + function imageField($f) + { + return 'T.'.$f['field']; + } + function imageOptions($f) + { + return false; + } + function imageOutput($f, $d) + { + return $d; + } + function imageInput($as, $f, $id, $idfield, $op) + { + + // If this is setup for a new entry, there is no default image capability + if ($op == 'n') { + $in = ''; + return $in; + } + + $current_img = false; + + // Setup Image server access + require_once IMAGE_SERVER_ABSTRACT; + $imServer = new ImageServerAbstract(); + + // Check if there's an existing image + if ($id != false) { + + // If no id field is specified, use 'id' + if ($idfield == false) { + $idfield = 'id'; + } + + // Get the current image + $sql = "SELECT $as + FROM $this->table + WHERE $idfield = $id;"; + + $d = $this->wpdb->get_results($sql, ARRAY_A); + + if (trim($d[$as]) != '') { + $current_img = $d[$as]; + } + } + + // Is there a new image being uploaded + $new = false; + + if (is_array($_FILES[$as.'_new']) && $_FILES[$as.'_new']['tmp_name'] != '') { + $new = true; + } + + // If there a request to delete an existing image or a new image and there's a current image + if (($_REQUEST[$as."_delete"] == 'on' || $new) && $current_img != false) { + $imServer->imageDelete($current_img); + $current_img = ''; + } + + // If there's a new image, try to store that one + if ($new) { + $current_img = $imServer->imageUpload($as.'_new'); + } + + return $current_img; + } + function imageStore($in, $f) + { + return "'".addslashes($in)."'"; + } + + /* + * latitude Field Processing + */ + function latitudeField($f) + { + return 'T.'.$f['field']; + } + function latitudeOptions($f) + { + return false; + } + function latitudeOutput($f, $d) + { + $type = 'DMS'; + if (isset($f['latlon_type'])) { + $type = $f['latlon_type']; + } + + $prec = 2; + if (isset($f['precision'])) { + $prec = $f['precision']; + } + + $lat = $this->f2LatLon($d, 'Lat', $type, $prec); + + return $lat; + } + function latitudeInput($as, $f, $id, $idfield, $op) + { + // If this is setup for a new entry, then just return default value + if ($op == 'n') { + $in = array( + 'dir' => 1, + 'dir_list' => array( + array('name' => 'N', 'value' => 1, 'default' => true), + array('name' => 'S', 'value' => - 1, 'default' => false) + ), + 'deg' => '0', + 'min' => '0', + 'sec' => '0.00' + ); + if (isset($f['default']) && $f['default'] != false) { + $lat = $this->f2LatLon($f['default'], 'Lat', 'DMS', 2); + $in = array( + 'dir' => $lat['dir'], + 'dir_list' => array( + array('name' => 'N', 'value' => 1, 'default' => ($lat['dir'] == 1)), + array('name' => 'S', 'value' => - 1, 'default' => ($lat['dir'] == - 1)) + ), + 'deg' => $lat['deg'], + 'min' => $lat['min'], + 'sec' => $lat['sec'] + ); + } + return $in; + } + + $this->inputFieldStatus = true; + $d = ($_REQUEST[$as."_dir"] - 0); + $in = array( + 'dir' => $d, + 'dir_list' => array( + array('name' => 'N', 'value' => 1, 'default' => ($d == 1)), + array('name' => 'S', 'value' => - 1, 'default' => ($d == - 1)) + ), + 'deg' => trim($_REQUEST[$as."_deg"]), + 'min' => trim($_REQUEST[$as."_min"]), + 'sec' => trim($_REQUEST[$as."_sec"]) + ); + + // Check for required field - A min of at least deg is required + if ($f['required'] && $in['deg'] == '') { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Required latitude input not provided.'; + return $in; + } + + if (!is_numeric($in['deg']) || + (trim($in['min']) != '' && !is_numeric($in['min'])) || + (trim($in['sec']) != '' && !is_numeric($in['sec'])) + ) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Latitude input is not entirely numeric.'; + return $in; + } + + // Make darn'd sure input is numeric + $in['deg'] = $in['deg'] - 0; + $in['min'] = $in['min'] - 0; + $in['sec'] = $in['sec'] - 0; + + // Check direction (E-W/N-S) is +1 or -1 + if (!($in['dir'] == - 1 || $in['dir'] == + 1)) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Invalid input for N or S.'; + return $in; + } + + // Check size of value range + if ($in['deg'] < 0 || $in['deg'] > 90) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Degrees Latitude must be between -90 and +90.'; + return $in; + } + if ($in['min'] < 0 || $in['min'] >= 60) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Minutes must be between 0 and +60.'; + return $in; + } + if ($in['sec'] < 0 || $in['sec'] >= 60) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Seconds must be between 0 and +60.'; + return $in; + } + + return $in; + } + function latitudeStore($in, $f) + { + // NOTE: input must be processed first. + + // Need to convert to float degrees here + $lat = $in['dir'] * ($in['deg'] + ($in['min'] + ($in['sec'] / 60)) / 60); + + return $lat; + } + + /* + * Longitude Field Processing + */ + function longitudeField($f) + { + return 'T.'.$f['field']; + } + function longitudeOptions($f) + { + return false; + } + function longitudeOutput($f, $d) + { + + $type = 'DMS'; + if (isset($f['latlon_type'])) { + $type = $f['latlon_type']; + } + + $prec = 2; + if (isset($f['precision'])) { + $prec = $f['precision']; + } + + $out = $this->f2LatLon($d, 'Lon', $type, $prec); + + return $out; + } + function longitudeInput($as, $f, $id, $idfield, $op) + { + // If this is setup for a new entry, then just return default value + if ($op == 'n') { + $in = array( + 'dir' => - 1, + 'dir_list' => array( + array('name' => 'E', 'value' => 1, 'default' => false), + array('name' => 'W', 'value' => - 1, 'default' => true) + ), + 'deg' => '0', + 'min' => '0', + 'sec' => '0.00' + ); + if (isset($f['default']) && $f['default'] != false) { + $lon = $this->f2LatLon($f['default'], 'Lon', 'DMS', 2); + $in = array( + 'dir' => $lon['dir'], + 'dir_list' => array( + array('name' => 'E', 'value' => 1, 'default' => ($lon['dir'] == 1)), + array('name' => 'W', 'value' => - 1, 'default' => ($lon['dir'] == - 1)) + ), + 'deg' => $lon['deg'], + 'min' => $lon['min'], + 'sec' => $lon['sec'] + ); + } + return $in; + } + + $this->inputFieldStatus = true; + $d = ($_REQUEST[$as."_dir"] - 0); + $in = array( + 'dir' => $d, + 'dir_list' => array( + array('name' => 'E', 'value' => 1, 'default' => ($d == 1)), + array('name' => 'W', 'value' => - 1, 'default' => ($d == - 1)) + ), + 'deg' => trim($_REQUEST[$as."_deg"]), + 'min' => trim($_REQUEST[$as."_min"]), + 'sec' => trim($_REQUEST[$as."_sec"]) + ); + + // Check for required field - A min of at least deg is required + if ($f['required'] && $in['deg'] == '') { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Required longitude input not provided.'; + return $in; + } + + if (!is_numeric($in['deg']) || + (trim($in['min']) != '' && !is_numeric($in['min'])) || + (trim($in['sec']) != '' && !is_numeric($in['sec'])) + ) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Longitude input is not entirely numeric.'; + return $in; + } + + // Make darn'd sure input is numeric + $in['deg'] = $in['deg'] - 0; + $in['min'] = $in['min'] - 0; + $in['sec'] = $in['sec'] - 0; + + // Check direction (E-W/N-S) is +1 or -1 + if (!($in['dir'] == - 1 || $in['dir'] == + 1)) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Invalid input for E or W.'; + return $in; + } + + // Check size of value range + if ($in['deg'] < -180 || $in['deg'] > 180) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Degrees Longitude must be between -180 and +180.'; + return $in; + } + if ($in['min'] < 0 || $in['min'] >= 60) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Minutes must be between 0 and +60.'; + return $in; + } + if ($in['sec'] < 0 || $in['sec'] >= 60) { + $this->inputFieldStatus = false; + $this->inputErrorReason = 'Seconds must be between 0 and +60.'; + return $in; + } + + return $in; + } + function longitudeStore($in, $f) + { + // NOTE: input must be processed first. + // Need to convert to float degrees here + $lon = $in['dir'] * ($in['deg'] + ($in['min'] + ($in['sec'] / 60)) / 60); + + return $lon; + } + + /** + * Build fields list + * + * @var $op is character defining the operation underway (list, detail, new, ...) + * @var $opts flag to create list of available options for pick, radio fields + * @var $defaults flag to create field defaults + * + * @return void + * @access public + */ + public function buildFieldsList($op = 'l', $options = false, $defaults = false) + { + $this->fieldData = array(); + $this->select = ''; + $sep = ''; // Used as separator for $select list + + // For each possible field + reset($this->fields); + while (list($k, $v) = each($this->fields )) { + + // If this field is selected for the current operation + if (strstr($v['use'], $op) || strstr($v['use'], 'a')) { + + $type = $v['type']; + + // Check for good field type + if (!in_array($v['type'], $this->knownFieldTypes)) { + echo "CONFIGURATION ERROR: Unknown field type - ".$v['type']; + exit; + } + + // Call field processing function based on field tye + $field = $this->{$type.'Field'}($v); + + // Add the field to the select list + $this->select .= $sep.$field; + + // If the field has an "AS" specifier, use that as the field name + $as = $v['field']; + $asFieldUsed = false; + if (isset($v['as']) && $v['as'] != false && trim($v['as']) != '') { + $this->select .= ' AS '.$v['as']; + $as = $v['as']; + $asFieldUsed = true; + } + + // If field type is pointer and we don't have AS then do it with default + if ($v['type'] == 'pointer' && ($asFieldUsed)) { + $this->select .= 'AS '.$v['field']; + } + + // Get this field specification + $this->fieldData[$as] = array( + 'name' => $as, + 'store_name' => $v['field'], + 'required' => (isset($v['required']) && $v['required']), + 'submit_error' => false + ); + + // If options are requested + if ($options) { + $opts = $this->{$type.'Options'}($v); + $this->fieldData[$v['field']]['options'] = $opts; + } + + // If defaults are requested + if ($defaults) { + $this->fieldData[$v['field']]['default'] = $v['default']; + } + + // Add separate for adding all subsequent fields + $sep = ", \n"; + } + + } + + return; + } + + /** + * Process fields Output for a single record + * + * @var $data is array of field data record retrieved from database + * @var $op is character defining the operation underway (list, detail, new, ...) + * + * @return array of updated field data or false if failure + * + * @access public + */ + public function processOutputData($data, $op = 'l', $forEdit = false, $id = false, $idfield = 'id') + { + + // For each possible field + reset($this->fields); + while (list($k, $v) = each($this->fields )) { + + // If this field is selected for the current operation + if (strstr($v['use'], $op) || strstr($v['use'], 'a')) { + + // Is there a separate output type? + $type = $v['type']; + if (isset($v['output_type']) && $v['output_type'] != false) { + $type = $v['output_type']; + } + + // Check for good field type + if (!in_array($type, $this->knownFieldTypes)) { + echo "CONFIGURATION ERROR: Unknown field type - ".$v['type']; + exit; + } + + // Check for "as" output field name + $as = $v['field']; + if (isset($v['as']) && $v['as'] != false && trim($v['as'] != '')) { + $as = $v['as']; + } + + // Get the current field data + if (isset($v['no_stripslashes']) && $v['no_stripslashes'] != true) { + $d = stripslashes($data[$as]); + } else { + $d = $data[$as]; + } + + // Call field processing function based on field tye + $out = $this->{$type.'Output'}($v, $d, $forEdit, $id, $idfield, $op); + + $data[$as] = $out; + } + } + + return $data; + } + + /** + * Process fields input for a single record + * If supplied, $id is ID of the current record that's being edited. + * This is used to check for conflicts with fields that must be unique + * and to exclude the current record from that check. + * + * @return void + * + * @access public + */ + public function processInputData($op = 'u', $id = false, $idField = false) + { + + // Status is good unless otherwise determined + $status = true; + + $fieldData = array(); + $fieldFail = array(); + $fieldRequired = array(); + $fieldStore = array(); + + // For each possible field + reset($this->fields); + while (list($k, $v) = each($this->fields )) { + + // Assume field will be OK + $this->inputFieldStatus = true; + + // If this field is selected for the current operation + if (strstr($v['use'], $op) || strstr($v['use'], 'a')) { + + // Check for good field type + if (!in_array($v['type'], $this->knownFieldTypes)) { + echo "CONFIGURATION ERROR: Unknown field type - ".$v['type']; + exit; + } + + // Check for "as" output field name + $as = $v['field']; + if (isset($v['as']) && $v['as'] != false && trim($v['as']) != '') { + $as = $v['as']; + } + + // Check if this is a vew only field. + if (isset($v['view_only']) && $v['view_only']) { + + } else { + + // This is not a "view_only" field + // Call field processing function based on field type + $type = $v['type']; + + $in = $this->{$type.'Input'}($as, $v, $id, $idField, $op); + + // If field did not validate + if ($this->inputFieldStatus == false) { + $fieldData[$as] = $in; + $fieldFail[$as] = $this->inputErrorReason; + $status = false; + } else { + // The field validated + $fieldData[$as] = $in; + $fieldFail[$as] = false; + + // Setup text for SQL INSERT/UPDATE + $fieldStore[$v['field']] = $this->{$type.'Store'}($in, $v); + + } + + $fieldRequired[$as] = (isset($v['required']) && $v['required']); + } + + if (isset($v['quicktip']) && $v['quicktip']) { + $fieldData[$as]['quicktip'] = $v['quicktip']; + } + + } + + } + + $r = array( + 'status' => $status, + 'fieldData' => $fieldData, + 'fieldRequired' => $fieldRequired, + 'fieldFail' => $fieldFail, + 'fieldStore' => $fieldStore + ); + + return $r; + } + + /** + * Stats Method + * + * @return void + * @access public + */ + public function getStats($where = 'true') + { + $sql = "SELECT count(DISTINCT id) + FROM $this->table + WHERE $where;"; + + $stats = $this->wpdb->get_results($sql, ARRAY_A); + + return $stats['count']; + + } + + /** + * List Method + * + * @return void + * @access public + */ + public function getList($where = '', $order = '') + { + + $this->optionIncludeSelectListData = false; + + // Get field specifications for this instance + $this->buildFieldsList('l'); + + $sql = "SELECT $this->select + FROM $this->table T + "; + + if (trim($where != '')) { + $sql .= "WHERE $where + "; + } + + if (trim($order != '')) { + $sql .= "ORDER BY $order + "; + } + +//echo "
$sql
"; + $list = $this->wpdb->get_results($sql, ARRAY_A); + + if (count($list) == 0) + return false; + + // Process individual fields + while (list($k, $v) = each($list)) { + $list[$k] = $this->processOutputData($v, 'l'); + } +//echo "
".print_r($list,1)."
"; + + return $list; + } + + /** + * Detail Method + * + * @return void + * @access public + */ + public function getEntry($id, $idfield = 'id', $where = '') + { + if ($id-0 == 0) { +// echo "DataAbstract.php - getEntry() called with invalid ID"; + return false; + } + + $this->buildFieldsList('g'); + + $sql = "SELECT $this->select + FROM $this->table T + WHERE $idfield = $id + $where + ;"; + + $detail = $this->wpdb->get_results($sql, ARRAY_A); + + // If nothing was found, simply return false + if ($detail == false) { + return false; + } + + // Process individual fields + $detail = $this->processOutputData($detail, 'g'); + + return $detail; + } + + /** + * New Method + * + * @return void + * @access public + */ + public function newEntry() + { + // Doing processInputData() with operation "n" only gets setup info + // such as pick-lists and does not actually process input. + $r = $this->processInputData('n'); + $r['fieldFail'] = false; + + return $r; + } + + /** + * Check Other fields (default function) + * This is here so it doesn't have to be defined in data{xxx}.php file. + * if it is, be sure to use the following in that function. + * parent::checkOther($r); + * + * @return void + * @access public + */ + public function checkOther($r) + { + return $r; + } + + /** + * Store New Method + * + * @param bool store must be true for result to be stored + * + * @return void + * @access public + */ + public function insertEntry($store = true) + { + // Assume everything goes OK. + $status = true; + + $r = $this->processInputData('i'); + + // Check if there's a function to do other checks + $r = $this->checkOther($r); + + // If input is OK, try to store + if ($r['status']) { + + $fields = ''; + $vals = ''; + + $sep = ''; + reset($r['fieldStore']); + while (list($k, $v) = each($r['fieldStore'])) { + $fields .= $sep." $k"; + $vals .= $sep." $v"; + $sep = ",\n"; + } + + if ($store) { + + // Store the data + $sql = " + INSERT INTO $this->table + ( $fields ) VALUES ( $vals ); + "; + + // Now store the field data + $this->wpdb->query($sql); + + // Get the current ID value and set that in the session + $sql = "SELECT CURRVAL('".$this->table."_id_seq') "; + $detail = $this->wpdb->get_row($sql, ARRAY_A); + $r['insertedID'] = $detail['currval']; + + // Get the data again for output + $r['fieldData'] = $this->getEntry($r['insertedID']); + + } + + } + + return $r; + } + + /** + * Edit Method + * + * @return void + * @access public + */ + public function editEntry($id, $idfield = 'id') + { + $this->buildFieldsList('g'); + + $sql = "SELECT $this->select + FROM $this->table T + WHERE $idfield = $id + ;"; + + $detail = $this->wpdb->get_results($sql, ARRAY_A); + + // Process individual fields + $detail = $this->processOutputData($detail, 'e', true, $id, $idfield); + + return $detail; + } + + /** + * Update Method + * + * @return void + * @access public + */ + public function updateEntry($id, $idField = 'id', $store = true) + { + // Get currently stored data for use with view_only field + $stored = $this->getEntry($id, $idField); + + $r = $this->processInputData('u', $id, $idField); + + // Check for 'view_only' fields + reset($this->fields); + while (list($k, $v) = each($this->fields )) { + + if (isset($v['view_only']) && $v['view_only']) { + + // Check for "as" output field name + $as = $v['field']; + if (isset($v['as']) && $v['as'] != false && trim($v['as']) != '' ) { + $as = $v['as']; + } + + $r['fieldData'][$as] = $stored[$as]; + } + } + + // Check if there's a function to do other checks + $r = $this->checkOther($r); + + // If input is OK, and we haven't been told not to, try to store + if ($r['status'] && $store) { + + // Store the data + $sql = " + UPDATE $this->table + SET + "; + + $sep = ''; + reset($r['fieldStore']); + + while (list($k, $v) = each($r['fieldStore'])) { + + // If do not store on empty option is set and the value is blank then don't store + // Note that $v also includes single quote marks (') so a length of 2 is actually blank. + if (!($this->fields[$k]['no_update_when_blank'] && strlen($v) == 2)) { + + $sql .= $sep."$k = $v"; + $sep = ",\n"; + } + } + + $sql .= " + WHERE $idField = $id; + "; + + // Now store the field data + $this->wpdb->query($sql, ARRAY_A); + + // Get the data again for output + $r['fieldData'] = $this->getEntry($id, $idField); + } + + return $r; + + } + + /** + * Delete Method + * + * @return void + * @access public + */ + public function deleteEntry($id, $confirm = false, $idField = 'id') + { + $deleteOK = false; + + // Get the current record data + $detail = $this->getEntry($id, $idField); + + // Add delete confirmation request flag + $detail['delete'] = true; + + // If deletion has been confirmed, then try to delete it + if ($confirm) { + + $detail['deleteConfirmed'] = true; + + // Check for delete restrictions + if ($this->deleteRestrictions != false) { + $restriction = false; + // **** NEED TO FIGURE THIS OUT YET **** + + // If there's a restriction + if ($restriction) { + $detail['reason'] = 'Put reason for not deleting here'; + } + + } else { + $deleteOK = true; + } + + // If it's OK to delete, then do so now + if ($deleteOK) { + $sql = " + DELETE FROM ".$this->table." + WHERE $idField = $id; + "; + + // Assume things will go fine + try { + $this->wpdb->query($sql, ARRAY_A); + } catch (Exception $e) { + $detail['deleteFailure'] = true; + $detail['reason'] = '
'.$e->getMessage().'
'; + } + + } + } + + return $detail; + } + + /* + * Convert fload degrees to N/S or E/W Lat/Lon as D, D M, or D M S + * + * @return array + * text Text output of value + * dir Direction (N,S,E,W) + * deg Degrees + * min Minutes + * sec Seconds + */ + + public function f2LatLon($d, $LatLon, $type, $precision) + { + + $sign = +1; + if ($d < 0) { + $sign = -1; + } + + switch ($LatLon) { + case 'Lat': + // Is it N or S? + $dir = 'N'; + if ($d < 0) { + $dir = 'S'; + } + + $deg_size = 2; + $dir_opts = array('1' => 'N', '-1' => 'S'); + break; + case 'Lon': + // Is it E or W? + $dir = 'E'; + if ($d < 0) { + $dir = 'W'; + } + + $deg_size = 3; + $dir_opts = array('1' => 'E', '-1' => 'W'); + break; + } + $d = abs($d); + $deg = 0; + $min = 0; + $sec = 0; + $format = "%s %0".$deg_size.".".$precision."f°"; + + if ($type == 'D') { + $deg = $d; + } elseif ($type == 'DM' || $type == 'DMS') { + $deg = (int) $d; + $d = ($d - $deg) * 60; + $min = $d; + $format = "%s %02d° %02.".$precision."f'"; + if ($type == 'DMS') { + $min = (int) $d; + $sec = ($d - $min) * 60; + $format = "%s %0".$deg_size."d° %02d' %02.".$precision."f\""; + } + } + + // Setup possible direction selection + $dir_select = array( + array( + 'value' => 1, + 'name' => $dir_opts[1], + 'default' => ($sign == 1) + ), + array( + 'value' => - 1, + 'name' => $dir_opts[-1], + 'default' => ($sign == - 1) + ) + ); + + $r = array( + 'text' => $dms = sprintf($format, $dir, $deg, $min, $sec), + 'd_only' => ($sign * ($deg + ($min + $sec / 60) / 60)), + 'dir' => $sign, + 'dir_list' => $dir_select, + 'deg' => $deg, + 'min' => $min, + 'sec' => $sec, + ); + + return $r; + + } +} +?> \ No newline at end of file diff --git a/lib/GlmDataAbstract/documentation.txt b/lib/GlmDataAbstract/documentation.txt new file mode 100644 index 00000000..01572ff4 --- /dev/null +++ b/lib/GlmDataAbstract/documentation.txt @@ -0,0 +1,439 @@ +GlmDataAbstract.php Documentation +------------------------------------------- + +This file is an abstract layer for all standard database operations. It +provides the following. + +* Standardized method for database use definition +* Standardized methods for database access +* Standardized data input and output processing +* Standardized response data structure for use with applications or directly with templates + +This abstraction layer is primarily driven by a dabase field definitions +array. The array defines both real and virtual database fields, the type +of those fields, how input to those fields is filtered and validated, +whether the fields are required, if those fields must be unique, and +for which database access methods the fields should be used. A specification +of that array is defined below under "Field Definitions Array Specification". + +Virtual fields are either modified copies of a real database field using +an alternative name and alternative parameters, or are the result of more +complex operations related to a single or multiple specific real database +fields (such as pointer field options, possibly with selection criteria). + + +Summary of Standard Database Access Methods +------------------------------------------- + +getStats() Collects and returns statistics from the database according + to the field definitions array. + +getList() Builds and returns a list of database entries according to + the field definitions array. + +getEntry() Builds and returns a single simple database table entry or + optionally a single instance of a composite of multiple + related table entries. + +newEntry() Prepairs for the creation of a new simple or composite database + entry and returns information sufficient to create the + necessary user input requests through a template. + +insertEntry() Checks for and compiles input data from the $_REQUEST array, + tests for all requirements to be met, and if possible inserts + the data into a single database table or if a composite into + multiple related tables. + +editEntry() Builds and returns a single simple database table entry or + optionally a single instance of a composite of multiple + related table entries and includes the information necessary + to build a user input request through a template. + +updateEntry() Checks for and compiles input data from the $_REQUEST array, + tests for all requirements to be met, if possible updates + the specified database table entry/entries, and returns the + stored data for display back to the user (similar to the + getEntry method). If the update fails, it returns the data + submitted and flags/information indicating the field(s) + and nature of the failure so that the user input form can + be redisplayed with such notices. + +deleteEntry() Checks for the deletion of a simple or composite database + entry, deletes that entry if possible, and returns information + on the success or failure of that operation. + +checkOther() Permits other checks before submission of data with insert + and update. This is a hook back into DataAbstract.php that + can be used to intercept the insert and update process, run + checks on data that was submitted, alter data, add fieldFail + data, and chage the result status. The function is passed the + entire result array ($r) and should return the same when done + performing checks and updates. This is not required when calling + DataAbstract since there is a stub checkOther() method there. + + An example follows showing how to hook into checkOther() in + DataAbstract and make additional checks ... + + function checkOther($r) + { + // Required + parent::checkOther($r); + + // ---- Perform test and changes ---- + + // Sample field checks and status updates + if ($r['fieldData']['date_specific']['value'] && $r['fieldData']['cart_sticky']['value']) { + $r['status'] = false; + $r['fieldFail']['cart_sticky'] = 'Sticky may not be used when "Specified Dates" is checked.'; + $r['fieldFail']['date_specific'] = 'Specified dates may not be used when "Sticky" is checked.'; + } + + // ---- End tests and changes ---- + + // Required + return $r; + } + + +Summary of Additional Methods Supporing the Methods Above +--------------------------------------------------------- + +{fieldtype}Field() Returns a field name as needed for use in an SQL query + for an individual field. + +{fieldtype}Options() Returns an SQL query segment needed to implement specific + field options for an individual field. + +{fieldtype}Output() Returns data for an individual real or virtual field. + +{fieldtype}Input() Processes input for an individual real or composite field + and returns a copy of the field information. + +{fieldtype}Store() Returns and SQL query segment representing the "VALUE" + parameter for an individual field. + +buildFieldsList() Parses the definitions array and builds a list of fields + and fields parameters that need to be processed for the + current operation. + +processOutputData() Processes a fields list and returns a set of output data + for all fields used for the current operation. + +processInputData() Processes a fields list and collects input data + for all fields used for the current operation. + +f2LatLon() Performs various types of Latitude/Longitude conversions. + + +Summary of Available Field Types +-------------------------------- + +integer Standard integer value. + +Float Standard float value. + +money A float value processed for monitary input or display stripping + any supplied "$" or "," characters and properly formatting for output. + +percent A float value processed for percentile input and display stripping + any supplied "%" characters and properly formatting for output. + +pointer An integer field being used as a pointer to other table entries. + +list An integer field being used as a pointer to a list of possible + values useable for radio buttons and picklists. + +text A standard text field. + +checkbox A boolean field represented in any standard boolean form (i.e. + Yes/No, 0/1, true/false). + +email A text field expecting and returning text formatted as an E-Mail + address. + +date A timestamp field represented as a date, timestamp, or date list. + +time A timestamp field represented as a time value. + +phone A text field expecting and returning text formatted as a Phone + number. + +image A field expecting and returning an image file to be stored and + retrieved from the Image Server and represented in a text field + as the Image Server file name. + +latitude A float field expecting and returning text formatted as a + latitude. + +longitude A float field expecting and returning text formatted as a + longitude. + +password A string field that uses crypt() to generate the stored value. + Consider using the 'no_update_when_blank' option with this type of field. + + +Field Definitions Array Specification +------------------------------------- + +Fields are specified using an array of field specification arrays. + +Sample: + + $this->fields = array( + + // Record ID + 'id' => array( + 'field' => 'id', + 'as' => false, + 'type' => 'integer', + 'filter' => 'int', + 'required' => true, + 'unique' => true, + 'default' => false, + 'use' => 'a' + ), + + // Name of event + 'name' => array( + 'field' => 'name', + 'as' => false, + 'type' => 'text', + 'filter' => 'string', + 'required' => true, + 'unique' => true, + 'default' => false, + 'use' => 'a' + ) + + ); + + +The index for fields must be unique, but three may be multiple entries for a +single field ('field') in the database table. + + +Field Specifications: + +(array index) The array index is only used to permit multiple entries for the + same database field. This permits including the field several + times so it can be processed differently based on the operation + being performed or can be displayed multiple time but each in a + different way. + +'field' Name of field in database table + +'as' Name to use for this field for all operations other than for talking + with the database. Doing this keeps any possible multiple instances + of use of a single database field separate. (see array index above) + + If this is not specified, then the actual database field name is + used for these purposes. + + +'type' Type of field - Possible field types are... + + 'integer', + 'float', + 'money', + 'percent', + 'pointer', + 'list', + 'text', + 'password', + 'checkbox', + 'email', + 'date', + 'time', + 'phone', + 'image', + 'latitude', Data is an array of (dir,deg,min,sec); + 'longitude' " " " + "dir" is - for West and South + +'filter' Optional filter - See PHP filter_input() "filter" parameter. + Currently only for type "text" + FILTER_SANITIZE_FULL_SPECIAL_CHARS does not seem to be defined at this time. + FILTER_SANITIZE_MAGIC_QUOTES seems to be good for permitting HTML + +'filter_options' Optional filter options - See PHP filter_input() "options" parameter. + Currently only for type "text". + +'required' If set and true, field data must be supplied + +'unique' If set and true, must be a unique value + +'default' If set and true use this value as the default for input fields. + Dates/times are expected to be timestamps + There is no default image capability + +'use' Character(s) that indicate which operations to use this field with. + + l = Listing records + g = Get - Displaying a record + n = Setup input for a new record + i = Insert new record + e = Edit an existing record + u = Update an edited record + d = Ask for verification of deletion of a record + c = Confirm delete and delete record. + a = All above operations + +'minValue' Minimum acceptable value (numeric) + Dates are specified as timestamp + +'maxValue' Maximum acceptable value (numeric) + Dates are specified as timestamp + +'minLength' Minimum length for an input field +'maxLength' Maximum length for an input field + +'p_table' Table to get related data from for pointer types + +'p_field' Field to get related data from for field types + +'p_id' name of ID field in related data table + +'p_where' Additional WHERE clause for getting possible values from related table. + "T." refers to the primary table + +'p_from' Additional FROM tables for getting possible values from related table. + See example in dataMembers.php + +'p_blank' If set or true provide a "blank" option for pointer input + +'p_sort' Optional ORDER BY sort clause (i.e. "name, age DESC") - May not be functional yet. + +'p_orderby' Optional "ORDER BY" clause for results from table pointed to by pointer + +'p_autoadd' Option to permit the addition of a new entry using a text input field + +'p_sum' If true causes a numeric sum of all returned values from the target table/column + +'p_static' A static pointer that does not do a lookup for a list of values, only a single value reference + +'output_type' Optional type to use for output. Useful with pointers. + +'latlon_type' Optional specification for lat/lon output (DMS, DM, or D) + +'view_only' View only field, do not check for input or store, only provide data from record. + +'list' Required with field type 'list' - includes simple array where... + array key is value for option + array value is name for option + +'list_keytype' Type of key field (default is 'text') + 'text' A Text key - expects a text field in the database + 'int' An Integer key - expects a numeric field in the database + +'output_format' Optional output format specification as would be used in printf() + Use only the actual format and not the type identifier (i.e. "02.2" rather than "%f02.2") + +'no_stripslashes' Don't strip slashes when recalling this field from the database. + +'quicktip' Text description of this field and its use. + +'no_update_when_blank' Do not store a new value is the submitted data is blank + Used particularly for password fields where you only want them updated when the user puts something in + +'pw_type' Type of password to require for password fields. (default is normal, 'strong' is for strong passwords with a mix of character types) + + +Data specification for various types +------------------------------------ + +Type 'list' + + Return data + + array( + 'list' => array( + array('name' => {name}, 'value' => {value}, 'default' => {true if default or selected}, + .... + ), + 'value' => {value of selected option}, + 'name' => {name of selected option} + ) + +Type 'date' + + Input data fields + + When using single input text field, input field is name of field + + When using separate M, D, Y picklist or input fields + + '{field}_month' + '{field}_day' + '{field}_year' + + Return data + + array( + 'date' => {text date}, + 'timestamp' => {timestamp}, + 'date_list' => array( + 'month' => {picklist array}, + 'day' => {picklist array}, + 'year' => {picklist array} + ), + ) + +Type 'time' + + Input data fields + + When using single input text field, input field is name of field + + When using separate H, M picklist or input fields + + '{field}_hour' + '{field}_min' + '{field}_ampm' + + + Return data + + array( + 'time' => {text time}, + 'time_list' => array( + 'hour' => {picklist array}, + 'min' => {picklist array}, + 'ampm' => {picklist array} + ), + ) + + +Types 'lat' & 'lon' + + Return data + + array( + 'dir' => {direction: -1 = S or W, +1 = N or E}, + 'dir_list' => array( + array('name' => 'N', 'value' => 1, 'default' => {true if default or selected}), + array('name' => 'S', 'value' => -1, 'default' => {true if default or selected}) + ), + 'deg' => {degrees}, + 'min' => {minutes}, + 'sec' => {seconds} + ) + + +Type 'image' + + Input fields + + '{field}_delete' Name of checkbox field to delete image + '{field}_new' Name of file input field to save new image + + +Type 'picklist' + + Parameters for {picklist array} + + 'name' Name to use for this option + 'value' Value to return when this option is selected + 'default' True if this option is currently selected + + + diff --git a/lib/Smarty-3.1.21/COPYING.lib b/lib/Smarty-3.1.21/COPYING.lib new file mode 100644 index 00000000..02bbb60b --- /dev/null +++ b/lib/Smarty-3.1.21/COPYING.lib @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. \ No newline at end of file diff --git a/lib/Smarty-3.1.21/README b/lib/Smarty-3.1.21/README new file mode 100644 index 00000000..6367f030 --- /dev/null +++ b/lib/Smarty-3.1.21/README @@ -0,0 +1,574 @@ +Smarty 3.1.21 + +Author: Monte Ohrt +Author: Uwe Tews + +AN INTRODUCTION TO SMARTY 3 + +NOTICE FOR 3.1 release: + +Please see the SMARTY_3.1_NOTES.txt file that comes with the distribution. + +NOTICE for 3.0.5 release: + +Smarty now follows the PHP error_reporting level by default. If PHP does not mask E_NOTICE and you try to access an unset template variable, you will now get an E_NOTICE warning. To revert to the old behavior: + +$smarty->error_reporting = E_ALL & ~E_NOTICE; + +NOTICE for 3.0 release: + +IMPORTANT: Some API adjustments have been made between the RC4 and 3.0 release. +We felt it is better to make these now instead of after a 3.0 release, then have to +immediately deprecate APIs in 3.1. Online documentation has been updated +to reflect these changes. Specifically: + +---- API CHANGES RC4 -> 3.0 ---- + +$smarty->register->* +$smarty->unregister->* +$smarty->utility->* +$samrty->cache->* + +Have all been changed to local method calls such as: + +$smarty->clearAllCache() +$smarty->registerFoo() +$smarty->unregisterFoo() +$smarty->testInstall() +etc. + +Registration of function, block, compiler, and modifier plugins have been +consolidated under two API calls: + +$smarty->registerPlugin(...) +$smarty->unregisterPlugin(...) + +Registration of pre, post, output and variable filters have been +consolidated under two API calls: + +$smarty->registerFilter(...) +$smarty->unregisterFilter(...) + +Please refer to the online documentation for all specific changes: + +http://www.smarty.net/documentation + +---- + +The Smarty 3 API has been refactored to a syntax geared +for consistency and modularity. The Smarty 2 API syntax is still supported, but +will throw a deprecation notice. You can disable the notices, but it is highly +recommended to adjust your syntax to Smarty 3, as the Smarty 2 syntax must run +through an extra rerouting wrapper. + +Basically, all Smarty methods now follow the "fooBarBaz" camel case syntax. Also, +all Smarty properties now have getters and setters. So for example, the property +$smarty->cache_dir can be set with $smarty->setCacheDir('foo/') and can be +retrieved with $smarty->getCacheDir(). + +Some of the Smarty 3 APIs have been revoked such as the "is*" methods that were +just duplicate functions of the now available "get*" methods. + +Here is a rundown of the Smarty 3 API: + +$smarty->fetch($template, $cache_id = null, $compile_id = null, $parent = null) +$smarty->display($template, $cache_id = null, $compile_id = null, $parent = null) +$smarty->isCached($template, $cache_id = null, $compile_id = null) +$smarty->createData($parent = null) +$smarty->createTemplate($template, $cache_id = null, $compile_id = null, $parent = null) +$smarty->enableSecurity() +$smarty->disableSecurity() +$smarty->setTemplateDir($template_dir) +$smarty->addTemplateDir($template_dir) +$smarty->templateExists($resource_name) +$smarty->loadPlugin($plugin_name, $check = true) +$smarty->loadFilter($type, $name) +$smarty->setExceptionHandler($handler) +$smarty->addPluginsDir($plugins_dir) +$smarty->getGlobal($varname = null) +$smarty->getRegisteredObject($name) +$smarty->getDebugTemplate() +$smarty->setDebugTemplate($tpl_name) +$smarty->assign($tpl_var, $value = null, $nocache = false) +$smarty->assignGlobal($varname, $value = null, $nocache = false) +$smarty->assignByRef($tpl_var, &$value, $nocache = false) +$smarty->append($tpl_var, $value = null, $merge = false, $nocache = false) +$smarty->appendByRef($tpl_var, &$value, $merge = false) +$smarty->clearAssign($tpl_var) +$smarty->clearAllAssign() +$smarty->configLoad($config_file, $sections = null) +$smarty->getVariable($variable, $_ptr = null, $search_parents = true, $error_enable = true) +$smarty->getConfigVariable($variable) +$smarty->getStreamVariable($variable) +$smarty->getConfigVars($varname = null) +$smarty->clearConfig($varname = null) +$smarty->getTemplateVars($varname = null, $_ptr = null, $search_parents = true) +$smarty->clearAllCache($exp_time = null, $type = null) +$smarty->clearCache($template_name, $cache_id = null, $compile_id = null, $exp_time = null, $type = null) + +$smarty->registerPlugin($type, $tag, $callback, $cacheable = true, $cache_attr = array()) + +$smarty->registerObject($object_name, $object_impl, $allowed = array(), $smarty_args = true, $block_methods = array()) + +$smarty->registerFilter($type, $function_name) +$smarty->registerResource($resource_type, $function_names) +$smarty->registerDefaultPluginHandler($function_name) +$smarty->registerDefaultTemplateHandler($function_name) + +$smarty->unregisterPlugin($type, $tag) +$smarty->unregisterObject($object_name) +$smarty->unregisterFilter($type, $function_name) +$smarty->unregisterResource($resource_type) + +$smarty->compileAllTemplates($extension = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null) +$smarty->clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null) +$smarty->testInstall() + +// then all the getters/setters, available for all properties. Here are a few: + +$caching = $smarty->getCaching(); // get $smarty->caching +$smarty->setCaching(true); // set $smarty->caching +$smarty->setDeprecationNotices(false); // set $smarty->deprecation_notices +$smarty->setCacheId($id); // set $smarty->cache_id +$debugging = $smarty->getDebugging(); // get $smarty->debugging + + +FILE STRUCTURE + +The Smarty 3 file structure is similar to Smarty 2: + +/libs/ + Smarty.class.php +/libs/sysplugins/ + internal.* +/libs/plugins/ + function.mailto.php + modifier.escape.php + ... + +A lot of Smarty 3 core functionality lies in the sysplugins directory; you do +not need to change any files here. The /libs/plugins/ folder is where Smarty +plugins are located. You can add your own here, or create a separate plugin +directory, just the same as Smarty 2. You will still need to create your own +/cache/, /templates/, /templates_c/, /configs/ folders. Be sure /cache/ and +/templates_c/ are writable. + +The typical way to use Smarty 3 should also look familiar: + +require('Smarty.class.php'); +$smarty = new Smarty; +$smarty->assign('foo','bar'); +$smarty->display('index.tpl'); + + +However, Smarty 3 works completely different on the inside. Smarty 3 is mostly +backward compatible with Smarty 2, except for the following items: + +*) Smarty 3 is PHP 5 only. It will not work with PHP 4. +*) The {php} tag is disabled by default. Enable with $smarty->allow_php_tag=true. +*) Delimiters surrounded by whitespace are no longer treated as Smarty tags. + Therefore, { foo } will not compile as a tag, you must use {foo}. This change + Makes Javascript/CSS easier to work with, eliminating the need for {literal}. + This can be disabled by setting $smarty->auto_literal = false; +*) The Smarty 3 API is a bit different. Many Smarty 2 API calls are deprecated + but still work. You will want to update your calls to Smarty 3 for maximum + efficiency. + + +There are many things that are new to Smarty 3. Here are the notable items: + +LEXER/PARSER +============ + +Smarty 3 now uses a lexing tokenizer for its parser/compiler. Basically, this +means Smarty has some syntax additions that make life easier such as in-template +math, shorter/intuitive function parameter options, infinite function recursion, +more accurate error handling, etc. + + +WHAT IS NEW IN SMARTY TEMPLATE SYNTAX +===================================== + +Smarty 3 allows expressions almost anywhere. Expressions can include PHP +functions as long as they are not disabled by the security policy, object +methods and properties, etc. The {math} plugin is no longer necessary but +is still supported for BC. + +Examples: +{$x+$y} will output the sum of x and y. +{$foo = strlen($bar)} function in assignment +{assign var=foo value= $x+$y} in attributes +{$foo = myfunct( ($x+$y)*3 )} as function parameter +{$foo[$x+3]} as array index + +Smarty tags can be used as values within other tags. +Example: {$foo={counter}+3} + +Smarty tags can also be used inside double quoted strings. +Example: {$foo="this is message {counter}"} + +You can define arrays within templates. +Examples: +{assign var=foo value=[1,2,3]} +{assign var=foo value=['y'=>'yellow','b'=>'blue']} +Arrays can be nested. +{assign var=foo value=[1,[9,8],3]} + +There is a new short syntax supported for assigning variables. +Example: {$foo=$bar+2} + +You can assign a value to a specific array element. If the variable exists but +is not an array, it is converted to an array before the new values are assigned. +Examples: +{$foo['bar']=1} +{$foo['bar']['blar']=1} + +You can append values to an array. If the variable exists but is not an array, +it is converted to an array before the new values are assigned. +Example: {$foo[]=1} + +You can use a PHP-like syntax for accessing array elements, as well as the +original "dot" notation. +Examples: +{$foo[1]} normal access +{$foo['bar']} +{$foo['bar'][1]} +{$foo[$x+$x]} index may contain any expression +{$foo[$bar[1]]} nested index +{$foo[section_name]} smarty section access, not array access! + +The original "dot" notation stays, and with improvements. +Examples: +{$foo.a.b.c} => $foo['a']['b']['c'] +{$foo.a.$b.c} => $foo['a'][$b]['c'] with variable index +{$foo.a.{$b+4}.c} => $foo['a'][$b+4]['c'] with expression as index +{$foo.a.{$b.c}} => $foo['a'][$b['c']] with nested index + +note that { and } are used to address ambiguties when nesting the dot syntax. + +Variable names themselves can be variable and contain expressions. +Examples: +$foo normal variable +$foo_{$bar} variable name containing other variable +$foo_{$x+$y} variable name containing expressions +$foo_{$bar}_buh_{$blar} variable name with multiple segments +{$foo_{$x}} will output the variable $foo_1 if $x has a value of 1. + +Object method chaining is implemented. +Example: {$object->method1($x)->method2($y)} + +{for} tag added for looping (replacement for {section} tag): +{for $x=0, $y=count($foo); $x<$y; $x++} .... {/for} +Any number of statements can be used separated by comma as the first +inital expression at {for}. + +{for $x = $start to $end step $step} ... {/for}is in the SVN now . +You can use also +{for $x = $start to $end} ... {/for} +In this case the step value will be automaticall 1 or -1 depending on the start and end values. +Instead of $start and $end you can use any valid expression. +Inside the loop the following special vars can be accessed: +$x@iteration = number of iteration +$x@total = total number of iterations +$x@first = true on first iteration +$x@last = true on last iteration + + +The Smarty 2 {section} syntax is still supported. + +New shorter {foreach} syntax to loop over an array. +Example: {foreach $myarray as $var}...{/foreach} + +Within the foreach loop, properties are access via: + +$var@key foreach $var array key +$var@iteration foreach current iteration count (1,2,3...) +$var@index foreach current index count (0,1,2...) +$var@total foreach $var array total +$var@first true on first iteration +$var@last true on last iteration + +The Smarty 2 {foreach} tag syntax is still supported. + +NOTE: {$bar[foo]} still indicates a variable inside of a {section} named foo. +If you want to access an array element with index foo, you must use quotes +such as {$bar['foo']}, or use the dot syntax {$bar.foo}. + +while block tag is now implemented: +{while $foo}...{/while} +{while $x lt 10}...{/while} + +Direct access to PHP functions: +Just as you can use PHP functions as modifiers directly, you can now access +PHP functions directly, provided they are permitted by security settings: +{time()} + +There is a new {function}...{/function} block tag to implement a template function. +This enables reuse of code sequences like a plugin function. It can call itself recursively. +Template function must be called with the new {call name=foo...} tag. + +Example: + +Template file: +{function name=menu level=0} +
    + {foreach $data as $entry} + {if is_array($entry)} +
  • {$entry@key}
  • + {call name=menu data=$entry level=$level+1} + {else} +
  • {$entry}
  • + {/if} + {/foreach} +
+{/function} + +{$menu = ['item1','item2','item3' => ['item3-1','item3-2','item3-3' => + ['item3-3-1','item3-3-2']],'item4']} + +{call name=menu data=$menu} + + +Generated output: + * item1 + * item2 + * item3 + o item3-1 + o item3-2 + o item3-3 + + item3-3-1 + + item3-3-2 + * item4 + +The function tag itself must have the "name" attribute. This name is the tag +name when calling the function. The function tag may have any number of +additional attributes. These will be default settings for local variables. + +New {nocache} block function: +{nocache}...{/nocache} will declare a section of the template to be non-cached +when template caching is enabled. + +New nocache attribute: +You can declare variable/function output as non-cached with the nocache attribute. +Examples: + +{$foo nocache=true} +{$foo nocache} /* same */ + +{foo bar="baz" nocache=true} +{foo bar="baz" nocache} /* same */ + +{time() nocache=true} +{time() nocache} /* same */ + +Or you can also assign the variable in your script as nocache: +$smarty->assign('foo',$something,true); // third param is nocache setting +{$foo} /* non-cached */ + +$smarty.current_dir returns the directory name of the current template. + +You can use strings directly as templates with the "string" resource type. +Examples: +$smarty->display('string:This is my template, {$foo}!'); // php +{include file="string:This is my template, {$foo}!"} // template + + + +VARIABLE SCOPE / VARIABLE STORAGE +================================= + +In Smarty 2, all assigned variables were stored within the Smarty object. +Therefore, all variables assigned in PHP were accessible by all subsequent +fetch and display template calls. + +In Smarty 3, we have the choice to assign variables to the main Smarty object, +to user-created data objects, and to user-created template objects. +These objects can be chained. The object at the end of a chain can access all +variables belonging to that template and all variables within the parent objects. +The Smarty object can only be the root of a chain, but a chain can be isolated +from the Smarty object. + +All known Smarty assignment interfaces will work on the data and template objects. + +Besides the above mentioned objects, there is also a special storage area for +global variables. + +A Smarty data object can be created as follows: +$data = $smarty->createData(); // create root data object +$data->assign('foo','bar'); // assign variables as usual +$data->config_load('my.conf'); // load config file + +$data= $smarty->createData($smarty); // create data object having a parent link to +the Smarty object + +$data2= $smarty->createData($data); // create data object having a parent link to +the $data data object + +A template object can be created by using the createTemplate method. It has the +same parameter assignments as the fetch() or display() method. +Function definition: +function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null) + +The first parameter can be a template name, a smarty object or a data object. + +Examples: +$tpl = $smarty->createTemplate('mytpl.tpl'); // create template object not linked to any parent +$tpl->assign('foo','bar'); // directly assign variables +$tpl->config_load('my.conf'); // load config file + +$tpl = $smarty->createTemplate('mytpl.tpl',$smarty); // create template having a parent link to the Smarty object +$tpl = $smarty->createTemplate('mytpl.tpl',$data); // create template having a parent link to the $data object + +The standard fetch() and display() methods will implicitly create a template object. +If the $parent parameter is not specified in these method calls, the template object +is will link back to the Smarty object as it's parent. + +If a template is called by an {include...} tag from another template, the +subtemplate links back to the calling template as it's parent. + +All variables assigned locally or from a parent template are accessible. If the +template creates or modifies a variable by using the {assign var=foo...} or +{$foo=...} tags, these new values are only known locally (local scope). When the +template exits, none of the new variables or modifications can be seen in the +parent template(s). This is same behavior as in Smarty 2. + +With Smarty 3, we can assign variables with a scope attribute which allows the +availablility of these new variables or modifications globally (ie in the parent +templates.) + +Possible scopes are local, parent, root and global. +Examples: +{assign var=foo value='bar'} // no scope is specified, the default 'local' +{$foo='bar'} // same, local scope +{assign var=foo value='bar' scope='local'} // same, local scope + +{assign var=foo value='bar' scope='parent'} // Values will be available to the parent object +{$foo='bar' scope='parent'} // (normally the calling template) + +{assign var=foo value='bar' scope='root'} // Values will be exported up to the root object, so they can +{$foo='bar' scope='root'} // be seen from all templates using the same root. + +{assign var=foo value='bar' scope='global'} // Values will be exported to global variable storage, +{$foo='bar' scope='global'} // they are available to any and all templates. + + +The scope attribute can also be attached to the {include...} tag. In this case, +the specified scope will be the default scope for all assignments within the +included template. + + +PLUGINS +======= + +Smarty3 are following the same coding rules as in Smarty2. +The only difference is that the template object is passed as additional third parameter. + +smarty_plugintype_name (array $params, object $smarty, object $template) + +The Smarty 2 plugins are still compatible as long as they do not make use of specific Smarty2 internals. + + +TEMPLATE INHERITANCE: +===================== + +With template inheritance you can define blocks, which are areas that can be +overriden by child templates, so your templates could look like this: + +parent.tpl: + + + {block name='title'}My site name{/block} + + +

{block name='page-title'}Default page title{/block}

+
+ {block name='content'} + Default content + {/block} +
+ + + +child.tpl: +{extends file='parent.tpl'} +{block name='title'} +Child title +{/block} + +grandchild.tpl: +{extends file='child.tpl'} +{block name='title'}Home - {$smarty.block.parent}{/block} +{block name='page-title'}My home{/block} +{block name='content'} + {foreach $images as $img} + {$img.description} + {/foreach} +{/block} + +We redefined all the blocks here, however in the title block we used {$smarty.block.parent}, +which tells Smarty to insert the default content from the parent template in its place. +The content block was overriden to display the image files, and page-title has also be +overriden to display a completely different title. + +If we render grandchild.tpl we will get this: + + + Home - Child title + + +

My home

+
+ image + image + image +
+ + + +NOTE: In the child templates everything outside the {extends} or {block} tag sections +is ignored. + +The inheritance tree can be as big as you want (meaning you can extend a file that +extends another one that extends another one and so on..), but be aware that all files +have to be checked for modifications at runtime so the more inheritance the more overhead you add. + +Instead of defining the parent/child relationships with the {extends} tag in the child template you +can use the resource as follow: + +$smarty->display('extends:parent.tpl|child.tpl|grandchild.tpl'); + +Child {block} tags may optionally have a append or prepend attribute. In this case the parent block content +is appended or prepended to the child block content. + +{block name='title' append} My title {/block} + + +PHP STREAMS: +============ + +(see online documentation) + +VARIBLE FILTERS: +================ + +(see online documentation) + + +STATIC CLASS ACCESS AND NAMESPACE SUPPORT +========================================= + +You can register a class with optional namespace for the use in the template like: + +$smarty->register->templateClass('foo','name\name2\myclass'); + +In the template you can use it like this: +{foo::method()} etc. + + +======================= + +Please look through it and send any questions/suggestions/etc to the forums. + +http://www.phpinsider.com/smarty-forum/viewtopic.php?t=14168 + +Monte and Uwe diff --git a/lib/Smarty-3.1.21/SMARTY_2_BC_NOTES.txt b/lib/Smarty-3.1.21/SMARTY_2_BC_NOTES.txt new file mode 100644 index 00000000..79a2cb1b --- /dev/null +++ b/lib/Smarty-3.1.21/SMARTY_2_BC_NOTES.txt @@ -0,0 +1,109 @@ += Known incompatibilities with Smarty 2 = + +== Syntax == + +Smarty 3 API has a new syntax. Much of the Smarty 2 syntax is supported +by a wrapper but deprecated. See the README that comes with Smarty 3 for more +information. + +The {$array|@mod} syntax has always been a bit confusing, where an "@" is required +to apply a modifier to an array instead of the individual elements. Normally you +always want the modifier to apply to the variable regardless of its type. In Smarty 3, +{$array|mod} and {$array|@mod} behave identical. It is safe to drop the "@" and the +modifier will still apply to the array. If you really want the modifier to apply to +each array element, you must loop the array in-template, or use a custom modifier that +supports array iteration. Most smarty functions already escape values where necessary +such as {html_options} + +== PHP Version == +Smarty 3 is PHP 5 only. It will not work with PHP 4. + +== {php} Tag == +The {php} tag is disabled by default. The use of {php} tags is +deprecated. It can be enabled with $smarty->allow_php_tag=true. + +But if you scatter PHP code which belongs together into several +{php} tags it may not work any longer. + +== Delimiters and whitespace == +Delimiters surrounded by whitespace are no longer treated as Smarty tags. +Therefore, { foo } will not compile as a tag, you must use {foo}. This change +Makes Javascript/CSS easier to work with, eliminating the need for {literal}. +This can be disabled by setting $smarty->auto_literal = false; + +== Unquoted Strings == +Smarty 2 was a bit more forgiving (and ambiguous) when it comes to unquoted strings +in parameters. Smarty3 is more restrictive. You can still pass strings without quotes +so long as they contain no special characters. (anything outside of A-Za-z0-9_) + +For example filename strings must be quoted + +{include file='path/foo.tpl'} + + +== Extending the Smarty class == +Smarty 3 makes use of the __construct method for initialization. If you are extending +the Smarty class, its constructor is not called implicitly if the your child class defines +its own constructor. In order to run Smarty's constructor, a call to parent::__construct() +within your child constructor is required. + + +class MySmarty extends Smarty { + function __construct() { + parent::__construct(); + + // your initialization code goes here + + } +} + + +== Autoloader == +Smarty 3 does register its own autoloader with spl_autoload_register. If your code has +an existing __autoload function then this function must be explicitly registered on +the __autoload stack. See http://us3.php.net/manual/en/function.spl-autoload-register.php +for further details. + +== Plugin Filenames == +Smarty 3 optionally supports the PHP spl_autoloader. The autoloader requires filenames +to be lower case. Because of this, Smarty plugin file names must also be lowercase. +In Smarty 2, mixed case file names did work. + +== Scope of Special Smarty Variables == +In Smarty 2 the special Smarty variables $smarty.section... and $smarty.foreach... +had global scope. If you had loops with the same name in subtemplates you could accidentally +overwrite values of parent template. + +In Smarty 3 these special Smarty variable have only local scope in the template which +is defining the loop. If you need their value in a subtemplate you have to pass them +as parameter. + +{include file='path/foo.tpl' index=$smarty.section.foo.index} + + +== SMARTY_RESOURCE_CHAR_SET == +Smarty 3 sets the constant SMARTY_RESOURCE_CHAR_SET to utf-8 as default template charset. +This is now used also on modifiers like escape as default charset. If your templates use +other charsets make sure that you define the constant accordingly. Otherwise you may not +get any output. + +== newline at {if} tags == +A \n was added to the compiled code of the {if},{else},{elseif},{/if} tags to get output of newlines as expected by the template source. +If one of the {if} tags is at the line end you will now get a newline in the HTML output. + +== trigger_error() == +The API function trigger_error() has been removed because it did just map to PHP trigger_error. +However it's still included in the Smarty2 API wrapper. + +== Smarty constants == +The constants +SMARTY_PHP_PASSTHRU +SMARTY_PHP_QUOTE +SMARTY_PHP_REMOVE +SMARTY_PHP_ALLOW +have been replaced with class constants +Smarty::PHP_PASSTHRU +Smarty::PHP_QUOTE +Smarty::PHP_REMOVE +Smarty::PHP_ALLOW + diff --git a/lib/Smarty-3.1.21/SMARTY_3.0_BC_NOTES.txt b/lib/Smarty-3.1.21/SMARTY_3.0_BC_NOTES.txt new file mode 100644 index 00000000..fd8b540c --- /dev/null +++ b/lib/Smarty-3.1.21/SMARTY_3.0_BC_NOTES.txt @@ -0,0 +1,24 @@ +== Smarty2 backward compatibility == +All Smarty2 specific API functions and deprecated functionallity has been moved +to the SmartyBC class. + +== {php} Tag == +The {php} tag is no longer available in the standard Smarty calls. +The use of {php} tags is deprecated and only available in the SmartyBC class. + +== {include_php} Tag == +The {include_php} tag is no longer available in the standard Smarty calls. +The use of {include_php} tags is deprecated and only available in the SmartyBC class. + +== php template resource == +The support of the php template resource is removed. + +== $cache_dir, $compile_dir, $config_dir, $template_dir access == +The mentioned properties can't be accessed directly any longer. You must use +corresponding getter/setters like addConfigDir(), setConfigDir(), getConfigDir() + +== obsolete Smarty class properties == +The following no longer used properties are removed: +$allow_php_tag +$allow_php_template +$deprecation_notices \ No newline at end of file diff --git a/lib/Smarty-3.1.21/SMARTY_3.1_NOTES.txt b/lib/Smarty-3.1.21/SMARTY_3.1_NOTES.txt new file mode 100644 index 00000000..57709f0d --- /dev/null +++ b/lib/Smarty-3.1.21/SMARTY_3.1_NOTES.txt @@ -0,0 +1,306 @@ +Smarty 3.1 Notes +================ + +Smarty 3.1 is a departure from 2.0 compatibility. Most notably, all +backward compatibility has been moved to a separate class file named +SmartyBC.class.php. If you require compatibility with 2.0, you will +need to use this class. + +Some differences from 3.0 are also present. 3.1 begins the journey of +requiring setters/getters for property access. So far this is only +implemented on the five directory properties: template_dir, +plugins_dir, configs_dir, compile_dir and cache_dir. These properties +are now protected, it is required to use the setters/getters instead. +That said, direct property access will still work, however slightly +slower since they will now fall through __set() and __get() and in +turn passed through the setter/getter methods. 3.2 will exhibit a full +list of setter/getter methods for all (currently) public properties, +so code-completion in your IDE will work as expected. + +There is absolutely no PHP allowed in templates any more. All +deprecated features of Smarty 2.0 are gone. Again, use the SmartyBC +class if you need any backward compatibility. + +Internal Changes + + Full UTF-8 Compatibility + +The plugins shipped with Smarty 3.1 have been rewritten to fully +support UTF-8 strings if Multibyte String is available. Without +MBString UTF-8 cannot be handled properly. For those rare cases where +templates themselves have to juggle encodings, the new modifiers +to_charset and from_charset may come in handy. + + Plugin API and Performance + +All Plugins (modifiers, functions, blocks, resources, +default_template_handlers, etc) are now receiving the +Smarty_Internal_Template instance, where they were supplied with the +Smarty instance in Smarty 3.0. *. As The Smarty_Internal_Template +mimics the behavior of Smarty, this API simplification should not +require any changes to custom plugins. + +The plugins shipped with Smarty 3.1 have been rewritten for better +performance. Most notably {html_select_date} and {html_select_time} +have been improved vastly. Performance aside, plugins have also been +reviewed and generalized in their API. {html_select_date} and +{html_select_time} now share almost all available options. + +The escape modifier now knows the $double_encode option, which will +prevent entities from being encoded again. + +The capitalize modifier now know the $lc_rest option, which makes sure +all letters following a captial letter are lower-cased. + +The count_sentences modifier now accepts (.?!) as +legitimate endings of a sentence - previously only (.) was +accepted + +The new unescape modifier is there to reverse the effects of the +escape modifier. This applies to the escape formats html, htmlall and +entity. + + default_template_handler_func + +The invocation of $smarty->$default_template_handler_func had to be +altered. Instead of a Smarty_Internal_Template, the fifth argument is +now provided with the Smarty instance. New footprint: + + +/** + * Default Template Handler + * + * called when Smarty's file: resource is unable to load a requested file + * + * @param string $type resource type (e.g. "file", "string", "eval", "resource") + * @param string $name resource name (e.g. "foo/bar.tpl") + * @param string &$content template's content + * @param integer &$modified template's modification time + * @param Smarty $smarty Smarty instance + * @return string|boolean path to file or boolean true if $content and $modified + * have been filled, boolean false if no default template + * could be loaded + */ +function default_template_handler_func($type, $name, &$content, &$modified, Smarty $smarty) { + if (false) { + // return corrected filepath + return "/tmp/some/foobar.tpl"; + } elseif (false) { + // return a template directly + $content = "the template source"; + $modified = time(); + return true; + } else { + // tell smarty that we failed + return false; + } +} + + Stuff done to the compiler + +Many performance improvements have happened internally. One notable +improvement is that all compiled templates are now handled as PHP +functions. This speeds up repeated templates tremendously, as each one +calls an (in-memory) PHP function instead of performing another file +include/scan. + +New Features + + Template syntax + + {block}..{/block} + +The {block} tag has a new hide option flag. It does suppress the block +content if no corresponding child block exists. +EXAMPLE: +parent.tpl +{block name=body hide} child content "{$smarty.block.child}" was +inserted {block} +In the above example the whole block will be suppressed if no child +block "body" is existing. + + {setfilter}..{/setfilter} + +The new {setfilter} block tag allows the definition of filters which +run on variable output. +SYNTAX: +{setfilter filter1|filter2|filter3....} +Smarty3 will lookup up matching filters in the following search order: +1. varibale filter plugin in plugins_dir. +2. a valid modifier. A modifier specification will also accept +additional parameter like filter2:'foo' +3. a PHP function +{/setfilter} will turn previous filter setting off again. +{setfilter} tags can be nested. +EXAMPLE: +{setfilter filter1} + {$foo} + {setfilter filter2} + {$bar} + {/setfilter} + {$buh} +{/setfilter} +{$blar} +In the above example filter1 will run on the output of $foo, filter2 +on $bar, filter1 again on $buh and no filter on $blar. +NOTES: +- {$foo nofilter} will suppress the filters +- These filters will run in addition to filters defined by +registerFilter('variable',...), autoLoadFilter('variable',...) and +defined default modifier. +- {setfilter} will effect only the current template, not included +subtemplates. + + Resource API + +Smarty 3.1 features a new approach to resource management. The +Smarty_Resource API allows simple, yet powerful integration of custom +resources for templates and configuration files. It offers simple +functions for loading data from a custom resource (e.g. database) as +well as define new template types adhering to the special +non-compiling (e,g, plain php) and non-compile-caching (e.g. eval: +resource type) resources. + +See demo/plugins/resource.mysql.php for an example custom database +resource. + +Note that old-fashioned registration of callbacks for resource +management has been deprecated but is still possible with SmartyBC. + + CacheResource API + +In line with the Resource API, the CacheResource API offers a more +comfortable handling of output-cache data. With the +Smarty_CacheResource_Custom accessing databases is made simple. With +the introduction of Smarty_CacheResource_KeyValueStore the +implementation of resources like memcache or APC became a no-brainer; +simple hash-based storage systems are now supporting hierarchical +output-caches. + +See demo/plugins/cacheresource.mysql.php for an example custom +database CacheResource. +See demo/plugins/cacheresource.memcache.php for an example custom +memcache CacheResource using the KeyValueStore helper. + +Note that old-fashioned registration of $cache_handler is not possible +anymore. As the functionality had not been ported to Smarty 3.0.x +properly, it has been dropped from 3.1 completely. + +Locking facilities have been implemented to avoid concurrent cache +generation. Enable cache locking by setting +$smarty->cache_locking = true; + + Relative Paths in Templates (File-Resource) + +As of Smarty 3.1 {include file="../foo.tpl"} and {include +file="./foo.tpl"} will resolve relative to the template they're in. +Relative paths are available with {include file="..."} and +{extends file="..."}. As $smarty->fetch('../foo.tpl') and +$smarty->fetch('./foo.tpl') cannot be relative to a template, an +exception is thrown. + + Addressing a specific $template_dir + +Smarty 3.1 introduces the $template_dir index notation. +$smarty->fetch('[foo]bar.tpl') and {include file="[foo]bar.tpl"} +require the template bar.tpl to be loaded from $template_dir['foo']; +Smarty::setTemplateDir() and Smarty::addTemplateDir() offer ways to +define indexes along with the actual directories. + + Mixing Resources in extends-Resource + +Taking the php extends: template resource one step further, it is now +possible to mix resources within an extends: call like +$smarty->fetch("extends:file:foo.tpl|db:bar.tpl"); + +To make eval: and string: resources available to the inheritance +chain, eval:base64:TPL_STRING and eval:urlencode:TPL_STRING have been +introduced. Supplying the base64 or urlencode flags will trigger +decoding the TPL_STRING in with either base64_decode() or urldecode(). + + extends-Resource in template inheritance + +Template based inheritance may now inherit from php's extends: +resource like {extends file="extends:foo.tpl|db:bar.tpl"}. + + New Smarty property escape_html + +$smarty->escape_html = true will autoescape all template variable +output by calling htmlspecialchars({$output}, ENT_QUOTES, +SMARTY_RESOURCE_CHAR_SET). +NOTE: +This is a compile time option. If you change the setting you must make +sure that the templates get recompiled. + + New option at Smarty property compile_check + +The automatic recompilation of modified templates can now be +controlled by the following settings: +$smarty->compile_check = COMPILECHECK_OFF (false) - template files +will not be checked +$smarty->compile_check = COMPILECHECK_ON (true) - template files will +always be checked +$smarty->compile_check = COMPILECHECK_CACHEMISS - template files will +be checked if caching is enabled and there is no existing cache file +or it has expired + + Automatic recompilation on Smarty version change + +Templates will now be automatically recompiled on Smarty version +changes to avoide incompatibillities in the compiled code. Compiled +template checked against the current setting of the SMARTY_VERSION +constant. + + default_config_handler_func() + +Analogous to the default_template_handler_func() +default_config_handler_func() has been introduced. + + default_plugin_handler_func() + +An optional default_plugin_handler_func() can be defined which gets called +by the compiler on tags which can't be resolved internally or by plugins. +The default_plugin_handler() can map tags to plugins on the fly. + +New getters/setters + +The following setters/getters will be part of the official +documentation, and will be strongly recommended. Direct property +access will still work for the foreseeable future... it will be +transparently routed through the setters/getters, and consequently a +bit slower. + +array|string getTemplateDir( [string $index] ) +replaces $smarty->template_dir; and $smarty->template_dir[$index]; +Smarty setTemplateDir( array|string $path ) +replaces $smarty->template_dir = "foo"; and $smarty->template_dir = +array("foo", "bar"); +Smarty addTemplateDir( array|string $path, [string $index]) +replaces $smarty->template_dir[] = "bar"; and +$smarty->template_dir[$index] = "bar"; + +array|string getConfigDir( [string $index] ) +replaces $smarty->config_dir; and $smarty->config_dir[$index]; +Smarty setConfigDir( array|string $path ) +replaces $smarty->config_dir = "foo"; and $smarty->config_dir = +array("foo", "bar"); +Smarty addConfigDir( array|string $path, [string $index]) +replaces $smarty->config_dir[] = "bar"; and +$smarty->config_dir[$index] = "bar"; + +array getPluginsDir() +replaces $smarty->plugins_dir; +Smarty setPluginsDir( array|string $path ) +replaces $smarty->plugins_dir = "foo"; +Smarty addPluginsDir( array|string $path ) +replaces $smarty->plugins_dir[] = "bar"; + +string getCompileDir() +replaces $smarty->compile_dir; +Smarty setCompileDir( string $path ) +replaces $smarty->compile_dir = "foo"; + +string getCacheDir() +replaces $smarty->cache_dir; +Smarty setCacheDir( string $path ) +replaces $smarty->cache_dir; diff --git a/lib/Smarty-3.1.21/change_log.txt b/lib/Smarty-3.1.21/change_log.txt new file mode 100644 index 00000000..a0161659 --- /dev/null +++ b/lib/Smarty-3.1.21/change_log.txt @@ -0,0 +1,2415 @@ + ===== 3.1.22-dev ===== (xx.xx.2014) + ===== 3.1.21 ===== (18.10.2014) + 18.10.2014 + - composer moved to github + - add COMPOSER_RELEASE_NOTES + + 17.10.2014 + - bugfix on $php_handling security and optimization of smarty_internal_parsetree (Thue Kristensen) + + 16.10.2014 + - bugfix composer.json update + + 15.10.2014 + - bugfix calling a new created cache file with fetch() and Smarty::CACHING_LIFETIME_SAVED multiple times did fail (forum 22350) + + 14.10.2014 + - bugfix any tag placed within " diff --git a/lib/Smarty-3.1.21/libs/plugins/block.textformat.php b/lib/Smarty-3.1.21/libs/plugins/block.textformat.php new file mode 100644 index 00000000..abf54493 --- /dev/null +++ b/lib/Smarty-3.1.21/libs/plugins/block.textformat.php @@ -0,0 +1,110 @@ + + * Name: textformat
+ * Purpose: format text a certain way with preset styles + * or custom wrap/indent settings
+ * Params: + *
+ * - style         - string (email)
+ * - indent        - integer (0)
+ * - wrap          - integer (80)
+ * - wrap_char     - string ("\n")
+ * - indent_char   - string (" ")
+ * - wrap_boundary - boolean (true)
+ * 
+ * + * @link http://www.smarty.net/manual/en/language.function.textformat.php {textformat} + * (Smarty online manual) + * + * @param array $params parameters + * @param string $content contents of the block + * @param Smarty_Internal_Template $template template object + * @param boolean &$repeat repeat flag + * + * @return string content re-formatted + * @author Monte Ohrt + */ +function smarty_block_textformat($params, $content, $template, &$repeat) +{ + if (is_null($content)) { + return; + } + + $style = null; + $indent = 0; + $indent_first = 0; + $indent_char = ' '; + $wrap = 80; + $wrap_char = "\n"; + $wrap_cut = false; + $assign = null; + + foreach ($params as $_key => $_val) { + switch ($_key) { + case 'style': + case 'indent_char': + case 'wrap_char': + case 'assign': + $$_key = (string) $_val; + break; + + case 'indent': + case 'indent_first': + case 'wrap': + $$_key = (int) $_val; + break; + + case 'wrap_cut': + $$_key = (bool) $_val; + break; + + default: + trigger_error("textformat: unknown attribute '$_key'"); + } + } + + if ($style == 'email') { + $wrap = 72; + } + // split into paragraphs + $_paragraphs = preg_split('![\r\n]{2}!', $content); + + foreach ($_paragraphs as &$_paragraph) { + if (!$_paragraph) { + continue; + } + // convert mult. spaces & special chars to single space + $_paragraph = preg_replace(array('!\s+!' . Smarty::$_UTF8_MODIFIER, '!(^\s+)|(\s+$)!' . Smarty::$_UTF8_MODIFIER), array(' ', ''), $_paragraph); + // indent first line + if ($indent_first > 0) { + $_paragraph = str_repeat($indent_char, $indent_first) . $_paragraph; + } + // wordwrap sentences + if (Smarty::$_MBSTRING) { + require_once(SMARTY_PLUGINS_DIR . 'shared.mb_wordwrap.php'); + $_paragraph = smarty_mb_wordwrap($_paragraph, $wrap - $indent, $wrap_char, $wrap_cut); + } else { + $_paragraph = wordwrap($_paragraph, $wrap - $indent, $wrap_char, $wrap_cut); + } + // indent lines + if ($indent > 0) { + $_paragraph = preg_replace('!^!m', str_repeat($indent_char, $indent), $_paragraph); + } + } + $_output = implode($wrap_char . $wrap_char, $_paragraphs); + + if ($assign) { + $template->assign($assign, $_output); + } else { + return $_output; + } +} diff --git a/lib/Smarty-3.1.21/libs/plugins/function.counter.php b/lib/Smarty-3.1.21/libs/plugins/function.counter.php new file mode 100644 index 00000000..4da85a14 --- /dev/null +++ b/lib/Smarty-3.1.21/libs/plugins/function.counter.php @@ -0,0 +1,78 @@ + + * Name: counter
+ * Purpose: print out a counter value + * + * @author Monte Ohrt + * @link http://www.smarty.net/manual/en/language.function.counter.php {counter} + * (Smarty online manual) + * + * @param array $params parameters + * @param Smarty_Internal_Template $template template object + * + * @return string|null + */ +function smarty_function_counter($params, $template) +{ + static $counters = array(); + + $name = (isset($params['name'])) ? $params['name'] : 'default'; + if (!isset($counters[$name])) { + $counters[$name] = array( + 'start' => 1, + 'skip' => 1, + 'direction' => 'up', + 'count' => 1 + ); + } + $counter =& $counters[$name]; + + if (isset($params['start'])) { + $counter['start'] = $counter['count'] = (int) $params['start']; + } + + if (!empty($params['assign'])) { + $counter['assign'] = $params['assign']; + } + + if (isset($counter['assign'])) { + $template->assign($counter['assign'], $counter['count']); + } + + if (isset($params['print'])) { + $print = (bool) $params['print']; + } else { + $print = empty($counter['assign']); + } + + if ($print) { + $retval = $counter['count']; + } else { + $retval = null; + } + + if (isset($params['skip'])) { + $counter['skip'] = $params['skip']; + } + + if (isset($params['direction'])) { + $counter['direction'] = $params['direction']; + } + + if ($counter['direction'] == "down") { + $counter['count'] -= $counter['skip']; + } else { + $counter['count'] += $counter['skip']; + } + + return $retval; +} diff --git a/lib/Smarty-3.1.21/libs/plugins/function.cycle.php b/lib/Smarty-3.1.21/libs/plugins/function.cycle.php new file mode 100644 index 00000000..8dc5cd9d --- /dev/null +++ b/lib/Smarty-3.1.21/libs/plugins/function.cycle.php @@ -0,0 +1,107 @@ + + * Name: cycle
+ * Date: May 3, 2002
+ * Purpose: cycle through given values
+ * Params: + *
+ * - name      - name of cycle (optional)
+ * - values    - comma separated list of values to cycle, or an array of values to cycle
+ *               (this can be left out for subsequent calls)
+ * - reset     - boolean - resets given var to true
+ * - print     - boolean - print var or not. default is true
+ * - advance   - boolean - whether or not to advance the cycle
+ * - delimiter - the value delimiter, default is ","
+ * - assign    - boolean, assigns to template var instead of printed.
+ * 
+ * Examples:
+ *
+ * {cycle values="#eeeeee,#d0d0d0d"}
+ * {cycle name=row values="one,two,three" reset=true}
+ * {cycle name=row}
+ * 
+ * + * @link http://www.smarty.net/manual/en/language.function.cycle.php {cycle} + * (Smarty online manual) + * @author Monte Ohrt + * @author credit to Mark Priatel + * @author credit to Gerard + * @author credit to Jason Sweat + * @version 1.3 + * + * @param array $params parameters + * @param Smarty_Internal_Template $template template object + * + * @return string|null + */ + +function smarty_function_cycle($params, $template) +{ + static $cycle_vars; + + $name = (empty($params['name'])) ? 'default' : $params['name']; + $print = (isset($params['print'])) ? (bool) $params['print'] : true; + $advance = (isset($params['advance'])) ? (bool) $params['advance'] : true; + $reset = (isset($params['reset'])) ? (bool) $params['reset'] : false; + + if (!isset($params['values'])) { + if (!isset($cycle_vars[$name]['values'])) { + trigger_error("cycle: missing 'values' parameter"); + + return; + } + } else { + if (isset($cycle_vars[$name]['values']) + && $cycle_vars[$name]['values'] != $params['values'] + ) { + $cycle_vars[$name]['index'] = 0; + } + $cycle_vars[$name]['values'] = $params['values']; + } + + if (isset($params['delimiter'])) { + $cycle_vars[$name]['delimiter'] = $params['delimiter']; + } elseif (!isset($cycle_vars[$name]['delimiter'])) { + $cycle_vars[$name]['delimiter'] = ','; + } + + if (is_array($cycle_vars[$name]['values'])) { + $cycle_array = $cycle_vars[$name]['values']; + } else { + $cycle_array = explode($cycle_vars[$name]['delimiter'], $cycle_vars[$name]['values']); + } + + if (!isset($cycle_vars[$name]['index']) || $reset) { + $cycle_vars[$name]['index'] = 0; + } + + if (isset($params['assign'])) { + $print = false; + $template->assign($params['assign'], $cycle_array[$cycle_vars[$name]['index']]); + } + + if ($print) { + $retval = $cycle_array[$cycle_vars[$name]['index']]; + } else { + $retval = null; + } + + if ($advance) { + if ($cycle_vars[$name]['index'] >= count($cycle_array) - 1) { + $cycle_vars[$name]['index'] = 0; + } else { + $cycle_vars[$name]['index'] ++; + } + } + + return $retval; +} diff --git a/lib/Smarty-3.1.21/libs/plugins/function.fetch.php b/lib/Smarty-3.1.21/libs/plugins/function.fetch.php new file mode 100644 index 00000000..3506d4a8 --- /dev/null +++ b/lib/Smarty-3.1.21/libs/plugins/function.fetch.php @@ -0,0 +1,221 @@ + + * Name: fetch
+ * Purpose: fetch file, web or ftp data and display results + * + * @link http://www.smarty.net/manual/en/language.function.fetch.php {fetch} + * (Smarty online manual) + * @author Monte Ohrt + * + * @param array $params parameters + * @param Smarty_Internal_Template $template template object + * + * @throws SmartyException + * @return string|null if the assign parameter is passed, Smarty assigns the result to a template variable + */ +function smarty_function_fetch($params, $template) +{ + if (empty($params['file'])) { + trigger_error("[plugin] fetch parameter 'file' cannot be empty", E_USER_NOTICE); + + return; + } + + // strip file protocol + if (stripos($params['file'], 'file://') === 0) { + $params['file'] = substr($params['file'], 7); + } + + $protocol = strpos($params['file'], '://'); + if ($protocol !== false) { + $protocol = strtolower(substr($params['file'], 0, $protocol)); + } + + if (isset($template->smarty->security_policy)) { + if ($protocol) { + // remote resource (or php stream, …) + if (!$template->smarty->security_policy->isTrustedUri($params['file'])) { + return; + } + } else { + // local file + if (!$template->smarty->security_policy->isTrustedResourceDir($params['file'])) { + return; + } + } + } + + $content = ''; + if ($protocol == 'http') { + // http fetch + if ($uri_parts = parse_url($params['file'])) { + // set defaults + $host = $server_name = $uri_parts['host']; + $timeout = 30; + $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*"; + $agent = "Smarty Template Engine " . Smarty::SMARTY_VERSION; + $referer = ""; + $uri = !empty($uri_parts['path']) ? $uri_parts['path'] : '/'; + $uri .= !empty($uri_parts['query']) ? '?' . $uri_parts['query'] : ''; + $_is_proxy = false; + if (empty($uri_parts['port'])) { + $port = 80; + } else { + $port = $uri_parts['port']; + } + if (!empty($uri_parts['user'])) { + $user = $uri_parts['user']; + } + if (!empty($uri_parts['pass'])) { + $pass = $uri_parts['pass']; + } + // loop through parameters, setup headers + foreach ($params as $param_key => $param_value) { + switch ($param_key) { + case "file": + case "assign": + case "assign_headers": + break; + case "user": + if (!empty($param_value)) { + $user = $param_value; + } + break; + case "pass": + if (!empty($param_value)) { + $pass = $param_value; + } + break; + case "accept": + if (!empty($param_value)) { + $accept = $param_value; + } + break; + case "header": + if (!empty($param_value)) { + if (!preg_match('![\w\d-]+: .+!', $param_value)) { + trigger_error("[plugin] invalid header format '" . $param_value . "'", E_USER_NOTICE); + + return; + } else { + $extra_headers[] = $param_value; + } + } + break; + case "proxy_host": + if (!empty($param_value)) { + $proxy_host = $param_value; + } + break; + case "proxy_port": + if (!preg_match('!\D!', $param_value)) { + $proxy_port = (int) $param_value; + } else { + trigger_error("[plugin] invalid value for attribute '" . $param_key . "'", E_USER_NOTICE); + + return; + } + break; + case "agent": + if (!empty($param_value)) { + $agent = $param_value; + } + break; + case "referer": + if (!empty($param_value)) { + $referer = $param_value; + } + break; + case "timeout": + if (!preg_match('!\D!', $param_value)) { + $timeout = (int) $param_value; + } else { + trigger_error("[plugin] invalid value for attribute '" . $param_key . "'", E_USER_NOTICE); + + return; + } + break; + default: + trigger_error("[plugin] unrecognized attribute '" . $param_key . "'", E_USER_NOTICE); + + return; + } + } + if (!empty($proxy_host) && !empty($proxy_port)) { + $_is_proxy = true; + $fp = fsockopen($proxy_host, $proxy_port, $errno, $errstr, $timeout); + } else { + $fp = fsockopen($server_name, $port, $errno, $errstr, $timeout); + } + + if (!$fp) { + trigger_error("[plugin] unable to fetch: $errstr ($errno)", E_USER_NOTICE); + + return; + } else { + if ($_is_proxy) { + fputs($fp, 'GET ' . $params['file'] . " HTTP/1.0\r\n"); + } else { + fputs($fp, "GET $uri HTTP/1.0\r\n"); + } + if (!empty($host)) { + fputs($fp, "Host: $host\r\n"); + } + if (!empty($accept)) { + fputs($fp, "Accept: $accept\r\n"); + } + if (!empty($agent)) { + fputs($fp, "User-Agent: $agent\r\n"); + } + if (!empty($referer)) { + fputs($fp, "Referer: $referer\r\n"); + } + if (isset($extra_headers) && is_array($extra_headers)) { + foreach ($extra_headers as $curr_header) { + fputs($fp, $curr_header . "\r\n"); + } + } + if (!empty($user) && !empty($pass)) { + fputs($fp, "Authorization: BASIC " . base64_encode("$user:$pass") . "\r\n"); + } + + fputs($fp, "\r\n"); + while (!feof($fp)) { + $content .= fgets($fp, 4096); + } + fclose($fp); + $csplit = preg_split("!\r\n\r\n!", $content, 2); + + $content = $csplit[1]; + + if (!empty($params['assign_headers'])) { + $template->assign($params['assign_headers'], preg_split("!\r\n!", $csplit[0])); + } + } + } else { + trigger_error("[plugin fetch] unable to parse URL, check syntax", E_USER_NOTICE); + + return; + } + } else { + $content = @file_get_contents($params['file']); + if ($content === false) { + throw new SmartyException("{fetch} cannot read resource '" . $params['file'] . "'"); + } + } + + if (!empty($params['assign'])) { + $template->assign($params['assign'], $content); + } else { + return $content; + } +} diff --git a/lib/Smarty-3.1.21/libs/plugins/function.html_checkboxes.php b/lib/Smarty-3.1.21/libs/plugins/function.html_checkboxes.php new file mode 100644 index 00000000..d7868036 --- /dev/null +++ b/lib/Smarty-3.1.21/libs/plugins/function.html_checkboxes.php @@ -0,0 +1,237 @@ + + * Type: function
+ * Name: html_checkboxes
+ * Date: 24.Feb.2003
+ * Purpose: Prints out a list of checkbox input types
+ * Examples: + *
+ * {html_checkboxes values=$ids output=$names}
+ * {html_checkboxes values=$ids name='box' separator='
' output=$names} + * {html_checkboxes values=$ids checked=$checked separator='
' output=$names} + *
+ * Params: + *
+ * - name       (optional) - string default "checkbox"
+ * - values     (required) - array
+ * - options    (optional) - associative array
+ * - checked    (optional) - array default not set
+ * - separator  (optional) - ie 
or   + * - output (optional) - the output next to each checkbox + * - assign (optional) - assign the output as an array to this variable + * - escape (optional) - escape the content (not value), defaults to true + *
+ * + * @link http://www.smarty.net/manual/en/language.function.html.checkboxes.php {html_checkboxes} + * (Smarty online manual) + * @author Christopher Kvarme + * @author credits to Monte Ohrt + * @version 1.0 + * + * @param array $params parameters + * @param object $template template object + * + * @return string + * @uses smarty_function_escape_special_chars() + */ +function smarty_function_html_checkboxes($params, $template) +{ + require_once(SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php'); + + $name = 'checkbox'; + $values = null; + $options = null; + $selected = array(); + $separator = ''; + $escape = true; + $labels = true; + $label_ids = false; + $output = null; + + $extra = ''; + + foreach ($params as $_key => $_val) { + switch ($_key) { + case 'name': + case 'separator': + $$_key = (string) $_val; + break; + + case 'escape': + case 'labels': + case 'label_ids': + $$_key = (bool) $_val; + break; + + case 'options': + $$_key = (array) $_val; + break; + + case 'values': + case 'output': + $$_key = array_values((array) $_val); + break; + + case 'checked': + case 'selected': + if (is_array($_val)) { + $selected = array(); + foreach ($_val as $_sel) { + if (is_object($_sel)) { + if (method_exists($_sel, "__toString")) { + $_sel = smarty_function_escape_special_chars((string) $_sel->__toString()); + } else { + trigger_error("html_checkboxes: selected attribute contains an object of class '" . get_class($_sel) . "' without __toString() method", E_USER_NOTICE); + continue; + } + } else { + $_sel = smarty_function_escape_special_chars((string) $_sel); + } + $selected[$_sel] = true; + } + } elseif (is_object($_val)) { + if (method_exists($_val, "__toString")) { + $selected = smarty_function_escape_special_chars((string) $_val->__toString()); + } else { + trigger_error("html_checkboxes: selected attribute is an object of class '" . get_class($_val) . "' without __toString() method", E_USER_NOTICE); + } + } else { + $selected = smarty_function_escape_special_chars((string) $_val); + } + break; + + case 'checkboxes': + trigger_error('html_checkboxes: the use of the "checkboxes" attribute is deprecated, use "options" instead', E_USER_WARNING); + $options = (array) $_val; + break; + + case 'assign': + break; + + case 'strict': + break; + + case 'disabled': + case 'readonly': + if (!empty($params['strict'])) { + if (!is_scalar($_val)) { + trigger_error("html_options: $_key attribute must be a scalar, only boolean true or string '$_key' will actually add the attribute", E_USER_NOTICE); + } + + if ($_val === true || $_val === $_key) { + $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_key) . '"'; + } + + break; + } + // omit break; to fall through! + + default: + if (!is_array($_val)) { + $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_val) . '"'; + } else { + trigger_error("html_checkboxes: extra attribute '$_key' cannot be an array", E_USER_NOTICE); + } + break; + } + } + + if (!isset($options) && !isset($values)) { + return ''; + } /* raise error here? */ + + $_html_result = array(); + + if (isset($options)) { + foreach ($options as $_key => $_val) { + $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels, $label_ids, $escape); + } + } else { + foreach ($values as $_i => $_key) { + $_val = isset($output[$_i]) ? $output[$_i] : ''; + $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels, $label_ids, $escape); + } + } + + if (!empty($params['assign'])) { + $template->assign($params['assign'], $_html_result); + } else { + return implode("\n", $_html_result); + } +} + +function smarty_function_html_checkboxes_output($name, $value, $output, $selected, $extra, $separator, $labels, $label_ids, $escape = true) +{ + $_output = ''; + + if (is_object($value)) { + if (method_exists($value, "__toString")) { + $value = (string) $value->__toString(); + } else { + trigger_error("html_options: value is an object of class '" . get_class($value) . "' without __toString() method", E_USER_NOTICE); + + return ''; + } + } else { + $value = (string) $value; + } + + if (is_object($output)) { + if (method_exists($output, "__toString")) { + $output = (string) $output->__toString(); + } else { + trigger_error("html_options: output is an object of class '" . get_class($output) . "' without __toString() method", E_USER_NOTICE); + + return ''; + } + } else { + $output = (string) $output; + } + + if ($labels) { + if ($label_ids) { + $_id = smarty_function_escape_special_chars(preg_replace('![^\w\-\.]!' . Smarty::$_UTF8_MODIFIER, '_', $name . '_' . $value)); + $_output .= '