From 3bb0f3e2a6dbb8ab4cdf24443710cbf32a493b6a Mon Sep 17 00:00:00 2001 From: Joel Mitchell Date: Wed, 4 Jul 2018 09:57:55 -0600 Subject: [PATCH] initial push --- .bowerrc | 3 + .gitignore | 1 + CHANGELOG.md | 20 + LICENSE | 68 + README.md | 18 + Rakefile | 50 + app/controllers/admin_controller.php | 68 + app/controllers/asset_controller.php | 289 ++ app/controllers/audit_trail_controller.php | 423 +++ app/controllers/cms_asset_info_controller.php | 139 + .../cms_asset_template_controller.php | 159 + app/controllers/cms_drafts_controller.php | 60 + app/controllers/code_caller_controller.php | 103 + app/controllers/content_controller.php | 58 + app/controllers/csv_export_controller.php | 262 ++ app/controllers/dashboard_controller.php | 314 ++ app/controllers/excel_export_controller.php | 267 ++ app/controllers/imageviewer_controller.php | 28 + app/controllers/login_controller.php | 149 + app/controllers/memcache_controller.php | 41 + app/controllers/nterchange_controller.php | 73 + app/controllers/page_content_controller.php | 732 ++++ app/controllers/page_controller.php | 1384 +++++++ .../page_template_containers_controller.php | 106 + app/controllers/page_template_controller.php | 52 + app/controllers/phpinfo_controller.php | 31 + app/controllers/redirect_controller.php | 94 + app/controllers/rss_controller.php | 116 + app/controllers/search_controller.php | 145 + app/controllers/settings_controller.php | 109 + app/controllers/site_admin_controller.php | 201 + app/controllers/test_sample_controller.php | 29 + app/controllers/users_controller.php | 207 ++ app/controllers/version_check_controller.php | 109 + app/controllers/version_controller.php | 219 ++ app/controllers/workflow_controller.php | 912 +++++ app/controllers/workflow_group_controller.php | 153 + app/controllers/workflow_users_controller.php | 84 + app/helpers/audit_trail_helper.php | 5 + app/helpers/cms_asset_info_helper.php | 53 + app/helpers/cms_asset_template_helper.php | 47 + app/helpers/content_helper.php | 5 + app/helpers/dashboard_helper.php | 13 + app/helpers/login_helper.php | 5 + app/helpers/page_content_helper.php | 5 + app/helpers/page_helper.php | 5 + .../page_template_containers_helper.php | 28 + app/helpers/page_template_helper.php | 28 + app/helpers/settings_helper.php | 5 + app/helpers/site_admin_helper.php | 5 + app/helpers/users_helper.php | 5 + app/models/action_track.php | 190 + app/models/cms_asset_info.php | 29 + app/models/cms_asset_template.php | 29 + app/models/cms_audit_trail.php | 70 + app/models/cms_auth.php | 173 + app/models/cms_drafts.php | 26 + app/models/cms_nterchange_versions.php | 27 + app/models/cms_settings.php | 90 + app/models/code_caller.php | 28 + app/models/page.php | 140 + app/models/page_content.php | 256 ++ app/models/page_template.php | 27 + app/models/page_template_containers.php | 28 + app/models/permissions.php | 26 + app/models/redirect.php | 47 + app/models/test_sample.php | 29 + app/models/workflow.php | 31 + app/models/workflow_group.php | 28 + app/models/workflow_users.php | 33 + app/views/audit_trail/audit_trail_record.html | 33 + app/views/audit_trail/page.html | 3 + .../audit_trail/page_audit_trail_record.html | 33 + app/views/audit_trail/viewlist.html | 13 + app/views/ck_upload/image_browse.html | 15 + app/views/ck_upload/media_browse.html | 20 + app/views/cms_asset_info/viewlist.html | 14 + app/views/cms_asset_template/edit.html | 5 + app/views/cms_asset_template/show.html | 10 + app/views/cms_asset_template/viewlist.html | 16 + app/views/code_caller/default.html | 3 + app/views/content/list_assets.html | 7 + .../dashboard/dashboard_client_content.html | 1 + .../dashboard_client_sidebar_content.html | 1 + app/views/dashboard/description.html | 12 + app/views/dashboard/draft_record.html | 13 + app/views/dashboard/index.html | 14 + app/views/dashboard/no_drafts.html | 3 + app/views/dashboard/no_workflows.html | 3 + app/views/dashboard/nterchange_training.html | 5 + app/views/dashboard/workflow.html | 1 + app/views/dashboard/workflow_description.html | 4 + app/views/dashboard/workflow_norecords.html | 3 + app/views/dashboard/workflow_page_submit.html | 7 + app/views/dashboard/workflow_record.html | 29 + app/views/dashboard/workflow_section.html | 1 + app/views/imageviewer/index.php | 68 + app/views/layouts/default.html | 30 + app/views/layouts/head.html | 44 + app/views/layouts/login.html | 28 + app/views/layouts/logo.html | 3 + app/views/layouts/navigation.html | 15 + app/views/layouts/plain.html | 20 + app/views/layouts/previewobject.html | 14 + app/views/layouts/simple.html | 16 + app/views/layouts/subnav.html | 9 + app/views/layouts/tail.html | 9 + app/views/page/children_container.html | 26 + app/views/page/content_container.html | 29 + app/views/page/content_container_title.html | 2 + app/views/page/reorder_close.html | 4 + app/views/page/sidebar.html | 32 + app/views/page/surftoedit.html | 7 + app/views/page_content/asset_add.html | 20 + app/views/page_content/asset_edit.html | 14 + app/views/page_content/form.html | 1 + app/views/page_template/viewlist.html | 15 + app/views/page_template_containers/edit.html | 5 + app/views/page_template_containers/show.html | 10 + .../page_template_containers/viewlist.html | 17 + app/views/rss/audit_trail.html | 21 + app/views/settings/viewlist.html | 7 + app/views/site_admin/clear_all_cache.html | 9 + app/views/site_admin/site_admin.html | 19 + app/views/site_admin/site_admin_list_end.html | 1 + .../site_admin/site_admin_list_start.html | 2 + app/views/site_admin/sitemap_list_item.html | 19 + app/views/templates/create.html | 5 + app/views/templates/edit.html | 12 + app/views/templates/page_content.html | 8 + app/views/templates/show.html | 13 + app/views/templates/sidebar_edit_status.html | 1 + app/views/templates/sidebar_page_content.html | 8 + app/views/templates/sidebar_versions.html | 30 + app/views/templates/viewlist.html | 58 + app/views/text/default.html | 5 + app/views/users/confirmation_email.html | 7 + app/views/users/password_email.html | 10 + app/views/users/viewlist.html | 14 + app/views/version/view.html | 24 + .../dashboard_version_check.html | 11 + app/views/workflow/disapproved.html | 7 + app/views/workflow/process.html | 24 + app/views/workflow/published.html | 11 + app/views/workflow/removed.html | 11 + app/views/workflow/send.html | 18 + app/views/workflow_group/viewlist.html | 7 + .../workflow_group/workflow_description.html | 4 + app/views/workflow_group/workflow_group.html | 21 + app/views/workflow_users/workflow_user.html | 24 + bower.json | 21 + composer.json | 20 + composer.lock | 508 +++ config/config.php | 47 + lib/NConfig.php | 41 + lib/NUpload.php | 102 + lib/NUpload/Local.php | 27 + lib/NUpload/S3.php | 80 + lib/app_controller.php | 907 +++++ lib/controller/form.php | 832 +++++ lib/controller/inflector.php | 91 + lib/mirror/ftp_mirror.php | 110 + lib/mirror/rsync_mirror.php | 96 + lib/mirror/s3_mirror.php | 73 + lib/model/fixtures.php | 122 + lib/model/tree.php | 347 ++ lib/model/value_cast.php | 253 ++ lib/n_asset.php | 192 + lib/n_auth.php | 110 + lib/n_cache.php | 84 + lib/n_controller.php | 648 ++++ lib/n_date.php | 280 ++ lib/n_db.php | 116 + lib/n_debug.php | 73 + lib/n_dispatcher.php | 236 ++ lib/n_download.php | 138 + lib/n_filesystem.php | 233 ++ lib/n_flash.php | 113 + lib/n_image.php | 212 ++ lib/n_mirror.php | 96 + lib/n_model.php | 1230 +++++++ lib/n_object.php | 27 + lib/n_quickform.php | 600 +++ lib/n_server.php | 64 + lib/n_view.php | 415 +++ lib/view/helper.php | 165 + lib/view/helpers/action_track_helper.php | 63 + lib/view/helpers/asset_tag_helper.php | 370 ++ lib/view/helpers/date_helper.php | 192 + lib/view/helpers/filesystem_helper.php | 54 + lib/view/helpers/javascript_helper.php | 152 + lib/view/helpers/search_helper.php | 59 + lib/view/helpers/tag_helper.php | 71 + lib/view/helpers/url_helper.php | 162 + nterchange/check.php | 52 + nterchange/images/add.gif | Bin 0 -> 58 bytes nterchange/images/created_by.gif | Bin 0 -> 630 bytes nterchange/images/drag.gif | Bin 0 -> 112 bytes nterchange/images/edit.gif | Bin 0 -> 72 bytes nterchange/images/icon_alert.png | Bin 0 -> 1583 bytes nterchange/images/icon_check.gif | Bin 0 -> 668 bytes nterchange/images/icon_error.png | Bin 0 -> 1575 bytes nterchange/images/icon_help.png | Bin 0 -> 1584 bytes nterchange/images/icon_x.gif | Bin 0 -> 669 bytes nterchange/images/indicator.gif | Bin 0 -> 1553 bytes nterchange/images/listarrow.gif | Bin 0 -> 51 bytes nterchange/images/nterchange.gif | Bin 0 -> 1159 bytes nterchange/images/nterchange3_manual.pdf | Bin 0 -> 1723192 bytes nterchange/images/order.gif | Bin 0 -> 57 bytes nterchange/images/otf/button.php | 62 + nterchange/images/otf/button/button_l.gif | Bin 0 -> 155 bytes nterchange/images/otf/button/button_m.gif | Bin 0 -> 91 bytes nterchange/images/otf/button/button_r.gif | Bin 0 -> 155 bytes nterchange/images/otf/fonts/mini7.ttf | Bin 0 -> 23200 bytes nterchange/images/remove.gif | Bin 0 -> 58 bytes nterchange/images/s_asc.gif | Bin 0 -> 67 bytes nterchange/images/s_desc.gif | Bin 0 -> 68 bytes nterchange/images/shadow_bg.png | Bin 0 -> 12054 bytes nterchange/images/shadow_bl.gif | Bin 0 -> 183 bytes nterchange/images/shadow_br.gif | Bin 0 -> 177 bytes nterchange/images/shadow_tr.gif | Bin 0 -> 177 bytes nterchange/images/site_admin_bg.gif | Bin 0 -> 60 bytes nterchange/images/subtab_off.gif | Bin 0 -> 104 bytes nterchange/images/subtab_on.gif | Bin 0 -> 130 bytes nterchange/images/subtab_over.gif | Bin 0 -> 118 bytes nterchange/images/timed.gif | Bin 0 -> 70 bytes nterchange/index.php | 3 + nterchange/javascripts/builder.js | 136 + nterchange/javascripts/ckeditor/CHANGES.md | 553 +++ nterchange/javascripts/ckeditor/LICENSE.md | 1264 +++++++ nterchange/javascripts/ckeditor/README.md | 39 + .../javascripts/ckeditor/adapters/jquery.js | 10 + .../javascripts/ckeditor/build-config.js | 175 + nterchange/javascripts/ckeditor/ckeditor.js | 991 +++++ nterchange/javascripts/ckeditor/config.js | 1 + nterchange/javascripts/ckeditor/contents.css | 134 + nterchange/javascripts/ckeditor/lang/af.js | 5 + nterchange/javascripts/ckeditor/lang/ar.js | 5 + nterchange/javascripts/ckeditor/lang/bg.js | 5 + nterchange/javascripts/ckeditor/lang/bn.js | 5 + nterchange/javascripts/ckeditor/lang/bs.js | 5 + nterchange/javascripts/ckeditor/lang/ca.js | 5 + nterchange/javascripts/ckeditor/lang/cs.js | 5 + nterchange/javascripts/ckeditor/lang/cy.js | 5 + nterchange/javascripts/ckeditor/lang/da.js | 5 + nterchange/javascripts/ckeditor/lang/de.js | 5 + nterchange/javascripts/ckeditor/lang/el.js | 5 + nterchange/javascripts/ckeditor/lang/en-au.js | 5 + nterchange/javascripts/ckeditor/lang/en-ca.js | 5 + nterchange/javascripts/ckeditor/lang/en-gb.js | 5 + nterchange/javascripts/ckeditor/lang/en.js | 5 + nterchange/javascripts/ckeditor/lang/eo.js | 5 + nterchange/javascripts/ckeditor/lang/es.js | 5 + nterchange/javascripts/ckeditor/lang/et.js | 5 + nterchange/javascripts/ckeditor/lang/eu.js | 5 + nterchange/javascripts/ckeditor/lang/fa.js | 5 + nterchange/javascripts/ckeditor/lang/fi.js | 5 + nterchange/javascripts/ckeditor/lang/fo.js | 5 + nterchange/javascripts/ckeditor/lang/fr-ca.js | 5 + nterchange/javascripts/ckeditor/lang/fr.js | 5 + nterchange/javascripts/ckeditor/lang/gl.js | 5 + nterchange/javascripts/ckeditor/lang/gu.js | 5 + nterchange/javascripts/ckeditor/lang/he.js | 5 + nterchange/javascripts/ckeditor/lang/hi.js | 5 + nterchange/javascripts/ckeditor/lang/hr.js | 5 + nterchange/javascripts/ckeditor/lang/hu.js | 5 + nterchange/javascripts/ckeditor/lang/is.js | 5 + nterchange/javascripts/ckeditor/lang/it.js | 5 + nterchange/javascripts/ckeditor/lang/ja.js | 5 + nterchange/javascripts/ckeditor/lang/ka.js | 5 + nterchange/javascripts/ckeditor/lang/km.js | 5 + nterchange/javascripts/ckeditor/lang/ko.js | 5 + nterchange/javascripts/ckeditor/lang/ku.js | 5 + nterchange/javascripts/ckeditor/lang/lt.js | 5 + nterchange/javascripts/ckeditor/lang/lv.js | 5 + nterchange/javascripts/ckeditor/lang/mk.js | 5 + nterchange/javascripts/ckeditor/lang/mn.js | 5 + nterchange/javascripts/ckeditor/lang/ms.js | 5 + nterchange/javascripts/ckeditor/lang/nb.js | 5 + nterchange/javascripts/ckeditor/lang/nl.js | 5 + nterchange/javascripts/ckeditor/lang/no.js | 5 + nterchange/javascripts/ckeditor/lang/pl.js | 5 + nterchange/javascripts/ckeditor/lang/pt-br.js | 5 + nterchange/javascripts/ckeditor/lang/pt.js | 5 + nterchange/javascripts/ckeditor/lang/ro.js | 5 + nterchange/javascripts/ckeditor/lang/ru.js | 5 + nterchange/javascripts/ckeditor/lang/si.js | 5 + nterchange/javascripts/ckeditor/lang/sk.js | 5 + nterchange/javascripts/ckeditor/lang/sl.js | 5 + nterchange/javascripts/ckeditor/lang/sq.js | 5 + .../javascripts/ckeditor/lang/sr-latn.js | 5 + nterchange/javascripts/ckeditor/lang/sr.js | 5 + nterchange/javascripts/ckeditor/lang/sv.js | 5 + nterchange/javascripts/ckeditor/lang/th.js | 5 + nterchange/javascripts/ckeditor/lang/tr.js | 5 + nterchange/javascripts/ckeditor/lang/ug.js | 5 + nterchange/javascripts/ckeditor/lang/uk.js | 5 + nterchange/javascripts/ckeditor/lang/vi.js | 5 + nterchange/javascripts/ckeditor/lang/zh-cn.js | 5 + nterchange/javascripts/ckeditor/lang/zh.js | 5 + .../plugins/a11yhelp/dialogs/a11yhelp.js | 10 + .../dialogs/lang/_translationstatus.txt | 25 + .../plugins/a11yhelp/dialogs/lang/ar.js | 11 + .../plugins/a11yhelp/dialogs/lang/bg.js | 11 + .../plugins/a11yhelp/dialogs/lang/ca.js | 13 + .../plugins/a11yhelp/dialogs/lang/cs.js | 13 + .../plugins/a11yhelp/dialogs/lang/cy.js | 11 + .../plugins/a11yhelp/dialogs/lang/da.js | 11 + .../plugins/a11yhelp/dialogs/lang/de.js | 12 + .../plugins/a11yhelp/dialogs/lang/el.js | 13 + .../plugins/a11yhelp/dialogs/lang/en-gb.js | 11 + .../plugins/a11yhelp/dialogs/lang/en.js | 11 + .../plugins/a11yhelp/dialogs/lang/eo.js | 13 + .../plugins/a11yhelp/dialogs/lang/es.js | 12 + .../plugins/a11yhelp/dialogs/lang/et.js | 11 + .../plugins/a11yhelp/dialogs/lang/fa.js | 11 + .../plugins/a11yhelp/dialogs/lang/fi.js | 12 + .../plugins/a11yhelp/dialogs/lang/fr-ca.js | 12 + .../plugins/a11yhelp/dialogs/lang/fr.js | 13 + .../plugins/a11yhelp/dialogs/lang/gl.js | 12 + .../plugins/a11yhelp/dialogs/lang/gu.js | 11 + .../plugins/a11yhelp/dialogs/lang/he.js | 11 + .../plugins/a11yhelp/dialogs/lang/hi.js | 11 + .../plugins/a11yhelp/dialogs/lang/hr.js | 11 + .../plugins/a11yhelp/dialogs/lang/hu.js | 13 + .../plugins/a11yhelp/dialogs/lang/id.js | 11 + .../plugins/a11yhelp/dialogs/lang/it.js | 13 + .../plugins/a11yhelp/dialogs/lang/ja.js | 9 + .../plugins/a11yhelp/dialogs/lang/km.js | 11 + .../plugins/a11yhelp/dialogs/lang/ko.js | 10 + .../plugins/a11yhelp/dialogs/lang/ku.js | 12 + .../plugins/a11yhelp/dialogs/lang/lt.js | 11 + .../plugins/a11yhelp/dialogs/lang/lv.js | 13 + .../plugins/a11yhelp/dialogs/lang/mk.js | 11 + .../plugins/a11yhelp/dialogs/lang/mn.js | 11 + .../plugins/a11yhelp/dialogs/lang/nb.js | 12 + .../plugins/a11yhelp/dialogs/lang/nl.js | 12 + .../plugins/a11yhelp/dialogs/lang/no.js | 11 + .../plugins/a11yhelp/dialogs/lang/pl.js | 13 + .../plugins/a11yhelp/dialogs/lang/pt-br.js | 11 + .../plugins/a11yhelp/dialogs/lang/pt.js | 12 + .../plugins/a11yhelp/dialogs/lang/ro.js | 12 + .../plugins/a11yhelp/dialogs/lang/ru.js | 11 + .../plugins/a11yhelp/dialogs/lang/si.js | 10 + .../plugins/a11yhelp/dialogs/lang/sk.js | 12 + .../plugins/a11yhelp/dialogs/lang/sl.js | 12 + .../plugins/a11yhelp/dialogs/lang/sq.js | 11 + .../plugins/a11yhelp/dialogs/lang/sr-latn.js | 11 + .../plugins/a11yhelp/dialogs/lang/sr.js | 11 + .../plugins/a11yhelp/dialogs/lang/sv.js | 12 + .../plugins/a11yhelp/dialogs/lang/th.js | 11 + .../plugins/a11yhelp/dialogs/lang/tr.js | 12 + .../plugins/a11yhelp/dialogs/lang/tt.js | 11 + .../plugins/a11yhelp/dialogs/lang/ug.js | 11 + .../plugins/a11yhelp/dialogs/lang/uk.js | 12 + .../plugins/a11yhelp/dialogs/lang/vi.js | 11 + .../plugins/a11yhelp/dialogs/lang/zh-cn.js | 9 + .../plugins/a11yhelp/dialogs/lang/zh.js | 10 + .../ckeditor/plugins/about/dialogs/about.js | 7 + .../about/dialogs/hidpi/logo_ckeditor.png | Bin 0 -> 13339 bytes .../plugins/about/dialogs/logo_ckeditor.png | Bin 0 -> 6757 bytes .../plugins/clipboard/dialogs/paste.js | 11 + .../colordialog/dialogs/colordialog.js | 13 + .../plugins/dialog/dialogDefinition.js | 4 + .../ckeditor/plugins/div/dialogs/div.js | 9 + .../ckeditor/plugins/find/dialogs/find.js | 24 + .../ckeditor/plugins/flash/dialogs/flash.js | 24 + .../plugins/flash/images/placeholder.png | Bin 0 -> 256 bytes .../ckeditor/plugins/forms/dialogs/button.js | 8 + .../plugins/forms/dialogs/checkbox.js | 8 + .../ckeditor/plugins/forms/dialogs/form.js | 8 + .../plugins/forms/dialogs/hiddenfield.js | 8 + .../ckeditor/plugins/forms/dialogs/radio.js | 8 + .../ckeditor/plugins/forms/dialogs/select.js | 20 + .../plugins/forms/dialogs/textarea.js | 8 + .../plugins/forms/dialogs/textfield.js | 10 + .../plugins/forms/images/hiddenfield.gif | Bin 0 -> 105 bytes .../javascripts/ckeditor/plugins/icons.png | Bin 0 -> 20626 bytes .../ckeditor/plugins/icons_hidpi.png | Bin 0 -> 66930 bytes .../ckeditor/plugins/iframe/dialogs/iframe.js | 10 + .../plugins/iframe/images/placeholder.png | Bin 0 -> 449 bytes .../ckeditor/plugins/image/dialogs/image.js | 43 + .../ckeditor/plugins/image/images/noimage.png | Bin 0 -> 2115 bytes .../ckeditor/plugins/link/dialogs/anchor.js | 7 + .../ckeditor/plugins/link/dialogs/link.js | 26 + .../ckeditor/plugins/link/images/anchor.png | Bin 0 -> 763 bytes .../plugins/link/images/hidpi/anchor.png | Bin 0 -> 1597 bytes .../plugins/liststyle/dialogs/liststyle.js | 10 + .../plugins/magicline/images/hidpi/icon.png | Bin 0 -> 260 bytes .../plugins/magicline/images/icon.png | Bin 0 -> 172 bytes .../plugins/pagebreak/images/pagebreak.gif | Bin 0 -> 54 bytes .../plugins/pastefromword/filter/default.js | 31 + .../ckeditor/plugins/preview/preview.html | 10 + .../ckeditor/plugins/scayt/LICENSE.md | 28 + .../ckeditor/plugins/scayt/README.md | 25 + .../ckeditor/plugins/scayt/dialogs/options.js | 17 + .../plugins/scayt/dialogs/toolbar.css | 71 + .../showblocks/images/block_address.png | Bin 0 -> 171 bytes .../showblocks/images/block_blockquote.png | Bin 0 -> 181 bytes .../plugins/showblocks/images/block_div.png | Bin 0 -> 136 bytes .../plugins/showblocks/images/block_h1.png | Bin 0 -> 127 bytes .../plugins/showblocks/images/block_h2.png | Bin 0 -> 134 bytes .../plugins/showblocks/images/block_h3.png | Bin 0 -> 131 bytes .../plugins/showblocks/images/block_h4.png | Bin 0 -> 133 bytes .../plugins/showblocks/images/block_h5.png | Bin 0 -> 133 bytes .../plugins/showblocks/images/block_h6.png | Bin 0 -> 129 bytes .../plugins/showblocks/images/block_p.png | Bin 0 -> 119 bytes .../plugins/showblocks/images/block_pre.png | Bin 0 -> 136 bytes .../ckeditor/plugins/smiley/dialogs/smiley.js | 10 + .../plugins/smiley/images/angel_smile.gif | Bin 0 -> 1250 bytes .../plugins/smiley/images/angel_smile.png | Bin 0 -> 1294 bytes .../plugins/smiley/images/angry_smile.gif | Bin 0 -> 1221 bytes .../plugins/smiley/images/angry_smile.png | Bin 0 -> 1351 bytes .../plugins/smiley/images/broken_heart.gif | Bin 0 -> 1131 bytes .../plugins/smiley/images/broken_heart.png | Bin 0 -> 1213 bytes .../plugins/smiley/images/confused_smile.gif | Bin 0 -> 1210 bytes .../plugins/smiley/images/confused_smile.png | Bin 0 -> 1175 bytes .../plugins/smiley/images/cry_smile.gif | Bin 0 -> 795 bytes .../plugins/smiley/images/cry_smile.png | Bin 0 -> 1315 bytes .../plugins/smiley/images/devil_smile.gif | Bin 0 -> 1239 bytes .../plugins/smiley/images/devil_smile.png | Bin 0 -> 1299 bytes .../smiley/images/embaressed_smile.gif | Bin 0 -> 790 bytes .../smiley/images/embarrassed_smile.gif | Bin 0 -> 790 bytes .../smiley/images/embarrassed_smile.png | Bin 0 -> 1222 bytes .../plugins/smiley/images/envelope.gif | Bin 0 -> 712 bytes .../plugins/smiley/images/envelope.png | Bin 0 -> 1049 bytes .../ckeditor/plugins/smiley/images/heart.gif | Bin 0 -> 1091 bytes .../ckeditor/plugins/smiley/images/heart.png | Bin 0 -> 1073 bytes .../ckeditor/plugins/smiley/images/kiss.gif | Bin 0 -> 1082 bytes .../ckeditor/plugins/smiley/images/kiss.png | Bin 0 -> 1077 bytes .../plugins/smiley/images/lightbulb.gif | Bin 0 -> 1062 bytes .../plugins/smiley/images/lightbulb.png | Bin 0 -> 993 bytes .../plugins/smiley/images/omg_smile.gif | Bin 0 -> 1207 bytes .../plugins/smiley/images/omg_smile.png | Bin 0 -> 1196 bytes .../plugins/smiley/images/regular_smile.gif | Bin 0 -> 1216 bytes .../plugins/smiley/images/regular_smile.png | Bin 0 -> 1158 bytes .../plugins/smiley/images/sad_smile.gif | Bin 0 -> 1199 bytes .../plugins/smiley/images/sad_smile.png | Bin 0 -> 1189 bytes .../plugins/smiley/images/shades_smile.gif | Bin 0 -> 1234 bytes .../plugins/smiley/images/shades_smile.png | Bin 0 -> 1353 bytes .../plugins/smiley/images/teeth_smile.gif | Bin 0 -> 1210 bytes .../plugins/smiley/images/teeth_smile.png | Bin 0 -> 1257 bytes .../plugins/smiley/images/thumbs_down.gif | Bin 0 -> 1117 bytes .../plugins/smiley/images/thumbs_down.png | Bin 0 -> 1059 bytes .../plugins/smiley/images/thumbs_up.gif | Bin 0 -> 1112 bytes .../plugins/smiley/images/thumbs_up.png | Bin 0 -> 1033 bytes .../plugins/smiley/images/tongue_smile.gif | Bin 0 -> 1216 bytes .../plugins/smiley/images/tongue_smile.png | Bin 0 -> 1206 bytes .../plugins/smiley/images/tounge_smile.gif | Bin 0 -> 1216 bytes .../images/whatchutalkingabout_smile.gif | Bin 0 -> 1190 bytes .../images/whatchutalkingabout_smile.png | Bin 0 -> 1113 bytes .../plugins/smiley/images/wink_smile.gif | Bin 0 -> 1214 bytes .../plugins/smiley/images/wink_smile.png | Bin 0 -> 1188 bytes .../dialogs/lang/_translationstatus.txt | 20 + .../plugins/specialchar/dialogs/lang/ar.js | 13 + .../plugins/specialchar/dialogs/lang/bg.js | 13 + .../plugins/specialchar/dialogs/lang/ca.js | 14 + .../plugins/specialchar/dialogs/lang/cs.js | 13 + .../plugins/specialchar/dialogs/lang/cy.js | 14 + .../plugins/specialchar/dialogs/lang/de.js | 13 + .../plugins/specialchar/dialogs/lang/el.js | 13 + .../plugins/specialchar/dialogs/lang/en-gb.js | 13 + .../plugins/specialchar/dialogs/lang/en.js | 13 + .../plugins/specialchar/dialogs/lang/eo.js | 12 + .../plugins/specialchar/dialogs/lang/es.js | 13 + .../plugins/specialchar/dialogs/lang/et.js | 13 + .../plugins/specialchar/dialogs/lang/fa.js | 12 + .../plugins/specialchar/dialogs/lang/fi.js | 13 + .../plugins/specialchar/dialogs/lang/fr-ca.js | 10 + .../plugins/specialchar/dialogs/lang/fr.js | 11 + .../plugins/specialchar/dialogs/lang/gl.js | 13 + .../plugins/specialchar/dialogs/lang/he.js | 12 + .../plugins/specialchar/dialogs/lang/hr.js | 13 + .../plugins/specialchar/dialogs/lang/hu.js | 12 + .../plugins/specialchar/dialogs/lang/id.js | 13 + .../plugins/specialchar/dialogs/lang/it.js | 14 + .../plugins/specialchar/dialogs/lang/ja.js | 9 + .../plugins/specialchar/dialogs/lang/km.js | 13 + .../plugins/specialchar/dialogs/lang/ku.js | 13 + .../plugins/specialchar/dialogs/lang/lv.js | 13 + .../plugins/specialchar/dialogs/lang/nb.js | 11 + .../plugins/specialchar/dialogs/lang/nl.js | 13 + .../plugins/specialchar/dialogs/lang/no.js | 11 + .../plugins/specialchar/dialogs/lang/pl.js | 12 + .../plugins/specialchar/dialogs/lang/pt-br.js | 11 + .../plugins/specialchar/dialogs/lang/pt.js | 13 + .../plugins/specialchar/dialogs/lang/ru.js | 13 + .../plugins/specialchar/dialogs/lang/si.js | 13 + .../plugins/specialchar/dialogs/lang/sk.js | 13 + .../plugins/specialchar/dialogs/lang/sl.js | 12 + .../plugins/specialchar/dialogs/lang/sq.js | 13 + .../plugins/specialchar/dialogs/lang/sv.js | 11 + .../plugins/specialchar/dialogs/lang/th.js | 13 + .../plugins/specialchar/dialogs/lang/tr.js | 12 + .../plugins/specialchar/dialogs/lang/tt.js | 13 + .../plugins/specialchar/dialogs/lang/ug.js | 13 + .../plugins/specialchar/dialogs/lang/uk.js | 12 + .../plugins/specialchar/dialogs/lang/vi.js | 14 + .../plugins/specialchar/dialogs/lang/zh-cn.js | 9 + .../plugins/specialchar/dialogs/lang/zh.js | 12 + .../specialchar/dialogs/specialchar.js | 14 + .../plugins/stylesheetparser/plugin.js | 152 + .../samples/assets/sample.css | 70 + .../samples/stylesheetparser.html | 82 + .../plugins/symbol/dialogs/lang/en.js | 181 + .../ckeditor/plugins/symbol/dialogs/symbol.js | 18 + .../ckeditor/plugins/symbol/icons/symbol.png | Bin 0 -> 212 bytes .../ckeditor/plugins/symbol/lang/en.js | 1 + .../ckeditor/plugins/symbol/plugin.js | 15 + .../ckeditor/plugins/table/dialogs/table.js | 21 + .../plugins/tabletools/dialogs/tableCell.js | 17 + .../plugins/templates/dialogs/templates.css | 84 + .../plugins/templates/dialogs/templates.js | 10 + .../plugins/templates/templates/default.js | 6 + .../templates/templates/images/template1.gif | Bin 0 -> 375 bytes .../templates/templates/images/template2.gif | Bin 0 -> 333 bytes .../templates/templates/images/template3.gif | Bin 0 -> 422 bytes .../ckeditor/plugins/wsc/LICENSE.md | 28 + .../ckeditor/plugins/wsc/README.md | 25 + .../ckeditor/plugins/wsc/dialogs/ciframe.html | 66 + .../plugins/wsc/dialogs/tmpFrameset.html | 52 + .../ckeditor/plugins/wsc/dialogs/wsc.css | 82 + .../ckeditor/plugins/wsc/dialogs/wsc.js | 74 + .../ckeditor/plugins/wsc/dialogs/wsc_ie.js | 11 + .../javascripts/ckeditor/samples/ajax.html | 82 + .../javascripts/ckeditor/samples/api.html | 207 ++ .../ckeditor/samples/appendto.html | 57 + .../samples/assets/inlineall/logo.png | Bin 0 -> 4411 bytes .../assets/outputxhtml/outputxhtml.css | 204 + .../ckeditor/samples/assets/posteddata.php | 59 + .../ckeditor/samples/assets/sample.css | 3 + .../ckeditor/samples/assets/sample.jpg | Bin 0 -> 17932 bytes .../samples/assets/uilanguages/languages.js | 7 + .../ckeditor/samples/datafiltering.html | 401 ++ .../ckeditor/samples/divreplace.html | 141 + .../javascripts/ckeditor/samples/index.html | 128 + .../ckeditor/samples/inlineall.html | 311 ++ .../ckeditor/samples/inlinebycode.html | 121 + .../ckeditor/samples/inlinetextarea.html | 110 + .../javascripts/ckeditor/samples/jquery.html | 100 + .../plugins/dialog/assets/my_dialog.js | 48 + .../samples/plugins/dialog/dialog.html | 187 + .../samples/plugins/enterkey/enterkey.html | 103 + .../assets/outputforflash/outputforflash.fla | Bin 0 -> 85504 bytes .../assets/outputforflash/outputforflash.swf | Bin 0 -> 15571 bytes .../assets/outputforflash/swfobject.js | 18 + .../plugins/htmlwriter/outputforflash.html | 280 ++ .../plugins/htmlwriter/outputhtml.html | 221 ++ .../samples/plugins/magicline/magicline.html | 206 ++ .../samples/plugins/toolbar/toolbar.html | 232 ++ .../samples/plugins/wysiwygarea/fullpage.html | 77 + .../ckeditor/samples/readonly.html | 73 + .../ckeditor/samples/replacebyclass.html | 57 + .../ckeditor/samples/replacebycode.html | 56 + .../javascripts/ckeditor/samples/sample.css | 365 ++ .../javascripts/ckeditor/samples/sample.js | 50 + .../ckeditor/samples/sample_posteddata.php | 16 + .../ckeditor/samples/tabindex.html | 75 + .../javascripts/ckeditor/samples/uicolor.html | 69 + .../ckeditor/samples/uilanguages.html | 119 + .../ckeditor/samples/xhtmlstyle.html | 231 ++ .../ckeditor/skins/moono/dialog.css | 5 + .../ckeditor/skins/moono/dialog_ie.css | 5 + .../ckeditor/skins/moono/dialog_ie7.css | 5 + .../ckeditor/skins/moono/dialog_ie8.css | 5 + .../ckeditor/skins/moono/dialog_iequirks.css | 5 + .../ckeditor/skins/moono/editor.css | 5 + .../ckeditor/skins/moono/editor_gecko.css | 5 + .../ckeditor/skins/moono/editor_ie.css | 5 + .../ckeditor/skins/moono/editor_ie7.css | 5 + .../ckeditor/skins/moono/editor_ie8.css | 5 + .../ckeditor/skins/moono/editor_iequirks.css | 5 + .../ckeditor/skins/moono/icons.png | Bin 0 -> 20626 bytes .../ckeditor/skins/moono/icons_hidpi.png | Bin 0 -> 66930 bytes .../ckeditor/skins/moono/images/arrow.png | Bin 0 -> 261 bytes .../ckeditor/skins/moono/images/close.png | Bin 0 -> 824 bytes .../skins/moono/images/hidpi/close.png | Bin 0 -> 1792 bytes .../skins/moono/images/hidpi/lock-open.png | Bin 0 -> 1503 bytes .../skins/moono/images/hidpi/lock.png | Bin 0 -> 1616 bytes .../skins/moono/images/hidpi/refresh.png | Bin 0 -> 2320 bytes .../ckeditor/skins/moono/images/lock-open.png | Bin 0 -> 736 bytes .../ckeditor/skins/moono/images/lock.png | Bin 0 -> 728 bytes .../ckeditor/skins/moono/images/refresh.png | Bin 0 -> 953 bytes .../ckeditor/skins/moono/readme.md | 51 + nterchange/javascripts/ckeditor/styles.js | 111 + nterchange/javascripts/controls.js | 875 +++++ .../javascripts/datechooser/changelog.txt | 58 + .../javascripts/datechooser/datechooser.css | 18 + .../javascripts/datechooser/datechooser.js | 1031 ++++++ .../javascripts/datechooser/datechooser.png | Bin 0 -> 647 bytes .../javascripts/datechooser/readme.html | 426 +++ nterchange/javascripts/dragdrop.js | 970 +++++ nterchange/javascripts/effects.js | 1094 ++++++ nterchange/javascripts/nterchange.js | 121 + nterchange/javascripts/page.js | 80 + nterchange/javascripts/page_content.js | 80 + nterchange/javascripts/prototype.js | 3277 +++++++++++++++++ nterchange/javascripts/scriptaculous.js | 58 + nterchange/javascripts/slider.js | 277 ++ nterchange/javascripts/sound.js | 60 + nterchange/javascripts/surftoedit.js | 15 + nterchange/javascripts/unittest.js | 564 +++ nterchange/javascripts/workflow.js | 30 + nterchange/stylesheets/audit_trail.css | 30 + nterchange/stylesheets/forms.css | 45 + nterchange/stylesheets/global.css | 35 + nterchange/stylesheets/handheld.css | 128 + nterchange/stylesheets/layout.css | 143 + nterchange/stylesheets/lists.css | 260 ++ nterchange/stylesheets/nterchange.css | 128 + nterchange/stylesheets/print.css | 0 nterchange/stylesheets/scaffold.css | 72 + nterchange/stylesheets/screen.css | 12 + nterchange/stylesheets/surftoedit.css | 88 + nterchange/stylesheets/typography.css | 59 + nterchange/stylesheets/workflow.css | 10 + package.json | 12 + page_content_grid.sql | 76 + test/environment.php | 25 + test/fixtures/base_schema.sql | 573 +++ test/fixtures/test_sample.sql | 6 + test/phpunit.xml | 14 + test/unit/AuditTrailControllerTest.php | 59 + test/unit/NControllerTest.php | 44 + test/unit/NDispatcherTest.php | 36 + test/unit/NModelTest.php | 152 + version.yml | 5 + 627 files changed, 41895 insertions(+) create mode 100644 .bowerrc create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 Rakefile create mode 100644 app/controllers/admin_controller.php create mode 100644 app/controllers/asset_controller.php create mode 100644 app/controllers/audit_trail_controller.php create mode 100644 app/controllers/cms_asset_info_controller.php create mode 100644 app/controllers/cms_asset_template_controller.php create mode 100644 app/controllers/cms_drafts_controller.php create mode 100644 app/controllers/code_caller_controller.php create mode 100644 app/controllers/content_controller.php create mode 100644 app/controllers/csv_export_controller.php create mode 100644 app/controllers/dashboard_controller.php create mode 100644 app/controllers/excel_export_controller.php create mode 100644 app/controllers/imageviewer_controller.php create mode 100644 app/controllers/login_controller.php create mode 100644 app/controllers/memcache_controller.php create mode 100644 app/controllers/nterchange_controller.php create mode 100644 app/controllers/page_content_controller.php create mode 100755 app/controllers/page_controller.php create mode 100644 app/controllers/page_template_containers_controller.php create mode 100644 app/controllers/page_template_controller.php create mode 100755 app/controllers/phpinfo_controller.php create mode 100644 app/controllers/redirect_controller.php create mode 100644 app/controllers/rss_controller.php create mode 100644 app/controllers/search_controller.php create mode 100644 app/controllers/settings_controller.php create mode 100644 app/controllers/site_admin_controller.php create mode 100644 app/controllers/test_sample_controller.php create mode 100644 app/controllers/users_controller.php create mode 100644 app/controllers/version_check_controller.php create mode 100644 app/controllers/version_controller.php create mode 100644 app/controllers/workflow_controller.php create mode 100644 app/controllers/workflow_group_controller.php create mode 100644 app/controllers/workflow_users_controller.php create mode 100644 app/helpers/audit_trail_helper.php create mode 100644 app/helpers/cms_asset_info_helper.php create mode 100644 app/helpers/cms_asset_template_helper.php create mode 100644 app/helpers/content_helper.php create mode 100644 app/helpers/dashboard_helper.php create mode 100644 app/helpers/login_helper.php create mode 100644 app/helpers/page_content_helper.php create mode 100644 app/helpers/page_helper.php create mode 100644 app/helpers/page_template_containers_helper.php create mode 100644 app/helpers/page_template_helper.php create mode 100644 app/helpers/settings_helper.php create mode 100644 app/helpers/site_admin_helper.php create mode 100644 app/helpers/users_helper.php create mode 100644 app/models/action_track.php create mode 100644 app/models/cms_asset_info.php create mode 100644 app/models/cms_asset_template.php create mode 100644 app/models/cms_audit_trail.php create mode 100644 app/models/cms_auth.php create mode 100644 app/models/cms_drafts.php create mode 100644 app/models/cms_nterchange_versions.php create mode 100644 app/models/cms_settings.php create mode 100644 app/models/code_caller.php create mode 100644 app/models/page.php create mode 100644 app/models/page_content.php create mode 100644 app/models/page_template.php create mode 100644 app/models/page_template_containers.php create mode 100644 app/models/permissions.php create mode 100644 app/models/redirect.php create mode 100644 app/models/test_sample.php create mode 100644 app/models/workflow.php create mode 100644 app/models/workflow_group.php create mode 100644 app/models/workflow_users.php create mode 100755 app/views/audit_trail/audit_trail_record.html create mode 100644 app/views/audit_trail/page.html create mode 100644 app/views/audit_trail/page_audit_trail_record.html create mode 100644 app/views/audit_trail/viewlist.html create mode 100644 app/views/ck_upload/image_browse.html create mode 100644 app/views/ck_upload/media_browse.html create mode 100644 app/views/cms_asset_info/viewlist.html create mode 100644 app/views/cms_asset_template/edit.html create mode 100644 app/views/cms_asset_template/show.html create mode 100644 app/views/cms_asset_template/viewlist.html create mode 100644 app/views/code_caller/default.html create mode 100644 app/views/content/list_assets.html create mode 100644 app/views/dashboard/dashboard_client_content.html create mode 100644 app/views/dashboard/dashboard_client_sidebar_content.html create mode 100644 app/views/dashboard/description.html create mode 100644 app/views/dashboard/draft_record.html create mode 100644 app/views/dashboard/index.html create mode 100644 app/views/dashboard/no_drafts.html create mode 100644 app/views/dashboard/no_workflows.html create mode 100644 app/views/dashboard/nterchange_training.html create mode 100644 app/views/dashboard/workflow.html create mode 100644 app/views/dashboard/workflow_description.html create mode 100644 app/views/dashboard/workflow_norecords.html create mode 100755 app/views/dashboard/workflow_page_submit.html create mode 100644 app/views/dashboard/workflow_record.html create mode 100644 app/views/dashboard/workflow_section.html create mode 100644 app/views/imageviewer/index.php create mode 100644 app/views/layouts/default.html create mode 100644 app/views/layouts/head.html create mode 100644 app/views/layouts/login.html create mode 100644 app/views/layouts/logo.html create mode 100644 app/views/layouts/navigation.html create mode 100644 app/views/layouts/plain.html create mode 100755 app/views/layouts/previewobject.html create mode 100644 app/views/layouts/simple.html create mode 100644 app/views/layouts/subnav.html create mode 100644 app/views/layouts/tail.html create mode 100644 app/views/page/children_container.html create mode 100644 app/views/page/content_container.html create mode 100644 app/views/page/content_container_title.html create mode 100644 app/views/page/reorder_close.html create mode 100755 app/views/page/sidebar.html create mode 100755 app/views/page/surftoedit.html create mode 100644 app/views/page_content/asset_add.html create mode 100644 app/views/page_content/asset_edit.html create mode 100644 app/views/page_content/form.html create mode 100644 app/views/page_template/viewlist.html create mode 100644 app/views/page_template_containers/edit.html create mode 100644 app/views/page_template_containers/show.html create mode 100644 app/views/page_template_containers/viewlist.html create mode 100644 app/views/rss/audit_trail.html create mode 100644 app/views/settings/viewlist.html create mode 100644 app/views/site_admin/clear_all_cache.html create mode 100644 app/views/site_admin/site_admin.html create mode 100644 app/views/site_admin/site_admin_list_end.html create mode 100644 app/views/site_admin/site_admin_list_start.html create mode 100644 app/views/site_admin/sitemap_list_item.html create mode 100644 app/views/templates/create.html create mode 100644 app/views/templates/edit.html create mode 100644 app/views/templates/page_content.html create mode 100644 app/views/templates/show.html create mode 100644 app/views/templates/sidebar_edit_status.html create mode 100644 app/views/templates/sidebar_page_content.html create mode 100644 app/views/templates/sidebar_versions.html create mode 100644 app/views/templates/viewlist.html create mode 100644 app/views/text/default.html create mode 100644 app/views/users/confirmation_email.html create mode 100644 app/views/users/password_email.html create mode 100644 app/views/users/viewlist.html create mode 100644 app/views/version/view.html create mode 100644 app/views/version_check/dashboard_version_check.html create mode 100644 app/views/workflow/disapproved.html create mode 100644 app/views/workflow/process.html create mode 100644 app/views/workflow/published.html create mode 100644 app/views/workflow/removed.html create mode 100644 app/views/workflow/send.html create mode 100644 app/views/workflow_group/viewlist.html create mode 100644 app/views/workflow_group/workflow_description.html create mode 100644 app/views/workflow_group/workflow_group.html create mode 100644 app/views/workflow_users/workflow_user.html create mode 100644 bower.json create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 config/config.php create mode 100644 lib/NConfig.php create mode 100644 lib/NUpload.php create mode 100644 lib/NUpload/Local.php create mode 100644 lib/NUpload/S3.php create mode 100644 lib/app_controller.php create mode 100644 lib/controller/form.php create mode 100644 lib/controller/inflector.php create mode 100644 lib/mirror/ftp_mirror.php create mode 100644 lib/mirror/rsync_mirror.php create mode 100644 lib/mirror/s3_mirror.php create mode 100644 lib/model/fixtures.php create mode 100644 lib/model/tree.php create mode 100644 lib/model/value_cast.php create mode 100644 lib/n_asset.php create mode 100644 lib/n_auth.php create mode 100755 lib/n_cache.php create mode 100644 lib/n_controller.php create mode 100644 lib/n_date.php create mode 100755 lib/n_db.php create mode 100644 lib/n_debug.php create mode 100644 lib/n_dispatcher.php create mode 100644 lib/n_download.php create mode 100644 lib/n_filesystem.php create mode 100644 lib/n_flash.php create mode 100644 lib/n_image.php create mode 100644 lib/n_mirror.php create mode 100644 lib/n_model.php create mode 100644 lib/n_object.php create mode 100644 lib/n_quickform.php create mode 100644 lib/n_server.php create mode 100644 lib/n_view.php create mode 100644 lib/view/helper.php create mode 100644 lib/view/helpers/action_track_helper.php create mode 100755 lib/view/helpers/asset_tag_helper.php create mode 100644 lib/view/helpers/date_helper.php create mode 100644 lib/view/helpers/filesystem_helper.php create mode 100755 lib/view/helpers/javascript_helper.php create mode 100644 lib/view/helpers/search_helper.php create mode 100755 lib/view/helpers/tag_helper.php create mode 100755 lib/view/helpers/url_helper.php create mode 100644 nterchange/check.php create mode 100644 nterchange/images/add.gif create mode 100644 nterchange/images/created_by.gif create mode 100644 nterchange/images/drag.gif create mode 100644 nterchange/images/edit.gif create mode 100644 nterchange/images/icon_alert.png create mode 100644 nterchange/images/icon_check.gif create mode 100644 nterchange/images/icon_error.png create mode 100644 nterchange/images/icon_help.png create mode 100644 nterchange/images/icon_x.gif create mode 100644 nterchange/images/indicator.gif create mode 100644 nterchange/images/listarrow.gif create mode 100644 nterchange/images/nterchange.gif create mode 100644 nterchange/images/nterchange3_manual.pdf create mode 100644 nterchange/images/order.gif create mode 100755 nterchange/images/otf/button.php create mode 100644 nterchange/images/otf/button/button_l.gif create mode 100644 nterchange/images/otf/button/button_m.gif create mode 100644 nterchange/images/otf/button/button_r.gif create mode 100644 nterchange/images/otf/fonts/mini7.ttf create mode 100644 nterchange/images/remove.gif create mode 100755 nterchange/images/s_asc.gif create mode 100755 nterchange/images/s_desc.gif create mode 100644 nterchange/images/shadow_bg.png create mode 100644 nterchange/images/shadow_bl.gif create mode 100644 nterchange/images/shadow_br.gif create mode 100644 nterchange/images/shadow_tr.gif create mode 100644 nterchange/images/site_admin_bg.gif create mode 100644 nterchange/images/subtab_off.gif create mode 100644 nterchange/images/subtab_on.gif create mode 100644 nterchange/images/subtab_over.gif create mode 100644 nterchange/images/timed.gif create mode 100644 nterchange/index.php create mode 100644 nterchange/javascripts/builder.js create mode 100644 nterchange/javascripts/ckeditor/CHANGES.md create mode 100644 nterchange/javascripts/ckeditor/LICENSE.md create mode 100644 nterchange/javascripts/ckeditor/README.md create mode 100644 nterchange/javascripts/ckeditor/adapters/jquery.js create mode 100644 nterchange/javascripts/ckeditor/build-config.js create mode 100644 nterchange/javascripts/ckeditor/ckeditor.js create mode 100644 nterchange/javascripts/ckeditor/config.js create mode 100644 nterchange/javascripts/ckeditor/contents.css create mode 100644 nterchange/javascripts/ckeditor/lang/af.js create mode 100644 nterchange/javascripts/ckeditor/lang/ar.js create mode 100644 nterchange/javascripts/ckeditor/lang/bg.js create mode 100644 nterchange/javascripts/ckeditor/lang/bn.js create mode 100644 nterchange/javascripts/ckeditor/lang/bs.js create mode 100644 nterchange/javascripts/ckeditor/lang/ca.js create mode 100644 nterchange/javascripts/ckeditor/lang/cs.js create mode 100644 nterchange/javascripts/ckeditor/lang/cy.js create mode 100644 nterchange/javascripts/ckeditor/lang/da.js create mode 100644 nterchange/javascripts/ckeditor/lang/de.js create mode 100644 nterchange/javascripts/ckeditor/lang/el.js create mode 100644 nterchange/javascripts/ckeditor/lang/en-au.js create mode 100644 nterchange/javascripts/ckeditor/lang/en-ca.js create mode 100644 nterchange/javascripts/ckeditor/lang/en-gb.js create mode 100644 nterchange/javascripts/ckeditor/lang/en.js create mode 100644 nterchange/javascripts/ckeditor/lang/eo.js create mode 100644 nterchange/javascripts/ckeditor/lang/es.js create mode 100644 nterchange/javascripts/ckeditor/lang/et.js create mode 100644 nterchange/javascripts/ckeditor/lang/eu.js create mode 100644 nterchange/javascripts/ckeditor/lang/fa.js create mode 100644 nterchange/javascripts/ckeditor/lang/fi.js create mode 100644 nterchange/javascripts/ckeditor/lang/fo.js create mode 100644 nterchange/javascripts/ckeditor/lang/fr-ca.js create mode 100644 nterchange/javascripts/ckeditor/lang/fr.js create mode 100644 nterchange/javascripts/ckeditor/lang/gl.js create mode 100644 nterchange/javascripts/ckeditor/lang/gu.js create mode 100644 nterchange/javascripts/ckeditor/lang/he.js create mode 100644 nterchange/javascripts/ckeditor/lang/hi.js create mode 100644 nterchange/javascripts/ckeditor/lang/hr.js create mode 100644 nterchange/javascripts/ckeditor/lang/hu.js create mode 100644 nterchange/javascripts/ckeditor/lang/is.js create mode 100644 nterchange/javascripts/ckeditor/lang/it.js create mode 100644 nterchange/javascripts/ckeditor/lang/ja.js create mode 100644 nterchange/javascripts/ckeditor/lang/ka.js create mode 100644 nterchange/javascripts/ckeditor/lang/km.js create mode 100644 nterchange/javascripts/ckeditor/lang/ko.js create mode 100644 nterchange/javascripts/ckeditor/lang/ku.js create mode 100644 nterchange/javascripts/ckeditor/lang/lt.js create mode 100644 nterchange/javascripts/ckeditor/lang/lv.js create mode 100644 nterchange/javascripts/ckeditor/lang/mk.js create mode 100644 nterchange/javascripts/ckeditor/lang/mn.js create mode 100644 nterchange/javascripts/ckeditor/lang/ms.js create mode 100644 nterchange/javascripts/ckeditor/lang/nb.js create mode 100644 nterchange/javascripts/ckeditor/lang/nl.js create mode 100644 nterchange/javascripts/ckeditor/lang/no.js create mode 100644 nterchange/javascripts/ckeditor/lang/pl.js create mode 100644 nterchange/javascripts/ckeditor/lang/pt-br.js create mode 100644 nterchange/javascripts/ckeditor/lang/pt.js create mode 100644 nterchange/javascripts/ckeditor/lang/ro.js create mode 100644 nterchange/javascripts/ckeditor/lang/ru.js create mode 100644 nterchange/javascripts/ckeditor/lang/si.js create mode 100644 nterchange/javascripts/ckeditor/lang/sk.js create mode 100644 nterchange/javascripts/ckeditor/lang/sl.js create mode 100644 nterchange/javascripts/ckeditor/lang/sq.js create mode 100644 nterchange/javascripts/ckeditor/lang/sr-latn.js create mode 100644 nterchange/javascripts/ckeditor/lang/sr.js create mode 100644 nterchange/javascripts/ckeditor/lang/sv.js create mode 100644 nterchange/javascripts/ckeditor/lang/th.js create mode 100644 nterchange/javascripts/ckeditor/lang/tr.js create mode 100644 nterchange/javascripts/ckeditor/lang/ug.js create mode 100644 nterchange/javascripts/ckeditor/lang/uk.js create mode 100644 nterchange/javascripts/ckeditor/lang/vi.js create mode 100644 nterchange/javascripts/ckeditor/lang/zh-cn.js create mode 100644 nterchange/javascripts/ckeditor/lang/zh.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/a11yhelp.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/_translationstatus.txt create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/ar.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/bg.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/ca.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/cs.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/cy.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/da.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/de.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/el.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/en-gb.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/en.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/eo.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/es.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/et.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/fa.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/fi.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/fr-ca.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/fr.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/gl.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/gu.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/he.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/hi.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/hr.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/hu.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/id.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/it.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/ja.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/km.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/ko.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/ku.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/lt.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/lv.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/mk.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/mn.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/nb.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/nl.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/no.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/pl.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/pt-br.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/pt.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/ro.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/ru.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/si.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/sk.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/sl.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/sq.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/sr-latn.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/sr.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/sv.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/th.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/tr.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/tt.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/ug.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/uk.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/vi.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/zh-cn.js create mode 100644 nterchange/javascripts/ckeditor/plugins/a11yhelp/dialogs/lang/zh.js create mode 100644 nterchange/javascripts/ckeditor/plugins/about/dialogs/about.js create mode 100644 nterchange/javascripts/ckeditor/plugins/about/dialogs/hidpi/logo_ckeditor.png create mode 100644 nterchange/javascripts/ckeditor/plugins/about/dialogs/logo_ckeditor.png create mode 100644 nterchange/javascripts/ckeditor/plugins/clipboard/dialogs/paste.js create mode 100644 nterchange/javascripts/ckeditor/plugins/colordialog/dialogs/colordialog.js create mode 100644 nterchange/javascripts/ckeditor/plugins/dialog/dialogDefinition.js create mode 100644 nterchange/javascripts/ckeditor/plugins/div/dialogs/div.js create mode 100644 nterchange/javascripts/ckeditor/plugins/find/dialogs/find.js create mode 100644 nterchange/javascripts/ckeditor/plugins/flash/dialogs/flash.js create mode 100644 nterchange/javascripts/ckeditor/plugins/flash/images/placeholder.png create mode 100644 nterchange/javascripts/ckeditor/plugins/forms/dialogs/button.js create mode 100644 nterchange/javascripts/ckeditor/plugins/forms/dialogs/checkbox.js create mode 100644 nterchange/javascripts/ckeditor/plugins/forms/dialogs/form.js create mode 100644 nterchange/javascripts/ckeditor/plugins/forms/dialogs/hiddenfield.js create mode 100644 nterchange/javascripts/ckeditor/plugins/forms/dialogs/radio.js create mode 100644 nterchange/javascripts/ckeditor/plugins/forms/dialogs/select.js create mode 100644 nterchange/javascripts/ckeditor/plugins/forms/dialogs/textarea.js create mode 100644 nterchange/javascripts/ckeditor/plugins/forms/dialogs/textfield.js create mode 100644 nterchange/javascripts/ckeditor/plugins/forms/images/hiddenfield.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/icons.png create mode 100644 nterchange/javascripts/ckeditor/plugins/icons_hidpi.png create mode 100644 nterchange/javascripts/ckeditor/plugins/iframe/dialogs/iframe.js create mode 100644 nterchange/javascripts/ckeditor/plugins/iframe/images/placeholder.png create mode 100644 nterchange/javascripts/ckeditor/plugins/image/dialogs/image.js create mode 100644 nterchange/javascripts/ckeditor/plugins/image/images/noimage.png create mode 100644 nterchange/javascripts/ckeditor/plugins/link/dialogs/anchor.js create mode 100644 nterchange/javascripts/ckeditor/plugins/link/dialogs/link.js create mode 100644 nterchange/javascripts/ckeditor/plugins/link/images/anchor.png create mode 100644 nterchange/javascripts/ckeditor/plugins/link/images/hidpi/anchor.png create mode 100644 nterchange/javascripts/ckeditor/plugins/liststyle/dialogs/liststyle.js create mode 100644 nterchange/javascripts/ckeditor/plugins/magicline/images/hidpi/icon.png create mode 100644 nterchange/javascripts/ckeditor/plugins/magicline/images/icon.png create mode 100644 nterchange/javascripts/ckeditor/plugins/pagebreak/images/pagebreak.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/pastefromword/filter/default.js create mode 100644 nterchange/javascripts/ckeditor/plugins/preview/preview.html create mode 100644 nterchange/javascripts/ckeditor/plugins/scayt/LICENSE.md create mode 100644 nterchange/javascripts/ckeditor/plugins/scayt/README.md create mode 100644 nterchange/javascripts/ckeditor/plugins/scayt/dialogs/options.js create mode 100644 nterchange/javascripts/ckeditor/plugins/scayt/dialogs/toolbar.css create mode 100644 nterchange/javascripts/ckeditor/plugins/showblocks/images/block_address.png create mode 100644 nterchange/javascripts/ckeditor/plugins/showblocks/images/block_blockquote.png create mode 100644 nterchange/javascripts/ckeditor/plugins/showblocks/images/block_div.png create mode 100644 nterchange/javascripts/ckeditor/plugins/showblocks/images/block_h1.png create mode 100644 nterchange/javascripts/ckeditor/plugins/showblocks/images/block_h2.png create mode 100644 nterchange/javascripts/ckeditor/plugins/showblocks/images/block_h3.png create mode 100644 nterchange/javascripts/ckeditor/plugins/showblocks/images/block_h4.png create mode 100644 nterchange/javascripts/ckeditor/plugins/showblocks/images/block_h5.png create mode 100644 nterchange/javascripts/ckeditor/plugins/showblocks/images/block_h6.png create mode 100644 nterchange/javascripts/ckeditor/plugins/showblocks/images/block_p.png create mode 100644 nterchange/javascripts/ckeditor/plugins/showblocks/images/block_pre.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/dialogs/smiley.js create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/angel_smile.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/angel_smile.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/angry_smile.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/angry_smile.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/broken_heart.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/broken_heart.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/confused_smile.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/confused_smile.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/cry_smile.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/cry_smile.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/devil_smile.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/devil_smile.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/embaressed_smile.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/embarrassed_smile.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/embarrassed_smile.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/envelope.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/envelope.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/heart.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/heart.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/kiss.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/kiss.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/lightbulb.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/lightbulb.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/omg_smile.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/omg_smile.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/regular_smile.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/regular_smile.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/sad_smile.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/sad_smile.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/shades_smile.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/shades_smile.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/teeth_smile.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/teeth_smile.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/thumbs_down.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/thumbs_down.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/thumbs_up.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/thumbs_up.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/tongue_smile.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/tongue_smile.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/tounge_smile.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/whatchutalkingabout_smile.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/whatchutalkingabout_smile.png create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/wink_smile.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/smiley/images/wink_smile.png create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/_translationstatus.txt create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/ar.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/bg.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/ca.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/cs.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/cy.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/de.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/el.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/en-gb.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/en.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/eo.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/es.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/et.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/fa.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/fi.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/fr-ca.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/fr.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/gl.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/he.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/hr.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/hu.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/id.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/it.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/ja.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/km.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/ku.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/lv.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/nb.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/nl.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/no.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/pl.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/pt-br.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/pt.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/ru.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/si.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/sk.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/sl.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/sq.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/sv.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/th.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/tr.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/tt.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/ug.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/uk.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/vi.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/zh-cn.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/lang/zh.js create mode 100644 nterchange/javascripts/ckeditor/plugins/specialchar/dialogs/specialchar.js create mode 100644 nterchange/javascripts/ckeditor/plugins/stylesheetparser/plugin.js create mode 100644 nterchange/javascripts/ckeditor/plugins/stylesheetparser/samples/assets/sample.css create mode 100644 nterchange/javascripts/ckeditor/plugins/stylesheetparser/samples/stylesheetparser.html create mode 100755 nterchange/javascripts/ckeditor/plugins/symbol/dialogs/lang/en.js create mode 100755 nterchange/javascripts/ckeditor/plugins/symbol/dialogs/symbol.js create mode 100755 nterchange/javascripts/ckeditor/plugins/symbol/icons/symbol.png create mode 100755 nterchange/javascripts/ckeditor/plugins/symbol/lang/en.js create mode 100755 nterchange/javascripts/ckeditor/plugins/symbol/plugin.js create mode 100644 nterchange/javascripts/ckeditor/plugins/table/dialogs/table.js create mode 100644 nterchange/javascripts/ckeditor/plugins/tabletools/dialogs/tableCell.js create mode 100644 nterchange/javascripts/ckeditor/plugins/templates/dialogs/templates.css create mode 100644 nterchange/javascripts/ckeditor/plugins/templates/dialogs/templates.js create mode 100644 nterchange/javascripts/ckeditor/plugins/templates/templates/default.js create mode 100644 nterchange/javascripts/ckeditor/plugins/templates/templates/images/template1.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/templates/templates/images/template2.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/templates/templates/images/template3.gif create mode 100644 nterchange/javascripts/ckeditor/plugins/wsc/LICENSE.md create mode 100644 nterchange/javascripts/ckeditor/plugins/wsc/README.md create mode 100644 nterchange/javascripts/ckeditor/plugins/wsc/dialogs/ciframe.html create mode 100644 nterchange/javascripts/ckeditor/plugins/wsc/dialogs/tmpFrameset.html create mode 100644 nterchange/javascripts/ckeditor/plugins/wsc/dialogs/wsc.css create mode 100644 nterchange/javascripts/ckeditor/plugins/wsc/dialogs/wsc.js create mode 100644 nterchange/javascripts/ckeditor/plugins/wsc/dialogs/wsc_ie.js create mode 100644 nterchange/javascripts/ckeditor/samples/ajax.html create mode 100644 nterchange/javascripts/ckeditor/samples/api.html create mode 100644 nterchange/javascripts/ckeditor/samples/appendto.html create mode 100644 nterchange/javascripts/ckeditor/samples/assets/inlineall/logo.png create mode 100644 nterchange/javascripts/ckeditor/samples/assets/outputxhtml/outputxhtml.css create mode 100644 nterchange/javascripts/ckeditor/samples/assets/posteddata.php create mode 100644 nterchange/javascripts/ckeditor/samples/assets/sample.css create mode 100644 nterchange/javascripts/ckeditor/samples/assets/sample.jpg create mode 100644 nterchange/javascripts/ckeditor/samples/assets/uilanguages/languages.js create mode 100644 nterchange/javascripts/ckeditor/samples/datafiltering.html create mode 100644 nterchange/javascripts/ckeditor/samples/divreplace.html create mode 100644 nterchange/javascripts/ckeditor/samples/index.html create mode 100644 nterchange/javascripts/ckeditor/samples/inlineall.html create mode 100644 nterchange/javascripts/ckeditor/samples/inlinebycode.html create mode 100644 nterchange/javascripts/ckeditor/samples/inlinetextarea.html create mode 100644 nterchange/javascripts/ckeditor/samples/jquery.html create mode 100644 nterchange/javascripts/ckeditor/samples/plugins/dialog/assets/my_dialog.js create mode 100644 nterchange/javascripts/ckeditor/samples/plugins/dialog/dialog.html create mode 100644 nterchange/javascripts/ckeditor/samples/plugins/enterkey/enterkey.html create mode 100644 nterchange/javascripts/ckeditor/samples/plugins/htmlwriter/assets/outputforflash/outputforflash.fla create mode 100644 nterchange/javascripts/ckeditor/samples/plugins/htmlwriter/assets/outputforflash/outputforflash.swf create mode 100644 nterchange/javascripts/ckeditor/samples/plugins/htmlwriter/assets/outputforflash/swfobject.js create mode 100644 nterchange/javascripts/ckeditor/samples/plugins/htmlwriter/outputforflash.html create mode 100644 nterchange/javascripts/ckeditor/samples/plugins/htmlwriter/outputhtml.html create mode 100644 nterchange/javascripts/ckeditor/samples/plugins/magicline/magicline.html create mode 100644 nterchange/javascripts/ckeditor/samples/plugins/toolbar/toolbar.html create mode 100644 nterchange/javascripts/ckeditor/samples/plugins/wysiwygarea/fullpage.html create mode 100644 nterchange/javascripts/ckeditor/samples/readonly.html create mode 100644 nterchange/javascripts/ckeditor/samples/replacebyclass.html create mode 100644 nterchange/javascripts/ckeditor/samples/replacebycode.html create mode 100644 nterchange/javascripts/ckeditor/samples/sample.css create mode 100644 nterchange/javascripts/ckeditor/samples/sample.js create mode 100644 nterchange/javascripts/ckeditor/samples/sample_posteddata.php create mode 100644 nterchange/javascripts/ckeditor/samples/tabindex.html create mode 100644 nterchange/javascripts/ckeditor/samples/uicolor.html create mode 100644 nterchange/javascripts/ckeditor/samples/uilanguages.html create mode 100644 nterchange/javascripts/ckeditor/samples/xhtmlstyle.html create mode 100644 nterchange/javascripts/ckeditor/skins/moono/dialog.css create mode 100644 nterchange/javascripts/ckeditor/skins/moono/dialog_ie.css create mode 100644 nterchange/javascripts/ckeditor/skins/moono/dialog_ie7.css create mode 100644 nterchange/javascripts/ckeditor/skins/moono/dialog_ie8.css create mode 100644 nterchange/javascripts/ckeditor/skins/moono/dialog_iequirks.css create mode 100644 nterchange/javascripts/ckeditor/skins/moono/editor.css create mode 100644 nterchange/javascripts/ckeditor/skins/moono/editor_gecko.css create mode 100644 nterchange/javascripts/ckeditor/skins/moono/editor_ie.css create mode 100644 nterchange/javascripts/ckeditor/skins/moono/editor_ie7.css create mode 100644 nterchange/javascripts/ckeditor/skins/moono/editor_ie8.css create mode 100644 nterchange/javascripts/ckeditor/skins/moono/editor_iequirks.css create mode 100644 nterchange/javascripts/ckeditor/skins/moono/icons.png create mode 100644 nterchange/javascripts/ckeditor/skins/moono/icons_hidpi.png create mode 100644 nterchange/javascripts/ckeditor/skins/moono/images/arrow.png create mode 100644 nterchange/javascripts/ckeditor/skins/moono/images/close.png create mode 100644 nterchange/javascripts/ckeditor/skins/moono/images/hidpi/close.png create mode 100644 nterchange/javascripts/ckeditor/skins/moono/images/hidpi/lock-open.png create mode 100644 nterchange/javascripts/ckeditor/skins/moono/images/hidpi/lock.png create mode 100644 nterchange/javascripts/ckeditor/skins/moono/images/hidpi/refresh.png create mode 100644 nterchange/javascripts/ckeditor/skins/moono/images/lock-open.png create mode 100644 nterchange/javascripts/ckeditor/skins/moono/images/lock.png create mode 100644 nterchange/javascripts/ckeditor/skins/moono/images/refresh.png create mode 100644 nterchange/javascripts/ckeditor/skins/moono/readme.md create mode 100644 nterchange/javascripts/ckeditor/styles.js create mode 100644 nterchange/javascripts/controls.js create mode 100755 nterchange/javascripts/datechooser/changelog.txt create mode 100755 nterchange/javascripts/datechooser/datechooser.css create mode 100755 nterchange/javascripts/datechooser/datechooser.js create mode 100755 nterchange/javascripts/datechooser/datechooser.png create mode 100755 nterchange/javascripts/datechooser/readme.html create mode 100644 nterchange/javascripts/dragdrop.js create mode 100644 nterchange/javascripts/effects.js create mode 100644 nterchange/javascripts/nterchange.js create mode 100644 nterchange/javascripts/page.js create mode 100644 nterchange/javascripts/page_content.js create mode 100644 nterchange/javascripts/prototype.js create mode 100644 nterchange/javascripts/scriptaculous.js create mode 100644 nterchange/javascripts/slider.js create mode 100644 nterchange/javascripts/sound.js create mode 100644 nterchange/javascripts/surftoedit.js create mode 100644 nterchange/javascripts/unittest.js create mode 100644 nterchange/javascripts/workflow.js create mode 100644 nterchange/stylesheets/audit_trail.css create mode 100644 nterchange/stylesheets/forms.css create mode 100644 nterchange/stylesheets/global.css create mode 100644 nterchange/stylesheets/handheld.css create mode 100644 nterchange/stylesheets/layout.css create mode 100644 nterchange/stylesheets/lists.css create mode 100644 nterchange/stylesheets/nterchange.css create mode 100755 nterchange/stylesheets/print.css create mode 100644 nterchange/stylesheets/scaffold.css create mode 100644 nterchange/stylesheets/screen.css create mode 100644 nterchange/stylesheets/surftoedit.css create mode 100644 nterchange/stylesheets/typography.css create mode 100644 nterchange/stylesheets/workflow.css create mode 100644 package.json create mode 100644 page_content_grid.sql create mode 100644 test/environment.php create mode 100644 test/fixtures/base_schema.sql create mode 100644 test/fixtures/test_sample.sql create mode 100644 test/phpunit.xml create mode 100644 test/unit/AuditTrailControllerTest.php create mode 100644 test/unit/NControllerTest.php create mode 100644 test/unit/NDispatcherTest.php create mode 100644 test/unit/NModelTest.php create mode 100644 version.yml diff --git a/.bowerrc b/.bowerrc new file mode 100644 index 0000000..c5e009f --- /dev/null +++ b/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory": "nterchange/assets/components" +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..48b8bf9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +vendor/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..00eba56 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,20 @@ +## 4.0.0 + +* Reboot repository. Remove old SQL, passwords, deprecated files + +## 3.3.0 + +* Many changes to support grids +* NModel now implements `Array Access` +* Update bootstrap to 3.1 +* Test suite refactored + +## 3.2.0 + +* Update to CKEditor 4.0 +* Config class with static properties added as an alternative to constants for configuration + +## 3.1.22 + +* NAsset - dynamic coffeescript & less compiling +* NModel::$_delete_uploads flag on model to delete upload files along with records diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..dd5d59f --- /dev/null +++ b/LICENSE @@ -0,0 +1,68 @@ +-------------------------------------------------------------------- + The PHP License, version 3.01 +Copyright (c) 1999 - 2006 The PHP Group. All rights reserved. +-------------------------------------------------------------------- + +Redistribution and use in source and binary forms, with or without +modification, is permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + 3. The name "PHP" must not be used to endorse or promote products + derived from this software without prior written permission. For + written permission, please contact group@php.net. + + 4. Products derived from this software may not be called "PHP", nor + may "PHP" appear in their name, without prior written permission + from group@php.net. You may indicate that your software works in + conjunction with PHP by saying "Foo for PHP" instead of calling + it "PHP Foo" or "phpfoo" + + 5. The PHP Group may publish revised and/or new versions of the + license from time to time. Each version will be given a + distinguishing version number. + Once covered code has been published under a particular version + of the license, you may always continue to use it under the terms + of that version. You may also choose to use such covered code + under the terms of any subsequent version of the license + published by the PHP Group. No one other than the PHP Group has + the right to modify the terms applicable to covered code created + under this License. + + 6. Redistributions of any form whatsoever must retain the following + acknowledgment: + "This product includes PHP software, freely available from + ". + +THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND +ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP +DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------- + +This software consists of voluntary contributions made by many +individuals on behalf of the PHP Group. + +The PHP Group can be contacted via Email at group@php.net. + +For more information on the PHP Group and the PHP project, +please see . + +PHP includes the Zend Engine, freely available at +. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..32f5bb6 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +nterchange +========== + +Content Management that gets out of your way + +Install +------- + +This repository contains the core libraries, intended for use by a front-end. + +Testing +------- + +Set up the dependencies for the backend if necessary, then run PHPUnit. +This will clear and create a database called `nterchange_test`. + + composer install + vendor/bin/phpunit -c test/phpunit.xml diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..4452b00 --- /dev/null +++ b/Rakefile @@ -0,0 +1,50 @@ +require 'rubygems' +require 'bundler' +require 'pathname' +require 'logger' +require 'fileutils' +Bundler.require + +require 'active_record' +require 'yui/compressor' +require 'uglifier' + +dir = Rake.application.original_dir + +ROOT = Pathname(File.dirname(__FILE__)) +BUNDLES = %w( surftoedit.js surftoedit.css jquery-ui.js noty.js ) +BUILD_DIR = ROOT.join("nterchange/assets") +SOURCE_DIR = ROOT.join("app/assets") +COMPONENTS_DIR = ROOT.join("nterchange/assets/components") + +namespace :asset do + desc "Compile all assets" + task :compile do + Sprockets::Cache::FileStore.new(File.join ROOT, '.cache') + sprockets = Sprockets::Environment.new(ROOT) do |env| + env.logger = Logger.new(STDOUT) + end + + # sprockets.css_compressor = YUI::CssCompressor.new + # sprockets.js_compressor = Uglifier.new(:mangle => false) + + sprockets.append_path(SOURCE_DIR.join('javascripts').to_s) + sprockets.append_path(SOURCE_DIR.join('stylesheets').to_s) + sprockets.append_path(COMPONENTS_DIR.to_s) + + BUNDLES.each do |bundle| + asset = sprockets.find_asset(bundle) + prefix, basename = asset.pathname.to_s.split('/')[-2..-1] + FileUtils.mkpath BUILD_DIR.join(prefix) + realname = asset.pathname.basename.to_s.split(".")[0..1].join(".") + output_file = BUILD_DIR.join(prefix, realname) + + File.open(output_file, 'wb') do |f| + f.write asset.to_s + end + end + + # # Make available bower components in public_html + # FileUtils.cp_r(Dir["#{SOURCE_DIR}/components*"],BUILD_DIR) + end +end diff --git a/app/controllers/admin_controller.php b/app/controllers/admin_controller.php new file mode 100644 index 0000000..618e303 --- /dev/null +++ b/app/controllers/admin_controller.php @@ -0,0 +1,68 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class AdminController extends nterchangeController { + var $user_level_required = N_USER_ROOT; + var $name = 'admin'; + + function __construct() { + parent::__construct(); + } + + function index() { + $this->redirectTo(array('users', 'viewlist')); + } + + function viewlist($parameter) { + $this->loadSubnav($parameter); + parent::viewlist($parameter); + } + function create($parameter) { + $this->loadSubnav($parameter); + parent::create($parameter); + } + function edit($parameter) { + $this->loadSubnav($parameter); + parent::edit($parameter); + } + + function &getDefaultModel() { + return false; + } + + function loadSidebar($parameter) { + $this->set('SIDEBAR_TITLE', $this->page_title . ' Info'); + $this->setAppend('SIDEBAR_CONTENT', $this->render(array('action'=>'sidebar_content', 'return'=>true))); + } + + function loadSubnav($parameter) { + $subnav = array(); + $subnav[] = array('title'=>'Users', 'controller'=>'users', 'action'=>'viewlist', 'id'=>$parameter, 'class'=>''); + $subnav[] = array('title'=>'Audit Trail', 'controller'=>'audit_trail', 'action'=>'viewlist', 'id'=>$parameter, 'class'=>''); + $subnav[] = array('title'=>'Templates', 'controller'=>'page_template', 'action'=>'viewlist', 'id'=>$parameter, 'class'=>''); + $subnav[] = array('title'=>'Assets', 'controller'=>'cms_asset_info', 'action'=>'viewlist', 'id'=>$parameter, 'class'=>''); + foreach ($subnav as $k=>$nav) { + if ($nav['controller'] == $this->name && $nav['action'] == $this->action) { + $subnav[$k]['class'] = 'current'; + } + } + $this->set('subnav', $subnav); + } +} +?> diff --git a/app/controllers/asset_controller.php b/app/controllers/asset_controller.php new file mode 100644 index 0000000..32effac --- /dev/null +++ b/app/controllers/asset_controller.php @@ -0,0 +1,289 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class AssetController extends ContentController { + var $paging = 25; + var $search_field = 'cms_headline'; + + function __construct() { + parent::__construct(); + } + + function index($parameter) { + $this->redirectTo('viewlist', $parameter); + } + + private function get_search_field(&$model, &$options){ + // Search $model->search_field to limit shown assets. + + $search = isset($_GET['search']) ? $_GET['search'] : false; + $options['is_search'] = $search ? true : false; + + if (!$options['is_search']) return; + + $search_field = isset($_GET['search_field']) ? $_GET['search_field'] : null; + if (!$search_field){ + $search_field = isset($model->search_field) ? $model->search_field : $this->search_field; + } + + if ($options['is_search'] && $search_field){ + $this->set('search_field', Inflector::humanize($search_field)); + $options['conditions'] = "$search_field LIKE '%$search%'"; + } + } + + function viewlist($parameter=null, $layout=true, $model=false) { + $options = array(); + $assigns = array(); + $model = $model ? $model : $this->getDefaultModel(); + $this->page_title = Inflector::humanize($this->name); + $this->auto_render = false; + $this->base_dir = APP_DIR; + $assigns['TITLE'] = Inflector::humanize($this->name); + + if ($model){ + $this->get_search_field($model, $options); + $this->get_viewlist_options($model, $options); + $this->get_sort_options($model, $options); + $this->set_pagination($model); + + $model->find($options); + + $page_content = &NController::singleton('page_content'); + $page_content_model = &$page_content->getDefaultModel(); + + $pk = $model->primaryKey(); + $models = array(); + $headline = $model->getHeadline()?$model->getHeadline():'cms_headline'; + $i = 0; + while ($model->fetch()) { + $arr = $model->toArray(); + $arr['_headline'] = isset($arr['cms_headline']) && $arr['cms_headline']?$arr['cms_headline']:$model->makeHeadline(); + $arr['_remove_delete'] = $page_content_model->isWorkflowContent($this->name, $arr[$pk])?1:0; + // Remove delete for models that have specified this. + $arr['_remove_delete'] = (isset($model->remove_delete) && ($model->remove_delete == true))?1:0; + $models[] = $arr; + unset($arr); + } + // Override standard paging limit if chosen in the model file. + $paging = isset($model->paging)?$model->paging:$this->paging; + // If paging is not disabled in the model AND the records are > than the paging size AND not searching. + if (($paging > 0) && count($models) > $paging && !$options['is_search']) { + SmartyPaginate::connect($this->name); + SmartyPaginate::setLimit($paging, $this->name); + SmartyPaginate::setTotal(count($models), $this->name); + $view = &NView::singleton($this); + SmartyPaginate::assign($view, 'paginate', $this->name); + // TODO: Could be more efficient and only get records it needs to. + $models = array_slice($models, SmartyPaginate::getCurrentIndex($this->name), SmartyPaginate::getLimit($this->name)); + $this->set('paging', true); + } + $this->set(array('rows'=>$models, 'asset'=>$this->name, 'asset_name'=>$this->page_title)); + unset($models); + } + $this->render(array('layout'=>'default')); + } + + private function get_viewlist_options(&$model, &$options){ + // Can set options in the model about items displayed in the viewlist. + // Only show items that meet a certain criteria - not everything in the list. + // For example: $this->viewlist_options = array('conditions'=>"cms_modified_by_user = '4'"); + if (isset($model->viewlist_options)) { + foreach ($model->viewlist_options as $key => $val) { + if (isset($options[$key])) { + $options[$key] .= ' AND ' . $val; + } else { + $options[$key] = "$val"; + } + } + } + + if (isset($model->viewlist_fields)) { + $this->set('viewlist_fields', $model->viewlist_fields); + } + + } + + private function get_sort_options(&$model, &$options){ + $sort_by = isset($_GET['sort'])?$_GET['sort']:null; + if($sort_by) { + $sort_by_array = explode('_', $sort_by); + $sort_order = $sort_by_array[count($sort_by_array)-1]; + $sort_array = array(); + if(strtolower($sort_order) == 'asc') { + $sort_field = str_replace('_asc', '', $sort_by); + $sort_array['field'] = $sort_field; + $sort_array['arrow_asc'] = true; + $sort_array['link'] = $sort_field.'_desc'; + $options['order_by'] = $sort_field. ' ASC'; + } else { + $sort_field = str_replace('_desc', '', $sort_by); + $sort_array['field'] = $sort_field; + $sort_array['arrow_desc'] = true; + $sort_array['link'] = $sort_field.'_asc'; + $options['order_by'] = $sort_field. ' DESC'; + } + $this->set('sort_array', $sort_array); + } + } + + private function set_pagination(&$model){ + + } + + function show($parameter) { + $this->page_title = Inflector::humanize($this->name); + $this->loadSidebar($parameter); + parent::show($parameter); + } + + function edit($parameter) { + $this->page_title = Inflector::humanize($this->name); + $this->loadSidebar($parameter); + parent::edit($parameter); + } + + function create($parameter=null) { + $this->page_title = Inflector::humanize($this->name); + parent::create($parameter); + } + + function delete($parameter) { + $this->page_title = Inflector::humanize($this->name); + if (SITE_WORKFLOW) { + // need to test for workflow first + $pc_model = &NModel::factory('page_content'); + /* @var $pc_model PageContent */ + $in_workflow = $pc_model->isWorkflowContent($this->name, $parameter); + // if it's in a workflowed page + if ($in_workflow) { + $this->flash->set('notice', 'The record cannot be deleted until it is removed from the workflow page it belongs to.'); + include_once 'view/helpers/url_helper.php'; + $referer = isset($this->params['_referer'])?urldecode($this->params['_referer']):false; + if ($referer) { + header('Location:' . $referer); + exit; + } + $this->redirectTo('viewlist'); + } + } + parent::delete($parameter); + } + + function loadSidebar($parameter) { + $this->set('SIDEBAR_TITLE', $this->page_title . ' Info'); + $page_model = &NModel::singleton('page'); + $page_content_model = &NModel::factory('page_content'); + $page_content_model->content_asset = $this->name; + $page_content_model->content_asset_id = $parameter; + $this->setAppend('SIDEBAR_CONTENT', $this->render(array('action'=>'sidebar_edit_status', 'return'=>true))); + if ($page_content_model->find()) { + $pages = array(); + while ($page_content_model->fetch()) { + $page_model->reset(); + if ($page_model->get($page_content_model->page_id)) { + $pages[] = $page_model->toArray(); + } + } + $page_model->reset(); + unset($page_model); + $this->set('pages', $pages); + $this->setAppend('SIDEBAR_CONTENT', $this->render(array('action'=>'sidebar_page_content', 'return'=>true))); + } + unset($page_content_model); + if ($this->versioning) { + $user_model = $this->loadModel('cms_auth'); + $model = $this->getDefaultModel(); + $model = clone($model); + if (!$model->{$model->primaryKey()}) { + $model->get($parameter); + $this->convertDateTimesToClient($model); + } + $model_data = $model->toArray(); + if ($user_model->get($model_data['cms_modified_by_user'])) { + $model_data['user'] = $user_model->toArray(); + } + $this->set($model_data); + $user_model->reset(); + $version_model = $this->loadModel('cms_nterchange_versions'); + $user_model = $this->loadModel('cms_auth'); + $version_model->asset = $this->name; + $version_model->asset_id = $parameter; + if ($version_model->find(array('order_by'=>'cms_modified DESC'))) { + $versions = array(); + while ($version_model->fetch()) { + $version = $version_model->toArray(); + if ($version_data = @unserialize($version['version'])) { + if ($user_model->get($version_data['cms_modified_by_user'])) { + $version['user'] = $user_model->toArray(); + } + $user_model->reset(); + $versions[] = $version; + } + } + $this->set('versions', $versions); + } + $this->setAppend('SIDEBAR_CONTENT', $this->render(array('action'=>'sidebar_versions', 'return'=>true))); + unset($version_model); + } + } + + /** + * Called before the form is generated + * + * Sets up a default rule for content tables so there are no + * identical headlines + * + * @see NController::preGenerateForm(); + * @access public + * @return null + */ + function preGenerateForm() { + $model = &$this->getDefaultModel(); + $fields = $model->fields(); + if (in_array('cms_headline', $fields)) { + $model->form_rules[] = array('cms_headline', 'This headline is already being used', 'callback', array(&$this, 'uniqueHeadline')); + } + parent::preGenerateForm(); + } + + function getAssetContent($params) { + $id = isset($params['id'])?$params['id']:false; + $template = isset($params['template'])?$params['template']:'default'; + $model = &$this->getDefaultModel($this->name); + if($id && $model && $model->get($id)) { + $this->set($model->toArray()); + unset($model); + return $this->render(array('action'=>$template, 'return'=>true)); + } else { + return false; + } + } + /* + * Returns a controller form for the asset + */ + function getForm(){ + require_once 'controller/form.php'; + $model = $this->getDefaultModel(); + $cform = new ControllerForm($this, $model); + return $cform->getForm(); + + } +} +?> diff --git a/app/controllers/audit_trail_controller.php b/app/controllers/audit_trail_controller.php new file mode 100644 index 0000000..e10234c --- /dev/null +++ b/app/controllers/audit_trail_controller.php @@ -0,0 +1,423 @@ + + * @author Darron Froese + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class AuditTrailController extends AdminController { + function __construct() { + $this->name = 'audit_trail'; + parent::__construct(); + } + + function index() { + $this->redirectTo('viewlist'); + } + + /** + * viewlist - Shows a list of audit trail records from the current date (by default). + * Can browse around records from different dates using the form + * at the top of the page. + * + * @return void + **/ + function viewlist($parameter) { + include_once 'n_date.php'; + include_once 'n_quickform.php'; + require_once 'HTML/QuickForm/Renderer/Array.php'; + + $this->_auth = new NAuth; + $this->auto_render = false; + + // set up the search form + $form = new NQuickForm('audit_search', 'get'); + + if ($date_params = $this->getParam('date')) { + $date = $this->dateStartEnd($date_params); + } else { + $date = $this->dateStartEnd(); + } + + $el = &$form->addElement('date', 'date', 'Date', array('addEmptyOption'=>true, 'format'=>'F d Y', 'maxYear' => 2015)); + $el->setValue($date['used']); + + $form->addElement('submit', null, 'Search'); + + $renderer = new HTML_QuickForm_Renderer_Array(true, true); + $form->accept($renderer); + $this->set('audit_search', $renderer->toArray()); + + $model = &$this->getDefaultModel(); + + if ($model->find(array('conditions'=>'cms_created BETWEEN ' . $model->quote($date['start']) . ' AND ' . $model->quote($date['end']), 'order_by'=>'cms_created DESC'))) { + $html = ''; + + if ($date['month']) { + $html .= "

Showing Monthly Results for: ".date("F, Y", strtotime($date['used'])); + } + while ($model->fetch()) { + // Actually turn the id's into something readable. + $info = $this->humanizeAuditTrailRecord($model); + $this->set($info); + $html .= $this->render(array('action'=>'audit_trail_record', 'return'=>true)); + } + + $this->set('audit_trail', $html); + $this->set('result_count', $model->numRows()); + } else { + $this->set('result_count', 'no'); + $this->set('audit_trail', '

There were no results found for the specified date.

'); + } + // Exposes an RSS feed link to Admin or higher users. + if (defined('RSS_AUDIT_TRAIL') && RSS_AUDIT_TRAIL) { + NDebug::debug('We are checking to see if we can display the RSS feed.' , N_DEBUGTYPE_INFO); + $this->checkRSSFeed(); + } + $this->set('date', $date['used']); + $this->loadSubnav($parameter); + $this->render(array('layout'=>'default')); + } + + function dateStartEnd($params=false){ + $y = (isset($params['Y']) && $params['Y']) ? $params['Y'] : false; + $m = (isset($params['F']) && $params['F']) ? $params['F'] : false; + $d = (isset($params['d']) && $params['d']) ? $params['d'] : false; + + $date = array(); + $date['month'] = false; + + if ($y && $d && $m){ + // Fully qualified + $date_arg = date('Y-m-d', strtotime("$y-$m-$d")); + $date['start'] = NDate::convertTimeToUTC($date_arg . ' 00:00:00', '%Y-%m-%d %H:%M:%S'); + $date['end'] = NDate::convertTimeToUTC($date_arg . ' 23:59:59', '%Y-%m-%d %H:%M:%S'); + $date['used'] = $date_arg; + return($date); + } + + if ((! $params['d']) && ( $y && $params['F'] )) { + // One Month + $date_arg = date('Y-m-d', strtotime("$y-$m-1")); + $days_in_month = date('t', strtotime($date_arg)); + $month_end = date('Y-m-d', strtotime("$y-$m-$days_in_month")); + $date['start'] = NDate::convertTimeToUTC($date_arg . ' 00:00:00', '%Y-%m-%d %H:%M:%S'); + $date['end'] = NDate::convertTimeToUTC($month_end . ' 23:59:59', '%Y-%m-%d %H:%M:%S'); + $date['used'] = "$y-$m-1"; + $date['month'] = true; + return $date; + } + + // Default to one day: today + $date['start'] = NDate::convertTimeToUTC(date('Y-m-d') . ' 00:00:00', '%Y-%m-%d %H:%M:%S'); + $date['end'] = NDate::convertTimeToUTC(date('Y-m-d') . ' 23:59:59', '%Y-%m-%d %H:%M:%S'); + $date['used'] = date('Y-m-d'); + return($date); + + } + + function page($parameter) { + $page_id = $parameter; + $this->_auth = new NAuth; + $this->auto_render = false; + // set up the search form + include_once 'n_quickform.php'; + // search for the date + /* @var $model cmsAuditTrail */ + $model = &$this->getDefaultModel(); + $model->page_id = $page_id; + if ($model->find(array('order_by'=>'cms_created DESC'))) { + $html = ''; + while ($model->fetch()) { + // Actually turn the id's into something readable. + $info = $this->humanizeAuditTrailRecord($model); + $this->set($info); + $html .= $this->render(array('action'=>'page_audit_trail_record', 'return'=>true)); + } + $this->set('audit_trail', $html); + $this->set('result_count', $model->numRows()); + } else { + $this->set('result_count', 'no'); + $this->set('audit_trail', '

There were no results found for the specified page.

'); + } + // Exposes an RSS feed link to Admin or higher users. + if (defined('RSS_AUDIT_TRAIL') && RSS_AUDIT_TRAIL) { + NDebug::debug('We are checking to see if we can display the RSS feed.' , N_DEBUGTYPE_INFO); + $this->checkRSSFeed(); + } + $this->loadSubnav($parameter); + $this->render(array('layout'=>'default')); + } + + /** + * humanizeAuditTrailRecord - Turns the id's in the cms_audit_trail table into human readable + * English. + * + * @param object An object which contains an audit trail record. + * @return array An array of human readable information about that audit trail record. + **/ + function humanizeAuditTrailRecord($model) { + $this->convertDateTimesToClient($model); + $info = array('user'=>false, 'asset'=>false, 'workflow'=>false, 'workflow_group'=>false, 'page'=>false, 'page_content'=>false); + if ($model->user_id) { + if ($model->user_id == $model->website_user_id) { + // This is a hack for timed_removal of content - see the cms_audit_trail model for info. + $info['user'] = array('id'=>$model->website_user_id, 'real_name'=>$model->website_user_name, 'email'=>$model->website_user_email); + } else { + $info['user'] = $this->getAuditInfo('users', $model->user_id); + } + } + if ($model->workflow_id) { + $info['workflow'] = $this->getAuditInfo('workflow', $model->workflow_id); + } + if ($model->asset && $model->asset != 'page' && $model->asset_id) { + $info['asset'] = $this->getAuditInfo($model->asset, $model->asset_id); + $info['asset_type'] = $model->asset; + $info['asset_name'] = Inflector::humanize($model->asset); + } else if ($info['workflow']) { + $info['asset'] = $this->getAuditInfo($info['workflow']['asset'], $info['workflow']['asset_id']); + $info['asset_type'] = $info['workflow']['asset']; + $info['asset_name'] = Inflector::humanize($info['workflow']['asset']); + } + if ($model->workflow_group_id) { + $info['workflow_group'] = $this->getAuditInfo('workflow_group', $model->workflow_group_id); + } else if ($info['workflow']) { + // if there's no workflow_group_id right in the audit trail, try the workflow['workflow_group_id'] + $info['workflow_group'] = $this->getAuditInfo('workflow_group', $info['workflow']['workflow_group_id']); + } + if ($model->page_content_id) { + $info['page_content'] = $this->getAuditInfo('page_content', $model->page_content_id); + } else if ($info['workflow']) { + // if there's no page_content_id right in the audit trail, try the workflow['page_content_id'] + $info['page_content'] = $this->getAuditInfo('page_content', $info['workflow']['page_content_id']); + } + if ($model->page_id || $model->asset == 'page') { + $info['page'] = $model->asset == 'page'?$this->getAuditInfo('page', $model->asset_id):$this->getAuditInfo('page', $model->page_id); + } else if ($info['page_content']) { + // if there's no page_id right in the audit trail, try the page_content['page_id'] + $info['page'] = $this->getAuditInfo('page', $info['page_content']['page_id']); + } else if ($info['workflow']) { + // if there's no page_id or page_content_id right in the audit trail, try the workflow['page_id'] + $info['page'] = $this->getAuditInfo('page', $info['workflow']['page_id']); + } + $info['action_taken'] = $this->actionToText($model->action_taken); + $info['ip'] = $model->ip; + $info['created'] = $model->cms_created; + return $info; + } + + /** + * checkRSSFeed - Checks the level of the user and exposes a link to an audit trail RSS feed + * to that user if they're an admin level or higher. + * + * @return void + **/ + function checkRSSFeed() { + // Check the user level - this only shows up for admins or higher. + $auth = new NAuth(); + $current_user_level = $auth->getAuthData('user_level'); + $user_id = $auth->currentUserID(); + if ($current_user_level >= N_USER_ADMIN) { + // Get their feed token if they have it. + $cms_user = NModel::factory('cms_auth'); + $feed_token = $cms_user->getFeedToken($user_id); + unset($cms_user); + + // If they don't have one, we should help them to generate it. + if (!isset($feed_token)) { + $rss = '

Click here to generate a private RSS feed

'; + } else { + $rss = '

Private RSS Feed of Audit Trail Activity - Regenerate Token

'; + } + + // Then show the link so that they can put it into their feed reader. + $this->set('rss_feed', $rss); + } + unset($auth); + } + + /** + * getAuditInfo - gets additional audit trail information by looking up foreign keys. + * + * @param string Name of a particular model. + * @param int Id of a record in that particular model. + * @return array Information related to $model_name and $id. + **/ + function getAuditInfo($model_name, $id) { + // checks for deleted and non-deleted records using special field + $info = false; + $fctrl = &NController::singleton($model_name); + if ($fctrl && $fmodel = &$fctrl->getDefaultModel()) { + $fmodel->reset(); + if (!$fmodel->get($id)) { + $fmodel->reset(); + $fields = $fmodel->fields(); + if (in_array('cms_deleted', $fields)) { + $fmodel->cms_deleted = 1; + } + $fmodel->get($id); + } + $info = $fmodel->{$fmodel->primaryKey()}?$fmodel->toArray():false; + if ($info && (!isset($info['_headline']) || !$info['_headline'])) { + $info['_headline'] = $fmodel->makeHeadline(); + } + unset($fmodel); + } + return $info; + } + + /** + * insert - Actually insert a cms_audit_trail record. Must be logged in to nterchange + * for this to succeed. + * NOTE: If you need to log an audit trail record without being logged in (eg. timed content removal) + * there is an alternate method in the cms_audit_trail model. + * + * @param array Required params - asset, asset_id, action_taken + * @return void + **/ + function insert($params=array()) { + $this->_auth = new NAuth; + if (empty($params)) return false; + $required_params = array('asset', 'asset_id', 'action_taken'); + foreach ($required_params as $param) { + if (!isset($params[$param])) return false; + } + $model = &$this->getDefaultModel(); + // apply fields in the model + $fields = $model->fields(); + foreach ($fields as $field) { + $model->$field = isset($params[$field])?$params[$field]:null; + } + $model->user_id = $this->_auth->currentUserID(); + $model->ip = NServer::env('REMOTE_ADDR'); + if (in_array('cms_created', $fields)) { + $model->cms_created = $model->now(); + } + if (in_array('cms_modified', $fields)) { + $model->cms_modified = $model->now(); + } + // set the user id if it's applicable and available + if (in_array('cms_modified_by_user', $fields)) { + $model->cms_modified_by_user = $this->_auth->currentUserID(); + } + $model->insert(); + } + + /** + * actionToText - Convert an action_id to it's human readable explanation. + * + * @param int The id of the action. + * @return string What that id actually means. + **/ + function actionToText($action) { + $txt = ''; + switch ($action) { + case AUDIT_ACTION_INSERT: + $txt = 'Inserted'; + break; + case AUDIT_ACTION_UPDATE: + $txt = 'Updated'; + break; + case AUDIT_ACTION_DELETE: + $txt = 'Deleted'; + break; + case AUDIT_ACTION_CONTENT_ADDEXISTING: + $txt = 'Added Existing Content'; + break; + case AUDIT_ACTION_CONTENT_ADDNEW: + $txt = 'Added New Content to a page'; + break; + case AUDIT_ACTION_CONTENT_REMOVE: + $txt = 'Removed Content from a page'; + break; + case AUDIT_ACTION_WORKFLOW_START: + $txt = 'Submitted Workflow'; + break; + case AUDIT_ACTION_WORKFLOW_SUBMIT: + $txt = 'Submitted Workflow'; + break; + case AUDIT_ACTION_WORKFLOW_APPROVE: + $txt = 'Approved Workflow'; + break; + case AUDIT_ACTION_WORKFLOW_APPROVEPUBLISH: + $txt = 'Approved & Published Workflow'; + break; + case AUDIT_ACTION_WORKFLOW_APPROVEREMOVE: + $txt = 'Approved & Removed Workflow Content'; + break; + case AUDIT_ACTION_WORKFLOW_DECLINE: + $txt = 'Declined Workflow'; + break; + case AUDIT_ACTION_DRAFT_SAVE: + $txt = 'Saved a Draft'; + break; + case AUDIT_ACTION_DRAFT_DELETE: + $txt = 'Deleted a Draft'; + break; + case AUDIT_ACTION_DELETE_ASSET_VERSIONS: + $txt = 'Removed all old content versions'; + break; + case AUDIT_ACTION_LOGIN: + $txt = 'Logged into nterchange'; + break; + } + return $txt; + } + + // override all the crud functions so that no one can edit or manually create an audit trail + // insert is already overridden above with a custom method + function create() { + $this->redirectTo('viewlist'); + } + function edit() { + $this->redirectTo('viewlist'); + } + function update() { + $this->redirectTo('viewlist'); + } + function delete() { + $this->redirectTo('viewlist'); + } + + function &getDefaultModel() { + $model = &$this->loadModel('cms_audit_trail'); + return $model; + } +} +?> diff --git a/app/controllers/cms_asset_info_controller.php b/app/controllers/cms_asset_info_controller.php new file mode 100644 index 0000000..4b119db --- /dev/null +++ b/app/controllers/cms_asset_info_controller.php @@ -0,0 +1,139 @@ + + * @copyright 2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class CmsAssetInfoController extends AdminController { + function __construct() { + $this->name = 'cms_asset_info'; + // set user level allowed to access the actions with required login + $this->user_level_required = N_USER_ADMIN; + $this->page_title = 'Assets'; + $this->login_required = true; + parent::__construct(); + } + + /** + * AssetList - Return an array of all assets in cms_asset_info table unless + * $connectable is set - then use $model->not_connectable to leave those + * assets out. + * + * @param boolean Whether you want only connectable assets. + * @return array An array with all of the possible assets. + **/ + function AssetList ($connectable=false) { + // Grab the list of available assets. + $assets = &NModel::factory($this->name); + if ($assets->find()) { + while ($assets->fetch()) { + $asset_list[] = $assets->toArray(); + } + unset($assets); + foreach ($asset_list as $asset) { + $model = &NModel::factory($asset['asset']); + // If you don't want any non_connectable assets in the array. + if ($model && $connectable && !isset($model->not_connectable)) { + $final_assets[] = $asset; + // Or if you just want them all. + } elseif($model && !$connectable) { + $final_assets[] = $asset; + } + unset($model); + } + return $final_assets; + } + } + + /** + * doesAssetModelFileExist - Check for the existance of an asset's model file. + * Check in the frontend and backend. + * + * @param string The name of the asset + * @return boolean Does it exist or not? + **/ + function doesAssetModelFileExist($asset){ + $full_path_filename = ASSET_DIR . '/models/' . $asset . '.php'; + if (file_exists($full_path_filename)) { + return true; + } else { + // Check in nterchange backend proper. + $full_path_filename = BASE_DIR . '/app/models/' . $asset . '.php'; + if (file_exists($full_path_filename)) { + return true; + } + return false; + } + } + + /** + * doesAssetControllerFileExist - Check for the existance of an asset's controller file. + * Check in the frontend and backend. + * + * @param string The name of the asset + * @return boolean Does it exist or not? + **/ + function doesAssetControllerFileExist($asset){ + $full_path_filename = ASSET_DIR . '/controllers/' . $asset . '_controller.php'; + if (file_exists($full_path_filename)) { + return true; + } else { + // Check in nterchange backend proper. + $full_path_filename = BASE_DIR . '/app/controllers/' . $asset . '_controller.php'; + if (file_exists($full_path_filename)) { + return true; + } + return false; + } + } + + /** + * doesAssetDatabaseTableExist - Check for the existance of an asset's database table. + * + * @param string The name of the asset + * @return boolean Does it exist or not? + **/ + function doesAssetDatabaseTableExist($asset){ + $model = &NModel::factory($asset); + if ($model) { + if ($model->_fields) { + return true; + } else { + return false; + } + } else { + return false; + } + } + + function &getDefaultModel() { + $model = &$this->loadModel($this->name); + return $model; + } + + /** + * postGenerateForm - Just setting some validation rules for the forms. + * + * @return void + **/ + function postGenerateForm(&$form) { + $form->removeElement('__header__'); + $form->addRule('asset', 'We need to have an asset.', 'required', null, 'client'); + $form->addRule('asset', 'Letters, numbers, dashes and underscores - without a suffix, spaces or punctuation.', 'regex', '/^[a-zA-Z0-9_-]+$/', 'client'); + $form->addRule('asset_name', 'We need to have a name for this asset.', 'required', null, 'client'); + } +} +?> \ No newline at end of file diff --git a/app/controllers/cms_asset_template_controller.php b/app/controllers/cms_asset_template_controller.php new file mode 100644 index 0000000..49a4a60 --- /dev/null +++ b/app/controllers/cms_asset_template_controller.php @@ -0,0 +1,159 @@ + + * @copyright 2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class CmsAssetTemplateController extends AdminController { + function __construct() { + $this->name = 'cms_asset_template'; + // set user level allowed to access the actions with required login + $this->user_level_required = N_USER_ADMIN; + $this->login_required = true; + $this->page_title = 'Asset / Container Templates'; + parent::__construct(); + } + + function getAssetTemplate($asset, $container_id) { + $model = &NModel::factory($this->name); + $model->asset = (string)$asset; + $model->page_template_container_id = (int)$container_id; + $ret = ''; + if ($model->find(null, true)) { + $ret = $model->template_filename; + } + unset($model); + return $ret; + } + + function viewlist($page_template_container) { + $this->loadSubnav($page_template_container); + $this->auto_render = false; + $html = ''; + if (!$page_template_container) { + // This is a bit of a hack. + header ('Location: /nterchange/page_template/viewlist'); + } + $model = $this->getDefaultModel($this->name); + $model->page_template_container_id = $page_template_container; + $this->set('page_template_container_id', $page_template_container); + // Let's get the Container Name. + if ($page_template_container = $model->getLink('page_template_container_id', 'page_template_containers')) { + $this->set('page_template_container_name', $page_template_container->container_name); + // With the name, let's get the template name and filename too. + $page_template = &NModel::factory('page_template'); + $page_template->id = $page_template_container->page_template_id; + $this->set('page_template_id', $page_template_container->page_template_id); + if ($page_template->find()) { + while ($page_template->fetch()) { + $page_template_tmp = $page_template->toArray(); + $this->set('page_template_filename', $page_template_tmp['template_filename']); + $this->set('page_template_name', $page_template_tmp['template_name']); + } + } + } + if ($model->find()) { + while ($model->fetch()) { + $arr = $model->toArray(); + $arr['_headline'] = isset($arr['cms_headline']) && $arr['cms_headline']?$arr['cms_headline']:$model->makeHeadline(); + $models[] = $arr; + unset($arr); + $html .= $this->set('rows', $models); + } + $html .= $this->set(array('rows'=>$models, 'asset'=>$this->name, 'asset_name'=>$this->page_title?$this->page_title:Inflector::humanize($this->name))); + } else { + $this->set('notice', 'There are no assets associated with that container.'); + } + $html .= $this->set(array('asset'=>$this->name, 'asset_name'=>$this->page_title?$this->page_title:Inflector::humanize($this->name))); + $html .= $this->render(array('layout'=>'default')); + return $html; + } + + function create($parameter=null, $layout=true) { + $this->page_template_container_id = $parameter; + $this->loadSubnav($parameter); + parent::create($parameter); + } + + function edit($parameter) { + $this->page_template_container_id = $this->getPTCIFromId($parameter); + $this->set('page_template_container_id', $this->page_template_container_id); + $this->loadSubnav($parameter); + parent::edit($parameter); + } + + // Get page_template_container_id from cms_asset_template_id + function getPTCIFromId($id) { + $model = &NModel::factory($this->name); + $model->id = $id; + if($model->find()) { + while ($model->fetch()) { + $result = $model->toArray(); + } + $page_template_container_id = $result['page_template_container_id']; + // Set the asset name for postGenerateForm. + $this->passed_asset = $result['asset']; + } + unset($model); + return $page_template_container_id; + } + + function postGenerateForm(&$form) { + $form->removeElement('__header__'); + // Set the container in the menu as passed by $parameter + $container_group = &$form->getElement('page_template_container_id'); + $container_group->setSelected($this->page_template_container_id); + // Not sure I should do this - but it seems to help with confusion. + $container_group->freeze(); + + // Grab the asset list and create an array for QuickForm. + $assets = &NController::factory('cms_asset_info'); + $array_of_assets = $assets->AssetList(true); + foreach ($array_of_assets as $asset) { + $select_array[$asset['asset']] = $asset['asset_name']; + } + // Add the element in place of the current asset form item. + $form->removeElement('asset'); + $new_select = &$form->addElement('select', 'asset', 'Asset:', $select_array); + $form->insertElementBefore($form->removeElement('asset', false), 'template_filename'); + // Set the asset if passed by edit. + if (isset($this->passed_asset)) { + $new_select->setSelected($this->passed_asset); + } + $form->addRule('template_filename', 'We need to have a template filename.', 'required', null, 'client'); + $form->addRule('template_filename', 'Letters, numbers, dashes and underscores - without a suffix, spaces or punctuation.', 'regex', '/^[a-zA-Z0-9_-]+$/', 'client'); + } + + function doesAssetTemplateExist($filename, $asset){ + $full_path_filename = ASSET_DIR . '/views/' . $asset . '/' . $filename . '.' . DEFAULT_PAGE_EXTENSION; + if (file_exists($full_path_filename)) { + return true; + } else { + // Check in nterchange backend proper. + $full_path_filename = BASE_DIR . '/app/views/' . $asset . '/' . $filename . '.' . DEFAULT_PAGE_EXTENSION; + if (file_exists($full_path_filename)) { + return true; + } + return false; + } + } + + function &getDefaultModel() { + $model = &$this->loadModel('cms_asset_template'); + return $model; + } +} +?> \ No newline at end of file diff --git a/app/controllers/cms_drafts_controller.php b/app/controllers/cms_drafts_controller.php new file mode 100644 index 0000000..19c89d6 --- /dev/null +++ b/app/controllers/cms_drafts_controller.php @@ -0,0 +1,60 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class CmsDraftsController extends AppController { + function __construct() { + $this->name = 'cms_drafts'; + // set user level allowed to access the actions with required login + $this->user_level_required = N_USER_NORIGHTS; + $this->login_required = true; + parent::__construct(); + } + + function delete($parameter) { + if (empty($parameter)) { + $this->redirectTo(array('dashboard')); + } + // load the model layer with info + $model = &NModel::factory($this->name); + if (!$model) $this->redirectTo(array('dashboard')); + if ($model->get($parameter)) { + // if the content record is flagged with cms_draft=1, then the content has never been published and should be deleted altogether + $content_model = &NModel::factory($model->asset); + if ($content_model && $content_model->get($model->asset_id) && $content_model->cms_draft == 1) { + $content_model->delete(); + } + unset($content_model); + if (defined('SITE_AUDIT_TRAIL') && SITE_AUDIT_TRAIL) { + // audit trail before delete so we don't lose the values + $audit_trail = &NController::factory('audit_trail'); + $audit_trail->insert(array('asset'=>$this->name, 'asset_id'=>$model->{$model->primaryKey()}, 'action_taken'=>AUDIT_ACTION_DRAFT_DELETE)); + unset($audit_trail); + } + $model->delete(); + if (isset($this->params['_referer']) && $this->params['_referer']) { + header('Location:' . urldecode($this->params['_referer'])); + exit; + } + $this->postProcessForm($model->toArray()); + $this->flash->set('notice', 'Draft deleted.'); + } + $this->redirectTo(array('dashboard')); + } +} +?> \ No newline at end of file diff --git a/app/controllers/code_caller_controller.php b/app/controllers/code_caller_controller.php new file mode 100644 index 0000000..2eac01d --- /dev/null +++ b/app/controllers/code_caller_controller.php @@ -0,0 +1,103 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class CodeCallerController extends AssetController { + function __construct() { + $this->name = 'code_caller'; + $this->versioning = true; + $this->base_view_dir = BASE_DIR; + parent::__construct(); + } + + function render($options) { + $in_nterchange = defined('IN_NTERCHANGE')?constant('IN_NTERCHANGE'):false; + $in_surftoedit = defined('IN_SURFTOEDIT')?constant('IN_SURFTOEDIT'):false; + if (!$in_nterchange || $in_surftoedit) { + $model = &$this->getDefaultModel(); + $content = $model->content; + require_once 'vendor/JSON.php'; + $json = new Services_JSON(); + if ($code = $json->decode($content) && !empty($code)) { + if (isset($code->controller) && isset($code->action)) { + $this->getContent((array) $code, $model->dynamic); + } + } else { + while (false !== ($pos = strpos($content, '{call'))) { + $pos2 = strpos($content, '}', $pos)+1; + $str = substr($content, $pos, $pos2-$pos); + // clean up the string + $str = trim(str_replace(array('{call ', '}'), '', $str)); + // replace value + $value = ''; + // find matches + preg_match_all('/\s?([^=]+)=[\"\']?([^\"\'\s$]+)[\"\']?/', $str, $matches); + // push the matches into an array if they exists + if (isset($matches[0])) { + $params = array(); + for ($i=0;$igetContent($params, $model->dynamic); + } + $content = substr($content, 0, $pos) . $value . substr($content, $pos2 + 1); + } + } + $model->content = $content; + $this->set($model->toArray()); + unset($json); + } + return parent::render($options); + } + + function getContent($params, $dynamic) { + $content = ''; + $controller = $params['controller']; + $action = $params['action']; + unset($params['controller'], $params['action']); + include_once 'controller/inflector.php'; + $method = Inflector::camelize($action); + if ($ctrl = &NController::factory($controller)) { + if ($dynamic) { + $content = $this->dynamicPHP($ctrl, $method, NController::getIncludePath($controller), $params); + } else { + $content = $ctrl->$method($params); + } + unset($ctrl); + } + return $content; + } + + function dynamicPHP(&$obj, $method, $include_file, $params=array()) { + $ret = ''; + if (is_object($obj) && method_exists($obj, $method)) { + $ret .= 'wrapSanitizedSerializer($obj) . ';'; + $ret .= '$params = ' . $this->wrapSanitizedSerializer($params) . ';'; + $ret .= 'print $obj->' . $method . '($params);'; + $ret .= '?>'; + } + return $ret; + } + + private function wrapSanitizedSerializer($obj) { + $encoded_serialized_string = base64_encode(serialize($obj)); + return "unserialize(base64_decode('$encoded_serialized_string'))"; + } +} +?> diff --git a/app/controllers/content_controller.php b/app/controllers/content_controller.php new file mode 100644 index 0000000..1569c75 --- /dev/null +++ b/app/controllers/content_controller.php @@ -0,0 +1,58 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class ContentController extends nterchangeController { + var $user_level_required = N_USER_NORIGHTS; + var $name = 'content'; + var $page_title = 'Content'; + + function __construct() { + if (is_array($this->login_required)) { + $this->login_required[] = 'list_assets'; + } + parent::__construct(); + } + + function index($parameter) { + $this->redirectTo('list_assets', $parameter); + } + + function listAssets($parameter) { + $this->auto_render = false; + $asset_model = &$this->getDefaultModel(); + if ($asset_model->find()) { + $assets = array(); + while ($asset_model->fetch()) { + $assets[] = $asset_model->toArray(); + } + $this->set(array('assets'=>$assets)); + } + $this->render(array('layout'=>'default')); + } + + function &getDefaultModel() { + if (get_class($this) == __CLASS__) { + $ret = &$this->loadModel('cms_asset_info'); + } else { + $ret = &parent::getDefaultModel(); + } + return $ret; + } +} +?> \ No newline at end of file diff --git a/app/controllers/csv_export_controller.php b/app/controllers/csv_export_controller.php new file mode 100644 index 0000000..73c0218 --- /dev/null +++ b/app/controllers/csv_export_controller.php @@ -0,0 +1,262 @@ + + * @copyright 2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class CsvExportController extends AdminController { + var $default_foreign_keys = array('cms_modified_by_user'=>array('cms_auth', 'real_name')); + var $default_field_exclusions = array('id'=>true, 'cms_active'=>true, 'cms_draft'=>true, 'cms_deleted'=>true, 'cms_headline'=>true); + + function __construct() { + $this->name = 'csv_export'; + // set user level allowed to access the actions with required login + $this->user_level_required = N_USER_EDITOR; + $this->login_required = true; + $this->page_title = 'CSV Export'; + parent::__construct(); + } + + function export($model_name) { + if (isset($model_name)) { + $model = NModel::factory($model_name); + // Foreign Key Lookup Support + if (isset($model->excel_export)) { + $model_foreign_keys = $model->excel_export; + // Default standard foreign keys get added and merged here. + $foreign_keys = array_merge($this->default_foreign_keys, $model_foreign_keys); + } else { + $foreign_keys = $this->default_foreign_keys; + } + // Field Inclusion and Exclusion Support + if (isset($model->excel_exclude_fields)) { + $model_excel_inclusions = $model->excel_exclude_fields; + $field_exclusions = array_merge($this->default_field_exclusions, $model_excel_inclusions); + } else { + $field_exclusions = $this->default_field_exclusions; + } + // If $_GET['search'] is set, only export those items. + $search = isset($_GET['search'])?$_GET['search']:null; + $search_field = isset($_GET['search_field'])?$_GET['search_field']:null; + if (isset($search) && $search != null) { + if (!$search_field && $search_field != null) { + $acon = NController::factory('asset'); + $search_field = isset($model->search_field)?$model->search_field:$acon->search_field; + unset($acon); + } + } + $options = $search?array('conditions'=>"$search_field LIKE '%$search%'"):array(); + // Can set options in the model about items exported to the Excel. + // Only export items that meet a certain criteria - not everything in the list. + // For example: $this->viewlist_options = array('conditions'=>"cms_modified_by_user = '4'"); + if (isset($model->viewlist_options)) { + foreach ($model->viewlist_options as $key => $val) { + if (isset($options[$key])) { + $options[$key] .= ' AND ' . $val; + } else { + $options[$key] = "$val"; + } + } + } + + if ($model->find($options)) { + $fields = $model->fields(); + // Add additional custom fields here from the model file. + if (isset($model->excel_extra_fields)) { + foreach ($model->excel_extra_fields as $key => $value) { + $fields[] = $key; + } + } + // Creating a workbook + $filename = $_SERVER['DOCUMENT_ROOT'] . UPLOAD_DIR . '/' . rand(1,1000) . '-file.csv'; + $fp = fopen($filename, 'w'); + + // Creating a workbook and sending it directly out to a browser. + //$fp = fopen('php://output', 'w'); + + // Let's add the field names to the title line. + // Leave out a few. + $x = 0; + foreach ($fields as $field) { + $exclude_this = array_key_exists($field, $field_exclusions); + if ($exclude_this && $field_exclusions[$field] == true) { + // do nothing + } else { + $good_fields[] = $field; + } + } + //$field_string = implode(',', $good_fields); + fputcsv($fp, $good_fields); + + // Now here comes the data. + $y = 1; + while ($model->fetch()) { + $data_fields = array(); + $item = $model->toArray(); + // For reference while we're working with things. + $original_item = array(); + $original_item = $item; + $x = 0; + foreach ($fields as $field) { + $exclude_this = array_key_exists($field, $field_exclusions); + if ($exclude_this && $field_exclusions[$field] == true) { + // do nothing + } else { + // Look for foreign keys and replace if assigned. + foreach($foreign_keys as $foreign_key => $foreign_key_value) { + if ($field == $foreign_key) { + $fk_model_name = $foreign_key_value[0]; + $fk_model_headline = $foreign_key_value[1]; + $fk_model = NModel::factory($fk_model_name); + if ($fk_model && ($fk_model->get($item[$field]))) { + $item[$field] = $fk_model->{$fk_model_headline}; + } + unset($fk_model); + } + } + + //Look for bitmask fields and replace with string value instead of numeric total + if (is_array($model->bitmask_fields) && count($model->bitmask_fields)) { + $bitmask_keys = array_keys($model->bitmask_fields); + if (in_array($field, $bitmask_keys)) { + $bitmask_total = $item[$field]; + $value_str = ''; + $i = 0; + foreach($model->bitmask_fields[$field] as $bit=>$val) { + if($bit & $bitmask_total) { + if($i > 0) { + $value_str .= ', '; + } + $value_str .= $val; + $i ++; + } + } + $item[$field] = $value_str; + } + } + + // Any extra fields get dealt with here. + if (isset($model->excel_extra_fields)) { + foreach ($model->excel_extra_fields as $key => $value) { + if ($field == $key) { + $extra_name = $value[0]; + $extra_attribute = $value[1]; + $extra_key = $value[2]; + $extra_info = NModel::factory($extra_name); + if (method_exists($extra_info, $extra_attribute)) { + $item[$field] = $extra_info->$extra_attribute($original_item["$extra_key"]); + } else { + $extra_info->get($original_item["$extra_key"]); + $item[$field] = $extra_info->$extra_attribute; + } + unset($extra_info); + } + } + } + // If it's an uploaded file, put the address in the conf.php before it so that it + // turns into a link in Excel. + if (eregi(UPLOAD_DIR, $item[$field])) { + $item[$field] = PUBLIC_SITE . ereg_replace("^/", "", $item[$field]); + } + $fixed_item = $this->convert_characters($item[$field]); + $data_fields[] = $fixed_item; + } + } + //$data_string = implode(',', $data_fields); + fputcsv($fp, $data_fields); + unset($original_item); + unset($item); + unset($data_fields); + } + // Close the file. + fclose($fp); + $download = new NDownload; + $download->serveFile($filename); + unlink($filename); + } + } + } + + function convert_characters($text) { + $dict = array(chr(138) => 'ä', chr(141) => 'ç', chr(142) => 'é', chr(145) => "'", chr(146) => "'", + chr(147) => '"', chr(148) => '"', chr(150) => '-', chr(151) => '-', chr(154) => 'ö', + chr(157) => 'ù', chr(158) => 'û', chr(160) => ' ', chr(161) => '°', chr(173) => '≠', + chr(188) => 'º', chr(189) => 'Ω', chr(190) => 'æ', chr(191) => 'ø', chr(192) => '¿', + chr(193) => '¡', chr(194) => '¬', chr(195) => '√', chr(196) => 'Æ’', chr(197) => '≈', + chr(198) => '∆', chr(199) => '«', chr(200) => '»', chr(201) => '…', chr(202) => ' ', + chr(203) => 'À', chr(204) => 'Ã', chr(205) => 'Õ', chr(206) => 'Å’', chr(207) => 'Å“', + chr(209) => '—', chr(210) => '“', chr(211) => 'â€', chr(212) => '‘', chr(213) => '’', + chr(214) => '÷', chr(216) => 'ÿ', chr(217) => 'Ÿ', chr(218) => 'â„', chr(219) => '€', + chr(220) => '‹', chr(221) => '›', chr(223) => 'fl', chr(224) => '‡', chr(225) => '·', + chr(226) => '‚', chr(227) => '„', chr(228) => '‰', chr(229) => 'Â', chr(230) => 'Ê', + chr(231) => 'Ã', chr(232) => 'Ë', chr(233) => 'È', chr(234) => 'Ã', chr(235) => 'ÃŽ', + chr(236) => 'Ã', chr(237) => 'ÃŒ', chr(238) => 'Ó', chr(239) => 'Ô', chr(241) => 'Ã’', + chr(242) => 'Ú', chr(243) => 'Û', chr(244) => 'Ù', chr(245) => 'ı', chr(246) => 'ˆ', + chr(248) => '¯', chr(249) => '˘', chr(250) => 'Ë™', chr(251) => 'Ëš', chr(252) => '¸', + chr(253) => 'Ë', chr(255) => 'ˇ', + + 'Š' => 'ä', '' => 'ç', 'Ž' => 'é', '‘' => "'", '’' => "'", + '“' => '"', '”' => '"', '–' => '-', '—' => '-', 'š' => 'ö', + '' => 'ù', 'ž' => 'û', ' ' => ' ', '¡' => '°', '­' => '≠', + '¼' => 'º', '½' => 'Ω', '¾' => 'æ', '¿' => 'ø', 'À' => '¿', + 'Á' => '¡', 'Â' => '¬', 'Ã' => '√', 'Ä' => 'Æ’', 'Å' => '≈', + 'Æ' => '∆', 'Ç' => '«', 'È' => '»', 'É' => '…', 'Ê' => ' ', + 'Ë' => 'À', 'Ì' => 'Ã', 'Í' => 'Õ', 'Î' => 'Å’', 'Ï' => 'Å“', + 'Ñ' => '—', 'Ò' => '“', 'Ó' => 'â€', 'Ô' => '‘', 'Õ' => '’', + 'Ö' => '÷', 'Ø' => 'ÿ', 'Ù' => 'Ÿ', 'Ú' => 'â„', 'Û' => '€', + 'Ü' => '‹', 'Ý' => '›', 'ß' => 'fl', 'à' => '‡', 'á' => '·', + 'â' => '‚', 'ã' => '„', 'ä' => '‰', 'å' => 'Â', 'æ' => 'Ê', + 'ç' => 'Ã', 'è' => 'Ë', 'é' => 'È', 'ê' => 'Ã', 'ë' => 'ÃŽ', + 'ì' => 'Ã', 'í' => 'ÃŒ', 'î' => 'Ó', 'ï' => 'Ô', 'ñ' => 'Ã’', + 'ò' => 'Ú', 'ó' => 'Û', 'ô' => 'Ù', 'õ' => 'ı', 'ö' => 'ˆ', + 'ø' => '¯', 'ù' => '˘', 'ú' => 'Ë™', 'û' => 'Ëš', 'ü' => '¸', + 'ý' => 'Ë', 'ÿ' => 'ˇ', + + '≈ ' => 'ä', 'Œ' => 'Ã¥', '≈Ω' => 'é', 'š' => 'ö', 'œ' => 'ú', 'ž' => 'û', '≈âˆ' => 'ü', + '¥' => '•', 'µ' => 'µ', 'À' => '¿', 'Á' => '¡', 'Â' => '¬', 'Ã' => '√', 'Ä' => 'Æ’', + '√Ö' => '≈', 'Æ' => '∆', 'Ç' => '«', 'È' => '»', 'É' => '…', 'Ê' => ' ', 'Ë' => 'À', + 'Ì' => 'Ã', 'Í' => 'Õ', 'Î' => 'Å’', 'Ï' => 'Å“', 'Ð' => '–', 'Ñ' => '—', 'Ò' => '“', + 'Ó' => 'â€', 'Ô' => '‘', 'Õ' => '’', 'Ö' => '÷', '√ò' => 'ÿ', '√ô' => 'Ÿ', '√ö' => 'â„', + '√õ' => '€', '√ú' => '‹', '√ù' => '›', 'ß' => 'fl', '√ ' => '‡', '√°' => '·', '√¢' => '‚', + '√£' => '„', 'ä' => '‰', 'å' => 'Â', 'æ' => 'Ê', 'ç' => 'Ã', 'è' => 'Ë', 'é' => 'È', + 'ê' => 'Ã', 'ë' => 'ÃŽ', 'ì' => 'Ã', 'í' => 'ÃŒ', 'î' => 'Ó', 'ï' => 'Ô', '√∞' => '', + 'ñ' => 'Ã’', 'ò' => 'Ú', 'ó' => 'Û', 'ô' => 'Ù', 'õ' => 'ı', 'ö' => 'ˆ', '√âˆ' => '¯', + '√π' => '˘', '√∫' => 'Ë™', 'û' => 'Ëš', 'ü' => '¸', '√Ω' => 'Ë', 'ÿ' => 'ˇ', "¬ø" => 'ø', + '¼' => 'º', '¬Ω' => 'Ω', '¾' => 'æ', '≈ ' => 'ä', '' => 'ç', '¬ù' => 'ù', '¬°' => '°', '­' => '-', + '“' => '"', '”' => '"', '–' => '-', "\n" => ' ', "\r" => ' ', '’' => "'", '‚Ä' => '"', + + '¿' => 'ø', 'Æ' => '∆', 'Á' => '¡', 'Â' => '¬', 'À' => '¿', + 'Å' => '≈', 'Ã' => '√', 'Ä' => 'Æ’', 'Ç' => '«', 'Ð' => '–', + 'É' => '…', 'Ê' => ' ', 'È' => '»', 'Ë' => 'À', 'Í' => 'Õ', + 'Î' => 'Å’', 'Ì' => 'Ã', 'Ï' => 'Å“', 'Ñ' => '—', 'Ó' => 'â€', + 'Ô' => '‘', 'Ò' => '“', 'Ø' => 'ÿ', 'Õ' => '’', 'Ö' => '÷', + 'Ú' => 'â„', 'Û' => '€', 'Ù' => 'Ÿ', 'Ü' => '‹', 'Ý' => '›', + 'á' => '·', 'â' => '‚', 'æ' => 'Ê', 'à' => '‡', 'å' => 'Â', + 'ã' => '„', 'ä' => '‰', 'ç' => 'Ã', 'é' => 'È', 'ê' => 'Ã', + 'è' => 'Ë', 'ð' => '', 'ë' => 'ÃŽ', '½' => 'Ω', '¼' => 'º', + '¾' => 'æ', 'í' => 'ÃŒ', 'î' => 'Ó', '¡' => '°', 'ì' => 'Ã', + '¿' => 'ø', 'ï' => 'Ô', '—' => 'ó', 'µ' => 'µ', '–' => 'ñ', + 'ñ' => 'Ã’', 'ó' => 'Û', 'ô' => 'Ù', 'ò' => 'Ú', 'ø' => '¯', + 'õ' => 'ı', 'ö' => 'ˆ', '"' => '"', '­' => '≠', 'ß' => 'fl', + 'ú' => 'Ë™', 'û' => 'Ëš', 'ù' => '˘', 'ü' => '¸', 'ý' => 'Ë', + '¥' => '•', 'ÿ' => 'ˇ', '—' => '-', "\n" => ' ', "\r" => ' '); + + return strtr($text, $dict); + } + +} +?> \ No newline at end of file diff --git a/app/controllers/dashboard_controller.php b/app/controllers/dashboard_controller.php new file mode 100644 index 0000000..09a94f7 --- /dev/null +++ b/app/controllers/dashboard_controller.php @@ -0,0 +1,314 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class DashboardController extends nterchangeController { + function __construct() { + $this->name = 'dashboard'; + $this->default_action = 'show'; + $this->page_title = 'Your Dashboard'; + // set user level allowed to access the actions with required login + $this->user_level_required = N_USER_NORIGHTS; + $this->login_required = true; + $this->base_view_dir = ROOT_DIR; + parent::__construct(); + } + + function index($parameter) { + $this->auto_render = false; + $sidebar_content = $this->render(array('action'=>'description', 'return'=>true)); + if (SITE_DRAFTS) { + $draft_model = &NModel::factory('cms_drafts'); + if ($draft_model) { + $draft_model->cms_modified_by_user = $this->_auth->currentUserId(); + if ($draft_model->find()) { + while ($draft_model->fetch()) { + $asset_ctrl = &NController::factory($draft_model->asset); + $asset_model = &$draft_model->getLink('asset_id', $draft_model->asset); + if ($asset_model) { + $this->set(array('draft'=>$draft_model->toArray(), 'asset_name'=>$asset_ctrl->page_title?$asset_ctrl->page_title:Inflector::humanize($asset_ctrl->name), 'asset'=>$draft_model->asset)); + $this->set($asset_model->toArray()); + $this->setAppend('drafts', $this->render(array('action'=>'draft_record', 'return'=>true))); + } + unset($asset_ctrl); + unset($asset_model); + } + } else { + $this->set('drafts', $this->render(array('action'=>'no_drafts', 'return'=>true))); + } + } + } + // load all workflow output into this variable to be assigned later + $workflow_html = ''; + if (SITE_WORKFLOW) { + $sidebar_content .= $this->render(array('action'=>'workflow_description', 'return'=>true)); + $user_id = $this->_auth->currentUserId(); + // If user is an admin, and has any unsubmitted workflow in groups they don't belong to, display them first + if ($this->_auth->getAuthData('user_level') >= N_USER_ADMIN) { + $workflow = &NController::factory('workflow'); + $workflow_model = &NModel::factory('workflow'); + $workflow_model_pk = $workflow_model->primaryKey(); + $workflow_model->cms_modified_by_user = $user_id; + $workflow_model->submitted = 0; + if ($workflow_model->find(array('order_by'=>'page_id'))) { + $admin_workflow_html = ''; + $this->set('workflow_section', 'Unsubmitted Admin Workflows'); + $workflow_html .= $this->render(array('action'=>'workflow_section', 'return'=>true)); + $page_id = 0; + $page_count = 0; + $page_workflows = array(); + while ($workflow_model->fetch()) { + $workflow_users_model = &NModel::factory('workflow_users'); + $workflow_users_model->workflow_group_id = $workflow_model->workflow_group_id; + $workflow_users_model->user_id = $workflow_model->cms_modified_by_user; + if ($workflow_users_model->find()) { + unset($workflow_users_model); + continue; + } + unset($workflow_users_model); + $unsubmitted[] = $workflow_model->$workflow_model_pk; + $page_content_model = &NModel::factory('page_content'); + $page_content_model->get($workflow_model->page_content_id); + $page_model = &$page_content_model->getLink('page_id', 'page'); + $asset_controller = &NController::factory($workflow_model->asset); + $asset_model = &$asset_controller->getDefaultModel(); + $asset_model->get($workflow_model->asset_id); + $this->convertDateTimesToClient($asset_model); + $action = $workflow->actionToString($workflow_model->action); + $cascade_delete = $page_content_model->cms_workflow?true:false; + // set the page title for the following pages + $this->set('page_title', ''); + if ($workflow_model->page_id == $page_id) { + $page_count++; + } else { + $this->set('page_title', $page_model->title); + $admin_workflow_html .= $this->workflowPageSubmit($page_workflows); + $page_id = $workflow_model->page_id; + $page_count = 0; + $page_workflows = array(); + } + $page_workflows[] = $workflow_model->$workflow_model_pk; + $user = &$workflow_model->getLink('cms_modified_by_user', 'cms_auth'); + $this->set(array('process'=>'submit', 'cascade_delete'=>$cascade_delete, 'approved'=>$workflow_model->approved, 'action'=>$action, 'workflow'=>$workflow_model->toArray(), 'page'=>$page_model->toArray(), 'asset'=>$asset_controller, 'row'=>$asset_model->toArray(), 'user'=>($user?$user->toArray():false))); + $admin_workflow_html .= $this->render(array('action'=>'workflow_record', 'return'=>true)); + } + $admin_workflow_html .= $this->workflowPageSubmit($page_workflows); + if ($admin_workflow_html) { + $this->set(array('workflow_title'=>'Admin Workflows')); + $workflow_html .= $this->render(array('action'=>'workflow', 'return'=>true)) . $admin_workflow_html; + unset($admin_workflow_html); + } + } + unset($workflow_model); + unset($workflow); + } + $workflow_users = &$this->loadModel('workflow_users'); + $workflow_users->user_id = $user_id; + if ($workflow_users->find()) { + while ($workflow_users->fetch()) { + // instantiate workflow group object + $workflow_group = &$workflow_users->getLink('workflow_group_id', 'workflow_group'); + // render current workflow group + $this->set($workflow_group->toArray()); + $workflow_html .= $this->render(array('action'=>'workflow', 'return'=>true)); + // instantiate workflow objects + $workflow = &NController::factory('workflow'); + $workflow_model = &$workflow->getDefaultModel(); + $workflow_model_pk = $workflow_model->primaryKey(); + // find unsubmitted workflows that belong to this user + $workflow_model->submitted = 0; + $workflow_model->completed = 0; + $workflow_model->workflow_group_id = $workflow_group->{$workflow_group->primaryKey()}; + $workflow_model->cms_modified_by_user = $user_id; + $unsubmitted = array(); + if ($workflow_model->find(array('order_by'=>'page_id, asset, asset_id, id'))) { + $this->set('workflow_section', 'Unsubmitted Workflows'); + $workflow_html .= $this->render(array('action'=>'workflow_section', 'return'=>true)); + $page_id = 0; + $page_count = 0; + $page_workflows = array(); + while ($workflow_model->fetch()) { + $unsubmitted[] = $workflow_model->$workflow_model_pk; + $page_content_model = &$workflow_model->getLink('page_content_id', 'page_content'); + if (!$page_content_model) continue; + $page_model = &$page_content_model->getLink('page_id', 'page'); + $asset_controller = &NController::factory($workflow_model->asset); + $asset_model = &$asset_controller->getDefaultModel(); + $asset_model->get($workflow_model->asset_id); + $this->convertDateTimesToClient($asset_model); + $action = $workflow->actionToString($workflow_model->action); + // set the page title for the following pages + $this->set('page_title', ''); + if ($workflow_model->page_id == $page_id) { + $page_count++; + } else { + $this->set('page_title', $page_model->title); + $workflow_html .= $this->workflowPageSubmit($page_workflows); + $page_id = $workflow_model->page_id; + $page_count = 0; + $page_workflows = array(); + } + $page_workflows[] = $workflow_model->$workflow_model_pk; + $user = &$workflow_model->getLink('cms_modified_by_user', 'cms_auth'); + $this->convertDateTimesToClient($workflow_model); + $this->set(array('process'=>'submit', 'list_only'=>false, 'approved'=>$workflow_model->approved, 'action'=>$action, 'workflow'=>$workflow_model->toArray(), 'page'=>$page_model->toArray(), 'asset'=>$asset_controller, 'row'=>$asset_model->toArray(), 'user'=>($user?$user->toArray():false))); + $workflow_html .= $this->render(array('action'=>'workflow_record', 'return'=>true)); + } + $workflow_html .= $this->workflowPageSubmit($page_workflows); + } + // find in process workflows, resetting the model object first + $workflow_model->reset(); + $workflow_model->workflow_group_id = $workflow_group->{$workflow_group->primaryKey()}; + $workflow_model->completed = 0; + $conditions = ''; + foreach ($unsubmitted as $id) { + $conditions .= ($conditions?' AND ':'') . "$workflow_model_pk!=$id"; + } + $this->set('workflow_section', 'Workflows in Process'); + $workflow_html .= $this->render(array('action'=>'workflow_section', 'return'=>true)); + $workflow_html_content = ''; + if ($workflow_model->find(array('conditions'=>$conditions, 'order_by'=>'page_id, asset, asset_id, id'))) { + $workflow_models = array(); + while ($workflow_model->fetch()) { + $workflow_models[] = clone($workflow_model); + } + $i = 0; + $current_asset = ''; + foreach ($workflow_models as $w_model) { + if ($w_model->submitted == 0) { + continue; + } + if ($current_asset != $w_model->asset . $w_model->asset_id) { + $current_asset = $w_model->asset . $w_model->asset_id; + if (!$page_content_model = &$w_model->getLink('page_content_id', 'page_content')) continue; + if (!$page_model = &$page_content_model->getLink('page_id', 'page')) continue; + $user_def = $workflow->getWorkflowUser($w_model->workflow_group_id); + if ($user_def) { + $user_role = $user_def->role; + $user_id = $user_def->user_id; + } + $user_rights = $workflow->getWorkflowUserRights($page_model); + $i = 0; + } + $asset_controller = &NController::factory($w_model->asset); + $asset_model = &$asset_controller->getDefaultModel(); + $asset_model->get($w_model->asset_id); + $this->convertDateTimesToClient($asset_model); + $action = $workflow->actionToString($w_model->action); + $all_workflow_users = $workflow->getWorkflowUsers($workflow_model->workflow_group_id); + if (count($all_workflow_users) < 2) { + $i++; + } + if ($i == 0) { + if ($user_rights == WORKFLOW_RIGHT_EDIT) { + $process = 'In Process - ' . ($w_model->approved?'Approved':'Unapproved'); + } else if ($user_rights & WORKFLOW_RIGHT_EDIT) { + // this is someone with editing rights and more. Could be the same user that submitted it. + $process = ($w_model->approved?'In Process - Approved':'editapprove'); + } else { + // This is someone up the line. Let them know something's coming, but they don't need to know what yet. + if ($w_model->approved) { + $process = 'Approved'; + } else { + $process = 'A workflow has been started. You will be notified if/when you need to take action.'; + } + } + } else if ($i == 1) { + if ($user_rights == WORKFLOW_RIGHT_EDIT) { + $process = 'In Process - ' . ($w_model->approved?'Approved':'Unapproved'); + } else if ($user_rights & WORKFLOW_RIGHT_APPROVE && $user_rights & WORKFLOW_RIGHT_PUBLISH) { + // this is someone with Approval rights. Could be the same user that submitted it + $process = 'approve'; + } else { + $process = 'In Process - ' . ($w_model->approved?'Approved':'Unapproved'); + } + } + $user = &$w_model->getLink('cms_modified_by_user', 'cms_auth'); + $this->convertDateTimesToClient($w_model); + $this->set(array('process'=>$process, 'list_only'=>false, 'approved'=>$w_model->approved, 'action'=>$action, 'workflow'=>$w_model->toArray(), 'page'=>$page_model->toArray(), 'asset'=>$asset_controller, 'row'=>$asset_model->toArray(), 'user'=>($user?$user->toArray():false))); + $workflow_html_content .= $this->render(array('action'=>'workflow_record', 'return'=>true)); + $i++; + } + } + $workflow_html .= $workflow_html_content?$workflow_html_content:$this->render(array('action'=>'workflow_norecords', 'return'=>true)); + // find completed workflows, resetting the model object first + $workflow_model->reset(); + $workflow_model->workflow_group_id = $workflow_group->{$workflow_group->primaryKey()}; + $workflow_model->completed = 1; + $workflow_model->parent_workflow = 0; + // bad timg - shouldn't do this here + $workflow_html .= '
' . "\n"; + $this->set('workflow_section', 'Completed Workflows'); + $workflow_html .= $this->render(array('action'=>'workflow_section', 'return'=>true)); + if ($workflow_model->find(array('conditions'=>$conditions, 'order_by'=>'cms_created DESC', 'limit'=>5))) { + $workflow_models = array(); + while ($workflow_model->fetch()) { + $page_model = &NModel::factory('page'); + $page_model->{$page_model->primaryKey()} = $workflow_model->page_id; + // if the page is not deleted, this works + if (!$page_model->find(null, true)) { + // otherwise, specify a deleted page and try again + $page_model->reset(); + $page_model->{$page_model->primaryKey()} = $workflow_model->page_id; + $page_model->cms_deleted = 1; + $page_model->find(null, true); + } + $page_values = $page_model?$page_model->toArray():false; + $asset_controller = &NController::factory($workflow_model->asset); + $asset_model = &$asset_controller->getDefaultModel(); + if (!$asset_model->get($workflow_model->asset_id)) { + $asset_model->reset(); + $asset_model->cms_deleted = 1; + $asset_model->get($workflow_model->asset_id); + } + $this->convertDateTimesToClient($asset_model); + $action = $workflow->actionToString($workflow_model->action); + $user = &$workflow_model->getLink('cms_modified_by_user', 'cms_auth'); + $this->convertDateTimesToClient($workflow_model); + $values = array('process'=>null, 'list_only'=>true, 'approved'=>$workflow_model->approved, 'action'=>$action, 'workflow'=>$workflow_model->toArray(), 'asset'=>$asset_controller, 'row'=>$asset_model->toArray(), 'page'=>$page_values, 'user'=>($user?$user->toArray():false)); + $this->set($values); + $workflow_html .= $this->render(array('action'=>'workflow_record', 'return'=>true)); + } + } + $workflow_html .= '
' . "\n"; + } + } else { + $workflow_html .= $this->render(array('action'=>'no_workflows', 'return'=>true)); + } + $this->set('workflow', $workflow_html); + } + $this->set('SIDEBAR_CONTENT', $sidebar_content); + $this->setAppend('SIDEBAR_CONTENT', $this->render(array('action'=>'nterchange_training', 'return'=>true))); + $this->setAppend('SIDEBAR_CONTENT', $this->render(array('action'=>'dashboard_client_sidebar_content', 'return'=>true))); + $this->render(array('layout'=>'default')); + } + + function workflowPageSubmit(&$page_workflows) { + $this->set('page_workflows', false); + if (count($page_workflows)) { + $this->set('page_workflows', $page_workflows); + return $this->render(array('action'=>'workflow_page_submit', 'return'=>true)); + } + return ''; + } + + function dashboardClientContent() { + $this->render(array('action'=>'dashboard_client_content', 'return'=>false)); + } +} +?> diff --git a/app/controllers/excel_export_controller.php b/app/controllers/excel_export_controller.php new file mode 100644 index 0000000..365e203 --- /dev/null +++ b/app/controllers/excel_export_controller.php @@ -0,0 +1,267 @@ + + * @copyright 2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class ExcelExportController extends AdminController { + var $default_foreign_keys = array('cms_modified_by_user'=>array('cms_auth', 'real_name')); + var $default_field_exclusions = array('id'=>true, 'cms_active'=>true, 'cms_draft'=>true, 'cms_deleted'=>true, 'cms_headline'=>true); + + function __construct() { + $this->name = 'excel_export'; + // set user level allowed to access the actions with required login + $this->user_level_required = N_USER_EDITOR; + $this->login_required = true; + $this->page_title = 'Excel Export'; + parent::__construct(); + } + + function export($model_name) { + if (isset($model_name)) { + $model = NModel::factory($model_name); + // Foreign Key Lookup Support + if (isset($model->excel_export)) { + $model_foreign_keys = $model->excel_export; + // Default standard foreign keys get added and merged here. + $foreign_keys = array_merge($this->default_foreign_keys, $model_foreign_keys); + } else { + $foreign_keys = $this->default_foreign_keys; + } + // Field Inclusion and Exclusion Support + if (isset($model->excel_exclude_fields)) { + $model_excel_inclusions = $model->excel_exclude_fields; + $field_exclusions = array_merge($this->default_field_exclusions, $model_excel_inclusions); + } else { + $field_exclusions = $this->default_field_exclusions; + } + // If $_GET['search'] is set, only export those items. + $search = isset($_GET['search'])?$_GET['search']:null; + $search_field = isset($_GET['search_field'])?$_GET['search_field']:null; + if (isset($search) && $search != null) { + if (!$search_field && $search_field != null) { + $acon = NController::factory('asset'); + $search_field = isset($model->search_field)?$model->search_field:$acon->search_field; + unset($acon); + } + } + $options = $search?array('conditions'=>"$search_field LIKE '%$search%'"):array(); + // Can set options in the model about items exported to the Excel. + // Only export items that meet a certain criteria - not everything in the list. + // For example: $this->viewlist_options = array('conditions'=>"cms_modified_by_user = '4'"); + if (isset($model->viewlist_options)) { + foreach ($model->viewlist_options as $key => $val) { + if (isset($options[$key])) { + $options[$key] .= ' AND ' . $val; + } else { + $options[$key] = "$val"; + } + } + } + + if ($model->find($options)) { + $fields = $model->fields(); + // Add additional custom fields here from the model file. + if (isset($model->excel_extra_fields)) { + foreach ($model->excel_extra_fields as $key => $value) { + $fields[] = $key; + } + } + require_once 'Spreadsheet/Excel/Writer.php'; + + // Creating a workbook + $workbook = new Spreadsheet_Excel_Writer(); + $worksheet =& $workbook->addWorksheet(ucwords(str_replace('_', ' ', $model_name))); + $worksheet->setColumn(2, 4, 20); + $worksheet->setColumn(7, 7, 15); + $worksheet->setColumn(10, 28, 20); + + // Make the title line look a little different + $title =& $workbook->addFormat(); + $title->setBold(); + $title->setAlign('center'); + $title->setBottom(2); + + // Let's add the field names to the title line. + // Leave out a few. + $x = 0; + $worksheet->setRow(0, 18.75); + foreach ($fields as $field) { + $exclude_this = array_key_exists($field, $field_exclusions); + if ($exclude_this && $field_exclusions[$field] == true) { + // do nothing + } else { + $worksheet->write(0, $x, ucwords(str_replace('_', ' ', $field)), $title); + $x++; + } + } + + // Now here comes the data. + $y = 1; + while ($model->fetch()) { + $item = $model->toArray(); + // For reference while we're working with things. + $original_item = array(); + $original_item = $item; + $x = 0; + $worksheet->setRow($y, 18.75); + foreach ($fields as $field) { + $exclude_this = array_key_exists($field, $field_exclusions); + if ($exclude_this && $field_exclusions[$field] == true) { + // do nothing + } else { + // Look for foreign keys and replace if assigned. + foreach($foreign_keys as $foreign_key => $foreign_key_value) { + if ($field == $foreign_key) { + $fk_model_name = $foreign_key_value[0]; + $fk_model_headline = $foreign_key_value[1]; + $fk_model = NModel::factory($fk_model_name); + if ($fk_model && ($fk_model->get($item[$field]))) { + $item[$field] = $fk_model->{$fk_model_headline}; + } + unset($fk_model); + } + } + + //Look for bitmask fields and replace with string value instead of numeric total + if (is_array($model->bitmask_fields) && count($model->bitmask_fields)) { + $bitmask_keys = array_keys($model->bitmask_fields); + if (in_array($field, $bitmask_keys)) { + $bitmask_total = $item[$field]; + $value_str = ''; + $i = 0; + foreach($model->bitmask_fields[$field] as $bit=>$val) { + if($bit & $bitmask_total) { + if($i > 0) { + $value_str .= ', '; + } + $value_str .= $val; + $i ++; + } + } + $item[$field] = $value_str; + } + } + + // Any extra fields get dealt with here. + if (isset($model->excel_extra_fields)) { + foreach ($model->excel_extra_fields as $key => $value) { + if ($field == $key) { + $extra_name = $value[0]; + $extra_attribute = $value[1]; + $extra_key = $value[2]; + $extra_info = NModel::factory($extra_name); + if (method_exists($extra_info, $extra_attribute)) { + $item[$field] = $extra_info->$extra_attribute($original_item["$extra_key"]); + } else { + $extra_info->get($original_item["$extra_key"]); + $item[$field] = $extra_info->$extra_attribute; + } + unset($extra_info); + } + } + } + // If it's an uploaded file, put the address in the conf.php before it so that it + // turns into a link in Excel. + if (eregi(UPLOAD_DIR, $item[$field])) { + $item[$field] = PUBLIC_SITE . ereg_replace("^/", "", $item[$field]); + } + $worksheet->write($y, $x, $this->convert_characters($item[$field])); + $x++; + } + } + $y++; + unset($original_item); + unset($item); + } + // sending HTTP headers + $xls_filename = $model_name . '_entries.xls'; + $workbook->send($xls_filename); + $workbook->close(); + } + } + } + + function convert_characters($text) { + $dict = array(chr(138) => 'Š', chr(141) => '', chr(142) => 'Ž', chr(145) => "'", chr(146) => "'", + chr(147) => '"', chr(148) => '"', chr(150) => '-', chr(151) => '-', chr(154) => 'š', + chr(157) => '', chr(158) => 'ž', chr(160) => ' ', chr(161) => '¡', chr(173) => '­', + chr(188) => '¼', chr(189) => '½', chr(190) => '¾', chr(191) => '¿', chr(192) => 'À', + chr(193) => 'Á', chr(194) => 'Â', chr(195) => 'Ã', chr(196) => 'Ä', chr(197) => 'Å', + chr(198) => 'Æ', chr(199) => 'Ç', chr(200) => 'È', chr(201) => 'É', chr(202) => 'Ê', + chr(203) => 'Ë', chr(204) => 'Ì', chr(205) => 'Í', chr(206) => 'Î', chr(207) => 'Ï', + chr(209) => 'Ñ', chr(210) => 'Ò', chr(211) => 'Ó', chr(212) => 'Ô', chr(213) => 'Õ', + chr(214) => 'Ö', chr(216) => 'Ø', chr(217) => 'Ù', chr(218) => 'Ú', chr(219) => 'Û', + chr(220) => 'Ü', chr(221) => 'Ý', chr(223) => 'ß', chr(224) => 'à', chr(225) => 'á', + chr(226) => 'â', chr(227) => 'ã', chr(228) => 'ä', chr(229) => 'å', chr(230) => 'æ', + chr(231) => 'ç', chr(232) => 'è', chr(233) => 'é', chr(234) => 'ê', chr(235) => 'ë', + chr(236) => 'ì', chr(237) => 'í', chr(238) => 'î', chr(239) => 'ï', chr(241) => 'ñ', + chr(242) => 'ò', chr(243) => 'ó', chr(244) => 'ô', chr(245) => 'õ', chr(246) => 'ö', + chr(248) => 'ø', chr(249) => 'ù', chr(250) => 'ú', chr(251) => 'û', chr(252) => 'ü', + chr(253) => 'ý', chr(255) => 'ÿ', + + 'Š' => 'Š', '' => '', 'Ž' => 'Ž', '‘' => "'", '’' => "'", + '“' => '"', '”' => '"', '–' => '-', '—' => '-', 'š' => 'š', + '' => '', 'ž' => 'ž', ' ' => ' ', '¡' => '¡', '­' => '­', + '¼' => '¼', '½' => '½', '¾' => '¾', '¿' => '¿', 'À' => 'À', + 'Á' => 'Á', 'Â' => 'Â', 'Ã' => 'Ã', 'Ä' => 'Ä', 'Å' => 'Å', + 'Æ' => 'Æ', 'Ç' => 'Ç', 'È' => 'È', 'É' => 'É', 'Ê' => 'Ê', + 'Ë' => 'Ë', 'Ì' => 'Ì', 'Í' => 'Í', 'Î' => 'Î', 'Ï' => 'Ï', + 'Ñ' => 'Ñ', 'Ò' => 'Ò', 'Ó' => 'Ó', 'Ô' => 'Ô', 'Õ' => 'Õ', + 'Ö' => 'Ö', 'Ø' => 'Ø', 'Ù' => 'Ù', 'Ú' => 'Ú', 'Û' => 'Û', + 'Ü' => 'Ü', 'Ý' => 'Ý', 'ß' => 'ß', 'à' => 'à', 'á' => 'á', + 'â' => 'â', 'ã' => 'ã', 'ä' => 'ä', 'å' => 'å', 'æ' => 'æ', + 'ç' => 'ç', 'è' => 'è', 'é' => 'é', 'ê' => 'ê', 'ë' => 'ë', + 'ì' => 'ì', 'í' => 'í', 'î' => 'î', 'ï' => 'ï', 'ñ' => 'ñ', + 'ò' => 'ò', 'ó' => 'ó', 'ô' => 'ô', 'õ' => 'õ', 'ö' => 'ö', + 'ø' => 'ø', 'ù' => 'ù', 'ú' => 'ú', 'û' => 'û', 'ü' => 'ü', + 'ý' => 'ý', 'ÿ' => 'ÿ', + + 'Å ' => 'Š', 'Å’' => 'Œ', 'Ž' => 'Ž', 'Å¡' => 'š', 'Å“' => 'œ', 'ž' => 'ž', 'Ÿ' => 'Ÿ', + 'Â¥' => '¥', 'µ' => 'µ', 'À' => 'À', 'Ã' => 'Á', 'Â' => 'Â', 'Ã' => 'Ã', 'Ä' => 'Ä', + 'Ã…' => 'Å', 'Æ' => 'Æ', 'Ç' => 'Ç', 'È' => 'È', 'É' => 'É', 'Ê' => 'Ê', 'Ë' => 'Ë', + 'ÃŒ' => 'Ì', 'Ã' => 'Í', 'ÃŽ' => 'Î', 'Ã' => 'Ï', 'Ã' => 'Ð', 'Ñ' => 'Ñ', 'Ã’' => 'Ò', + 'Ó' => 'Ó', 'Ô' => 'Ô', 'Õ' => 'Õ', 'Ö' => 'Ö', 'Ø' => 'Ø', 'Ù' => 'Ù', 'Ú' => 'Ú', + 'Û' => 'Û', 'Ãœ' => 'Ü', 'Ã' => 'Ý', 'ß' => 'ß', 'à ' => 'à', 'á' => 'á', 'â' => 'â', + 'ã' => 'ã', 'ä' => 'ä', 'Ã¥' => 'å', 'æ' => 'æ', 'ç' => 'ç', 'è' => 'è', 'é' => 'é', + 'ê' => 'ê', 'ë' => 'ë', 'ì' => 'ì', 'í' => 'í', 'î' => 'î', 'ï' => 'ï', 'ð' => 'ð', + 'ñ' => 'ñ', 'ò' => 'ò', 'ó' => 'ó', 'ô' => 'ô', 'õ' => 'õ', 'ö' => 'ö', 'ø' => 'ø', + 'ù' => 'ù', 'ú' => 'ú', 'û' => 'û', 'ü' => 'ü', 'ý' => 'ý', 'ÿ' => 'ÿ', "¿" => '¿', + '¼' => '¼', '½' => '½', '¾' => '¾', 'Å ' => 'Š', 'Â' => '', 'Â' => '', '¡' => '¡', '­' => '-', + '“' => '"', 'â€' => '"', '–' => '-', "\n" => ' ', "\r" => ' ', '’' => "'", 'â€' => '"', + + '¿' => '¿', 'Æ' => 'Æ', 'Á' => 'Á', 'Â' => 'Â', 'À' => 'À', + 'Å' => 'Å', 'Ã' => 'Ã', 'Ä' => 'Ä', 'Ç' => 'Ç', 'Ð' => 'Ð', + 'É' => 'É', 'Ê' => 'Ê', 'È' => 'È', 'Ë' => 'Ë', 'Í' => 'Í', + 'Î' => 'Î', 'Ì' => 'Ì', 'Ï' => 'Ï', 'Ñ' => 'Ñ', 'Ó' => 'Ó', + 'Ô' => 'Ô', 'Ò' => 'Ò', 'Ø' => 'Ø', 'Õ' => 'Õ', 'Ö' => 'Ö', + 'Ú' => 'Ú', 'Û' => 'Û', 'Ù' => 'Ù', 'Ü' => 'Ü', 'Ý' => 'Ý', + 'á' => 'á', 'â' => 'â', 'æ' => 'æ', 'à' => 'à', 'å' => 'å', + 'ã' => 'ã', 'ä' => 'ä', 'ç' => 'ç', 'é' => 'é', 'ê' => 'ê', + 'è' => 'è', 'ð' => 'ð', 'ë' => 'ë', '½' => '½', '¼' => '¼', + '¾' => '¾', 'í' => 'í', 'î' => 'î', '¡' => '¡', 'ì' => 'ì', + '¿' => '¿', 'ï' => 'ï', '—' => '—', 'µ' => 'µ', '–' => '–', + 'ñ' => 'ñ', 'ó' => 'ó', 'ô' => 'ô', 'ò' => 'ò', 'ø' => 'ø', + 'õ' => 'õ', 'ö' => 'ö', '"' => '"', '­' => '­', 'ß' => 'ß', + 'ú' => 'ú', 'û' => 'û', 'ù' => 'ù', 'ü' => 'ü', 'ý' => 'ý', + '¥' => '¥', 'ÿ' => 'ÿ', '—' => '-', "\n" => ' ', "\r" => ' '); + + return strtr($text, $dict); + } + +} +?> \ No newline at end of file diff --git a/app/controllers/imageviewer_controller.php b/app/controllers/imageviewer_controller.php new file mode 100644 index 0000000..7d50814 --- /dev/null +++ b/app/controllers/imageviewer_controller.php @@ -0,0 +1,28 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class ImageviewerController extends AppController { + function __construct() { + $this->name = 'imageviewer'; + parent::__construct(); + } + + function index() { + } +} +?> \ No newline at end of file diff --git a/app/controllers/login_controller.php b/app/controllers/login_controller.php new file mode 100644 index 0000000..9c705f0 --- /dev/null +++ b/app/controllers/login_controller.php @@ -0,0 +1,149 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class LoginController extends AppController { + function __construct() { + $this->base_dir = APP_DIR; + $this->name = 'login'; + $this->page_title = 'Login'; + parent::__construct(); + } + + function index() { + $this->login(); + } + + function login() { + NDebug::debug('Redirecting ' . $_SERVER['REMOTE_ADDR'] . ' to login to nterchange.', N_DEBUGTYPE_AUTH); + $auth = new NAuth(); + $auth->start(); + + $username = $auth->username; + $status = $auth->status; + + $form = new NQuickForm('login_form', 'post', preg_replace('/logout=1[\&]?/', '', $_SERVER['REQUEST_URI'])); + $form->setDefaults(array('username'=>$username)); + if (isset($_GET['logout']) && $_GET['logout'] == 1) { + $form->addElement('cmsalert', 'logout_header', 'You have signed out. Sign back in to continue.'); + } else { + if ($status < 0 &&!empty($username)) { + $form->addElement('cmserror', 'login_status', $auth->statusMessage($status)); + } else { + $form->addElement('cmsalert', 'login_status', 'Please sign in and you will be sent right along.'); + } + } + $form->addElement('text', 'username', 'Username', array('maxlength'=>32, 'style'=>'width:300px;')); + $form->addElement('password', 'password', 'Password', array('maxlength'=>32, 'style'=>'width:150px;')); + // $form->addElement('checkbox', 'remember', null, 'Remember me for 2 weeks.'); + $form->addElement('submit', 'login', 'Sign In'); + $referer = isset($_GET['_referer'])?urlencode($_GET['_referer']):urlencode('/' . $this->base_dir); + $form->addElement('hidden', '_referer', $referer); + + if ($auth->checkAuth()) { + NDebug::debug('Logged ' . $_POST['username'] . ' from ' . $_SERVER['REMOTE_ADDR'] . ' in to nterchange.', N_DEBUGTYPE_AUTH); + // Log this in the audit trail. + $user_id = $auth->currentUserID(); + $audit_trail = &NController::factory('audit_trail'); + $audit_trail->insert(array('asset'=>'users', 'asset_id'=>$user_id, 'action_taken'=>AUDIT_ACTION_LOGIN)); + unset($audit_trail); + // Redirect to the page requested. + header('Location:' . urldecode($referer)); + exit; + } + + $content = $form->toHTML(); + $this->set(array('MAIN_CONTENT'=>$content, 'username'=>$username, 'status'=>$status)); + $this->auto_render = false; + $this->render(array('layout'=>'login')); + } + + /** + * forgot - I forgot my password and need to reset it. Takes an email address and + * sends a confirmation email with a random token to that address. + * + * @return void + **/ + function forgot() { + $form = new NQuickForm('reset_password', 'post'); + $form->addElement('text', 'email', 'Email Address', array('maxlength'=>32, 'style'=>'width:300px;')); + $form->addElement('submit', 'reset_password', 'Reset Password'); + $form->addRule('email', 'You need to enter an email address.', 'required', null, 'client'); + $form->addRule('email', 'The email does not appear to be the correct format', 'email', null, 'client'); + if ($form->validate()) { + $vals = $form->exportValues(); + if (isset($vals['email'])) { + $cms_auth = NModel::factory('cms_auth'); + // Set the token - then send the email. + if ($result = $cms_auth->setConfirmationToken($vals['email'])) { + // Send the confirmation email. + $user = NController::factory('users'); + $user->sendConfirmationEmail($vals['email']); + } + } + // TODO: Put this into the template and out of here. + if ($result == true) { + $content = '

We have sent you a confirmation - please check your email and follow the instructions.

'; + } else { + $content = '

There was a problem - please click back and enter your email address again.

'; + } + $this->set(array('MAIN_CONTENT'=>$content, 'forgot'=>'true')); + } else { + $content = $form->toHTML(); + $this->set(array('MAIN_CONTENT'=>$content, 'forgot'=>'true')); + } + $this->auto_render = false; + $this->render(array('layout'=>'login')); + } + + /** + * confirmPasswordReset - Takes a token passed in the get string, verifies it and resets + * the corresponding password for that particular email address. + * + * @return void + **/ + function confirmPasswordReset() { + // Verify the token + $passed_token = $_GET['token']; + $cms_auth = NModel::factory('cms_auth'); + $cms_auth->confirmation_token = $passed_token; + // If it checks out, then send out the new password. + if ($cms_auth->find()) { + while ($cms_auth->fetch()) { + // If it's there - grab the email. + $email = $cms_auth->email; + // Set the confirmation_token to NULL + $cms_auth->confirmation_token = 'NULL'; + $cms_auth->save(); + // Reset it and send it out. + $cms_auth->resetPassword($email); + $content = 'The password was reset and emailed.'; + } + } else { + $content = 'There was a problem - please try again.'; + } + $this->set(array('MAIN_CONTENT'=>$content)); + $this->auto_render = false; + $this->render(array('layout'=>'login')); + } + +} +?> diff --git a/app/controllers/memcache_controller.php b/app/controllers/memcache_controller.php new file mode 100644 index 0000000..d48dd6d --- /dev/null +++ b/app/controllers/memcache_controller.php @@ -0,0 +1,41 @@ + + * @copyright 2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + * @since Version 3.1.17 + * @todo Expose this if you're actually running a memcached server. + */ +class MemcacheController extends AppController { + function __construct() { + $this->login_required = true; + parent::__construct(); + } + + /** + * index - Just show the memcache server's statistics. + * + * @return void + **/ + function index() { + $this->auto_render = true; + $memcache_obj = new Memcache; + $memcache_obj->addServer(MEMCACHED_SERVER, MEMCACHED_SERVER_PORT); + $stats = $memcache_obj->getExtendedStats(); + varDump($stats); + } +} +?> \ No newline at end of file diff --git a/app/controllers/nterchange_controller.php b/app/controllers/nterchange_controller.php new file mode 100644 index 0000000..7993bed --- /dev/null +++ b/app/controllers/nterchange_controller.php @@ -0,0 +1,73 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class nterchangeController extends AppController { + var $base_dir = APP_DIR; + function __construct() { + if (defined('ADMIN_URL') && constant('ADMIN_URL') != false && is_string(ADMIN_URL) && preg_match('|^/' . APP_DIR . '/|', $_SERVER['REQUEST_URI'])) { + if (!preg_match('|http[s]?://' . $_SERVER['SERVER_NAME'] . '|', ADMIN_URL)) { + $loc = preg_replace('|/$|', '', ADMIN_URL) . $_SERVER['REQUEST_URI']; + // if you don't want a 404 and want to redirect instead, comment out this line + die(NDispatcher::error404()); + header('Location:' . $loc); + exit; + } + } + if (is_null($this->name)) + $this->name = 'nterchange'; + if (is_null($this->base_view_dir)) + $this->base_view_dir = BASE_DIR; + if (!defined('IN_NTERCHANGE')) define('IN_NTERCHANGE', preg_match('|^/' . APP_DIR . '|', NServer::env('REQUEST_URI'))?true:false); + parent::__construct(); + } + + function navigation($current_section) { + if (!isset($this->_auth)) return; + $current_user_level = $this->_auth->getAuthData('user_level'); + // need to loop through other constructors and see + // if they belong in the navigation tabs + $navigation = array(); + $navigation[] = array('title'=>'Dashboard', 'controller'=>'dashboard', 'class'=>''); + $navigation[] = array('title'=>'Site Admin', 'controller'=>'site_admin', 'class'=>''); + if ($current_user_level >= N_USER_ADMIN) { + $navigation[] = array('title'=>'Content', 'controller'=>'content', 'class'=>''); + } + if (SITE_WORKFLOW) { + $navigation[] = array('title'=>'Workflow', 'controller'=>'workflow_group', 'class'=>''); + } + $navigation[] = array('title'=>'Admin', 'controller'=>'admin', 'class'=>'right'); + if ($current_user_level < N_USER_ADMIN) { + $navigation[] = array('title'=>'User', 'controller'=>'users', 'class'=>'right'); + } + foreach ($navigation as $k=>$nav) { + $ctrl = &NController::factory($nav['controller']); + $ctrl->_auth = &$this->_auth; + if (!$ctrl || !$ctrl->checkUserLevel()) { + unset($navigation[$k]); + continue; + } + if ($this->name == $ctrl->name || is_a($this, get_class($ctrl))) { + $navigation[$k]['class'] .= ($navigation[$k]['class']?' ':'') . 'current'; + } + } + return $navigation; + } +} diff --git a/app/controllers/page_content_controller.php b/app/controllers/page_content_controller.php new file mode 100644 index 0000000..510694c --- /dev/null +++ b/app/controllers/page_content_controller.php @@ -0,0 +1,732 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class PageContentController extends nterchangeController { + function __construct() { + $this->name = 'page_content'; + parent::__construct(); + $this->login_required = true; + $this->public_actions = array('select_content_type', 'add_new_content', 'add_existing_content', 'remove_content', 'reorder'); + // set user level allowed to access the actions with required login + $this->user_level_required = N_USER_NORIGHTS; + $this->base_view_dir = ROOT_DIR; + } + + function selectContentType($parameter) { + $page_model = &$this->loadModel('page'); + $page_model->get($parameter); + // instantiate form, + include_once 'n_quickform.php'; + $form = new NQuickForm('select_content_type'); + $values = $form->getSubmitValues(); + + if(isset($values['template_container_id'])){ + $template_container_id = $values['template_container_id']; + } else { + if(isset($this->params['template_container_id'])){ + $template_container_id = $this->params['template_container_id']; + } else { + $template_container_id = false; + } + } + $form->addElement('header', null, 'Do you wish to add new or existing content to the "' . $page_model->title . '" page?'); + // next action + $options = array('addnewcontent'=>'New Content', 'addexistingcontent'=>'Existing Content'); + $form->addElement('select', '_action', 'Select', $options); + // assets for this container + $model = &$this->loadModel('cms_asset_template'); + $pk = $model->primaryKey(); + $model->page_template_container_id = $template_container_id; + $options = array(); + if ($model->find(array('join'=>'INNER JOIN cms_asset_info ON cms_asset_info.asset=' . $model->tableName() . '.asset'))) { + while ($model->fetch()) { + $options[$model->asset] = $model->asset_name; + } + } + $form->addElement('select', 'asset', 'Asset', $options); + // hidden values + $form->addElement('hidden', 'page_id', $parameter); + $form->addElement('hidden', 'template_container_id', $template_container_id); + if (isset($this->params['_referer'])) { + $form->addElement('hidden', '_referer', urlencode($this->params['_referer'])); + } + // finish up + $form->addElement('submit', '__submit__', 'go'); + // rules + $form->addRule('asset', '', 'required'); + $form->addRule('template_container_id', '', 'required'); + // validation + if ($form->validate()) { + $values = $form->exportValues(); + $params = array('asset'=>$this->params['asset'], 'template_container_id'=>$this->params['template_container_id']); + if (isset($this->params['_referer'])) { + $params['_referer'] = $this->params['_referer']; + } + $this->redirectTo($values['_action'], $parameter, $params); + } + unset($page_model); + $this->auto_render = false; + $this->page_title = 'Select Content Type'; + $this->set('form', $form->toHTML()); + $this->render(array('action'=>'form', 'layout'=>'plain')); + } + + function addNewContent($parameter, $load_model_content=false) { + $page_model = &$this->loadModel('page'); + $page_model->get($parameter); + $template_container_id = isset($this->params['template_container_id'])?$this->params['template_container_id']:false; + $asset = isset($this->params['asset'])?$this->params['asset']:false; + $asset_controller = &NController::singleton($asset); + $asset_controller->_auth = new NAuth(); + + // load the model layer with info + $asset_model = &$asset_controller->getDefaultModel(); + + // create the form + include_once 'controller/form.php'; + $cform = new ControllerForm($asset_controller, $asset_model); + $form = &$cform->getForm(); + // check for workflow + if (SITE_WORKFLOW) { + // get the users rights and bit compare them below + $workflow = &NController::factory('workflow'); + $user_rights = $workflow->getWorkflowUserRights($page_model); + $workflow_group = &$workflow->getWorkflowGroup($page_model); + if ($workflow_group && !($user_rights & WORKFLOW_RIGHT_EDIT)) { + // they don't belong here - go to the dashboard + header('Location:/' . APP_DIR . '/dashboard'); + } else if ($user_rights & WORKFLOW_RIGHT_EDIT) { + $form->insertElementBefore(NQuickForm::createElement('submit', '__submit_workflow__', 'Start Workflow'), '__submit__'); + $form->removeElement('__submit__'); + } + unset($workflow); + } + // timed content + $form->addElement('header', null, 'Make it timed content?'); + $timed_options = array('format'=>'Y-m-d H:i', 'minYear'=>date('Y'), 'maxYear'=>date('Y')+4, 'addEmptyOption'=>true); + $form->addElement('date', 'timed_start', 'Timed Start', $timed_options); + $form->addElement('date', 'timed_end', 'Timed End', $timed_options); + $form->addElement('submit', '__submit_timed__', 'Add Scheduled Content'); + // page_content values + $form->addElement('hidden', 'template_container_id', $template_container_id); + $form->addElement('hidden', 'asset', $asset); + if (isset($this->params['_referer'])) { + $form->addElement('hidden', '_referer', urlencode($this->params['_referer'])); + } + // assign the info and render + $asset_controller->base_dir = APP_DIR; + $assigns = array(); + $table = $asset_model->table(); + $fields = $asset_model->fields(); + if ($form->validate()) { + $values = $form->getSubmitValues(); + if (in_array('cms_created', $fields)) { + $asset_model->cms_created = $asset_model->now(); + } + if (in_array('cms_modified', $fields)) { + $asset_model->cms_modified = $asset_model->now(); + } + // set the user id if it's applicable and available + if (in_array('cms_modified_by_user', $fields)) { + $asset_model->cms_modified_by_user = isset($asset_controller->_auth)?$asset_controller->_auth->currentUserId():0; + } + $referer = isset($values['_referer'])?$values['_referer']:false; + if ($referer) { + // cheat and remove the referer from the form oject so it doesn't redirect + if (isset($form->_submitValues['_referer'])) unset($form->_submitValues['_referer']); + } + $success = $form->process(array($cform, 'processForm')); + $asset_id = $asset_model->{$asset_model->primaryKey()}; + if ($success) { + $values = $form->exportValues(); + $model = &$this->loadModel($this->name); + $workflow_active = false; + $workflow_required = false; + if (SITE_WORKFLOW) { + $workflow = &NController::factory('workflow'); + if ($workflow_group_model = $workflow->getWorkflowGroup($page_model)) { + $workflow_required = true; + } + if ($workflow_required && isset($values['__submit_workflow__'])) { + $workflow_active = true; + } + } + $model->page_id = $parameter; + $model->page_template_container_id = $values['template_container_id']; + $model->content_asset = $values['asset']; + $model->content_asset_id = $asset_id; + // prep the timed content values if they exist + if (isset($values['timed_start'])) { + $values['timed_start'] = NDate::arrayToDate($values['timed_start']); + $values['timed_start'] = NDate::convertTimeToUTC($values['timed_start']); + } + if (isset($values['timed_end'])) { + $values['timed_end'] = NDate::arrayToDate($values['timed_end']); + $values['timed_end'] = NDate::convertTimeToUTC($values['timed_end']); + } + // + if (!$workflow_active) { + if (isset($values['timed_start'])) $model->timed_start = $values['timed_start']; + if (isset($values['timed_end'])) $model->timed_end = $values['timed_end']; + } + if ($workflow_required) { + $model->cms_workflow = 1; + } + $model->cms_created = $model->now(); + $model->cms_modified = $model->now(); + $model->cms_modified_by_user = $this->_auth->currentUserID(); + if ($workflow_active) { + // set page_content cms_workflow to 1 so it can't show up + $model->cms_workflow = 1; + } + $model->insert(); + // do the workflow stuff if appropriate + if ($workflow_active) { + $page_content_id = $model->{$model->primaryKey()}; + $workflow_values = array(); + $workflow_values['page_content_id'] = $page_content_id; + $workflow_values['workflow_group_id'] = $workflow_group_model->{$workflow_group_model->primaryKey()}; + // add timed content + if (isset($values['timed_start'])) $workflow_values['timed_start'] = $values['timed_start']; + if (isset($values['timed_end'])) $workflow_values['timed_end'] = $values['timed_end']; + $workflow->saveWorkflow($workflow_values, WORKFLOW_ACTION_ADDNEW, $asset_controller); + // set page_content cms_workflow to 1 so it can't show up + } + // delete the page cache + $page = &NController::singleton('page'); + $page->deletePageCache($model->page_id); + if (defined('SITE_AUDIT_TRAIL') && SITE_AUDIT_TRAIL) { + // audit trail + $audit_trail = &NController::factory('audit_trail'); + $audit_trail->insert(array('asset'=>$asset_controller->name, 'asset_id'=>$asset_model->{$asset_model->primaryKey()}, 'action_taken'=>AUDIT_ACTION_CONTENT_ADDNEW, 'page_content_id'=>$model->{$model->primaryKey()}, 'page_id'=>$model->page_id)); + unset($audit_trail); + } + unset($page); + unset($model); + } + if (isset($this->params['_referer']) && $this->params['_referer']) { + $referer = urldecode($this->params['_referer']); + } else { + include_once 'view/helpers/url_helper.php'; + $referer = urlHelper::urlFor($this, array('controller'=>'page', 'action'=>'surftoedit', 'id'=>$parameter)); + } + header('Location:' . $referer); + exit; + } else { + if ($asset_model) { + $this->set(array('form'=>$form->toHTML(), 'asset'=>$asset_controller->name, 'asset_name'=>Inflector::humanize($asset_controller->name))); + } + } + $this->auto_render = false; + $this->page_title = 'Add New Content to "' . $page_model->title . '"'; + $this->render(array('action'=>'form', 'layout'=>'default')); + } + + function addExistingContent($parameter) { + $page_model = &$this->loadModel('page'); + $page_model->get($parameter); + $template_container_id = isset($this->params['template_container_id'])?$this->params['template_container_id']:false; + $asset = isset($this->params['asset'])?$this->params['asset']:false; + // instantiate form + include_once 'n_quickform.php'; + $form = new NQuickForm(); + $values = $form->getSubmitValues(); + $form->addElement('header', null, 'Add "' . Inflector::humanize($asset) . '" content to the "' . $page_model->title . '" page'); + $asset_controller = &NController::factory($asset); + $asset_model = &NModel::factory($asset); + $pk = $asset_model->primaryKey(); + $records = array(); + if ($asset_model->find()) { + while ($asset_model->fetch()) { + $records[$asset_model->$pk] = $asset_model->cms_headline; + } + } + unset($asset_model); + // add asset select + $options = defined('SITE_WORKFLOW') && SITE_WORKFLOW?array():array('size'=>10, 'multiple'=>'multiple'); + $form->addElement('select', 'asset_id', Inflector::humanize($asset), $records, $options); + // hidden fields + $form->addElement('hidden', 'asset', $asset); + $form->addElement('hidden', 'template_container_id', $template_container_id); + if (isset($this->params['_referer'])) { + $form->addElement('hidden', '_referer', urlencode($this->params['_referer'])); + } + // finish up + $form->addElement('submit', '__submit__', 'Add Content'); + // rules + defined('SITE_WORKFLOW') && SITE_WORKFLOW?$form->addRule('asset_id', 'You must select a record.', 'required'):$form->addGroupRule('asset_id', 'You must select a record.', 'required'); + $form->addRule('asset', '', 'required'); + $form->addRule('template_container_id', '', 'required'); + // check for workflow + $user_rights = 0; + if (SITE_WORKFLOW) { + // get the users rights and bit compare them below + $workflow = &NController::factory('workflow'); + $user_rights = $workflow->getWorkflowUserRights($page_model); + if ($workflow_group_model = &$workflow->getWorkflowGroup($page_model)) { + if (!($user_rights & WORKFLOW_RIGHT_EDIT)) { + // they don't belong here - go to the dashboard + header('Location:/' . APP_DIR . '/dashboard'); + } else if ($user_rights & WORKFLOW_RIGHT_EDIT) { + $form->insertElementBefore(NQuickForm::createElement('submit', '__submit_workflow__', 'Start Workflow'), '__submit__'); + $form->removeElement('__submit__'); + } + } + unset($workflow); + } + $form->addElement('header', null, 'Make it timed content?'); + $timed_options = array('format'=>'Y-m-d H:i', 'minYear'=>date('Y'), 'maxYear'=>date('Y')+4, 'addEmptyOption'=>true); + $form->addElement('date', 'timed_start', 'Timed Start', $timed_options); + $form->addElement('date', 'timed_end', 'Timed End', $timed_options); + if (!$user_rights) { + $form->addElement('submit', '__submit_timed__', 'Add Scheduled Content'); + } else { + $form->addElement('submit', '__submit_workflow__', 'Start Workflow with Scheduled Content'); + } + if ($form->validate()) { + $values = $form->exportValues(); + $model = &$this->loadModel($this->name); + $workflow_active = false; + if (SITE_WORKFLOW) { + $workflow = &NController::factory('workflow'); + // check if this content is on any other page. + // if it is, if either pages are part of a workflow group, we need to copy the content (go to addnewcontent with notice) + // if neither do, then go ahead + $asset_model = &$asset_controller->loadModel($asset_controller->name); + $asset_model->get($values['asset_id']); + $other_page = &$this->getContentPage($asset_controller); + if ($other_page) { + $owned_content = false; + if ($workflow_group_model = &$workflow->getWorkflowGroup($page_model)) { + $owned_content = true; + } else { + if ($workflow_group_model = &$workflow->getWorkflowGroup($other_page)) { + $owned_content = true; + } + } + // if the content is already connected somewhere and one of the pages belongs to a workflow_group, then addNewContent with preloaded content + if ($owned_content) { + if (isset($values['__submit__'])) unset($values['__submit__']); + if (isset($values['__submit_workflow__'])) unset($values['__submit_workflow__']); + $this->redirectTo('copy_existing_content', $parameter, $values); + exit; + } + } + if (isset($values['__submit_workflow__']) && $values['__submit_workflow__']) { + $workflow = &NController::factory('workflow'); + if ($workflow_group_model = $workflow->getWorkflowGroup($page_model)) { + $workflow_active = true; + } + } + } + $model->page_id = $parameter; + if (SITE_WORKFLOW && isset($values['__submit_workflow__']) && $values['__submit_workflow__']) { + $model->cms_workflow = 1; + } + $model->page_template_container_id = $values['template_container_id']; + $model->content_asset = $values['asset']; + // set the timed values + $timed_start = null; + $timed_end = null; + include_once 'n_date.php'; + if (isset($values['timed_start'])) { + $timed_start = NDate::arrayToDate($values['timed_start']); + $timed_start = NDate::convertTimeToUTC($timed_start); + unset($values['timed_start']); + } + if (isset($values['timed_end'])) { + $timed_end = NDate::arrayToDate($values['timed_end']); + $timed_end = NDate::convertTimeToUTC($timed_end); + unset($values['timed_end']); + } + if (!$workflow_active) { + $table = $model->table(); + $def = $table['timed_start']; + if (NDate::validDateTime($timed_start, $def)) { + $model->timed_start = $timed_start; + } else { + $model->timed_start = N_DAO_NOTNULL & $def?$timed_start:'null'; + } + $def = $table['timed_end']; + if (NDate::validDateTime($timed_end, $def)) { + $model->timed_end = $timed_end; + } else { + $model->timed_end = N_DAO_NOTNULL & $def?$timed_end:'null'; + } + } + $model->cms_created = $model->now(); + $model->cms_modified = $model->now(); + $model->cms_modified_by_user = $this->_auth->currentUserID(); + if (!is_array($values['asset_id'])) { + $values['asset_id'] = array($values['asset_id']); + } + foreach ($values['asset_id'] as $asset_id) { + $model->content_asset_id = $asset_id; + $model->insert(); + if (defined('SITE_AUDIT_TRAIL') && SITE_AUDIT_TRAIL) { + // audit trail + $audit_trail = &NController::factory('audit_trail'); + $audit_trail->insert(array('asset'=>$asset_controller->name, 'asset_id'=>$asset_id, 'action_taken'=>AUDIT_ACTION_CONTENT_ADDEXISTING, 'page_content_id'=>$model->{$model->primaryKey()}, 'page_id'=>$model->page_id)); + unset($audit_trail); + } + } + if ($workflow_active) { + $asset_controller = &NController::factory($values['asset']); + $asset_controller->_auth = new NAuth(); + $asset_model = &$asset_controller->getDefaultModel(); + $asset_model->get($values['asset_id'][0]); + $workflow_values = array(); + $workflow_values['page_content_id'] = $model->{$model->primaryKey()}; + $workflow_values['workflow_group_id'] = $workflow_group_model->{$workflow_group_model->primaryKey()}; + // add timed content + $workflow_values['timed_start'] = $timed_start; + $workflow_values['timed_end'] = $timed_end; + $workflow->saveWorkflow($workflow_values, WORKFLOW_ACTION_ADDEXISTING, $asset_controller); + } + // delete the page cache + $page = &NController::singleton('page'); + $page->deletePageCache($model->page_id); + unset($page); + // set up the referer + if (isset($this->params['_referer']) && $this->params['_referer']) { + $referer = urldecode($this->params['_referer']); + } else { + include_once 'view/helpers/url_helper.php'; + $referer = urlHelper::urlFor($this, array('controller'=>'page', 'action'=>'surftoedit', 'id'=>$parameter)); + } + header('Location:' . $referer); + exit; + } + $this->auto_render = false; + $this->page_title = 'Add Existing Content to "' . $page_model->title . '"'; + $this->set(array('title'=>'Select Content', 'form'=>$form->toHTML())); + $this->render(array('action'=>'form', 'layout'=>'plain')); + unset($page_model); + } + + function copyExistingContent($parameter) { + $params = $this->params; + if (!isset($params['asset']) || !isset($params['asset_id']) || !isset($params['template_container_id'])) { + header('Location:/' . APP_DIR . '/'); + } + $asset_controller = &NController::singleton($params['asset']); + $asset_model = &$asset_controller->getDefaultModel(); + $asset_model->get($params['asset_id']); + $asset_model->{$asset_model->primaryKey()} = null; + $asset_model->cms_headline = null; + $this->flash->set('notice', 'The content you chose already belongs to another Workflow Group.
We have made a copy of the content for you.
Please enter a new headline to connect the content to your page.'); + $this->flash->now('notice'); + $this->addNewContent($parameter, true); + } + + function removeContent($parameter, $redirect=true, $timed_remove=false) { + $model = &$this->getDefaultModel(); + $referer = (isset($this->params['_referer']) && $this->params['_referer'])?$this->params['_referer']:false; + if ($model->get($parameter)) { + // check for workflow + // if it's a timed remove, the timed portion went through workflow, so it's okay + if (SITE_WORKFLOW && $timed_remove == false) { + // get the users rights and bit compare them below + $workflow = &NController::factory('workflow'); + $page_model = &$model->getLink('page_id', 'page'); + $user_rights = $workflow->getWorkflowUserRights($page_model); + if ($workflow_group_model = &$workflow->getWorkflowGroup($page_model)) { + if (!($user_rights & WORKFLOW_RIGHT_EDIT)) { + // they don't belong here - go to the dashboard + header('Location:/' . APP_DIR . '/dashboard'); + exit; + } + $asset_controller = &NController::factory($model->content_asset); + $asset_controller->_auth = new NAuth(); + $asset_model = &$asset_controller->getDefaultModel(); + $asset_model->get($model->content_asset_id); + // workflow values for saveWorkflow + $workflow_values = array(); + $workflow_values['page_content_id'] = $model->{$model->primaryKey()}; + $workflow_values['workflow_group_id'] = $workflow_group_model->{$workflow_group_model->primaryKey()}; + // save the workflow + $workflow->saveWorkflow($workflow_values, WORKFLOW_ACTION_REMOVE, $asset_controller); + if ($redirect) { + include_once 'view/helpers/url_helper.php'; + $referer = isset($this->params['referer'])?urldecode($this->params['referer']):urlHelper::urlFor($this, array('controller'=>'page', 'action'=>'surftoedit', 'id'=>$page_model->{$page_model->primaryKey()})); + header('Location:' . $referer); + exit; + } + } + unset($workflow); + } + include_once 'view/helpers/url_helper.php'; + $page_id = $model->page_id; + if (!$referer) { + $referer = urlHelper::urlFor($this, array('controller'=>'page', 'action'=>'surftoedit', 'id'=>$page_id)); + } + // delete the page cache + $page = &NController::singleton('page'); + $page->deletePageCache($model->page_id); + unset($page); + $audit_trail_array = array('asset'=>$model->content_asset, 'asset_id'=>$model->content_asset_id, 'action_taken'=>AUDIT_ACTION_CONTENT_REMOVE, 'page_content_id'=>$model->{$model->primaryKey()}, 'page_id'=>$model->page_id); + if (defined('SITE_AUDIT_TRAIL') && SITE_AUDIT_TRAIL) { + // audit trail just before the delete or we lose the info + if ($timed_remove == false) { + $audit_trail = &NController::factory('audit_trail'); + $audit_trail->insert($audit_trail_array); + // Bit of an ugly hack, but I didn't want to mess with the controller. + // The model doesn't require authentication, so we can force it through when + // we're removing timed_content auto-magically. + } elseif ($timed_remove == true) { + $audit_trail = &NModel::factory('cms_audit_trail'); + $audit_trail->insert_audit_trail($audit_trail_array); + } + unset($audit_trail); + } + unset($audit_trail_array); + // delete the page_content record + $deleted = $model->delete(); + // if delete was successful and there is an unsubmitted workflow, then cascade delete the workflow + if ($timed_remove == false && $deleted && SITE_WORKFLOW && $workflow_model = &$this->loadModel('workflow')) { + $workflow_model->page_id = $page_id; + $workflow_model->asset = $model->content_asset; + $workflow_model->asset_id = $model->content_asset_id; + $workflow_model->submitted = 0; + $workflow_model->parent_workflow = 0; + $workflow_model->cms_modified_by_user = $this->_auth->currentUserID(); + if ($workflow_model->find()) { + while ($workflow_model->fetch()) { + $workflow_model->delete(); + } + } + unset($workflow_model); + } + unset($model); + } + if ($redirect) { + header('Location:' . $referer); + exit; + } + } + + + function show($parameter, $layout=true) { + $this->auto_render = false; + $this->base_dir = APP_DIR; + $model = &$this->getDefaultModel(); + if ($model && $model->get($parameter)) { + $this->convertDateTimesToClient($model); + $page_controller = &NController::singleton('page'); + + if ($this->checkUserLevel()) { + $page_controller->edit = true; + $page_controller->page_edit_allowed = true; + $page_controller->content_edit_allowed = true; + } + + $html = $page_controller->getContainerContent($model->page_id, $model->page_template_container_id, $model->id); + } else { + $html = 'The specified record could not be found.'; + } + print trim($html); + } + + + function reorder() { + $id = isset($this->params['id'])?(int) $this->params['id']:false; + if (!$id) { + return; + } + $before = isset($this->params['before'])?(int) $this->params['before']:false; + if ($model = &$this->getDefaultModel() && $model->get($id)) { + $pk = $model->primaryKey(); + $page_content_model = &NModel::factory($this->name); + $page_content_model->page_id = $model->page_id; + $page_contents = array(); + if ($page_content_model->find()) { + $before_found = false; + $item = null; + while ($page_content_model->fetch()) { + if ($page_content_model->$pk == $id) { + // pull the "id" record out of the array + $item = clone($page_content_model); + } else { + $page_contents[] = clone($page_content_model); + } + } + if (!$before) { // if there is no before, then the item goes last + $page_contents[] = $item; + } else { // loop through until you find "before" and then splice the "id" in front of it + foreach ($page_contents as $key=>$page_content) { + if ($page_content->$pk == $before) { + array_splice($page_contents, $key, 1, array($item, $page_content)); + break; + } + } + } + $i = 0; + foreach ($page_contents as $key=>$page_content) { + $page_content->content_order = $i; + $page_content->save(false,false); // second false prevents converting time to UTC (unnecessary for a reorder) + $i++; + } + } + $page = &NController::singleton('page'); + $page->deletePageCache($model->page_id); + unset($page); + unset($page_contents); + unset($page_content_model); + unset($model); + } + } + + function &getContentPage(&$asset_controller) { + if (!$asset_controller) return false; + $asset_model = &$asset_controller->loadModel($asset_controller->name); + if (!$asset_model) return false; + $pk = $asset_model->primaryKey(); + $model = &NModel::factory($this->name); + $model->content_asset = $asset_controller->name; + $model->content_asset_id = $asset_model->$pk; + if ($model->find(null, true)) { + $page_model = &$model->getLink('page_id', 'page'); + unset($model); + return $page_model; + } + unset($model); + $model = false; + return $model; + } + + function changeTemplate($page_id, $to_template_id) { + $page_id = (int)$page_id; + $to_template_id = (int)$to_template_id; + if (!$page_id || !$to_template_id) { + // TODO: add a log error + return false; + } + + // load the container_vars + $tc_model = &NModel::singleton('page_template_containers'); + $tc_pk = $tc_model->primaryKey(); + $tc_model->reset(); + $tc_model->page_template_id = $to_template_id; + $containers = array(); + if ($tc_model->find()) { + while ($tc_model->fetch()) { + $containers[$tc_model->$tc_pk] = $tc_model->container_var; + } + } + + // grab records attached to the old template + $model = &$this->getDefaultModel(); + $model->reset(); + $model->page_id = $page_id; + $conditions = ''; + foreach ($containers as $container_id=>$container_var) { + $conditions .= ($conditions?' AND ':'') . 'page_template_container_id != ' . $container_id; + } + $old_contents = $model->find(array('conditions'=>$conditions))?$model->fetchAll():array(); + if (empty($old_contents)) return true; + + // loop through the old content. If the new template has the same + // container_var and isn't already connected to that template_container, + // then update the record + foreach ($old_contents as $content) { + // grab the old template_container for the content + $tc_model->reset(); + if ($tc_model->get($content->page_template_container_id)) { + if ($new_container_id = array_search($tc_model->container_var, $containers)) { + // check if the same content is already connected to the new template_container + $model->reset(); + $model->page_id = $page_id; + $model->content_asset = $content->content_asset; + $model->content_asset_id = $content->content_asset_id; + $model->page_template_container_id = $new_container_id; + if ($model->find()) { + continue; + } + // if not, update the content to the new container_id + $content->page_template_container_id = $new_container_id; + $content->update(); + } + } + } + return true; + } + + /* + / Grab all of the content_asset_ids for a particular asset_name on a + / particular page in a particular container. + / Used to create RSS feeds from a blog page, also to show last + / few records connected to a page on another. + */ + function getAssetContainerPageItems ($page_template_container_id, $page_id, $asset_name) { + $model = &NModel::factory('page_content'); + $model->page_id = $page_id; + $model->content_asset = $asset_name; + $model->page_template_container_id = $page_template_container_id; + if ($model->find()) { + $records = &$model->fetchAll(true); + $records = $this->_removeTimedContent($records); + unset($model); + $model = &NModel::factory($asset_name); + foreach ($records as $record) { + $model->reset(); + if ($model->get($record['content_asset_id'])) { + $assets[] = $model->toArray(); + } + } + } + return $assets; + } + + // Used with getAssetContainerPageItems to remove any timed content from the + // $assets array. + function _removeTimedContent ($records) { + $cleaned_records = array(); + $time = date("Y-m-d G:i:s", time()); + $time = NDate::convertTimeToUTC($time); + foreach ($records as $record) { + // If they're both null - just add the record and skip the rest. + if(is_null($record['timed_start']) && is_null($record['timed_end']) || ($record['timed_start'] == '0000-00-00 00:00:00')) { + $cleaned_records[] = $record; + continue; + } + if (!is_null($record['timed_start']) && ($record['timed_start'] > $time)) continue; + if (!is_null($record['timed_end']) && ($record['timed_end'] < $time)) continue; + $cleaned_records[] = $record; + } + return $cleaned_records; + } + + // See if an asset is being used in a particular container. + // Return an int. + function checkAssetContainerUsage($asset, $container_id) { + $count = 0; + $model = &NModel::factory($this->name); + $model->content_asset = $asset; + $model->page_template_container_id = $container_id; + if ($model->find()) { + while ($model->fetch()) { + $count++; + } + } + unset ($model); + return $count; + } +} +?> diff --git a/app/controllers/page_controller.php b/app/controllers/page_controller.php new file mode 100755 index 0000000..a94c35f --- /dev/null +++ b/app/controllers/page_controller.php @@ -0,0 +1,1384 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class PageController extends SiteAdminController { + // ONLY IN THIS CONTROLLER + var $nterchange = false; + var $edit = false; + + // permissions settings + var $page_edit_allowed = false; + var $content_edit_allowed = false; + + var $page_last_modified = 0; + var $view_cache_lifetimes = array(); + + // special settings for page + var $public_actions = array('index', 'menus'); + + function __construct() { + $this->name = 'page'; + // more logins for this controller + $this->login_required[] = 'surftoedit'; + $this->login_required[] = 'preview'; + $this->login_required[] = 'site_admin'; + $this->login_required[] = 'content'; + $this->login_required[] = 'children'; + $this->login_required[] = 'reorder_content'; + // set user level allowed to access the actions with required login + $this->user_level_required = N_USER_ADMIN; + parent::__construct(); + } + + function index($parameter) { + $this->page($parameter); + } + + function create($parameter) { + $this->nterchange = true; + parent::create($parameter); + } + + function edit($parameter) { + if (!$this->checkUserLevel()) { + $this->redirectTo(array('site_admin')); + } + $this->nterchange = true; + $this->loadSubnav($parameter); + $model = &$this->getDefaultModel(); + $model->get($parameter); + $this->page_title = 'Page - ' . $model->title; + $this->set('page_title', $model->title); + $this->loadSidebar(); + $model->reset(); + parent::edit($parameter); + } + + /** + * delete - Very bad things can happen if certain pages are deleted, + * here we check the id and throw a nasty error if that happens. + */ + function delete($parameter) { + $protected_pages = NConfig::$protectedPages; + + if (in_array($parameter, $protected_pages)) { + $this->flash->set('notice', 'This content is protected and cannot be deleted.'); + $this->redirectTo(array('page', "edit/$parameter")); + } else { + parent::delete($parameter); + } + } + + function content($parameter) { + if (!$this->checkUserLevel()) { + $this->redirectTo(array('site_admin')); + } + $this->nterchange = true; + $this->auto_render = false; + $this->page_title = 'Page Content'; + $this->loadSubnav($parameter); + $model = &$this->loadModel($this->name); + $page_content = &NController::factory('page_content'); + $page_content_model = &$page_content->loadModel('page_content'); + $pk = $page_content_model->primaryKey(); + $page_content->set('page_id', $parameter); + $content_html = ''; + if ($model->get($parameter)) { + $this->page_title .= ' - ' . $model->title; + $content = array(); + $template_containers = $this->templateContainers($model->page_template_id); + if (!is_array($template_containers)) return null; + foreach ($template_containers as $container) { + if (empty($container)) continue; + $page_content_model->reset(); + $page_content_model->getContainerContent($model->{$model->primaryKey()}, $container['id'], $this->nterchange); + $this->set(array('container'=>$container)); + $content_html .= $this->render(array('action'=>'content_container_title', 'return'=>true)); + $page_content->set('template_container_id', $container['id']); + $page_content->set('no_reorder', true); + $content_html .= $page_content->render(array('action'=>'asset_add', 'return'=>true)); + if ($page_content_model->numRows()) { + $contents = array(); + while ($page_content_model->fetch()) { + $asset_ctrl = &NController::factory($page_content_model->content_asset); + if ($asset_ctrl && $asset_model = &$asset_ctrl->loadModel($asset_ctrl->name) && $asset_model->get($page_content_model->content_asset_id)) { + $content = $asset_model->toArray(); + $content['_asset'] = $asset_ctrl->name; + $content['_asset_name'] = Inflector::humanize($asset_ctrl->name); + $content['page_content_id'] = $page_content_model->$pk; + $contents[] = $content; + } + unset($asset_ctrl); + } + if (empty($contents)) continue; + $this->set('template_container_id', $container['id']); + $this->set('contents', $contents); + $this->set(array('reorder_link'=>count($contents) > 1?true:false)); + $content_html .= $this->render(array('action'=>'content_container', 'return'=>true)); + } + } + $this->set('page_title', $model->title); + $this->loadSidebar(); + } + $this->set('MAIN_CONTENT', $content_html); + $this->render(array('layout'=>'default')); + } + + function children($parameter) { + if (!$this->checkUserLevel()) { + $this->redirectTo(array('site_admin')); + } + $this->nterchange = true; + $this->auto_render = false; + // set view caching to false + $this->view_caching = false; + $this->loadSubnav($parameter); + $model = &$this->getDefaultModel(); + if ($model->get($parameter)) { + $this->page_title = 'Page Children - ' . $model->title; + $children = $model->getChildren($parameter, false, false); + $this->set('page_title', $model->title); + $this->set('parent_id', $parameter); + $this->set('pages', $children); + $this->loadSidebar(); + } + $this->render(array('layout'=>'default', 'action'=>'children_container')); + } + + function loadSidebar() { + $model = &$this->getDefaultModel(); + $surfedit = false; + switch ($this->_auth->getAuthData('user_level')) { + case N_USER_EDITOR: + $surfedit = true; + break; + case N_USER_ADMIN: + case N_USER_ROOT: + $surfedit = true; + break; + } + if (SITE_WORKFLOW) { + $assigns['workflow'] = ''; + $workflow = &NController::singleton('workflow'); + if ($workflow_group_model = &$workflow->getWorkflowGroup($model)) { + $user_rights = $workflow->getWorkflowUserRights($model); + if ($user_rights & WORKFLOW_RIGHT_EDIT) { + $surfedit = true; + } + } + } + $this->set('surfedit', $surfedit); + $this->set('page_id', $model->{$model->primaryKey()}?$model->{$model->primaryKey()}:null); + $this->set('action', $this->action); + $this->set(array('children'=>$this->getChildren(), 'breadcrumbs'=>$this->getBreadcrumbs(false))); + $this->set('SIDEBAR_CONTENT', $this->render(array('action'=>'sidebar', 'return'=>true))); + } + + function reorder($parameter) { + NDebug::debug('Reordering children of page id ' . $parameter, N_DEBUGTYPE_INFO); + if (!$this->checkUserLevel()) { + $this->redirectTo(array('site_admin')); + } + $id = isset($this->params['id'])?(int) $this->params['id']:false; + if (!$id) { + return; + } + $before = isset($this->params['before'])?(int) $this->params['before']:false; + if ($model = &$this->getDefaultModel() && $model->get($id)) { + $pk = $model->primaryKey(); + $page_model = &NModel::factory($this->name); + $page_model->parent_id = $parameter; + $pages = array(); + if ($page_model->find()) { + $before_found = false; + $item = null; + while ($page_model->fetch()) { + if ($page_model->$pk == $id) { + // pull the "id" record out of the array + $item = clone($page_model); + } else { + $pages[] = clone($page_model); + } + } + if (!$before) { // if there is no before, then the item goes last + $pages[] = $item; + } else { // loop through until you find "before" and then splice the "id" in front of it + foreach ($pages as $key=>$page) { + if ($page->$pk == $before) { + array_splice($pages, $key, 1, array($item, $page)); + break; + } + } + } + $i = 0; + foreach ($pages as $key=>$page) { + $page->sort_order = $i; + $page->save(); + $i++; + } + } + $site_admin = &NController::singleton('site_admin'); + if ($model->getParent($id) == $model->getRootNode()) { + // we need to clear all caches + @ob_start(); + $site_admin->clearAllCache(); + @ob_end_clean(); + } else { + $site_admin->deleteCache(); + include_once 'n_cache.php'; + NCache::removeJavascript(); + } + unset($site_admin); + unset($pages); + unset($page_model); + unset($model); + } + } + + function checkUserLevel() { + switch ($this->action) { + case 'surftoedit': + case 'preview': + $this->user_level_required = N_USER_NORIGHTS; + break; + case 'content': + $this->user_level_required = N_USER_EDITOR; + break; + default: + $this->user_level_required = N_USER_ADMIN; + } + return parent::checkUserLevel(); + } + + function viewlist() { + if ($this->flash->exists('notice')) { + $this->flash->keep('notice'); + } + $this->redirectTo(array('site_admin')); + } + + function page($parameter) { + if (!defined('IN_SURFTOEDIT')) define('IN_SURFTOEDIT', $this->nterchange && $this->edit); + $this->base_view_dir = ROOT_DIR; + if (!$parameter) { + $this->do404(); + return; + } + $this->auto_render = false; + // load the model + $model = &$this->getDefaultModel(); + $pk = $model->primaryKey(); + if (!$model->get($parameter)) { // get the page info + // if the page doesn't exist, then 404 + $this->do404(); + return; + } + + if (!$this->nterchange && $model->external_url && preg_match('/^(http[s]?)|(\/)/', $model->external_url)) { + header('Location:' . $model->external_url); + return; + } + + // check if a disclaimer is required + if (defined('SITE_DISCLAIMER') && constant('SITE_DISCLAIMER') && !$this->nterchange && $disclaimer = &NController::factory('disclaimer')) { + $disclaimer->checkDisclaimer($parameter); + } + + // find the action + $action = $this->getTemplate($model->page_template_id); + $action = $action?$action:'default'; + // set up caching + if (!$this->nterchange && defined('PAGE_CACHING') && PAGE_CACHING == true && $model->cache_lifetime != 0) { + // set the view cache values + $this->view_cache_name = 'page' . $parameter . (NServer::env('QUERY_STRING')?':' . md5(NServer::env('QUERY_STRING')):''); + $this->view_caching = true; + $this->view_cache_lifetime = $model->cache_lifetime; + $this->view_cache_lifetimes[] = $model->cache_lifetime; + $this->view_client_cache_lifetime = isset($model->client_cache_lifetime)?$model->client_cache_lifetime:'3600'; + header('Expires:' . gmdate('D, d M Y H:i:s \G\M\T', time() + $this->view_client_cache_lifetime)); + header('Cache-Control:max-age='.$this->view_client_cache_lifetime.', must-revalidate'); + } else { + header('Cache-Control:max-age=0, must-revalidate'); + } + // set the page fields + $this->set($model->toArray()); + // load the page, checking if it's cached if we're not in nterchange + if ($this->nterchange || $this->getParam('mode') == 'print' || !$this->isCached(array('action'=>$action))) { + if (defined('PAGE_CACHING') && PAGE_CACHING == false) { + $this->debug('Cache not created for page for Page ID ' . $model->$pk . ' because PAGE_CACHING is set to false.', N_DEBUGTYPE_CACHE); + } else if ($model->cache_lifetime == 0) { + $this->debug('Cache not created for page for Page ID ' . $model->$pk . ' because caching is turned off for that page.', N_DEBUGTYPE_CACHE); + } else { + if (!$this->nterchange) $this->debug('Created cached page for Page ID ' . $model->$pk . '.', N_DEBUGTYPE_CACHE); + } + $this->page_last_modified = strtotime($model->cms_modified); + + // load up the manual content (site name, breadcrumbs, children, nav, etc.) + $contents['_SITE_NAME_'] = htmlentities(SITE_NAME); + $contents['_EXTERNAL_CACHE_'] = defined('EXTERNAL_CACHE') && constant('EXTERNAL_CACHE')?EXTERNAL_CACHE:false; + $contents['_PAGE_EDIT_'] = ''; + if ($this->checkUserLevel()) { + $this->page_edit_allowed = true; + $this->content_edit_allowed = true; + } + if ($this->nterchange && $this->edit && SITE_WORKFLOW) { + // set up the user's rights on the page + $workflow = &NController::factory('workflow'); + if ($workflow_group_model = &$workflow->getWorkflowGroup($model) && $users = $workflow->getWorkflowUsers($workflow_group_model->{$workflow_group_model->primaryKey()})) { + $contents['_PAGE_EDIT_'] = '
This page is owned by the "' . $workflow_group_model->workflow_title . '" Workflow Group
' . "\n"; + $current_user = $this->_auth->currentUserID(); + $edit = false; + foreach ($users as $user) { + if ($current_user == $user->user_id) { + $edit = true; + } + } + $this->content_edit_allowed = $edit; + $assigns['workflow'] = $workflow_group_model->workflow_title; + $user_rights = $workflow->getWorkflowUserRights($model); + $this->content_edit_allowed = $user_rights & WORKFLOW_RIGHT_EDIT?true:false; + } else { + switch ($this->_auth->getAuthData('user_level')) { + case N_USER_NORIGHTS: + $this->page_edit_allowed = false; + $this->content_edit_allowed = false; + break; + case N_USER_EDITOR: + $this->page_edit_allowed = false; + $this->content_edit_allowed = true; + break; + } + } + unset($workflow); + } + if ($this->edit && $this->page_edit_allowed) { + // $contents['_PAGE_EDIT_'] .= '
Edit Page
' . "\n\n"; + $contents['_PAGE_EDIT_'] .= $this->render(array('action'=>'surftoedit', 'return'=>true)); + } + $contents['HOME_LINK'] = $this->getHref($model->getInfo($model->getRootNode())); + $contents['HOME_CHILDREN'] = $this->getHomeChildren(); + $contents['BREADCRUMBS'] = $this->getBreadcrumbs(); + $contents['CHILDREN'] = $this->getChildren(); + // get ancestor + $ancestor = $this->getAncestor(); + if ($ancestor && count($ancestor)) { + $contents['ancestor'] = $ancestor['filename']; + $contents['ancestor_id'] = $ancestor[$pk]; + } + + if ($this->nterchange) { + $contents['header'] = ''; + $contents['header'] .= "\n \n "; + $contents['header'] .= ''; + $contents['header'] .= "\n "; + $contents['header'] .= ''; + } + if ($this->nterchange) { + $contents['admin_dir'] = 1; + } + if ($this->nterchange && $this->edit) { + $contents['page_edit'] = 1; + } + // set the variables so far + $this->set($contents); + // load the content into those vars using custom views + $this->set($this->getContent()); + // last-modified + $this->set('last_modified', $this->page_last_modified); + } + if (!$this->nterchange && defined('PAGE_CACHING') && PAGE_CACHING == true && $model->cache_lifetime != 0) { + $this->view_caching = true; + } + if (!$this->nterchange && defined('PAGE_CACHING') && PAGE_CACHING == true) { + foreach ($this->view_cache_lifetimes as $cache_lifetime) { + if ($this->view_cache_lifetime == -1 || $this->view_cache_lifetime > $cache_lifetime) { + $this->view_cache_lifetime = $cache_lifetime; + } + } + } + if (SITE_PRINTABLE && isset($model->printable) && $model->printable && $this->getParam('mode') == 'print') { + $this->view_caching = false; + $this->render(array('action'=>'print')); + } else { + $this->render(array('action'=>$action)); + } + } + + function loadSubnav($parameter) { + $subnav = array(); + $subnav[] = array('title'=>'Edit Page', 'action'=>'edit', 'id'=>$parameter, 'class'=>''); + $subnav[] = array('title'=>'Content', 'action'=>'content', 'id'=>$parameter, 'class'=>''); + $subnav[] = array('title'=>'Children', 'action'=>'children', 'id'=>$parameter, 'class'=>''); + foreach ($subnav as $k=>$nav) { + if ($nav['action'] == $this->action) { + $subnav[$k]['class'] = 'current'; + } + } + $this->set('subnav', $subnav); + } + + function surfToEdit($parameter) { + $this->edit = true; + $this->nterchange = true; + $this->page($parameter); + } + + function preview($parameter) { + $this->edit = false; + $this->nterchange = true; + $this->page($parameter); + } + + function do404() { + if ($redirect = &NController::factory('redirect')) { + $redirect->checkRedirect(); + } + $model = &$this->getDefaultModel(); + $model->reset(); + header("HTTP/1.1 404 Not Found"); + $this->page(4); + } + + function getHomeChildren($parent_id = null) { + $model = &$this->getDefaultModel(); + $pk = $model->primaryKey(); + $page_info = $model->getInfo($model->$pk); + $parent_id = $parent_id?$parent_id:$model->getRootNode(); + $children = $model->getChildren($parent_id, true, true); + foreach ($children as $key=>$child) { + $children[$key]['href'] = $this->getHref($child); + } + return $children; + } + + function getBreadcrumbs($no_home=true) { + $model = &$this->getDefaultModel(); + $pk = $model->primaryKey(); + $breadcrumbs = array_reverse($model->getAncestors($model->$pk, false, false)); + if ($no_home) { + array_shift($breadcrumbs); // shift home out of the array + } + foreach ($breadcrumbs as $key=>$breadcrumb) { + $breadcrumbs[$key]['href'] = $this->getHref($breadcrumb); + } + return $breadcrumbs; + } + + function getChildren() { + $model = &$this->getDefaultModel(); + $pk = $model->primaryKey(); + $page_info = $model->getInfo($model->$pk); + if ($children = $model->getChildren($model->$pk, !$this->nterchange, !$this->nterchange)) { + foreach ($children as $key=>$child) { + $children[$key]['href'] = $this->getHref($child); + } + } + return $children; + } + + function getAncestor() { + $model = &$this->getDefaultModel(); + $pk = $model->primaryKey(); + $ancestors = $model->getAncestors($model->$pk, false, false); + // pop off the home page + array_pop($ancestors); + $ancestor = count($ancestors)?array_pop($ancestors):$model->toArray(); + return $ancestor; + } + + function getAncestors(){ + $model = &$this->getDefaultModel(); + $pk = $model->primaryKey(); + $ancestors = $model->getAncestors($model->$pk, false, false); + return $ancestors; + } + + function reorderContent($parameter) { + $this->auto_render = false; + $template_container_id = isset($this->params['template_container_id'])?(int) $this->params['template_container_id']:false; + if (!$template_container_id) return; + $this->page_title = 'Reorder Page Content'; + $model = &$this->loadModel($this->name); + $page_content = &NController::factory('page_content'); + $page_content_model = &$page_content->loadModel('page_content'); + $pk = $page_content_model->primaryKey(); + $page_content->set('page_id', $parameter); + $content_html = ''; + if ($model->get($parameter)) { + $content = array(); + $page_content_model->reset(); + $page_content_model->getContainerContent($model->{$model->primaryKey()}, $template_container_id); + $page_content->set('template_container_id', $template_container_id); + if ($page_content_model->numRows()) { + $contents = array(); + while ($page_content_model->fetch()) { + $asset_ctrl = &NController::factory($page_content_model->content_asset); + if ($asset_ctrl && $asset_model = &$asset_ctrl->loadModel($asset_ctrl->name) && $asset_model->get($page_content_model->content_asset_id)) { + $content = $asset_model->toArray(); + $content['_asset'] = $asset_ctrl->name; + $content['_asset_name'] = Inflector::humanize($asset_ctrl->name); + $content['page_content_id'] = $page_content_model->$pk; + $contents[] = $content; + } + unset($asset_ctrl); + } + $this->set('template_container_id', $template_container_id); + $this->set('contents', $contents); + $this->set(array('reorder_link'=>count($contents) > 1?true:false)); + $this->set('no_edit', true); + $content_html .= $this->render(array('action'=>'content_container', 'return'=>true)); + } + } + $content_html .= $this->render(array('action'=>'reorder_close', 'return'=>true)); + $this->set('MAIN_CONTENT', $content_html); + $this->render(array('layout'=>'simple')); + } + + function menus($parent_id = null) { + $this->nterchange = (bool) preg_match('|^/' . APP_DIR . '|', $_SERVER['REQUEST_URI']); + if ($this->nterchange && isset($this->params['edit'])) { + $this->edit = true; + } + if ($this->nterchange) { + $this->_auth = new NAuth(); + } + $model = &$this->getDefaultModel(); + $parent_id = $parent_id?(int) $parent_id:$model->getRootNode(); + $check_visible = $check_active = ($this->nterchange?false:true); + header('Content-type:text/javascript'); + + // set up the values for the view layer + $this->base_view_dir = ROOT_DIR; + // don't allow caching for "submenus" + if ($parent_id != $model->getRootNode()) { + $view_caching = false; + } else { + $view_caching = (bool) PAGE_CACHING; + } + $this->view_caching = $view_caching; + $this->view_cache_lifetime = JS_CACHE_LIFETIME; + if (!$this->nterchange && $this->view_cache_lifetime) { + header('Expires:' . gmdate('D, d M Y H:i:s \G\M\T', time() + 3600)); + header('Cache-Control:max-age=3600, must-revalidate'); + } + + // SET UP CACHING + $qualified = $this->getParam('qualify')?true:false; + if ($this->nterchange && $this->edit) { + $this->view_cache_name = 'admin_edit_javascript'; + } else if ($this->nterchange) { + $this->view_cache_name = 'admin_javascript'; + } else if (CURRENT_SITE == 'secure') { + $this->view_cache_name = 'javascript_secure'; + } else if ($qualified) { + $this->view_cache_name = 'javascript_qualified'; + } else { + $this->view_cache_name = 'javascript'; + } + // instantiate the view now that we have a view_cache_name + $view = &NView::singleton($this); + $view_options = array('action'=>'blank'); + + // check if it's currently being built, if so, wait so you can use the cached version + // this protects against multiple people building the js menus at once + $buildfile = CACHE_DIR . '/ntercache/menubuild'; + // if the menu is being built, then wait quarter second and try again. + $wait = 0; + while (1==1) { + if (!file_exists($buildfile) || $this->isCached($view_options) || time() - filemtime($buildfile) > 8) { + if ($wait > 0) $this->debug('Client waited for ' . number_format($wait) . ' microseconds for someone else to write ' . $this->view_cache_name, N_DEBUGTYPE_CACHE); + break; + } + $wait += 250000; + usleep(250000); + } + // build the menus + if (!$this->isCached($view_options)) { + @touch($buildfile); + if ($this->view_caching != false) { + $this->debug('Creating cache for ' . $this->view_cache_name . '.' , N_DEBUGTYPE_CACHE); + } + $full_url = $qualified?preg_replace('/\/$/', '', PUBLIC_SITE):''; + $subdir = $this->getParam('subdir')?$this->getParam('subdir') . '/':''; + $main_nav = $model->getChildren($parent_id, true, true); + $i = 0; + $js = ''; + $html = ''; + $preload = ''; + $img_types = array('gif', 'png', 'jpg'); + $external_cache = defined('EXTERNAL_CACHE')?constant('EXTERNAL_CACHE'):''; + foreach($main_nav as $nav) { + $width = false; + foreach ($img_types as $img_type) { + if (file_exists(DOCUMENT_ROOT . '/images/nav/' . $subdir . $nav['filename'] . '.' . $img_type)) { + if (file_exists(DOCUMENT_ROOT . '/images/nav/' . $subdir . $nav['filename'] . '_over.' . $img_type)) { + if ($preload) $preload .= ', '; + $preload .= '\'' . $external_cache . '/images/nav/' . $subdir . $nav['filename'] . '_over.' . $img_type . '\''; + } + $size = getimagesize(DOCUMENT_ROOT . '/images/nav/' . $subdir . $nav['filename'] . '.' . $img_type); + if ($size) + $width = $size[0]; + if ($model->isBranch($nav['id'], $check_active, $check_visible)) { + $html .= $this->getMenuHTML($nav['id'], $i, $i, $width); + $js .= $this->getMenuIDs($nav['id'], $i); + } + $i++; + } + } + } + $preload = "preloadImages(" . $preload . ");\n"; + $js = ereg_replace('^, ', '', $js); + $js = 'var menus = new Array(' . $js . ");\n"; + $html = "document.write('" . $html . "');\n"; + $assigns = array('CONTENT'=>$preload . $js . $html); + $this->set($assigns); + print "// non-cached file\n\n"; + @unlink($buildfile); + } else { + $this->debug('Served cached script for ' . $this->view_cache_name . '.', N_DEBUGTYPE_CACHE); + print "// cached file\n\n"; + } + $this->auto_render = false; + $this->view_caching = $view_caching; + $this->render($view_options); + } + + function getMenuHTML($id, $menuid, $cssid, $width=false, $ancestors = array()) { + $qualified = $this->getParam('qualify')?true:false; + $full_url = $qualified?preg_replace('/\/$/', '', PUBLIC_SITE):''; + $this->view_caching = false; + $model = &$this->getDefaultModel(); + $check_visible = $check_active = ($this->nterchange?false:true); + // get children of this page + $children = $model->getChildren($id, $check_active, $check_visible); + $html = ''; + $submenus = array(); + $i = 0; + if ($children) { + foreach ($children as $child) { + // set mouseover ids for the template + $mouseovers = array(); + if (is_array($ancestors)) { + foreach ($ancestors as $key=>$ancestor) { + $mouseovers[] = $ancestor['menuid']; + } + } + $mouseovers[] = $menuid; + $branch = false; + $submenu_id = false; + if ($model->isBranch($child['id'], $check_active, $check_visible)) { + $branch = true; + // add submenus for recursion + $submenus[] = array('id'=>$child['id'], 'submenuid'=>$i); + $submenu_id = $i; + $mouseovers[] = $menuid . '_' . $i; + } + if (!$child['external_url'] || (!preg_match('/^http[s]?:\/\//', $child['external_url']) && !preg_match('/^javascript:/', $child['external_url']))) { + $href = $full_url . $this->getHref($child); + } else { + $href = $this->getHref($child); + } + $this->set('full_url', $full_url); + $this->set(array('menu_id'=>$menuid, 'submenu_id'=>$submenu_id, 'page'=>$child, 'href'=>$href, 'mouseovers'=>$mouseovers, 'branch'=>$branch)); + $html .= $this->render(array('action'=>'menu_item', 'return'=>true)); + $i++; + } + } + $this->set(array('menu_id'=>$menuid, 'width'=>$width, 'js'=>$html)); + $html = $this->render(array('action'=>'menu', 'return'=>true)); + // prep the html for js inclusion + $html = str_replace(array("'", "\n", "\r"), array("\\'", '\\n', '\\n'), $html); + if (count($submenus) > 0) { + $ancestors[] = array('id'=>$id, 'menuid'=>$menuid); + foreach ($submenus as $submenu) { + $html .= $this->getMenuHTML($submenu['id'], $menuid . '_' . $submenu['submenuid'], $cssid, $width, $ancestors); + } + } + return $html; + } + + function getMenuIDs($id, $menuid) { + $model = &$this->getDefaultModel(); + $check_visible = $check_active = ($this->nterchange?false:true); + $children = $model->getChildren($id, $check_active, $check_visible); + $submenus = array(); + $i = 0; + $js = ''; + $js .= ', \'' . $menuid . '\''; + foreach ($children as $child) { + if ($model->isBranch($child['id'], $check_active, $check_visible)) { + $submenus[] = array('id'=>$child['id'], 'submenuid'=>$i); + } + $i++; + } + if (count($submenus) > 0) { + $ancestors[] = array('id'=>$id, 'menuid'=>$menuid); + foreach ($submenus as $submenu) { + $js .= $this->getMenuIDs($submenu['id'], $menuid . '_' . $submenu['submenuid'], $ancestors); + } + } + return $js; + } + + function getContent() { + // don't cache any content + $this->view_caching = false; + $page_model = &$this->getDefaultModel(); + $pk = $page_model->primaryKey(); + $content = array(); + $template_containers = $this->templateContainers($page_model->page_template_id); + $page_content = &NController::singleton('page_content'); + if (!is_array($template_containers)) return null; + $page_content->set('page_id', $page_model->$pk); + foreach ($template_containers as $container) { + if (empty($container)) continue; + if (!isset($content[$container['container_var']])) { + $content[$container['container_var']] = ''; + $content[$container['container_var'] . '_EDIT_START'] = ''; + if ($this->nterchange && $this->edit && $this->content_edit_allowed) { + $page_content->set('template_container_id', $container[$pk]); + $page_content->set('template_container_name', $container['container_name']); + $content[$container['container_var'] . '_EDIT_START'] .= $page_content->render(array('action'=>'asset_add', 'return'=>true)); + } + } + $content[$container['container_var']] .= $this->getContainerContent($page_model->id, $container['id']); + } + unset($page_content); + return $content; + } + + function getContainerContent($page_id, $container_id, $page_content_id=null) { + $page_model = &$this->getDefaultModel(); + $this->auto_render = false; + $page_id = (int)$page_id; + $container_id = (int)$container_id; + if (!$page_id || !$container_id) return null; + // instantiate the page content controller + // TODO: put some methods into the page_content controller to do some of this. + $page_content = &NController::factory('page_content'); + $page_content_model = &$page_content->getDefaultModel(); + $page_content_pk = $page_content_model->primaryKey(); + + $asset_ctrl = &NController::singleton('cms_asset_template'); + if (SITE_WORKFLOW && $this->nterchange) { + // get the users rights and bit compare them below + $workflow = &NController::factory('workflow'); + $user_rights = $workflow->getWorkflowUserRights($page_model); + } + // load up the content + $content = ''; + // set the time using a trusted source + $now = new Date(gmdate('Y-m-d H:i:s')); + $now->setTZbyID('UTC'); + if ($page_content_model->getContainerContent($page_id, $container_id, $this->nterchange, $page_content_id)) { + $page_content->set('page_id', $page_id); + while ($page_content_model->fetch()) { + $page_content->set('page_content_id', $page_content_model->$page_content_pk); + $timed_start_obj = $page_content_model->timed_start && $page_content_model->timed_start != '0000-00-00 00:00:00'?new Date($page_content_model->timed_start):false; + $timed_end_obj = $page_content_model->timed_end && $page_content_model->timed_end != '0000-00-00 00:00:00'?new Date($page_content_model->timed_end):false; + if ($timed_start_obj) { + $timed_start_obj->setTZbyID('UTC'); + } + if ($timed_end_obj) { + $timed_end_obj->setTZbyID('UTC'); + } + // set cache lifetimes for the page + if ($timed_start_obj) { + $time_diff = $timed_start_obj->getDate(DATE_FORMAT_UNIXTIME) - $now->getDate(DATE_FORMAT_UNIXTIME); + if ($time_diff > 0) { + $this->view_cache_lifetimes[] = $time_diff; + } + } + if ($timed_end_obj) { + $time_diff = $timed_end_obj->getDate(DATE_FORMAT_UNIXTIME) - $now->getDate(DATE_FORMAT_UNIXTIME); + if ($time_diff > 0) { + $this->view_cache_lifetimes[] = $time_diff; + } + } + if ($timed_end_obj && $timed_end_obj->before($now)) { + $timed_end_active = true; + } + // if the timed end is in the past then kill it and continue. + if ($timed_end_obj && $now->after($timed_end_obj)) { + // remove the content, which also kills the page cache + $page_content_controller = &NController::factory('page_content'); + $page_content_controller->_auth = &$this->_auth; + $page_content_controller->removeContent($page_content_model->$page_content_pk, false, true); + unset($page_content_controller); + continue; + } else if ($this->nterchange || !$timed_start_obj || ($timed_start_obj && $timed_start_obj->before($now))) { + $content_controller = &NController::factory($page_content_model->content_asset); + if ($content_controller && is_object($content_controller)) { + $content_model = &$content_controller->getDefaultModel(); + $fields = $content_model->fields(); + $pk = $content_model->primaryKey(); + // if we're on the public site, don't grab workflow or draft inserts + $conditions = array(); + if ($this->nterchange && in_array('cms_draft', $fields)) { + $conditions = '(cms_draft = 0 OR (cms_draft=1 AND cms_modified_by_user=' . $this->_auth->currentUserId() . '))'; + } else { + $content_model->cms_draft = 0; + } + $content_model->$pk = $page_content_model->content_asset_id; + if ($content_model->find(array('conditions'=>$conditions), true)) { + // last modified + if (strtotime($content_model->cms_modified) > $this->page_last_modified) { + $this->page_last_modified = strtotime($content_model->cms_modified); + } + $template = $asset_ctrl->getAssetTemplate($page_content_model->content_asset, $page_content_model->page_template_container_id); + if (SITE_DRAFTS && $this->nterchange) { + $is_draft = false; + $user_owned = false; + $user_id = $this->_auth->currentUserId(); + $draft_model = &NModel::factory('cms_drafts'); + $draft_model->asset = $content_controller->name; + $draft_model->asset_id = $content_model->$pk; + if ($draft_model->find(null, true)) { + $is_draft = true; + // fill the local model with the draft info + $current_user_id = isset($this->_auth) && is_object($this->_auth)?$this->_auth->currentUserID():0; + if ($current_user_id == $draft_model->cms_modified_by_user) { + $draft_content = unserialize($draft_model->draft); + foreach ($draft_content as $field=>$val) { + $content_model->$field = $val; + } + $user_owned = true; + $draft_msg = 'You have saved'; + } else { + $user_model = &$this->loadModel('cms_auth'); + $user_model->get($draft_model->cms_modified_by_user); + $draft_msg = $user_model->real_name . ' has saved'; + unset($user_model); + } + } + unset($draft_model); + } + if (SITE_WORKFLOW && $this->nterchange) { + if ($workflow_group_model = &$workflow->getWorkflowGroup($page_model)) { + if ($current_workflow = &$workflow->getWorkflow($page_content_model->{$page_content_model->primaryKey()}, $workflow_group_model->{$workflow_group_model->primaryKey()}, $content_controller)) { + $current_user_id = isset($this->_auth) && is_object($this->_auth)?$this->_auth->currentUserID():0; + $content_edit_allowed = $this->content_edit_allowed; + $this->content_edit_allowed = !$current_workflow->submitted && $current_user_id == $current_workflow->cms_modified_by_user?true:false; + $workflow_draft = unserialize($current_workflow->draft); + foreach ($workflow_draft as $field=>$val) { + $content_model->$field = $val; + } + } + } + } + $values = $content_model->toArray(); + $values['_EDIT_START_'] = ''; + $values['_EDIT_END_'] = ''; + if ($this->nterchange && $this->edit) { $values['_SURFTOEDIT_'] = true; } + if ($this->edit) { + if ($this->content_edit_allowed) { + // $values['_EDIT_START_'] .= '
' . "\n"; + $page_content->set(array('asset'=>$content_controller->name, 'asset_id'=>$content_model->$pk)); + $values['_EDIT_START_'] .= $page_content->render(array('action'=>'asset_edit', 'return'=>true)); + } + $page_content->set(array('asset'=>$content_controller->name, 'asset_id'=>$content_model->$pk, 'page_content_id'=>$page_content_model->$page_content_pk, 'page_id'=>$page_id)); + $values['_EDIT_START_'] .= '
' . "\n"; + if (SITE_WORKFLOW && isset($current_workflow) && $current_workflow) { + if ($this->content_edit_allowed) { + $values['_EDIT_START_'] .= '
The following content is waiting to be submitted to workflow in the dashboard.
' . "\n"; + } else { + $values['_EDIT_START_'] .= '
The following content is currently in workflow and cannot be edited.
' . "\n"; + } + } + $values['_EDIT_END_'] .= "
\n"; + if ($this->content_edit_allowed) { + if (SITE_DRAFTS && $is_draft) { + $values['_EDIT_START_'] .= '
' . $draft_msg . ' the following content as a draft.
' . "\n"; + } + $values['_EDIT_END_'] .= "
\n"; + } + } + if ($this->nterchange && (($timed_start_obj && $timed_start_obj->after($now)) || ($timed_end_obj && $timed_end_obj->after($now)))) { + $format = '%a, %b %e, %Y @ %I:%M:%S %p'; + $values['_EDIT_START_'] .= '
'; + $values['_EDIT_START_'] .= 'The following content is currently' . ($timed_start_obj && $timed_start_obj->after($now)?' NOT':'') . ' visible (it is now ' . NDate::convertTimeToClient($now, $format) . ')'; + if ($timed_start_obj && $timed_start_obj->after($now)) $values['_EDIT_START_'] .= '
It will appear: ' . NDate::convertTimeToClient($timed_start_obj, $format); + if ($timed_end_obj && $timed_end_obj->after($now)) $values['_EDIT_START_'] .= '
It will be removed: ' . NDate::convertTimeToClient($timed_end_obj, $format); + $values['_EDIT_START_'] .= '
'; + } + if (isset($content_edit_allowed)) { + $this->content_edit_allowed = $content_edit_allowed; + unset($content_edit_allowed); + } + + // Remove extra whitespace/newlines + $values['_EDIT_START_'] = trim(preg_replace('/\s+/', ' ', $values['_EDIT_START_'])); + $values['_EDIT_END_'] = trim(preg_replace('/\s+/', ' ', $values['_EDIT_END_'])); + + // Render the content + $content_controller->set($values); + $content .= $content_controller->render(array('action'=>$template, 'return'=>true)); + } + unset($content_model); + unset($content_controller); + } + } + } + } + + // free up some memory + unset($page_content_model); + unset($page_content); + // return the content + return $content; + } + + function getTemplate($template_id) { + $template_id = (int) $template_id; + $model = &$this->getDefaultModel(); + if (!$template_id) { + return false; + } + $tc_model = &NModel::factory('page_template'); + $layout = null; + if ($tc_model->get($template_id)) { + $layout = $tc_model->template_filename; + } + unset($model); + return $layout; + } + + function templateContainers($page_template_id, $id=0) { + // TODO: put some methods into the page_content controller to do some of this. + $controller_name = 'page_template_containers'; + $tc = &NController::singleton($controller_name); + $model = &$tc->getDefaultModel(); + $model->reset(); + $options = array(); + $options['conditions'] = 'page_template_id=' . (int)$page_template_id; + if ($id) { + $model->id = (int) $id; + } + $containers = array(); + if ($model->find($options)) { + while ($model->fetch()) { + $containers[] = $model->toArray(); + } + } + unset($model); + unset($tc); + return $containers; + } + + function preGenerateForm() { + $model = &$this->loadModel($this->name); + // the parent_id select field + if ($model->{$model->primaryKey()} != $model->getRootNode()) { + $model->form_elements['parent_id'] = &$this->getTreeAsSelect('parent_id', 'Parent Page'); + } else { + $model->form_ignore_fields[] = 'parent_id'; + } + } + + function postGenerateForm(&$form) { + // grab the model + $model = &$this->getDefaultModel(); + $pk = $model->primaryKey(); + // change the header + $el = &$form->getElement('__header__'); + if ($model->$pk) { + $el->setValue($model->title . ' - page' . $model->$pk); + } else { + $el->setValue('Create a page'); + } + // if parent_id has been passed, then use it + if ($parent_id = (int) $this->getParam('parent_id')) { + $form->setDefaults(array('parent_id'=>$parent_id)); + } + // put in some rich stuff for template changing + $page_template_value = $form->getElementValue('page_template_id'); + $page_template_value = $page_template_value[0]; + $tpl = &$form->getElement('page_template_id'); + $tpl->updateAttributes(array('onchange'=>'if(this.options[this.selectedIndex].value != ' . $page_template_value . '){Element.show(\'mv_content_check\');}else{Element.hide(\'mv_content_check\');}')); + $mv_content = &NQuickForm::createElement('checkbox', 'mv_content'); + $mv_content_html = &NQuickForm::createElement('html', ' 
' . $mv_content->toHTML() . ' Attempt to move content?
' . "\n"); + $form->insertElementBefore($mv_content_html, 'visible'); + // add section headers + if ($model->{$model->primaryKey()} == $model->getRootNode()) { + $form->removeElement('parent_id'); + } + if ($form->elementExists('permissions_id')) { + $form->insertElementBefore($form->createElement('header', null, 'Public Page Permissions'), 'permissions_id'); + } + if ($form->elementExists('external_url')) { + $form->insertElementBefore($form->createElement('header', null, 'External Link'), 'external_url'); + } + if ($form->elementExists('workflow_group_id')) { + $form->insertElementBefore($form->createElement('header', null, 'Workflow'), 'workflow_group_id'); + } + if ($form->elementExists('disclaimer_required')) { + $form->insertElementBefore($form->createElement('header', null, 'Legal Disclaimer'), 'disclaimer_required'); + } + if ($form->elementExists('meta_keywords')) { + $form->insertElementBefore($form->createElement('header', null, 'Meta Information'), 'meta_keywords'); + } + if ($form->elementExists('notify_date')) { + $form->insertElementBefore($form->createElement('header', null, 'Update Notification'), 'notify_date'); + } + parent::postGenerateForm($form); + } + + function preProcessForm(&$values) { + if (empty($values['filename'])) { + include_once 'n_filesystem.php'; + $values['filename'] = NFilesystem::cleanFileName($values['title']); + } + parent::preProcessForm($values); + } + + function postProcessForm(&$values) { + $model = &$this->getDefaultModel(); + $pk = $model->primaryKey(); + + // fix the paths for navigation + // if (on insert or if changed path on update) + $this->fixPaths($model->$pk); + + // move all the old content to the current template + // into matching template containers + if (isset($values['mv_content'])) { + $page_content = &NController::singleton('page_content'); + $page_content->changeTemplate($model->$pk, $model->page_template_id); + } + + // delete general caches + include_once 'n_cache.php'; + NCache::removeMenu(); + NCache::removeTreeAsSelect(); + NCache::removeJavascript($model->$pk); + + // REMOVE PAGE CACHE + $this->deletePageCache($model->$pk); + + // REMOVE PARENT PAGE CACHE (for child links, etc); + if ($this->action == 'create') { + // load a new one + $new_model = &NModel::factory($this->name); + $parent_id = $new_model->getParent($model->$pk); + unset($new_model); + } else { + // user the existing model to find the parent + $parent_id = $model->getParent($model->$pk); + } + $this->deletePageCache($parent_id); + + // remove the site admin cache + $site_admin = &NController::singleton('site_admin'); + $site_admin->deleteCache(); + unset($site_admin); + + if ($this->action == 'delete') { + $this->flash->set('notice', 'Your page has been deleted.'); + } else { + $this->flash->set('notice', 'Your page has been saved.'); + } + parent::postProcessForm($values); + } + + function getPageContent($page_id, $container_id=0, $checkactive=true) { + if (!$page_id) { + // Pear Error goes here. + } + $res = $this->getPages($page_id); + $page_info = $res->fetchRow(); + $res->free(); + $res = InputOutput::getPageTemplateContainers($page_info['page_template_id']); + $template_containers = array(); + while ($row = $this->prepareOutputContent($res->fetchRow())) { + $template_containers[] = array('id'=>$row['id'], 'var'=>$row['container_var']); + } + $page_content = array(); + foreach($template_containers as $template_container) { + if ($container_id == 0 || $container_id == $template_container['id']) { + $sql = "SELECT * FROM page p, page_content pc WHERE p.id = $page_id AND pc.page_id = p.id"; + $sql .= " AND pc.page_template_container_id = " . $template_container['id']; + $sql .= " ORDER BY"; + $sql .= " pc.page_template_container_id,"; + $sql .= " content_order, pc.id"; + $res = $this->db->query($sql); + while ($row = $this->prepareOutputContent($res->fetchRow())) { + if ($row['timed_end'] != '0000-00-00 00:00:00' && strtotime($row['timed_end']) < time()) { + $this->deletePageContent($row['id']); + } else { + $io = InputOutput::singleton($row['content_object']); + $cres = $io->getRecords($row['content_object_id'], $checkactive); + if (!DB::isError($cres)) { + $crow = $this->prepareOutputContent($cres->fetchRow()); + if ($crow) $page_content[$template_container['var']][] = array('id'=>$crow['id'], 'page_template_container_id'=>$row['page_template_container_id'], 'object'=>$io->getObject(), 'object_name'=>$io->getObjectName(), 'headline'=>$crow['cms_headline'], 'page_content_id'=>$row['id'], 'timed_start'=>$row['timed_start'], 'timed_end'=>$row['timed_end']); + } + } + } + } + } + + return $page_content; + } + + function changeContentOrder($page_id, $content) { + foreach($content as $key=>$id) { + $ordernum = $key + 1; + $sql = 'UPDATE page_content SET content_order=' . $ordernum . ' WHERE page_id=' . $page_id . ' AND id=' . $id; + $this->db->query($sql); + } + $this->deletePageCache($page_id); + return true; + } + + function getLink($page_info, $treat_title=false) { + $model = $this->getDefaultModel(); + $link = ''; + $title = $page_info['title']; + if (is_callable($treat_title)) { + $title = call_user_func($treat_title, $title); + } + if ($page_info['active'] == 0) { + $title = '[' . $title . ']'; + } else if ($page_info['visible'] == 0) { + $title = '(' . $title . ')'; + } + $link .= $title; + $link .= ''; + return $link; + } + function getHref($page_info, $branch=null) { + $model = &$this->getDefaultModel(); + if (defined('IN_NTERCHANGE') && IN_NTERCHANGE && defined('IN_SURFTOEDIT') && IN_SURFTOEDIT) { + $href = '/' . APP_DIR . '/page/surftoedit/' . $page_info[$model->primaryKey()]; + } else if (defined('IN_NTERCHANGE') && IN_NTERCHANGE) { + $href = '/' . APP_DIR . '/page/preview/' . $page_info[$model->primaryKey()]; + } else { + if ($page_info['external_url']) { + $href = $page_info['external_url']; + } else { + $href = $page_info['path']; + if ($branch === null) { + if ($model->isBranch($page_info[$model->primaryKey()], true, true)) { + $href .= '/'; + } else { + $href .= '.' . DEFAULT_PAGE_EXTENSION; + } + } else if ($branch == false) { + $href .= '.' . DEFAULT_PAGE_EXTENSION; + } else { + $href .= '/'; + } + $href = ((defined('SECURE_SITE') && SECURE_SITE != false && $page_info['secure_page'] != 0)?preg_replace('|/$|', '', SECURE_SITE):((CURRENT_SITE == 'secure')?preg_replace('|/$|', '', PUBLIC_SITE):'')) . $href; + } + } + return $href; + } + function getTarget($page_info) { + if ($this->nterchange && $page_info['external_url'] != '' && $page_info['external_url_popout'] != 0) { + return ' target="_blank"'; + } + return ''; + } + + function deletePageCache($id) { + if (!empty($id)) { + // load the model + $model = &NModel::singleton($this->name); + $model->reset(); + if ($model->get($id)) { + $pk = $model->primaryKey(); + // find the action + $action = $this->getTemplate($model->page_template_id); + $action = $action?$action:'default'; + $action = $this->getTemplate($model->page_template_id); + $action = $action?$action:'default'; + // set up caching values + $this->base_view_dir = ROOT_DIR; + $this->view_caching = true; + $this->view_cache_lifetime = $model->cache_lifetime; + $this->view_cache_name = 'page' . $id; + $view = &NView::singleton($this); + if ($this->isCached($action)) { + $cleared = $view->clearCache($action); + $this->debug('Page cache for Page ID ' . $id . ($cleared?' removed':' failed attempted removal') . '.', N_DEBUGTYPE_CACHE); + } else { + $this->debug('Page cache for Page ID ' . $id . ' failed attempted removal since cache does not exist.', N_DEBUGTYPE_CACHE); + } + // Check the smarty_cache folder for additional caches from query string pages. + $query_string_caches = CACHE_DIR . '/smarty_cache/page' . $id . '%*'; + if (count(glob($query_string_caches)) != 0) { + $files = glob($query_string_caches); + foreach ($files as $file) { + unlink($file); + } + NDebug::debug('Deleted query string cache files for page id ' . $id , N_DEBUGTYPE_INFO); + } + } + unset($model); + unset($view); + } + return; + } + + function fixPaths($id=0) { + $model = &NModel::singleton($this->name); + $model->reset(); + if (!$id) $id = $model->getRootNode(); + $fields = $model->fields(); + if ($model->get($id)) { + // update the current page + $model->path = $model->buildPath($id); + if (in_array('cms_modified_by_user', $fields)) { + $model->cms_modified_by_user = isset($this->_auth)?(int) $this->_auth->currentUserID():0; + } + $model->update(); + // update all the children + $all_children = $model->getAllChildren($id, false, false); + foreach ($all_children as $child) { + $model->reset(); + $model->get($child[$model->primaryKey()]); + $model->path = $model->buildPath($child['id']); + if (in_array('cms_modified_by_user', $fields)) { + $model->cms_modified_by_user = isset($this->_auth)?(int) $this->_auth->currentUserID():0; + } + $model->update(); + } + } + unset($model); + } + + function &getTreeAsSelect($name, $label) { + include_once 'n_cache.php'; + include_once 'n_quickform.php'; + if (!$options = NCache::getTreeAsSelect()) { + $options = $this->getOptions(false); + if ($options) { + NCache::createTreeAsSelect($options); + } + } + return NQuickForm::createElement('select', $name, $label, $options); + } + + function getOptions($options=false, $id=0, $level=0) { + $spaces = str_repeat('- ', $level); + $model = &$this->getDefaultModel(); + $children = $model->getChildren($id, !$this->nterchange, !$this->nterchange); + if (!$options) $options = array(); + if (is_array($children)) { + for ($x=0;$xgetOptions($options, $children[$x]['id'], $level+1); + } + return $options; + } + } + + function evalHTML($tpl_output) { + $pos = 0; + // Loop through to find the php code in html... + while (($pos = strpos($tpl_output, '', $pos + 5); + // Eval outputs directly to the buffer. Catch / Clean it + ob_start(); + eval(substr($tpl_output, $pos + 5, $pos2 - $pos - 5)); + $value = ob_get_contents(); + ob_end_clean(); + // Grab that chunk! + $tpl_output = substr($tpl_output, 0, $pos) . $value . substr($tpl_output, $pos2 + 2); + } + return $tpl_output; + } + + function render($options=array()) { + $return = isset($options['return'])?$options['return']:false; + $options['return'] = true; + $page = parent::render($options); + $page = $this->evalHTML($page); + if ($return) return $page; + print $page; + } + + function sitemap($params=array()) { + $model = &$this->getDefaultModel(); + $page_id = isset($params['page_id'])?$params['page_id']:$model->getRootNode(); + $treat_title = isset($params['treat_title'])?$params['treat_title']:null; + $title_recurse = isset($params['treat_title_recurse'])?(bool) $params['treat_title']:false; + if ($this->nterchange) { + $checkactive = false; + $checkvisible = false; + } else { + $checkactive = true; + $checkvisible = true; + } + $main_nav = $model->getChildren($page_id, $checkactive, $checkvisible); + $html = '
'; + + foreach($main_nav as $nav) { + $html .= "
  • "; + if (isset($GLOBALS['page_id']) && $GLOBALS['page_id'] == $nav['id']) $html .= ''; + $html .= $this->getLink($nav, $treat_title); + if (isset($GLOBALS['page_id']) && $GLOBALS['page_id'] == $nav['id']) $html .= ''; + + if ($model->isBranch($nav['id'], $checkactive, $checkactive)) { + $sub_treat_title = ($title_recurse == true)?$treat_title:false; + $html .= $this->getChildList($nav['id'], $sub_treat_title); + } + $html .= "
\n"; + } + $html .="
"; + return $html; + } + + function getChildList($page_id, $treat_title=false) { + $model = &$this->getDefaultModel(); + if ($this->nterchange) { + $checkactive = false; + $checkvisible = false; + } else { + $checkactive = true; + $checkvisible = true; + } + $children = $model->getChildren($page_id, $checkactive, $checkvisible); + $html = ''; + $submenu = array(); + foreach ($children as $child) { + $html .= "\t
  • "; + $info = $model->getInfo($child['id']); + if (isset($GLOBALS['page_id']) && $GLOBALS['page_id'] == $info['id']) $html .= ''; + $html .= $this->getLink($info, $treat_title); + if (isset($GLOBALS['page_id']) && $GLOBALS['page_id'] == $info['id']) $html .= ''; + if ($model->isBranch($child['id'], $checkactive, $checkactive)) { + $html .= $this->getChildList($child['id'], $treat_title); + } + $html .= "
  • \n"; + } + if ($html) { + $html = "
      \n" . $html . "
    \n\n"; + } + return $html; + } +} diff --git a/app/controllers/page_template_containers_controller.php b/app/controllers/page_template_containers_controller.php new file mode 100644 index 0000000..c08a8d1 --- /dev/null +++ b/app/controllers/page_template_containers_controller.php @@ -0,0 +1,106 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class PageTemplateContainersController extends AdminController { + function __construct() { + $this->name = 'page_template_containers'; + // set user level allowed to access the actions with required login + $this->user_level_required = N_USER_ADMIN; + $this->login_required = true; + parent::__construct(); + } + + function viewlist($page_template_id) { + $this->loadSubnav($page_template_id); + $this->auto_render = false; + $html = ''; + if (!$page_template_id) { + // This is a bit of a hack. + header ('Location: /nterchange/page_template/viewlist'); + } + $model = $this->getDefaultModel($this->name); + $model->page_template_id = $page_template_id; + // Let's get more information about the page_template. + if ($page_template = $model->getLink('page_template_id', 'page_template')) { + $this->set('page_template_name', $page_template->template_name); + $this->set('page_template_filename', $page_template->template_filename); + } + $this->set('page_template_id', $page_template_id); + if ($model->find()) { + while ($model->fetch()) { + $arr = $model->toArray(); + $arr['_headline'] = isset($arr['cms_headline']) && $arr['cms_headline']?$arr['cms_headline']:$model->makeHeadline(); + $models[] = $arr; + unset($arr); + } + $html .= $this->set('rows', $models); + } else { + $this->set('notice', 'There are no containers for that template.'); + } + $html .= $this->set(array('asset'=>$this->name, 'asset_name'=>$this->page_title?$this->page_title:Inflector::humanize($this->name))); + $html .= $this->render(array('layout'=>'default')); + return $html; + } + + function create($parameter=null, $layout=true) { + $this->page_template_id = $parameter; + $this->loadSubnav($parameter); + parent::create($parameter); + } + + function edit($parameter) { + $this->page_template_id = $this->getPTIFromId($parameter); + $this->set('page_template_id', $this->page_template_id); + $this->loadSubnav($parameter); + parent::edit($parameter); + } + + // Get page_template_id from page_template_container_id. + function getPTIFromId($id) { + $model = &NModel::factory($this->name); + $model->id = $id; + if($model->find()) { + while ($model->fetch()) { + $result = $model->toArray(); + } + $page_template_id = $result['page_template_id']; + } + unset($model); + return $page_template_id; + } + + function postGenerateForm(&$form) { + $form->removeElement('__header__'); + $form->addRule('container_var', 'We need to have a variable for this container.', 'required', null, 'client'); + $form->addRule('container_name', 'We need to have a name for this container.', 'required', null, 'client'); + $form->addRule('container_var', 'Uppercase letters, numbers and underscores - without spaces or punctuation.', 'regex', '/^[A-Z0-9_]+$/', 'client'); + // Set the page_template in the menu as passed by $parameter. + $template_group = &$form->getElement('page_template_id'); + $template_group->setSelected($this->page_template_id); + // Not sure I should do this - but it seems to help with confusion. + $template_group->freeze(); + } + + function &getDefaultModel() { + $model = &$this->loadModel('page_template_containers'); + return $model; + } + +} +?> \ No newline at end of file diff --git a/app/controllers/page_template_controller.php b/app/controllers/page_template_controller.php new file mode 100644 index 0000000..e80ab31 --- /dev/null +++ b/app/controllers/page_template_controller.php @@ -0,0 +1,52 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class PageTemplateController extends AdminController { + function __construct() { + $this->name = 'page_template'; + // set user level allowed to access the actions with required login + $this->user_level_required = N_USER_ADMIN; + $this->login_required = true; + $this->page_title = 'Templates'; + parent::__construct(); + } + + function &getDefaultModel() { + $model = &$this->loadModel('page_template'); + return $model; + } + + function doesPageTemplateExist($filename){ + $full_path_filename = ASSET_DIR . '/views/page/' . $filename . '.' . DEFAULT_PAGE_EXTENSION; + if (file_exists($full_path_filename)) { + return true; + } else { + return false; + } + } + + function postGenerateForm(&$form) { + $form->removeElement('__header__'); + $form->addRule('template_filename', 'We need to have a filename.', 'required', null, 'client'); + $form->addRule('template_name', 'We need to have a name for this template.', 'required', null, 'client'); + $form->addRule('template_filename', 'Letters, numbers, dashes and underscores - without a suffix, spaces or punctuation.', 'regex', '/^[a-zA-Z0-9_-]+$/', 'client'); + //'Code contains numbers only', 'regex', '/^\d+$/' + } +} +?> \ No newline at end of file diff --git a/app/controllers/phpinfo_controller.php b/app/controllers/phpinfo_controller.php new file mode 100755 index 0000000..202c8b6 --- /dev/null +++ b/app/controllers/phpinfo_controller.php @@ -0,0 +1,31 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class PhpinfoController extends AppController { + function __construct() { + $this->login_required = true; + parent::__construct(); + } + + function index() { + $this->auto_render = false; + phpinfo(INFO_ALL ^ INFO_ENVIRONMENT); + } +} +?> diff --git a/app/controllers/redirect_controller.php b/app/controllers/redirect_controller.php new file mode 100644 index 0000000..e2fceec --- /dev/null +++ b/app/controllers/redirect_controller.php @@ -0,0 +1,94 @@ + + * @author Darron Froese + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class RedirectController extends AssetController { + function __construct() { + $this->name = 'redirect'; + $this->versioning = true; + $this->base_view_dir = ROOT_DIR; + $this->redirect_delay = 3; + parent::__construct(); + } + + /** + * checkRedirect - Look in the database to see if there's a redirect to follow. + * If there is - hit renderRedirect. + * + * @return void + **/ + function checkRedirect() { + include_once 'n_server.php'; + $current_url = NServer::env('REQUEST_URI'); + // Check DB for direct match. + $model = &$this->getDefaultModel(); + $model->reset(); + $model->url = $current_url; + $model->regex = 0; + $model->find(); + while ($model->fetch()) { + $this->renderRedirect($model->toArray()); + } + // Let's look at the regex matches. + $model->reset(); + $model->regex = 1; + $model->find(); + $urls = &$model->fetchAll(); + foreach ($urls as $url) { + if ($url->regex != 0 && eregi($url->url, $current_url)) { + $this->renderRedirect($url->toArray()); + } + } + } + + /** + * renderRedirect - Render a page that automatically redirects to the required location. + * Doing it this way allows your regular website statistics to generate reports. + * If there isn't a template to use, then just redirect and count the old way. + * + * @param array A redirect model object converted toArray(); + * @return void + **/ + function renderRedirect($array) { + if (file_exists(ASSET_DIR . '/views/redirect/default.html')) { + // Do the new style page load and render. + $contents['_SITE_NAME_'] = htmlentities(SITE_NAME); + $contents['_EXTERNAL_CACHE_'] = defined('EXTERNAL_CACHE') && constant('EXTERNAL_CACHE')?EXTERNAL_CACHE:false; + $this->set('title', 'Redirecting...'); + $this->set('redirect_delay', $this->redirect_delay); + $this->set('header', ''); + $this->set($contents); + $this->set($array); + $this->render(array('action'=>'default')); + die; + } else { + // Do the old redirect style and count. + // $url = &$this->getDefaultModel(); + // $url->id = $array['id']; + // $url->get(); + // $url->count += 1; + // $url->update(); + if ($address = $array['redirect']) { + header ("Location: $address"); + die; + } + } + } +} +?> \ No newline at end of file diff --git a/app/controllers/rss_controller.php b/app/controllers/rss_controller.php new file mode 100644 index 0000000..5ed7e41 --- /dev/null +++ b/app/controllers/rss_controller.php @@ -0,0 +1,116 @@ + + * @copyright 2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + * @since Version 3.1.17 + */ +class RSSController extends AssetController { + function __construct() { + $this->name = 'rss'; + $this->page_title = 'RSS Feeds'; + $this->records = 50; + $this->set('_SITE_NAME_', SITE_NAME); + parent::__construct(); + } + + /** + * generateFeedToken - Generate a feed_token for a logged in user. + * Puts it into the database and returns to the passed url. + * + * @return void + **/ + function generateFeedToken() { + $redirect_url = isset($_GET['redirect'])?$_GET['redirect']:'/nterchange'; + $random = $_SERVER['REMOTE_ADDR'] . rand(0,1000000) . time(); + $tmp_feed_token = md5($random); + $auth = new NAuth(); + $user_id = $auth->currentUserID(); + unset($auth); + $cms_user = NModel::factory('cms_auth'); + $cms_user->id = $user_id; + if ($cms_user->find()) { + while ($cms_user->fetch()) { + $cms_user->feed_token = $tmp_feed_token; + $cms_user->save(); + header("Location:$redirect_url"); + } + } + } + + /** + * checkToken - Check whether or not the token is present in the DB. + * + * @param string The offered token. + * @return boolean + **/ + function checkToken($token) { + // Check the token to the ones in the database. + $cms_auth = NModel::factory('cms_auth'); + $cms_auth->feed_token = $token; + if ($cms_auth->find()) { + return true; + } else { + return false; + } + } + + /** + * getToken - Get a token as passed on the $_GET string. + * + * @return string The $_GET['token'] passed + **/ + function getToken() { + return $_GET['token']; + } + + /** + * auditTrail - Create an RSS feed of audit trail records. + * Shows $this->records many records. + * + * @return void + **/ + function auditTrail() { + if (defined('RSS_AUDIT_TRAIL') && RSS_AUDIT_TRAIL) { + $this->auto_render = false; + $count = 0; + $token = $this->getToken(); + // It's got to be 32 characters - this keeps people from trying token= + if ($length = strlen($token) < 32) die; + if ($allowed = $this->checkToken($token)) { + // Grab the last 50 results + $audit_trail = NModel::factory('cms_audit_trail'); + $options['order_by'] = 'cms_created DESC'; + if ($audit_trail->find($options)) { + while ($audit_trail->fetch()) { + $audit_trail_controller = NController::factory('audit_trail'); + $record = $audit_trail_controller->humanizeAuditTrailRecord($audit_trail); + //varDump($record); + $records[] = $record; + $count++; + if ($count >= $this->records) break; + } + } + $this->set('records', $records); + $this->render(array('action'=>'audit_trail')); + } else { + print "Unauthorized access"; + } + } + } + +} +?> diff --git a/app/controllers/search_controller.php b/app/controllers/search_controller.php new file mode 100644 index 0000000..ddd866e --- /dev/null +++ b/app/controllers/search_controller.php @@ -0,0 +1,145 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class SearchController extends AppController { + function __construct() { + $this->name = 'search'; + $this->versioning = true; + $this->base_view_dir = ROOT_DIR; + parent::__construct(); + } + + function search() { + include_once 'HTTP/Header.php'; + $header = new HTTP_Header; + $search = htmlentities($this->getParam('search')); + $html = ''; + $this->set('request_uri', NServer::env('PHP_SELF')); + $this->set('search', $search); + $html .= $this->render(array('action'=>'search_form', 'return'=>true)); + if ($search && function_exists('udm_alloc_agent')) { + $current_page = $this->getParam('page')?(int) $this->getParam('page'):0; + + // instantiate the search agent + $udm_agent = udm_alloc_agent(DB_DSN_SEARCH); + $page_size = 10; + + // pull in the stopwords and remove them from the query + $stopfile = defined('MNOGO_STOPFILE')?constant('MNOGO_STOPFILE'):'/usr/local/mnogosearch/etc/stopwords/en.huge.sl'; + $tmp = file($stopfile); + $stopwords = array(); + for($i=0;$i 0?$total_rows-1:$total_rows; + $page_rows = udm_get_res_param($res, UDM_PARAM_NUM_ROWS); + $first_doc = udm_get_res_param($res, UDM_PARAM_FIRST_DOC); + $last_doc = udm_get_res_param($res, UDM_PARAM_LAST_DOC); + $total_pages = ceil($total_rows/$page_size); + + // set general template values + $this->set('rows', $total_rows); + $template_pages = array(); + for ($i=0;$i<$total_pages;$i++) { + $template_pages[] = $i+1; + } + $search_url = NServer::env('PHP_SELF') . '?search=' . $search . '&page='; + $this->set('stopped_words', $stopped_words); + $this->set('search_url', $search_url); + $this->set('current_page', $current_page); + $this->set('pages', $template_pages); + $this->set('previous_page', ($current_page>0)?$current_page-1:-1); + $this->set('next_page', ($current_page+1<$total_pages)?$current_page+1:-1); + + // gather the results and pass them to the template + $items = array(); + for ($i=0;$i<$page_rows;$i++) { + $item['title'] = udm_get_res_field($res, $i, UDM_FIELD_TITLE); + $item['url'] = udm_get_res_field($res, $i, UDM_FIELD_URL); + $item['text'] = udm_get_res_field($res, $i, UDM_FIELD_TEXT); + $item['size'] = udm_get_res_field($res, $i, UDM_FIELD_SIZE); + $item['filesize'] = udm_get_res_field($res, $i, UDM_FIELD_SIZE); + if ($item['filesize']) $item['filesize'] = NFilesystem::filesize_format($item['filesize']); + $item['rating'] = udm_get_res_field($res, $i, UDM_FIELD_RATING); + $item['title'] = $item['title']?$this->cleanupItem(htmlspecialchars($item['title'])):basename($item['url']); + $item['text'] = $this->cleanupItem($item['text']); + $items[] = $item; + } + $this->set('items', $items); + $html .= $this->render(array('action'=>'found_items', 'return'=>true)); + udm_free_res($res); + udm_free_agent($udm_agent); + } else { + $html .= '

    You have not entered any search queries - please enter one in the form above.

    '; + } + return $html; + } + + function search404() { + if ($this->getParam('search')) { + return $this->search(); + } + $uri = NServer::env('PHP_SELF'); + $words = explode('/', $uri); + // remove any empty elements + foreach ($words as $i=>$val) { + if(empty($val)){ + unset($words[$i]); + } + } + $this->setParam('search', urldecode(implode(' ', $words))); + return $this->search(); + } + + function cleanupItem($var) { + include_once 'model/value_cast.php'; + $var = ValueCast::toLatinISO($var); + // some weird mnogosearch characters to replace + $var = preg_replace('/\\x02/', '', $var); + $var = preg_replace('/\\x03/', '', $var); + return $var; + } +} +?> diff --git a/app/controllers/settings_controller.php b/app/controllers/settings_controller.php new file mode 100644 index 0000000..a304c80 --- /dev/null +++ b/app/controllers/settings_controller.php @@ -0,0 +1,109 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class SettingsController extends nterchangeController { + function __construct() { + $this->name = 'settings'; + // set user level allowed to access the actions with required login + $this->user_level_required = N_USER_NORIGHTS; + // $this->public_actions = array(); + $this->login_required = true; + parent::__construct(); + } + + function &getDefaultModel() { + return $this->loadModel('cms_settings'); + } + + function index() { + $this->redirectTo('viewlist'); + $this->auto_render = false; + $model = &$this->getDefaultModel(); + + $this->render(array('layout'=>'default')); + } + + function viewlist() { + $this->auto_render = false; + include_once 'n_quickform.php'; + $model = &$this->getDefaultModel(); + $pk = $model->primaryKey(); + $setting_forms = array(); + $user_settings = $GLOBALS['USER_SETTINGS']; + foreach ($user_settings as $setting=>$default) { + $model->reset(); + $model->user_id = (int) $this->_auth->currentUserId(); + $model->setting = $setting; + $form = new NQuickForm('setting_' . $setting); + $form->addElement('header', null, $model->settingToText($setting)); + $description = $this->getSettingDescription($setting); + if (!$description) { + $description = 'Setting'; + } + $form->addElement('hidden', 'setting', $setting); + $checkbox = &$form->addElement('checkbox', 'value', $description, null, array('id'=>'qf_' . $model->setting)); + if ($model->find(null, true)) { + // set the form action to edit + $form->updateAttributes(array('action'=>'/' . APP_DIR . '/' . $this->name . '/edit/' . $model->$pk)); + $form->addElement('hidden', $pk, $model->$pk); + // check the box according to the value + $checkbox->setChecked((bool) $model->value); + } else { + $form->updateAttributes(array('action'=>'/' . APP_DIR . '/' . $this->name . '/create')); + $checkbox->setChecked((bool) $default); + } + $form->addElement('hidden', '_referer', urlencode(NServer::env('REQUEST_URI'))); + $form->addElement('submit', '__submit__', 'Submit'); + $form->addRule('setting', null, 'required'); + $setting_forms[] = &$form; + } + $this->set('settings', $setting_forms); + $this->render(array('layout'=>'default')); + } + + function show($parameter) { + $model = &$this->getDefaultModel(); + $model->user_id = (int) $this->_auth->currentUserId(); + return parent::show($parameter); + } + + function edit($parameter) { + $model = &$this->getDefaultModel(); + $model->user_id = (int) $this->_auth->currentUserId(); + $this->flash->set('notice', 'Your preference has been saved.'); + return parent::edit($parameter); + } + + function create($parameter) { + $model = &$this->getDefaultModel(); + $model->user_id = (int) $this->_auth->currentUserId(); + $this->flash->set('notice', 'Your preference has been saved.'); + return parent::create($parameter); + } + + function getSettingDescription($setting) { + switch ($setting) { + case SETTINGS_EDITOR: + $ret = 'WYSIWYG Editor
    Choose whether you want the editor to be active for you or not.'; + break; + } + return $ret; + } +} +?> diff --git a/app/controllers/site_admin_controller.php b/app/controllers/site_admin_controller.php new file mode 100644 index 0000000..9d36b9b --- /dev/null +++ b/app/controllers/site_admin_controller.php @@ -0,0 +1,201 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class SiteAdminController extends nterchangeController { + function __construct() { + if (get_class($this) == __CLASS__) { + $this->name = 'site_admin'; + // login required + $this->login_required = true; + // set user level allowed to access the actions with required login + $this->user_level_required = N_USER_NORIGHTS; + // set up view caching values + $this->view_cache_name = 'nterchange_site_admin'; + $this->view_caching = true; + $this->view_cache_lifetime = -1; // forever + } + parent::__construct(); + } + + function index() { + $this->nterchange = true; + $this->auto_render = false; + // preset layout values + $main_content = null; + $sidebar = null; + $this->view_cache_name = 'nterchange_site_admin_' . $this->_auth->currentUserID(); + // check if it's currently being built, if so, wait so you can use the cached version + // this protects against multiple people building the site admin at once + $buildfile = CACHE_DIR . '/ntercache/siteadminbuild'; + // if the menu is being built, then wait quarter second and try again. + $wait = 0; + while (1==1) { + if (!file_exists($buildfile) || $this->isCachedLayout('default') || time() - filemtime($buildfile) > 8) { + if ($wait > 0 && defined('LOG_CACHE') && LOG_CACHE == true) $this->debug('Client waited for ' . number_format($wait) . ' microseconds for someone else to write ' . $this->view_cache_name); + break; + } + $wait += 250000; + usleep(250000); + } + if (!$this->isCachedLayout('default')) { + @touch($buildfile); + $this->set('user_level', $this->_auth->getAuthData('user_level')); + $this->page_title = 'Site Admin'; + $this->set(array('asset'=>$this->name, 'sitemap_list'=>$this->siteAdminList())); + $main_content = $this->render(array('return'=>true, 'action'=>'site_admin')); + @unlink($buildfile); + } + // set caching back to true before rendering as it was set to false in siteAdminList() + $this->view_caching = true; + $this->renderLayout('default', $main_content, $sidebar); + } + + function siteAdminList($id=null) { + // set view caching to false so as to not cache every item + $this->view_caching = false; + $page_ctrl = &NController::singleton('page'); + $model = &$page_ctrl->getDefaultModel(); + $model->reset(); + $pk = $model->primaryKey(); + $html = ''; + $model->parent_id = $id?(int) $id:'null'; + if ($model->find()) { + $this->set('reorder', ($id==0?false:true)); + $this->set('parent_id', $id); + $html .= $this->render(array('action'=>'site_admin_list_start', 'return'=>true)); + $i = 0; + $assigns['_referer'] = urlencode(NServer::env('REQUEST_URI')); + $pages = &$model->fetchAll(); + foreach ($pages as $page) { + $page_edit = false; + $surfedit = false; + switch ($this->_auth->getAuthData('user_level')) { + case N_USER_EDITOR: + $surfedit = true; + break; + case N_USER_ADMIN: + case N_USER_ROOT: + $page_edit = true; + $surfedit = true; + break; + } + if (SITE_WORKFLOW) { + $assigns['workflow'] = ''; + $workflow = &NController::singleton('workflow'); + if ($workflow_group_model = &$workflow->getWorkflowGroup($page)) { + $user_rights = $workflow->getWorkflowUserRights($page); + if ($user_rights & WORKFLOW_RIGHT_EDIT) { + $surfedit = true; + } + $assigns['workflow'] = $workflow_group_model->workflow_title; + } + } + $assigns['id'] = $page->$pk; + $assigns['title'] = $page->title; + $assigns['active'] = $page->active; + $assigns['visible'] = $page->visible; + $assigns['page_edit'] = $page_edit; + $assigns['surfedit'] = $surfedit; + $assigns['odd_or_even'] = $i%2 == 0?'even':'odd'; + $this->set($assigns); + $html .= $this->render(array('action'=>'sitemap_list_item', 'return'=>true)); + $i++; + $html .= $this->siteAdminList($page->$pk); + } + unset($pages); + $html .= $this->render(array('action'=>'site_admin_list_end', 'return'=>true)); + } + unset($model, $page_ctrl); + return $html; + } + + /** + * clearAllCache + * + * front-end method for clearing caches (see clearCache for the actual work) + */ + function clearAllCache() { + $this->page_title = 'Clear all caches'; + $this->auto_render = false; + $this->clearCache(); + $this->render(array('layout'=>'default')); + } + + /** + * clearCache + * + * clears the view and database caches as well as CDN cache if applicable + */ + function clearCache() { + $this->view_cache_name = 'clear_all_cache'; + $this->view_caching = false; + $view = &NView::singleton($this); + $view->clear_all_cache(); + // Remove cache folder contents + $this->rmDirFiles(CACHE_DIR . '/templates_c'); + $this->rmDirFiles(CACHE_DIR . '/smarty_cache'); + $this->rmDirFiles(CACHE_DIR . '/ntercache'); + $this->rmDirFiles(CACHE_DIR . '/ntercache/db'); + $this->rmDirFiles(CACHE_DIR . '/ntercache/code_caller'); + $this->rmDirFiles(CACHE_DIR . '/magpie'); + + // Clear CDN cache if needed. + if (defined('CDN_CLEAR') && CDN_CLEAR) { + if (defined('CDN_TYPE')) { + $this->debug('Clearing the CDN cache'); + $cdn_file = realpath(ROOT_DIR . '/lib/cdn/' . CDN_TYPE . '.php'); + if (file_exists($cdn_file)) { + $this->debug('CDN ' . CDN_TYPE . ' exists.'); + include($cdn_file); + } + } + } + } + + function rmDirFiles($dir) { + if (!$dir) return; + $dir = preg_replace('/\/$/', '', $dir); + if (!file_exists($dir) || !is_dir($dir)) return; + if (!$dh = @opendir($dir)) return; + while (false !== ($file = readdir($dh))) { + if (preg_match('/^\./', $file)) { + continue; + } + @unlink($dir . '/' . $file); + } + closedir($dh); + return true; + } + + function deleteCache() { + $auth_model = &NModel::factory('cms_auth'); + if ($auth_model->find()) { + $pk = $auth_model->primaryKey(); + while ($auth_model->fetch()) { + // remove the site admin cache + $this->view_cache_name = 'nterchange_site_admin_' . $auth_model->$pk; + $view = &NView::singleton($this); + $view->clearLayoutCache('default'); + } + } + unset($auth_model); + unset($view); + } +} +?> diff --git a/app/controllers/test_sample_controller.php b/app/controllers/test_sample_controller.php new file mode 100644 index 0000000..565a0cf --- /dev/null +++ b/app/controllers/test_sample_controller.php @@ -0,0 +1,29 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class TestSampleController extends AppController { + function __construct() { + $this->name = 'test_sample'; + // set user level allowed to access the actions with required login + $this->user_level_required = N_USER_ADMIN; + $this->login_required = true; + parent::__construct(); + } +} +?> \ No newline at end of file diff --git a/app/controllers/users_controller.php b/app/controllers/users_controller.php new file mode 100644 index 0000000..ee5a14f --- /dev/null +++ b/app/controllers/users_controller.php @@ -0,0 +1,207 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class UsersController extends AdminController { + function __construct() { + $this->name = 'users'; + // set user level allowed to access the actions with required login + $this->user_level_required = N_USER_NORIGHTS; + $this->login_required = true; + $this->page_title = 'Users'; + parent::__construct(); + } + + function index($parameter) { + $current_user_level = $this->_auth->getAuthData('user_level'); + if ($current_user_level < N_USER_ADMIN) { + $user_id = $this->_auth->getAuthData('id'); + $this->redirectTo('edit', $user_id); + } + $this->redirectTo('viewlist', $parameter); + } + + function viewlist($parameter) { + $current_user_level = $this->_auth->getAuthData('user_level'); + if ($current_user_level < N_USER_ADMIN) { + $this->redirectTo('index', $parameter); + } + parent::viewlist($parameter); + } + + function show($parameter) { + $this->checkUserId($parameter); + parent::show($parameter); + } + + function edit($parameter) { + $this->checkUserId($parameter); + parent::edit($parameter); + } + + function delete($parameter) { + $current_user_level = $this->_auth->getAuthData('user_level'); + if ($current_user_level < N_USER_ADMIN) { + $this->redirectTo('index', $parameter); + } + parent::delete($parameter); + } + + function checkUserId($parameter) { + $current_user_level = $this->_auth->getAuthData('user_level'); + $current_user_id = $this->_auth->getAuthData('id'); + if ($current_user_level < N_USER_ADMIN && $current_user_id != $parameter) { + $this->redirectTo('index', $parameter); + } + return true; + } + + function &getDefaultModel() { + $model = &$this->loadModel('cms_auth'); + return $model; + } + + function preGenerateForm() { + // user level - a non-root can't set someone else to be root + $model = &$this->getDefaultModel(); + $current_user_level = $this->_auth->getAuthData('user_level'); + $user_lvl = &$model->form_elements['user_level']; + if ($current_user_level >= N_USER_ROOT) { + $user_lvl[3][N_USER_ROOT] = 'root'; + } + if (!$model->{$model->primaryKey()}) { + $model->form_required_fields[] = 'password'; + } + parent::preGenerateForm(); + } + + function postGenerateForm(&$form) { + $model = &$this->getDefaultModel(); + $current_user_level = $this->_auth->getAuthData('user_level'); + // empty the password field manually + $password = &$form->getElement('password'); + $password->setValue(''); + // turn status on by default + // $status = &$form->getElement('status'); + // $status->setChecked(true); + // put in confirmation password field + $form->insertElementBefore(NQuickForm::createElement('password', 'confirm_password', 'Confirm Password'), 'user_level'); + if ($model->{$model->primaryKey()}) { + $password->setLabel('Current Password'); + $form->insertElementBefore(NQuickForm::createElement('password', 'new_password', 'New Password'), 'confirm_password'); + $form->addRule(array('new_password', 'confirm_password'), 'The passwords do not match', 'compare'); + $form->addRule('new_password', 'The new password must be at least 8 characters long and contain upper and lower case characters and a number.', 'minlength', 8, 'client'); + $form->addRule('new_password', 'The new password must be at least 8 characters long and contain upper and lower case characters and a number.', 'regex', '/[A-Z]/', 'client'); + $form->addRule('new_password', 'The new password must be at least 8 characters long and contain upper and lower case characters and a number.', 'regex', '/[a-z]/', 'client'); + $form->addRule('new_password', 'The new password must be at least 8 characters long and contain upper and lower case characters and a number.', 'regex', '/[0-9]/', 'client'); + $password = &$form->removeElement('password'); + if ($current_user_level < N_USER_ADMIN) { + $form->insertElementBefore($password, 'new_password'); + $password->setValue(''); + $form->addFormRule(array(&$this, 'validateEdit')); + $form->removeElement('user_level'); + } + } else { + $form->addRule('password', 'That is not the correct password', 'callback', array(&$this, 'checkPassword')); + $form->addRule(array('password', 'confirm_password'), 'The passwords do not match', 'compare'); + } + parent::postGenerateForm($form); + } + + function preProcessForm(&$values) { + $current_user_level = $this->_auth->getAuthData('user_level'); + if ($current_user_level >= N_USER_ADMIN && isset($values['new_password']) && $values['new_password']) { + $values['password'] = md5($values['new_password']); + } else { + if (isset($values['password']) && isset($values['new_password']) && $values['new_password']) { + $values['password'] = md5($values['new_password']); + } else if (isset($values['password']) && isset($values['new_password']) && !$values['new_password']) { + $values['password'] = null; + } else if (!$values['id']) { + $values['password'] = md5($values['password']); + } + } + parent::preProcessForm($values); + } + + function validateEdit($values) { + $model = &$this->getDefaultModel(); + $errors = array(); + if (isset($values['new_password'])) { + if ($values['new_password'] && !$values['password']) { + $errors['password'] = 'You must type in the current password in order to change it.'; + } else if ($values['new_password'] && $values['password']) { + if ($model->password != md5($values['password'])) { + $errors['password'] = 'That is not the correct password'; + } + } + } + return empty($errors)?true:$errors; + } + + function loadSubnav($parameter) { + $current_user_level = $this->_auth->getAuthData('user_level'); + if ($current_user_level >= N_USER_ADMIN) { + parent::loadSubnav($parameter); + } + } + + /** + * passwordEmail - Email the passed password back to the user in $model_array['email'] + * + * @param array cms_user array + * @param string The password for the user. + * @return void + **/ + function passwordEmail($model_array, $password) { + $this->set($model_array); + $this->set('password', $password); + $this->set('public_site', PUBLIC_SITE); + + // set up and send the email + $email_message = $this->render(array('action'=>'password_email', 'return'=>true)); + $email_from = 'website@' . $_SERVER['SERVER_NAME']; + $email_to = $model_array['email']; + $email_subject = SITE_NAME . ' - Forgotten Password'; + mail($email_to, $email_subject, $email_message); + } + + /** + * sendConfirmationEmail - Sends a confirmation email for a password reset. + * + * @param string The email address to send the email to. + * @return void + **/ + function sendConfirmationEmail($email) { + $cms_auth = NModel::factory('cms_auth'); + if ($confirmation_token = $cms_auth->getConfirmationToken($email)) { + $this->set('confirmation_token', $confirmation_token); + $this->set('ip', $_SERVER['REMOTE_ADDR']); + $this->set('public_site', PUBLIC_SITE); + + // set up and send the email + $email_message = $this->render(array('action'=>'confirmation_email', 'return'=>true)); + $email_from = 'website@' . $_SERVER['SERVER_NAME']; + $email_to = $email; + $email_subject = SITE_NAME . ' - Confirm Password Reset'; + mail($email_to, $email_subject, $email_message); + } + } + +} +?> \ No newline at end of file diff --git a/app/controllers/version_check_controller.php b/app/controllers/version_check_controller.php new file mode 100644 index 0000000..1c19917 --- /dev/null +++ b/app/controllers/version_check_controller.php @@ -0,0 +1,109 @@ + + * @copyright 2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + * @since 3.1.12 + */ +class VersionCheckController extends AssetController { + var $check_version_url = 'https://raw.githubusercontent.com/nonfiction/nterchange/master/version.yml'; + var $check_version_interval = 86400; + var $cache_name = 'version_check'; + var $cache_group = 'vcheck'; + + function __construct() { + $this->name = 'version_check'; + $this->base_view_dir = ROOT_DIR; + parent::__construct(); + } + + /** + * versionCheck - Get the most current version of nterchange and cache the result. + * + * @return array Information about the newest version of nterchange. + **/ + function versionCheck() { + require_once 'Cache/Lite.php'; + $options = array('cacheDir'=>CACHE_DIR . '/ntercache/', 'lifeTime'=>$this->check_version_interval); + $cache = new Cache_Lite($options); + $yaml = $cache->get($this->cache_name, $this->cache_group); + if (empty($yaml)) { + include_once 'HTTP/Request.php'; + $req = new HTTP_Request($this->check_version_url); + if (!PEAR::isError($req->sendRequest())) { + $yaml = $req->getResponseBody(); + $cached = $cache->save($yaml, $this->cache_name, $this->cache_group); + if ($cached == true) { + NDebug::debug('Version check - data is from the web and is now cached.' , N_DEBUGTYPE_INFO); + } else { + NDebug::debug('Version check - data is from the web and is NOT cached.' , N_DEBUGTYPE_INFO); + } + } + } else { + NDebug::debug('Version check - data is from the cache.' , N_DEBUGTYPE_INFO); + } + require_once 'vendor/spyc.php'; + $newest_version_info = @Spyc::YAMLLoad($yaml); + return $newest_version_info; + } + + /** + * compareVersions - Compares the current nterchange version to the newest version. + * + * @param string Current version of nterchange. + * @param string New version of nterchange. + * @return boolean + **/ + function compareVersions($current, $new) { + $comparison = version_compare($current, $new); + if ($comparison == -1) { + return true; + } else { + return false; + } + } + + /** + * dashboardVersionCheck - This runs for ADMIN users or higher and lets them know + * if there is an upgrade available for nterchange. Called from the dashboard + * helper and displays on the dashboard. + * + * @return void + **/ + function dashboardVersionCheck() { + // Check the user level - this only shows up for admins or higher. + $auth = new NAuth(); + $current_user_level = $auth->getAuthData('user_level'); + unset($auth); + if ($current_user_level >= N_USER_ADMIN) { + $newest = $this->versionCheck(); + if (is_array($newest)) { + $upgrade = $this->compareVersions(NTERCHANGE_VERSION, $newest['version']); + if ($upgrade == true) { + $this->set('upgrade', $newest); + $this->set('nterchange_version', NTERCHANGE_VERSION); + } else { + $this->set('uptodate', true); + } + $this->render(array('action'=>'dashboard_version_check', 'return'=>false)); + } else { + NDebug::debug('There was an error with the version check.' , N_DEBUGTYPE_INFO); + } + } + } + +} +?> diff --git a/app/controllers/version_controller.php b/app/controllers/version_controller.php new file mode 100644 index 0000000..28d9221 --- /dev/null +++ b/app/controllers/version_controller.php @@ -0,0 +1,219 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class VersionController extends nterchangeController { + function __construct() { + $this->name = 'version'; + // set user level allowed to access the actions with required login + $this->user_level_required = N_USER_NORIGHTS; + $this->public_actions = array('view', 'reinstate'); + $this->login_required = true; + parent::__construct(); + } + + function &getDefaultModel() { + return $this->loadModel('cms_nterchange_versions'); + } + + function view($parameter) { + if ($model = &$this->getDefaultModel() && $model->get($parameter)) { + $this->set('asset', unserialize($model->version)); + } + } + + /** + * reinstate - Pull an old version of a content asset back and insert it as the current version. + * + * @param int Version id you want reinstated. + * @return void + **/ + function reinstate($parameter) { + // pull the version and save the content into the asset record + if ($model = &$this->getDefaultModel() && $model->get($parameter)) { + $version = unserialize($model->version); + $asset_controller = &NController::factory($model->asset); + $asset_controller->_auth = &$this->_auth; + $asset_model = &$asset_controller->getDefaultModel(); + if ($asset_controller && $asset_model && $asset_model->get($model->asset_id)) { + foreach ($version as $k=>$v) { + if (!preg_match('/^cms_/', $k) && $k != 'id') { + $asset_model->$k = $v; + } + } + // insert a new version as part of the process + $asset_controller->insertVersion(); + // save the new record + $asset_model->save(); + } + unset($asset_model); + $this->flash->set('notice', 'The version has been reinstated.'); + $referer = isset($this->params['_referer'])?$this->params['_referer']:false; + if (!$referer) { + include_once 'view/helpers/url_helper.php'; + $referer = urlHelper::urlFor($this, array('controller'=>$model->asset, 'action'=>'edit', 'id'=>$model->asset_id)); + } + header('Location:' . $referer); + exit; + } + } + + /** + * fileDelete - Delete a file from an old version - but only if it's not available + * in the current version. + * + * @param array An unserialized array from cms_nterchange_versions->version + * @param string The name of an asset + * @param int The id of the asset. + * @return boolean + * @todo Make this work with n_mirror. + **/ + function fileDelete($array, $asset, $asset_id) { + $current_version = $this->getCurrentVersion($asset, $asset_id); + if (!$current_version) return false; + foreach ($array as $field) { + $ereg = '^' . UPLOAD_DIR; + if (eregi($ereg, $field)) { + // Check to see whether or not the file can be deleted. + // If it was uploaded in a previous version, but is still available in the + // current version, we don't want to delete it. + if (in_array($field, $current_version)) { + NDebug::debug('Cannot delete ' . $field . ' as it is in the current version.' , N_DEBUGTYPE_INFO); + } else { + $ret = NFilesystem::deleteFile($field); + } + } + } + return $ret; + } + + /** + * deleteEmptyFolders - Delete folders without anything in them anymore. + * + * @param string The name of the asset. + * @param int The id of that asset. + * @return void + * @todo Make this work with n_mirror. + **/ + function deleteEmptyFolders($asset_name, $asset_id) { + $folder = DOCUMENT_ROOT . UPLOAD_DIR . '/' . $asset_name . '/' . $asset_id; + if (is_dir($folder)) { + if ($handle = opendir($folder)) { + while (false !== ($file = readdir($handle))) { + if ($file != "." && $file != "..") { + if (is_dir($folder . '/' . $file)) { + $full_path = $folder . '/' . $file; + // Check to see if it's empty. + if (count(glob("$full_path/*")) === 0) { + // Then delete if this is so. + NFilesystem::deleteFolder($full_path); + } else { + NDebug::debug("$full_path is not empty and will not be deleted." , N_DEBUGTYPE_INFO); + } + + } + } + } + closedir($handle); + } + } + } + + /** + * getCurrentVersion - Get the current version of the $asset referenced by $asset_id + * + * @param string The name of the asset. + * @param int The id of that asset. + * @return array All the content in that asset. + **/ + function getCurrentVersion($asset, $asset_id) { + $asset_object = NModel::factory($asset); + $asset_object->id = $asset_id; + if ($asset_object->find()) { + while ($asset_object->fetch()) { + $arr = $asset_object->toArray(); + return $arr; + } + } else { + return false; + } + } + + /** + * deleteAll - Delete all old versions of a particular asset. + * This comprises all files and empty folders as well. + * + * @param int The id of this particular version. + * @return void + **/ + function deleteAll($parameter) { + if ($model = &$this->getDefaultModel() && $model->get($parameter)) { + $info = $model->toArray(); + $model->reset(); + // Let's get all the versions for that asset and asset_id. + $model->asset_id = $info['asset_id']; + $model->asset = $info['asset']; + $this->debug("Deleting versions for {$model->asset} : {$model->asset_id}"); + if ($model->find()) { + while ($model->fetch()) { + $arr = $model->toArray(); + $content = unserialize($arr['version']); + $success = $this->fileDelete($content, $info['asset'], $info['asset_id']); + $model->delete(); + } + } + $this->deleteEmptyFolders($info['asset'], $info['asset_id']); + if (defined('SITE_AUDIT_TRAIL') && SITE_AUDIT_TRAIL) { + $audit_trail = &NController::factory('audit_trail'); + $audit_trail->insert(array('asset'=>$info['asset'], 'asset_id'=>$info['asset_id'], 'action_taken'=>AUDIT_ACTION_DELETE_ASSET_VERSIONS)); + unset($audit_trail); + } + header('Location:' . $_GET['_referer']); + } + } + + /** + * deleteEverything - Delete all old versions of everything. Used just before + * website launch or when somebody just wants to clean up. + * NOTE: Not linked to from anywhere or really heavily tested. Use with caution. + * + * @return void + **/ + function deleteEverything($parameter) { + if ($model = &$this->getDefaultModel()) { + if ($model->find()) { + while ($model->fetch()) { + $arr = $model->toArray(); + $content = unserialize($arr['version']); + $success = $this->fileDelete($content, $arr['asset'], $arr['asset_id']); + $this->deleteEmptyFolders($arr['asset'], $arr['asset_id']); + $model->delete(); + } + // Let's empty out the entire table as well. + $sql = 'TRUNCATE cms_nterchange_versions'; + $db = NDB::connect(); + $res = $db->query($sql); + } else { + NDebug::debug('There were no old versions of anything to delete.' , N_DEBUGTYPE_INFO); + } + header('Location:/nterchange/'); + } + } +} +?> diff --git a/app/controllers/workflow_controller.php b/app/controllers/workflow_controller.php new file mode 100644 index 0000000..8988b8f --- /dev/null +++ b/app/controllers/workflow_controller.php @@ -0,0 +1,912 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class WorkflowController extends nterchangeController { + var $workflow_users = array(); + + function __construct() { + $this->name = 'workflow'; + // set user level allowed to access the actions with required login + $this->user_level_required = N_USER_NORIGHTS; + // this whole controller requires login if called directly + $this->login_required = true; + $this->base_dir = APP_DIR; + parent::__construct(); + } + + function index() { + $this->redirectTo(array('dashboard')); + } + + function viewlist() { + $this->redirectTo(array('dashboard')); + } + + function process($workflow_id) { + $this->auto_render = false; + $model = &$this->getDefaultModel(); + $model->completed = 0; + // get the workflow info + if (!$model->get($workflow_id)) { + $this->redirectTo('index'); + } + // push to the client's time zone + $this->convertDateTimesToClient($model); + // load the workflow group + $workflow_group = &$model->getLink('workflow_group_id', 'workflow_group'); + // get the asset info for the email + $asset_ctrl = &NController::factory($model->asset); + $asset_model = &$asset_ctrl->getDefaultModel(); + if(!$asset_ctrl || !$asset_model->get($model->asset_id)) { + $this->redirectTo('index'); + } + $asset_name = $asset_ctrl->page_title?$asset_ctrl->page_title:Inflector::humanize($asset_ctrl->name); + // load the workflow draft into the asset_model for the form + $workflow_values = unserialize($model->draft); + foreach ($workflow_values as $field=>$val) { + $asset_model->$field = $val; + } + // check for the content being linked to any other pages + $page_content_model = &NModel::factory('page_content'); + $page_contents = &$page_content_model->getActivePageContent($asset_ctrl->name, $asset_model->{$asset_model->primaryKey()}); + $pages = false; + if ($model->action == WORKFLOW_ACTION_EDIT && $page_contents && count($page_contents) > 1) { + $pages = array(); + $tmp_page_model = clone($page_model); + foreach ($page_contents as $page_content) { + if (!isset($pages[$tmp_page_model->{$tmp_page_model->primaryKey()}])) { + $tmp_page_model->reset(); + $tmp_page_model->get($page_content->page_id); + $pages[$tmp_page_model->{$tmp_page_model->primaryKey()}] = $tmp_page_model->toArray(); + } + } + if (count($pages) == 1) { + $pages = false; + } + unset($tmp_page_model); + } + unset($page_contents); + $this->set('pages', $pages); + unset($pages); + // get the page info for the email + $page_content_model = &$model->getLink('page_content_id', 'page_content'); + $page = &NController::singleton('page'); + $page_model = $page->getDefaultModel(); + if (!$page_model->get($page_content_model->page_id)) { + $this->redirectTo('index'); + } + // set up urls + $public_site = preg_replace('|/$|', '', PUBLIC_SITE); + $admin_site = preg_replace('|/$|', '', (defined('ADMIN_URL') && ADMIN_URL?ADMIN_URL:PUBLIC_SITE)); + $live_url = $public_site . $page->getHref($page_model->toArray()); + $page->nterchange = true; + $preview_url = $admin_site . $page->getHref($page_model->toArray()); + // user rights + $user_rights = &$this->getWorkflowUserRights($page_model); + if ($user_rights & WORKFLOW_RIGHT_EDIT && !($user_rights & WORKFLOW_RIGHT_APPROVE)) { + // only an author, can't approve anything + $this->redirectTo('index'); + } + $description = ''; + switch ($model->action) { + case WORKFLOW_ACTION_EDIT: + $description = 'This content is being edited on the page.'; + break; + case WORKFLOW_ACTION_DELETE: + $description = 'This content is being deleted.'; + break; + case WORKFLOW_ACTION_ADDNEW: + $description = 'This is new content being added to the page.'; + break; + case WORKFLOW_ACTION_ADDEXISTING: + $description = 'This is existing content being added to the page.'; + break; + case WORKFLOW_ACTION_REMOVE: + $description = 'The content is being removed from the page.'; + break; + } + $this->set('description', $description); + // set up the form + $cform = new ControllerForm($asset_ctrl, $asset_model); + $form = &$cform->getForm(); + if (SITE_DRAFTS) { + // remove the submit draft button since we're in workflow + $form->removeElement('__submit_draft__'); + } + // remove the submit button since we're in workflow + $form->removeElement('__submit__'); + // get the workflow form + $wcform = new ControllerForm($this, $model); + $wform = &$wcform->getForm(); + $submit = &$wform->getElement('__submit__'); + $submit->setName('__submit_workflow__'); + if ($user_rights & WORKFLOW_RIGHT_PUBLISH) { + $submit->setValue('Submit & Publish'); + } else { + $submit->setValue('Submit'); + } + // add workflow form to the existing form + foreach ($wform->_elements as $el) { + $form->addElement($el); + } + $form->addFormRule(array(&$this, 'validateWorkflowProcess')); + /* + if (!($user_rights & WORKFLOW_RIGHT_EDIT)) { + $fields = $asset_model->fields(); + foreach ($fields as $i=>$field) { + if ($form->elementExists($field)) { + $el = &$form->getElement($field); + $el->freeze(); + } + } + } + */ + if ($model->action == WORKFLOW_ACTION_REMOVE) { + $fields = $asset_model->fields(); + $form->removeElement('timed_start'); + $form->removeElement('timed_end'); + $form->freeze($fields); + } + + // act on the submission + if ($form->validate()) { + $values = $form->getSubmitValues(); + $model->comments = $values['comments']; + $fields = $asset_model->fields(); + $draft_values = array(); + foreach ($fields as $field) { + if (isset($values[$field])) + $draft_values[$field] = $values[$field]; + } + $auth = new NAuth(); + $user_id = $auth->currentUserID(); + unset($auth); + + if ($values['workflow_approve'] == 0) { + // if not approved, then email the original user and set the workflow unsubmitted + if ($parent_workflow = $model->parent_workflow) { + $model->delete(); + $model->reset(); + $model->get($parent_workflow); + $model->approved = 0; + } else { + $model->submitted = 0; + } + if (isset($draft_values)) { + $model->draft = serialize($draft_values); + } + $model->comments = $values['comments']; + include_once 'n_date.php'; + $model->cms_created = NDate::convertTimeToUTC($model->cms_created, '%Y-%m-%d %H:%M:%S'); + $model->cms_modified = NDate::convertTimeToUTC($model->cms_modified , '%Y-%m-%d %H:%M:%S'); + $model->update(); + $current_user = &NModel::factory('cms_auth'); + $current_user->get($user_id); + $user_model = &NModel::factory('cms_auth'); + $user_model->get($model->cms_modified_by_user); + include_once 'Mail.php'; + $mail = &Mail::factory('mail', "-f{$current_user->email}"); + $headers['From'] = "{$current_user->real_name} <{$current_user->email}>"; + $headers['Subject'] = 'Website: "' . $workflow_group->workflow_title . '" Workflow Group has content that was declined'; + $msg = ''; + $msg .= "The workflow for the \"{$asset_model->cms_headline}\" {$asset_name} record on the {$page_model->title} page was declined.\n\n"; + $msg .= "COMMENTS:\n{$model->comments}\n\n"; + $msg .= "You can view the current live page at:\n$live_url\n\n"; + $msg .= "You can preview the page at:\n$preview_url\n\n"; + $msg .= "To Edit & Resubmit your changes, please go to Your Dashboard:\n" . $admin_site . '/' . APP_DIR . "/dashboard\n\n"; + $this->set('public_site', $public_site); + $this->set('admin_site', $admin_site); + // gather the users + $recipients = array(); + $email = "{$user_model->real_name} <{$user_model->email}>"; + $recipients[] = $email; + $mail->send($recipients, $headers, $msg); + unset($mail); + if (defined('SITE_AUDIT_TRAIL') && SITE_AUDIT_TRAIL) { + // audit trail + $audit_trail = &NController::factory('audit_trail'); + $audit_trail->insert(array('asset'=>$model->asset, 'asset_id'=>$model->asset_id, 'action_taken'=>AUDIT_ACTION_WORKFLOW_DECLINE, 'workflow_id'=>$model->{$model->primaryKey()}, 'workflow_group_id'=>$model->workflow_group_id, 'page_id'=>$model->page_id, 'page_content_id'=>$model->page_content_id)); + unset($audit_trail); + } + $this->render(array('layout'=>'plain', 'action'=>'disapproved')); + exit; + } else { + // if approved, then set any comments, set the workflow approved, insert a new one + // either submit it (which emails it to the next users) + // or publish it (if there are no next users) + if ($user_rights & WORKFLOW_RIGHT_PUBLISH) { + // publish by pulling the draft, updating the original asset and marking page_content.cms_workflow=0 + if (isset($draft_values)) { + foreach ($draft_values as $field=>$val) { + $asset_model->$field = $val; + } + } + $asset_model->cms_modified = $asset_model->now(); + $asset_model->cms_modified_by_user = $user_id; + $asset_model->cms_draft = 0; + $asset_model->update(); + // kill a draft if one exists + $workflow_model = &NModel::factory('workflow'); + $workflow_model->parent_workflow = 0; + $workflow_model->asset = $model->asset; + $workflow_model->asset_id = $model->asset_id; + $workflow_model->workflow_group_id = $model->workflow_group_id; + if ($workflow_model->find(null, true)) { + // delete drafts related to this workflow + $draft_model = &NModel::factory('cms_drafts'); + $draft_model->asset = $model->asset; + $draft_model->asset_id = $model->asset_id; + $draft_model->cms_modified_by_user = $workflow_model->cms_modified_by_user; + if ($draft_model->find()) { + while ($draft_model->fetch()) { + $draft_model->delete(); + } + } + } + if ($workflow_model->action == WORKFLOW_ACTION_REMOVE) { + // delete the page_content to detach + if ($page_content_model->{$page_content_model->primaryKey()}) { + $page_content_model->delete(); + } + unset($page_content_model); + $page->deletePageCache($model->page_id); + if (defined('SITE_AUDIT_TRAIL') && SITE_AUDIT_TRAIL) { + // audit trail + $audit_trail = &NController::factory('audit_trail'); + $audit_trail->insert(array('asset'=>$model->asset, 'asset_id'=>$model->asset_id, 'action_taken'=>AUDIT_ACTION_WORKFLOW_APPROVEREMOVE, 'workflow_id'=>$model->{$model->primaryKey()}, 'workflow_group_id'=>$model->workflow_group_id, 'page_id'=>$model->page_id, 'page_content_id'=>$model->page_content_id)); + unset($audit_trail); + } + $this->completeWorkflow($workflow_id); + $this->set('workflow_group', $workflow_group->toArray()); + $this->set('asset_name', $asset_name); + $this->set('asset', $asset_model->toArray()); + $this->set('page', $page_model->toArray()); + $this->render(array('action'=>'removed', 'layout'=>'default')); + exit; + } else { + // update the page_content row + if ($page_content_model->{$page_content_model->primaryKey()}) { + $timed_start = NDate::arrayToDate($values['timed_start']); + $timed_end = NDate::arrayToDate($values['timed_end']); + if (!NDate::validDateTime($timed_start)) { + $timed_start = 'null'; + } + if (!NDate::validDateTime($timed_end)) { + $timed_end = 'null'; + } + // set the timed content in page_content + $page_content_model->timed_start = $timed_start; + $page_content_model->timed_end = $timed_end; + // set page_content cms_workflow to 0, allowing the content to show up + $page_content_model->cms_workflow = 0; + $page_content_model->update(); + } + unset($page_content_model); + $this->completeWorkflow($workflow_id); + $page->deletePageCache($page_model->{$page_model->primaryKey()}); + if (defined('SITE_AUDIT_TRAIL') && SITE_AUDIT_TRAIL) { + // audit trail + $audit_trail = &NController::factory('audit_trail'); + $audit_trail->insert(array('asset'=>$model->asset, 'asset_id'=>$model->asset_id, 'action_taken'=>AUDIT_ACTION_WORKFLOW_APPROVEPUBLISH, 'workflow_id'=>$model->{$model->primaryKey()}, 'workflow_group_id'=>$model->workflow_group_id, 'page_id'=>$model->page_id, 'page_content_id'=>$model->page_content_id)); + unset($audit_trail); + } + $this->set('workflow_group', $workflow_group->toArray()); + $this->set('asset_name', $asset_name); + $this->set('asset', $asset_model->toArray()); + $this->set('page', $page_model->toArray()); + $this->render(array('action'=>'published', 'layout'=>'default')); + exit; + } + } else { + $model->approved = 1; + $model->comments = $values['comments']; + $timed_start = isset($values['timed_start'])?NDate::arrayToDate($values['timed_start']):null; + $timed_end = isset($values['timed_end'])?NDate::arrayToDate($values['timed_end']):null; + if (!NDate::validDateTime($timed_start)) { + $timed_start = 'null'; + } + if (!NDate::validDateTime($timed_end)) { + $timed_end = 'null'; + } + $model->timed_start = $timed_start; + $model->timed_end = $timed_end; + include_once 'n_date.php'; + $model->cms_created = NDate::convertTimeToUTC($model->cms_created, '%Y-%m-%d %H:%M:%S'); + $model->cms_modified = NDate::convertTimeToUTC($model->cms_modified , '%Y-%m-%d %H:%M:%S'); + $model->update(); + $parent_workflow = $model->{$model->primaryKey()}; + $new_workflow = &NModel::factory($this->name); + $new_workflow->page_id = $model->page_id; + $new_workflow->page_content_id = $model->page_content_id; + $new_workflow->workflow_group_id = $model->workflow_group_id; + $new_workflow->asset = $model->asset; + $new_workflow->asset_id = $model->asset_id; + $new_workflow->action = $model->action; + $new_workflow->draft = serialize($draft_values); + $new_workflow->comments = $values['comments']; + $new_workflow->timed_start = $timed_start; + $new_workflow->timed_end = $timed_end; + $new_workflow->parent_workflow = $parent_workflow; + $new_workflow->cms_created = $new_workflow->now(); + $new_workflow->cms_modified = $new_workflow->now(); + $new_workflow->cms_modified_by_user = $user_id; + $new_workflow->insert(); + if (defined('SITE_AUDIT_TRAIL') && SITE_AUDIT_TRAIL) { + // audit trail + $audit_trail = &NController::factory('audit_trail'); + $audit_trail->insert(array('asset'=>$model->asset, 'asset_id'=>$model->asset_id, 'action_taken'=>AUDIT_ACTION_WORKFLOW_APPROVE, 'workflow_id'=>$model->{$model->primaryKey()}, 'workflow_group_id'=>$model->workflow_group_id, 'page_id'=>$model->page_id, 'page_content_id'=>$model->page_content_id)); + unset($audit_trail); + } + $this->flash->set('notice', 'Your workflow step has been submitted and notifications have been sent.'); + $this->redirectTo('submit', $new_workflow->{$new_workflow->primaryKey()}); + } + } + } + unset($page_content_model); + // set up the view + $this->set('workflow_group', $workflow_group->toArray()); + $this->set('asset_name', $asset_name); + $this->set('asset', $asset_model->toArray()); + $this->set('page', $page_model->toArray()); + $this->set('form', $form->toHTML()); + $this->render(array('layout'=>'plain', 'action'=>'process')); + } + + function validateWorkflowProcess($values) { + $errors = array(); + if ($values['workflow_approve'] == 0 && !$values['comments']) { + $errors['comments'] = 'You must supply comments if you do not approve the workflow'; + } + return count($errors)?$errors:true; + } + + function completeWorkflow($workflow_id) { + if (!$workflow_id) return; + $model = &NModel::factory($this->name); + if ($model->get($workflow_id)) { + $parent_workflow = $model->parent_workflow; + $model->approved = 1; + $model->completed = 1; + $model->update(); + $this->completeWorkflow($parent_workflow); + } + unset($model); + return true; + } + + function submit($workflow_id) { + if (false !== strpos($workflow_id, ';')) { + $workflow_id = explode(';', $workflow_id); + } else { + $workflow_id = array($workflow_id); + } + $this->auto_render = false; + $model = &$this->getDefaultModel(); + $pk = $model->primaryKey(); + // get the workflow info + $workflows = array(); + foreach ($workflow_id as $id) { + $model->reset(); + $model->submitted = 0; + if ($model->get($id)) { + $this->convertDateTimesToClient($model); + $workflows[] = clone($model); + } + } + if (empty($workflows)) { + $this->redirectTo('index'); + } + $html = ''; + foreach ($workflows as $model) { + // push the times back so they can get pushed forward again on update() + // get the asset info for the email + $asset_ctrl = &NController::factory($model->asset); + $asset_model = &NModel::factory($model->asset); + if(!$asset_ctrl || !$asset_model->get($model->asset_id)) { + $this->redirectTo('index'); + } + $asset_name = $asset_ctrl->page_title?$asset_ctrl->page_title:Inflector::humanize($asset_ctrl->name); + // get the page info for the email + $page_content_model = $workflows[0]->getLink('page_content_id', 'page_content'); + $page = &NController::singleton('page'); + $page_model = &$page->getDefaultModel(); + $page_model->reset(); + if (!$page_model->get($page_content_model->page_id)) { + $this->redirectTo('index'); + } + $live_url = preg_replace('/\/$/', '', PUBLIC_SITE) . $page->getHref($page_model->toArray()); + $page->nterchange = true; + $preview_url = preg_replace('/\/$/', '', (defined('ADMIN_URL') && ADMIN_URL?ADMIN_URL:PUBLIC_SITE)) . $page->getHref($page_model->toArray()); + $dashboard_url = preg_replace('/\/$/', '', (defined('ADMIN_URL') && ADMIN_URL?ADMIN_URL:PUBLIC_SITE)) . '/' . APP_DIR . '/dashboard'; + $auth = new NAuth(); + $user_model = &NModel::factory('cms_auth'); + $user_model->get($auth->currentUserId()); + unset($auth); + $workflow_group = &$workflows[0]->getLink('workflow_group_id', 'workflow_group'); + // get the users + $user_rights = $this->getWorkflowUserRights($page_model, $user_model->{$user_model->primaryKey()}); + $users = $this->getNotifyUsers($model->$pk, $user_rights); + +/* +varDump('###################'); +varDump($user_rights); +foreach ($users as $user) { + varDump($user->toArray()); +} +exit; +*/ + + include_once 'Mail.php'; + $mail = &Mail::factory('mail', "-f{$user_model->email}"); + $headers['From'] = "{$user_model->real_name} <{$user_model->email}>"; + $headers['Subject'] = 'Website: "' . $workflow_group->workflow_title . '" Workflow Group has content waiting for your approval'; + // $headers['To'] = ''; + $msg = ''; + $msg .= "The workflow for the \"{$asset_model->cms_headline}\" {$asset_name} record on the {$page_model->title} page is awaiting your approval.\n\n"; + if ($model->comments) { + $msg .= "COMMENTS:\n{$model->comments}\n\n"; + } + $msg .= "You can view the current live page at:\n$live_url\n\n"; + $msg .= "You can preview the page at:\n$preview_url\n\n"; + $msg .= "To Approve/Decline the changes, please go to Your Dashboard:\n" . $dashboard_url; + // gather the users + $user_array = array(); + $recipients = array(); + foreach ($users as $user) { + if ($user->{$user->primaryKey()} == $user_model->{$user_model->primaryKey()}) continue; + $email = "{$user->real_name} <{$user->email}>"; + $recipients[] = $email; + // $headers['To'] .= ($headers['To']?', ':'') . $email; + $user_array[] = $user->toArray(); + } + if (!empty($recipients)) { + $mail->send($recipients, $headers, $msg); + } + unset($mail); + // update the workflow and set submitted to true + $model->submitted = 1; + include_once 'n_date.php'; + $model->cms_created = NDate::convertTimeToUTC($model->cms_created, '%Y-%m-%d %H:%M:%S'); + $model->cms_modified = NDate::convertTimeToUTC($model->cms_modified , '%Y-%m-%d %H:%M:%S'); + $model->update(); + if (defined('SITE_AUDIT_TRAIL') && SITE_AUDIT_TRAIL) { + // audit trail + $audit_trail = &NController::factory('audit_trail'); + $audit_trail->insert(array('asset'=>$model->asset, 'asset_id'=>$model->asset_id, 'action_taken'=>AUDIT_ACTION_WORKFLOW_SUBMIT, 'workflow_id'=>$model->{$model->primaryKey()}, 'workflow_group_id'=>$model->workflow_group_id, 'page_id'=>$model->page_id, 'page_content_id'=>$model->page_content_id)); + unset($audit_trail); + } + // set up the view + $this->set('asset_name', $asset_name); + $this->set('asset', $asset_model->toArray()); + $this->set('workflow_group', $workflow_group->toArray()); + $this->set('page', $page_model->toArray()); + $this->set('users', $user_array); + $html .= $this->render(array('action'=>'send', 'return'=>true)); + } + $this->set('MAIN_CONTENT', $html); + $this->render(array('layout'=>'default')); + } + + function actionToString($action) { + switch ($action) { + case WORKFLOW_ACTION_ADDEXISTING: + $action = 'added'; + break; + case WORKFLOW_ACTION_ADDNEW: + $action = 'created and added'; + break; + case WORKFLOW_ACTION_REMOVE: + $action = 'removed'; + break; + case WORKFLOW_ACTION_EDIT: + $action = 'edited'; + break; + case WORKFLOW_ACTION_DELETE: + $action = 'deleted'; + break; + } + return $action; + } + + function getNotifyUsers($workflow_id, $user_rights) { + $model = &NModel::factory($this->name); + $pk = $model->primaryKey(); + if ($model->get($workflow_id)) { + $page_model = &$model->getLink('page_id', 'page'); + $model_count = clone($model); + $model_count->reset(); + $parent_workflow = $model->parent_workflow?$model->parent_workflow:$workflow_id; + $workflow_steps = array(); + if ($model_count->find(array('conditions'=>$pk . '=' . $parent_workflow . ' OR parent_workflow=' . $parent_workflow))) { + $workflow_steps = &$model_count->fetchAll(); + } + // we need to figure out who to email to... + $notify_users = array(); + if ($page_model = &$model->getLink('page_id', 'page')) { + $user_model = &NModel::factory('cms_auth'); + $pk = $user_model->primaryKey(); + // + $users = array(); + $workflow_user = &NModel::factory('workflow_users'); + $workflow_user->workflow_group_id = $model->workflow_group_id; + $auth = new NAuth(); + if ($workflow_user->find()) { + $author = false; + $editor = false; + $approver = false; + while ($workflow_user->fetch()) { + if ($user_model->get($workflow_user->user_id)) { + switch ($workflow_user->role) { + case WORKFLOW_ROLE_AUTHOR: + $author = true; + break; + case WORKFLOW_ROLE_EDITOR: + $editor = true; + break; + case WORKFLOW_ROLE_APPROVER: + $approver = true; + break; + } + $users[] = clone($user_model); + } + $user_model->reset(); + } + foreach ($users as $user) { + $notify_user_rights = $this->getWorkflowUserRights($page_model, $user->{$user->primaryKey()}); + switch (1) { + case count($workflow_steps) == 1: + $rights_needed = WORKFLOW_RIGHT_EDIT + WORKFLOW_RIGHT_APPROVE; + if ($notify_user_rights >= $rights_needed) { + if ($author && $editor && $approver && !($notify_user_rights & WORKFLOW_RIGHT_PUBLISH)) { + $notify_users[] = $user; + } else if ((!$author || !$editor || !$approver) && $notify_user_rights & WORKFLOW_RIGHT_APPROVE) { + $notify_users[] = $user; + } + } + break; + case count($workflow_steps) == 2 && $workflow_steps[1]->approved: + $rights_needed = WORKFLOW_RIGHT_APPROVE + WORKFLOW_RIGHT_PUBLISH; + if ($notify_user_rights >= $rights_needed) { + $notify_users[] = $user; + } + break; + } + } + unset($users); + } + if (empty($notify_users) && $user_model->get($auth->currentUserId()) && $user_model->user_level >= N_USER_ADMIN) { + $notify_users[] = clone($user_model); + } + unset($user_model); + unset($page_content_model); + unset($page_model); + return $notify_users; + } + } + return false; + } + + function &getWorkflowGroup(&$page_model) { + if (!$page_model) return false; + $workflow_group_id = 0; + if ($page_model->workflow_group_id) { + // look no further, this is all you need + $workflow_group_id = $page_model->workflow_group_id; + } else { + // find the first ancestor with a workflow_group_id that is also recursive + $ancestors = $page_model->getAncestors($page_model->{$page_model->primaryKey()}, false, false); + foreach ($ancestors as $ancestor) { + if ($ancestor['workflow_group_id'] && $ancestor['workflow_recursive']) { + $workflow_group_id = $ancestor['workflow_group_id']; + break; + } + } + } + if ($workflow_group_id) { + $model = &NModel::factory('workflow_group'); + if ($model && $model->get($workflow_group_id)) { + return $model; + } + } + $model = false; + return $model; + } + + function getWorkflowUserRights(&$page_model, $user_id=null) { + $model = &NModel::factory('workflow_users'); + if (!$model) { + return false; + } + $auth = new NAuth; + if (!$user_id) { + $user_id = $auth->currentUserID(); + } + $user_model = &$this->loadModel('cms_auth'); + $user_model->get($user_id); + $rights = 0; + $workflow_group = &$this->getWorkflowGroup($page_model); + if ($workflow_group) { + $workflow_group_id = $workflow_group->{$workflow_group->primaryKey()}; + $model->workflow_group_id = $workflow_group_id; + $model->user_id = $user_id; + if ($model->find(null, true)) { + $workflow_user_model = clone($model); + $current_role = $workflow_user_model->role; + $rights = 0; + $model->reset(); + $model->workflow_group_id = $workflow_group_id; + if ($model->find()) { + $author = false; + $editor = false; + $approver = false; + while ($model->fetch()) { + switch ($model->role) { + case WORKFLOW_ROLE_AUTHOR: + $author = true; + break; + case WORKFLOW_ROLE_EDITOR: + $editor = true; + break; + case WORKFLOW_ROLE_APPROVER: + $approver = true; + break; + } + } + switch (1) { + case $current_role == WORKFLOW_ROLE_AUTHOR: + $rights = WORKFLOW_RIGHT_EDIT; + if (!$editor) { + $rights += WORKFLOW_RIGHT_APPROVE; + } + if (!$editor && !$approver) { + $rights += WORKFLOW_RIGHT_PUBLISH; + } + break; + case $current_role == WORKFLOW_ROLE_EDITOR: + $rights = WORKFLOW_RIGHT_EDIT + WORKFLOW_RIGHT_APPROVE; + if (!$approver) { + $rights += WORKFLOW_RIGHT_PUBLISH; + } + break; + case $current_role == WORKFLOW_ROLE_APPROVER: + $rights = WORKFLOW_RIGHT_APPROVE + WORKFLOW_RIGHT_PUBLISH; + break; + } + } + } + if ($user_model->user_level >= N_USER_ADMIN && !($rights & WORKFLOW_RIGHT_EDIT)) { + $rights += WORKFLOW_RIGHT_EDIT; + } + } + unset($model); + return $rights; + } + + function getWorkflowUsers($workflow_group_id) { + $model = &NModel::factory('workflow_users'); + if ($model) { + $model->workflow_group_id = $workflow_group_id; + if ($model->find()) { + return $model->fetchAll(); + } + } + return false; + } + + function getWorkflowUser($workflow_group_id) { + $model = &$this->loadModel('workflow_users'); + if ($model) { + $auth = new NAuth(); + $current_user = $auth->currentUserID(); + $model->workflow_group_id = $workflow_group_id; + $model->user_id = $current_user; + if ($model->find(null, true)) { + return $model; + } + } + return false; + } + + function findContentWorkflowGroup(&$asset_controller) { + if (!$asset_controller) return false; + $asset_model = &$asset_controller->getDefaultModel(); + $pk = $asset_model->primaryKey(); + if (!$asset_model->$pk) return false; + $page_content_model = &$asset_controller->loadModel('page_content'); + if ($page_content_model->find(array('conditions'=>'content_asset=\'' . $asset_controller->name . '\' AND content_asset_id=' . $asset_model->$pk))) { + $page_model = &$this->loadModel('page'); + while ($page_content_model->fetch()) { + // reset before every loop so the get call will work + $page_model->reset(); + if ($page_model->get($page_content_model->page_id)) { + if ($workflow_group_model = $this->getWorkflowGroup($page_model)) { + unset($page_model); + unset($page_content_model); + return $workflow_group_model; + } + } + } + unset($page_model); + } + unset($page_content_model); + return false; + } + + function findContentWorkflow($workflow_group_id, &$asset_controller) { + if (!$workflow_group_id || !$asset_controller) return false; + $asset_model = &$asset_controller->getDefaultModel(); + $pk = $asset_model->primaryKey(); + if (!$asset_model->$pk) return false; + $page_content_model = &$asset_controller->loadModel('page_content'); + $page_content_model->reset(); + if ($page_content_model->find(array('conditions'=>'content_asset=\'' . $asset_controller->name . '\' AND content_asset_id=' . $asset_model->$pk))) { + while ($page_content_model->fetch()) { + $page_model = &$page_content_model->getLink('page_id', 'page'); + if ($page_model) { + if ($workflow = &$this->getWorkflow($page_content_model->{$page_content_model->primaryKey()}, $workflow_group_id, $asset_controller)) { + unset($page_content_model); + return $workflow; + } + } + unset($page_model); + } + } + unset($page_content_model); + return false; + } + + function saveWorkflow($values, $action, &$asset_controller) { + if (!isset($values['page_content_id']) || !$values['page_content_id'] || !isset($values['workflow_group_id']) || !$values['workflow_group_id']) { + return false; + } + // instantiate workflow model + $model = &$this->getDefaultModel(); + $table = $model->table(); + // load values + $page_content_id = $values['page_content_id']; + $page_content_model = &NModel::factory('page_content'); + $page_content_model->get($page_content_id); + $page_id = (int) $page_content_model->page_id; + unset($page_content_model); + $workflow_group_id = $values['workflow_group_id']; + // timed content + $timed_start = isset($values['timed_start']) && $values['timed_start']?$values['timed_start']:null; + $timed_end = isset($values['timed_end']) && $values['timed_end']?$values['timed_end']:null; + if ($timed_start == 'null') $timed_start = null; + if ($timed_end == 'null') $timed_end = null; + if ($timed_start && is_array($timed_start)) { + $def = $table['timed_start']; + $timed_start = NDate::arrayToDate($timed_start); + if (!($def & N_DAO_NOTNULL)) { + if (!NDate::validDateTime($timed_start)) { + $timed_start = false; + } + } + } + if ($timed_end && is_array($timed_end)) { + $def = $table['timed_end']; + $timed_end = NDate::arrayToDate($timed_end); + if (!($def & N_DAO_NOTNULL)) { + if (!NDate::validDateTime($timed_end)) { + $timed_end = false; + } + } + } + // load asset + if (!$asset_controller) return false; + $asset_model = &$asset_controller->getDefaultModel(); + if (!$asset_model) return false; + $pk = $asset_model->primaryKey(); + $fields = $asset_model->fields(); + $values = array(); + foreach ($fields as $field) { + if ($field != $pk && !preg_match('|^cms_|', $field)) // don't save any of the meta content + $values[$field] = $asset_model->$field; + } + $model->reset(); + $model->page_id = $page_id; + $model->page_content_id = $page_content_id; + $model->workflow_group_id = $workflow_group_id; + $model->asset = $asset_controller->name; + $model->asset_id = $asset_model->$pk; + $model->submitted = 0; + $model->completed = 0; + if ($timed_start) $model->timed_start = $timed_start; + if ($timed_end) $model->timed_end = $timed_end; + $model->cms_modified_by_user = $asset_controller->_auth->currentUserID(); + if ($model->find(null, true)) { + $model->cms_modified = $model->now(); + $model->draft = serialize($values); + $ret = $model->update(); + } else { + $model->action = (int) $action; + $model->draft = serialize($values); + $model->cms_created = $model->now(); + $model->cms_modified = $model->now(); + $ret = $model->insert(); + } + if (defined('SITE_AUDIT_TRAIL') && SITE_AUDIT_TRAIL) { + $audit_trail = &NController::factory('audit_trail'); + $audit_trail->insert(array('asset'=>$asset_controller->name, 'asset_id'=>$asset_model->$pk, 'action_taken'=>AUDIT_ACTION_WORKFLOW_START, 'workflow_id'=>$model->{$model->primaryKey()}, 'workflow_group_id'=>$workflow_group_id, 'page_id'=>$page_id, 'page_content_id'=>$page_content_id)); + unset($audit_trail); + } + unset($auth); + unset($model); + return $ret; + } + + function getWorkflow($page_content_id, $workflow_group_id, &$asset_controller, $completed=0) { + if (!$asset_controller || !$asset_model = &$asset_controller->getDefaultModel()) return false; + $pk = $asset_model->primaryKey(); + $model = &NModel::factory($this->name); + $model->page_content_id = $page_content_id; + $model->workflow_group_id = $workflow_group_id; + $model->asset = $asset_controller->name; + $model->asset_id = $asset_model->$pk; + $model->completed = (int) $completed; + if ($model->find(array('order_by'=>'id DESC'), true)) { + return $model; + } + unset($model); + return false; + } + + function isWorkflow($page_content_id, $workflow_group_id, &$asset_controller) { + if (!$asset_controller || !$asset_model = &$asset_controller->getDefaultModel()) return false; + $pk = $asset_model->primaryKey(); + $model = &$this->loadModel($this->name); + $model->page_content_id = $page_content_id; + $model->workflow_group_id = $workflow_group_id; + $model->asset = $asset_controller->name; + $model->asset_id = $asset_model->$pk; + $ret = (bool) $model->find(); + unset($model); + return $ret; + } + + function delete($parameter) { + $model = &$this->getDefaultModel(); + if ($model->get($parameter)) { + if ($page_content_model = &$model->getLink('page_content_id', 'page_content') && $page_content_model->cms_workflow == 1) { + $page_content_model->delete(); + } + } + $model->reset(); + if (defined('SITE_AUDIT_TRAIL') && SITE_AUDIT_TRAIL) { + // audit trail + $audit_trail = &NController::factory('audit_trail'); + $audit_trail->insert(array('asset'=>$model->asset, 'asset_id'=>$model->asset_id, 'action_taken'=>AUDIT_ACTION_WORKFLOW_DELETE, 'workflow_id'=>$model->{$model->primaryKey()}, 'workflow_group_id'=>$model->workflow_group_id, 'page_id'=>$model->page_id, 'page_content_id'=>$model->page_content_id)); + unset($audit_trail); + } + parent::delete($parameter); + } +} +?> diff --git a/app/controllers/workflow_group_controller.php b/app/controllers/workflow_group_controller.php new file mode 100644 index 0000000..2b32d53 --- /dev/null +++ b/app/controllers/workflow_group_controller.php @@ -0,0 +1,153 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class WorkflowGroupController extends nterchangeController { + function __construct() { + $this->name = 'workflow_group'; + // set user level allowed to access the actions with required login + $this->user_level_required = N_USER_ADMIN; + // this whole controller requires login if called directly + $this->login_required = true; + $this->base_dir = APP_DIR; + $this->page_title = 'Workflow Groups'; + parent::__construct(); + } + + function index($parameter) { + $this->redirectTo('viewlist', $parameter); + } + + // specialized list for workflow (integrated ajax for workflow users) + function viewlist($parameter=null) { + $this->auto_render = false; + $wusers_ctrl = &NController::singleton('workflow_users'); + include_once 'controller/form.php'; + + $this->base_dir = APP_DIR; + $model = &$this->loadModel($this->name); + $pk = $model->primaryKey(); + if ($model) { + if ($parameter) $model->{$model->primaryKey()} = $parameter; + $model->find(); + $rows = $model->fetchAll(true); + $wusers_model = &$wusers_ctrl->loadModel($wusers_ctrl->name); + $workflows = ''; + // put the _headline variable in for the viewlist template + foreach ($rows as $key=>$workflow_group) { + $cform = new ControllerForm($wusers_ctrl, $wusers_model); + $form = &$cform->getForm('add_person_form_' . $workflow_group[$pk]); + $form->removeElement('workflow_group_id'); + $form->setDefaults(array('workflow_group_id'=>$workflow_group[$pk])); + $form->addElement('hidden', 'workflow_group_id', $workflow_group[$pk]); + $form->addElement('hidden', '_referer', urlencode($_SERVER['REQUEST_URI'])); + $cform->makeRemoteForm(array('url'=>array('controller'=>'workflow_users', 'action'=>'add_user'), 'loading'=>'workflowManager.addUserLoading(request, ' . $workflow_group[$pk] . ')', 'complete'=>'workflowManager.onAddUser(request, ' . $workflow_group[$pk] . ')')); + if ($form->validate()) { + $fields = $wusers_model->fields(); + if (in_array('cms_created', $fields)) { + $wusers_model->cms_created = $model->now(); + } + if (in_array('cms_modified', $fields)) { + $wusers_model->cms_modified = $model->now(); + } + // set the user id if it's applicable and available + if (in_array('cms_modified_by_user', $fields)) { + $wusers_model->cms_modified_by_user = isset($this->_auth) && is_object($this->_auth)?$this->_auth->currentUserID():0; + } + $success = $form->process(array($cform, 'processForm')); + } + $headline = $model->getHeadline(); + if (!empty($headline)) { + if (is_array($headline)) { + $workflow_group['_headline'] = ''; + foreach ($headline as $row) { + $workflow_group['_headline'] .= $workflow_group['_headline']?' - ':''; + $workflow_group['_headline'] .= $workflow_group[$row]; + } + } else { + $workflow_group['_headline'] = $workflow_group[$headline]; + } + } else { + $workflow_group['_headline'] = $workflow_group['cms_headline']; + } + $workflow_group['_users'] = array(); + $wusers_model->reset(); + $wusers_model->workflow_group_id = $workflow_group[$pk]; + if ($wusers_model->find()) { + while ($wusers_model->fetch()) { + $user_model = &$wusers_model->getLink('user_id', 'cms_auth'); + if ($user_model) { + $user = $wusers_model->toArray(); + $user['real_name'] = $user_model->real_name; + $workflow_group['_users'][] = $user; + } + } + } + $workflow_group['asset'] = $this->name; + $workflow_group['add_user_form'] = $form->toHTML(); + $this->set($workflow_group); + $workflows .= $this->render(array('action'=>'workflow_group', 'return'=>true)); + unset($form); + unset($cform); + } + $this->set(array('asset'=>$this->name, 'workflows'=>$workflows)); + $main_content = $this->render(array('return'=>true)); + $sidebar_content = $this->render(array('action'=>'workflow_description', 'return'=>true)); + } + $this->renderLayout('default', $main_content, $sidebar_content); + } + + function delete($parameter) { + if (empty($parameter)) { + $this->redirectTo('viewlist'); + } + // delete the workflow group + $model = &$this->getDefaultModel(); + if (!$model) $this->redirectTo('viewlist'); + $model->get($parameter); + $model->delete($parameter); + // cascade delete the workflow_users records + $workflow_users = &$this->loadModel('workflow_users'); + $workflow_users->workflow_group_id = $parameter; + if ($workflow_users->find()) { + while ($workflow_users->fetch()) { + $workflow_users->delete(); + } + } + if (isset($_GET['_referer']) && $_GET['_referer']) { + header('Location:' . urldecode($_GET['_referer'])); + exit; + } + $this->flash->set('notice', Inflector::humanize($this->name) . ' record deleted.'); + $this->redirectTo('viewlist'); + } +} +?> diff --git a/app/controllers/workflow_users_controller.php b/app/controllers/workflow_users_controller.php new file mode 100644 index 0000000..d4fcbf3 --- /dev/null +++ b/app/controllers/workflow_users_controller.php @@ -0,0 +1,84 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class WorkflowUsersController extends AppController { + function __construct() { + $this->name = 'workflow_users'; + // this whole controller requires login if called directly + $this->login_required = true; + $this->base_view_dir = BASE_DIR; + $this->base_dir = APP_DIR; + // set user level allowed to access the actions with required login + $this->user_level_required = N_USER_ADMIN; + parent::__construct(); + } + + function preGenerateForm() { + parent::preGenerateForm(); + } + + function addUser() { + $model = &$this->getDefaultModel(); + if (isset($_POST['_referer'])) unset($_POST['_referer']); + if ($this->insert()) { + require_once 'vendor/JSON.php'; + $json = new Services_JSON(); + if ($html = $this->loadUser($model->{$model->primaryKey()})) { + $data = array('id'=>$model->{$model->primaryKey()}, 'data'=>$html); + print 'result = ' . $json->encode($data); + } + } + } + + function deleteUser($parameter) { + if (empty($parameter)) { + print 'success=false;'; + return; + } + // load the model layer with info + $model = &$this->getDefaultModel(); + if (!$model) { + $this->render(array('nothing'=>true)); + return; + } + $model->get($parameter); + $model->delete($parameter); + $this->render(array('nothing'=>true)); + } + + function loadUser($parameter) { + $this->auto_render = false; + $model = &$this->loadModel($this->name); + if ($model && $model->get($parameter)) { + $user_model = &$model->getLink('user_id', 'cms_auth'); + if ($user_model) { + $user = $model->toArray(); + $user['real_name'] = $user_model->real_name; + } + $this->set($user); + return $this->render(array('action'=>'workflow_user', 'return'=>true)); + } + $this->render(array('nothing'=>true)); + } + + function listUser($parameter) { + print $this->loadUser($parameter); + } +} +?> diff --git a/app/helpers/audit_trail_helper.php b/app/helpers/audit_trail_helper.php new file mode 100644 index 0000000..e4c3a21 --- /dev/null +++ b/app/helpers/audit_trail_helper.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/app/helpers/cms_asset_info_helper.php b/app/helpers/cms_asset_info_helper.php new file mode 100644 index 0000000..80c71c3 --- /dev/null +++ b/app/helpers/cms_asset_info_helper.php @@ -0,0 +1,53 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class CmsAssetInfoHelper{ + + function function_check_asset_model($params) { + $asset = $params['asset']; + $model_check = &NController::factory('cms_asset_info'); + $result = $model_check->doesAssetModelFileExist($asset); + if (!$result) print ' Model File not found '; + unset($model_check); + } + + function function_check_asset_controller($params) { + $asset = $params['asset']; + $controller_check = &NController::factory('cms_asset_info'); + $result = $controller_check->doesAssetControllerFileExist($asset); + if (!$result) print ' Controller File not found '; + unset($controller_check); + } + + function function_check_asset_table($params) { + $asset = $params['asset']; + $table_check = &NController::factory('cms_asset_info'); + $result = $table_check->doesAssetDatabaseTableExist($asset); + if (!$result) print ' Database table not found '; + unset($table_check); + } + + function function_check_asset_template_use($params) { + $asset = $params['asset']; + $container_id = $params['container_id']; + $check = &NController::factory('page_content'); + $result = $check->checkAssetContainerUsage($asset, $container_id); + if ($result > 0) print ' (' . $result . ' uses)'; + } +} +?> \ No newline at end of file diff --git a/app/helpers/cms_asset_template_helper.php b/app/helpers/cms_asset_template_helper.php new file mode 100644 index 0000000..0cbcf46 --- /dev/null +++ b/app/helpers/cms_asset_template_helper.php @@ -0,0 +1,47 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class CmsAssetTemplateHelper{ + var $file_warning = ' File not found '; + + function function_check_asset_template($params) { + $filename = $params['filename']; + $asset = $params['asset']; + $template_check = &NController::factory('cms_asset_template'); + $result = $template_check->doesAssetTemplateExist($filename, $asset); + if (!$result) print $this->file_warning; + unset($template_check); + } + + function function_check_template($params) { + $filename = $params['filename']; + $template_check = &NController::factory('page_template'); + $result = $template_check->doesPageTemplateExist($filename); + if (!$result) print $this->file_warning; + unset($template_check); + } + + function function_check_asset_template_use($params) { + $asset = $params['asset']; + $container_id = $params['container_id']; + $check = &NController::factory('page_content'); + $result = $check->checkAssetContainerUsage($asset, $container_id); + if ($result > 0) print ' (' . $result . ' uses)'; + } +} +?> \ No newline at end of file diff --git a/app/helpers/content_helper.php b/app/helpers/content_helper.php new file mode 100644 index 0000000..0d97384 --- /dev/null +++ b/app/helpers/content_helper.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/app/helpers/dashboard_helper.php b/app/helpers/dashboard_helper.php new file mode 100644 index 0000000..96fe578 --- /dev/null +++ b/app/helpers/dashboard_helper.php @@ -0,0 +1,13 @@ +dashboardVersionCheck(); + } + + function function_dashboard_client_content() { + $dashboard = NController::factory('dashboard'); + $dashboard->dashboardClientContent(); + } +} +?> \ No newline at end of file diff --git a/app/helpers/login_helper.php b/app/helpers/login_helper.php new file mode 100644 index 0000000..ff154aa --- /dev/null +++ b/app/helpers/login_helper.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/app/helpers/page_content_helper.php b/app/helpers/page_content_helper.php new file mode 100644 index 0000000..49b9656 --- /dev/null +++ b/app/helpers/page_content_helper.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/app/helpers/page_helper.php b/app/helpers/page_helper.php new file mode 100644 index 0000000..4f57cdf --- /dev/null +++ b/app/helpers/page_helper.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/app/helpers/page_template_containers_helper.php b/app/helpers/page_template_containers_helper.php new file mode 100644 index 0000000..49f9942 --- /dev/null +++ b/app/helpers/page_template_containers_helper.php @@ -0,0 +1,28 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class PageTemplateContainersHelper{ + function function_check_template($params) { + $filename = $params['filename']; + $template_check = &NController::factory('page_template'); + $result = $template_check->doesPageTemplateExist($filename); + if (!$result) print ' File not found '; + unset($template_check); + } +} +?> \ No newline at end of file diff --git a/app/helpers/page_template_helper.php b/app/helpers/page_template_helper.php new file mode 100644 index 0000000..164f0ed --- /dev/null +++ b/app/helpers/page_template_helper.php @@ -0,0 +1,28 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class PageTemplateHelper{ + function function_check_template($params) { + $filename = $params['filename']; + $template_check = &NController::factory('page_template'); + $result = $template_check->doesPageTemplateExist($filename); + if (!$result) print ' File not found '; + unset($template_check); + } +} +?> \ No newline at end of file diff --git a/app/helpers/settings_helper.php b/app/helpers/settings_helper.php new file mode 100644 index 0000000..05b64e6 --- /dev/null +++ b/app/helpers/settings_helper.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/app/helpers/site_admin_helper.php b/app/helpers/site_admin_helper.php new file mode 100644 index 0000000..cbfaf41 --- /dev/null +++ b/app/helpers/site_admin_helper.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/app/helpers/users_helper.php b/app/helpers/users_helper.php new file mode 100644 index 0000000..f735537 --- /dev/null +++ b/app/helpers/users_helper.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/app/models/action_track.php b/app/models/action_track.php new file mode 100644 index 0000000..5193467 --- /dev/null +++ b/app/models/action_track.php @@ -0,0 +1,190 @@ + + * @copyright 2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @since 3.1.14 + * @link http://www.nterchange.com/ + */ +class ActionTrack extends NModel { + var $time_limit = 300; + + function __construct() { + $this->__table = 'action_track'; + $this->_order_by = 'timestamp DESC'; + parent::__construct(); + } + + /** + * cleanURL - Clean up the REQUEST_URI as passed. + * Removes /APP_DIR and the leading slash. + * + * @param string REQUEST_URI + * @return string Cleaned URL + **/ + function cleanURL($url) { + $url = str_replace('/' . APP_DIR, '', $url); + $url = preg_replace('|^/|', '', $url); + return $url; + } + + /** + * setAssetValues - Set the values for the class based on the cleaned up URL. + * + * @param string A cleaned up URL + * @return boolean + **/ + function setAssetValues($url) { + $pieces = explode('/', $url); + $this->asset_name = $pieces[0]; + $this->action = $pieces[1]; + $this->asset_id = $pieces[2]; + return true; + } + + /** + * trackCurrentEdit - Log that a user is editing a record in this->__table. + * + * @param int User id who is editing a record. + * @param string Name of the asset they are editing. + * @param int Id of the asset they are editing + * @return boolean + **/ + function trackCurrentEdit($user_id, $asset_name, $asset_id) { + $this->user_id = $user_id; + $this->asset_name = $asset_name; + $this->action = 'edit'; + $this->asset_id = $asset_id; + $this->timestamp = time(); + if ($this->save()) { + $this->removeOldEdits($user_id, $this->timestamp); + return true; + } else { + return false; + } + } + + /** + * completeCurrentEdit - This is called after a record has been updated + * in app_controller:edit. It removes the record from $this->__table. + * + * @param int User id who is editing a record. + * @param string Name of the asset they are editing. + * @param int Id of the asset they are editing + * @return void + **/ + function completeCurrentEdit($user_id, $asset_name, $asset_id) { + $this->user_id = $user_id; + $this->asset_name = $asset_name; + $this->action = 'edit'; + $this->asset_id = $asset_id; + if ($this->find()) { + while ($this->fetch()) { + $this->delete(); + } + } + } + + /** + * removeOldEdits - This is called after a trackCurrentEdit saves an entry. + * It's to make sure that there's only one entry by that user at any time. + * + * @param int User id who has edited a record. + * @param int Timestamp from time() + * @return void + **/ + function removeOldEdits($user_id, $last_modified) { + $this->reset(); + $this->user_id = $user_id; + if ($this->find()) { + while ($this->fetch()) { + if ($this->timestamp < $last_modified) { + $this->delete(); + } + } + } + } + + /** + * checkAssetEditStatus - This is called from app_controller:edit and returns false if: + * 1. Nobody is editing the record. + * 2. An edit was longer than $this->time_limit. + * It returns true if there somebody is currently editing the same record. + * + * @param string Name of the asset they are editing. + * @param int Id of the asset they are editing + * @return boolean + **/ + function checkAssetEditStatus($asset_name, $asset_id) { + $time_now = time(); + $this->asset_name = $asset_name; + $this->asset_id = $asset_id; + if ($this->find()) { + while ($this->fetch()) { + // Check time limit to see if it's past. + $item = $this->toArray(); + if ($limit = $this->timestampWithinLimit($item['timestamp'])) { + return true; + } else { + return false; + } + } + } else { + return false; + } + } + + /** + * timestampWithinLimit - Check to see whether or not a timestamp is + * within $this->time_limit away from the current time. + * Returns true if it is, false if it's not. + * + * @param int timestamp as returned from time() + * @return boolean + **/ + function timestampWithinLimit($timestamp) { + $time_now = time(); + $time_diff = $time_now - $timestamp; + if ($time_diff < $this->time_limit) { + return true; + } else { + return false; + } + } + + /** + * getActiveEdits - This grabs any currently active edits as long as they're within + * $this->time_limit - used for display by the action_track helper. + * Returns an array of items. + * + * @return array An array of currently active edits. + **/ + function getActiveEdits() { + $items = array(); + if ($this->find()) { + while ($this->fetch()) { + $item = $this->toArray(); + // Check to see if it's within the time_limit; + if ($limit = $this->timestampWithinLimit($item['timestamp'])) { + $items[] = $item; + } + } + } + return $items; + } +} +?> diff --git a/app/models/cms_asset_info.php b/app/models/cms_asset_info.php new file mode 100644 index 0000000..e7b1584 --- /dev/null +++ b/app/models/cms_asset_info.php @@ -0,0 +1,29 @@ + + * @copyright 2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class CmsAssetInfo extends NModel { + function __construct() { + $this->__table = 'cms_asset_info'; + $this->_order_by = 'cms_asset_info.asset_name'; + $this->setHeadline('asset_name'); + parent::__construct(); + } + +} +?> \ No newline at end of file diff --git a/app/models/cms_asset_template.php b/app/models/cms_asset_template.php new file mode 100644 index 0000000..be5ab43 --- /dev/null +++ b/app/models/cms_asset_template.php @@ -0,0 +1,29 @@ + + * @copyright 2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class CmsAssetTemplate extends NModel { + function __construct() { + $this->__table = 'cms_asset_template'; + $this->_order_by = $this->__table . '.asset'; + $this->setHeadline('asset'); + $this->form_elements['page_template_container_id'] = array('foreignkey', 'page_template_container_id', 'Container:', array('model'=>'page_template_containers', 'headline'=>'container_name', 'addEmptyOption'=>false)); + parent::__construct(); + } +} +?> \ No newline at end of file diff --git a/app/models/cms_audit_trail.php b/app/models/cms_audit_trail.php new file mode 100644 index 0000000..9777402 --- /dev/null +++ b/app/models/cms_audit_trail.php @@ -0,0 +1,70 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class CmsAuditTrail extends NModel { + function __construct() { + $this->__table = 'cms_audit_trail'; + $this->name = 'cms_audit_trail'; + $this->_order_by = 'cms_created ASC'; + // This is the fake user we use when the website removes timed content from the site. + // It's to keep audit trail working. + $this->website_user_id = 99999; + $this->website_user_name = 'Website Robot'; + $this->website_user_email = 'website@' . $_SERVER['SERVER_NAME']; + parent::__construct(); + } + + /** + * insert_audit_trail - This is only for timed_remove so that we don't + * lose the audit_trail. + * Refactor: Duplication of audit_trail_controller->insert(); + * + * @param array Required params - asset, asset_id, action_taken + * @return void + **/ + function insert_audit_trail($params=array()) { + if (empty($params)) return false; + $required_params = array('asset', 'asset_id', 'action_taken'); + foreach ($required_params as $param) { + if (!isset($params[$param])) return false; + } + $model = &NModel::factory($this->name); + // apply fields in the model + $fields = $model->fields(); + foreach ($fields as $field) { + $model->$field = isset($params[$field])?$params[$field]:null; + } + $model->user_id = $this->website_user_id; + $model->ip = NServer::env('REMOTE_ADDR'); + if (in_array('cms_created', $fields)) { + $model->cms_created = $model->now(); + } + if (in_array('cms_modified', $fields)) { + $model->cms_modified = $model->now(); + } + // set the user id if it's applicable and available + if (in_array('cms_modified_by_user', $fields)) { + $model->cms_modified_by_user = $this->website_user_id; + } + $model->insert(); + } + +} +?> \ No newline at end of file diff --git a/app/models/cms_auth.php b/app/models/cms_auth.php new file mode 100644 index 0000000..97d47cf --- /dev/null +++ b/app/models/cms_auth.php @@ -0,0 +1,173 @@ + + * @author Darron Froese + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class CmsAuth extends NModel { + function __construct() { + $this->__table = 'cms_auth'; + $this->_order_by = 'real_name'; + parent::__construct(); + // form stuff + $this->form_header = 'real_name'; + $this->display_fields = array('real_name', 'username', 'user_level', 'status'); + $this->form_required_fields[] = 'real_name'; + $this->form_required_fields[] = 'email'; + $this->form_required_fields[] = 'username'; + $this->form_rules[] = array('email', 'The email does not appear to be the correct format', 'email'); + $this->form_rules[] = array('username', 'This is not a unique username', 'callback', array(&$this, 'uniqueUsername')); + // secure password rules, 8 characters long, upper and lower case characters + // $this->form_rules[] = array('password', 'The password must be at least 8 characters long and contain upper and lower case characters and a number.', 'minlength', 8, 'client'); + // $this->form_rules[] = array('password', 'The password must be at least 8 characters long and contain upper and lower case characters and a number.', 'regex', '/[A-Z]/', 'client'); + // $this->form_rules[] = array('password', 'The password must be at least 8 characters long and contain upper and lower case characters and a number.', 'regex', '/[a-z]/', 'client'); + // $this->form_rules[] = array('password', 'The password must be at least 8 characters long and contain upper and lower case characters and a number.', 'regex', '/[0-9]/', 'client'); + // password field + $this->form_elements['password'] = array('password'); + // hide the status field for now + $this->form_elements['status'] = array('hidden', 'status'); + // Ignore the feed_token field for now + $this->form_ignore_fields[] = 'feed_token'; + // Ignore the confirmation_token field for now + $this->form_ignore_fields[] = 'confirmation_token'; + // user level - a non-root can't set someone else to be root + $user_lvl = array(N_USER_NORIGHTS=>'non-privileged', N_USER_EDITOR=>'user', N_USER_ADMIN=>'admin'); + $this->form_elements['user_level'] = array('select', 'user_level', 'User Level', $user_lvl); + $this->setHeadline('real_name'); + } + + /** + * uniqueUsername - Make sure that the username is unique. + * + * @param string The username to check. + * @return boolean + **/ + function uniqueUsername($value) { + $id = $this->{$this->primaryKey()}; + $model = &NModel::factory($this->__table); + if ($model) { + $conditions = $id?$model->primaryKey() . '!=' . $id:''; + $model->username = $value; + if ($model->find(array('conditions'=>$conditions))) { + unset($model); + return false; + } + } + unset($model); + return true; + } + + /** + * getFeedToken - Returns the feed token for an id. + * + * @param int User_id + * @return string The feed token for that user. + **/ + function getFeedToken($id) { + $this->id = $id; + if ($this->find()) { + while ($this->fetch()) { + return $this->feed_token; + } + } + } + + /** + * resetPassword - Reset the users' password and email it to them. + * + * @param string An email address. + * @return boolean + * @todo Audit trail this method. + **/ + function resetPassword($email) { + // Make sure to clear out the model - after searching a few times already. + $this->reset(); + $this->email = $email; + if ($this->find()) { + while ($this->fetch()) { + $password = $this->_createPassword(); + $this->password = md5($password); + $this->save(); + $users = NController::factory('users'); + $users->passwordEmail($this->toArray(), $password); + return true; + } + } else { + return false; + } + } + + /** + * _createPassword - Create a password using PEAR's Text_Password generator. + * + * @return string The new password. + **/ + function _createPassword() { + include_once 'Text/Password.php'; + $password = Text_Password::create(rand(8, 10), 'unpronounceable'); + return $password; + } + + /** + * setConfirmationToken - Generate and set a confirmation token for a particular user. + * Returns true if successful, false if not. + * + * @param string Email address for that user. + * @return boolean + **/ + function setConfirmationToken($email) { + // Generate the token and put it into the database. + $random = rand(1,1000000) . time() . $_SERVER['REMOTE_ADDR'] . rand(1,1000000); + $confirmation_token = md5($random); + $this->email = $email; + if ($this->find()) { + while ($this->fetch()) { + $this->confirmation_token = $confirmation_token; + if ($this->save()) { + return true; + } else { + return false; + } + } + } + } + + /** + * getConfirmationToken - Gets a confirmation token from the database. + * Returns false if it's null or if there's no match. + * + * @param string Email address for that user. + * @return string The confirmation token. + **/ + function getConfirmationToken($email) { + $this->email = $email; + if ($this->find()) { + while ($this->fetch()) { + if (!is_null($this->confirmation_token)) { + return $this->confirmation_token; + } else { + return false; + } + } + } else { + return false; + } + } + + +} +?> \ No newline at end of file diff --git a/app/models/cms_drafts.php b/app/models/cms_drafts.php new file mode 100644 index 0000000..356f336 --- /dev/null +++ b/app/models/cms_drafts.php @@ -0,0 +1,26 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class CmsDrafts extends NModel { + function __construct() { + $this->__table = 'cms_drafts'; + parent::__construct(); + } +} +?> \ No newline at end of file diff --git a/app/models/cms_nterchange_versions.php b/app/models/cms_nterchange_versions.php new file mode 100644 index 0000000..cce22b2 --- /dev/null +++ b/app/models/cms_nterchange_versions.php @@ -0,0 +1,27 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class CmsNterchangeVersions extends NModel { + function __construct() { + $this->__table = 'cms_nterchange_versions'; + $this->_order_by = 'cms_nterchange_versions.cms_created desc'; + parent::__construct(); + } +} +?> \ No newline at end of file diff --git a/app/models/cms_settings.php b/app/models/cms_settings.php new file mode 100644 index 0000000..e78405a --- /dev/null +++ b/app/models/cms_settings.php @@ -0,0 +1,90 @@ +SETTINGS_EDITOR_DEFAULT); + +/** + * + * PHP versions 4 and 5 + * + * LICENSE: This source file is subject to version 3.01 of the PHP license + * that is available through the world-wide-web at the following URI: + * http://www.php.net/license/3_01.txt. If you did not receive a copy of + * the PHP License and are unable to obtain it through the web, please + * send a note to license@php.net so we can mail you a copy immediately. + * + * @category CMS Settings Model + * @author Tim Glen + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class CmsSettings extends NModel { + function __construct() { + $this->__table = 'cms_settings'; + $this->setHeadline('setting_var'); + $this->_order_by = 'cms_settings.setting'; + $this->form_elements['setting'] = array('select', 'setting', 'Setting', array(SETTINGS_EDITOR=>'WYSIWYG Editor')); + $this->form_ignore_fields[] = 'user_id'; + parent::__construct(); + } + + /** + * settingToText - Returns English description of setting. + * + * @param int Setting define id + * @return string English description of that string + **/ + function settingToText($setting) { + $ret = ''; + switch($setting) { + case SETTINGS_EDITOR: + $ret = 'WYSIWYG Editor'; + break; + } + return $ret; + } + + function fetch() { + $ret = parent::fetch(); + if ($ret) { + $this->setting_var = $this->settingToText($this->setting); + } + return $ret; + } + + function toArray() { + $ret = parent::toArray(); + if (is_array($ret) && count($ret) && isset($this->setting_var)) { + $ret['setting_var'] = $this->setting_var; + } + return $ret; + } + + /** + * getSetting - Get a user's setting from the database - or use the defaults. + * + * @param int The id of the particular setting. + * @return boolean + **/ + function getSetting($setting) { + $auth = new NAuth(); + $this->user_id = $auth->currentUserID(); + $this->setting = $setting; + if ($this->find(null, true)) { + $ret = (bool) $this->value; + } else { + $user_settings = $GLOBALS['USER_SETTINGS']; + $ret = isset($user_settings[$setting])?$user_settings[$setting]:true; + } + $this->reset(); + return $ret; + } +} +?> diff --git a/app/models/code_caller.php b/app/models/code_caller.php new file mode 100644 index 0000000..5562076 --- /dev/null +++ b/app/models/code_caller.php @@ -0,0 +1,28 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class CodeCaller extends NModel { + function __construct() { + $this->__table = 'code_caller'; + $this->form_required_fields[] = 'content'; + $this->_order_by = 'cms_headline'; + parent::__construct(); + } +} +?> \ No newline at end of file diff --git a/app/models/page.php b/app/models/page.php new file mode 100644 index 0000000..90a583b --- /dev/null +++ b/app/models/page.php @@ -0,0 +1,140 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class Page extends ModelTree { + var $_order_by = 'page.sort_order, page.id'; + + function __construct() { + $this->__table = 'page'; + parent::__construct(); + $this->setHeadline('title'); + // form & validation + $this->form_header = 'title'; + $this->form_field_labels['filename'] = 'Filename
    (nonfiction use)'; + // always ignore these as they are updated programatically + $this->form_ignore_fields = array('path', 'sort_order', 'static_content'); + if (!defined('SITE_DISCLAIMER') || !SITE_DISCLAIMER || !defined('SITE_DISCLAIMER_ID') || !SITE_DISCLAIMER_ID) { + $this->form_ignore_fields[] = 'disclaimer_required'; + $this->form_ignore_fields[] = 'disclaimer_recursive'; + } + // always require the title + $this->form_required_fields = array('title'); + // cache lifetime options + $this->form_elements['cache_lifetime'] = array('select', 'cache_lifetime', 'Cache Lifetime', array(0=>'no caching', 5*60=>'5 minutes', 15*60=>'15 minutes', 60*60=>'1 hour', 60*60*8=>'8 hours', 60*60*24=>'1 day', 60*60*24*7=>'1 week', '-1'=>'indefinite')); + // cache lifetime options + $this->form_elements['client_cache_lifetime'] = array('select', 'client_cache_lifetime', 'Client Cache Lifetime', array(0=>'no caching', 5*60=>'5 minutes', 15*60=>'15 minutes', 60*60=>'1 hour', 60*60*8=>'8 hours', 60*60*24=>'1 day', 60*60*24*7=>'1 week', '-1'=>'indefinite')); + + // this is a foreign key + $this->form_elements['page_template_id'] = array('foreignkey', 'page_template_id', 'Template', array('model'=>'page_template', 'headline'=>'template_name')); + // Ignore printable - not being used in nterchange 3 at all. + $this->form_ignore_fields[] = 'printable'; + + // Ignore permissions field - not being used in nterchange 3 at the moment. + $this->form_ignore_fields[] = 'permissions_id'; + + // check for workflow being used + if (SITE_WORKFLOW) { + $this->form_elements['workflow_group_id'] = array('foreignkey', 'workflow_group_id', 'Workflow Group', array('model'=>'workflow_group', 'headline'=>'workflow_title', 'addEmptyOption'=>true)); + $this->form_field_labels['workflow_recursive'] = 'Cascade Workflow'; + } else { + $this->form_ignore_fields[] = 'workflow_group_id'; + $this->form_ignore_fields[] = 'workflow_recursive'; + } + if (!SECURE_SITE) { + $this->form_ignore_fields[] = 'secure_page'; + } + $this->form_rules[] = array('parent_id', 'You cannot make a page a child of itself.', 'callback', array(&$this, 'checkChildOfItself')); + + // cache lifetime should be indefinite by default + $this->form_field_defaults['cache_lifetime'] = '-1'; + $this->form_field_defaults['client_cache_lifetime'] = '3600'; + $this->form_field_defaults['visible'] = 1; + $this->form_field_defaults['active'] = 1; + } + + /** + * checkChildOfItself - A page cannot be a child of itself. That would be + * illogical and cause that page to disappear. Returns true if OK and false + * if you're setting something to be a child of itself. + * + * @param int The page_id of a page. + * @return boolean + **/ + function checkChildOfItself($parent_id) { + $parent_id = (int) $parent_id; + $pk = $this->primaryKey(); + $page = &NController::singleton('page'); + $page_id = (int) $page->getParam($pk); + if (!$page_id) { + return true; + } + if ($page_id == $parent_id) { + return false; + } + $all_children = $this->getAllChildren($page_id, false, false); + foreach ($all_children as $child) { + if ($parent_id == $child[$pk]) { + return false; + } + } + return true; + } + + function afterCreate() { + // Delete Smarty Cache + $this->deleteSmartyCache(); + } + + function afterUpdate() { + // Delete Smarty Cache + $this->deleteSmartyCache(); + } + + function afterDelete($page_id) { + // After a page is deleted, make sure to remove all linked + // content from the page_content table. Cleans things up and + // helps with some possible workflow trauma. + $page_content = NModel::factory('page_content'); + $page_content->deleteOrphanedPageContent($page_id); + // Delete Smarty Cache + $this->deleteSmartyCache(); + } + + /** + * deleteSmartyCache - Delete the entire cache when you make a page change. + * If you're including the navigation in the page as ul/li's - this keeps the + * navigation always consistent. + * + * @return void + **/ + function deleteSmartyCache() { + // Only delete the entire cache if the NAV_IN_PAGE is true and we're in production. + if (defined('NAV_IN_PAGE') && NAV_IN_PAGE && (ENVIRONMENT == 'production') && !isset($this->smarty_cache_cleared)) { + NDebug::debug('We are clearing the smarty caches because of a page edit.' , N_DEBUGTYPE_INFO); + $view = &NView::singleton($this); + $view->clear_all_cache(); + $site_admin = NController::factory('site_admin'); + $site_admin->rmDirFiles(CACHE_DIR . '/smarty_cache'); + $site_admin->rmDirFiles(CACHE_DIR . '/templates_c'); + $this->smarty_cache_cleared = true; + } + } +} +?> \ No newline at end of file diff --git a/app/models/page_content.php b/app/models/page_content.php new file mode 100644 index 0000000..204a83c --- /dev/null +++ b/app/models/page_content.php @@ -0,0 +1,256 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class PageContent extends NModel { + function __construct() { + $this->__table = 'page_content'; + $this->_order_by = 'page_content.content_order, page_content.id'; + + $this->form_field_options['timed_start'] = array('addEmptyOption'=>true); + $this->form_field_options['timed_end'] = array('addEmptyOption'=>true); + + $this->form_elements['col_xs'] = array('select', 'col_xs', 'Width (xs)', $this->grid_options('col_xs')); + $this->form_elements['col_sm'] = array('select', 'col_sm', 'Width (sm)', $this->grid_options('col')); + $this->form_elements['col_md'] = array('select', 'col_md', 'Width (md)', $this->grid_options('col')); + $this->form_elements['col_lg'] = array('select', 'col_lg', 'Width (lg)', $this->grid_options('col')); + + $this->form_elements['row_xs'] = array('select', 'row_xs', 'Height (xs)', $this->grid_options('row_xs')); + $this->form_elements['row_sm'] = array('select', 'row_sm', 'Height (sm)', $this->grid_options('row')); + $this->form_elements['row_md'] = array('select', 'row_md', 'Height (md)', $this->grid_options('row')); + $this->form_elements['row_lg'] = array('select', 'row_lg', 'Height (lg)', $this->grid_options('row')); + + $this->form_elements['offset_col_xs'] = array('select', 'offset_col_xs', 'Offset Width (xs)', $this->grid_options('offset_col_xs')); + $this->form_elements['offset_col_sm'] = array('select', 'offset_col_sm', 'Offset Width (sm)', $this->grid_options('offset_col')); + $this->form_elements['offset_col_md'] = array('select', 'offset_col_md', 'Offset Width (md)', $this->grid_options('offset_col')); + $this->form_elements['offset_col_lg'] = array('select', 'offset_col_lg', 'Offset Width (lg)', $this->grid_options('offset_col')); + + $this->form_elements['offset_row_xs'] = array('select', 'offset_row_xs', 'Offset Height (xs)', $this->grid_options('offset_row_xs')); + $this->form_elements['offset_row_sm'] = array('select', 'offset_row_sm', 'Offset Height (sm)', $this->grid_options('offset_row')); + $this->form_elements['offset_row_md'] = array('select', 'offset_row_md', 'Offset Height (md)', $this->grid_options('offset_row')); + $this->form_elements['offset_row_lg'] = array('select', 'offset_row_lg', 'Offset Height (lg)', $this->grid_options('offset_row')); + + $this->form_elements['pull_xs'] = array('select', 'pull_xs', 'Pull (xs)', $this->grid_options('pull_xs')); + $this->form_elements['pull_sm'] = array('select', 'pull_sm', 'Pull (sm)', $this->grid_options('pull')); + $this->form_elements['pull_md'] = array('select', 'pull_md', 'Pull (md)', $this->grid_options('pull')); + $this->form_elements['pull_lg'] = array('select', 'pull_lg', 'Pull (lg)', $this->grid_options('pull')); + + $this->form_elements['gutter_xs'] = array('text', 'gutter_xs', 'Gutter (xs)'); + $this->form_elements['gutter_sm'] = array('text', 'gutter_sm', 'Gutter (sm)'); + $this->form_elements['gutter_md'] = array('text', 'gutter_md', 'Gutter (md)'); + $this->form_elements['gutter_lg'] = array('text', 'gutter_lg', 'Gutter (lg)'); + + parent::__construct(); + } + + function getContainerContent($page_id, $container_id, $admin=false, $page_content_id=null) { + $options = array('conditions'=>"page_id=$page_id AND page_template_container_id=$container_id"); + if ($admin == false) { + $options['conditions'] .= ' AND cms_workflow=0'; + } + if ($page_content_id) { + $options['conditions'] .= " AND id=$page_content_id"; + } + return $this->find($options); + } + + function isWorkflowContent($asset, $asset_id) { + if (SITE_WORKFLOW) { + $this->reset(); + $page_model = &NModel::singleton('page'); + $page_model->reset(); + $join = 'INNER JOIN ' . $page_model->tableName() . ' ON '; + $join .= $this->tableName() . '.page_id=' . $page_model->tableName() . '.' . $page_model->primaryKey(); + $this->content_asset = $asset; + $this->content_asset_id = $asset_id; + if ($this->find(array('join'=>$join, 'conditions'=>$page_model->tableName() . '.workflow_group_id != 0'))) { + return true; + } + } + return false; + } + + function &getActivePageContent($asset, $asset_id) { + if (!$asset || !$asset_id) { + $ret = false; + return $ret; + } + $page = &NModel::singleton('page'); + $this->reset(); + $this->content_asset = (string) $asset; + $this->content_asset_id = (int) $asset_id; + $page_contents = false; + if ($this->find()) { + $page_contents = array(); + while ($this->fetch()) { + $page->reset(); + // Only get active pages. + $page->cms_deleted = 0; + if (!$page->get($this->page_id)) { + continue; + } + $page_contents[] = clone($this); + } + } + return $page_contents; + } + + /** + * deleteOrphanedPageContent - Remove all content from the page_content table for + * a particular page_id. This is called from the page model when a page is deleted. + * + * @param int The id of a page that has been deleted. + * @return void + **/ + function deleteOrphanedPageContent($page_id) { + $this->page_id = $page_id; + if ($this->find()) { + while ($this->fetch()) { + $this->delete(); + } + } + } + + function to_percent($col) { + $percent = round(($col/12)*100); + return "{$percent}%"; + } + + function grid_options($name) { + $col = array( + 'inherit' => 'Inherit', + '12' => '12 cols', + '11' => '11 cols', + '10' => '10 cols', + '9' => '9 cols', + '8' => '8 cols', + '7' => '7 cols', + '6' => '6 cols', + '5' => '5 cols', + '4' => '4 cols', + '3' => '3 cols', + '2' => '2 cols', + '1' => '1 col', + 'auto' => 'Auto'); + $col_xs = array( + '12' => '12 cols', + '11' => '11 cols', + '10' => '10 cols', + '9' => '9 cols', + '8' => '8 cols', + '7' => '7 cols', + '6' => '6 cols', + '5' => '5 cols', + '4' => '4 cols', + '3' => '3 cols', + '2' => '2 cols', + '1' => '1 col', + 'auto' => 'Auto'); + + $row = array('inherit'=>'Inherit', 'auto'=>'Auto', + '1'=> '1 row', '2'=> '2 rows', '3'=> '3 rows', '4'=> '4 rows', '5'=> '5 rows', '6'=> '6 rows', '7'=> '7 rows', '8'=> '8 rows', '9'=> '9 rows', '10'=>'10 rows', + '11'=>'11 rows', '12'=>'12 rows', '13'=>'13 rows', '14'=>'14 rows', '15'=>'15 rows', '16'=>'16 rows', '17'=>'17 rows', '18'=>'18 rows', '19'=>'19 rows', '20'=>'20 rows', + '21'=>'21 rows', '22'=>'22 rows', '23'=>'23 rows', '24'=>'24 rows', '25'=>'25 rows', '26'=>'26 rows', '27'=>'27 rows', '28'=>'28 rows', '29'=>'29 rows', '30'=>'30 rows', + '31'=>'31 rows', '32'=>'32 rows', '33'=>'33 rows', '34'=>'34 rows', '35'=>'35 rows', '36'=>'36 rows', '37'=>'37 rows', '38'=>'38 rows', '39'=>'39 rows', '40'=>'40 rows', + '41'=>'41 rows', '42'=>'42 rows', '43'=>'43 rows', '44'=>'44 rows', '45'=>'45 rows', '46'=>'46 rows', '47'=>'47 rows', '48'=>'48 rows', '49'=>'49 rows', '50'=>'50 rows'); + $row_xs = array('auto'=>'Auto', + '1'=> '1 row', '2'=> '2 rows', '3'=> '3 rows', '4'=> '4 rows', '5'=> '5 rows', '6'=> '6 rows', '7'=> '7 rows', '8'=> '8 rows', '9'=> '9 rows', '10'=>'10 rows', + '11'=>'11 rows', '12'=>'12 rows', '13'=>'13 rows', '14'=>'14 rows', '15'=>'15 rows', '16'=>'16 rows', '17'=>'17 rows', '18'=>'18 rows', '19'=>'19 rows', '20'=>'20 rows', + '21'=>'21 rows', '22'=>'22 rows', '23'=>'23 rows', '24'=>'24 rows', '25'=>'25 rows', '26'=>'26 rows', '27'=>'27 rows', '28'=>'28 rows', '29'=>'29 rows', '30'=>'30 rows', + '31'=>'31 rows', '32'=>'32 rows', '33'=>'33 rows', '34'=>'34 rows', '35'=>'35 rows', '36'=>'36 rows', '37'=>'37 rows', '38'=>'38 rows', '39'=>'39 rows', '40'=>'40 rows', + '41'=>'41 rows', '42'=>'42 rows', '43'=>'43 rows', '44'=>'44 rows', '45'=>'45 rows', '46'=>'46 rows', '47'=>'47 rows', '48'=>'48 rows', '49'=>'49 rows', '50'=>'50 rows'); + + $offset_col = array( + 'inherit' => 'Inherit', + '0' => '0 cols', + '1' => '1 col', + '2' => '2 cols', + '3' => '3 cols', + '4' => '4 cols', + '5' => '5 cols', + '6' => '6 cols', + '7' => '7 cols', + '8' => '8 cols', + '9' => '9 cols', + '10' => '10 cols', + '11' => '11 cols', + '12' => '12 cols'); + $offset_col_xs = array( + '0' => '0 cols', + '1' => '1 col', + '2' => '2 cols', + '3' => '3 cols', + '4' => '4 cols', + '5' => '5 cols', + '6' => '6 cols', + '7' => '7 cols', + '8' => '8 cols', + '9' => '9 cols', + '10' => '10 cols', + '11' => '11 cols', + '12' => '12 cols'); + + $offset_row = array('inherit'=>'Inherit', '0'=>'0 rows', + '-25'=>'-25 rows', '-24'=>'-24 rows', '-23'=>'-23 rows', '-22'=>'-22 rows', '-21'=>'-20 rows', + '-19'=>'-19 rows', '-18'=>'-18 rows', '-17'=>'-17 rows', '-16'=>'-16 rows', '-16'=>'-16 rows', + '-15'=>'-15 rows', '-14'=>'-14 rows', '-13'=>'-13 rows', '-12'=>'-12 rows', '-11'=>'-11 rows', + '-10'=>'-10 rows', '-9'=> '-9 rows', '-8'=> '-8 rows', '-7'=> '-7 rows', '-6'=> '-6 rows', + '-5'=> '-5 rows', '-4'=> '-4 rows', '-3'=> '-3 rows', '-2'=> '-2 rows', '-1'=> '-1 row', + '1'=> '1 row', '2'=> '2 rows', '3'=> '3 rows', '4'=> '4 rows', '5'=> '5 rows', + '6'=> '6 rows', '7'=> '7 rows', '8'=> '8 rows', '9'=> '9 rows', '10'=> '10 rows', + '11'=> '11 rows', '12'=> '12 rows', '13'=> '13 rows', '14'=> '14 rows', '15'=> '15 rows', + '16'=> '16 rows', '17'=> '17 rows', '18'=> '18 rows', '19'=> '19 rows', '20'=> '20 rows', + '21'=> '21 rows', '22'=> '22 rows', '23'=> '23 rows', '24'=> '24 rows', '25'=> '25 rows'); + + $offset_row_xs = array('0'=>'0 rows', + '-25'=>'-25 rows', '-24'=>'-24 rows', '-23'=>'-23 rows', '-22'=>'-22 rows', '-21'=>'-20 rows', + '-19'=>'-19 rows', '-18'=>'-18 rows', '-17'=>'-17 rows', '-16'=>'-16 rows', '-16'=>'-16 rows', + '-15'=>'-15 rows', '-14'=>'-14 rows', '-13'=>'-13 rows', '-12'=>'-12 rows', '-11'=>'-11 rows', + '-10'=>'-10 rows', '-9'=> '-9 rows', '-8'=> '-8 rows', '-7'=> '-7 rows', '-6'=> '-6 rows', + '-5'=> '-5 rows', '-4'=> '-4 rows', '-3'=> '-3 rows', '-2'=> '-2 rows', '-1'=> '-1 row', + '1'=> '1 row', '2'=> '2 rows', '3'=> '3 rows', '4'=> '4 rows', '5'=> '5 rows', + '6'=> '6 rows', '7'=> '7 rows', '8'=> '8 rows', '9'=> '9 rows', '10'=> '10 rows', + '11'=> '11 rows', '12'=> '12 rows', '13'=> '13 rows', '14'=> '14 rows', '15'=> '15 rows', + '16'=> '16 rows', '17'=> '17 rows', '18'=> '18 rows', '19'=> '19 rows', '20'=> '20 rows', + '21'=> '21 rows', '22'=> '22 rows', '23'=> '23 rows', '24'=> '24 rows', '25'=> '25 rows'); + + $pull = array( + 'inherit' => 'Inherit', + 'none' => 'None', + 'right' => 'Right', + 'left' => 'Left'); + $pull_xs = array( + 'none' => 'None', + 'right' => 'Right', + 'left' => 'Left'); + + switch ($name) { + case 'col': return $col; + case 'col_xs': return $col_xs; + case 'row': return $row; + case 'row_xs': return $row_xs; + case 'offset_col': return $offset_col; + case 'offset_col_xs': return $offset_col_xs; + case 'offset_row': return $offset_row; + case 'offset_row_xs': return $offset_row_xs; + case 'pull': return $pull; + case 'pull_xs': return $pull_xs; + } + } +} +?> diff --git a/app/models/page_template.php b/app/models/page_template.php new file mode 100644 index 0000000..11b2675 --- /dev/null +++ b/app/models/page_template.php @@ -0,0 +1,27 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class PageTemplate extends NModel { + function __construct() { + $this->__table = 'page_template'; + $this->setHeadline('template_name'); + parent::__construct(); + } +} +?> \ No newline at end of file diff --git a/app/models/page_template_containers.php b/app/models/page_template_containers.php new file mode 100644 index 0000000..5a459ad --- /dev/null +++ b/app/models/page_template_containers.php @@ -0,0 +1,28 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class PageTemplateContainers extends NModel { + function __construct() { + $this->__table = 'page_template_containers'; + $this->setHeadline('container_name'); + $this->form_elements['page_template_id'] = array('foreignkey', 'page_template_id', 'Page Template:', array('model'=>'page_template', 'headline'=>'template_name', 'addEmptyOption'=>false)); + parent::__construct(); + } +} +?> \ No newline at end of file diff --git a/app/models/permissions.php b/app/models/permissions.php new file mode 100644 index 0000000..e45ec60 --- /dev/null +++ b/app/models/permissions.php @@ -0,0 +1,26 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class Permissions extends NModel { + function __construct() { + $this->__table = 'permissions'; + parent::__construct(); + } +} +?> \ No newline at end of file diff --git a/app/models/redirect.php b/app/models/redirect.php new file mode 100644 index 0000000..00758e7 --- /dev/null +++ b/app/models/redirect.php @@ -0,0 +1,47 @@ + + * @author Darron Froese + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class Redirect extends NModel { + function __construct() { + $this->__table = 'redirect'; + $this->form_ignore_fields[] = 'count'; + $this->not_connectable = true; + $this->form_rules[] = array('url', 'This is not a unique url', 'callback', array(&$this, 'validate_url')); + parent::__construct(); + } + + /** + * validate_url - Each URL must be unique. Having duplicates is a problem. + * This is called because it's set in $this->form_rules. + * + * @param string The value of the $url field. + * @return boolean + **/ + function validate_url($value) { + $this->url = $value; + if ($this->find()) { + return false; + } else { + return true; + } + } + +} +?> \ No newline at end of file diff --git a/app/models/test_sample.php b/app/models/test_sample.php new file mode 100644 index 0000000..f74080d --- /dev/null +++ b/app/models/test_sample.php @@ -0,0 +1,29 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class TestSample extends NModel { + function __construct() { + $this->__table = 'test_sample'; + parent::__construct(); + } + + function test_method(){ + return $this->cms_headline.' '.$this->the_text; + } +} diff --git a/app/models/workflow.php b/app/models/workflow.php new file mode 100644 index 0000000..0e5d546 --- /dev/null +++ b/app/models/workflow.php @@ -0,0 +1,31 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class Workflow extends NModel { + var $_order_by = 'workflow.id DESC'; + function __construct() { + $this->__table = 'workflow'; + $this->form_ignore_fields = array('page_id', 'page_content_id', 'workflow_group_id', 'asset', 'asset_id', 'action', 'draft', 'submitted', 'parent_workflow', 'completed'); + $this->form_elements['approved'] = array('select', 'workflow_approve', 'Approval', array('1'=>'Approve', '0'=>'Decline')); + $this->form_field_options['timed_start'] = array('addEmptyOption'=>true); + $this->form_field_options['timed_end'] = array('addEmptyOption'=>true); + parent::__construct(); + } +} +?> \ No newline at end of file diff --git a/app/models/workflow_group.php b/app/models/workflow_group.php new file mode 100644 index 0000000..b5173f9 --- /dev/null +++ b/app/models/workflow_group.php @@ -0,0 +1,28 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class WorkflowGroup extends NModel { + function __construct() { + $this->__table = 'workflow_group'; + $this->setHeadline('workflow_title'); + $this->_order_by = 'id'; + parent::__construct(); + } +} +?> \ No newline at end of file diff --git a/app/models/workflow_users.php b/app/models/workflow_users.php new file mode 100644 index 0000000..26c9d82 --- /dev/null +++ b/app/models/workflow_users.php @@ -0,0 +1,33 @@ + + * @copyright 2005-2007 nonfiction studios inc. + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version SVN: $Id$ + * @link http://www.nterchange.com/ + */ +class WorkflowUsers extends NModel { + function __construct() { + $this->__table = 'workflow_users'; + $this->_order_by = 'workflow_group_id, cms_created DESC'; + parent::__construct(); + // load the workgroup constants + include_once BASE_DIR . '/app/controllers/workflow_group_controller.php'; + $this->form_elements['workflow_group_id'] = array('foreignkey', 'workflow_group_id', 'Workflow Group', array('model'=>'workflow_group', 'headline'=>'workflow_title', 'addEmptyOption'=>true)); + $this->form_elements['user_id'] = array('foreignkey', 'user_id', 'User', array('model'=>'cms_auth', 'headline'=>'real_name', 'addEmptyOption'=>true)); + $this->form_elements['role'] = array('select', 'role', 'Role', array(''=>'Select...', WORKFLOW_ROLE_AUTHOR=>'Author', WORKFLOW_ROLE_EDITOR=>'Editor', WORKFLOW_ROLE_APPROVER=>'Approver')); + $this->form_required_fields = array('workflow_group_id', 'user_id', 'role'); + } +} +?> \ No newline at end of file diff --git a/app/views/audit_trail/audit_trail_record.html b/app/views/audit_trail/audit_trail_record.html new file mode 100755 index 0000000..ab6ab96 --- /dev/null +++ b/app/views/audit_trail/audit_trail_record.html @@ -0,0 +1,33 @@ +
    +
    + {$action_taken} +
    + {if $asset} +
    + {$asset_name}: + {if $asset.cms_deleted} + {$asset._headline} (deleted) + {else} + {link_to href="controller:`$asset_type`;action:show;id:`$asset.id`;" text=$asset._headline rel="blank"} + {/if} +
    + {/if} + {if $page} +
    + Page: + {if $page.cms_deleted == 0} + {link_to href="controller:page;action:surftoedit;id:`$page.id`;" text=$page.title rel="blank"} + {else} + {$page.title} (deleted) + {/if} +
    + {/if} + {if $workflow_group} +
    + Workflow Group: {$workflow_group.workflow_title} +
    + {/if} +
    + {$user.real_name} @ {$created|date_format:'%I:%M:%S %p on %F'} from the IP address: {$ip} +
    +
    diff --git a/app/views/audit_trail/page.html b/app/views/audit_trail/page.html new file mode 100644 index 0000000..e30cc6e --- /dev/null +++ b/app/views/audit_trail/page.html @@ -0,0 +1,3 @@ +{$rss_feed} + +{$audit_trail} \ No newline at end of file diff --git a/app/views/audit_trail/page_audit_trail_record.html b/app/views/audit_trail/page_audit_trail_record.html new file mode 100644 index 0000000..ab6ab96 --- /dev/null +++ b/app/views/audit_trail/page_audit_trail_record.html @@ -0,0 +1,33 @@ +
    +
    + {$action_taken} +
    + {if $asset} +
    + {$asset_name}: + {if $asset.cms_deleted} + {$asset._headline} (deleted) + {else} + {link_to href="controller:`$asset_type`;action:show;id:`$asset.id`;" text=$asset._headline rel="blank"} + {/if} +
    + {/if} + {if $page} +
    + Page: + {if $page.cms_deleted == 0} + {link_to href="controller:page;action:surftoedit;id:`$page.id`;" text=$page.title rel="blank"} + {else} + {$page.title} (deleted) + {/if} +
    + {/if} + {if $workflow_group} +
    + Workflow Group: {$workflow_group.workflow_title} +
    + {/if} +
    + {$user.real_name} @ {$created|date_format:'%I:%M:%S %p on %F'} from the IP address: {$ip} +
    +
    diff --git a/app/views/audit_trail/viewlist.html b/app/views/audit_trail/viewlist.html new file mode 100644 index 0000000..6fd26dc --- /dev/null +++ b/app/views/audit_trail/viewlist.html @@ -0,0 +1,13 @@ + +

    Your search on {$date|date_format:'%b %e, %Y'} found {$result_count} matches.

    +{$rss_feed} +{$audit_trail} diff --git a/app/views/ck_upload/image_browse.html b/app/views/ck_upload/image_browse.html new file mode 100644 index 0000000..bfbf25b --- /dev/null +++ b/app/views/ck_upload/image_browse.html @@ -0,0 +1,15 @@ + + +{literal} + +{/literal} + +

    {$title}

    +{$form} diff --git a/app/views/ck_upload/media_browse.html b/app/views/ck_upload/media_browse.html new file mode 100644 index 0000000..808b96a --- /dev/null +++ b/app/views/ck_upload/media_browse.html @@ -0,0 +1,20 @@ + + +{literal} + +{/literal} + +

    {$title}

    +{$form} diff --git a/app/views/cms_asset_info/viewlist.html b/app/views/cms_asset_info/viewlist.html new file mode 100644 index 0000000..0377bbb --- /dev/null +++ b/app/views/cms_asset_info/viewlist.html @@ -0,0 +1,14 @@ +New {$asset_name} + +
    +
      +{foreach from=$rows item=row} +
    • {$row._headline}     +{link_to href="controller:`$asset`;action:show;id:`$row.id`;" text="Show" class="control"} +{link_to href="controller:`$asset`;action:edit;id:`$row.id`;" text="Edit" class="control"} +{if !isset($row._remove_delete) || !$row._remove_delete} +{link_to href="controller:`$asset`;action:delete;id:`$row.id`;" text="Delete" class="control" confirm="Are you sure?"} +{/if} {check_asset_model asset=$row.asset} {check_asset_controller asset=$row.asset} {check_asset_table asset=$row.asset} +{/foreach} +
    +
    diff --git a/app/views/cms_asset_template/edit.html b/app/views/cms_asset_template/edit.html new file mode 100644 index 0000000..8933630 --- /dev/null +++ b/app/views/cms_asset_template/edit.html @@ -0,0 +1,5 @@ +

    Editing {$asset_name}

    + +{$form} + +List diff --git a/app/views/cms_asset_template/show.html b/app/views/cms_asset_template/show.html new file mode 100644 index 0000000..65254a7 --- /dev/null +++ b/app/views/cms_asset_template/show.html @@ -0,0 +1,10 @@ +

    Show {$asset_name}

    +{if $headline}

    {$headline}

    {/if} +
    +{foreach from=$row key=key item=val} +{$key|humanize}: {$val}
    +{/foreach} +
    + +Edit | +List \ No newline at end of file diff --git a/app/views/cms_asset_template/viewlist.html b/app/views/cms_asset_template/viewlist.html new file mode 100644 index 0000000..716a029 --- /dev/null +++ b/app/views/cms_asset_template/viewlist.html @@ -0,0 +1,16 @@ +{link_to href="controller:`$asset`;action:create;id:`$page_template_container_id`;" text="New `$asset_name`" class="btn btn-sm"} for container {$page_template_container_name} in template {$page_template_name} - {$page_template_filename}.html {check_template filename=`$page_template_filename`} + +{if $notice ne ''}{$notice}{/if} + +
    +
      +{foreach from=$rows item=row} +
    • {$row._headline}     +{link_to href="controller:`$asset`;action:edit;id:`$row.id`;" text="Edit" class="control"} +{if !isset($row._remove_delete) || !$row._remove_delete} +{link_to href="controller:`$asset`;action:delete;id:`$row.id`;" text="Delete" class="control" confirm="Are you sure?"} +{/if} + - {$row.template_filename}.html {check_asset_template filename=$row.template_filename asset=$row.asset} {check_asset_template_use asset=`$row._headline` container_id=`$page_template_container_id`} +{/foreach} +
    +
    diff --git a/app/views/code_caller/default.html b/app/views/code_caller/default.html new file mode 100644 index 0000000..be51f80 --- /dev/null +++ b/app/views/code_caller/default.html @@ -0,0 +1,3 @@ +{$_EDIT_START_} +{$content} +{$_EDIT_END_} diff --git a/app/views/content/list_assets.html b/app/views/content/list_assets.html new file mode 100644 index 0000000..087e9fe --- /dev/null +++ b/app/views/content/list_assets.html @@ -0,0 +1,7 @@ +
    + +
    \ No newline at end of file diff --git a/app/views/dashboard/dashboard_client_content.html b/app/views/dashboard/dashboard_client_content.html new file mode 100644 index 0000000..941862d --- /dev/null +++ b/app/views/dashboard/dashboard_client_content.html @@ -0,0 +1 @@ + diff --git a/app/views/dashboard/dashboard_client_sidebar_content.html b/app/views/dashboard/dashboard_client_sidebar_content.html new file mode 100644 index 0000000..56d7096 --- /dev/null +++ b/app/views/dashboard/dashboard_client_sidebar_content.html @@ -0,0 +1 @@ + diff --git a/app/views/dashboard/description.html b/app/views/dashboard/description.html new file mode 100644 index 0000000..c660252 --- /dev/null +++ b/app/views/dashboard/description.html @@ -0,0 +1,12 @@ +

    The Dashboard

    + +

    +The Dashboard is your nterchange home page. It gives you an overview of what the website is doing and provides the links to where you can find out more. +

    + +{if $drafts} +

    Drafts

    +

    +Any Drafts that you have saved appear here as a reminder that they are waiting for your completion. +

    +{/if} \ No newline at end of file diff --git a/app/views/dashboard/draft_record.html b/app/views/dashboard/draft_record.html new file mode 100644 index 0000000..5006b92 --- /dev/null +++ b/app/views/dashboard/draft_record.html @@ -0,0 +1,13 @@ +
    +You have the {$asset} asset named "{$cms_headline}" saved as a draft. +
    +  {link_to href="controller:`$asset`;action:show;id:`$id`;" text="Show" referer=1} +| {link_to href="controller:`$asset`;action:edit;id:`$id`;" text="Edit" referer=1} +{if $cms_draft} +{assign var="delete_msg" value="Since this content has never been published, it will be completely deleted.\\n\\nAre you sure?"} +{else} +{assign var="delete_msg" value="Are you sure?"} +{/if} +| {link_to href="controller:cms_drafts;action:delete;id:`$draft.id`;" text="Delete Draft" confirm="`$delete_msg`" referer=1} +
    +
    \ No newline at end of file diff --git a/app/views/dashboard/index.html b/app/views/dashboard/index.html new file mode 100644 index 0000000..e7767c6 --- /dev/null +++ b/app/views/dashboard/index.html @@ -0,0 +1,14 @@ +{if $drafts} +

    Drafts

    + {$drafts} +{/if} + +{version_check} + +{if $workflow} +

    Workflow Groups

    +{$workflow} +{/if} + +{* To put client data in the main content area - look in app/views/dashboard/dashboard_client_content.html *} +{dashboard_client_content} \ No newline at end of file diff --git a/app/views/dashboard/no_drafts.html b/app/views/dashboard/no_drafts.html new file mode 100644 index 0000000..08b7cb7 --- /dev/null +++ b/app/views/dashboard/no_drafts.html @@ -0,0 +1,3 @@ +

    +You do not have any drafts saved. +

    \ No newline at end of file diff --git a/app/views/dashboard/no_workflows.html b/app/views/dashboard/no_workflows.html new file mode 100644 index 0000000..dc7faed --- /dev/null +++ b/app/views/dashboard/no_workflows.html @@ -0,0 +1,3 @@ +

    +You do not belong to any workflow groups. +

    \ No newline at end of file diff --git a/app/views/dashboard/nterchange_training.html b/app/views/dashboard/nterchange_training.html new file mode 100644 index 0000000..b9c0052 --- /dev/null +++ b/app/views/dashboard/nterchange_training.html @@ -0,0 +1,5 @@ +

    nterchange Training

    + + \ No newline at end of file diff --git a/app/views/dashboard/workflow.html b/app/views/dashboard/workflow.html new file mode 100644 index 0000000..dfdc66f --- /dev/null +++ b/app/views/dashboard/workflow.html @@ -0,0 +1 @@ +

    {$workflow_title}

    diff --git a/app/views/dashboard/workflow_description.html b/app/views/dashboard/workflow_description.html new file mode 100644 index 0000000..9cdbd8f --- /dev/null +++ b/app/views/dashboard/workflow_description.html @@ -0,0 +1,4 @@ +

    Workflow

    +

    +Workflow controls the process that content takes to be published on the website. +

    \ No newline at end of file diff --git a/app/views/dashboard/workflow_norecords.html b/app/views/dashboard/workflow_norecords.html new file mode 100644 index 0000000..48223b0 --- /dev/null +++ b/app/views/dashboard/workflow_norecords.html @@ -0,0 +1,3 @@ +
    +There are no workflows currently in process for this group. +
    \ No newline at end of file diff --git a/app/views/dashboard/workflow_page_submit.html b/app/views/dashboard/workflow_page_submit.html new file mode 100755 index 0000000..fb74c7c --- /dev/null +++ b/app/views/dashboard/workflow_page_submit.html @@ -0,0 +1,7 @@ +{if $page_workflows} + +{/if} \ No newline at end of file diff --git a/app/views/dashboard/workflow_record.html b/app/views/dashboard/workflow_record.html new file mode 100644 index 0000000..91175df --- /dev/null +++ b/app/views/dashboard/workflow_record.html @@ -0,0 +1,29 @@ +{if $page_title} +
    +{$page_title} +
    +{/if} +
    +"{$row.cms_headline}" {if $asset->page_title}{$asset->page_title}{else}{$asset->name|humanize}{/if} asset on "{if !$page.cms_deleted}{$page.title}{else}{$page.title}{/if}" was {$action} @ {$workflow.cms_created|date_format:'%b %e, %Y %I:%M:%S %p'}{if $user} by {$user.real_name}{/if}. +{if !$list_only} +
    +  {link_to href="controller:page;action:surftoedit;id:`$page.id`;" text="Preview Page" rel="blank"} +{if $process == 'submit'} +| {link_to href="controller:workflow;action:submit;id:`$workflow.id`;" text="Submit To Workflow"} +| {link_to href="controller:`$asset->name`;action:edit;id:`$row.id`;" text="Edit Record" referer=1} +{if $cascade_delete} +| {link_to href="controller:workflow;action:delete;id:`$workflow.id`;" text="Delete Workflow" referer=1 confirm="Since this content has not yet been published on this page, it will also be removed from the page.\\n\\nAre you sure?"} +{else} +| {link_to href="controller:workflow;action:delete;id:`$workflow.id`;" text="Delete Workflow" referer=1 confirm="Are you sure?"} +{/if} +{elseif $process == 'editapprove'} +| {link_to href="controller:workflow;action:process;id:`$workflow.id`;" text="Edit & Approve/Decline"} +{elseif $process == 'approve'} +| {link_to href="controller:workflow;action:process;id:`$workflow.id`;" text="Approve/Decline"} +{elseif $process} +| {$process} +{/if} +
    +{/if} +
    + diff --git a/app/views/dashboard/workflow_section.html b/app/views/dashboard/workflow_section.html new file mode 100644 index 0000000..020df06 --- /dev/null +++ b/app/views/dashboard/workflow_section.html @@ -0,0 +1 @@ +
    {$workflow_section}
    \ No newline at end of file diff --git a/app/views/imageviewer/index.php b/app/views/imageviewer/index.php new file mode 100644 index 0000000..9ba34c1 --- /dev/null +++ b/app/views/imageviewer/index.php @@ -0,0 +1,68 @@ +$path) { + $i = $num+1; + if ($key == $num) { + $directions .= ' ' . $i; + } else { + $directions .= ' ' . $i . ''; + } + } +} +?> + + + + + Image Zoom<?php echo (($_GET['alt'])?' - ' . urldecode(stripslashes($_GET['alt'])):''); ?> + + + + + + + + + + + +
    + +<?php echo urldecode($alt); ?> border="0"> + +

    + +

    +
    + + + + diff --git a/app/views/layouts/default.html b/app/views/layouts/default.html new file mode 100644 index 0000000..7d8921a --- /dev/null +++ b/app/views/layouts/default.html @@ -0,0 +1,30 @@ +{include file="layouts/head" layout="default"} +{include file="layouts/navigation"} + +
    + +
    +
    +

    {$_TITLE_}

    + {dynamic}{if $_FLASH_.notice}
    {$_FLASH_.notice}
    {/if}{/dynamic} + {if $subnav} + {include file="layouts/subnav"} +
    + {/if} + {$MAIN_CONTENT} + {if $subnav} +
    + {/if} +
    +
     
    +
    + + {if $SIDEBAR_CONTENT} +
    +

    {$SIDEBAR_TITLE}

    + {$SIDEBAR_CONTENT} +
    + {/if} +
    + +{include file="layouts/tail"} diff --git a/app/views/layouts/head.html b/app/views/layouts/head.html new file mode 100644 index 0000000..cf30e3d --- /dev/null +++ b/app/views/layouts/head.html @@ -0,0 +1,44 @@ + + + + + + nterchange{if $_TITLE_} - {$_TITLE_}{/if} + + {stylesheet_link_tag href=screen} + {stylesheet_link_tag href=handheld media=handheld} + {stylesheet_link_tag href=nterchange_custom} + + + + + + + + + + {if $layout eq 'simple'} + {javascript_include_tag src=workflow} + {javascript_include_tag src=page_content} + {javascript_include_tag src=nterchange} + {/if} + + {if $layout eq 'default' || $layout eq 'plain'} + + {javascript_include_tag src=datechooser/datechooser} + {javascript_include_tag src=nterchange} + {/if} + + {if $layout eq 'default'} + {javascript_include_tag src=utils} + {javascript_include_tag src=application} + {javascript_include_tag src=workflow} + {javascript_include_tag src=page_content} + {javascript_include_tag src=page} + {javascript_include_tag src=ckeditor/ckeditor} + {/if} + + {$HEADER} + + + diff --git a/app/views/layouts/login.html b/app/views/layouts/login.html new file mode 100644 index 0000000..5c529b0 --- /dev/null +++ b/app/views/layouts/login.html @@ -0,0 +1,28 @@ +{include file="layouts/head" layout="login"} +{include file="layouts/navigation"} +{literal}{/literal} + +{if $_FLASH_.notice}
    {$_FLASH_.notice}
    {/if} + +
    +
    +
    +

    {$_TITLE_}

    + {$MAIN_CONTENT} + {if !$forgot} + + {/if} + {php} + print '
    ' . "\n"; + print 'Browser: ' . $_SERVER['HTTP_USER_AGENT'] . "
    \n"; + print 'IP: ' . $_SERVER['REMOTE_ADDR'] . "\n"; + print "
    \n"; + {/php} +
    +
     
    +
    +
    + +{include file="layouts/tail"} diff --git a/app/views/layouts/logo.html b/app/views/layouts/logo.html new file mode 100644 index 0000000..75cfeaa --- /dev/null +++ b/app/views/layouts/logo.html @@ -0,0 +1,3 @@ + diff --git a/app/views/layouts/navigation.html b/app/views/layouts/navigation.html new file mode 100644 index 0000000..5000974 --- /dev/null +++ b/app/views/layouts/navigation.html @@ -0,0 +1,15 @@ + diff --git a/app/views/layouts/plain.html b/app/views/layouts/plain.html new file mode 100644 index 0000000..eb9a1a7 --- /dev/null +++ b/app/views/layouts/plain.html @@ -0,0 +1,20 @@ +{include file="layouts/head" layout="plain"} +{include file="layouts/navigation"} + +
    +
    +
    +

    {$_TITLE_}

    + {if $_FLASH_.notice}
    {$_FLASH_.notice}
    {/if} + {$MAIN_CONTENT} +
    +
     
    +
    + {if $SIDEBAR_CONTENT} +
    + {$SIDEBAR_CONTENT} +
    + {/if} +
    + +{include file="layouts/tail"} diff --git a/app/views/layouts/previewobject.html b/app/views/layouts/previewobject.html new file mode 100755 index 0000000..217bfd4 --- /dev/null +++ b/app/views/layouts/previewobject.html @@ -0,0 +1,14 @@ + + + + + + Content Preview + {stylesheet_link_tag href=reset} + {stylesheet_link_tag href=default} + {javascript_include_tag src=utils} + {javascript_include_tag src=application} + + +{$MAIN_CONTENT} + diff --git a/app/views/layouts/simple.html b/app/views/layouts/simple.html new file mode 100644 index 0000000..d515027 --- /dev/null +++ b/app/views/layouts/simple.html @@ -0,0 +1,16 @@ +{include file="layouts/head" layout="simple"} + +
    +
    +
    +

    {$_TITLE_}

    + {if $_FLASH_.notice}
    {$_FLASH_.notice}
    {/if} + {$MAIN_CONTENT} +
    +
     
    +
    +
    +
     
    + + + diff --git a/app/views/layouts/subnav.html b/app/views/layouts/subnav.html new file mode 100644 index 0000000..3772618 --- /dev/null +++ b/app/views/layouts/subnav.html @@ -0,0 +1,9 @@ +{if $subnav} + +{/if} diff --git a/app/views/layouts/tail.html b/app/views/layouts/tail.html new file mode 100644 index 0000000..fa5e479 --- /dev/null +++ b/app/views/layouts/tail.html @@ -0,0 +1,9 @@ +
     
    + + + diff --git a/app/views/page/children_container.html b/app/views/page/children_container.html new file mode 100644 index 0000000..a8577a3 --- /dev/null +++ b/app/views/page/children_container.html @@ -0,0 +1,26 @@ + + + + New Page + + +{if is_array($pages) && count($pages) > 1} + + Re-order + +{/if} +{if is_array($pages) && count($pages)} +
    +
      + {foreach from=$pages item=page name=pages} +
    • +
      + + {if $page.active == 0}{$page.title|string_format:'[%s]'}{elseif $page.visible == 0}{$page.title|string_format:'(%s)'}{else}{$page.title}{/if} +
      +
    • + {/foreach} +
    +
    +{/if} + + diff --git a/app/views/page/content_container.html b/app/views/page/content_container.html new file mode 100644 index 0000000..55aa834 --- /dev/null +++ b/app/views/page/content_container.html @@ -0,0 +1,29 @@ +{if $reorder_link} + + Re-order + +{/if} + +{if is_array($contents) && !empty($contents)} +
    +
      + {foreach from=$contents item=content name=content} +
    • + {if !$no_edit} + + {/if} +
      + + {$content.cms_headline} ({$content._asset_name}) +
      +
    • + {/foreach} +
    +
    +{/if} + + diff --git a/app/views/page/content_container_title.html b/app/views/page/content_container_title.html new file mode 100644 index 0000000..ea70e58 --- /dev/null +++ b/app/views/page/content_container_title.html @@ -0,0 +1,2 @@ +

    {$container.container_name}

    + diff --git a/app/views/page/reorder_close.html b/app/views/page/reorder_close.html new file mode 100644 index 0000000..5c2dc1f --- /dev/null +++ b/app/views/page/reorder_close.html @@ -0,0 +1,4 @@ + + diff --git a/app/views/page/sidebar.html b/app/views/page/sidebar.html new file mode 100755 index 0000000..9a506fd --- /dev/null +++ b/app/views/page/sidebar.html @@ -0,0 +1,32 @@ +{if $surfedit && $page_id} +

    Surf to Edit

    +{link_to href="controller:page;action:surftoedit;id:`$page_id`;" text="Surf to Edit this page" rel="blank"} +{/if} + +{if $breadcrumbs} +

    Breadcrumbs

    + +{/if} + +{if $children} +

    Child Pages

    +
    +{foreach from=$children key=k item=child} +{if $k > 0} | {/if} +{assign var=title value=$child.title} +{if $child.visible == 0}{assign var=title value="(`$child.title`)"}{/if} +{if $child.active == 0}{assign var=title value="[`$child.title`]"}{/if} +{link_to href="action:`$action`;id:`$child.id`;" text=$title} +{/foreach} +
    +{/if} + +

    Utilities

    +

    {link_to href="controller:audit_trail;action:page;id:`$page_id`;" text="Page History"}

    +

    {link_to href="controller:page;action:delete_page_cache;id:`$page_id`;" text="Delete Page Cache"}

    \ No newline at end of file diff --git a/app/views/page/surftoedit.html b/app/views/page/surftoedit.html new file mode 100755 index 0000000..f2ee269 --- /dev/null +++ b/app/views/page/surftoedit.html @@ -0,0 +1,7 @@ + diff --git a/app/views/page_content/asset_add.html b/app/views/page_content/asset_add.html new file mode 100644 index 0000000..a6d47a8 --- /dev/null +++ b/app/views/page_content/asset_add.html @@ -0,0 +1,20 @@ + diff --git a/app/views/page_content/asset_edit.html b/app/views/page_content/asset_edit.html new file mode 100644 index 0000000..933756e --- /dev/null +++ b/app/views/page_content/asset_edit.html @@ -0,0 +1,14 @@ +
    + diff --git a/app/views/page_content/form.html b/app/views/page_content/form.html new file mode 100644 index 0000000..ba911ec --- /dev/null +++ b/app/views/page_content/form.html @@ -0,0 +1 @@ +{$form} \ No newline at end of file diff --git a/app/views/page_template/viewlist.html b/app/views/page_template/viewlist.html new file mode 100644 index 0000000..8ceb7f1 --- /dev/null +++ b/app/views/page_template/viewlist.html @@ -0,0 +1,15 @@ +New {$asset_name} + +
    +
      +{foreach from=$rows item=row} +
    • {$row._headline}     +{link_to href="controller:`$asset`;action:edit;id:`$row.id`;" text="Edit" class="control"} +{if !isset($row._remove_delete) || !$row._remove_delete} +{link_to href="controller:`$asset`;action:delete;id:`$row.id`;" text="Delete" class="control" confirm="Are you sure?"} +{/if} +{link_to href="controller:page_template_containers;action:viewlist;id:`$row.id`;" text="Containers" class="control"} + - {$row.template_filename}.html {check_template filename=$row.template_filename} +{/foreach} +
    +
    diff --git a/app/views/page_template_containers/edit.html b/app/views/page_template_containers/edit.html new file mode 100644 index 0000000..0f1b37b --- /dev/null +++ b/app/views/page_template_containers/edit.html @@ -0,0 +1,5 @@ +

    Editing {$asset_name}

    + +{$form} + +List \ No newline at end of file diff --git a/app/views/page_template_containers/show.html b/app/views/page_template_containers/show.html new file mode 100644 index 0000000..bff3c6c --- /dev/null +++ b/app/views/page_template_containers/show.html @@ -0,0 +1,10 @@ +

    Show {$asset_name}

    +{if $headline}

    {$headline}

    {/if} +
    +{foreach from=$row key=key item=val} +{$key|humanize}: {$val}
    +{/foreach} +
    + +Edit | +List \ No newline at end of file diff --git a/app/views/page_template_containers/viewlist.html b/app/views/page_template_containers/viewlist.html new file mode 100644 index 0000000..1aca21f --- /dev/null +++ b/app/views/page_template_containers/viewlist.html @@ -0,0 +1,17 @@ +{link_to href="controller:`$asset`;action:create;id:`$page_template_id`;" text="New `$asset_name`" class="btn btn-sm"} for template {$page_template_name} - {$page_template_filename}.html {check_template filename=$page_template_filename} + +{if $notice ne ''}{$notice}{/if} + +
    +
      +{foreach from=$rows item=row} +
    • {$row._headline}     +{link_to href="controller:`$asset`;action:edit;id:`$row.id`;" text="Edit" class="control"} +Delete +{*{if !isset($row._remove_delete) || !$row._remove_delete} +{link_to href="controller:`$asset`;action:delete;id:`$row.id`;" text="Delete" class="control" confirm="Are you sure?"} +{/if}*} +{link_to href="controller:cms_asset_template;action:viewlist;id:`$row.id`;" text="Connected Assets" class="control"}
    • +{/foreach} +
    +
    diff --git a/app/views/rss/audit_trail.html b/app/views/rss/audit_trail.html new file mode 100644 index 0000000..22c0694 --- /dev/null +++ b/app/views/rss/audit_trail.html @@ -0,0 +1,21 @@ + + + + audit trail rss feed - {$_SITE_NAME_} + + {$smarty.now|date_format:'%Y-%m-%d'}T00:00:00-07:00 + + nterchange + do-not-reply@nterchange.com + + urn:uuid:{$smarty.server.SERVER_NAME} +{foreach from=$records item=record} + + {$record.user.real_name} {$record.action_taken} a {$record.asset_name} + + urn:uuid:{$smarty.server.SERVER_NAME}:audit_trail{$record.id} + {$record.cms_created}T00:00:00-07:00 + {$record.user_id} {$record.action_taken} a {$record.asset_type} (id: {$record.asset.id}) on {if $record.page ne ''}page {$record.page.title} {/if}from IP address {$record.ip} at {$record.created} + +{/foreach} + \ No newline at end of file diff --git a/app/views/settings/viewlist.html b/app/views/settings/viewlist.html new file mode 100644 index 0000000..3b0a8fe --- /dev/null +++ b/app/views/settings/viewlist.html @@ -0,0 +1,7 @@ +

    +Below are the available Settings that allow you to customize how nterchange works for you. +

    + +{foreach from=$settings item=setting} +{$setting->toHTML()} +{/foreach} diff --git a/app/views/site_admin/clear_all_cache.html b/app/views/site_admin/clear_all_cache.html new file mode 100644 index 0000000..65bacc4 --- /dev/null +++ b/app/views/site_admin/clear_all_cache.html @@ -0,0 +1,9 @@ +

    +Caches have been cleared from: +

    + +
      +
    • Template compiling directory
    • +
    • View cache
    • +
    • ntercache
    • +
    diff --git a/app/views/site_admin/site_admin.html b/app/views/site_admin/site_admin.html new file mode 100644 index 0000000..340c864 --- /dev/null +++ b/app/views/site_admin/site_admin.html @@ -0,0 +1,19 @@ +

    +{if $page_edit} + + Surf To Edit + + + + New Page + +{/if} +{if $user_level >= 2} + + Clear All Caches + +{/if} +

    +{$content} +
    +{$sitemap_list} +
    diff --git a/app/views/site_admin/site_admin_list_end.html b/app/views/site_admin/site_admin_list_end.html new file mode 100644 index 0000000..776b4ca --- /dev/null +++ b/app/views/site_admin/site_admin_list_end.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/views/site_admin/site_admin_list_start.html b/app/views/site_admin/site_admin_list_start.html new file mode 100644 index 0000000..b9ee825 --- /dev/null +++ b/app/views/site_admin/site_admin_list_start.html @@ -0,0 +1,2 @@ +
    ',CKEDITOR.document);a.appendTo(CKEDITOR.document.getHead());try{var e=a.getComputedStyle("border-top-color"),b=a.getComputedStyle("border-right-color");CKEDITOR.env.hc=!!(e&&e==b)}catch(c){CKEDITOR.env.hc=false}a.remove()}if(CKEDITOR.env.hc)CKEDITOR.env.cssClass=CKEDITOR.env.cssClass+" cke_hc"; +CKEDITOR.document.appendStyleText(".cke{visibility:hidden;}");CKEDITOR.status="loaded";CKEDITOR.fireOnce("loaded");if(a=CKEDITOR._.pending){delete CKEDITOR._.pending;for(e=0;ec;c++){var f=a,h=c,d;d=parseInt(a[c],16);d=("0"+(0>e?0|d*(1+e):0|d+(255-d)*e).toString(16)).slice(-2);f[h]=d}return"#"+a.join("")}}(),c=function(){var b=new CKEDITOR.template("background:#{to};background-image:-webkit-gradient(linear,lefttop,leftbottom,from({from}),to({to}));background-image:-moz-linear-gradient(top,{from},{to});background-image:-webkit-linear-gradient(top,{from},{to});background-image:-o-linear-gradient(top,{from},{to});background-image:-ms-linear-gradient(top,{from},{to});background-image:linear-gradient(top,{from},{to});filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='{from}',endColorstr='{to}');");return function(c, +a){return b.output({from:c,to:a})}}(),f={editor:new CKEDITOR.template("{id}.cke_chrome [border-color:{defaultBorder};] {id} .cke_top [ {defaultGradient}border-bottom-color:{defaultBorder};] {id} .cke_bottom [{defaultGradient}border-top-color:{defaultBorder};] {id} .cke_resizer [border-right-color:{ckeResizer}] {id} .cke_dialog_title [{defaultGradient}border-bottom-color:{defaultBorder};] {id} .cke_dialog_footer [{defaultGradient}outline-color:{defaultBorder};border-top-color:{defaultBorder};] {id} .cke_dialog_tab [{lightGradient}border-color:{defaultBorder};] {id} .cke_dialog_tab:hover [{mediumGradient}] {id} .cke_dialog_contents [border-top-color:{defaultBorder};] {id} .cke_dialog_tab_selected, {id} .cke_dialog_tab_selected:hover [background:{dialogTabSelected};border-bottom-color:{dialogTabSelectedBorder};] {id} .cke_dialog_body [background:{dialogBody};border-color:{defaultBorder};] {id} .cke_toolgroup [{lightGradient}border-color:{defaultBorder};] {id} a.cke_button_off:hover, {id} a.cke_button_off:focus, {id} a.cke_button_off:active [{mediumGradient}] {id} .cke_button_on [{ckeButtonOn}] {id} .cke_toolbar_separator [background-color: {ckeToolbarSeparator};] {id} .cke_combo_button [border-color:{defaultBorder};{lightGradient}] {id} a.cke_combo_button:hover, {id} a.cke_combo_button:focus, {id} .cke_combo_on a.cke_combo_button [border-color:{defaultBorder};{mediumGradient}] {id} .cke_path_item [color:{elementsPathColor};] {id} a.cke_path_item:hover, {id} a.cke_path_item:focus, {id} a.cke_path_item:active [background-color:{elementsPathBg};] {id}.cke_panel [border-color:{defaultBorder};] "), +panel:new CKEDITOR.template(".cke_panel_grouptitle [{lightGradient}border-color:{defaultBorder};] .cke_menubutton_icon [background-color:{menubuttonIcon};] .cke_menubutton:hover .cke_menubutton_icon, .cke_menubutton:focus .cke_menubutton_icon, .cke_menubutton:active .cke_menubutton_icon [background-color:{menubuttonIconHover};] .cke_menuseparator [background-color:{menubuttonIcon};] a:hover.cke_colorbox, a:focus.cke_colorbox, a:active.cke_colorbox [border-color:{defaultBorder};] a:hover.cke_colorauto, a:hover.cke_colormore, a:focus.cke_colorauto, a:focus.cke_colormore, a:active.cke_colorauto, a:active.cke_colormore [background-color:{ckeColorauto};border-color:{defaultBorder};] ")}; +return function(g,e){var a=g.uiColor,a={id:"."+g.id,defaultBorder:b(a,-0.1),defaultGradient:c(b(a,0.9),a),lightGradient:c(b(a,1),b(a,0.7)),mediumGradient:c(b(a,0.8),b(a,0.5)),ckeButtonOn:c(b(a,0.6),b(a,0.7)),ckeResizer:b(a,-0.4),ckeToolbarSeparator:b(a,0.5),ckeColorauto:b(a,0.8),dialogBody:b(a,0.7),dialogTabSelected:c("#FFFFFF","#FFFFFF"),dialogTabSelectedBorder:"#FFF",elementsPathColor:b(a,-0.6),elementsPathBg:a,menubuttonIcon:b(a,0.5),menubuttonIconHover:b(a,0.3)};return f[e].output(a).replace(/\[/g, +"{").replace(/\]/g,"}")}}();CKEDITOR.plugins.add("dialogui",{onLoad:function(){var i=function(b){this._||(this._={});this._["default"]=this._.initValue=b["default"]||"";this._.required=b.required||!1;for(var a=[this._],d=1;darguments.length)){var c=i.call(this,a);c.labelId=CKEDITOR.tools.getNextId()+"_label";this._.children=[];CKEDITOR.ui.dialog.uiElement.call(this,b,a,d,"div",null,{role:"presentation"},function(){var f=[],d=a.required?" cke_required":"";"horizontal"!= +a.labelLayout?f.push('",'
    ',e.call(this,b,a),"
    "):(d={type:"hbox",widths:a.widths,padding:0,children:[{type:"html",html:'

    VqMii{1*8CWtlFm7RCQf??4E>nQ;_mCi4bx7#`V1XLRCNffK`OxJL3Se5!ZY(hIj12aQH(zDZ|Y8jU|<-RuH zWZUU~tYT(S*!!gI&8I>pyjDIlRoyNpVDG{*e)(g~&lDIKBpP}2Lj_KUu2$!NWzP|J zVr^5n-b=f(Hw(mCSekg`7R|NbwB5}wW3hsrbC-aH1DEQF*_#uEYbVTSSM@Oa#E_)C z@sVlvF8->;46c=1jAEudxUhg@-qwm8Z6V5z3?WP+6$cKt!dhd?Hq3Hl=-hz zD?V%>b0Wiv!f+~k8b0h*Q1E3>%Je~)MTLP+3fise9%NJZ-BeWlQ68I^TwUSjQltQlptp)n6 ziDc(&>Sx07Cou2ZKL8xcWG$;2+*2igd~&e2^ZL1N=6>(x`nhf<2Ya6a-q?(Ct&%OK z5&GlTGcB$0JqHO!qS*gUks7(eqo+s5(6pvZ)>2zh-n#hj7{N#sfM6twa_5-O3^r0c zgNjiNKC^9mjJz|qGEf(5X8g)W0H2yhX!};+1K~s`^E2s{foSt1%>C8R)X?WGz-Oir z>NSm!Z5km}dhF6zoep3cp&sBQ&!Mgk2iWWrPLv3`p>@6uTN^$#5D>_Ybs3Bh$cEPTgxq;of;!G z`~%}{AM^Z?WBC1k0P^`feHXsr#iK7dI?$88d`1iUC5dNV!=rCo0R--U9Hcy=NY?LaXlqg!G1RysA6{JMU@|+H&{gDRj+&IY#AFQg@{XF#S33TbA zmK9e}Erg3wihw^*22a%(O-Rj4TUQVM;Jsy&lvse0*Gh`J!dpxreL(5}5+_ST(qG|vk z*5`GAOxBt*jnFH5U;qBn(1-2b-E9X6?`Qx(^Z1HjRk=#!2IsNTxH4JmM_+Kqd#x{@ zCpCNtYi1l2#R@5@mQt`dpJR4P(vy!q`Z7IL>ht@^Baebm%7QDZa{jP0ZT!NbgmdWMoicQ!6M+7A$qH=f@Jt^w}@ zuL9*X5sHd{4W600000NkvXXu0mjf DExzht literal 0 HcmV?d00001 diff --git a/nterchange/javascripts/ckeditor/plugins/smiley/images/tongue_smile.gif b/nterchange/javascripts/ckeditor/plugins/smiley/images/tongue_smile.gif new file mode 100644 index 0000000000000000000000000000000000000000..369b43508217c8045bd03478a212069579ed8fab GIT binary patch literal 1216 zcmc)J`A?Gv0LJmx($aPK)MFh(?+dnw;h}g2gJ)QjKV( zT7U{6bRy^^RHX!!o@BLbsX?;TsOJ<0o0&>l$9CqthX`n@o)-rBDq`{m?-0*~Yv zlw(Li4tryG14g_tpv15bMrkUH`Cwd$$21j;G+&r}F|iSov`wos{xGXCqlVcZGaulI zKYsJatUuMel^hRTdlCRs5GI1K6i9Z2!LS#GSlo-F9)3nnMo`mXw(d9>zouprZI9CM zBzeu8Vw*aKsSFrTQd6hMr)lIuCdN)8ujgQW3hM&iE@Sl% zP-~!Uph$oMK>SZryk)KN2*O|1t&pV2RCU$`|xcnBG@MU3)YJZ4$->uLCIk}bbC)Rld&iUA_+H*DX@?FaIbFAug zRm`RNt}Q!bHX9i!!_#|MJ*>X5qc;y_1ZY_$pI>GPd6s|kFR~mqltwvsXES8#uZo4? z{N!SfvElk?dqSEXy3QjaoW(nI!ujDg=B8r|#}=h!fM5y&PW!40yK)4+8!rpCx8?@i z&%eqMgc6K|a0YjMditLI{Mr2su6o*%M=&z7cX6Z{al9X|DDCXoK1m8sH)%Q%xi!K) c{(|3argOx`27$}7aJKBb@uDQ5tAP0AKd693O8@`> literal 0 HcmV?d00001 diff --git a/nterchange/javascripts/ckeditor/plugins/smiley/images/tongue_smile.png b/nterchange/javascripts/ckeditor/plugins/smiley/images/tongue_smile.png new file mode 100644 index 0000000000000000000000000000000000000000..5bee4c049e62a165432a5ea7b8457202aeefa8bb GIT binary patch literal 1206 zcmV;n1WEgeP)R`S(u;7aiE5dZ5ptFA%xp5s^rwxOxX;#zarb(N0 z`FHO*KHQr&EiDfG!I$6t!}%qf8-(j@+n&ht`%m|nfNJpHPfnEr@3LQuy7SuofhWF!#+`$}@r0SrtO<9(dYr$$XyfWBZSOfI*wTk6TtSrM zh~f>YHC-KlX-}Vphn)A7Gcj z)}R#FYB}SD@CVRx5Qbld`(J?e_XZPY{?!%maL{*{g~@ZA@6*=a7pc=XgiuM)+L2Og z7f=eC55SJk;D;W~!QTaqy9N?wen?EGa!yxhdy*gbhjddJ-O_@z;vfJGMkEUwdb)g| z6vpL6K-1ISuv~P&mg!5F@SF>;4u z!J=5OF~(9DVKT4_+0^U1a%ld+sd)R4*A zWU}`1eNH=Yt--pBj-Q2XPea-O=&g6*J(y8w@PKWtXwBBGUP9Y9JJ(yhpmoi?2TCPp z=1N1xK!=VXZk_|^S%#+#*jBHwl|;BtHAvfL;I)UH+5VFPr5SkTA?JNOxniNk!gcKJ zAzha?L@nG2<*t4;w081L%Iz4}g6Y|1uWPfYKxuYqc-3=*KsVei$*R})B(+l7vlYy! zAkYn9tb~^;HG^#~U&%2wRah51JyYgdtmxQcE3|AxWG7e+j}YjFLK$q^m15f?&5TC# z{Bm)gn^Q${Ig4D*Vk%MMw@Zs$953R3u*sRZ23_w*%uiO~k(y0pO>%x;2jj`vE)yDUg-a7qvCvwg>jO#_=Ol+NL377I!psjW$3;2PjfW1Jsn*sg=qHexe`)j*r`2UT60YM*Z Ut&PLbj{pDw07*qoM6N<$g5yL)asU7T literal 0 HcmV?d00001 diff --git a/nterchange/javascripts/ckeditor/plugins/smiley/images/tounge_smile.gif b/nterchange/javascripts/ckeditor/plugins/smiley/images/tounge_smile.gif new file mode 100644 index 0000000000000000000000000000000000000000..369b43508217c8045bd03478a212069579ed8fab GIT binary patch literal 1216 zcmc)J`A?Gv0LJmx($aPK)MFh(?+dnw;h}g2gJ)QjKV( zT7U{6bRy^^RHX!!o@BLbsX?;TsOJ<0o0&>l$9CqthX`n@o)-rBDq`{m?-0*~Yv zlw(Li4tryG14g_tpv15bMrkUH`Cwd$$21j;G+&r}F|iSov`wos{xGXCqlVcZGaulI zKYsJatUuMel^hRTdlCRs5GI1K6i9Z2!LS#GSlo-F9)3nnMo`mXw(d9>zouprZI9CM zBzeu8Vw*aKsSFrTQd6hMr)lIuCdN)8ujgQW3hM&iE@Sl% zP-~!Uph$oMK>SZryk)KN2*O|1t&pV2RCU$`|xcnBG@MU3)YJZ4$->uLCIk}bbC)Rld&iUA_+H*DX@?FaIbFAug zRm`RNt}Q!bHX9i!!_#|MJ*>X5qc;y_1ZY_$pI>GPd6s|kFR~mqltwvsXES8#uZo4? z{N!SfvElk?dqSEXy3QjaoW(nI!ujDg=B8r|#}=h!fM5y&PW!40yK)4+8!rpCx8?@i z&%eqMgc6K|a0YjMditLI{Mr2su6o*%M=&z7cX6Z{al9X|DDCXoK1m8sH)%Q%xi!K) c{(|3argOx`27$}7aJKBb@uDQ5tAP0AKd693O8@`> literal 0 HcmV?d00001 diff --git a/nterchange/javascripts/ckeditor/plugins/smiley/images/whatchutalkingabout_smile.gif b/nterchange/javascripts/ckeditor/plugins/smiley/images/whatchutalkingabout_smile.gif new file mode 100644 index 0000000000000000000000000000000000000000..2cc81c14f6812119c710e01609a0b26fd77c43ac GIT binary patch literal 1190 zcmdVZ`A^da00r&7YM>|c34i9vC zpi6{qF>Z-r^t5+Ka7%(N8PzPO405#jlFgxL*#<)-)v*N~QD{}dxC0%#(7v1O+JnwL zcC*ah=Zzi-Otg(K)1>H?qR*4;^+LZF24xuZ#*jCLee6SWa>$n)mSe;hqrSK;C&xBn z%nx@qVK@L|{TqyofU@jc@!f-Df^WjwAR&qQV zlS)h}VT&f)W6|{yx)RZyObx`7(;rZ?u?|x*te;WyM;s%W`18xPxeUk5H<| zIT1uJ5&Cxi+fNW&iYVZDDI>0!(pc`By+rEinz-%9BUk;I1xSPJ@eCrAurxftyVK~6`Q{pP$x$-onyvA;|edyE~phMNv89a5iQ4s@scg@ z9oTs~vS@qmKR+undR77xPB&fhX*%o`a^UJ>g{<@YHOeWQ!xyClpBK&Y`b+#i6@?%5 zUh97;I4I2fR{Hw5Mlir;X+PIrkKqb0AMKPre#+z9a^0TX*ZU+F1|;rEPgO`88+-W+ zy9ZU=ptKwlC+bv8g3465^_=E@nLx#LP5d<{IBM^!B4^1liJ9Y*rR`zf$U7uZBt=G; oSgui)97d95$uD1@)jYI*Tj<2_yWK|&mRQcl+LdAkn?>yW58nPPJpcdz literal 0 HcmV?d00001 diff --git a/nterchange/javascripts/ckeditor/plugins/smiley/images/whatchutalkingabout_smile.png b/nterchange/javascripts/ckeditor/plugins/smiley/images/whatchutalkingabout_smile.png new file mode 100644 index 0000000000000000000000000000000000000000..bebf74daa626292587f5a64c5e3921a73c1501a5 GIT binary patch literal 1113 zcmV-f1g86mP)2(5HZ@H)$);{?u%gA#B(~-gTC1pi zsP@4IDTrFd`lKKcrHW4?Mtl`NpuSl!;EN9_LbQU2H8IrOXtbs^rBc|eansz*Za153 zHhb?JAMV{`x2$O&JaCvh4EJ~Dod28|HM_7xC2NV))&U2AUZBT!0L%9Y;HS8q%~S*c zsuH{`g!dd|y_zddq9Rdd8b~aTJ?tx{BOCR3Jg+X!mo=`ORp>n^W z)?%pDDhYq z!4)tDT(dD!4J~g%<6#(m2JUzg+Fl!q+u7&J;4P8bqhw}=8R-+J>nW<_ic%&4BAy#l zIe;+`J_Nhphp&2s!#^nMTKkI{C=sbc+!?+;7?t`pq_Gk0#6ST8)4qnm|>x#_eoI0|%Hp8zpxE*%n0SW9vIxT`6FVUc(x@#%j)C zHRocDFJO(^tma%Wem0i}q4_}w24U`O)IY*#pqHctTdUDd5{%=e>>5%j#}iQ?m3B#` z-HrK@cyJMLR*=|f*zqtVE&Sdf0Q6u_LMRBXQ+7^o-(F30*Ea9Fxf(=D=0V8ky`39@ zl!Zi(p{@>t-*6s0X~B+w!8ID?lLfTv(*OM3-fsU{03-B2dzZH!OOy$%G8b`oMWrff zsZzLS##g^+BHlQ+;GY=31hexSwJsf10rK-@nQOqJsT)@Ex>)O5a#QXS+z$4nqNy9a zyQc)6FO>Z3-W7jO-t>rm-wO5p)uf~Ib`v<9{AdP?7)OJgq<*vul~Djw&u#gW6JC5>tNh+J&Zv)Yep~6Y4*Jh;r5}@yIq$gIY8UV7<&gHQ_$q{n+t0U6dW*B zn$Gv2?PLrXD6QI!k3}Q!3F$wcX7mL}PeGOT9tn*g0J}92=fRrNIZ~%+mILyPR+y(8E&G8 zFj4LeiWMn`3Z()S%3`hI!=JN!MrJjy5d#KI_% z7D}WYC2}J4^1j!XMlob3828RHr%O^GQA z%^~MQZb=ncqR5IY5lxg^&6HWrDfy@{h0+WUY33gu@=&<~RVz?UTL~2pk9erDKrJ7S z`A}NDQ>|K13Fc}=iz)$X1$Zn#jcBIUjw%yV3Nb2e$ueh@dqA;)Qhg59CRBJrxf!Z0 zsQ!wq@x~+Xg$5Do1gNL2LIcebjh1M#A{&Kh65=l*nuTZ)p~aePwLz;j+H7W;oyb;O zwA-SCCPt?iU9{DBvIcGT=(58TJ3OVWh1w1pdvx1Fxpr9vRZ`W z*q_wcA4}uEVCp(1GclcoXL*>E>RuJ%?@~;bW2!pCuG(G7VH(w2H{Pxk#yo6(W#Sf2ohl^Fykv;2z8}EoX{}zQyj)cY! z4h0pO=WmPuD0JE%c+E9yOqz4KLSC@jSF$vcp_N;je#fZFnZ11_Ww(DKiycQCjpT(j zt5Xju8?>waw;7uTs|$<>B3K?Y>mJxucCqS~kNw*^6B+wJ;>bS_WbHRX6ernJXPmCs zN-o5jhn#-?G|u3xV#|Twodz7^N8&oGq65^T!swZkn%j=;Hypg`+&FO|8(*#u2y5v( ze!eY9v_E$K*ty6ZudEr07bW{*5|Um<9L}*w-{sG9Nf&0@g@&D1{2+1+8#!t*G>6xrX>OB=S$a=@eMh qvDO$`1iLkRY*^cL&Alqy+|RUNO4=FE&p4edIdEoH=A)-ac>M>-s%%66 literal 0 HcmV?d00001 diff --git a/nterchange/javascripts/ckeditor/plugins/smiley/images/wink_smile.png b/nterchange/javascripts/ckeditor/plugins/smiley/images/wink_smile.png new file mode 100644 index 0000000000000000000000000000000000000000..805da9605880b395a2ab1495ec826dd0807cc215 GIT binary patch literal 1188 zcmV;V1Y7%wP)~^x%cLNe&?Lu_jisO9h+pXkxDd2fwe#{(Blgr?P~z|DeDvq za{>T07d(|{-ip`{$Q@7O41hBL`2p`^ycZI_k{fd<{X*6$e*UlURHC^Zc$dQY9h}?= zVHZ*lLwq%~t^uXs+G)5t2&3OXwFc`xg6O@6fL&RqI6f!b1IuZCd*>d`?iI6Qr(*tU zRQU|5nn6un00AOh(6k(4TOfZD`d<~6zoxkFWb3k zAHh_>2v`fo&PEy`wFhFGpzkTT^Ks~WG{1d|3L_c;nK0BZ(%ghOFj+r8qsbZtP936@>iAh+ZMCs z`7UCM+L$a^#wU!w8W^ASS0n;%3CSFQg%3eKjo%xDfF7Jdh=jqoGd9|=t`%$-b*Ki? z#JizX(HPHSW7mYQj^?SB4b$&#lC7777l1RUhGBwBAM0RVTZB)($TR#$nc}49BDZG9{avG6GP5%m zkWf47+VC`dAkakaFh|xTaes%Vh__+kFx%cCVueU~Mluj0A_KrGfs&k{u{uE7ct zNg~{i*0;gt{v0Z_Eb9~tv+X}IbeJQ((AsFxS|c8aSQOf$(9}r9RfI9~T%OVE6&&01!()TP(oQ4MN zT@o7cXR5INirQDg`UB9m{A1vytW&&tOL!p3cEsJ!#iI%GgUkp#H%#lUM;uh>#jI2O z>?X*q;C_O3U<0rU==LMPDPYi#Kiqh={U`YUG5!I(3wUsm2)vX40000'],d=0,g=b.length,h,e;d');for(var j=0;j'+h+''+e+"")}else f.push(' ');f.push("")}f.push("")}f.push("",''+l.options+"");this.getContentElement("info","charContainer").getElement().setHtml(f.join(""))},contents:[{id:"info",label:i.lang.common.generalTab, +title:i.lang.common.generalTab,padding:0,align:"top",elements:[{type:"hbox",align:"top",widths:["320px","90px"],children:[{type:"html",id:"charContainer",html:"",onMouseover:g,onMouseout:d,focus:function(){var c=this.getElement().getElementsByTag("a").getItem(0);setTimeout(function(){c.focus();g(null,c)},0)},onShow:function(){var c=this.getElement().getChild([0,0,0,0,0]);setTimeout(function(){c.focus();g(null,c)},0)},onLoad:function(c){e=c.sender}},{type:"hbox",align:"top",widths:["100%"],children:[{type:"vbox", +align:"top",children:[{type:"html",html:"