From 9d707d180073f84328935371edc05d20b22bc33b Mon Sep 17 00:00:00 2001 From: Llewellyn van der Merwe Date: Wed, 26 Jul 2023 11:09:42 +0200 Subject: [PATCH] aVersion 2 --- .octojpack | 69 + CHANGELOG.md | 11 + LICENSE.txt | 340 + README.md | 60 + admin/README.txt | 60 + admin/access.xml | 505 + admin/assets/css/admin.css | 21 + admin/assets/css/book.css | 19 + admin/assets/css/books.css | 19 + admin/assets/css/chapter.css | 19 + admin/assets/css/chapters.css | 19 + admin/assets/css/dashboard.css | 169 + admin/assets/css/index.html | 1 + admin/assets/css/linker.css | 19 + admin/assets/css/linkers.css | 19 + admin/assets/css/note.css | 19 + admin/assets/css/notes.css | 19 + admin/assets/css/open_ai_message.css | 19 + admin/assets/css/open_ai_messages.css | 19 + admin/assets/css/open_ai_response.css | 19 + admin/assets/css/open_ai_responses.css | 19 + admin/assets/css/password.css | 19 + admin/assets/css/passwords.css | 19 + admin/assets/css/prompt.css | 19 + admin/assets/css/prompts.css | 19 + admin/assets/css/tag.css | 19 + admin/assets/css/tagged_verse.css | 19 + admin/assets/css/tagged_verses.css | 19 + admin/assets/css/tags.css | 19 + admin/assets/css/translation.css | 19 + admin/assets/css/translations.css | 19 + admin/assets/css/verse.css | 19 + admin/assets/css/verses.css | 19 + admin/assets/images/ajax.gif | Bin 0 -> 65516 bytes admin/assets/images/icons/books.png | Bin 0 -> 26047 bytes admin/assets/images/icons/chapters.png | Bin 0 -> 16769 bytes admin/assets/images/icons/index.html | 1 + admin/assets/images/icons/linkers.png | Bin 0 -> 16792 bytes admin/assets/images/icons/notes.png | Bin 0 -> 18612 bytes .../assets/images/icons/open_ai_responses.png | Bin 0 -> 19033 bytes admin/assets/images/icons/prompts.png | Bin 0 -> 23423 bytes admin/assets/images/icons/tagged_verses.png | Bin 0 -> 20450 bytes admin/assets/images/icons/tags.png | Bin 0 -> 15341 bytes admin/assets/images/icons/translations.png | Bin 0 -> 22931 bytes admin/assets/images/icons/verses.png | Bin 0 -> 28629 bytes admin/assets/images/import.gif | Bin 0 -> 65516 bytes admin/assets/images/index.html | 1 + admin/assets/images/vdm-component.jpg | Bin 0 -> 13109 bytes admin/assets/index.html | 1 + admin/assets/js/admin.js | 17 + admin/assets/js/index.html | 1 + admin/config.xml | 1444 ++ admin/controller.php | 130 + admin/controllers/ajax.json.php | 247 + admin/controllers/book.php | 330 + admin/controllers/books.php | 52 + admin/controllers/chapter.php | 330 + admin/controllers/chapters.php | 52 + admin/controllers/getbible.php | 30 + admin/controllers/index.html | 1 + admin/controllers/linker.php | 330 + admin/controllers/linkers.php | 52 + admin/controllers/note.php | 330 + admin/controllers/notes.php | 52 + admin/controllers/open_ai_message.php | 330 + admin/controllers/open_ai_messages.php | 52 + admin/controllers/open_ai_response.php | 330 + admin/controllers/open_ai_responses.php | 52 + admin/controllers/password.php | 330 + admin/controllers/passwords.php | 52 + admin/controllers/prompt.php | 330 + admin/controllers/prompts.php | 52 + admin/controllers/tag.php | 330 + admin/controllers/tagged_verse.php | 330 + admin/controllers/tagged_verses.php | 52 + admin/controllers/tags.php | 52 + admin/controllers/translation.php | 330 + admin/controllers/translations.php | 52 + admin/controllers/verse.php | 330 + admin/controllers/verses.php | 52 + admin/getbible.php | 91 + admin/helpers/getbible.php | 1465 ++ admin/helpers/headercheck.php | 77 + admin/helpers/html/batch_.php | 84 + admin/helpers/html/index.html | 1 + admin/helpers/index.html | 1 + admin/index.html | 1 + admin/language/en-GB/en-GB.com_getbible.ini | 1853 +++ .../language/en-GB/en-GB.com_getbible.sys.ini | 523 + admin/language/en-GB/index.html | 1 + admin/language/index.html | 1 + admin/layouts/batchselection.php | 54 + admin/layouts/book/details_above.php | 51 + admin/layouts/book/details_left.php | 48 + admin/layouts/book/details_right.php | 48 + admin/layouts/book/index.html | 1 + admin/layouts/book/publishing.php | 52 + admin/layouts/book/publlshing.php | 53 + admin/layouts/chapter/details_above.php | 52 + admin/layouts/chapter/details_left.php | 48 + admin/layouts/chapter/details_right.php | 48 + admin/layouts/chapter/index.html | 1 + admin/layouts/chapter/publishing.php | 52 + admin/layouts/chapter/publlshing.php | 53 + admin/layouts/index.html | 1 + admin/layouts/linker/details_left.php | 48 + admin/layouts/linker/index.html | 1 + admin/layouts/linker/notes_fullwidth.php | 149 + admin/layouts/linker/passwords_fullwidth.php | 149 + admin/layouts/linker/publishing.php | 53 + admin/layouts/linker/publlshing.php | 53 + admin/layouts/linker/tags_fullwidth.php | 169 + admin/layouts/note/details_above.php | 51 + admin/layouts/note/details_left.php | 50 + admin/layouts/note/details_right.php | 48 + admin/layouts/note/index.html | 1 + admin/layouts/note/publishing.php | 53 + admin/layouts/note/publlshing.php | 52 + admin/layouts/open_ai_message/index.html | 1 + .../layouts/open_ai_message/message_above.php | 52 + .../open_ai_message/message_fullwidth.php | 50 + .../layouts/open_ai_message/message_left.php | 49 + .../layouts/open_ai_message/message_right.php | 48 + admin/layouts/open_ai_message/publishing.php | 52 + admin/layouts/open_ai_message/publlshing.php | 53 + admin/layouts/open_ai_response/bible_left.php | 51 + .../layouts/open_ai_response/bible_right.php | 51 + .../open_ai_response/details_above.php | 51 + .../layouts/open_ai_response/details_left.php | 50 + .../open_ai_response/details_right.php | 50 + admin/layouts/open_ai_response/index.html | 1 + .../open_ai_response/message_fullwidth.php | 147 + .../layouts/open_ai_response/prompt_left.php | 50 + .../layouts/open_ai_response/prompt_right.php | 51 + admin/layouts/open_ai_response/publishing.php | 52 + admin/layouts/open_ai_response/publlshing.php | 53 + admin/layouts/password/details_above.php | 50 + admin/layouts/password/details_left.php | 48 + admin/layouts/password/details_right.php | 48 + admin/layouts/password/index.html | 1 + admin/layouts/password/publishing.php | 53 + admin/layouts/password/publlshing.php | 53 + admin/layouts/prompt/index.html | 1 + admin/layouts/prompt/open_ai_left.php | 73 + admin/layouts/prompt/open_ai_right.php | 68 + admin/layouts/prompt/prompt_above.php | 51 + admin/layouts/prompt/prompt_fullwidth.php | 53 + admin/layouts/prompt/prompt_left.php | 53 + admin/layouts/prompt/prompt_right.php | 51 + admin/layouts/prompt/publishing.php | 53 + admin/layouts/prompt/publlshing.php | 53 + admin/layouts/tag/details_above.php | 51 + admin/layouts/tag/details_fullwidth.php | 50 + admin/layouts/tag/details_left.php | 48 + admin/layouts/tag/index.html | 1 + admin/layouts/tag/publishing.php | 53 + admin/layouts/tag/publlshing.php | 52 + admin/layouts/tagged_verse/details_above.php | 52 + admin/layouts/tagged_verse/details_left.php | 49 + admin/layouts/tagged_verse/details_right.php | 49 + admin/layouts/tagged_verse/index.html | 1 + admin/layouts/tagged_verse/publishing.php | 53 + admin/layouts/tagged_verse/publlshing.php | 52 + admin/layouts/translation/details_above.php | 52 + .../layouts/translation/details_fullwidth.php | 51 + admin/layouts/translation/details_left.php | 54 + admin/layouts/translation/details_right.php | 52 + admin/layouts/translation/index.html | 1 + admin/layouts/translation/publishing.php | 52 + admin/layouts/translation/publlshing.php | 53 + admin/layouts/trashhelper.php | 79 + admin/layouts/verse/details_above.php | 52 + admin/layouts/verse/details_fullwidth.php | 50 + admin/layouts/verse/details_left.php | 48 + admin/layouts/verse/details_right.php | 48 + admin/layouts/verse/index.html | 1 + admin/layouts/verse/publishing.php | 52 + admin/layouts/verse/publlshing.php | 53 + admin/models/ajax.php | 255 + admin/models/book.php | 951 ++ admin/models/books.php | 380 + admin/models/chapter.php | 969 ++ admin/models/chapters.php | 457 + admin/models/fields/booksfiltername.php | 73 + admin/models/fields/booksfilternr.php | 73 + admin/models/fields/chaptersfilterbooknr.php | 72 + admin/models/fields/chaptersfilterchapter.php | 72 + admin/models/fields/index.html | 1 + admin/models/fields/linkers.php | 183 + admin/models/fields/linkersfiltername.php | 73 + admin/models/fields/notesfilteraccess.php | 77 + admin/models/fields/notesfilterbooknr.php | 73 + admin/models/fields/notesfilterchapter.php | 73 + admin/models/fields/notesfilterverse.php | 73 + .../fields/openaimessagesfilterrole.php | 77 + .../fields/openaimessagesfiltersource.php | 77 + admin/models/fields/openairesponses.php | 78 + .../openairesponsesfilterresponseid.php | 73 + .../openairesponsesfilterresponsemodel.php | 73 + admin/models/fields/passwordsfiltername.php | 73 + admin/models/fields/prompts.php | 78 + .../fields/promptsfiltercachebehaviour.php | 77 + admin/models/fields/promptsfiltermodel.php | 77 + admin/models/fields/promptsfiltername.php | 73 + admin/models/fields/tagers.php | 183 + .../fields/taggedversesfilteraccess.php | 77 + .../fields/taggedversesfilterbooknr.php | 72 + .../fields/taggedversesfilterchapter.php | 72 + .../models/fields/taggedversesfilterverse.php | 72 + admin/models/fields/tagsfilteraccess.php | 77 + admin/models/fields/targettranslations.php | 80 + admin/models/fields/translations.php | 79 + .../fields/translationsfilterdirection.php | 77 + admin/models/fields/versesfilterbooknr.php | 73 + admin/models/fields/versesfilterchapter.php | 73 + admin/models/fields/versesfilterverse.php | 73 + admin/models/forms/book.xml | 184 + admin/models/forms/chapter.xml | 196 + admin/models/forms/filter_books.xml | 92 + admin/models/forms/filter_chapters.xml | 96 + admin/models/forms/filter_linkers.xml | 74 + admin/models/forms/filter_notes.xml | 97 + .../models/forms/filter_open_ai_messages.xml | 101 + .../models/forms/filter_open_ai_responses.xml | 96 + admin/models/forms/filter_passwords.xml | 83 + admin/models/forms/filter_prompts.xml | 101 + admin/models/forms/filter_tagged_verses.xml | 119 + admin/models/forms/filter_tags.xml | 76 + admin/models/forms/filter_translations.xml | 80 + admin/models/forms/filter_verses.xml | 101 + admin/models/forms/index.html | 1 + admin/models/forms/linker.xml | 148 + admin/models/forms/note.xml | 200 + admin/models/forms/open_ai_message.xml | 212 + admin/models/forms/open_ai_response.xml | 419 + admin/models/forms/password.xml | 174 + admin/models/forms/prompt.xml | 571 + admin/models/forms/tag.xml | 178 + admin/models/forms/tagged_verse.xml | 209 + admin/models/forms/translation.xml | 415 + admin/models/forms/verse.xml | 209 + admin/models/getbible.php | 431 + admin/models/index.html | 1 + admin/models/linker.php | 1280 ++ admin/models/linkers.php | 324 + admin/models/note.php | 992 ++ admin/models/notes.php | 433 + admin/models/open_ai_message.php | 1010 ++ admin/models/open_ai_messages.php | 461 + admin/models/open_ai_response.php | 1458 ++ admin/models/open_ai_responses.php | 398 + admin/models/password.php | 1005 ++ admin/models/passwords.php | 354 + admin/models/prompt.php | 1397 ++ admin/models/prompts.php | 488 + admin/models/rules/guid.php | 60 + admin/models/rules/index.html | 1 + admin/models/rules/int.php | 62 + admin/models/rules/numbershyphens.php | 60 + admin/models/tag.php | 984 ++ admin/models/tagged_verse.php | 1010 ++ admin/models/tagged_verses.php | 629 + admin/models/tags.php | 363 + admin/models/translation.php | 1214 ++ admin/models/translations.php | 385 + admin/models/verse.php | 989 ++ admin/models/verses.php | 406 + admin/sql/index.html | 1 + admin/sql/install.mysql.utf8.sql | 446 + admin/sql/uninstall.mysql.utf8.sql | 13 + admin/sql/updates/index.html | 1 + admin/sql/updates/mysql/index.html | 1 + admin/tables/book.php | 327 + admin/tables/chapter.php | 327 + admin/tables/index.html | 1 + admin/tables/linker.php | 327 + admin/tables/note.php | 330 + admin/tables/open_ai_message.php | 330 + admin/tables/open_ai_response.php | 330 + admin/tables/password.php | 327 + admin/tables/prompt.php | 330 + admin/tables/tag.php | 330 + admin/tables/tagged_verse.php | 330 + admin/tables/translation.php | 327 + admin/tables/verse.php | 327 + admin/views/book/submitbutton.js | 31 + admin/views/book/tmpl/edit.php | 112 + admin/views/book/tmpl/index.html | 1 + admin/views/book/view.html.php | 130 + admin/views/books/index.html | 1 + admin/views/books/tmpl/default.php | 73 + admin/views/books/tmpl/default_batch_body.php | 24 + .../views/books/tmpl/default_batch_footer.php | 29 + admin/views/books/tmpl/default_body.php | 109 + admin/views/books/tmpl/default_foot.php | 24 + admin/views/books/tmpl/default_head.php | 59 + admin/views/books/tmpl/default_toolbar.php | 51 + admin/views/books/tmpl/index.html | 1 + admin/views/books/view.html.php | 289 + admin/views/chapter/submitbutton.js | 31 + admin/views/chapter/tmpl/edit.php | 112 + admin/views/chapter/tmpl/index.html | 1 + admin/views/chapter/view.html.php | 130 + admin/views/chapters/index.html | 1 + admin/views/chapters/tmpl/default.php | 75 + .../chapters/tmpl/default_batch_body.php | 24 + .../chapters/tmpl/default_batch_footer.php | 29 + admin/views/chapters/tmpl/default_body.php | 112 + admin/views/chapters/tmpl/default_foot.php | 24 + admin/views/chapters/tmpl/default_head.php | 62 + admin/views/chapters/tmpl/default_toolbar.php | 51 + admin/views/chapters/tmpl/index.html | 1 + admin/views/chapters/view.html.php | 290 + admin/views/getbible/index.html | 1 + admin/views/getbible/tmpl/default.php | 85 + admin/views/getbible/tmpl/default_main.php | 36 + ...t_notice_board_vast_development_method.php | 22 + .../tmpl/default_readme_information.php | 22 + admin/views/getbible/tmpl/default_vdm.php | 44 + .../getbible/tmpl/default_wiki_tutorials.php | 22 + admin/views/getbible/tmpl/index.html | 1 + admin/views/getbible/view.html.php | 100 + admin/views/index.html | 1 + admin/views/linker/submitbutton.js | 31 + admin/views/linker/tmpl/edit.php | 144 + admin/views/linker/tmpl/index.html | 1 + admin/views/linker/view.html.php | 231 + admin/views/linkers/index.html | 1 + admin/views/linkers/tmpl/default.php | 73 + .../views/linkers/tmpl/default_batch_body.php | 24 + .../linkers/tmpl/default_batch_footer.php | 29 + admin/views/linkers/tmpl/default_body.php | 100 + admin/views/linkers/tmpl/default_foot.php | 24 + admin/views/linkers/tmpl/default_head.php | 56 + admin/views/linkers/tmpl/default_toolbar.php | 51 + admin/views/linkers/tmpl/index.html | 1 + admin/views/linkers/view.html.php | 247 + admin/views/note/submitbutton.js | 31 + admin/views/note/tmpl/edit.php | 112 + admin/views/note/tmpl/index.html | 1 + admin/views/note/view.html.php | 203 + admin/views/notes/index.html | 1 + admin/views/notes/tmpl/default.php | 73 + admin/views/notes/tmpl/default_batch_body.php | 24 + .../views/notes/tmpl/default_batch_footer.php | 29 + admin/views/notes/tmpl/default_body.php | 109 + admin/views/notes/tmpl/default_foot.php | 24 + admin/views/notes/tmpl/default_head.php | 59 + admin/views/notes/tmpl/default_toolbar.php | 51 + admin/views/notes/tmpl/index.html | 1 + admin/views/notes/view.html.php | 319 + admin/views/open_ai_message/submitbutton.js | 31 + admin/views/open_ai_message/tmpl/edit.php | 117 + admin/views/open_ai_message/tmpl/index.html | 1 + admin/views/open_ai_message/view.html.php | 203 + admin/views/open_ai_messages/index.html | 1 + admin/views/open_ai_messages/tmpl/default.php | 73 + .../tmpl/default_batch_body.php | 24 + .../tmpl/default_batch_footer.php | 29 + .../open_ai_messages/tmpl/default_body.php | 118 + .../open_ai_messages/tmpl/default_foot.php | 24 + .../open_ai_messages/tmpl/default_head.php | 62 + .../open_ai_messages/tmpl/default_toolbar.php | 51 + admin/views/open_ai_messages/tmpl/index.html | 1 + admin/views/open_ai_messages/view.html.php | 310 + admin/views/open_ai_response/submitbutton.js | 31 + admin/views/open_ai_response/tmpl/edit.php | 146 + admin/views/open_ai_response/tmpl/index.html | 1 + admin/views/open_ai_response/view.html.php | 230 + admin/views/open_ai_responses/index.html | 1 + .../views/open_ai_responses/tmpl/default.php | 73 + .../tmpl/default_batch_body.php | 24 + .../tmpl/default_batch_footer.php | 29 + .../open_ai_responses/tmpl/default_body.php | 115 + .../open_ai_responses/tmpl/default_foot.php | 24 + .../open_ai_responses/tmpl/default_head.php | 65 + .../tmpl/default_toolbar.php | 51 + admin/views/open_ai_responses/tmpl/index.html | 1 + admin/views/open_ai_responses/view.html.php | 291 + admin/views/password/submitbutton.js | 31 + admin/views/password/tmpl/edit.php | 112 + admin/views/password/tmpl/index.html | 1 + admin/views/password/view.html.php | 198 + admin/views/passwords/index.html | 1 + admin/views/passwords/tmpl/default.php | 73 + .../passwords/tmpl/default_batch_body.php | 24 + .../passwords/tmpl/default_batch_footer.php | 29 + admin/views/passwords/tmpl/default_body.php | 109 + admin/views/passwords/tmpl/default_foot.php | 24 + admin/views/passwords/tmpl/default_head.php | 59 + .../views/passwords/tmpl/default_toolbar.php | 51 + admin/views/passwords/tmpl/index.html | 1 + admin/views/passwords/view.html.php | 268 + admin/views/prompt/submitbutton.js | 31 + admin/views/prompt/tmpl/edit.php | 138 + admin/views/prompt/tmpl/index.html | 1 + admin/views/prompt/view.html.php | 203 + admin/views/prompts/index.html | 1 + admin/views/prompts/tmpl/default.php | 73 + .../views/prompts/tmpl/default_batch_body.php | 24 + .../prompts/tmpl/default_batch_footer.php | 29 + admin/views/prompts/tmpl/default_body.php | 112 + admin/views/prompts/tmpl/default_foot.php | 24 + admin/views/prompts/tmpl/default_head.php | 68 + admin/views/prompts/tmpl/default_toolbar.php | 51 + admin/views/prompts/tmpl/index.html | 1 + admin/views/prompts/view.html.php | 310 + admin/views/tag/submitbutton.js | 31 + admin/views/tag/tmpl/edit.php | 114 + admin/views/tag/tmpl/index.html | 1 + admin/views/tag/view.html.php | 203 + admin/views/tagged_verse/submitbutton.js | 31 + admin/views/tagged_verse/tmpl/edit.php | 112 + admin/views/tagged_verse/tmpl/index.html | 1 + admin/views/tagged_verse/view.html.php | 203 + admin/views/tagged_verses/index.html | 1 + admin/views/tagged_verses/tmpl/default.php | 77 + .../tagged_verses/tmpl/default_batch_body.php | 24 + .../tmpl/default_batch_footer.php | 29 + .../views/tagged_verses/tmpl/default_body.php | 127 + .../views/tagged_verses/tmpl/default_foot.php | 24 + .../views/tagged_verses/tmpl/default_head.php | 65 + .../tagged_verses/tmpl/default_toolbar.php | 51 + admin/views/tagged_verses/tmpl/index.html | 1 + admin/views/tagged_verses/view.html.php | 361 + admin/views/tags/index.html | 1 + admin/views/tags/tmpl/default.php | 73 + admin/views/tags/tmpl/default_batch_body.php | 24 + .../views/tags/tmpl/default_batch_footer.php | 29 + admin/views/tags/tmpl/default_body.php | 103 + admin/views/tags/tmpl/default_foot.php | 24 + admin/views/tags/tmpl/default_head.php | 59 + admin/views/tags/tmpl/default_toolbar.php | 51 + admin/views/tags/tmpl/index.html | 1 + admin/views/tags/view.html.php | 259 + admin/views/translation/submitbutton.js | 31 + admin/views/translation/tmpl/edit.php | 117 + admin/views/translation/tmpl/index.html | 1 + admin/views/translation/view.html.php | 132 + admin/views/translations/index.html | 1 + admin/views/translations/tmpl/default.php | 73 + .../translations/tmpl/default_batch_body.php | 24 + .../tmpl/default_batch_footer.php | 29 + .../views/translations/tmpl/default_body.php | 106 + .../views/translations/tmpl/default_foot.php | 24 + .../views/translations/tmpl/default_head.php | 62 + .../translations/tmpl/default_toolbar.php | 51 + admin/views/translations/tmpl/index.html | 1 + admin/views/translations/view.html.php | 250 + admin/views/verse/submitbutton.js | 31 + admin/views/verse/tmpl/edit.php | 117 + admin/views/verse/tmpl/index.html | 1 + admin/views/verse/view.html.php | 130 + admin/views/verses/index.html | 1 + admin/views/verses/tmpl/default.php | 73 + .../views/verses/tmpl/default_batch_body.php | 24 + .../verses/tmpl/default_batch_footer.php | 29 + admin/views/verses/tmpl/default_body.php | 112 + admin/views/verses/tmpl/default_foot.php | 24 + admin/views/verses/tmpl/default_head.php | 62 + admin/views/verses/tmpl/default_toolbar.php | 51 + admin/views/verses/tmpl/index.html | 1 + admin/views/verses/view.html.php | 310 + getbible.xml | 120 + index.html | 1 + libraries/jcb_powers/.htaccess | 9 + .../jcb_powers/VDM.Joomla.GetBible/index.html | 1 + .../jcb_powers/VDM.Joomla.GetBible/src/AI.php | 104 + .../VDM.Joomla.GetBible/src/AI/Engineer.php | 308 + .../VDM.Joomla.GetBible/src/AI/index.html | 1 + .../src/Abstraction/Api.php | 67 + .../src/Abstraction/index.html | 1 + .../VDM.Joomla.GetBible/src/Api/Books.php | 96 + .../VDM.Joomla.GetBible/src/Api/Chapters.php | 100 + .../src/Api/Translations.php | 74 + .../VDM.Joomla.GetBible/src/Api/Verses.php | 44 + .../VDM.Joomla.GetBible/src/Api/index.html | 1 + .../VDM.Joomla.GetBible/src/Config.php | 81 + .../src/DailyScripture.php | 244 + .../VDM.Joomla.GetBible/src/Data/Book.php | 156 + .../VDM.Joomla.GetBible/src/Data/Chapter.php | 214 + .../src/Data/Placeholders.php | 151 + .../VDM.Joomla.GetBible/src/Data/Prompt.php | 327 + .../VDM.Joomla.GetBible/src/Data/Response.php | 200 + .../src/Data/Scripture.php | 154 + .../src/Data/Translation.php | 140 + .../VDM.Joomla.GetBible/src/Data/Verse.php | 453 + .../VDM.Joomla.GetBible/src/Data/Word.php | 391 + .../VDM.Joomla.GetBible/src/Data/index.html | 1 + .../src/Database/Insert.php | 161 + .../VDM.Joomla.GetBible/src/Database/Load.php | 262 + .../src/Database/Update.php | 168 + .../src/Database/index.html | 1 + .../VDM.Joomla.GetBible/src/Factory.php | 84 + .../VDM.Joomla.GetBible/src/Linker.php | 424 + .../VDM.Joomla.GetBible/src/Loader.php | 83 + .../VDM.Joomla.GetBible/src/Model/Load.php | 160 + .../VDM.Joomla.GetBible/src/Model/Upsert.php | 159 + .../VDM.Joomla.GetBible/src/Model/index.html | 1 + .../VDM.Joomla.GetBible/src/Note.php | 241 + .../VDM.Joomla.GetBible/src/Openai.php | 86 + .../VDM.Joomla.GetBible/src/Openai/Config.php | 305 + .../VDM.Joomla.GetBible/src/Openai/index.html | 1 + .../VDM.Joomla.GetBible/src/Search.php | 23 + .../VDM.Joomla.GetBible/src/Service/AI.php | 81 + .../VDM.Joomla.GetBible/src/Service/Api.php | 121 + .../VDM.Joomla.GetBible/src/Service/App.php | 259 + .../VDM.Joomla.GetBible/src/Service/Data.php | 276 + .../src/Service/Database.php | 149 + .../VDM.Joomla.GetBible/src/Service/Model.php | 77 + .../src/Service/Openai.php | 121 + .../src/Service/Utilities.php | 124 + .../src/Service/index.html | 1 + .../VDM.Joomla.GetBible/src/Table.php | 1076 ++ .../VDM.Joomla.GetBible/src/Tag.php | 209 + .../VDM.Joomla.GetBible/src/Tagged.php | 364 + .../src/Tagged/Paragraphs.php | 275 + .../VDM.Joomla.GetBible/src/Tagged/index.html | 1 + .../src/Utilities/Http.php | 48 + .../src/Utilities/Response.php | 123 + .../src/Utilities/SessionHelper.php | 76 + .../src/Utilities/StringHelper.php | 120 + .../VDM.Joomla.GetBible/src/Utilities/Uri.php | 63 + .../src/Utilities/index.html | 1 + .../VDM.Joomla.GetBible/src/Watcher.php | 693 + .../VDM.Joomla.GetBible/src/index.html | 1 + .../jcb_powers/VDM.Joomla.Gitea/index.html | 1 + .../VDM.Joomla.Gitea/src/Abstraction/Api.php | 83 + .../src/Abstraction/index.html | 1 + .../VDM.Joomla.Gitea/src/Admin/Cron.php | 72 + .../src/Admin/Organizations.php | 51 + .../VDM.Joomla.Gitea/src/Admin/Unadopted.php | 101 + .../VDM.Joomla.Gitea/src/Admin/Users.php | 207 + .../VDM.Joomla.Gitea/src/Admin/Users/Keys.php | 86 + .../src/Admin/Users/Organization.php | 70 + .../src/Admin/Users/Repository.php | 85 + .../src/Admin/Users/index.html | 1 + .../VDM.Joomla.Gitea/src/Admin/index.html | 1 + .../VDM.Joomla.Gitea/src/Factory.php | 97 + .../jcb_powers/VDM.Joomla.Gitea/src/Issue.php | 406 + .../VDM.Joomla.Gitea/src/Issue/Comments.php | 176 + .../VDM.Joomla.Gitea/src/Issue/Deadline.php | 54 + .../VDM.Joomla.Gitea/src/Issue/Labels.php | 181 + .../VDM.Joomla.Gitea/src/Issue/Milestones.php | 230 + .../VDM.Joomla.Gitea/src/Issue/Reactions.php | 110 + .../src/Issue/Reactions/Comment.php | 103 + .../src/Issue/Reactions/index.html | 1 + .../src/Issue/Repository/Comments.php | 67 + .../src/Issue/Repository/index.html | 1 + .../VDM.Joomla.Gitea/src/Issue/Stopwatch.php | 95 + .../src/Issue/Subscriptions.php | 137 + .../VDM.Joomla.Gitea/src/Issue/Timeline.php | 78 + .../VDM.Joomla.Gitea/src/Issue/Times.php | 179 + .../VDM.Joomla.Gitea/src/Issue/index.html | 1 + .../VDM.Joomla.Gitea/src/Labels.php | 162 + .../src/Miscellaneous/Activitypub.php | 69 + .../src/Miscellaneous/Gpg.php | 45 + .../src/Miscellaneous/Markdown.php | 87 + .../src/Miscellaneous/NodeInfo.php | 45 + .../src/Miscellaneous/Version.php | 45 + .../src/Miscellaneous/index.html | 1 + .../VDM.Joomla.Gitea/src/Notifications.php | 149 + .../src/Notifications/Repository.php | 144 + .../src/Notifications/Thread.php | 96 + .../src/Notifications/index.html | 1 + .../VDM.Joomla.Gitea/src/Organization.php | 209 + .../src/Organization/Hooks.php | 200 + .../src/Organization/Labels.php | 183 + .../src/Organization/Members.php | 100 + .../src/Organization/PublicMembers.php | 119 + .../src/Organization/Repository.php | 145 + .../src/Organization/Teams.php | 274 + .../src/Organization/Teams/Members.php | 124 + .../src/Organization/Teams/Repository.php | 135 + .../src/Organization/Teams/index.html | 1 + .../src/Organization/User.php | 111 + .../src/Organization/index.html | 1 + .../VDM.Joomla.Gitea/src/Package.php | 84 + .../VDM.Joomla.Gitea/src/Package/Files.php | 55 + .../VDM.Joomla.Gitea/src/Package/Owner.php | 68 + .../VDM.Joomla.Gitea/src/Package/index.html | 1 + .../VDM.Joomla.Gitea/src/Repository.php | 439 + .../src/Repository/Archive.php | 58 + .../src/Repository/Assignees.php | 51 + .../src/Repository/Attachments.php | 196 + .../src/Repository/Branch.php | 148 + .../src/Repository/Branch/Protection.php | 380 + .../src/Repository/Branch/index.html | 1 + .../src/Repository/Collaborator.php | 175 + .../src/Repository/Commits.php | 225 + .../src/Repository/Contents.php | 509 + .../VDM.Joomla.Gitea/src/Repository/Forks.php | 102 + .../VDM.Joomla.Gitea/src/Repository/Gpg.php | 48 + .../VDM.Joomla.Gitea/src/Repository/Hooks.php | 214 + .../src/Repository/Hooks/Git.php | 137 + .../src/Repository/Hooks/index.html | 1 + .../VDM.Joomla.Gitea/src/Repository/Keys.php | 159 + .../src/Repository/Languages.php | 49 + .../VDM.Joomla.Gitea/src/Repository/Media.php | 63 + .../VDM.Joomla.Gitea/src/Repository/Merge.php | 167 + .../src/Repository/Mirror.php | 48 + .../src/Repository/Mirrors.php | 190 + .../VDM.Joomla.Gitea/src/Repository/Notes.php | 53 + .../VDM.Joomla.Gitea/src/Repository/Patch.php | 78 + .../VDM.Joomla.Gitea/src/Repository/Pulls.php | 547 + .../VDM.Joomla.Gitea/src/Repository/Refs.php | 77 + .../src/Repository/Releases.php | 309 + .../src/Repository/Remote.php | 96 + .../src/Repository/Reviewers.php | 126 + .../src/Repository/Reviews.php | 321 + .../src/Repository/Stargazers.php | 59 + .../src/Repository/Statuses.php | 122 + .../VDM.Joomla.Gitea/src/Repository/Tags.php | 182 + .../VDM.Joomla.Gitea/src/Repository/Teams.php | 133 + .../src/Repository/Templates.php | 91 + .../VDM.Joomla.Gitea/src/Repository/Times.php | 80 + .../src/Repository/Topics.php | 175 + .../src/Repository/Transfer.php | 108 + .../VDM.Joomla.Gitea/src/Repository/Trees.php | 63 + .../src/Repository/Watchers.php | 140 + .../VDM.Joomla.Gitea/src/Repository/Wiki.php | 232 + .../src/Repository/index.html | 1 + .../VDM.Joomla.Gitea/src/Service/Admin.php | 185 + .../VDM.Joomla.Gitea/src/Service/Issue.php | 294 + .../VDM.Joomla.Gitea/src/Service/Jcb.php | 85 + .../src/Service/Miscellaneous.php | 143 + .../src/Service/Notifications.php | 101 + .../src/Service/Organization.php | 248 + .../VDM.Joomla.Gitea/src/Service/Package.php | 101 + .../src/Service/Repository.php | 836 + .../VDM.Joomla.Gitea/src/Service/Settings.php | 123 + .../VDM.Joomla.Gitea/src/Service/User.php | 332 + .../src/Service/Utilities.php | 72 + .../VDM.Joomla.Gitea/src/Service/index.html | 1 + .../VDM.Joomla.Gitea/src/Settings/Api.php | 45 + .../src/Settings/Attachment.php | 45 + .../src/Settings/Repository.php | 45 + .../VDM.Joomla.Gitea/src/Settings/Ui.php | 45 + .../VDM.Joomla.Gitea/src/Settings/index.html | 1 + .../jcb_powers/VDM.Joomla.Gitea/src/User.php | 335 + .../src/User/Applications.php | 166 + .../VDM.Joomla.Gitea/src/User/Emails.php | 94 + .../VDM.Joomla.Gitea/src/User/Followers.php | 54 + .../VDM.Joomla.Gitea/src/User/Following.php | 122 + .../VDM.Joomla.Gitea/src/User/Gpg.php | 173 + .../VDM.Joomla.Gitea/src/User/Keys.php | 135 + .../VDM.Joomla.Gitea/src/User/Repos.php | 188 + .../VDM.Joomla.Gitea/src/User/Settings.php | 124 + .../VDM.Joomla.Gitea/src/User/Starred.php | 76 + .../src/User/Subscriptions.php | 54 + .../VDM.Joomla.Gitea/src/User/Teams.php | 54 + .../VDM.Joomla.Gitea/src/User/Times.php | 96 + .../VDM.Joomla.Gitea/src/User/Tokens.php | 111 + .../VDM.Joomla.Gitea/src/User/index.html | 1 + .../VDM.Joomla.Gitea/src/Utilities/Http.php | 78 + .../src/Utilities/Response.php | 146 + .../VDM.Joomla.Gitea/src/Utilities/Uri.php | 140 + .../VDM.Joomla.Gitea/src/Utilities/index.html | 1 + .../VDM.Joomla.Gitea/src/index.html | 1 + .../jcb_powers/VDM.Joomla.Openai/index.html | 1 + .../VDM.Joomla.Openai/src/Abstraction/Api.php | 67 + .../src/Abstraction/index.html | 1 + .../jcb_powers/VDM.Joomla.Openai/src/Chat.php | 142 + .../VDM.Joomla.Openai/src/Completions.php | 158 + .../VDM.Joomla.Openai/src/Models.php | 44 + .../VDM.Joomla.Openai/src/Moderate.php | 60 + .../src/Service/Utilities.php | 113 + .../VDM.Joomla.Openai/src/Service/index.html | 1 + .../VDM.Joomla.Openai/src/Utilities/Http.php | 139 + .../src/Utilities/Response.php | 140 + .../VDM.Joomla.Openai/src/Utilities/Uri.php | 115 + .../src/Utilities/index.html | 1 + .../VDM.Joomla.Openai/src/index.html | 1 + libraries/jcb_powers/VDM.Joomla/index.html | 1 + .../VDM.Joomla/src/Abstraction/BaseConfig.php | 122 + .../VDM.Joomla/src/Abstraction/BaseTable.php | 364 + .../VDM.Joomla/src/Abstraction/Database.php | 118 + .../VDM.Joomla/src/Abstraction/Model.php | 358 + .../VDM.Joomla/src/Abstraction/index.html | 1 + .../VDM.Joomla/src/Database/Insert.php | 290 + .../VDM.Joomla/src/Database/Load.php | 446 + .../VDM.Joomla/src/Database/Update.php | 188 + .../VDM.Joomla/src/Database/index.html | 1 + .../src/Interfaces/FactoryInterface.php | 41 + .../src/Interfaces/InsertInterface.php | 78 + .../src/Interfaces/LoadInterface.php | 114 + .../src/Interfaces/ModelInterface.php | 94 + .../src/Interfaces/Tableinterface.php | 89 + .../src/Interfaces/UpdateInterface.php | 72 + .../VDM.Joomla/src/Interfaces/index.html | 1 + .../VDM.Joomla/src/Utilities/ArrayHelper.php | 107 + .../src/Utilities/Component/Helper.php | 189 + .../src/Utilities/Component/index.html | 1 + .../VDM.Joomla/src/Utilities/FileHelper.php | 363 + .../VDM.Joomla/src/Utilities/GetHelper.php | 253 + .../VDM.Joomla/src/Utilities/GuidHelper.php | 215 + .../VDM.Joomla/src/Utilities/JsonHelper.php | 101 + .../VDM.Joomla/src/Utilities/ObjectHelper.php | 78 + .../Utilities/String/ClassfunctionHelper.php | 47 + .../src/Utilities/String/index.html | 1 + .../VDM.Joomla/src/Utilities/StringHelper.php | 416 + libraries/jcb_powers/htaccess.txt | 9 + libraries/jcb_powers/index.html | 1 + libraries/jcb_powers/web.config | 7 + media/css/index.html | 1 + media/datatable/css/datatables.min.css | 57 + media/datatable/css/index.html | 1 + media/datatable/index.html | 1 + media/datatable/js/datatables.min.js | 1238 ++ media/datatable/js/index.html | 1 + media/datatable/js/pdfmake.min.js | 3 + media/datatable/js/vfs_fonts.js | 6 + media/images/ajax.gif | Bin 0 -> 65516 bytes media/images/icon.png | Bin 0 -> 3491 bytes media/images/index.html | 1 + media/index.html | 1 + media/js/book.js | 17 + media/js/chapter.js | 17 + media/js/index.html | 1 + media/js/linker.js | 17 + media/js/note.js | 17 + media/js/open_ai_message.js | 17 + media/js/open_ai_response.js | 17 + media/js/password.js | 17 + media/js/prompt.js | 58 + media/js/tag.js | 17 + media/js/tagged_verse.js | 17 + media/js/translation.js | 17 + media/js/verse.js | 17 + media/nouislider/css/index.html | 1 + media/nouislider/css/nouislider.min.css | 1 + media/nouislider/index.html | 1 + media/nouislider/js/index.html | 1 + media/nouislider/js/nouislider.min.js | 1 + media/uikit-v3/css/index.html | 1 + media/uikit-v3/css/uikit-rtl.css | 12595 ++++++++++++++++ media/uikit-v3/css/uikit-rtl.min.css | 1 + media/uikit-v3/css/uikit.css | 12595 ++++++++++++++++ media/uikit-v3/css/uikit.min.css | 1 + media/uikit-v3/index.html | 1 + media/uikit-v3/js/index.html | 1 + media/uikit-v3/js/uikit-icons.js | 169 + media/uikit-v3/js/uikit-icons.min.js | 3 + media/uikit-v3/js/uikit.js | 12368 +++++++++++++++ media/uikit-v3/js/uikit.min.js | 3 + script.php | 2113 +++ site/assets/css/api.css | 19 + site/assets/css/app.css | 29 + site/assets/css/index.html | 1 + site/assets/css/openai.css | 19 + site/assets/css/search.css | 19 + site/assets/css/site.css | 21 + site/assets/css/tag.css | 28 + site/assets/images/index.html | 1 + site/assets/index.html | 1 + site/assets/js/app.js | 573 + site/assets/js/index.html | 1 + site/assets/js/openai.js | 30 + site/assets/js/search.js | 139 + site/assets/js/site.js | 17 + site/controller.php | 89 + site/controllers/ajax.json.php | 655 + site/controllers/index.html | 1 + site/getbible.php | 85 + site/helpers/category.php | 24 + site/helpers/getbible.php | 1417 ++ site/helpers/headercheck.php | 77 + site/helpers/index.html | 1 + site/helpers/route.php | 433 + site/index.html | 1 + site/language/en-GB/en-GB.com_getbible.ini | 226 + .../language/en-GB/en-GB.com_getbible.sys.ini | 3 + site/language/en-GB/index.html | 1 + site/language/index.html | 1 + site/layouts/aidetails.php | 33 + site/layouts/airesponsemessage.php | 27 + site/layouts/getbibleappnote.php | 24 + site/layouts/getbibleappnotelink.php | 24 + site/layouts/getbiblefooter.php | 38 + site/layouts/getbiblehashdetails.php | 40 + site/layouts/getbibleparagraph.php | 25 + site/layouts/getbibleverse.php | 43 + site/layouts/getbibleverses.php | 28 + site/layouts/getbibleversetag.php | 46 + site/layouts/index.html | 1 + site/layouts/input.php | 44 + site/layouts/inputbox.php | 35 + site/layouts/modal.php | 86 + site/layouts/modulepositionerror.php | 27 + site/layouts/nextchapter.php | 26 + site/layouts/previouschapter.php | 26 + site/layouts/promptmessage.php | 27 + site/layouts/promptsettings.php | 34 + site/layouts/rows.php | 49 + site/layouts/select.php | 52 + site/layouts/selectbox.php | 33 + site/layouts/table.php | 80 + site/models/ajax.php | 365 + site/models/api.php | 109 + site/models/app.php | 1722 +++ site/models/index.html | 1 + site/models/openai.php | 288 + site/models/search.php | 649 + site/models/tag.php | 666 + site/router.php | 790 + site/views/api/index.html | 1 + site/views/api/tmpl/default.php | 24 + site/views/api/tmpl/default.xml | 8 + site/views/api/tmpl/index.html | 1 + site/views/api/view.html.php | 118 + site/views/app/index.html | 1 + site/views/app/tmpl/default.php | 35 + site/views/app/tmpl/default.xml | 756 + site/views/app/tmpl/default_getbibleapp.php | 344 + .../app/tmpl/default_getbibleappbody.php | 85 + .../tmpl/default_getbibleappbottommenu.php | 59 + .../tmpl/default_getbibleappcustomtabs.php | 53 + .../default_getbibleappcustomtabsmenu.php | 42 + .../app/tmpl/default_getbibleappdebug.php | 138 + .../app/tmpl/default_getbibleappdetails.php | 51 + .../app/tmpl/default_getbibleappfooter.php | 50 + .../tmpl/default_getbibleappmodalbottom.php | 44 + .../app/tmpl/default_getbibleappnotes.php | 73 + .../app/tmpl/default_getbibleappsettings.php | 159 + .../app/tmpl/default_getbibleappshare.php | 425 + .../app/tmpl/default_getbibleapptags.php | 108 + .../app/tmpl/default_getbibleapptopmenu.php | 59 + .../app/tmpl/default_getbibleappword.php | 172 + site/views/app/tmpl/default_getbiblebooks.php | 38 + .../app/tmpl/default_getbiblechapters.php | 38 + ...default_getbiblefavouriteverseselector.php | 110 + .../tmpl/default_getbibleinstallbutton.php | 170 + site/views/app/tmpl/default_getbibletext.php | 63 + .../app/tmpl/default_getbibletranslations.php | 38 + .../app/tmpl/default_versesparagraph.php | 38 + .../app/tmpl/default_versesunorderedlist.php | 40 + site/views/app/tmpl/index.html | 1 + site/views/app/view.html.php | 845 ++ site/views/index.html | 1 + site/views/openai/index.html | 1 + site/views/openai/tmpl/default.php | 37 + site/views/openai/tmpl/default_getbibleai.php | 43 + .../openai/tmpl/default_getbibleaibody.php | 73 + .../tmpl/default_getbibleaibottommenu.php | 53 + .../tmpl/default_getbibleaicustomtabs.php | 53 + .../tmpl/default_getbibleaicustomtabsmenu.php | 42 + .../openai/tmpl/default_getbibleaidebug.php | 34 + .../openai/tmpl/default_getbibleaidetails.php | 28 + .../openai/tmpl/default_getbibleaifilter.php | 37 + .../openai/tmpl/default_getbibleaifooter.php | 25 + .../tmpl/default_getbibleaimessages.php | 34 + .../tmpl/default_getbibleaipromptmessages.php | 34 + .../openai/tmpl/default_getbibleaitopmenu.php | 53 + .../tmpl/default_getbiblepromptsettings.php | 28 + site/views/openai/tmpl/index.html | 1 + site/views/openai/view.html.php | 183 + site/views/search/index.html | 1 + site/views/search/tmpl/default.php | 30 + .../search/tmpl/default_getbiblesearch.php | 34 + .../search/tmpl/default_getbiblesearchbox.php | 46 + .../tmpl/default_getbiblesearchinput.php | 55 + .../default_getbiblesearchnotenoughverses.php | 26 + .../tmpl/default_getbiblesearchoptions.php | 114 + .../tmpl/default_getbiblesearchtable.php | 98 + site/views/search/tmpl/index.html | 1 + site/views/search/view.html.php | 224 + site/views/tag/index.html | 1 + site/views/tag/tmpl/default.php | 38 + site/views/tag/tmpl/default_getbiblenotag.php | 43 + .../tag/tmpl/default_getbibleselecttags.php | 32 + site/views/tag/tmpl/default_getbibletag.php | 43 + .../tag/tmpl/default_getbibletagbody.php | 52 + .../tmpl/default_getbibletagbottommenu.php | 43 + .../tmpl/default_getbibletagcustomtabs.php | 53 + .../default_getbibletagcustomtabsmenu.php | 42 + .../tag/tmpl/default_getbibletagdebug.php | 34 + .../tag/tmpl/default_getbibletagfooter.php | 25 + .../tmpl/default_getbibletagparagraphs.php | 31 + .../default_getbibletagparagraphssorter.php | 30 + .../tag/tmpl/default_getbibletagtopmenu.php | 43 + site/views/tag/tmpl/index.html | 1 + site/views/tag/view.html.php | 338 + update_server.xml | 20 + 883 files changed, 148096 insertions(+) create mode 100644 .octojpack create mode 100644 CHANGELOG.md create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 admin/README.txt create mode 100644 admin/access.xml create mode 100644 admin/assets/css/admin.css create mode 100644 admin/assets/css/book.css create mode 100644 admin/assets/css/books.css create mode 100644 admin/assets/css/chapter.css create mode 100644 admin/assets/css/chapters.css create mode 100644 admin/assets/css/dashboard.css create mode 100644 admin/assets/css/index.html create mode 100644 admin/assets/css/linker.css create mode 100644 admin/assets/css/linkers.css create mode 100644 admin/assets/css/note.css create mode 100644 admin/assets/css/notes.css create mode 100644 admin/assets/css/open_ai_message.css create mode 100644 admin/assets/css/open_ai_messages.css create mode 100644 admin/assets/css/open_ai_response.css create mode 100644 admin/assets/css/open_ai_responses.css create mode 100644 admin/assets/css/password.css create mode 100644 admin/assets/css/passwords.css create mode 100644 admin/assets/css/prompt.css create mode 100644 admin/assets/css/prompts.css create mode 100644 admin/assets/css/tag.css create mode 100644 admin/assets/css/tagged_verse.css create mode 100644 admin/assets/css/tagged_verses.css create mode 100644 admin/assets/css/tags.css create mode 100644 admin/assets/css/translation.css create mode 100644 admin/assets/css/translations.css create mode 100644 admin/assets/css/verse.css create mode 100644 admin/assets/css/verses.css create mode 100644 admin/assets/images/ajax.gif create mode 100644 admin/assets/images/icons/books.png create mode 100644 admin/assets/images/icons/chapters.png create mode 100644 admin/assets/images/icons/index.html create mode 100644 admin/assets/images/icons/linkers.png create mode 100644 admin/assets/images/icons/notes.png create mode 100644 admin/assets/images/icons/open_ai_responses.png create mode 100644 admin/assets/images/icons/prompts.png create mode 100644 admin/assets/images/icons/tagged_verses.png create mode 100644 admin/assets/images/icons/tags.png create mode 100644 admin/assets/images/icons/translations.png create mode 100644 admin/assets/images/icons/verses.png create mode 100644 admin/assets/images/import.gif create mode 100644 admin/assets/images/index.html create mode 100644 admin/assets/images/vdm-component.jpg create mode 100644 admin/assets/index.html create mode 100644 admin/assets/js/admin.js create mode 100644 admin/assets/js/index.html create mode 100644 admin/config.xml create mode 100644 admin/controller.php create mode 100644 admin/controllers/ajax.json.php create mode 100644 admin/controllers/book.php create mode 100644 admin/controllers/books.php create mode 100644 admin/controllers/chapter.php create mode 100644 admin/controllers/chapters.php create mode 100644 admin/controllers/getbible.php create mode 100644 admin/controllers/index.html create mode 100644 admin/controllers/linker.php create mode 100644 admin/controllers/linkers.php create mode 100644 admin/controllers/note.php create mode 100644 admin/controllers/notes.php create mode 100644 admin/controllers/open_ai_message.php create mode 100644 admin/controllers/open_ai_messages.php create mode 100644 admin/controllers/open_ai_response.php create mode 100644 admin/controllers/open_ai_responses.php create mode 100644 admin/controllers/password.php create mode 100644 admin/controllers/passwords.php create mode 100644 admin/controllers/prompt.php create mode 100644 admin/controllers/prompts.php create mode 100644 admin/controllers/tag.php create mode 100644 admin/controllers/tagged_verse.php create mode 100644 admin/controllers/tagged_verses.php create mode 100644 admin/controllers/tags.php create mode 100644 admin/controllers/translation.php create mode 100644 admin/controllers/translations.php create mode 100644 admin/controllers/verse.php create mode 100644 admin/controllers/verses.php create mode 100644 admin/getbible.php create mode 100644 admin/helpers/getbible.php create mode 100644 admin/helpers/headercheck.php create mode 100644 admin/helpers/html/batch_.php create mode 100644 admin/helpers/html/index.html create mode 100644 admin/helpers/index.html create mode 100644 admin/index.html create mode 100644 admin/language/en-GB/en-GB.com_getbible.ini create mode 100644 admin/language/en-GB/en-GB.com_getbible.sys.ini create mode 100644 admin/language/en-GB/index.html create mode 100644 admin/language/index.html create mode 100644 admin/layouts/batchselection.php create mode 100644 admin/layouts/book/details_above.php create mode 100644 admin/layouts/book/details_left.php create mode 100644 admin/layouts/book/details_right.php create mode 100644 admin/layouts/book/index.html create mode 100644 admin/layouts/book/publishing.php create mode 100644 admin/layouts/book/publlshing.php create mode 100644 admin/layouts/chapter/details_above.php create mode 100644 admin/layouts/chapter/details_left.php create mode 100644 admin/layouts/chapter/details_right.php create mode 100644 admin/layouts/chapter/index.html create mode 100644 admin/layouts/chapter/publishing.php create mode 100644 admin/layouts/chapter/publlshing.php create mode 100644 admin/layouts/index.html create mode 100644 admin/layouts/linker/details_left.php create mode 100644 admin/layouts/linker/index.html create mode 100644 admin/layouts/linker/notes_fullwidth.php create mode 100644 admin/layouts/linker/passwords_fullwidth.php create mode 100644 admin/layouts/linker/publishing.php create mode 100644 admin/layouts/linker/publlshing.php create mode 100644 admin/layouts/linker/tags_fullwidth.php create mode 100644 admin/layouts/note/details_above.php create mode 100644 admin/layouts/note/details_left.php create mode 100644 admin/layouts/note/details_right.php create mode 100644 admin/layouts/note/index.html create mode 100644 admin/layouts/note/publishing.php create mode 100644 admin/layouts/note/publlshing.php create mode 100644 admin/layouts/open_ai_message/index.html create mode 100644 admin/layouts/open_ai_message/message_above.php create mode 100644 admin/layouts/open_ai_message/message_fullwidth.php create mode 100644 admin/layouts/open_ai_message/message_left.php create mode 100644 admin/layouts/open_ai_message/message_right.php create mode 100644 admin/layouts/open_ai_message/publishing.php create mode 100644 admin/layouts/open_ai_message/publlshing.php create mode 100644 admin/layouts/open_ai_response/bible_left.php create mode 100644 admin/layouts/open_ai_response/bible_right.php create mode 100644 admin/layouts/open_ai_response/details_above.php create mode 100644 admin/layouts/open_ai_response/details_left.php create mode 100644 admin/layouts/open_ai_response/details_right.php create mode 100644 admin/layouts/open_ai_response/index.html create mode 100644 admin/layouts/open_ai_response/message_fullwidth.php create mode 100644 admin/layouts/open_ai_response/prompt_left.php create mode 100644 admin/layouts/open_ai_response/prompt_right.php create mode 100644 admin/layouts/open_ai_response/publishing.php create mode 100644 admin/layouts/open_ai_response/publlshing.php create mode 100644 admin/layouts/password/details_above.php create mode 100644 admin/layouts/password/details_left.php create mode 100644 admin/layouts/password/details_right.php create mode 100644 admin/layouts/password/index.html create mode 100644 admin/layouts/password/publishing.php create mode 100644 admin/layouts/password/publlshing.php create mode 100644 admin/layouts/prompt/index.html create mode 100644 admin/layouts/prompt/open_ai_left.php create mode 100644 admin/layouts/prompt/open_ai_right.php create mode 100644 admin/layouts/prompt/prompt_above.php create mode 100644 admin/layouts/prompt/prompt_fullwidth.php create mode 100644 admin/layouts/prompt/prompt_left.php create mode 100644 admin/layouts/prompt/prompt_right.php create mode 100644 admin/layouts/prompt/publishing.php create mode 100644 admin/layouts/prompt/publlshing.php create mode 100644 admin/layouts/tag/details_above.php create mode 100644 admin/layouts/tag/details_fullwidth.php create mode 100644 admin/layouts/tag/details_left.php create mode 100644 admin/layouts/tag/index.html create mode 100644 admin/layouts/tag/publishing.php create mode 100644 admin/layouts/tag/publlshing.php create mode 100644 admin/layouts/tagged_verse/details_above.php create mode 100644 admin/layouts/tagged_verse/details_left.php create mode 100644 admin/layouts/tagged_verse/details_right.php create mode 100644 admin/layouts/tagged_verse/index.html create mode 100644 admin/layouts/tagged_verse/publishing.php create mode 100644 admin/layouts/tagged_verse/publlshing.php create mode 100644 admin/layouts/translation/details_above.php create mode 100644 admin/layouts/translation/details_fullwidth.php create mode 100644 admin/layouts/translation/details_left.php create mode 100644 admin/layouts/translation/details_right.php create mode 100644 admin/layouts/translation/index.html create mode 100644 admin/layouts/translation/publishing.php create mode 100644 admin/layouts/translation/publlshing.php create mode 100644 admin/layouts/trashhelper.php create mode 100644 admin/layouts/verse/details_above.php create mode 100644 admin/layouts/verse/details_fullwidth.php create mode 100644 admin/layouts/verse/details_left.php create mode 100644 admin/layouts/verse/details_right.php create mode 100644 admin/layouts/verse/index.html create mode 100644 admin/layouts/verse/publishing.php create mode 100644 admin/layouts/verse/publlshing.php create mode 100644 admin/models/ajax.php create mode 100644 admin/models/book.php create mode 100644 admin/models/books.php create mode 100644 admin/models/chapter.php create mode 100644 admin/models/chapters.php create mode 100644 admin/models/fields/booksfiltername.php create mode 100644 admin/models/fields/booksfilternr.php create mode 100644 admin/models/fields/chaptersfilterbooknr.php create mode 100644 admin/models/fields/chaptersfilterchapter.php create mode 100644 admin/models/fields/index.html create mode 100644 admin/models/fields/linkers.php create mode 100644 admin/models/fields/linkersfiltername.php create mode 100644 admin/models/fields/notesfilteraccess.php create mode 100644 admin/models/fields/notesfilterbooknr.php create mode 100644 admin/models/fields/notesfilterchapter.php create mode 100644 admin/models/fields/notesfilterverse.php create mode 100644 admin/models/fields/openaimessagesfilterrole.php create mode 100644 admin/models/fields/openaimessagesfiltersource.php create mode 100644 admin/models/fields/openairesponses.php create mode 100644 admin/models/fields/openairesponsesfilterresponseid.php create mode 100644 admin/models/fields/openairesponsesfilterresponsemodel.php create mode 100644 admin/models/fields/passwordsfiltername.php create mode 100644 admin/models/fields/prompts.php create mode 100644 admin/models/fields/promptsfiltercachebehaviour.php create mode 100644 admin/models/fields/promptsfiltermodel.php create mode 100644 admin/models/fields/promptsfiltername.php create mode 100644 admin/models/fields/tagers.php create mode 100644 admin/models/fields/taggedversesfilteraccess.php create mode 100644 admin/models/fields/taggedversesfilterbooknr.php create mode 100644 admin/models/fields/taggedversesfilterchapter.php create mode 100644 admin/models/fields/taggedversesfilterverse.php create mode 100644 admin/models/fields/tagsfilteraccess.php create mode 100644 admin/models/fields/targettranslations.php create mode 100644 admin/models/fields/translations.php create mode 100644 admin/models/fields/translationsfilterdirection.php create mode 100644 admin/models/fields/versesfilterbooknr.php create mode 100644 admin/models/fields/versesfilterchapter.php create mode 100644 admin/models/fields/versesfilterverse.php create mode 100644 admin/models/forms/book.xml create mode 100644 admin/models/forms/chapter.xml create mode 100644 admin/models/forms/filter_books.xml create mode 100644 admin/models/forms/filter_chapters.xml create mode 100644 admin/models/forms/filter_linkers.xml create mode 100644 admin/models/forms/filter_notes.xml create mode 100644 admin/models/forms/filter_open_ai_messages.xml create mode 100644 admin/models/forms/filter_open_ai_responses.xml create mode 100644 admin/models/forms/filter_passwords.xml create mode 100644 admin/models/forms/filter_prompts.xml create mode 100644 admin/models/forms/filter_tagged_verses.xml create mode 100644 admin/models/forms/filter_tags.xml create mode 100644 admin/models/forms/filter_translations.xml create mode 100644 admin/models/forms/filter_verses.xml create mode 100644 admin/models/forms/index.html create mode 100644 admin/models/forms/linker.xml create mode 100644 admin/models/forms/note.xml create mode 100644 admin/models/forms/open_ai_message.xml create mode 100644 admin/models/forms/open_ai_response.xml create mode 100644 admin/models/forms/password.xml create mode 100644 admin/models/forms/prompt.xml create mode 100644 admin/models/forms/tag.xml create mode 100644 admin/models/forms/tagged_verse.xml create mode 100644 admin/models/forms/translation.xml create mode 100644 admin/models/forms/verse.xml create mode 100644 admin/models/getbible.php create mode 100644 admin/models/index.html create mode 100644 admin/models/linker.php create mode 100644 admin/models/linkers.php create mode 100644 admin/models/note.php create mode 100644 admin/models/notes.php create mode 100644 admin/models/open_ai_message.php create mode 100644 admin/models/open_ai_messages.php create mode 100644 admin/models/open_ai_response.php create mode 100644 admin/models/open_ai_responses.php create mode 100644 admin/models/password.php create mode 100644 admin/models/passwords.php create mode 100644 admin/models/prompt.php create mode 100644 admin/models/prompts.php create mode 100644 admin/models/rules/guid.php create mode 100644 admin/models/rules/index.html create mode 100644 admin/models/rules/int.php create mode 100644 admin/models/rules/numbershyphens.php create mode 100644 admin/models/tag.php create mode 100644 admin/models/tagged_verse.php create mode 100644 admin/models/tagged_verses.php create mode 100644 admin/models/tags.php create mode 100644 admin/models/translation.php create mode 100644 admin/models/translations.php create mode 100644 admin/models/verse.php create mode 100644 admin/models/verses.php create mode 100644 admin/sql/index.html create mode 100644 admin/sql/install.mysql.utf8.sql create mode 100644 admin/sql/uninstall.mysql.utf8.sql create mode 100644 admin/sql/updates/index.html create mode 100644 admin/sql/updates/mysql/index.html create mode 100644 admin/tables/book.php create mode 100644 admin/tables/chapter.php create mode 100644 admin/tables/index.html create mode 100644 admin/tables/linker.php create mode 100644 admin/tables/note.php create mode 100644 admin/tables/open_ai_message.php create mode 100644 admin/tables/open_ai_response.php create mode 100644 admin/tables/password.php create mode 100644 admin/tables/prompt.php create mode 100644 admin/tables/tag.php create mode 100644 admin/tables/tagged_verse.php create mode 100644 admin/tables/translation.php create mode 100644 admin/tables/verse.php create mode 100644 admin/views/book/submitbutton.js create mode 100644 admin/views/book/tmpl/edit.php create mode 100644 admin/views/book/tmpl/index.html create mode 100644 admin/views/book/view.html.php create mode 100644 admin/views/books/index.html create mode 100644 admin/views/books/tmpl/default.php create mode 100644 admin/views/books/tmpl/default_batch_body.php create mode 100644 admin/views/books/tmpl/default_batch_footer.php create mode 100644 admin/views/books/tmpl/default_body.php create mode 100644 admin/views/books/tmpl/default_foot.php create mode 100644 admin/views/books/tmpl/default_head.php create mode 100644 admin/views/books/tmpl/default_toolbar.php create mode 100644 admin/views/books/tmpl/index.html create mode 100644 admin/views/books/view.html.php create mode 100644 admin/views/chapter/submitbutton.js create mode 100644 admin/views/chapter/tmpl/edit.php create mode 100644 admin/views/chapter/tmpl/index.html create mode 100644 admin/views/chapter/view.html.php create mode 100644 admin/views/chapters/index.html create mode 100644 admin/views/chapters/tmpl/default.php create mode 100644 admin/views/chapters/tmpl/default_batch_body.php create mode 100644 admin/views/chapters/tmpl/default_batch_footer.php create mode 100644 admin/views/chapters/tmpl/default_body.php create mode 100644 admin/views/chapters/tmpl/default_foot.php create mode 100644 admin/views/chapters/tmpl/default_head.php create mode 100644 admin/views/chapters/tmpl/default_toolbar.php create mode 100644 admin/views/chapters/tmpl/index.html create mode 100644 admin/views/chapters/view.html.php create mode 100644 admin/views/getbible/index.html create mode 100644 admin/views/getbible/tmpl/default.php create mode 100644 admin/views/getbible/tmpl/default_main.php create mode 100644 admin/views/getbible/tmpl/default_notice_board_vast_development_method.php create mode 100644 admin/views/getbible/tmpl/default_readme_information.php create mode 100644 admin/views/getbible/tmpl/default_vdm.php create mode 100644 admin/views/getbible/tmpl/default_wiki_tutorials.php create mode 100644 admin/views/getbible/tmpl/index.html create mode 100644 admin/views/getbible/view.html.php create mode 100644 admin/views/index.html create mode 100644 admin/views/linker/submitbutton.js create mode 100644 admin/views/linker/tmpl/edit.php create mode 100644 admin/views/linker/tmpl/index.html create mode 100644 admin/views/linker/view.html.php create mode 100644 admin/views/linkers/index.html create mode 100644 admin/views/linkers/tmpl/default.php create mode 100644 admin/views/linkers/tmpl/default_batch_body.php create mode 100644 admin/views/linkers/tmpl/default_batch_footer.php create mode 100644 admin/views/linkers/tmpl/default_body.php create mode 100644 admin/views/linkers/tmpl/default_foot.php create mode 100644 admin/views/linkers/tmpl/default_head.php create mode 100644 admin/views/linkers/tmpl/default_toolbar.php create mode 100644 admin/views/linkers/tmpl/index.html create mode 100644 admin/views/linkers/view.html.php create mode 100644 admin/views/note/submitbutton.js create mode 100644 admin/views/note/tmpl/edit.php create mode 100644 admin/views/note/tmpl/index.html create mode 100644 admin/views/note/view.html.php create mode 100644 admin/views/notes/index.html create mode 100644 admin/views/notes/tmpl/default.php create mode 100644 admin/views/notes/tmpl/default_batch_body.php create mode 100644 admin/views/notes/tmpl/default_batch_footer.php create mode 100644 admin/views/notes/tmpl/default_body.php create mode 100644 admin/views/notes/tmpl/default_foot.php create mode 100644 admin/views/notes/tmpl/default_head.php create mode 100644 admin/views/notes/tmpl/default_toolbar.php create mode 100644 admin/views/notes/tmpl/index.html create mode 100644 admin/views/notes/view.html.php create mode 100644 admin/views/open_ai_message/submitbutton.js create mode 100644 admin/views/open_ai_message/tmpl/edit.php create mode 100644 admin/views/open_ai_message/tmpl/index.html create mode 100644 admin/views/open_ai_message/view.html.php create mode 100644 admin/views/open_ai_messages/index.html create mode 100644 admin/views/open_ai_messages/tmpl/default.php create mode 100644 admin/views/open_ai_messages/tmpl/default_batch_body.php create mode 100644 admin/views/open_ai_messages/tmpl/default_batch_footer.php create mode 100644 admin/views/open_ai_messages/tmpl/default_body.php create mode 100644 admin/views/open_ai_messages/tmpl/default_foot.php create mode 100644 admin/views/open_ai_messages/tmpl/default_head.php create mode 100644 admin/views/open_ai_messages/tmpl/default_toolbar.php create mode 100644 admin/views/open_ai_messages/tmpl/index.html create mode 100644 admin/views/open_ai_messages/view.html.php create mode 100644 admin/views/open_ai_response/submitbutton.js create mode 100644 admin/views/open_ai_response/tmpl/edit.php create mode 100644 admin/views/open_ai_response/tmpl/index.html create mode 100644 admin/views/open_ai_response/view.html.php create mode 100644 admin/views/open_ai_responses/index.html create mode 100644 admin/views/open_ai_responses/tmpl/default.php create mode 100644 admin/views/open_ai_responses/tmpl/default_batch_body.php create mode 100644 admin/views/open_ai_responses/tmpl/default_batch_footer.php create mode 100644 admin/views/open_ai_responses/tmpl/default_body.php create mode 100644 admin/views/open_ai_responses/tmpl/default_foot.php create mode 100644 admin/views/open_ai_responses/tmpl/default_head.php create mode 100644 admin/views/open_ai_responses/tmpl/default_toolbar.php create mode 100644 admin/views/open_ai_responses/tmpl/index.html create mode 100644 admin/views/open_ai_responses/view.html.php create mode 100644 admin/views/password/submitbutton.js create mode 100644 admin/views/password/tmpl/edit.php create mode 100644 admin/views/password/tmpl/index.html create mode 100644 admin/views/password/view.html.php create mode 100644 admin/views/passwords/index.html create mode 100644 admin/views/passwords/tmpl/default.php create mode 100644 admin/views/passwords/tmpl/default_batch_body.php create mode 100644 admin/views/passwords/tmpl/default_batch_footer.php create mode 100644 admin/views/passwords/tmpl/default_body.php create mode 100644 admin/views/passwords/tmpl/default_foot.php create mode 100644 admin/views/passwords/tmpl/default_head.php create mode 100644 admin/views/passwords/tmpl/default_toolbar.php create mode 100644 admin/views/passwords/tmpl/index.html create mode 100644 admin/views/passwords/view.html.php create mode 100644 admin/views/prompt/submitbutton.js create mode 100644 admin/views/prompt/tmpl/edit.php create mode 100644 admin/views/prompt/tmpl/index.html create mode 100644 admin/views/prompt/view.html.php create mode 100644 admin/views/prompts/index.html create mode 100644 admin/views/prompts/tmpl/default.php create mode 100644 admin/views/prompts/tmpl/default_batch_body.php create mode 100644 admin/views/prompts/tmpl/default_batch_footer.php create mode 100644 admin/views/prompts/tmpl/default_body.php create mode 100644 admin/views/prompts/tmpl/default_foot.php create mode 100644 admin/views/prompts/tmpl/default_head.php create mode 100644 admin/views/prompts/tmpl/default_toolbar.php create mode 100644 admin/views/prompts/tmpl/index.html create mode 100644 admin/views/prompts/view.html.php create mode 100644 admin/views/tag/submitbutton.js create mode 100644 admin/views/tag/tmpl/edit.php create mode 100644 admin/views/tag/tmpl/index.html create mode 100644 admin/views/tag/view.html.php create mode 100644 admin/views/tagged_verse/submitbutton.js create mode 100644 admin/views/tagged_verse/tmpl/edit.php create mode 100644 admin/views/tagged_verse/tmpl/index.html create mode 100644 admin/views/tagged_verse/view.html.php create mode 100644 admin/views/tagged_verses/index.html create mode 100644 admin/views/tagged_verses/tmpl/default.php create mode 100644 admin/views/tagged_verses/tmpl/default_batch_body.php create mode 100644 admin/views/tagged_verses/tmpl/default_batch_footer.php create mode 100644 admin/views/tagged_verses/tmpl/default_body.php create mode 100644 admin/views/tagged_verses/tmpl/default_foot.php create mode 100644 admin/views/tagged_verses/tmpl/default_head.php create mode 100644 admin/views/tagged_verses/tmpl/default_toolbar.php create mode 100644 admin/views/tagged_verses/tmpl/index.html create mode 100644 admin/views/tagged_verses/view.html.php create mode 100644 admin/views/tags/index.html create mode 100644 admin/views/tags/tmpl/default.php create mode 100644 admin/views/tags/tmpl/default_batch_body.php create mode 100644 admin/views/tags/tmpl/default_batch_footer.php create mode 100644 admin/views/tags/tmpl/default_body.php create mode 100644 admin/views/tags/tmpl/default_foot.php create mode 100644 admin/views/tags/tmpl/default_head.php create mode 100644 admin/views/tags/tmpl/default_toolbar.php create mode 100644 admin/views/tags/tmpl/index.html create mode 100644 admin/views/tags/view.html.php create mode 100644 admin/views/translation/submitbutton.js create mode 100644 admin/views/translation/tmpl/edit.php create mode 100644 admin/views/translation/tmpl/index.html create mode 100644 admin/views/translation/view.html.php create mode 100644 admin/views/translations/index.html create mode 100644 admin/views/translations/tmpl/default.php create mode 100644 admin/views/translations/tmpl/default_batch_body.php create mode 100644 admin/views/translations/tmpl/default_batch_footer.php create mode 100644 admin/views/translations/tmpl/default_body.php create mode 100644 admin/views/translations/tmpl/default_foot.php create mode 100644 admin/views/translations/tmpl/default_head.php create mode 100644 admin/views/translations/tmpl/default_toolbar.php create mode 100644 admin/views/translations/tmpl/index.html create mode 100644 admin/views/translations/view.html.php create mode 100644 admin/views/verse/submitbutton.js create mode 100644 admin/views/verse/tmpl/edit.php create mode 100644 admin/views/verse/tmpl/index.html create mode 100644 admin/views/verse/view.html.php create mode 100644 admin/views/verses/index.html create mode 100644 admin/views/verses/tmpl/default.php create mode 100644 admin/views/verses/tmpl/default_batch_body.php create mode 100644 admin/views/verses/tmpl/default_batch_footer.php create mode 100644 admin/views/verses/tmpl/default_body.php create mode 100644 admin/views/verses/tmpl/default_foot.php create mode 100644 admin/views/verses/tmpl/default_head.php create mode 100644 admin/views/verses/tmpl/default_toolbar.php create mode 100644 admin/views/verses/tmpl/index.html create mode 100644 admin/views/verses/view.html.php create mode 100644 getbible.xml create mode 100644 index.html create mode 100644 libraries/jcb_powers/.htaccess create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/AI.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/AI/Engineer.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/AI/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Abstraction/Api.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Abstraction/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Api/Books.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Api/Chapters.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Api/Translations.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Api/Verses.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Api/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Config.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/DailyScripture.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Book.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Chapter.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Placeholders.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Prompt.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Response.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Scripture.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Translation.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Verse.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Word.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Database/Insert.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Database/Load.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Database/Update.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Database/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Factory.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Linker.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Loader.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Model/Load.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Model/Upsert.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Model/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Note.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Openai.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Openai/Config.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Openai/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Search.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/AI.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Api.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/App.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Data.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Database.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Model.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Openai.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Utilities.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Table.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Tag.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Tagged.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Tagged/Paragraphs.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Tagged/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/Http.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/Response.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/SessionHelper.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/StringHelper.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/Uri.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/Watcher.php create mode 100644 libraries/jcb_powers/VDM.Joomla.GetBible/src/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Abstraction/Api.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Abstraction/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Cron.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Organizations.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Unadopted.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Users.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Users/Keys.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Users/Organization.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Users/Repository.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Users/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Factory.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Comments.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Deadline.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Labels.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Milestones.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Reactions.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Reactions/Comment.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Reactions/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Repository/Comments.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Repository/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Stopwatch.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Subscriptions.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Timeline.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Times.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Labels.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/Activitypub.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/Gpg.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/Markdown.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/NodeInfo.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/Version.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Notifications.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Notifications/Repository.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Notifications/Thread.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Notifications/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Hooks.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Labels.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Members.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/PublicMembers.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Repository.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Teams.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Teams/Members.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Teams/Repository.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Teams/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/User.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Package.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Package/Files.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Package/Owner.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Package/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Archive.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Assignees.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Attachments.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Branch.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Branch/Protection.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Branch/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Collaborator.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Commits.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Contents.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Forks.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Gpg.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Hooks.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Hooks/Git.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Hooks/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Keys.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Languages.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Media.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Merge.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Mirror.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Mirrors.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Notes.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Patch.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Pulls.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Refs.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Releases.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Remote.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Reviewers.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Reviews.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Stargazers.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Statuses.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Tags.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Teams.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Templates.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Times.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Topics.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Transfer.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Trees.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Watchers.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Wiki.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Admin.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Issue.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Jcb.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Miscellaneous.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Notifications.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Organization.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Package.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Repository.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Settings.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/User.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Utilities.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Settings/Api.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Settings/Attachment.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Settings/Repository.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Settings/Ui.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Settings/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/User.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Applications.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Emails.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Followers.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Following.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Gpg.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Keys.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Repos.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Settings.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Starred.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Subscriptions.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Teams.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Times.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Tokens.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/User/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Utilities/Http.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Utilities/Response.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Utilities/Uri.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/Utilities/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Gitea/src/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Openai/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Openai/src/Abstraction/Api.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Openai/src/Abstraction/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Openai/src/Chat.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Openai/src/Completions.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Openai/src/Models.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Openai/src/Moderate.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Openai/src/Service/Utilities.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Openai/src/Service/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Openai/src/Utilities/Http.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Openai/src/Utilities/Response.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Openai/src/Utilities/Uri.php create mode 100644 libraries/jcb_powers/VDM.Joomla.Openai/src/Utilities/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla.Openai/src/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Abstraction/BaseConfig.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Abstraction/BaseTable.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Abstraction/Database.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Abstraction/Model.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Abstraction/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Database/Insert.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Database/Load.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Database/Update.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Database/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Interfaces/FactoryInterface.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Interfaces/InsertInterface.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Interfaces/LoadInterface.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Interfaces/ModelInterface.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Interfaces/Tableinterface.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Interfaces/UpdateInterface.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Interfaces/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Utilities/ArrayHelper.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Utilities/Component/Helper.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Utilities/Component/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Utilities/FileHelper.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Utilities/GetHelper.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Utilities/GuidHelper.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Utilities/JsonHelper.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Utilities/ObjectHelper.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Utilities/String/ClassfunctionHelper.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Utilities/String/index.html create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Utilities/StringHelper.php create mode 100644 libraries/jcb_powers/htaccess.txt create mode 100644 libraries/jcb_powers/index.html create mode 100644 libraries/jcb_powers/web.config create mode 100644 media/css/index.html create mode 100644 media/datatable/css/datatables.min.css create mode 100644 media/datatable/css/index.html create mode 100644 media/datatable/index.html create mode 100644 media/datatable/js/datatables.min.js create mode 100644 media/datatable/js/index.html create mode 100644 media/datatable/js/pdfmake.min.js create mode 100644 media/datatable/js/vfs_fonts.js create mode 100644 media/images/ajax.gif create mode 100644 media/images/icon.png create mode 100644 media/images/index.html create mode 100644 media/index.html create mode 100644 media/js/book.js create mode 100644 media/js/chapter.js create mode 100644 media/js/index.html create mode 100644 media/js/linker.js create mode 100644 media/js/note.js create mode 100644 media/js/open_ai_message.js create mode 100644 media/js/open_ai_response.js create mode 100644 media/js/password.js create mode 100644 media/js/prompt.js create mode 100644 media/js/tag.js create mode 100644 media/js/tagged_verse.js create mode 100644 media/js/translation.js create mode 100644 media/js/verse.js create mode 100644 media/nouislider/css/index.html create mode 100644 media/nouislider/css/nouislider.min.css create mode 100644 media/nouislider/index.html create mode 100644 media/nouislider/js/index.html create mode 100644 media/nouislider/js/nouislider.min.js create mode 100644 media/uikit-v3/css/index.html create mode 100644 media/uikit-v3/css/uikit-rtl.css create mode 100644 media/uikit-v3/css/uikit-rtl.min.css create mode 100644 media/uikit-v3/css/uikit.css create mode 100644 media/uikit-v3/css/uikit.min.css create mode 100644 media/uikit-v3/index.html create mode 100644 media/uikit-v3/js/index.html create mode 100644 media/uikit-v3/js/uikit-icons.js create mode 100644 media/uikit-v3/js/uikit-icons.min.js create mode 100644 media/uikit-v3/js/uikit.js create mode 100644 media/uikit-v3/js/uikit.min.js create mode 100644 script.php create mode 100644 site/assets/css/api.css create mode 100644 site/assets/css/app.css create mode 100644 site/assets/css/index.html create mode 100644 site/assets/css/openai.css create mode 100644 site/assets/css/search.css create mode 100644 site/assets/css/site.css create mode 100644 site/assets/css/tag.css create mode 100644 site/assets/images/index.html create mode 100644 site/assets/index.html create mode 100644 site/assets/js/app.js create mode 100644 site/assets/js/index.html create mode 100644 site/assets/js/openai.js create mode 100644 site/assets/js/search.js create mode 100644 site/assets/js/site.js create mode 100644 site/controller.php create mode 100644 site/controllers/ajax.json.php create mode 100644 site/controllers/index.html create mode 100644 site/getbible.php create mode 100644 site/helpers/category.php create mode 100644 site/helpers/getbible.php create mode 100644 site/helpers/headercheck.php create mode 100644 site/helpers/index.html create mode 100644 site/helpers/route.php create mode 100644 site/index.html create mode 100644 site/language/en-GB/en-GB.com_getbible.ini create mode 100644 site/language/en-GB/en-GB.com_getbible.sys.ini create mode 100644 site/language/en-GB/index.html create mode 100644 site/language/index.html create mode 100644 site/layouts/aidetails.php create mode 100644 site/layouts/airesponsemessage.php create mode 100644 site/layouts/getbibleappnote.php create mode 100644 site/layouts/getbibleappnotelink.php create mode 100644 site/layouts/getbiblefooter.php create mode 100644 site/layouts/getbiblehashdetails.php create mode 100644 site/layouts/getbibleparagraph.php create mode 100644 site/layouts/getbibleverse.php create mode 100644 site/layouts/getbibleverses.php create mode 100644 site/layouts/getbibleversetag.php create mode 100644 site/layouts/index.html create mode 100644 site/layouts/input.php create mode 100644 site/layouts/inputbox.php create mode 100644 site/layouts/modal.php create mode 100644 site/layouts/modulepositionerror.php create mode 100644 site/layouts/nextchapter.php create mode 100644 site/layouts/previouschapter.php create mode 100644 site/layouts/promptmessage.php create mode 100644 site/layouts/promptsettings.php create mode 100644 site/layouts/rows.php create mode 100644 site/layouts/select.php create mode 100644 site/layouts/selectbox.php create mode 100644 site/layouts/table.php create mode 100644 site/models/ajax.php create mode 100644 site/models/api.php create mode 100644 site/models/app.php create mode 100644 site/models/index.html create mode 100644 site/models/openai.php create mode 100644 site/models/search.php create mode 100644 site/models/tag.php create mode 100644 site/router.php create mode 100644 site/views/api/index.html create mode 100644 site/views/api/tmpl/default.php create mode 100644 site/views/api/tmpl/default.xml create mode 100644 site/views/api/tmpl/index.html create mode 100644 site/views/api/view.html.php create mode 100644 site/views/app/index.html create mode 100644 site/views/app/tmpl/default.php create mode 100644 site/views/app/tmpl/default.xml create mode 100644 site/views/app/tmpl/default_getbibleapp.php create mode 100644 site/views/app/tmpl/default_getbibleappbody.php create mode 100644 site/views/app/tmpl/default_getbibleappbottommenu.php create mode 100644 site/views/app/tmpl/default_getbibleappcustomtabs.php create mode 100644 site/views/app/tmpl/default_getbibleappcustomtabsmenu.php create mode 100644 site/views/app/tmpl/default_getbibleappdebug.php create mode 100644 site/views/app/tmpl/default_getbibleappdetails.php create mode 100644 site/views/app/tmpl/default_getbibleappfooter.php create mode 100644 site/views/app/tmpl/default_getbibleappmodalbottom.php create mode 100644 site/views/app/tmpl/default_getbibleappnotes.php create mode 100644 site/views/app/tmpl/default_getbibleappsettings.php create mode 100644 site/views/app/tmpl/default_getbibleappshare.php create mode 100644 site/views/app/tmpl/default_getbibleapptags.php create mode 100644 site/views/app/tmpl/default_getbibleapptopmenu.php create mode 100644 site/views/app/tmpl/default_getbibleappword.php create mode 100644 site/views/app/tmpl/default_getbiblebooks.php create mode 100644 site/views/app/tmpl/default_getbiblechapters.php create mode 100644 site/views/app/tmpl/default_getbiblefavouriteverseselector.php create mode 100644 site/views/app/tmpl/default_getbibleinstallbutton.php create mode 100644 site/views/app/tmpl/default_getbibletext.php create mode 100644 site/views/app/tmpl/default_getbibletranslations.php create mode 100644 site/views/app/tmpl/default_versesparagraph.php create mode 100644 site/views/app/tmpl/default_versesunorderedlist.php create mode 100644 site/views/app/tmpl/index.html create mode 100644 site/views/app/view.html.php create mode 100644 site/views/index.html create mode 100644 site/views/openai/index.html create mode 100644 site/views/openai/tmpl/default.php create mode 100644 site/views/openai/tmpl/default_getbibleai.php create mode 100644 site/views/openai/tmpl/default_getbibleaibody.php create mode 100644 site/views/openai/tmpl/default_getbibleaibottommenu.php create mode 100644 site/views/openai/tmpl/default_getbibleaicustomtabs.php create mode 100644 site/views/openai/tmpl/default_getbibleaicustomtabsmenu.php create mode 100644 site/views/openai/tmpl/default_getbibleaidebug.php create mode 100644 site/views/openai/tmpl/default_getbibleaidetails.php create mode 100644 site/views/openai/tmpl/default_getbibleaifilter.php create mode 100644 site/views/openai/tmpl/default_getbibleaifooter.php create mode 100644 site/views/openai/tmpl/default_getbibleaimessages.php create mode 100644 site/views/openai/tmpl/default_getbibleaipromptmessages.php create mode 100644 site/views/openai/tmpl/default_getbibleaitopmenu.php create mode 100644 site/views/openai/tmpl/default_getbiblepromptsettings.php create mode 100644 site/views/openai/tmpl/index.html create mode 100644 site/views/openai/view.html.php create mode 100644 site/views/search/index.html create mode 100644 site/views/search/tmpl/default.php create mode 100644 site/views/search/tmpl/default_getbiblesearch.php create mode 100644 site/views/search/tmpl/default_getbiblesearchbox.php create mode 100644 site/views/search/tmpl/default_getbiblesearchinput.php create mode 100644 site/views/search/tmpl/default_getbiblesearchnotenoughverses.php create mode 100644 site/views/search/tmpl/default_getbiblesearchoptions.php create mode 100644 site/views/search/tmpl/default_getbiblesearchtable.php create mode 100644 site/views/search/tmpl/index.html create mode 100644 site/views/search/view.html.php create mode 100644 site/views/tag/index.html create mode 100644 site/views/tag/tmpl/default.php create mode 100644 site/views/tag/tmpl/default_getbiblenotag.php create mode 100644 site/views/tag/tmpl/default_getbibleselecttags.php create mode 100644 site/views/tag/tmpl/default_getbibletag.php create mode 100644 site/views/tag/tmpl/default_getbibletagbody.php create mode 100644 site/views/tag/tmpl/default_getbibletagbottommenu.php create mode 100644 site/views/tag/tmpl/default_getbibletagcustomtabs.php create mode 100644 site/views/tag/tmpl/default_getbibletagcustomtabsmenu.php create mode 100644 site/views/tag/tmpl/default_getbibletagdebug.php create mode 100644 site/views/tag/tmpl/default_getbibletagfooter.php create mode 100644 site/views/tag/tmpl/default_getbibletagparagraphs.php create mode 100644 site/views/tag/tmpl/default_getbibletagparagraphssorter.php create mode 100644 site/views/tag/tmpl/default_getbibletagtopmenu.php create mode 100644 site/views/tag/tmpl/index.html create mode 100644 site/views/tag/view.html.php create mode 100644 update_server.xml diff --git a/.octojpack b/.octojpack new file mode 100644 index 0000000..9b64be0 --- /dev/null +++ b/.octojpack @@ -0,0 +1,69 @@ +{ + "global": { + "packager": "Vast Development Method", + "packager_url": "https://dev.vdm.io/", + "url": "git.vdm.dev", + "api": "https://git.vdm.dev/api/v1" + }, + "package": { + "name": "PKG_GETBIBLE", + "code_name": "getbible", + "package_name": "pkg_getbible", + "min_joomla_version": "3.8", + "max_joomla_version": "3.10", + "copyright": "Copyright (C) 2015 Llewellyn van der Merwe. All rights reserved.", + "copyright_year": "2015", + "license": "GNU General Public License version 2; see LICENSE", + "license_file": "LICENSE", + "author": "Llewellyn van der Merwe", + "author_email": "joomla@vdm.io", + "author_url": "https://io.vdm.dev/", + "description": "The Get Bible for Joomla.", + "version_id": "com_getbible", + "update_servers": "https://git.vdm.dev/getBible/joomla-component/raw/branch/master/update_server.xml" + }, + "repository": { + "owner": "getBible", + "repo": "joomla-pkg" + }, + "files": [ + { + "owner": "getBible", + "repo": "joomla-component", + "id": "com_getbible", + "type": "component", + "mode": "master" + }, + { + "owner": "getBible", + "repo": "daily-light-module", + "id": "mod_dailylight", + "type": "module", + "client": "site", + "mode": "master" + }, + { + "owner": "getBible", + "repo": "daily-scripture-module", + "id": "mod_dailyscripture", + "type": "module", + "client": "site", + "mode": "master" + } + ], + "languages": [ + { + "tag": "en-GB", + "ini": "sys.ini", + "key": "PKG_GETBIBLE", + "value": "GetBible Package" + }, + { + "tag": "en-GB", + "ini": "ini", + "key": "PKG_GETBIBLE", + "value": "GetBible Package" + } + ] +} + diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9614ab3 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +# v2.0.1 + +- New System Architecture as to how Scripture is added +- New Application Page (Bible Page) +- New Linker (anonymous users) system +- SEO for each chapter of the Bible +- New Easy Sharing System +- New Tagging system +- New Notes system +- New Search system +- Integration with OpenAI \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..df50810 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,340 @@ +GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e26ed39 --- /dev/null +++ b/README.md @@ -0,0 +1,60 @@ +# Get Bible (2.0.1) + + ![Get Bible image](https://git.vdm.dev/getBible/joomla-component/raw/branch/master/admin/assets/images/vdm-component.jpg "GetBible") + +Welcome to the next level of scripture engagement - The Bible for Joomla! Our purpose is to bring the Word of God to every person, in their native language, entirely free. This isn't just a typical extension; it's a groundbreaking tool developed to span language divides and deliver a rich, customizable Bible study experience to users worldwide. + +With an impressive array of 80 translations, our Joomla extension allows people from all corners of the globe to read, comprehend, and meditate on the Holy Scriptures in their preferred language. Moreover, we offer the unique opportunity for individuals to host the Bible on their own website, further extending the reach of the Word. + +We've integrated robust features such as note-taking, tagging, and a search function, to enhance your interaction with the Scriptures. This allows users to immerse themselves in the text, crafting a personal journey through the Bible that can be revisited in future sessions. Furthermore, our innovative linker system assigns each visitor a unique identifier (GUID) - no login required. This means you can create notes, select favorite verses, and even share sessions, while maintaining control over your personalized content. + +A distinctive feature of our application is the integration with OpenAI. This advanced capability allows website owners to create custom prompts to interact with OpenAI using text from any translation. This function allows you to ask questions, gain clarity, and deepen your understanding of the Scriptures in an engaging and user-friendly manner. + +In essence, The Bible for Joomla is designed to transform how the Word of God is shared, studied, and comprehended. Its comprehensive features, combined with a user-friendly interface, make it an essential tool for individuals, churches, and website owners alike. Join us on this journey of faith as we make the wisdom and guidance of the Scriptures accessible to all, one verse, one language, and one website at a time. + +# Build Details + ++ *Company*: [Vast Development Method](https://getbible.net) ++ *Author*: [Llewellyn van der Merwe](mailto:joomla@vdm.io) ++ *Name*: [Get Bible](https://getbible.net) ++ *First Build*: 3rd December, 2015 ++ *Last Build*: 26th July, 2023 ++ *Version*: 2.0.1 ++ *Copyright*: Copyright (C) 2015. All Rights Reserved ++ *License*: GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +## Build Time + +**530 Hours** or **66 Eight Hour Days** (actual time the author saved - +due to [Automated Component Builder](https://www.joomlacomponentbuilder.com)) + +> (if creating a folder and file took **5 seconds** and writing one line of code took **10 seconds**, +> never making one mistake or taking any coffee break.) + ++ *Line count*: **189808** ++ *File count*: **1660** ++ *Folder count*: **161** + +**349 Hours** or **44 Eight Hour Days** (the actual time the author spent) + +> (with the following break down: +> **debugging @132hours** = codingtime / 4; +> **planning @76hours** = codingtime / 7; +> **mapping @53hours** = codingtime / 10; +> **office @88hours** = codingtime / 6;) + +**879 Hours** or **110 Eight Hour Days** +(a total of the realistic time frame for this project) + +> (if creating a folder and file took **5 seconds** and writing one line of code took **10 seconds**, +> with the normal everyday realities at the office, that includes the component planning, mapping & debugging.) + +Project duration: **22 weeks** or **4.6 months** + +> This **component** was build with a Joomla [Automated Component Builder](https://www.joomlacomponentbuilder.com). +> Developed by [Llewellyn van der Merwe](mailto:joomla@vdm.io) + +## Donations + +If you want to support this project, please consider donating: +* Open Collective: [Joomla-Component-Builder](https://opencollective.com/Joomla-Component-Builder) \ No newline at end of file diff --git a/admin/README.txt b/admin/README.txt new file mode 100644 index 0000000..e26ed39 --- /dev/null +++ b/admin/README.txt @@ -0,0 +1,60 @@ +# Get Bible (2.0.1) + + ![Get Bible image](https://git.vdm.dev/getBible/joomla-component/raw/branch/master/admin/assets/images/vdm-component.jpg "GetBible") + +Welcome to the next level of scripture engagement - The Bible for Joomla! Our purpose is to bring the Word of God to every person, in their native language, entirely free. This isn't just a typical extension; it's a groundbreaking tool developed to span language divides and deliver a rich, customizable Bible study experience to users worldwide. + +With an impressive array of 80 translations, our Joomla extension allows people from all corners of the globe to read, comprehend, and meditate on the Holy Scriptures in their preferred language. Moreover, we offer the unique opportunity for individuals to host the Bible on their own website, further extending the reach of the Word. + +We've integrated robust features such as note-taking, tagging, and a search function, to enhance your interaction with the Scriptures. This allows users to immerse themselves in the text, crafting a personal journey through the Bible that can be revisited in future sessions. Furthermore, our innovative linker system assigns each visitor a unique identifier (GUID) - no login required. This means you can create notes, select favorite verses, and even share sessions, while maintaining control over your personalized content. + +A distinctive feature of our application is the integration with OpenAI. This advanced capability allows website owners to create custom prompts to interact with OpenAI using text from any translation. This function allows you to ask questions, gain clarity, and deepen your understanding of the Scriptures in an engaging and user-friendly manner. + +In essence, The Bible for Joomla is designed to transform how the Word of God is shared, studied, and comprehended. Its comprehensive features, combined with a user-friendly interface, make it an essential tool for individuals, churches, and website owners alike. Join us on this journey of faith as we make the wisdom and guidance of the Scriptures accessible to all, one verse, one language, and one website at a time. + +# Build Details + ++ *Company*: [Vast Development Method](https://getbible.net) ++ *Author*: [Llewellyn van der Merwe](mailto:joomla@vdm.io) ++ *Name*: [Get Bible](https://getbible.net) ++ *First Build*: 3rd December, 2015 ++ *Last Build*: 26th July, 2023 ++ *Version*: 2.0.1 ++ *Copyright*: Copyright (C) 2015. All Rights Reserved ++ *License*: GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +## Build Time + +**530 Hours** or **66 Eight Hour Days** (actual time the author saved - +due to [Automated Component Builder](https://www.joomlacomponentbuilder.com)) + +> (if creating a folder and file took **5 seconds** and writing one line of code took **10 seconds**, +> never making one mistake or taking any coffee break.) + ++ *Line count*: **189808** ++ *File count*: **1660** ++ *Folder count*: **161** + +**349 Hours** or **44 Eight Hour Days** (the actual time the author spent) + +> (with the following break down: +> **debugging @132hours** = codingtime / 4; +> **planning @76hours** = codingtime / 7; +> **mapping @53hours** = codingtime / 10; +> **office @88hours** = codingtime / 6;) + +**879 Hours** or **110 Eight Hour Days** +(a total of the realistic time frame for this project) + +> (if creating a folder and file took **5 seconds** and writing one line of code took **10 seconds**, +> with the normal everyday realities at the office, that includes the component planning, mapping & debugging.) + +Project duration: **22 weeks** or **4.6 months** + +> This **component** was build with a Joomla [Automated Component Builder](https://www.joomlacomponentbuilder.com). +> Developed by [Llewellyn van der Merwe](mailto:joomla@vdm.io) + +## Donations + +If you want to support this project, please consider donating: +* Open Collective: [Joomla-Component-Builder](https://opencollective.com/Joomla-Component-Builder) \ No newline at end of file diff --git a/admin/access.xml b/admin/access.xml new file mode 100644 index 0000000..f722b7d --- /dev/null +++ b/admin/access.xml @@ -0,0 +1,505 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + +
+
+ + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
\ No newline at end of file diff --git a/admin/assets/css/admin.css b/admin/assets/css/admin.css new file mode 100644 index 0000000..c9c3e5e --- /dev/null +++ b/admin/assets/css/admin.css @@ -0,0 +1,21 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ +.no-click { + pointer-events: none; +} + diff --git a/admin/assets/css/book.css b/admin/assets/css/book.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/book.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/books.css b/admin/assets/css/books.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/books.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/chapter.css b/admin/assets/css/chapter.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/chapter.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/chapters.css b/admin/assets/css/chapters.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/chapters.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/dashboard.css b/admin/assets/css/dashboard.css new file mode 100644 index 0000000..10742d8 --- /dev/null +++ b/admin/assets/css/dashboard.css @@ -0,0 +1,169 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + +.dashboard-container { + margin-left: 10px; + margin-top: 10px; + width: 100%; +} +.dashboard-container [class*="span"] { + display: block; + float: none; + margin-left: 0; + width: auto; +} +.dashboard-container:before, .dashboard-container:after { + content: ""; + display: table; +} +.dashboard-container:after { + clear: both; +} +.dashboard-container [class*="span"] { + box-sizing: border-box; + display: block; + float: left; + min-height: 145px; + min-width: 96px; + width: 100%; +} +.dashboard-container [class*="span"]:first-child { + margin-left: 0; +} +.dashboard-wraper { + background: none repeat scroll 0 0 hsl(0, 0%, 93%); + border-radius: 5px; + float: left; + margin: 1%; + padding: 3px; + width: 17%; + min-height: 194px; + min-width: 96px; +} +.dashboard-content a { + background: linear-gradient(to bottom, hsl(0, 0%, 100%) 0%, hsl(0, 0%, 96%) 47%, hsl(0, 0%, 93%) 100%) repeat scroll 0 0 hsla(0, 0%, 0%, 0); + border: 1px solid hsl(0, 0%, 85%); + border-radius: 4px; + box-shadow: 0 0 3px hsla(0, 0%, 0%, 0.1) inset; + color: hsl(0, 0%, 20%); + display: block; + min-height: 89px; + padding: 10px; + text-align: center; + text-decoration: none; +} +.dashboard-content a:hover { + background: linear-gradient(to bottom, hsl(0, 0%, 90%) 0%, hsl(0, 0%, 100%) 100%) repeat scroll 0 0 hsla(0, 0%, 0%, 0); + color: hsl(200, 100%, 30%); + text-decoration: none; +} +.dashboard-title { + display: block; + padding-top: 5px; +} +.dashboard-info { + background: linear-gradient(to bottom, hsl(0, 0%, 100%) 0%, hsl(0, 0%, 96%) 47%, hsl(0, 0%, 93%) 100%) repeat scroll 0 0 hsla(0, 0%, 0%, 0); + border: 1px solid hsl(0, 0%, 85%); + border-radius: 4px; + box-shadow: 0 0 3px hsla(0, 0%, 0%, 0.1) inset; + color: hsl(0, 0%, 20%); + display: block; + font-size: 12px; + padding: 10px; + text-align: center; +} +.dashboard-info span { + display: block; + text-align: center; +} +.dashboard-info img { + margin: 0 auto; +} +.dashboard-table { + border-top: 1px solid hsl(0, 0%, 87%); + margin-top: 5px; + width: 100%; +} +.dashboard-info h5 { + font-size: 11px; + font-weight: bold; +} +.dashboard-block { + background: linear-gradient(to bottom, hsl(0, 0%, 95%) 0%, hsl(0, 0%, 86%) 100%) repeat scroll 0 0 hsla(0, 0%, 0%, 0); + border: 1px solid hsl(0, 0%, 76%); + border-radius: 3px; + box-shadow: 0 1px 0 hsl(0, 0%, 98%) inset; + margin-bottom: 20px; +} +.dashboard-block .dashboard-block-head { + background: linear-gradient(to bottom, hsl(0, 0%, 95%) 0%, hsl(0, 0%, 86%) 100%) repeat scroll 0 0 hsla(0, 0%, 0%, 0); + border-bottom: 1px solid hsl(0, 0%, 76%); + border-radius: 3px 3px 0 0; + box-shadow: 0 1px 0 hsl(0, 0%, 98%) inset, 0 0 3px hsl(0, 0%, 87%); + height: 40px; + position: relative; +} +.dashboard-block .dashboard-block-head h5 { + font-size: 12px; + margin: 0; + padding-left: 10px; + padding-top: 11px; + text-transform: uppercase; +} +.dashboard-block .dashboard-block-content { + background: none repeat scroll 0 0 hsl(0, 0%, 93%); + border-radius: 0 0 3px 3px; +} +.dashboard-block .dashboard-block-box { + background: none repeat scroll 0 0 hsl(0, 0%, 100%); + border-top: 1px solid hsl(0, 0%, 82%); + box-shadow: 0 0 5px hsl(0, 0%, 87%) inset; +} +.dashboard-block .dashboard-block-content .dashboard-block-box { + margin-top: 0 !important; +} +.dashboard-block .dashboard-block-content .dashboard-block-box .dashboard-block-table { + margin-bottom: 0 !important; +} +.dashboard-block-table { + background-color: hsla(0, 0%, 0%, 0); + border-collapse: collapse; + border-spacing: 0; + margin-bottom: 20px; + max-width: 100%; + width: 100%; +} +.dashboard-block-table th, .dashboard-block-table td { + border-top: 1px solid hsl(0, 0%, 87%); + line-height: 20px; + padding: 5px; + text-align: left; + vertical-align: middle; +} +.dashboard-badge { + background-color: hsl(0, 0%, 60%); + border-radius: 9px; + color: hsl(0, 0%, 100%); + font-size: 11.844px; + font-weight: bold; + line-height: 14px; + padding: 1px 9px 2px; + text-shadow: 0 -1px 0 hsla(0, 0%, 0%, 0.25); + vertical-align: baseline; + white-space: nowrap; +} \ No newline at end of file diff --git a/admin/assets/css/index.html b/admin/assets/css/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/assets/css/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/assets/css/linker.css b/admin/assets/css/linker.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/linker.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/linkers.css b/admin/assets/css/linkers.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/linkers.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/note.css b/admin/assets/css/note.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/note.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/notes.css b/admin/assets/css/notes.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/notes.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/open_ai_message.css b/admin/assets/css/open_ai_message.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/open_ai_message.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/open_ai_messages.css b/admin/assets/css/open_ai_messages.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/open_ai_messages.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/open_ai_response.css b/admin/assets/css/open_ai_response.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/open_ai_response.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/open_ai_responses.css b/admin/assets/css/open_ai_responses.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/open_ai_responses.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/password.css b/admin/assets/css/password.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/password.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/passwords.css b/admin/assets/css/passwords.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/passwords.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/prompt.css b/admin/assets/css/prompt.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/prompt.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/prompts.css b/admin/assets/css/prompts.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/prompts.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/tag.css b/admin/assets/css/tag.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/tag.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/tagged_verse.css b/admin/assets/css/tagged_verse.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/tagged_verse.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/tagged_verses.css b/admin/assets/css/tagged_verses.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/tagged_verses.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/tags.css b/admin/assets/css/tags.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/tags.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/translation.css b/admin/assets/css/translation.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/translation.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/translations.css b/admin/assets/css/translations.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/translations.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/verse.css b/admin/assets/css/verse.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/verse.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/verses.css b/admin/assets/css/verses.css new file mode 100644 index 0000000..488f773 --- /dev/null +++ b/admin/assets/css/verses.css @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/images/ajax.gif b/admin/assets/images/ajax.gif new file mode 100644 index 0000000000000000000000000000000000000000..4371cc618bdc1702aad69fc871a50182a01537ec GIT binary patch literal 65516 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⩔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 literal 0 HcmV?d00001 diff --git a/admin/assets/images/icons/books.png b/admin/assets/images/icons/books.png new file mode 100644 index 0000000000000000000000000000000000000000..3076ed48dd3bdea999d5145cf78939a53ffef618 GIT binary patch literal 26047 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 R \ No newline at end of file diff --git a/admin/assets/images/icons/linkers.png b/admin/assets/images/icons/linkers.png new file mode 100644 index 0000000000000000000000000000000000000000..47f68050809879d7dd0b7e511d1d4c60c8f404cb GIT binary patch literal 16792 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 literal 0 HcmV?d00001 diff --git a/admin/assets/images/icons/tagged_verses.png b/admin/assets/images/icons/tagged_verses.png new file mode 100644 index 0000000000000000000000000000000000000000..743dfaae360ae8b69092251f5e0f640621894ba2 GIT binary patch literal 20450 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 literal 0 HcmV?d00001 diff --git a/admin/assets/images/icons/translations.png b/admin/assets/images/icons/translations.png new file mode 100644 index 0000000000000000000000000000000000000000..4c3ca8ca6d32f5bf250e94791d77197aefec6cb5 GIT binary patch literal 22931 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

d_KiKBV4!U$Kb(ioS5zngo}#~I$gHp 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 iHzs#00(GZSJO3ZN6pqLt#xAKAL(B)HYWBv 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⩔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 literal 0 HcmV?d00001 diff --git a/admin/assets/images/index.html b/admin/assets/images/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/assets/images/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/assets/images/vdm-component.jpg b/admin/assets/images/vdm-component.jpg new file mode 100644 index 0000000000000000000000000000000000000000..be6df550e8a9a2d278dd84d8fcfb00eb649982be GIT binary patch literal 13109 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 literal 0 HcmV?d00001 diff --git a/admin/assets/index.html b/admin/assets/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/assets/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/assets/js/admin.js b/admin/assets/js/admin.js new file mode 100644 index 0000000..a32768d --- /dev/null +++ b/admin/assets/js/admin.js @@ -0,0 +1,17 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +/* JS Document */ diff --git a/admin/assets/js/index.html b/admin/assets/js/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/assets/js/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/config.xml b/admin/config.xml new file mode 100644 index 0000000..eacee4b --- /dev/null +++ b/admin/config.xml @@ -0,0 +1,1444 @@ + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + " + " + + + + " + " + " + + + + " + " + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
+ + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ \ No newline at end of file diff --git a/admin/controller.php b/admin/controller.php new file mode 100644 index 0000000..0b43409 --- /dev/null +++ b/admin/controller.php @@ -0,0 +1,130 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\BaseController; +use Joomla\Utilities\ArrayHelper; + +/** + * General Controller of Getbible component + */ +class GetbibleController extends BaseController +{ + /** + * Constructor. + * + * @param array $config An optional associative array of configuration settings. + * Recognized key values include 'name', 'default_task', 'model_path', and + * 'view_path' (this list is not meant to be comprehensive). + * + * @since 3.0 + */ + public function __construct($config = array()) + { + // set the default view + $config['default_view'] = 'getbible'; + + parent::__construct($config); + } + + /** + * display task + * + * @return void + */ + function display($cachable = false, $urlparams = false) + { + // set default view if not set + $view = $this->input->getCmd('view', 'getbible'); + $data = $this->getViewRelation($view); + $layout = $this->input->get('layout', null, 'WORD'); + $id = $this->input->getInt('id'); + + // Check for edit form. + if(GetbibleHelper::checkArray($data)) + { + if ($data['edit'] && $layout == 'edit' && !$this->checkEditId('com_getbible.edit.'.$data['view'], $id)) + { + // Somehow the person just went to the form - we don't allow that. + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id)); + $this->setMessage($this->getError(), 'error'); + // check if item was opend from other then its own list view + $ref = $this->input->getCmd('ref', 0); + $refid = $this->input->getInt('refid', 0); + // set redirect + if ($refid > 0 && GetbibleHelper::checkString($ref)) + { + // redirect to item of ref + $this->setRedirect(JRoute::_('index.php?option=com_getbible&view='.(string)$ref.'&layout=edit&id='.(int)$refid, false)); + } + elseif (GetbibleHelper::checkString($ref)) + { + + // redirect to ref + $this->setRedirect(JRoute::_('index.php?option=com_getbible&view='.(string)$ref, false)); + } + else + { + // normal redirect back to the list view + $this->setRedirect(JRoute::_('index.php?option=com_getbible&view='.$data['views'], false)); + } + + return false; + } + } + + return parent::display($cachable, $urlparams); + } + + protected function getViewRelation($view) + { + // check the we have a value + if (GetbibleHelper::checkString($view)) + { + // the view relationships + $views = array( + 'linker' => 'linkers', + 'note' => 'notes', + 'tagged_verse' => 'tagged_verses', + 'prompt' => 'prompts', + 'open_ai_response' => 'open_ai_responses', + 'open_ai_message' => 'open_ai_messages', + 'password' => 'passwords', + 'tag' => 'tags', + 'translation' => 'translations', + 'book' => 'books', + 'chapter' => 'chapters', + 'verse' => 'verses' + ); + // check if this is a list view + if (in_array($view, $views)) + { + // this is a list view + return array('edit' => false, 'view' => array_search($view,$views), 'views' => $view); + } + // check if it is an edit view + elseif (array_key_exists($view, $views)) + { + // this is a edit view + return array('edit' => true, 'view' => $view, 'views' => $views[$view]); + } + } + return false; + } +} diff --git a/admin/controllers/ajax.json.php b/admin/controllers/ajax.json.php new file mode 100644 index 0000000..156bbaa --- /dev/null +++ b/admin/controllers/ajax.json.php @@ -0,0 +1,247 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\BaseController; +use Joomla\Utilities\ArrayHelper; + +/** + * Getbible Ajax Base Controller + */ +class GetbibleControllerAjax extends BaseController +{ + public function __construct($config) + { + parent::__construct($config); + // make sure all json stuff are set + JFactory::getDocument()->setMimeEncoding( 'application/json' ); + // get the application + $app = JFactory::getApplication(); + $app->setHeader('Content-Disposition','attachment;filename="getajax.json"'); + $app->setHeader('Access-Control-Allow-Origin', '*'); + // load the tasks + $this->registerTask('isNew', 'ajax'); + $this->registerTask('isRead', 'ajax'); + $this->registerTask('getWiki', 'ajax'); + $this->registerTask('getVersion', 'ajax'); + } + + public function ajax() + { + // get the user for later use + $user = JFactory::getUser(); + // get the input values + $jinput = JFactory::getApplication()->input; + // check if we should return raw + $returnRaw = $jinput->get('raw', false, 'BOOLEAN'); + // return to a callback function + $callback = $jinput->get('callback', null, 'CMD'); + // Check Token! + $token = JSession::getFormToken(); + $call_token = $jinput->get('token', 0, 'ALNUM'); + if($jinput->get($token, 0, 'ALNUM') || $token === $call_token) + { + // get the task + $task = $this->getTask(); + switch($task) + { + case 'isNew': + try + { + $noticeValue = $jinput->get('notice', NULL, 'STRING'); + if($noticeValue && $user->id != 0) + { + $result = $this->getModel('ajax')->isNew($noticeValue); + } + else + { + $result = false; + } + if($callback) + { + echo $callback . "(".json_encode($result).");"; + } + elseif($returnRaw) + { + echo json_encode($result); + } + else + { + echo "(".json_encode($result).");"; + } + } + catch(Exception $e) + { + if($callback) + { + echo $callback."(".json_encode($e).");"; + } + elseif($returnRaw) + { + echo json_encode($e); + } + else + { + echo "(".json_encode($e).");"; + } + } + break; + case 'isRead': + try + { + $noticeValue = $jinput->get('notice', NULL, 'STRING'); + if($noticeValue && $user->id != 0) + { + $result = $this->getModel('ajax')->isRead($noticeValue); + } + else + { + $result = false; + } + if($callback) + { + echo $callback . "(".json_encode($result).");"; + } + elseif($returnRaw) + { + echo json_encode($result); + } + else + { + echo "(".json_encode($result).");"; + } + } + catch(Exception $e) + { + if($callback) + { + echo $callback."(".json_encode($e).");"; + } + elseif($returnRaw) + { + echo json_encode($e); + } + else + { + echo "(".json_encode($e).");"; + } + } + break; + case 'getWiki': + try + { + $nameValue = $jinput->get('name', NULL, 'WORD'); + if($nameValue && $user->id != 0) + { + $result = $this->getModel('ajax')->getWiki($nameValue); + } + else + { + $result = false; + } + if($callback) + { + echo $callback . "(".json_encode($result).");"; + } + elseif($returnRaw) + { + echo json_encode($result); + } + else + { + echo "(".json_encode($result).");"; + } + } + catch(Exception $e) + { + if($callback) + { + echo $callback."(".json_encode($e).");"; + } + elseif($returnRaw) + { + echo json_encode($e); + } + else + { + echo "(".json_encode($e).");"; + } + } + break; + case 'getVersion': + try + { + $versionValue = $jinput->get('version', NULL, 'INT'); + if($versionValue && $user->id != 0) + { + $result = $this->getModel('ajax')->getVersion($versionValue); + } + else + { + $result = false; + } + if($callback) + { + echo $callback . "(".json_encode($result).");"; + } + elseif($returnRaw) + { + echo json_encode($result); + } + else + { + echo "(".json_encode($result).");"; + } + } + catch(Exception $e) + { + if($callback) + { + echo $callback."(".json_encode($e).");"; + } + elseif($returnRaw) + { + echo json_encode($e); + } + else + { + echo "(".json_encode($e).");"; + } + } + break; + } + } + else + { + // return to a callback function + if($callback) + { + echo $callback."(".json_encode(false).");"; + } + elseif($returnRaw) + { + echo json_encode(false); + } + else + { + echo "(".json_encode(false).");"; + } + } + } +} diff --git a/admin/controllers/book.php b/admin/controllers/book.php new file mode 100644 index 0000000..5323de7 --- /dev/null +++ b/admin/controllers/book.php @@ -0,0 +1,330 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\FormController; +use Joomla\Utilities\ArrayHelper; + +/** + * Book Form Controller + */ +class GetbibleControllerBook extends FormController +{ + /** + * Current or most recently performed task. + * + * @var string + * @since 12.2 + * @note Replaces _task. + */ + protected $task; + + /** + * Class constructor. + * + * @param array $config A named array of configuration variables. + * + * @since 1.6 + */ + public function __construct($config = array()) + { + $this->view_list = 'Books'; // safeguard for setting the return view listing to the main view. + parent::__construct($config); + }###ADMIN_CUSTOM_BUTTONS_CONTROLLER### + + /** + * Method override to check if you can add a new record. + * + * @param array $data An array of input data. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowAdd($data = array()) + { + // Get user object. + $user = JFactory::getUser(); + // Access check. + $access = $user->authorise('book.access', 'com_getbible'); + if (!$access) + { + return false; + } + + // In the absense of better information, revert to the component permissions. + return $user->authorise('book.create', $this->option); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // get user object. + $user = JFactory::getUser(); + // get record id. + $recordId = (int) isset($data[$key]) ? $data[$key] : 0; + + + // Access check. + $access = ($user->authorise('book.access', 'com_getbible.book.' . (int) $recordId) && $user->authorise('book.access', 'com_getbible')); + if (!$access) + { + return false; + } + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('book.edit', 'com_getbible.book.' . (int) $recordId); + if (!$permission) + { + if ($user->authorise('book.edit.own', 'com_getbible.book.' . $recordId)) + { + // Now test the owner is the user. + $ownerId = (int) isset($data['created_by']) ? $data['created_by'] : 0; + if (empty($ownerId)) + { + // Need to do a lookup from the model. + $record = $this->getModel()->getItem($recordId); + + if (empty($record)) + { + return false; + } + $ownerId = $record->created_by; + } + + // If the owner matches 'me' then allow. + if ($ownerId == $user->id) + { + if ($user->authorise('book.edit.own', 'com_getbible')) + { + return true; + } + } + } + return false; + } + } + // Since there is no permission, revert to the component permissions. + return $user->authorise('book.edit', $this->option); + } + + /** + * Gets the URL arguments to append to an item redirect. + * + * @param integer $recordId The primary key id for the item. + * @param string $urlVar The name of the URL variable for the id. + * + * @return string The arguments to append to the redirect URL. + * + * @since 1.6 + */ + protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id') + { + // get the referral options (old method use return instead see parent) + $ref = $this->input->get('ref', 0, 'string'); + $refid = $this->input->get('refid', 0, 'int'); + + // get redirect info. + $append = parent::getRedirectToItemAppend($recordId, $urlVar); + + // set the referral options + if ($refid && $ref) + { + $append = '&ref=' . (string)$ref . '&refid='. (int)$refid . $append; + } + elseif ($ref) + { + $append = '&ref='. (string)$ref . $append; + } + + return $append; + } + + /** + * Method to run batch operations. + * + * @param object $model The model. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 2.5 + */ + public function batch($model = null) + { + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + // Set the model + $model = $this->getModel('Book', '', array()); + + // Preset the redirect + $this->setRedirect(JRoute::_('index.php?option=com_getbible&view=books' . $this->getRedirectToListAppend(), false)); + + return parent::batch($model); + } + + /** + * Method to cancel an edit. + * + * @param string $key The name of the primary key of the URL variable. + * + * @return boolean True if access level checks pass, false otherwise. + * + * @since 12.2 + */ + public function cancel($key = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + + $cancel = parent::cancel($key); + + if (!is_null($return) && JUri::isInternal(base64_decode($return))) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view='.(string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $cancel; + } + + /** + * Method to save a record. + * + * @param string $key The name of the primary key of the URL variable. + * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). + * + * @return boolean True if successful, false otherwise. + * + * @since 12.2 + */ + public function save($key = null, $urlVar = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + $canReturn = (!is_null($return) && JUri::isInternal(base64_decode($return))); + + if ($this->ref || $this->refid || $canReturn) + { + // to make sure the item is checkedin on redirect + $this->task = 'save'; + } + + $saved = parent::save($key, $urlVar); + + // This is not needed since parent save already does this + // Due to the ref and refid implementation we need to add this + if ($canReturn) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view=' . (string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $saved; + } + + /** + * Function that allows child controller access to model data + * after the data has been saved. + * + * @param JModel &$model The data model object. + * @param array $validData The validated data. + * + * @return void + * + * @since 11.1 + */ + protected function postSaveHook(JModelLegacy $model, $validData = array()) + { + return; + } + +} diff --git a/admin/controllers/books.php b/admin/controllers/books.php new file mode 100644 index 0000000..c1f4c16 --- /dev/null +++ b/admin/controllers/books.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\AdminController; +use Joomla\Utilities\ArrayHelper; + +/** + * Books Admin Controller + */ +class GetbibleControllerBooks extends AdminController +{ + /** + * The prefix to use with controller messages. + * + * @var string + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE_BOOKS'; + + /** + * Method to get a model object, loading it if required. + * + * @param string $name The model name. Optional. + * @param string $prefix The class prefix. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JModelLegacy The model. + * + * @since 1.6 + */ + public function getModel($name = 'Book', $prefix = 'GetbibleModel', $config = array('ignore_request' => true)) + { + return parent::getModel($name, $prefix, $config); + } +} diff --git a/admin/controllers/chapter.php b/admin/controllers/chapter.php new file mode 100644 index 0000000..ca14d59 --- /dev/null +++ b/admin/controllers/chapter.php @@ -0,0 +1,330 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\FormController; +use Joomla\Utilities\ArrayHelper; + +/** + * Chapter Form Controller + */ +class GetbibleControllerChapter extends FormController +{ + /** + * Current or most recently performed task. + * + * @var string + * @since 12.2 + * @note Replaces _task. + */ + protected $task; + + /** + * Class constructor. + * + * @param array $config A named array of configuration variables. + * + * @since 1.6 + */ + public function __construct($config = array()) + { + $this->view_list = 'Chapters'; // safeguard for setting the return view listing to the main view. + parent::__construct($config); + }###ADMIN_CUSTOM_BUTTONS_CONTROLLER### + + /** + * Method override to check if you can add a new record. + * + * @param array $data An array of input data. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowAdd($data = array()) + { + // Get user object. + $user = JFactory::getUser(); + // Access check. + $access = $user->authorise('chapter.access', 'com_getbible'); + if (!$access) + { + return false; + } + + // In the absense of better information, revert to the component permissions. + return $user->authorise('chapter.create', $this->option); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // get user object. + $user = JFactory::getUser(); + // get record id. + $recordId = (int) isset($data[$key]) ? $data[$key] : 0; + + + // Access check. + $access = ($user->authorise('chapter.access', 'com_getbible.chapter.' . (int) $recordId) && $user->authorise('chapter.access', 'com_getbible')); + if (!$access) + { + return false; + } + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('chapter.edit', 'com_getbible.chapter.' . (int) $recordId); + if (!$permission) + { + if ($user->authorise('chapter.edit.own', 'com_getbible.chapter.' . $recordId)) + { + // Now test the owner is the user. + $ownerId = (int) isset($data['created_by']) ? $data['created_by'] : 0; + if (empty($ownerId)) + { + // Need to do a lookup from the model. + $record = $this->getModel()->getItem($recordId); + + if (empty($record)) + { + return false; + } + $ownerId = $record->created_by; + } + + // If the owner matches 'me' then allow. + if ($ownerId == $user->id) + { + if ($user->authorise('chapter.edit.own', 'com_getbible')) + { + return true; + } + } + } + return false; + } + } + // Since there is no permission, revert to the component permissions. + return $user->authorise('chapter.edit', $this->option); + } + + /** + * Gets the URL arguments to append to an item redirect. + * + * @param integer $recordId The primary key id for the item. + * @param string $urlVar The name of the URL variable for the id. + * + * @return string The arguments to append to the redirect URL. + * + * @since 1.6 + */ + protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id') + { + // get the referral options (old method use return instead see parent) + $ref = $this->input->get('ref', 0, 'string'); + $refid = $this->input->get('refid', 0, 'int'); + + // get redirect info. + $append = parent::getRedirectToItemAppend($recordId, $urlVar); + + // set the referral options + if ($refid && $ref) + { + $append = '&ref=' . (string)$ref . '&refid='. (int)$refid . $append; + } + elseif ($ref) + { + $append = '&ref='. (string)$ref . $append; + } + + return $append; + } + + /** + * Method to run batch operations. + * + * @param object $model The model. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 2.5 + */ + public function batch($model = null) + { + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + // Set the model + $model = $this->getModel('Chapter', '', array()); + + // Preset the redirect + $this->setRedirect(JRoute::_('index.php?option=com_getbible&view=chapters' . $this->getRedirectToListAppend(), false)); + + return parent::batch($model); + } + + /** + * Method to cancel an edit. + * + * @param string $key The name of the primary key of the URL variable. + * + * @return boolean True if access level checks pass, false otherwise. + * + * @since 12.2 + */ + public function cancel($key = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + + $cancel = parent::cancel($key); + + if (!is_null($return) && JUri::isInternal(base64_decode($return))) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view='.(string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $cancel; + } + + /** + * Method to save a record. + * + * @param string $key The name of the primary key of the URL variable. + * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). + * + * @return boolean True if successful, false otherwise. + * + * @since 12.2 + */ + public function save($key = null, $urlVar = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + $canReturn = (!is_null($return) && JUri::isInternal(base64_decode($return))); + + if ($this->ref || $this->refid || $canReturn) + { + // to make sure the item is checkedin on redirect + $this->task = 'save'; + } + + $saved = parent::save($key, $urlVar); + + // This is not needed since parent save already does this + // Due to the ref and refid implementation we need to add this + if ($canReturn) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view=' . (string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $saved; + } + + /** + * Function that allows child controller access to model data + * after the data has been saved. + * + * @param JModel &$model The data model object. + * @param array $validData The validated data. + * + * @return void + * + * @since 11.1 + */ + protected function postSaveHook(JModelLegacy $model, $validData = array()) + { + return; + } + +} diff --git a/admin/controllers/chapters.php b/admin/controllers/chapters.php new file mode 100644 index 0000000..a157982 --- /dev/null +++ b/admin/controllers/chapters.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\AdminController; +use Joomla\Utilities\ArrayHelper; + +/** + * Chapters Admin Controller + */ +class GetbibleControllerChapters extends AdminController +{ + /** + * The prefix to use with controller messages. + * + * @var string + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE_CHAPTERS'; + + /** + * Method to get a model object, loading it if required. + * + * @param string $name The model name. Optional. + * @param string $prefix The class prefix. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JModelLegacy The model. + * + * @since 1.6 + */ + public function getModel($name = 'Chapter', $prefix = 'GetbibleModel', $config = array('ignore_request' => true)) + { + return parent::getModel($name, $prefix, $config); + } +} diff --git a/admin/controllers/getbible.php b/admin/controllers/getbible.php new file mode 100644 index 0000000..6a25675 --- /dev/null +++ b/admin/controllers/getbible.php @@ -0,0 +1,30 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\AdminController; +use Joomla\Utilities\ArrayHelper; + +/** + * Getbible Admin Controller + */ +class GetbibleControllerGetbible extends AdminController +{ + +} diff --git a/admin/controllers/index.html b/admin/controllers/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/controllers/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/controllers/linker.php b/admin/controllers/linker.php new file mode 100644 index 0000000..40dbe28 --- /dev/null +++ b/admin/controllers/linker.php @@ -0,0 +1,330 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\FormController; +use Joomla\Utilities\ArrayHelper; + +/** + * Linker Form Controller + */ +class GetbibleControllerLinker extends FormController +{ + /** + * Current or most recently performed task. + * + * @var string + * @since 12.2 + * @note Replaces _task. + */ + protected $task; + + /** + * Class constructor. + * + * @param array $config A named array of configuration variables. + * + * @since 1.6 + */ + public function __construct($config = array()) + { + $this->view_list = 'Linkers'; // safeguard for setting the return view listing to the main view. + parent::__construct($config); + } + + /** + * Method override to check if you can add a new record. + * + * @param array $data An array of input data. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowAdd($data = array()) + { + // Get user object. + $user = JFactory::getUser(); + // Access check. + $access = $user->authorise('linker.access', 'com_getbible'); + if (!$access) + { + return false; + } + + // In the absense of better information, revert to the component permissions. + return $user->authorise('linker.create', $this->option); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // get user object. + $user = JFactory::getUser(); + // get record id. + $recordId = (int) isset($data[$key]) ? $data[$key] : 0; + + + // Access check. + $access = ($user->authorise('linker.access', 'com_getbible.linker.' . (int) $recordId) && $user->authorise('linker.access', 'com_getbible')); + if (!$access) + { + return false; + } + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('linker.edit', 'com_getbible.linker.' . (int) $recordId); + if (!$permission) + { + if ($user->authorise('linker.edit.own', 'com_getbible.linker.' . $recordId)) + { + // Now test the owner is the user. + $ownerId = (int) isset($data['created_by']) ? $data['created_by'] : 0; + if (empty($ownerId)) + { + // Need to do a lookup from the model. + $record = $this->getModel()->getItem($recordId); + + if (empty($record)) + { + return false; + } + $ownerId = $record->created_by; + } + + // If the owner matches 'me' then allow. + if ($ownerId == $user->id) + { + if ($user->authorise('linker.edit.own', 'com_getbible')) + { + return true; + } + } + } + return false; + } + } + // Since there is no permission, revert to the component permissions. + return $user->authorise('linker.edit', $this->option); + } + + /** + * Gets the URL arguments to append to an item redirect. + * + * @param integer $recordId The primary key id for the item. + * @param string $urlVar The name of the URL variable for the id. + * + * @return string The arguments to append to the redirect URL. + * + * @since 1.6 + */ + protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id') + { + // get the referral options (old method use return instead see parent) + $ref = $this->input->get('ref', 0, 'string'); + $refid = $this->input->get('refid', 0, 'int'); + + // get redirect info. + $append = parent::getRedirectToItemAppend($recordId, $urlVar); + + // set the referral options + if ($refid && $ref) + { + $append = '&ref=' . (string)$ref . '&refid='. (int)$refid . $append; + } + elseif ($ref) + { + $append = '&ref='. (string)$ref . $append; + } + + return $append; + } + + /** + * Method to run batch operations. + * + * @param object $model The model. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 2.5 + */ + public function batch($model = null) + { + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + // Set the model + $model = $this->getModel('Linker', '', array()); + + // Preset the redirect + $this->setRedirect(JRoute::_('index.php?option=com_getbible&view=linkers' . $this->getRedirectToListAppend(), false)); + + return parent::batch($model); + } + + /** + * Method to cancel an edit. + * + * @param string $key The name of the primary key of the URL variable. + * + * @return boolean True if access level checks pass, false otherwise. + * + * @since 12.2 + */ + public function cancel($key = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + + $cancel = parent::cancel($key); + + if (!is_null($return) && JUri::isInternal(base64_decode($return))) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view='.(string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $cancel; + } + + /** + * Method to save a record. + * + * @param string $key The name of the primary key of the URL variable. + * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). + * + * @return boolean True if successful, false otherwise. + * + * @since 12.2 + */ + public function save($key = null, $urlVar = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + $canReturn = (!is_null($return) && JUri::isInternal(base64_decode($return))); + + if ($this->ref || $this->refid || $canReturn) + { + // to make sure the item is checkedin on redirect + $this->task = 'save'; + } + + $saved = parent::save($key, $urlVar); + + // This is not needed since parent save already does this + // Due to the ref and refid implementation we need to add this + if ($canReturn) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view=' . (string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $saved; + } + + /** + * Function that allows child controller access to model data + * after the data has been saved. + * + * @param JModel &$model The data model object. + * @param array $validData The validated data. + * + * @return void + * + * @since 11.1 + */ + protected function postSaveHook(JModelLegacy $model, $validData = array()) + { + return; + } + +} diff --git a/admin/controllers/linkers.php b/admin/controllers/linkers.php new file mode 100644 index 0000000..65da3fe --- /dev/null +++ b/admin/controllers/linkers.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\AdminController; +use Joomla\Utilities\ArrayHelper; + +/** + * Linkers Admin Controller + */ +class GetbibleControllerLinkers extends AdminController +{ + /** + * The prefix to use with controller messages. + * + * @var string + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE_LINKERS'; + + /** + * Method to get a model object, loading it if required. + * + * @param string $name The model name. Optional. + * @param string $prefix The class prefix. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JModelLegacy The model. + * + * @since 1.6 + */ + public function getModel($name = 'Linker', $prefix = 'GetbibleModel', $config = array('ignore_request' => true)) + { + return parent::getModel($name, $prefix, $config); + } +} diff --git a/admin/controllers/note.php b/admin/controllers/note.php new file mode 100644 index 0000000..d1ddfd9 --- /dev/null +++ b/admin/controllers/note.php @@ -0,0 +1,330 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\FormController; +use Joomla\Utilities\ArrayHelper; + +/** + * Note Form Controller + */ +class GetbibleControllerNote extends FormController +{ + /** + * Current or most recently performed task. + * + * @var string + * @since 12.2 + * @note Replaces _task. + */ + protected $task; + + /** + * Class constructor. + * + * @param array $config A named array of configuration variables. + * + * @since 1.6 + */ + public function __construct($config = array()) + { + $this->view_list = 'Notes'; // safeguard for setting the return view listing to the main view. + parent::__construct($config); + } + + /** + * Method override to check if you can add a new record. + * + * @param array $data An array of input data. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowAdd($data = array()) + { + // Get user object. + $user = JFactory::getUser(); + // Access check. + $access = $user->authorise('note.access', 'com_getbible'); + if (!$access) + { + return false; + } + + // In the absense of better information, revert to the component permissions. + return $user->authorise('note.create', $this->option); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // get user object. + $user = JFactory::getUser(); + // get record id. + $recordId = (int) isset($data[$key]) ? $data[$key] : 0; + + + // Access check. + $access = ($user->authorise('note.access', 'com_getbible.note.' . (int) $recordId) && $user->authorise('note.access', 'com_getbible')); + if (!$access) + { + return false; + } + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('note.edit', 'com_getbible.note.' . (int) $recordId); + if (!$permission) + { + if ($user->authorise('note.edit.own', 'com_getbible.note.' . $recordId)) + { + // Now test the owner is the user. + $ownerId = (int) isset($data['created_by']) ? $data['created_by'] : 0; + if (empty($ownerId)) + { + // Need to do a lookup from the model. + $record = $this->getModel()->getItem($recordId); + + if (empty($record)) + { + return false; + } + $ownerId = $record->created_by; + } + + // If the owner matches 'me' then allow. + if ($ownerId == $user->id) + { + if ($user->authorise('note.edit.own', 'com_getbible')) + { + return true; + } + } + } + return false; + } + } + // Since there is no permission, revert to the component permissions. + return $user->authorise('note.edit', $this->option); + } + + /** + * Gets the URL arguments to append to an item redirect. + * + * @param integer $recordId The primary key id for the item. + * @param string $urlVar The name of the URL variable for the id. + * + * @return string The arguments to append to the redirect URL. + * + * @since 1.6 + */ + protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id') + { + // get the referral options (old method use return instead see parent) + $ref = $this->input->get('ref', 0, 'string'); + $refid = $this->input->get('refid', 0, 'int'); + + // get redirect info. + $append = parent::getRedirectToItemAppend($recordId, $urlVar); + + // set the referral options + if ($refid && $ref) + { + $append = '&ref=' . (string)$ref . '&refid='. (int)$refid . $append; + } + elseif ($ref) + { + $append = '&ref='. (string)$ref . $append; + } + + return $append; + } + + /** + * Method to run batch operations. + * + * @param object $model The model. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 2.5 + */ + public function batch($model = null) + { + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + // Set the model + $model = $this->getModel('Note', '', array()); + + // Preset the redirect + $this->setRedirect(JRoute::_('index.php?option=com_getbible&view=notes' . $this->getRedirectToListAppend(), false)); + + return parent::batch($model); + } + + /** + * Method to cancel an edit. + * + * @param string $key The name of the primary key of the URL variable. + * + * @return boolean True if access level checks pass, false otherwise. + * + * @since 12.2 + */ + public function cancel($key = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + + $cancel = parent::cancel($key); + + if (!is_null($return) && JUri::isInternal(base64_decode($return))) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view='.(string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $cancel; + } + + /** + * Method to save a record. + * + * @param string $key The name of the primary key of the URL variable. + * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). + * + * @return boolean True if successful, false otherwise. + * + * @since 12.2 + */ + public function save($key = null, $urlVar = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + $canReturn = (!is_null($return) && JUri::isInternal(base64_decode($return))); + + if ($this->ref || $this->refid || $canReturn) + { + // to make sure the item is checkedin on redirect + $this->task = 'save'; + } + + $saved = parent::save($key, $urlVar); + + // This is not needed since parent save already does this + // Due to the ref and refid implementation we need to add this + if ($canReturn) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view=' . (string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $saved; + } + + /** + * Function that allows child controller access to model data + * after the data has been saved. + * + * @param JModel &$model The data model object. + * @param array $validData The validated data. + * + * @return void + * + * @since 11.1 + */ + protected function postSaveHook(JModelLegacy $model, $validData = array()) + { + return; + } + +} diff --git a/admin/controllers/notes.php b/admin/controllers/notes.php new file mode 100644 index 0000000..952ab27 --- /dev/null +++ b/admin/controllers/notes.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\AdminController; +use Joomla\Utilities\ArrayHelper; + +/** + * Notes Admin Controller + */ +class GetbibleControllerNotes extends AdminController +{ + /** + * The prefix to use with controller messages. + * + * @var string + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE_NOTES'; + + /** + * Method to get a model object, loading it if required. + * + * @param string $name The model name. Optional. + * @param string $prefix The class prefix. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JModelLegacy The model. + * + * @since 1.6 + */ + public function getModel($name = 'Note', $prefix = 'GetbibleModel', $config = array('ignore_request' => true)) + { + return parent::getModel($name, $prefix, $config); + } +} diff --git a/admin/controllers/open_ai_message.php b/admin/controllers/open_ai_message.php new file mode 100644 index 0000000..2f08b70 --- /dev/null +++ b/admin/controllers/open_ai_message.php @@ -0,0 +1,330 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\FormController; +use Joomla\Utilities\ArrayHelper; + +/** + * Open_ai_message Form Controller + */ +class GetbibleControllerOpen_ai_message extends FormController +{ + /** + * Current or most recently performed task. + * + * @var string + * @since 12.2 + * @note Replaces _task. + */ + protected $task; + + /** + * Class constructor. + * + * @param array $config A named array of configuration variables. + * + * @since 1.6 + */ + public function __construct($config = array()) + { + $this->view_list = 'Open_ai_messages'; // safeguard for setting the return view listing to the main view. + parent::__construct($config); + } + + /** + * Method override to check if you can add a new record. + * + * @param array $data An array of input data. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowAdd($data = array()) + { + // Get user object. + $user = JFactory::getUser(); + // Access check. + $access = $user->authorise('open_ai_message.access', 'com_getbible'); + if (!$access) + { + return false; + } + + // In the absense of better information, revert to the component permissions. + return $user->authorise('open_ai_message.create', $this->option); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // get user object. + $user = JFactory::getUser(); + // get record id. + $recordId = (int) isset($data[$key]) ? $data[$key] : 0; + + + // Access check. + $access = ($user->authorise('open_ai_message.access', 'com_getbible.open_ai_message.' . (int) $recordId) && $user->authorise('open_ai_message.access', 'com_getbible')); + if (!$access) + { + return false; + } + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('open_ai_message.edit', 'com_getbible.open_ai_message.' . (int) $recordId); + if (!$permission) + { + if ($user->authorise('open_ai_message.edit.own', 'com_getbible.open_ai_message.' . $recordId)) + { + // Now test the owner is the user. + $ownerId = (int) isset($data['created_by']) ? $data['created_by'] : 0; + if (empty($ownerId)) + { + // Need to do a lookup from the model. + $record = $this->getModel()->getItem($recordId); + + if (empty($record)) + { + return false; + } + $ownerId = $record->created_by; + } + + // If the owner matches 'me' then allow. + if ($ownerId == $user->id) + { + if ($user->authorise('open_ai_message.edit.own', 'com_getbible')) + { + return true; + } + } + } + return false; + } + } + // Since there is no permission, revert to the component permissions. + return $user->authorise('open_ai_message.edit', $this->option); + } + + /** + * Gets the URL arguments to append to an item redirect. + * + * @param integer $recordId The primary key id for the item. + * @param string $urlVar The name of the URL variable for the id. + * + * @return string The arguments to append to the redirect URL. + * + * @since 1.6 + */ + protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id') + { + // get the referral options (old method use return instead see parent) + $ref = $this->input->get('ref', 0, 'string'); + $refid = $this->input->get('refid', 0, 'int'); + + // get redirect info. + $append = parent::getRedirectToItemAppend($recordId, $urlVar); + + // set the referral options + if ($refid && $ref) + { + $append = '&ref=' . (string)$ref . '&refid='. (int)$refid . $append; + } + elseif ($ref) + { + $append = '&ref='. (string)$ref . $append; + } + + return $append; + } + + /** + * Method to run batch operations. + * + * @param object $model The model. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 2.5 + */ + public function batch($model = null) + { + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + // Set the model + $model = $this->getModel('Open_ai_message', '', array()); + + // Preset the redirect + $this->setRedirect(JRoute::_('index.php?option=com_getbible&view=open_ai_messages' . $this->getRedirectToListAppend(), false)); + + return parent::batch($model); + } + + /** + * Method to cancel an edit. + * + * @param string $key The name of the primary key of the URL variable. + * + * @return boolean True if access level checks pass, false otherwise. + * + * @since 12.2 + */ + public function cancel($key = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + + $cancel = parent::cancel($key); + + if (!is_null($return) && JUri::isInternal(base64_decode($return))) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view='.(string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $cancel; + } + + /** + * Method to save a record. + * + * @param string $key The name of the primary key of the URL variable. + * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). + * + * @return boolean True if successful, false otherwise. + * + * @since 12.2 + */ + public function save($key = null, $urlVar = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + $canReturn = (!is_null($return) && JUri::isInternal(base64_decode($return))); + + if ($this->ref || $this->refid || $canReturn) + { + // to make sure the item is checkedin on redirect + $this->task = 'save'; + } + + $saved = parent::save($key, $urlVar); + + // This is not needed since parent save already does this + // Due to the ref and refid implementation we need to add this + if ($canReturn) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view=' . (string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $saved; + } + + /** + * Function that allows child controller access to model data + * after the data has been saved. + * + * @param JModel &$model The data model object. + * @param array $validData The validated data. + * + * @return void + * + * @since 11.1 + */ + protected function postSaveHook(JModelLegacy $model, $validData = array()) + { + return; + } + +} diff --git a/admin/controllers/open_ai_messages.php b/admin/controllers/open_ai_messages.php new file mode 100644 index 0000000..d1a88c2 --- /dev/null +++ b/admin/controllers/open_ai_messages.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\AdminController; +use Joomla\Utilities\ArrayHelper; + +/** + * Open_ai_messages Admin Controller + */ +class GetbibleControllerOpen_ai_messages extends AdminController +{ + /** + * The prefix to use with controller messages. + * + * @var string + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE_OPEN_AI_MESSAGES'; + + /** + * Method to get a model object, loading it if required. + * + * @param string $name The model name. Optional. + * @param string $prefix The class prefix. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JModelLegacy The model. + * + * @since 1.6 + */ + public function getModel($name = 'Open_ai_message', $prefix = 'GetbibleModel', $config = array('ignore_request' => true)) + { + return parent::getModel($name, $prefix, $config); + } +} diff --git a/admin/controllers/open_ai_response.php b/admin/controllers/open_ai_response.php new file mode 100644 index 0000000..f075763 --- /dev/null +++ b/admin/controllers/open_ai_response.php @@ -0,0 +1,330 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\FormController; +use Joomla\Utilities\ArrayHelper; + +/** + * Open_ai_response Form Controller + */ +class GetbibleControllerOpen_ai_response extends FormController +{ + /** + * Current or most recently performed task. + * + * @var string + * @since 12.2 + * @note Replaces _task. + */ + protected $task; + + /** + * Class constructor. + * + * @param array $config A named array of configuration variables. + * + * @since 1.6 + */ + public function __construct($config = array()) + { + $this->view_list = 'Open_ai_responses'; // safeguard for setting the return view listing to the main view. + parent::__construct($config); + } + + /** + * Method override to check if you can add a new record. + * + * @param array $data An array of input data. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowAdd($data = array()) + { + // Get user object. + $user = JFactory::getUser(); + // Access check. + $access = $user->authorise('open_ai_response.access', 'com_getbible'); + if (!$access) + { + return false; + } + + // In the absense of better information, revert to the component permissions. + return $user->authorise('open_ai_response.create', $this->option); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // get user object. + $user = JFactory::getUser(); + // get record id. + $recordId = (int) isset($data[$key]) ? $data[$key] : 0; + + + // Access check. + $access = ($user->authorise('open_ai_response.access', 'com_getbible.open_ai_response.' . (int) $recordId) && $user->authorise('open_ai_response.access', 'com_getbible')); + if (!$access) + { + return false; + } + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('open_ai_response.edit', 'com_getbible.open_ai_response.' . (int) $recordId); + if (!$permission) + { + if ($user->authorise('open_ai_response.edit.own', 'com_getbible.open_ai_response.' . $recordId)) + { + // Now test the owner is the user. + $ownerId = (int) isset($data['created_by']) ? $data['created_by'] : 0; + if (empty($ownerId)) + { + // Need to do a lookup from the model. + $record = $this->getModel()->getItem($recordId); + + if (empty($record)) + { + return false; + } + $ownerId = $record->created_by; + } + + // If the owner matches 'me' then allow. + if ($ownerId == $user->id) + { + if ($user->authorise('open_ai_response.edit.own', 'com_getbible')) + { + return true; + } + } + } + return false; + } + } + // Since there is no permission, revert to the component permissions. + return $user->authorise('open_ai_response.edit', $this->option); + } + + /** + * Gets the URL arguments to append to an item redirect. + * + * @param integer $recordId The primary key id for the item. + * @param string $urlVar The name of the URL variable for the id. + * + * @return string The arguments to append to the redirect URL. + * + * @since 1.6 + */ + protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id') + { + // get the referral options (old method use return instead see parent) + $ref = $this->input->get('ref', 0, 'string'); + $refid = $this->input->get('refid', 0, 'int'); + + // get redirect info. + $append = parent::getRedirectToItemAppend($recordId, $urlVar); + + // set the referral options + if ($refid && $ref) + { + $append = '&ref=' . (string)$ref . '&refid='. (int)$refid . $append; + } + elseif ($ref) + { + $append = '&ref='. (string)$ref . $append; + } + + return $append; + } + + /** + * Method to run batch operations. + * + * @param object $model The model. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 2.5 + */ + public function batch($model = null) + { + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + // Set the model + $model = $this->getModel('Open_ai_response', '', array()); + + // Preset the redirect + $this->setRedirect(JRoute::_('index.php?option=com_getbible&view=open_ai_responses' . $this->getRedirectToListAppend(), false)); + + return parent::batch($model); + } + + /** + * Method to cancel an edit. + * + * @param string $key The name of the primary key of the URL variable. + * + * @return boolean True if access level checks pass, false otherwise. + * + * @since 12.2 + */ + public function cancel($key = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + + $cancel = parent::cancel($key); + + if (!is_null($return) && JUri::isInternal(base64_decode($return))) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view='.(string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $cancel; + } + + /** + * Method to save a record. + * + * @param string $key The name of the primary key of the URL variable. + * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). + * + * @return boolean True if successful, false otherwise. + * + * @since 12.2 + */ + public function save($key = null, $urlVar = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + $canReturn = (!is_null($return) && JUri::isInternal(base64_decode($return))); + + if ($this->ref || $this->refid || $canReturn) + { + // to make sure the item is checkedin on redirect + $this->task = 'save'; + } + + $saved = parent::save($key, $urlVar); + + // This is not needed since parent save already does this + // Due to the ref and refid implementation we need to add this + if ($canReturn) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view=' . (string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $saved; + } + + /** + * Function that allows child controller access to model data + * after the data has been saved. + * + * @param JModel &$model The data model object. + * @param array $validData The validated data. + * + * @return void + * + * @since 11.1 + */ + protected function postSaveHook(JModelLegacy $model, $validData = array()) + { + return; + } + +} diff --git a/admin/controllers/open_ai_responses.php b/admin/controllers/open_ai_responses.php new file mode 100644 index 0000000..f7856fd --- /dev/null +++ b/admin/controllers/open_ai_responses.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\AdminController; +use Joomla\Utilities\ArrayHelper; + +/** + * Open_ai_responses Admin Controller + */ +class GetbibleControllerOpen_ai_responses extends AdminController +{ + /** + * The prefix to use with controller messages. + * + * @var string + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE_OPEN_AI_RESPONSES'; + + /** + * Method to get a model object, loading it if required. + * + * @param string $name The model name. Optional. + * @param string $prefix The class prefix. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JModelLegacy The model. + * + * @since 1.6 + */ + public function getModel($name = 'Open_ai_response', $prefix = 'GetbibleModel', $config = array('ignore_request' => true)) + { + return parent::getModel($name, $prefix, $config); + } +} diff --git a/admin/controllers/password.php b/admin/controllers/password.php new file mode 100644 index 0000000..4b1d2d0 --- /dev/null +++ b/admin/controllers/password.php @@ -0,0 +1,330 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\FormController; +use Joomla\Utilities\ArrayHelper; + +/** + * Password Form Controller + */ +class GetbibleControllerPassword extends FormController +{ + /** + * Current or most recently performed task. + * + * @var string + * @since 12.2 + * @note Replaces _task. + */ + protected $task; + + /** + * Class constructor. + * + * @param array $config A named array of configuration variables. + * + * @since 1.6 + */ + public function __construct($config = array()) + { + $this->view_list = 'Passwords'; // safeguard for setting the return view listing to the main view. + parent::__construct($config); + } + + /** + * Method override to check if you can add a new record. + * + * @param array $data An array of input data. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowAdd($data = array()) + { + // Get user object. + $user = JFactory::getUser(); + // Access check. + $access = $user->authorise('password.access', 'com_getbible'); + if (!$access) + { + return false; + } + + // In the absense of better information, revert to the component permissions. + return $user->authorise('password.create', $this->option); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // get user object. + $user = JFactory::getUser(); + // get record id. + $recordId = (int) isset($data[$key]) ? $data[$key] : 0; + + + // Access check. + $access = ($user->authorise('password.access', 'com_getbible.password.' . (int) $recordId) && $user->authorise('password.access', 'com_getbible')); + if (!$access) + { + return false; + } + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('password.edit', 'com_getbible.password.' . (int) $recordId); + if (!$permission) + { + if ($user->authorise('password.edit.own', 'com_getbible.password.' . $recordId)) + { + // Now test the owner is the user. + $ownerId = (int) isset($data['created_by']) ? $data['created_by'] : 0; + if (empty($ownerId)) + { + // Need to do a lookup from the model. + $record = $this->getModel()->getItem($recordId); + + if (empty($record)) + { + return false; + } + $ownerId = $record->created_by; + } + + // If the owner matches 'me' then allow. + if ($ownerId == $user->id) + { + if ($user->authorise('password.edit.own', 'com_getbible')) + { + return true; + } + } + } + return false; + } + } + // Since there is no permission, revert to the component permissions. + return $user->authorise('password.edit', $this->option); + } + + /** + * Gets the URL arguments to append to an item redirect. + * + * @param integer $recordId The primary key id for the item. + * @param string $urlVar The name of the URL variable for the id. + * + * @return string The arguments to append to the redirect URL. + * + * @since 1.6 + */ + protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id') + { + // get the referral options (old method use return instead see parent) + $ref = $this->input->get('ref', 0, 'string'); + $refid = $this->input->get('refid', 0, 'int'); + + // get redirect info. + $append = parent::getRedirectToItemAppend($recordId, $urlVar); + + // set the referral options + if ($refid && $ref) + { + $append = '&ref=' . (string)$ref . '&refid='. (int)$refid . $append; + } + elseif ($ref) + { + $append = '&ref='. (string)$ref . $append; + } + + return $append; + } + + /** + * Method to run batch operations. + * + * @param object $model The model. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 2.5 + */ + public function batch($model = null) + { + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + // Set the model + $model = $this->getModel('Password', '', array()); + + // Preset the redirect + $this->setRedirect(JRoute::_('index.php?option=com_getbible&view=passwords' . $this->getRedirectToListAppend(), false)); + + return parent::batch($model); + } + + /** + * Method to cancel an edit. + * + * @param string $key The name of the primary key of the URL variable. + * + * @return boolean True if access level checks pass, false otherwise. + * + * @since 12.2 + */ + public function cancel($key = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + + $cancel = parent::cancel($key); + + if (!is_null($return) && JUri::isInternal(base64_decode($return))) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view='.(string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $cancel; + } + + /** + * Method to save a record. + * + * @param string $key The name of the primary key of the URL variable. + * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). + * + * @return boolean True if successful, false otherwise. + * + * @since 12.2 + */ + public function save($key = null, $urlVar = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + $canReturn = (!is_null($return) && JUri::isInternal(base64_decode($return))); + + if ($this->ref || $this->refid || $canReturn) + { + // to make sure the item is checkedin on redirect + $this->task = 'save'; + } + + $saved = parent::save($key, $urlVar); + + // This is not needed since parent save already does this + // Due to the ref and refid implementation we need to add this + if ($canReturn) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view=' . (string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $saved; + } + + /** + * Function that allows child controller access to model data + * after the data has been saved. + * + * @param JModel &$model The data model object. + * @param array $validData The validated data. + * + * @return void + * + * @since 11.1 + */ + protected function postSaveHook(JModelLegacy $model, $validData = array()) + { + return; + } + +} diff --git a/admin/controllers/passwords.php b/admin/controllers/passwords.php new file mode 100644 index 0000000..4a008ef --- /dev/null +++ b/admin/controllers/passwords.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\AdminController; +use Joomla\Utilities\ArrayHelper; + +/** + * Passwords Admin Controller + */ +class GetbibleControllerPasswords extends AdminController +{ + /** + * The prefix to use with controller messages. + * + * @var string + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE_PASSWORDS'; + + /** + * Method to get a model object, loading it if required. + * + * @param string $name The model name. Optional. + * @param string $prefix The class prefix. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JModelLegacy The model. + * + * @since 1.6 + */ + public function getModel($name = 'Password', $prefix = 'GetbibleModel', $config = array('ignore_request' => true)) + { + return parent::getModel($name, $prefix, $config); + } +} diff --git a/admin/controllers/prompt.php b/admin/controllers/prompt.php new file mode 100644 index 0000000..cb6d4c6 --- /dev/null +++ b/admin/controllers/prompt.php @@ -0,0 +1,330 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\FormController; +use Joomla\Utilities\ArrayHelper; + +/** + * Prompt Form Controller + */ +class GetbibleControllerPrompt extends FormController +{ + /** + * Current or most recently performed task. + * + * @var string + * @since 12.2 + * @note Replaces _task. + */ + protected $task; + + /** + * Class constructor. + * + * @param array $config A named array of configuration variables. + * + * @since 1.6 + */ + public function __construct($config = array()) + { + $this->view_list = 'Prompts'; // safeguard for setting the return view listing to the main view. + parent::__construct($config); + } + + /** + * Method override to check if you can add a new record. + * + * @param array $data An array of input data. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowAdd($data = array()) + { + // Get user object. + $user = JFactory::getUser(); + // Access check. + $access = $user->authorise('prompt.access', 'com_getbible'); + if (!$access) + { + return false; + } + + // In the absense of better information, revert to the component permissions. + return $user->authorise('prompt.create', $this->option); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // get user object. + $user = JFactory::getUser(); + // get record id. + $recordId = (int) isset($data[$key]) ? $data[$key] : 0; + + + // Access check. + $access = ($user->authorise('prompt.access', 'com_getbible.prompt.' . (int) $recordId) && $user->authorise('prompt.access', 'com_getbible')); + if (!$access) + { + return false; + } + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('prompt.edit', 'com_getbible.prompt.' . (int) $recordId); + if (!$permission) + { + if ($user->authorise('prompt.edit.own', 'com_getbible.prompt.' . $recordId)) + { + // Now test the owner is the user. + $ownerId = (int) isset($data['created_by']) ? $data['created_by'] : 0; + if (empty($ownerId)) + { + // Need to do a lookup from the model. + $record = $this->getModel()->getItem($recordId); + + if (empty($record)) + { + return false; + } + $ownerId = $record->created_by; + } + + // If the owner matches 'me' then allow. + if ($ownerId == $user->id) + { + if ($user->authorise('prompt.edit.own', 'com_getbible')) + { + return true; + } + } + } + return false; + } + } + // Since there is no permission, revert to the component permissions. + return $user->authorise('prompt.edit', $this->option); + } + + /** + * Gets the URL arguments to append to an item redirect. + * + * @param integer $recordId The primary key id for the item. + * @param string $urlVar The name of the URL variable for the id. + * + * @return string The arguments to append to the redirect URL. + * + * @since 1.6 + */ + protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id') + { + // get the referral options (old method use return instead see parent) + $ref = $this->input->get('ref', 0, 'string'); + $refid = $this->input->get('refid', 0, 'int'); + + // get redirect info. + $append = parent::getRedirectToItemAppend($recordId, $urlVar); + + // set the referral options + if ($refid && $ref) + { + $append = '&ref=' . (string)$ref . '&refid='. (int)$refid . $append; + } + elseif ($ref) + { + $append = '&ref='. (string)$ref . $append; + } + + return $append; + } + + /** + * Method to run batch operations. + * + * @param object $model The model. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 2.5 + */ + public function batch($model = null) + { + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + // Set the model + $model = $this->getModel('Prompt', '', array()); + + // Preset the redirect + $this->setRedirect(JRoute::_('index.php?option=com_getbible&view=prompts' . $this->getRedirectToListAppend(), false)); + + return parent::batch($model); + } + + /** + * Method to cancel an edit. + * + * @param string $key The name of the primary key of the URL variable. + * + * @return boolean True if access level checks pass, false otherwise. + * + * @since 12.2 + */ + public function cancel($key = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + + $cancel = parent::cancel($key); + + if (!is_null($return) && JUri::isInternal(base64_decode($return))) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view='.(string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $cancel; + } + + /** + * Method to save a record. + * + * @param string $key The name of the primary key of the URL variable. + * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). + * + * @return boolean True if successful, false otherwise. + * + * @since 12.2 + */ + public function save($key = null, $urlVar = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + $canReturn = (!is_null($return) && JUri::isInternal(base64_decode($return))); + + if ($this->ref || $this->refid || $canReturn) + { + // to make sure the item is checkedin on redirect + $this->task = 'save'; + } + + $saved = parent::save($key, $urlVar); + + // This is not needed since parent save already does this + // Due to the ref and refid implementation we need to add this + if ($canReturn) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view=' . (string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $saved; + } + + /** + * Function that allows child controller access to model data + * after the data has been saved. + * + * @param JModel &$model The data model object. + * @param array $validData The validated data. + * + * @return void + * + * @since 11.1 + */ + protected function postSaveHook(JModelLegacy $model, $validData = array()) + { + return; + } + +} diff --git a/admin/controllers/prompts.php b/admin/controllers/prompts.php new file mode 100644 index 0000000..d144152 --- /dev/null +++ b/admin/controllers/prompts.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\AdminController; +use Joomla\Utilities\ArrayHelper; + +/** + * Prompts Admin Controller + */ +class GetbibleControllerPrompts extends AdminController +{ + /** + * The prefix to use with controller messages. + * + * @var string + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE_PROMPTS'; + + /** + * Method to get a model object, loading it if required. + * + * @param string $name The model name. Optional. + * @param string $prefix The class prefix. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JModelLegacy The model. + * + * @since 1.6 + */ + public function getModel($name = 'Prompt', $prefix = 'GetbibleModel', $config = array('ignore_request' => true)) + { + return parent::getModel($name, $prefix, $config); + } +} diff --git a/admin/controllers/tag.php b/admin/controllers/tag.php new file mode 100644 index 0000000..21c13fa --- /dev/null +++ b/admin/controllers/tag.php @@ -0,0 +1,330 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\FormController; +use Joomla\Utilities\ArrayHelper; + +/** + * Tag Form Controller + */ +class GetbibleControllerTag extends FormController +{ + /** + * Current or most recently performed task. + * + * @var string + * @since 12.2 + * @note Replaces _task. + */ + protected $task; + + /** + * Class constructor. + * + * @param array $config A named array of configuration variables. + * + * @since 1.6 + */ + public function __construct($config = array()) + { + $this->view_list = 'Tags'; // safeguard for setting the return view listing to the main view. + parent::__construct($config); + } + + /** + * Method override to check if you can add a new record. + * + * @param array $data An array of input data. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowAdd($data = array()) + { + // Get user object. + $user = JFactory::getUser(); + // Access check. + $access = $user->authorise('tag.access', 'com_getbible'); + if (!$access) + { + return false; + } + + // In the absense of better information, revert to the component permissions. + return $user->authorise('tag.create', $this->option); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // get user object. + $user = JFactory::getUser(); + // get record id. + $recordId = (int) isset($data[$key]) ? $data[$key] : 0; + + + // Access check. + $access = ($user->authorise('tag.access', 'com_getbible.tag.' . (int) $recordId) && $user->authorise('tag.access', 'com_getbible')); + if (!$access) + { + return false; + } + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('tag.edit', 'com_getbible.tag.' . (int) $recordId); + if (!$permission) + { + if ($user->authorise('tag.edit.own', 'com_getbible.tag.' . $recordId)) + { + // Now test the owner is the user. + $ownerId = (int) isset($data['created_by']) ? $data['created_by'] : 0; + if (empty($ownerId)) + { + // Need to do a lookup from the model. + $record = $this->getModel()->getItem($recordId); + + if (empty($record)) + { + return false; + } + $ownerId = $record->created_by; + } + + // If the owner matches 'me' then allow. + if ($ownerId == $user->id) + { + if ($user->authorise('tag.edit.own', 'com_getbible')) + { + return true; + } + } + } + return false; + } + } + // Since there is no permission, revert to the component permissions. + return $user->authorise('tag.edit', $this->option); + } + + /** + * Gets the URL arguments to append to an item redirect. + * + * @param integer $recordId The primary key id for the item. + * @param string $urlVar The name of the URL variable for the id. + * + * @return string The arguments to append to the redirect URL. + * + * @since 1.6 + */ + protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id') + { + // get the referral options (old method use return instead see parent) + $ref = $this->input->get('ref', 0, 'string'); + $refid = $this->input->get('refid', 0, 'int'); + + // get redirect info. + $append = parent::getRedirectToItemAppend($recordId, $urlVar); + + // set the referral options + if ($refid && $ref) + { + $append = '&ref=' . (string)$ref . '&refid='. (int)$refid . $append; + } + elseif ($ref) + { + $append = '&ref='. (string)$ref . $append; + } + + return $append; + } + + /** + * Method to run batch operations. + * + * @param object $model The model. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 2.5 + */ + public function batch($model = null) + { + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + // Set the model + $model = $this->getModel('Tag', '', array()); + + // Preset the redirect + $this->setRedirect(JRoute::_('index.php?option=com_getbible&view=tags' . $this->getRedirectToListAppend(), false)); + + return parent::batch($model); + } + + /** + * Method to cancel an edit. + * + * @param string $key The name of the primary key of the URL variable. + * + * @return boolean True if access level checks pass, false otherwise. + * + * @since 12.2 + */ + public function cancel($key = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + + $cancel = parent::cancel($key); + + if (!is_null($return) && JUri::isInternal(base64_decode($return))) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view='.(string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $cancel; + } + + /** + * Method to save a record. + * + * @param string $key The name of the primary key of the URL variable. + * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). + * + * @return boolean True if successful, false otherwise. + * + * @since 12.2 + */ + public function save($key = null, $urlVar = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + $canReturn = (!is_null($return) && JUri::isInternal(base64_decode($return))); + + if ($this->ref || $this->refid || $canReturn) + { + // to make sure the item is checkedin on redirect + $this->task = 'save'; + } + + $saved = parent::save($key, $urlVar); + + // This is not needed since parent save already does this + // Due to the ref and refid implementation we need to add this + if ($canReturn) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view=' . (string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $saved; + } + + /** + * Function that allows child controller access to model data + * after the data has been saved. + * + * @param JModel &$model The data model object. + * @param array $validData The validated data. + * + * @return void + * + * @since 11.1 + */ + protected function postSaveHook(JModelLegacy $model, $validData = array()) + { + return; + } + +} diff --git a/admin/controllers/tagged_verse.php b/admin/controllers/tagged_verse.php new file mode 100644 index 0000000..2be0bca --- /dev/null +++ b/admin/controllers/tagged_verse.php @@ -0,0 +1,330 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\FormController; +use Joomla\Utilities\ArrayHelper; + +/** + * Tagged_verse Form Controller + */ +class GetbibleControllerTagged_verse extends FormController +{ + /** + * Current or most recently performed task. + * + * @var string + * @since 12.2 + * @note Replaces _task. + */ + protected $task; + + /** + * Class constructor. + * + * @param array $config A named array of configuration variables. + * + * @since 1.6 + */ + public function __construct($config = array()) + { + $this->view_list = 'Tagged_verses'; // safeguard for setting the return view listing to the main view. + parent::__construct($config); + } + + /** + * Method override to check if you can add a new record. + * + * @param array $data An array of input data. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowAdd($data = array()) + { + // Get user object. + $user = JFactory::getUser(); + // Access check. + $access = $user->authorise('tagged_verse.access', 'com_getbible'); + if (!$access) + { + return false; + } + + // In the absense of better information, revert to the component permissions. + return $user->authorise('tagged_verse.create', $this->option); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // get user object. + $user = JFactory::getUser(); + // get record id. + $recordId = (int) isset($data[$key]) ? $data[$key] : 0; + + + // Access check. + $access = ($user->authorise('tagged_verse.access', 'com_getbible.tagged_verse.' . (int) $recordId) && $user->authorise('tagged_verse.access', 'com_getbible')); + if (!$access) + { + return false; + } + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('tagged_verse.edit', 'com_getbible.tagged_verse.' . (int) $recordId); + if (!$permission) + { + if ($user->authorise('tagged_verse.edit.own', 'com_getbible.tagged_verse.' . $recordId)) + { + // Now test the owner is the user. + $ownerId = (int) isset($data['created_by']) ? $data['created_by'] : 0; + if (empty($ownerId)) + { + // Need to do a lookup from the model. + $record = $this->getModel()->getItem($recordId); + + if (empty($record)) + { + return false; + } + $ownerId = $record->created_by; + } + + // If the owner matches 'me' then allow. + if ($ownerId == $user->id) + { + if ($user->authorise('tagged_verse.edit.own', 'com_getbible')) + { + return true; + } + } + } + return false; + } + } + // Since there is no permission, revert to the component permissions. + return $user->authorise('tagged_verse.edit', $this->option); + } + + /** + * Gets the URL arguments to append to an item redirect. + * + * @param integer $recordId The primary key id for the item. + * @param string $urlVar The name of the URL variable for the id. + * + * @return string The arguments to append to the redirect URL. + * + * @since 1.6 + */ + protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id') + { + // get the referral options (old method use return instead see parent) + $ref = $this->input->get('ref', 0, 'string'); + $refid = $this->input->get('refid', 0, 'int'); + + // get redirect info. + $append = parent::getRedirectToItemAppend($recordId, $urlVar); + + // set the referral options + if ($refid && $ref) + { + $append = '&ref=' . (string)$ref . '&refid='. (int)$refid . $append; + } + elseif ($ref) + { + $append = '&ref='. (string)$ref . $append; + } + + return $append; + } + + /** + * Method to run batch operations. + * + * @param object $model The model. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 2.5 + */ + public function batch($model = null) + { + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + // Set the model + $model = $this->getModel('Tagged_verse', '', array()); + + // Preset the redirect + $this->setRedirect(JRoute::_('index.php?option=com_getbible&view=tagged_verses' . $this->getRedirectToListAppend(), false)); + + return parent::batch($model); + } + + /** + * Method to cancel an edit. + * + * @param string $key The name of the primary key of the URL variable. + * + * @return boolean True if access level checks pass, false otherwise. + * + * @since 12.2 + */ + public function cancel($key = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + + $cancel = parent::cancel($key); + + if (!is_null($return) && JUri::isInternal(base64_decode($return))) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view='.(string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $cancel; + } + + /** + * Method to save a record. + * + * @param string $key The name of the primary key of the URL variable. + * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). + * + * @return boolean True if successful, false otherwise. + * + * @since 12.2 + */ + public function save($key = null, $urlVar = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + $canReturn = (!is_null($return) && JUri::isInternal(base64_decode($return))); + + if ($this->ref || $this->refid || $canReturn) + { + // to make sure the item is checkedin on redirect + $this->task = 'save'; + } + + $saved = parent::save($key, $urlVar); + + // This is not needed since parent save already does this + // Due to the ref and refid implementation we need to add this + if ($canReturn) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view=' . (string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $saved; + } + + /** + * Function that allows child controller access to model data + * after the data has been saved. + * + * @param JModel &$model The data model object. + * @param array $validData The validated data. + * + * @return void + * + * @since 11.1 + */ + protected function postSaveHook(JModelLegacy $model, $validData = array()) + { + return; + } + +} diff --git a/admin/controllers/tagged_verses.php b/admin/controllers/tagged_verses.php new file mode 100644 index 0000000..3ef684f --- /dev/null +++ b/admin/controllers/tagged_verses.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\AdminController; +use Joomla\Utilities\ArrayHelper; + +/** + * Tagged_verses Admin Controller + */ +class GetbibleControllerTagged_verses extends AdminController +{ + /** + * The prefix to use with controller messages. + * + * @var string + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE_TAGGED_VERSES'; + + /** + * Method to get a model object, loading it if required. + * + * @param string $name The model name. Optional. + * @param string $prefix The class prefix. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JModelLegacy The model. + * + * @since 1.6 + */ + public function getModel($name = 'Tagged_verse', $prefix = 'GetbibleModel', $config = array('ignore_request' => true)) + { + return parent::getModel($name, $prefix, $config); + } +} diff --git a/admin/controllers/tags.php b/admin/controllers/tags.php new file mode 100644 index 0000000..360a32e --- /dev/null +++ b/admin/controllers/tags.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\AdminController; +use Joomla\Utilities\ArrayHelper; + +/** + * Tags Admin Controller + */ +class GetbibleControllerTags extends AdminController +{ + /** + * The prefix to use with controller messages. + * + * @var string + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE_TAGS'; + + /** + * Method to get a model object, loading it if required. + * + * @param string $name The model name. Optional. + * @param string $prefix The class prefix. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JModelLegacy The model. + * + * @since 1.6 + */ + public function getModel($name = 'Tag', $prefix = 'GetbibleModel', $config = array('ignore_request' => true)) + { + return parent::getModel($name, $prefix, $config); + } +} diff --git a/admin/controllers/translation.php b/admin/controllers/translation.php new file mode 100644 index 0000000..ec1474e --- /dev/null +++ b/admin/controllers/translation.php @@ -0,0 +1,330 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\FormController; +use Joomla\Utilities\ArrayHelper; + +/** + * Translation Form Controller + */ +class GetbibleControllerTranslation extends FormController +{ + /** + * Current or most recently performed task. + * + * @var string + * @since 12.2 + * @note Replaces _task. + */ + protected $task; + + /** + * Class constructor. + * + * @param array $config A named array of configuration variables. + * + * @since 1.6 + */ + public function __construct($config = array()) + { + $this->view_list = 'Translations'; // safeguard for setting the return view listing to the main view. + parent::__construct($config); + }###ADMIN_CUSTOM_BUTTONS_CONTROLLER### + + /** + * Method override to check if you can add a new record. + * + * @param array $data An array of input data. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowAdd($data = array()) + { + // Get user object. + $user = JFactory::getUser(); + // Access check. + $access = $user->authorise('translation.access', 'com_getbible'); + if (!$access) + { + return false; + } + + // In the absense of better information, revert to the component permissions. + return $user->authorise('translation.create', $this->option); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // get user object. + $user = JFactory::getUser(); + // get record id. + $recordId = (int) isset($data[$key]) ? $data[$key] : 0; + + + // Access check. + $access = ($user->authorise('translation.access', 'com_getbible.translation.' . (int) $recordId) && $user->authorise('translation.access', 'com_getbible')); + if (!$access) + { + return false; + } + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('translation.edit', 'com_getbible.translation.' . (int) $recordId); + if (!$permission) + { + if ($user->authorise('translation.edit.own', 'com_getbible.translation.' . $recordId)) + { + // Now test the owner is the user. + $ownerId = (int) isset($data['created_by']) ? $data['created_by'] : 0; + if (empty($ownerId)) + { + // Need to do a lookup from the model. + $record = $this->getModel()->getItem($recordId); + + if (empty($record)) + { + return false; + } + $ownerId = $record->created_by; + } + + // If the owner matches 'me' then allow. + if ($ownerId == $user->id) + { + if ($user->authorise('translation.edit.own', 'com_getbible')) + { + return true; + } + } + } + return false; + } + } + // Since there is no permission, revert to the component permissions. + return $user->authorise('translation.edit', $this->option); + } + + /** + * Gets the URL arguments to append to an item redirect. + * + * @param integer $recordId The primary key id for the item. + * @param string $urlVar The name of the URL variable for the id. + * + * @return string The arguments to append to the redirect URL. + * + * @since 1.6 + */ + protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id') + { + // get the referral options (old method use return instead see parent) + $ref = $this->input->get('ref', 0, 'string'); + $refid = $this->input->get('refid', 0, 'int'); + + // get redirect info. + $append = parent::getRedirectToItemAppend($recordId, $urlVar); + + // set the referral options + if ($refid && $ref) + { + $append = '&ref=' . (string)$ref . '&refid='. (int)$refid . $append; + } + elseif ($ref) + { + $append = '&ref='. (string)$ref . $append; + } + + return $append; + } + + /** + * Method to run batch operations. + * + * @param object $model The model. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 2.5 + */ + public function batch($model = null) + { + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + // Set the model + $model = $this->getModel('Translation', '', array()); + + // Preset the redirect + $this->setRedirect(JRoute::_('index.php?option=com_getbible&view=translations' . $this->getRedirectToListAppend(), false)); + + return parent::batch($model); + } + + /** + * Method to cancel an edit. + * + * @param string $key The name of the primary key of the URL variable. + * + * @return boolean True if access level checks pass, false otherwise. + * + * @since 12.2 + */ + public function cancel($key = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + + $cancel = parent::cancel($key); + + if (!is_null($return) && JUri::isInternal(base64_decode($return))) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view='.(string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $cancel; + } + + /** + * Method to save a record. + * + * @param string $key The name of the primary key of the URL variable. + * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). + * + * @return boolean True if successful, false otherwise. + * + * @since 12.2 + */ + public function save($key = null, $urlVar = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + $canReturn = (!is_null($return) && JUri::isInternal(base64_decode($return))); + + if ($this->ref || $this->refid || $canReturn) + { + // to make sure the item is checkedin on redirect + $this->task = 'save'; + } + + $saved = parent::save($key, $urlVar); + + // This is not needed since parent save already does this + // Due to the ref and refid implementation we need to add this + if ($canReturn) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view=' . (string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $saved; + } + + /** + * Function that allows child controller access to model data + * after the data has been saved. + * + * @param JModel &$model The data model object. + * @param array $validData The validated data. + * + * @return void + * + * @since 11.1 + */ + protected function postSaveHook(JModelLegacy $model, $validData = array()) + { + return; + } + +} diff --git a/admin/controllers/translations.php b/admin/controllers/translations.php new file mode 100644 index 0000000..5291825 --- /dev/null +++ b/admin/controllers/translations.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\AdminController; +use Joomla\Utilities\ArrayHelper; + +/** + * Translations Admin Controller + */ +class GetbibleControllerTranslations extends AdminController +{ + /** + * The prefix to use with controller messages. + * + * @var string + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE_TRANSLATIONS'; + + /** + * Method to get a model object, loading it if required. + * + * @param string $name The model name. Optional. + * @param string $prefix The class prefix. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JModelLegacy The model. + * + * @since 1.6 + */ + public function getModel($name = 'Translation', $prefix = 'GetbibleModel', $config = array('ignore_request' => true)) + { + return parent::getModel($name, $prefix, $config); + } +} diff --git a/admin/controllers/verse.php b/admin/controllers/verse.php new file mode 100644 index 0000000..fc04a0f --- /dev/null +++ b/admin/controllers/verse.php @@ -0,0 +1,330 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\FormController; +use Joomla\Utilities\ArrayHelper; + +/** + * Verse Form Controller + */ +class GetbibleControllerVerse extends FormController +{ + /** + * Current or most recently performed task. + * + * @var string + * @since 12.2 + * @note Replaces _task. + */ + protected $task; + + /** + * Class constructor. + * + * @param array $config A named array of configuration variables. + * + * @since 1.6 + */ + public function __construct($config = array()) + { + $this->view_list = 'Verses'; // safeguard for setting the return view listing to the main view. + parent::__construct($config); + }###ADMIN_CUSTOM_BUTTONS_CONTROLLER### + + /** + * Method override to check if you can add a new record. + * + * @param array $data An array of input data. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowAdd($data = array()) + { + // Get user object. + $user = JFactory::getUser(); + // Access check. + $access = $user->authorise('verse.access', 'com_getbible'); + if (!$access) + { + return false; + } + + // In the absense of better information, revert to the component permissions. + return $user->authorise('verse.create', $this->option); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // get user object. + $user = JFactory::getUser(); + // get record id. + $recordId = (int) isset($data[$key]) ? $data[$key] : 0; + + + // Access check. + $access = ($user->authorise('verse.access', 'com_getbible.verse.' . (int) $recordId) && $user->authorise('verse.access', 'com_getbible')); + if (!$access) + { + return false; + } + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('verse.edit', 'com_getbible.verse.' . (int) $recordId); + if (!$permission) + { + if ($user->authorise('verse.edit.own', 'com_getbible.verse.' . $recordId)) + { + // Now test the owner is the user. + $ownerId = (int) isset($data['created_by']) ? $data['created_by'] : 0; + if (empty($ownerId)) + { + // Need to do a lookup from the model. + $record = $this->getModel()->getItem($recordId); + + if (empty($record)) + { + return false; + } + $ownerId = $record->created_by; + } + + // If the owner matches 'me' then allow. + if ($ownerId == $user->id) + { + if ($user->authorise('verse.edit.own', 'com_getbible')) + { + return true; + } + } + } + return false; + } + } + // Since there is no permission, revert to the component permissions. + return $user->authorise('verse.edit', $this->option); + } + + /** + * Gets the URL arguments to append to an item redirect. + * + * @param integer $recordId The primary key id for the item. + * @param string $urlVar The name of the URL variable for the id. + * + * @return string The arguments to append to the redirect URL. + * + * @since 1.6 + */ + protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id') + { + // get the referral options (old method use return instead see parent) + $ref = $this->input->get('ref', 0, 'string'); + $refid = $this->input->get('refid', 0, 'int'); + + // get redirect info. + $append = parent::getRedirectToItemAppend($recordId, $urlVar); + + // set the referral options + if ($refid && $ref) + { + $append = '&ref=' . (string)$ref . '&refid='. (int)$refid . $append; + } + elseif ($ref) + { + $append = '&ref='. (string)$ref . $append; + } + + return $append; + } + + /** + * Method to run batch operations. + * + * @param object $model The model. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 2.5 + */ + public function batch($model = null) + { + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + // Set the model + $model = $this->getModel('Verse', '', array()); + + // Preset the redirect + $this->setRedirect(JRoute::_('index.php?option=com_getbible&view=verses' . $this->getRedirectToListAppend(), false)); + + return parent::batch($model); + } + + /** + * Method to cancel an edit. + * + * @param string $key The name of the primary key of the URL variable. + * + * @return boolean True if access level checks pass, false otherwise. + * + * @since 12.2 + */ + public function cancel($key = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + + $cancel = parent::cancel($key); + + if (!is_null($return) && JUri::isInternal(base64_decode($return))) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view='.(string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $cancel; + } + + /** + * Method to save a record. + * + * @param string $key The name of the primary key of the URL variable. + * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). + * + * @return boolean True if successful, false otherwise. + * + * @since 12.2 + */ + public function save($key = null, $urlVar = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + $canReturn = (!is_null($return) && JUri::isInternal(base64_decode($return))); + + if ($this->ref || $this->refid || $canReturn) + { + // to make sure the item is checkedin on redirect + $this->task = 'save'; + } + + $saved = parent::save($key, $urlVar); + + // This is not needed since parent save already does this + // Due to the ref and refid implementation we need to add this + if ($canReturn) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + JRoute::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view=' . (string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $saved; + } + + /** + * Function that allows child controller access to model data + * after the data has been saved. + * + * @param JModel &$model The data model object. + * @param array $validData The validated data. + * + * @return void + * + * @since 11.1 + */ + protected function postSaveHook(JModelLegacy $model, $validData = array()) + { + return; + } + +} diff --git a/admin/controllers/verses.php b/admin/controllers/verses.php new file mode 100644 index 0000000..754606f --- /dev/null +++ b/admin/controllers/verses.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\AdminController; +use Joomla\Utilities\ArrayHelper; + +/** + * Verses Admin Controller + */ +class GetbibleControllerVerses extends AdminController +{ + /** + * The prefix to use with controller messages. + * + * @var string + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE_VERSES'; + + /** + * Method to get a model object, loading it if required. + * + * @param string $name The model name. Optional. + * @param string $prefix The class prefix. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JModelLegacy The model. + * + * @since 1.6 + */ + public function getModel($name = 'Verse', $prefix = 'GetbibleModel', $config = array('ignore_request' => true)) + { + return parent::getModel($name, $prefix, $config); + } +} diff --git a/admin/getbible.php b/admin/getbible.php new file mode 100644 index 0000000..435b779 --- /dev/null +++ b/admin/getbible.php @@ -0,0 +1,91 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// register this component namespace +spl_autoload_register(function ($class) { + // project-specific base directories and namespace prefix + $search = [ + 'libraries/jcb_powers/VDM.Joomla.GetBible' => 'VDM\\Joomla\\GetBible', + 'libraries/jcb_powers/VDM.Joomla.Openai' => 'VDM\\Joomla\\Openai', + 'libraries/jcb_powers/VDM.Joomla.Gitea' => 'VDM\\Joomla\\Gitea', + 'libraries/jcb_powers/VDM.Joomla' => 'VDM\\Joomla' + ]; + // Start the search and load if found + $found = false; + $found_base_dir = ""; + $found_len = 0; + foreach ($search as $base_dir => $prefix) + { + // does the class use the namespace prefix? + $len = strlen($prefix); + if (strncmp($prefix, $class, $len) === 0) + { + // we have a match so load the values + $found = true; + $found_base_dir = $base_dir; + $found_len = $len; + // done here + break; + } + } + // check if we found a match + if (!$found) + { + // not found so move to the next registered autoloader + return; + } + // get the relative class name + $relative_class = substr($class, $found_len); + // replace the namespace prefix with the base directory, replace namespace + // separators with directory separators in the relative class name, append + // with .php + $file = JPATH_ROOT . '/' . $found_base_dir . '/src' . str_replace('\\', '/', $relative_class) . '.php'; + // if the file exists, require it + if (file_exists($file)) + { + require $file; + } +}); + + + +// Access check. +if (!JFactory::getUser()->authorise('core.manage', 'com_getbible')) +{ + throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403); +}; + +// Add CSS file for all pages +$document = JFactory::getDocument(); +$document->addStyleSheet('components/com_getbible/assets/css/admin.css'); +$document->addScript('components/com_getbible/assets/js/admin.js'); + +// require helper files +JLoader::register('GetbibleHelper', __DIR__ . '/helpers/getbible.php'); +JLoader::register('JHtmlBatch_', __DIR__ . '/helpers/html/batch_.php'); + +// Get an instance of the controller prefixed by Getbible +$controller = JControllerLegacy::getInstance('Getbible'); + +// Perform the Request task +$controller->execute(JFactory::getApplication()->input->get('task')); + +// Redirect if set by the controller +$controller->redirect(); diff --git a/admin/helpers/getbible.php b/admin/helpers/getbible.php new file mode 100644 index 0000000..7461ab1 --- /dev/null +++ b/admin/helpers/getbible.php @@ -0,0 +1,1465 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// register this component namespace +spl_autoload_register(function ($class) { + // project-specific base directories and namespace prefix + $search = [ + 'libraries/jcb_powers/VDM.Joomla.GetBible' => 'VDM\\Joomla\\GetBible', + 'libraries/jcb_powers/VDM.Joomla.Openai' => 'VDM\\Joomla\\Openai', + 'libraries/jcb_powers/VDM.Joomla.Gitea' => 'VDM\\Joomla\\Gitea', + 'libraries/jcb_powers/VDM.Joomla' => 'VDM\\Joomla' + ]; + // Start the search and load if found + $found = false; + $found_base_dir = ""; + $found_len = 0; + foreach ($search as $base_dir => $prefix) + { + // does the class use the namespace prefix? + $len = strlen($prefix); + if (strncmp($prefix, $class, $len) === 0) + { + // we have a match so load the values + $found = true; + $found_base_dir = $base_dir; + $found_len = $len; + // done here + break; + } + } + // check if we found a match + if (!$found) + { + // not found so move to the next registered autoloader + return; + } + // get the relative class name + $relative_class = substr($class, $found_len); + // replace the namespace prefix with the base directory, replace namespace + // separators with directory separators in the relative class name, append + // with .php + $file = JPATH_ROOT . '/' . $found_base_dir . '/src' . str_replace('\\', '/', $relative_class) . '.php'; + // if the file exists, require it + if (file_exists($file)) + { + require $file; + } +}); + +use Joomla\CMS\Filesystem\File; +use Joomla\CMS\Language\Language; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; +use VDM\Joomla\GetBible\Factory; + +/** + * Getbible component helper. + */ +abstract class GetbibleHelper +{ + /** + * Composer Switch + * + * @var array + */ + protected static $composer = array(); + + /** + * The Main Active Language + * + * @var string + */ + public static $langTag; + + /** + * Load the scripture into content + * + * @param object &$row The article object. Note $article->text is also available + * @param object $plugin The plugin params + * + * @return void + * @since 2.0.1 + **/ + public static function loadScripture(object &$row, object $plugin): void + { + // get call string + $call_class = $plugin->get('call_class', 'getBible'); + + // Simple performance check to determine whether bot should process further + if (strpos($row->text, $call_class) === false) + { + return; + } + + Factory::_('GetBible.Loader')->set($row, $plugin); + } + + /** + * Load the Composer Vendors + */ + public static function composerAutoload($target) + { + // insure we load the composer vendor only once + if (!isset(self::$composer[$target])) + { + // get the function name + $functionName = self::safeString('compose' . $target); + // check if method exist + if (method_exists(__CLASS__, $functionName)) + { + return self::{$functionName}(); + } + return false; + } + return self::$composer[$target]; + } + + /** + * Load the Component xml manifest. + */ + public static function manifest() + { + $manifestUrl = JPATH_ADMINISTRATOR."/components/com_getbible/getbible.xml"; + return simplexml_load_file($manifestUrl); + } + + /** + * Joomla version object + */ + protected static $JVersion; + + /** + * set/get Joomla version + */ + public static function jVersion() + { + // check if set + if (!self::checkObject(self::$JVersion)) + { + self::$JVersion = new JVersion(); + } + return self::$JVersion; + } + + /** + * Load the Contributors details. + */ + public static function getContributors() + { + // get params + $params = JComponentHelper::getParams('com_getbible'); + // start contributors array + $contributors = array(); + // get all Contributors (max 20) + $searchArray = range('0','20'); + foreach($searchArray as $nr) + { + if ((NULL !== $params->get("showContributor".$nr)) && ($params->get("showContributor".$nr) == 1 || $params->get("showContributor".$nr) == 3)) + { + // set link based of selected option + if($params->get("useContributor".$nr) == 1) + { + $link_front = '
'; + $link_back = ''; + } + elseif($params->get("useContributor".$nr) == 2) + { + $link_front = ''; + $link_back = ''; + } + else + { + $link_front = ''; + $link_back = ''; + } + $contributors[$nr]['title'] = self::htmlEscape($params->get("titleContributor".$nr)); + $contributors[$nr]['name'] = $link_front.self::htmlEscape($params->get("nameContributor".$nr)).$link_back; + } + } + return $contributors; + } + + /** + * Can be used to build help urls. + **/ + public static function getHelpUrl($view) + { + return false; + } + + /** + * Configure the Linkbar. + */ + public static function addSubmenu($submenu) + { + // load user for access menus + $user = JFactory::getUser(); + // load the submenus to sidebar + JHtmlSidebar::addEntry(JText::_('COM_GETBIBLE_SUBMENU_DASHBOARD'), 'index.php?option=com_getbible&view=getbible', $submenu === 'getbible'); + if ($user->authorise('linker.access', 'com_getbible') && $user->authorise('linker.submenu', 'com_getbible')) + { + JHtmlSidebar::addEntry(JText::_('COM_GETBIBLE_SUBMENU_LINKERS'), 'index.php?option=com_getbible&view=linkers', $submenu === 'linkers'); + } + if ($user->authorise('note.access', 'com_getbible') && $user->authorise('note.submenu', 'com_getbible')) + { + JHtmlSidebar::addEntry(JText::_('COM_GETBIBLE_SUBMENU_NOTES'), 'index.php?option=com_getbible&view=notes', $submenu === 'notes'); + } + if ($user->authorise('tagged_verse.access', 'com_getbible') && $user->authorise('tagged_verse.submenu', 'com_getbible')) + { + JHtmlSidebar::addEntry(JText::_('COM_GETBIBLE_SUBMENU_TAGGED_VERSES'), 'index.php?option=com_getbible&view=tagged_verses', $submenu === 'tagged_verses'); + } + if ($user->authorise('prompt.access', 'com_getbible') && $user->authorise('prompt.submenu', 'com_getbible')) + { + JHtmlSidebar::addEntry(JText::_('COM_GETBIBLE_SUBMENU_PROMPTS'), 'index.php?option=com_getbible&view=prompts', $submenu === 'prompts'); + } + if ($user->authorise('open_ai_response.access', 'com_getbible') && $user->authorise('open_ai_response.submenu', 'com_getbible')) + { + JHtmlSidebar::addEntry(JText::_('COM_GETBIBLE_SUBMENU_OPEN_AI_RESPONSES'), 'index.php?option=com_getbible&view=open_ai_responses', $submenu === 'open_ai_responses'); + } + if ($user->authorise('tag.access', 'com_getbible') && $user->authorise('tag.submenu', 'com_getbible')) + { + JHtmlSidebar::addEntry(JText::_('COM_GETBIBLE_SUBMENU_TAGS'), 'index.php?option=com_getbible&view=tags', $submenu === 'tags'); + } + if ($user->authorise('translation.access', 'com_getbible') && $user->authorise('translation.submenu', 'com_getbible')) + { + JHtmlSidebar::addEntry(JText::_('COM_GETBIBLE_SUBMENU_TRANSLATIONS'), 'index.php?option=com_getbible&view=translations', $submenu === 'translations'); + } + if ($user->authorise('book.access', 'com_getbible') && $user->authorise('book.submenu', 'com_getbible')) + { + JHtmlSidebar::addEntry(JText::_('COM_GETBIBLE_SUBMENU_BOOKS'), 'index.php?option=com_getbible&view=books', $submenu === 'books'); + } + if ($user->authorise('chapter.access', 'com_getbible') && $user->authorise('chapter.submenu', 'com_getbible')) + { + JHtmlSidebar::addEntry(JText::_('COM_GETBIBLE_SUBMENU_CHAPTERS'), 'index.php?option=com_getbible&view=chapters', $submenu === 'chapters'); + } + if ($user->authorise('verse.access', 'com_getbible') && $user->authorise('verse.submenu', 'com_getbible')) + { + JHtmlSidebar::addEntry(JText::_('COM_GETBIBLE_SUBMENU_VERSES'), 'index.php?option=com_getbible&view=verses', $submenu === 'verses'); + } + } + + /** + * Get a Variable + * + * @param string $table The table from which to get the variable + * @param string $where The value where + * @param string $whereString The target/field string where/name + * @param string $what The return field + * @param string $operator The operator between $whereString/field and $where/value + * @param string $main The component in which the table is found + * + * @return mix string/int/float + * + */ + public static function getVar($table, $where = null, $whereString = 'user', $what = 'id', $operator = '=', $main = 'getbible') + { + if(!$where) + { + $where = JFactory::getUser()->id; + } + // Get a db connection. + $db = JFactory::getDbo(); + // Create a new query object. + $query = $db->getQuery(true); + $query->select($db->quoteName(array($what))); + if (empty($table)) + { + $query->from($db->quoteName('#__'.$main)); + } + else + { + $query->from($db->quoteName('#__'.$main.'_'.$table)); + } + if (is_numeric($where)) + { + $query->where($db->quoteName($whereString) . ' '.$operator.' '.(int) $where); + } + elseif (is_string($where)) + { + $query->where($db->quoteName($whereString) . ' '.$operator.' '. $db->quote((string)$where)); + } + else + { + return false; + } + $db->setQuery($query); + $db->execute(); + if ($db->getNumRows()) + { + return $db->loadResult(); + } + return false; + } + + /** + * Get array of variables + * + * @param string $table The table from which to get the variables + * @param string $where The value where + * @param string $whereString The target/field string where/name + * @param string $what The return field + * @param string $operator The operator between $whereString/field and $where/value + * @param string $main The component in which the table is found + * @param bool $unique The switch to return a unique array + * + * @return array + * + */ + public static function getVars($table, $where = null, $whereString = 'user', $what = 'id', $operator = 'IN', $main = 'getbible', $unique = true) + { + if(!$where) + { + $where = JFactory::getUser()->id; + } + + if (!self::checkArray($where) && $where > 0) + { + $where = array($where); + } + + if (self::checkArray($where)) + { + // prep main <-- why? well if $main='' is empty then $table can be categories or users + if (self::checkString($main)) + { + $main = '_'.ltrim($main, '_'); + } + // Get a db connection. + $db = JFactory::getDbo(); + // Create a new query object. + $query = $db->getQuery(true); + + $query->select($db->quoteName(array($what))); + if (empty($table)) + { + $query->from($db->quoteName('#__'.$main)); + } + else + { + $query->from($db->quoteName('#_'.$main.'_'.$table)); + } + // add strings to array search + if ('IN_STRINGS' === $operator || 'NOT IN_STRINGS' === $operator) + { + $query->where($db->quoteName($whereString) . ' ' . str_replace('_STRINGS', '', $operator) . ' ("' . implode('","',$where) . '")'); + } + else + { + $query->where($db->quoteName($whereString) . ' ' . $operator . ' (' . implode(',',$where) . ')'); + } + $db->setQuery($query); + $db->execute(); + if ($db->getNumRows()) + { + if ($unique) + { + return array_unique($db->loadColumn()); + } + return $db->loadColumn(); + } + } + return false; + } + + public static function jsonToString($value, $sperator = ", ", $table = null, $id = 'id', $name = 'name') + { + // do some table foot work + $external = false; + if (strpos($table, '#__') !== false) + { + $external = true; + $table = str_replace('#__', '', $table); + } + // check if string is JSON + $result = json_decode($value, true); + if (json_last_error() === JSON_ERROR_NONE) + { + // is JSON + if (self::checkArray($result)) + { + if (self::checkString($table)) + { + $names = array(); + foreach ($result as $val) + { + if ($external) + { + if ($_name = self::getVar(null, $val, $id, $name, '=', $table)) + { + $names[] = $_name; + } + } + else + { + if ($_name = self::getVar($table, $val, $id, $name)) + { + $names[] = $_name; + } + } + } + if (self::checkArray($names)) + { + return (string) implode($sperator,$names); + } + } + return (string) implode($sperator,$result); + } + return (string) json_decode($value); + } + return $value; + } + + public static function isPublished($id,$type) + { + if ($type == 'raw') + { + $type = 'item'; + } + $db = JFactory::getDbo(); + $query = $db->getQuery(true); + $query->select(array('a.published')); + $query->from('#__getbible_'.$type.' AS a'); + $query->where('a.id = '. (int) $id); + $query->where('a.published = 1'); + $db->setQuery($query); + $db->execute(); + $found = $db->getNumRows(); + if($found) + { + return true; + } + return false; + } + + public static function getGroupName($id) + { + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + $query->select(array('a.title')); + $query->from('#__usergroups AS a'); + $query->where('a.id = '. (int) $id); + $db->setQuery($query); + $db->execute(); + $found = $db->getNumRows(); + if($found) + { + return $db->loadResult(); + } + return $id; + } + + /** + * Get the action permissions + * + * @param string $view The related view name + * @param int $record The item to act upon + * @param string $views The related list view name + * @param mixed $target Only get this permission (like edit, create, delete) + * @param string $component The target component + * @param object $user The user whose permissions we are loading + * + * @return object The JObject of permission/authorised actions + * + */ + public static function getActions($view, &$record = null, $views = null, $target = null, $component = 'getbible', $user = 'null') + { + // load the user if not given + if (!self::checkObject($user)) + { + // get the user object + $user = JFactory::getUser(); + } + // load the JObject + $result = new JObject; + // make view name safe (just incase) + $view = self::safeString($view); + if (self::checkString($views)) + { + $views = self::safeString($views); + } + // get all actions from component + $actions = JAccess::getActionsFromFile( + JPATH_ADMINISTRATOR . '/components/com_' . $component . '/access.xml', + "/access/section[@name='component']/" + ); + // if non found then return empty JObject + if (empty($actions)) + { + return $result; + } + // get created by if not found + if (self::checkObject($record) && !isset($record->created_by) && isset($record->id)) + { + $record->created_by = self::getVar($view, $record->id, 'id', 'created_by', '=', $component); + } + // set actions only set in component settings + $componentActions = array('core.admin', 'core.manage', 'core.options', 'core.export'); + // check if we have a target + $checkTarget = false; + if ($target) + { + // convert to an array + if (self::checkString($target)) + { + $target = array($target); + } + // check if we are good to go + if (self::checkArray($target)) + { + $checkTarget = true; + } + } + // loop the actions and set the permissions + foreach ($actions as $action) + { + // check target action filter + if ($checkTarget && self::filterActions($view, $action->name, $target)) + { + continue; + } + // set to use component default + $fallback = true; + // reset permission per/action + $permission = false; + $catpermission = false; + // set area + $area = 'comp'; + // check if the record has an ID and the action is item related (not a component action) + if (self::checkObject($record) && isset($record->id) && $record->id > 0 && !in_array($action->name, $componentActions) && + (strpos($action->name, 'core.') !== false || strpos($action->name, $view . '.') !== false)) + { + // we are in item + $area = 'item'; + // The record has been set. Check the record permissions. + $permission = $user->authorise($action->name, 'com_' . $component . '.' . $view . '.' . (int) $record->id); + // if no permission found, check edit own + if (!$permission) + { + // With edit, if the created_by matches current user then dig deeper. + if (($action->name === 'core.edit' || $action->name === $view . '.edit') && $record->created_by > 0 && ($record->created_by == $user->id)) + { + // the correct target + $coreCheck = (array) explode('.', $action->name); + // check that we have both local and global access + if ($user->authorise($coreCheck[0] . '.edit.own', 'com_' . $component . '.' . $view . '.' . (int) $record->id) && + $user->authorise($coreCheck[0] . '.edit.own', 'com_' . $component)) + { + // allow edit + $result->set($action->name, true); + // set not to use global default + // because we already validated it + $fallback = false; + } + else + { + // do not allow edit + $result->set($action->name, false); + $fallback = false; + } + } + } + elseif (self::checkString($views) && isset($record->catid) && $record->catid > 0) + { + // we are in item + $area = 'category'; + // set the core check + $coreCheck = explode('.', $action->name); + $core = $coreCheck[0]; + // make sure we use the core. action check for the categories + if (strpos($action->name, $view) !== false && strpos($action->name, 'core.') === false ) + { + $coreCheck[0] = 'core'; + $categoryCheck = implode('.', $coreCheck); + } + else + { + $categoryCheck = $action->name; + } + // The record has a category. Check the category permissions. + $catpermission = $user->authorise($categoryCheck, 'com_' . $component . '.' . $views . '.category.' . (int) $record->catid); + if (!$catpermission && !is_null($catpermission)) + { + // With edit, if the created_by matches current user then dig deeper. + if (($action->name === 'core.edit' || $action->name === $view . '.edit') && $record->created_by > 0 && ($record->created_by == $user->id)) + { + // check that we have both local and global access + if ($user->authorise('core.edit.own', 'com_' . $component . '.' . $views . '.category.' . (int) $record->catid) && + $user->authorise($core . '.edit.own', 'com_' . $component)) + { + // allow edit + $result->set($action->name, true); + // set not to use global default + // because we already validated it + $fallback = false; + } + else + { + // do not allow edit + $result->set($action->name, false); + $fallback = false; + } + } + } + } + } + // if allowed then fallback on component global settings + if ($fallback) + { + // if item/category blocks access then don't fall back on global + if ((($area === 'item') && !$permission) || (($area === 'category') && !$catpermission)) + { + // do not allow + $result->set($action->name, false); + } + // Finally remember the global settings have the final say. (even if item allow) + // The local item permissions can block, but it can't open and override of global permissions. + // Since items are created by users and global permissions is set by system admin. + else + { + $result->set($action->name, $user->authorise($action->name, 'com_' . $component)); + } + } + } + return $result; + } + + /** + * Filter the action permissions + * + * @param string $action The action to check + * @param array $targets The array of target actions + * + * @return boolean true if action should be filtered out + * + */ + protected static function filterActions(&$view, &$action, &$targets) + { + foreach ($targets as $target) + { + if (strpos($action, $view . '.' . $target) !== false || + strpos($action, 'core.' . $target) !== false) + { + return false; + break; + } + } + return true; + } + + /** + * Get any component's model + */ + public static function getModel($name, $path = JPATH_COMPONENT_ADMINISTRATOR, $Component = 'Getbible', $config = array()) + { + // fix the name + $name = self::safeString($name); + // full path to models + $fullPathModels = $path . '/models'; + // load the model file + JModelLegacy::addIncludePath($fullPathModels, $Component . 'Model'); + // make sure the table path is loaded + if (!isset($config['table_path']) || !self::checkString($config['table_path'])) + { + // This is the JCB default path to tables in Joomla 3.x + $config['table_path'] = JPATH_ADMINISTRATOR . '/components/com_' . strtolower($Component) . '/tables'; + } + // get instance + $model = JModelLegacy::getInstance($name, $Component . 'Model', $config); + // if model not found (strange) + if ($model == false) + { + jimport('joomla.filesystem.file'); + // get file path + $filePath = $path . '/' . $name . '.php'; + $fullPathModel = $fullPathModels . '/' . $name . '.php'; + // check if it exists + if (File::exists($filePath)) + { + // get the file + require_once $filePath; + } + elseif (File::exists($fullPathModel)) + { + // get the file + require_once $fullPathModel; + } + // build class names + $modelClass = $Component . 'Model' . $name; + if (class_exists($modelClass)) + { + // initialize the model + return new $modelClass($config); + } + } + return $model; + } + + /** + * Add to asset Table + */ + public static function setAsset($id, $table, $inherit = true) + { + $parent = JTable::getInstance('Asset'); + $parent->loadByName('com_getbible'); + + $parentId = $parent->id; + $name = 'com_getbible.'.$table.'.'.$id; + $title = ''; + + $asset = JTable::getInstance('Asset'); + $asset->loadByName($name); + + // Check for an error. + $error = $asset->getError(); + + if ($error) + { + return false; + } + else + { + // Specify how a new or moved node asset is inserted into the tree. + if ($asset->parent_id != $parentId) + { + $asset->setLocation($parentId, 'last-child'); + } + + // Prepare the asset to be stored. + $asset->parent_id = $parentId; + $asset->name = $name; + $asset->title = $title; + // get the default asset rules + $rules = self::getDefaultAssetRules('com_getbible', $table, $inherit); + if ($rules instanceof JAccessRules) + { + $asset->rules = (string) $rules; + } + + if (!$asset->check() || !$asset->store()) + { + JFactory::getApplication()->enqueueMessage($asset->getError(), 'warning'); + return false; + } + else + { + // Create an asset_id or heal one that is corrupted. + $object = new stdClass(); + + // Must be a valid primary key value. + $object->id = $id; + $object->asset_id = (int) $asset->id; + + // Update their asset_id to link to the asset table. + return JFactory::getDbo()->updateObject('#__getbible_'.$table, $object, 'id'); + } + } + return false; + } + + /** + * Gets the default asset Rules for a component/view. + */ + protected static function getDefaultAssetRules($component, $view, $inherit = true) + { + // if new or inherited + $assetId = 0; + // Only get the actual item rules if not inheriting + if (!$inherit) + { + // Need to find the asset id by the name of the component. + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select($db->quoteName('id')) + ->from($db->quoteName('#__assets')) + ->where($db->quoteName('name') . ' = ' . $db->quote($component)); + $db->setQuery($query); + $db->execute(); + // check that there is a value + if ($db->getNumRows()) + { + // asset already set so use saved rules + $assetId = (int) $db->loadResult(); + } + } + // get asset rules + $result = JAccess::getAssetRules($assetId); + if ($result instanceof JAccessRules) + { + $_result = (string) $result; + $_result = json_decode($_result); + foreach ($_result as $name => &$rule) + { + $v = explode('.', $name); + if ($view !== $v[0]) + { + // remove since it is not part of this view + unset($_result->$name); + } + elseif ($inherit) + { + // clear the value since we inherit + $rule = array(); + } + } + // check if there are any view values remaining + if (count((array) $_result)) + { + $_result = json_encode($_result); + $_result = array($_result); + // Instantiate and return the JAccessRules object for the asset rules. + $rules = new JAccessRules($_result); + // return filtered rules + return $rules; + } + } + return $result; + } + + /** + * xmlAppend + * + * @param SimpleXMLElement $xml The XML element reference in which to inject a comment + * @param mixed $node A SimpleXMLElement node to append to the XML element reference, or a stdClass object containing a comment attribute to be injected before the XML node and a fieldXML attribute containing a SimpleXMLElement + * + * @return null + * + */ + public static function xmlAppend(&$xml, $node) + { + if (!$node) + { + // element was not returned + return; + } + switch (get_class($node)) + { + case 'stdClass': + if (property_exists($node, 'comment')) + { + self::xmlComment($xml, $node->comment); + } + if (property_exists($node, 'fieldXML')) + { + self::xmlAppend($xml, $node->fieldXML); + } + break; + case 'SimpleXMLElement': + $domXML = dom_import_simplexml($xml); + $domNode = dom_import_simplexml($node); + $domXML->appendChild($domXML->ownerDocument->importNode($domNode, true)); + $xml = simplexml_import_dom($domXML); + break; + } + } + + /** + * xmlComment + * + * @param SimpleXMLElement $xml The XML element reference in which to inject a comment + * @param string $comment The comment to inject + * + * @return null + * + */ + public static function xmlComment(&$xml, $comment) + { + $domXML = dom_import_simplexml($xml); + $domComment = new DOMComment($comment); + $nodeTarget = $domXML->ownerDocument->importNode($domComment, true); + $domXML->appendChild($nodeTarget); + $xml = simplexml_import_dom($domXML); + } + + /** + * xmlAddAttributes + * + * @param SimpleXMLElement $xml The XML element reference in which to inject a comment + * @param array $attributes The attributes to apply to the XML element + * + * @return null + * + */ + public static function xmlAddAttributes(&$xml, $attributes = array()) + { + foreach ($attributes as $key => $value) + { + $xml->addAttribute($key, $value); + } + } + + /** + * xmlAddOptions + * + * @param SimpleXMLElement $xml The XML element reference in which to inject a comment + * @param array $options The options to apply to the XML element + * + * @return void + * + */ + public static function xmlAddOptions(&$xml, $options = array()) + { + foreach ($options as $key => $value) + { + $addOption = $xml->addChild('option'); + $addOption->addAttribute('value', $key); + $addOption[] = $value; + } + } + + /** + * get the field object + * + * @param array $attributes The array of attributes + * @param string $default The default of the field + * @param array $options The options to apply to the XML element + * + * @return object + * + */ + public static function getFieldObject(&$attributes, $default = '', $options = null) + { + // make sure we have attributes and a type value + if (self::checkArray($attributes) && isset($attributes['type'])) + { + // make sure the form helper class is loaded + if (!method_exists('JFormHelper', 'loadFieldType')) + { + jimport('joomla.form.form'); + } + // get field type + $field = JFormHelper::loadFieldType($attributes['type'], true); + // get field xml + $XML = self::getFieldXML($attributes, $options); + // setup the field + $field->setup($XML, $default); + // return the field object + return $field; + } + return false; + } + + /** + * get the field xml + * + * @param array $attributes The array of attributes + * @param array $options The options to apply to the XML element + * + * @return object + * + */ + public static function getFieldXML(&$attributes, $options = null) + { + // make sure we have attributes and a type value + if (self::checkArray($attributes)) + { + // start field xml + $XML = new SimpleXMLElement(''); + // load the attributes + self::xmlAddAttributes($XML, $attributes); + // check if we have options + if (self::checkArray($options)) + { + // load the options + self::xmlAddOptions($XML, $options); + } + // return the field xml + return $XML; + } + return false; + } + + /** + * Render Bool Button + * + * @param array $args All the args for the button + * 0) name + * 1) additional (options class) // not used at this time + * 2) default + * 3) yes (name) + * 4) no (name) + * + * @return string The input html of the button + * + */ + public static function renderBoolButton() + { + $args = func_get_args(); + // check if there is additional button class + $additional = isset($args[1]) ? (string) $args[1] : ''; // not used at this time + // button attributes + $buttonAttributes = array( + 'type' => 'radio', + 'name' => isset($args[0]) ? self::htmlEscape($args[0]) : 'bool_button', + 'label' => isset($args[0]) ? self::safeString(self::htmlEscape($args[0]), 'Ww') : 'Bool Button', // not seen anyway + 'class' => 'btn-group', + 'filter' => 'INT', + 'default' => isset($args[2]) ? (int) $args[2] : 0); + // set the button options + $buttonOptions = array( + '1' => isset($args[3]) ? self::htmlEscape($args[3]) : 'JYES', + '0' => isset($args[4]) ? self::htmlEscape($args[4]) : 'JNO'); + // return the input + return self::getFieldObject($buttonAttributes, $buttonAttributes['default'], $buttonOptions)->input; + } + + /** + * Check if have an json string + * + * @input string The json string to check + * + * @returns bool true on success + */ + public static function checkJson($string) + { + if (self::checkString($string)) + { + json_decode($string); + return (json_last_error() === JSON_ERROR_NONE); + } + return false; + } + + /** + * Check if have an object with a length + * + * @input object The object to check + * + * @returns bool true on success + */ + public static function checkObject($object) + { + if (isset($object) && is_object($object)) + { + return count((array)$object) > 0; + } + return false; + } + + /** + * Check if have an array with a length + * + * @input array The array to check + * + * @returns bool/int number of items in array on success + */ + public static function checkArray($array, $removeEmptyString = false) + { + if (isset($array) && is_array($array) && ($nr = count((array)$array)) > 0) + { + // also make sure the empty strings are removed + if ($removeEmptyString) + { + foreach ($array as $key => $string) + { + if (empty($string)) + { + unset($array[$key]); + } + } + return self::checkArray($array, false); + } + return $nr; + } + return false; + } + + /** + * Check if have a string with a length + * + * @input string The string to check + * + * @returns bool true on success + */ + public static function checkString($string) + { + if (isset($string) && is_string($string) && strlen($string) > 0) + { + return true; + } + return false; + } + + /** + * Check if we are connected + * Thanks https://stackoverflow.com/a/4860432/1429677 + * + * @returns bool true on success + */ + public static function isConnected() + { + // If example.com is down, then probably the whole internet is down, since IANA maintains the domain. Right? + $connected = @fsockopen("www.example.com", 80); + // website, port (try 80 or 443) + if ($connected) + { + //action when connected + $is_conn = true; + fclose($connected); + } + else + { + //action in connection failure + $is_conn = false; + } + return $is_conn; + } + + /** + * Merge an array of array's + * + * @input array The arrays you would like to merge + * + * @returns array on success + */ + public static function mergeArrays($arrays) + { + if(self::checkArray($arrays)) + { + $arrayBuket = array(); + foreach ($arrays as $array) + { + if (self::checkArray($array)) + { + $arrayBuket = array_merge($arrayBuket, $array); + } + } + return $arrayBuket; + } + return false; + } + + // typo sorry! + public static function sorten($string, $length = 40, $addTip = true) + { + return self::shorten($string, $length, $addTip); + } + + /** + * Shorten a string + * + * @input string The you would like to shorten + * + * @returns string on success + */ + public static function shorten($string, $length = 40, $addTip = true) + { + if (self::checkString($string)) + { + $initial = strlen($string); + $words = preg_split('/([\s\n\r]+)/', $string, null, PREG_SPLIT_DELIM_CAPTURE); + $words_count = count((array)$words); + + $word_length = 0; + $last_word = 0; + for (; $last_word < $words_count; ++$last_word) + { + $word_length += strlen($words[$last_word]); + if ($word_length > $length) + { + break; + } + } + + $newString = implode(array_slice($words, 0, $last_word)); + $final = strlen($newString); + if ($initial != $final && $addTip) + { + $title = self::shorten($string, 400 , false); + return ''.trim($newString).'...'; + } + elseif ($initial != $final && !$addTip) + { + return trim($newString).'...'; + } + } + return $string; + } + + /** + * Making strings safe (various ways) + * + * @input string The you would like to make safe + * + * @returns string on success + */ + public static function safeString($string, $type = 'L', $spacer = '_', $replaceNumbers = true, $keepOnlyCharacters = true) + { + if ($replaceNumbers === true) + { + // remove all numbers and replace with english text version (works well only up to millions) + $string = self::replaceNumbers($string); + } + // 0nly continue if we have a string + if (self::checkString($string)) + { + // create file name without the extention that is safe + if ($type === 'filename') + { + // make sure VDM is not in the string + $string = str_replace('VDM', 'vDm', $string); + // Remove anything which isn't a word, whitespace, number + // or any of the following caracters -_() + // If you don't need to handle multi-byte characters + // you can use preg_replace rather than mb_ereg_replace + // Thanks @Łukasz Rysiak! + // $string = mb_ereg_replace("([^\w\s\d\-_\(\)])", '', $string); + $string = preg_replace("([^\w\s\d\-_\(\)])", '', $string); + // http://stackoverflow.com/a/2021729/1429677 + return preg_replace('/\s+/', ' ', $string); + } + // remove all other characters + $string = trim($string); + $string = preg_replace('/'.$spacer.'+/', ' ', $string); + $string = preg_replace('/\s+/', ' ', $string); + // Transliterate string + $string = self::transliterate($string); + // remove all and keep only characters + if ($keepOnlyCharacters) + { + $string = preg_replace("/[^A-Za-z ]/", '', $string); + } + // keep both numbers and characters + else + { + $string = preg_replace("/[^A-Za-z0-9 ]/", '', $string); + } + // select final adaptations + if ($type === 'L' || $type === 'strtolower') + { + // replace white space with underscore + $string = preg_replace('/\s+/', $spacer, $string); + // default is to return lower + return strtolower($string); + } + elseif ($type === 'W') + { + // return a string with all first letter of each word uppercase(no undersocre) + return ucwords(strtolower($string)); + } + elseif ($type === 'w' || $type === 'word') + { + // return a string with all lowercase(no undersocre) + return strtolower($string); + } + elseif ($type === 'Ww' || $type === 'Word') + { + // return a string with first letter of the first word uppercase and all the rest lowercase(no undersocre) + return ucfirst(strtolower($string)); + } + elseif ($type === 'WW' || $type === 'WORD') + { + // return a string with all the uppercase(no undersocre) + return strtoupper($string); + } + elseif ($type === 'U' || $type === 'strtoupper') + { + // replace white space with underscore + $string = preg_replace('/\s+/', $spacer, $string); + // return all upper + return strtoupper($string); + } + elseif ($type === 'F' || $type === 'ucfirst') + { + // replace white space with underscore + $string = preg_replace('/\s+/', $spacer, $string); + // return with first caracter to upper + return ucfirst(strtolower($string)); + } + elseif ($type === 'cA' || $type === 'cAmel' || $type === 'camelcase') + { + // convert all words to first letter uppercase + $string = ucwords(strtolower($string)); + // remove white space + $string = preg_replace('/\s+/', '', $string); + // now return first letter lowercase + return lcfirst($string); + } + // return string + return $string; + } + // not a string + return ''; + } + + public static function transliterate($string) + { + // set tag only once + if (!self::checkString(self::$langTag)) + { + // get global value + self::$langTag = JComponentHelper::getParams('com_getbible')->get('language', 'en-GB'); + } + // Transliterate on the language requested + $lang = Language::getInstance(self::$langTag); + return $lang->transliterate($string); + } + + public static function htmlEscape($var, $charset = 'UTF-8', $shorten = false, $length = 40) + { + if (self::checkString($var)) + { + $filter = new JFilterInput(); + $string = $filter->clean(html_entity_decode(htmlentities($var, ENT_COMPAT, $charset)), 'HTML'); + if ($shorten) + { + return self::shorten($string,$length); + } + return $string; + } + else + { + return ''; + } + } + + public static function replaceNumbers($string) + { + // set numbers array + $numbers = array(); + // first get all numbers + preg_match_all('!\d+!', $string, $numbers); + // check if we have any numbers + if (isset($numbers[0]) && self::checkArray($numbers[0])) + { + foreach ($numbers[0] as $number) + { + $searchReplace[$number] = self::numberToString((int)$number); + } + // now replace numbers in string + $string = str_replace(array_keys($searchReplace), array_values($searchReplace),$string); + // check if we missed any, strange if we did. + return self::replaceNumbers($string); + } + // return the string with no numbers remaining. + return $string; + } + + /** + * Convert an integer into an English word string + * Thanks to Tom Nicholson + * + * @input an int + * @returns a string + */ + public static function numberToString($x) + { + $nwords = array( "zero", "one", "two", "three", "four", "five", "six", "seven", + "eight", "nine", "ten", "eleven", "twelve", "thirteen", + "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", + "nineteen", "twenty", 30 => "thirty", 40 => "forty", + 50 => "fifty", 60 => "sixty", 70 => "seventy", 80 => "eighty", + 90 => "ninety" ); + + if(!is_numeric($x)) + { + $w = $x; + } + elseif(fmod($x, 1) != 0) + { + $w = $x; + } + else + { + if($x < 0) + { + $w = 'minus '; + $x = -$x; + } + else + { + $w = ''; + // ... now $x is a non-negative integer. + } + + if($x < 21) // 0 to 20 + { + $w .= $nwords[$x]; + } + elseif($x < 100) // 21 to 99 + { + $w .= $nwords[10 * floor($x/10)]; + $r = fmod($x, 10); + if($r > 0) + { + $w .= ' '. $nwords[$r]; + } + } + elseif($x < 1000) // 100 to 999 + { + $w .= $nwords[floor($x/100)] .' hundred'; + $r = fmod($x, 100); + if($r > 0) + { + $w .= ' and '. self::numberToString($r); + } + } + elseif($x < 1000000) // 1000 to 999999 + { + $w .= self::numberToString(floor($x/1000)) .' thousand'; + $r = fmod($x, 1000); + if($r > 0) + { + $w .= ' '; + if($r < 100) + { + $w .= 'and '; + } + $w .= self::numberToString($r); + } + } + else // millions + { + $w .= self::numberToString(floor($x/1000000)) .' million'; + $r = fmod($x, 1000000); + if($r > 0) + { + $w .= ' '; + if($r < 100) + { + $w .= 'and '; + } + $w .= self::numberToString($r); + } + } + } + return $w; + } + + /** + * Random Key + * + * @returns a string + */ + public static function randomkey($size) + { + $bag = "abcefghijknopqrstuwxyzABCDDEFGHIJKLLMMNOPQRSTUVVWXYZabcddefghijkllmmnopqrstuvvwxyzABCEFGHIJKNOPQRSTUWXYZ"; + $key = array(); + $bagsize = strlen($bag) - 1; + for ($i = 0; $i < $size; $i++) + { + $get = rand(0, $bagsize); + $key[] = $bag[$get]; + } + return implode($key); + } +} + diff --git a/admin/helpers/headercheck.php b/admin/helpers/headercheck.php new file mode 100644 index 0000000..171cdbe --- /dev/null +++ b/admin/helpers/headercheck.php @@ -0,0 +1,77 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +class getbibleHeaderCheck +{ + function js_loaded($script_name) + { + // UIkit check point + if (strpos($script_name,'uikit') !== false) + { + $app = JFactory::getApplication(); + $getTemplateName = $app->getTemplate('template')->template; + + if (strpos($getTemplateName,'yoo') !== false) + { + return true; + } + } + + $document = JFactory::getDocument(); + $head_data = $document->getHeadData(); + foreach (array_keys($head_data['scripts']) as $script) + { + if (stristr($script, $script_name)) + { + return true; + } + } + + return false; + } + + function css_loaded($script_name) + { + // UIkit check point + if (strpos($script_name,'uikit') !== false) + { + $app = JFactory::getApplication(); + $getTemplateName = $app->getTemplate('template')->template; + + if (strpos($getTemplateName,'yoo') !== false) + { + return true; + } + } + + $document = JFactory::getDocument(); + $head_data = $document->getHeadData(); + + foreach (array_keys($head_data['styleSheets']) as $script) + { + if (stristr($script, $script_name)) + { + return true; + } + } + + return false; + } +} \ No newline at end of file diff --git a/admin/helpers/html/batch_.php b/admin/helpers/html/batch_.php new file mode 100644 index 0000000..1abd495 --- /dev/null +++ b/admin/helpers/html/batch_.php @@ -0,0 +1,84 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('JPATH_PLATFORM') or die; + +/** + * Utility class to render a list view batch selection options + * + * @since 3.0 + */ +abstract class JHtmlBatch_ +{ + /** + * ListSelection + * + * @var array + * @since 3.0 + */ + protected static $ListSelection = array(); + + /** + * Render the batch selection options. + * + * @return string The necessary HTML to display the batch selection options + * + * @since 3.0 + */ + public static function render() + { + // Collect display data + $data = new stdClass; + $data->ListSelection = static::getListSelection(); + + // Create a layout object and ask it to render the batch selection options + $layout = new JLayoutFile('batchselection'); + $batchHtml = $layout->render($data); + + return $batchHtml; + } + + /** + * Method to add a list selection to the batch modal + * + * @param string $label Label for the menu item. + * @param string $name Name for the filter. Also used as id. + * @param string $options Options for the select field. + * @param bool $noDefault Don't the label as the empty option + * + * @return void + * + * @since 3.0 + */ + public static function addListSelection($label, $name, $options, $noDefault = false) + { + array_push(static::$ListSelection, array('label' => $label, 'name' => $name, 'options' => $options, 'noDefault' => $noDefault)); + } + + /** + * Returns an array of all ListSelection + * + * @return array + * + * @since 3.0 + */ + public static function getListSelection() + { + return static::$ListSelection; + } +} diff --git a/admin/helpers/html/index.html b/admin/helpers/html/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/helpers/html/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/helpers/index.html b/admin/helpers/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/helpers/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/index.html b/admin/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/language/en-GB/en-GB.com_getbible.ini b/admin/language/en-GB/en-GB.com_getbible.ini new file mode 100644 index 0000000..62282c5 --- /dev/null +++ b/admin/language/en-GB/en-GB.com_getbible.ini @@ -0,0 +1,1853 @@ +COM_GETBIBLE="Get Bible" +COM_GETBIBLE_ACCESS_ALREADY_EXIST_BUT_COULD_NOT_BE_REACTIVATED="Access already exist, but could not be reactivated." +COM_GETBIBLE_ALL_IS_GOOD_PLEASE_CHECK_AGAIN_LATTER="All is good, please check again latter." +COM_GETBIBLE_ALL_TRANSLATIONS="All Translations" +COM_GETBIBLE_ARCHIVED="Archived" +COM_GETBIBLE_ARE_YOU_SURE_YOU_WANT_TO_DELETE_CONFIRMING_WILL_PERMANENTLY_DELETE_THE_SELECTED_ITEMS="Are you sure you want to delete? Confirming will permanently delete the selected item(s)!" +COM_GETBIBLE_AUTHOR="Author" +COM_GETBIBLE_BACK="Back" +COM_GETBIBLE_BETA_RELEASE="Beta Release" +COM_GETBIBLE_BOOK="Book" +COM_GETBIBLE_BOOKS="Books" +COM_GETBIBLE_BOOKS_ACCESS="Books Access" +COM_GETBIBLE_BOOKS_ACCESS_DESC="Allows the users in this group to access access books" +COM_GETBIBLE_BOOKS_BATCH_OPTIONS="Batch process the selected Books" +COM_GETBIBLE_BOOKS_BATCH_TIP="All changes will be applied to all selected Books" +COM_GETBIBLE_BOOKS_BATCH_USE="Books Batch Use" +COM_GETBIBLE_BOOKS_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch books" +COM_GETBIBLE_BOOKS_CREATE="Books Create" +COM_GETBIBLE_BOOKS_CREATE_DESC="Allows the users in this group to create create books" +COM_GETBIBLE_BOOKS_DASHBOARD_LIST="Books Dashboard List" +COM_GETBIBLE_BOOKS_DASHBOARD_LIST_DESC="Allows the users in this group to dashboard list of book" +COM_GETBIBLE_BOOKS_DELETE="Books Delete" +COM_GETBIBLE_BOOKS_DELETE_DESC="Allows the users in this group to delete delete books" +COM_GETBIBLE_BOOKS_EDIT="Books Edit" +COM_GETBIBLE_BOOKS_EDIT_ABBREVIATION="Books Edit Abbreviation" +COM_GETBIBLE_BOOKS_EDIT_ABBREVIATION_DESC="Allows the users in this group to edit abbreviation of book" +COM_GETBIBLE_BOOKS_EDIT_CREATED_BY="Books Edit Created By" +COM_GETBIBLE_BOOKS_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by books" +COM_GETBIBLE_BOOKS_EDIT_CREATED_DATE="Books Edit Created Date" +COM_GETBIBLE_BOOKS_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created books" +COM_GETBIBLE_BOOKS_EDIT_DESC="Allows the users in this group to edit the book" +COM_GETBIBLE_BOOKS_EDIT_NAME="Books Edit Name" +COM_GETBIBLE_BOOKS_EDIT_NAME_DESC="Allows the users in this group to edit name of book" +COM_GETBIBLE_BOOKS_EDIT_NR="Books Edit Nr" +COM_GETBIBLE_BOOKS_EDIT_NR_DESC="Allows the users in this group to edit nr of book" +COM_GETBIBLE_BOOKS_EDIT_OWN="Books Edit Own" +COM_GETBIBLE_BOOKS_EDIT_OWN_DESC="Allows the users in this group to edit edit own books created by them" +COM_GETBIBLE_BOOKS_EDIT_SHA="Books Edit Sha" +COM_GETBIBLE_BOOKS_EDIT_SHA_DESC="Allows the users in this group to edit sha of book" +COM_GETBIBLE_BOOKS_EDIT_STATE="Books Edit State" +COM_GETBIBLE_BOOKS_EDIT_STATE_DESC="Allows the users in this group to update the state of the book" +COM_GETBIBLE_BOOKS_N_ITEMS_ARCHIVED="%s Books archived." +COM_GETBIBLE_BOOKS_N_ITEMS_ARCHIVED_1="%s Book archived." +COM_GETBIBLE_BOOKS_N_ITEMS_CHECKED_IN_0="No Book successfully checked in." +COM_GETBIBLE_BOOKS_N_ITEMS_CHECKED_IN_1="%d Book successfully checked in." +COM_GETBIBLE_BOOKS_N_ITEMS_CHECKED_IN_MORE="%d Books successfully checked in." +COM_GETBIBLE_BOOKS_N_ITEMS_DELETED="%s Books deleted." +COM_GETBIBLE_BOOKS_N_ITEMS_DELETED_1="%s Book deleted." +COM_GETBIBLE_BOOKS_N_ITEMS_FAILED_PUBLISHING="%s Books failed publishing." +COM_GETBIBLE_BOOKS_N_ITEMS_FAILED_PUBLISHING_1="%s Book failed publishing." +COM_GETBIBLE_BOOKS_N_ITEMS_FEATURED="%s Books featured." +COM_GETBIBLE_BOOKS_N_ITEMS_FEATURED_1="%s Book featured." +COM_GETBIBLE_BOOKS_N_ITEMS_PUBLISHED="%s Books published." +COM_GETBIBLE_BOOKS_N_ITEMS_PUBLISHED_1="%s Book published." +COM_GETBIBLE_BOOKS_N_ITEMS_TRASHED="%s Books trashed." +COM_GETBIBLE_BOOKS_N_ITEMS_TRASHED_1="%s Book trashed." +COM_GETBIBLE_BOOKS_N_ITEMS_UNFEATURED="%s Books unfeatured." +COM_GETBIBLE_BOOKS_N_ITEMS_UNFEATURED_1="%s Book unfeatured." +COM_GETBIBLE_BOOKS_N_ITEMS_UNPUBLISHED="%s Books unpublished." +COM_GETBIBLE_BOOKS_N_ITEMS_UNPUBLISHED_1="%s Book unpublished." +COM_GETBIBLE_BOOKS_SUBMENU="Books Submenu" +COM_GETBIBLE_BOOKS_SUBMENU_DESC="Allows the users in this group to submenu of book" +COM_GETBIBLE_BOOK_ABBREVIATION_DESCRIPTION="Select a Bible translation" +COM_GETBIBLE_BOOK_ABBREVIATION_LABEL="Translation" +COM_GETBIBLE_BOOK_CREATED_BY_DESC="The user that created this Book." +COM_GETBIBLE_BOOK_CREATED_BY_LABEL="Created By" +COM_GETBIBLE_BOOK_CREATED_DATE_DESC="The date this Book was created." +COM_GETBIBLE_BOOK_CREATED_DATE_LABEL="Created Date" +COM_GETBIBLE_BOOK_DETAILS="Details" +COM_GETBIBLE_BOOK_ERROR_UNIQUE_ALIAS="Another Book has the same alias." +COM_GETBIBLE_BOOK_ID="Id" +COM_GETBIBLE_BOOK_MODIFIED_BY_DESC="The last user that modified this Book." +COM_GETBIBLE_BOOK_MODIFIED_BY_LABEL="Modified By" +COM_GETBIBLE_BOOK_MODIFIED_DATE_DESC="The date this Book was modified." +COM_GETBIBLE_BOOK_MODIFIED_DATE_LABEL="Modified Date" +COM_GETBIBLE_BOOK_NAME_DESCRIPTION="Enter Name Here" +COM_GETBIBLE_BOOK_NAME_HINT="Name Here" +COM_GETBIBLE_BOOK_NAME_LABEL="Name" +COM_GETBIBLE_BOOK_NAME_MESSAGE="Error! Please add name here." +COM_GETBIBLE_BOOK_NR_DESCRIPTION="Select the book number" +COM_GETBIBLE_BOOK_NR_LABEL="Number" +COM_GETBIBLE_BOOK_ORDERING_LABEL="Ordering" +COM_GETBIBLE_BOOK_PERMISSION="Permissions" +COM_GETBIBLE_BOOK_PUBLISHING="Publishing" +COM_GETBIBLE_BOOK_READONLY="Book :: Readonly" +COM_GETBIBLE_BOOK_SAVE_WARNING="Alias already existed so a number was added at the end. You can re-edit the Book to customise the alias." +COM_GETBIBLE_BOOK_SHA_DESCRIPTION="Enter some checksum sha" +COM_GETBIBLE_BOOK_SHA_LABEL="Checksum" +COM_GETBIBLE_BOOK_SHA_MESSAGE="Error! Please add some checksum sha here." +COM_GETBIBLE_BOOK_STATUS="Status" +COM_GETBIBLE_BOOK_VERSION_DESC="A count of the number of times this Book has been revised." +COM_GETBIBLE_BOOK_VERSION_LABEL="Version" +COM_GETBIBLE_CHAPTER="Chapter" +COM_GETBIBLE_CHAPTERS="Chapters" +COM_GETBIBLE_CHAPTERS_ACCESS="Chapters Access" +COM_GETBIBLE_CHAPTERS_ACCESS_DESC="Allows the users in this group to access access chapters" +COM_GETBIBLE_CHAPTERS_BATCH_OPTIONS="Batch process the selected Chapters" +COM_GETBIBLE_CHAPTERS_BATCH_TIP="All changes will be applied to all selected Chapters" +COM_GETBIBLE_CHAPTERS_BATCH_USE="Chapters Batch Use" +COM_GETBIBLE_CHAPTERS_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch chapters" +COM_GETBIBLE_CHAPTERS_CREATE="Chapters Create" +COM_GETBIBLE_CHAPTERS_CREATE_DESC="Allows the users in this group to create create chapters" +COM_GETBIBLE_CHAPTERS_DASHBOARD_LIST="Chapters Dashboard List" +COM_GETBIBLE_CHAPTERS_DASHBOARD_LIST_DESC="Allows the users in this group to dashboard list of chapter" +COM_GETBIBLE_CHAPTERS_DELETE="Chapters Delete" +COM_GETBIBLE_CHAPTERS_DELETE_DESC="Allows the users in this group to delete delete chapters" +COM_GETBIBLE_CHAPTERS_EDIT="Chapters Edit" +COM_GETBIBLE_CHAPTERS_EDIT_ABBREVIATION="Chapters Edit Abbreviation" +COM_GETBIBLE_CHAPTERS_EDIT_ABBREVIATION_DESC="Allows the users in this group to edit abbreviation of chapter" +COM_GETBIBLE_CHAPTERS_EDIT_BOOK_NR="Chapters Edit Book Nr" +COM_GETBIBLE_CHAPTERS_EDIT_BOOK_NR_DESC="Allows the users in this group to edit book nr of chapter" +COM_GETBIBLE_CHAPTERS_EDIT_CHAPTER="Chapters Edit Chapter" +COM_GETBIBLE_CHAPTERS_EDIT_CHAPTER_DESC="Allows the users in this group to edit chapter of chapter" +COM_GETBIBLE_CHAPTERS_EDIT_CREATED_BY="Chapters Edit Created By" +COM_GETBIBLE_CHAPTERS_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by chapters" +COM_GETBIBLE_CHAPTERS_EDIT_CREATED_DATE="Chapters Edit Created Date" +COM_GETBIBLE_CHAPTERS_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created chapters" +COM_GETBIBLE_CHAPTERS_EDIT_DESC="Allows the users in this group to edit the chapter" +COM_GETBIBLE_CHAPTERS_EDIT_NAME="Chapters Edit Name" +COM_GETBIBLE_CHAPTERS_EDIT_NAME_DESC="Allows the users in this group to edit name of chapter" +COM_GETBIBLE_CHAPTERS_EDIT_OWN="Chapters Edit Own" +COM_GETBIBLE_CHAPTERS_EDIT_OWN_DESC="Allows the users in this group to edit edit own chapters created by them" +COM_GETBIBLE_CHAPTERS_EDIT_SHA="Chapters Edit Sha" +COM_GETBIBLE_CHAPTERS_EDIT_SHA_DESC="Allows the users in this group to edit sha of chapter" +COM_GETBIBLE_CHAPTERS_EDIT_STATE="Chapters Edit State" +COM_GETBIBLE_CHAPTERS_EDIT_STATE_DESC="Allows the users in this group to update the state of the chapter" +COM_GETBIBLE_CHAPTERS_N_ITEMS_ARCHIVED="%s Chapters archived." +COM_GETBIBLE_CHAPTERS_N_ITEMS_ARCHIVED_1="%s Chapter archived." +COM_GETBIBLE_CHAPTERS_N_ITEMS_CHECKED_IN_0="No Chapter successfully checked in." +COM_GETBIBLE_CHAPTERS_N_ITEMS_CHECKED_IN_1="%d Chapter successfully checked in." +COM_GETBIBLE_CHAPTERS_N_ITEMS_CHECKED_IN_MORE="%d Chapters successfully checked in." +COM_GETBIBLE_CHAPTERS_N_ITEMS_DELETED="%s Chapters deleted." +COM_GETBIBLE_CHAPTERS_N_ITEMS_DELETED_1="%s Chapter deleted." +COM_GETBIBLE_CHAPTERS_N_ITEMS_FAILED_PUBLISHING="%s Chapters failed publishing." +COM_GETBIBLE_CHAPTERS_N_ITEMS_FAILED_PUBLISHING_1="%s Chapter failed publishing." +COM_GETBIBLE_CHAPTERS_N_ITEMS_FEATURED="%s Chapters featured." +COM_GETBIBLE_CHAPTERS_N_ITEMS_FEATURED_1="%s Chapter featured." +COM_GETBIBLE_CHAPTERS_N_ITEMS_PUBLISHED="%s Chapters published." +COM_GETBIBLE_CHAPTERS_N_ITEMS_PUBLISHED_1="%s Chapter published." +COM_GETBIBLE_CHAPTERS_N_ITEMS_TRASHED="%s Chapters trashed." +COM_GETBIBLE_CHAPTERS_N_ITEMS_TRASHED_1="%s Chapter trashed." +COM_GETBIBLE_CHAPTERS_N_ITEMS_UNFEATURED="%s Chapters unfeatured." +COM_GETBIBLE_CHAPTERS_N_ITEMS_UNFEATURED_1="%s Chapter unfeatured." +COM_GETBIBLE_CHAPTERS_N_ITEMS_UNPUBLISHED="%s Chapters unpublished." +COM_GETBIBLE_CHAPTERS_N_ITEMS_UNPUBLISHED_1="%s Chapter unpublished." +COM_GETBIBLE_CHAPTERS_SUBMENU="Chapters Submenu" +COM_GETBIBLE_CHAPTERS_SUBMENU_DESC="Allows the users in this group to submenu of chapter" +COM_GETBIBLE_CHAPTER_ABBREVIATION_DESCRIPTION="Select a Bible translation" +COM_GETBIBLE_CHAPTER_ABBREVIATION_LABEL="Translation" +COM_GETBIBLE_CHAPTER_BOOK_NR_DESCRIPTION="Select the book number" +COM_GETBIBLE_CHAPTER_BOOK_NR_LABEL="Book Number" +COM_GETBIBLE_CHAPTER_CHAPTER_DESCRIPTION="Select the chapter number" +COM_GETBIBLE_CHAPTER_CHAPTER_LABEL="Chapter" +COM_GETBIBLE_CHAPTER_CREATED_BY_DESC="The user that created this Chapter." +COM_GETBIBLE_CHAPTER_CREATED_BY_LABEL="Created By" +COM_GETBIBLE_CHAPTER_CREATED_DATE_DESC="The date this Chapter was created." +COM_GETBIBLE_CHAPTER_CREATED_DATE_LABEL="Created Date" +COM_GETBIBLE_CHAPTER_DETAILS="Details" +COM_GETBIBLE_CHAPTER_ERROR_UNIQUE_ALIAS="Another Chapter has the same alias." +COM_GETBIBLE_CHAPTER_ID="Id" +COM_GETBIBLE_CHAPTER_MODIFIED_BY_DESC="The last user that modified this Chapter." +COM_GETBIBLE_CHAPTER_MODIFIED_BY_LABEL="Modified By" +COM_GETBIBLE_CHAPTER_MODIFIED_DATE_DESC="The date this Chapter was modified." +COM_GETBIBLE_CHAPTER_MODIFIED_DATE_LABEL="Modified Date" +COM_GETBIBLE_CHAPTER_NAME_DESCRIPTION="Enter Name Here" +COM_GETBIBLE_CHAPTER_NAME_HINT="Name Here" +COM_GETBIBLE_CHAPTER_NAME_LABEL="Name" +COM_GETBIBLE_CHAPTER_NAME_MESSAGE="Error! Please add name here." +COM_GETBIBLE_CHAPTER_ORDERING_LABEL="Ordering" +COM_GETBIBLE_CHAPTER_PERMISSION="Permissions" +COM_GETBIBLE_CHAPTER_PUBLISHING="Publishing" +COM_GETBIBLE_CHAPTER_READONLY="Chapter :: Readonly" +COM_GETBIBLE_CHAPTER_SAVE_WARNING="Alias already existed so a number was added at the end. You can re-edit the Chapter to customise the alias." +COM_GETBIBLE_CHAPTER_SHA_DESCRIPTION="Enter some checksum sha" +COM_GETBIBLE_CHAPTER_SHA_LABEL="Checksum" +COM_GETBIBLE_CHAPTER_SHA_MESSAGE="Error! Please add some checksum sha here." +COM_GETBIBLE_CHAPTER_STATUS="Status" +COM_GETBIBLE_CHAPTER_VERSION_DESC="A count of the number of times this Chapter has been revised." +COM_GETBIBLE_CHAPTER_VERSION_LABEL="Version" +COM_GETBIBLE_CLOSE_NEW="Close & New" +COM_GETBIBLE_CONFIG_ABBREVIATION="Abbreviation" +COM_GETBIBLE_CONFIG_ACTIVATE_NOTES_DESCRIPTION="Activate the option to add notes on verses." +COM_GETBIBLE_CONFIG_ACTIVATE_NOTES_LABEL="Activate Notes" +COM_GETBIBLE_CONFIG_ACTIVATE_SEARCH_DESCRIPTION="Activate the option to search verses." +COM_GETBIBLE_CONFIG_ACTIVATE_SEARCH_LABEL="Activate Search" +COM_GETBIBLE_CONFIG_ACTIVATE_SHARING_DESCRIPTION="Activate the option to share verses." +COM_GETBIBLE_CONFIG_ACTIVATE_SHARING_LABEL="Activate Sharing" +COM_GETBIBLE_CONFIG_ACTIVATE_TAGS_DESCRIPTION="Activate the option to tag verses." +COM_GETBIBLE_CONFIG_ACTIVATE_TAGS_LABEL="Activate Tags" +COM_GETBIBLE_CONFIG_ACTIVE_SHARING_NOTE_DESCRIPTION="We cache the user selection, which means that these settings only form the default advance options for new visitors, or for those who clear their cache." +COM_GETBIBLE_CONFIG_ACTIVE_SHARING_NOTE_LABEL="Default Advance Options" +COM_GETBIBLE_CONFIG_ADD="Add" +COM_GETBIBLE_CONFIG_ALLOW_UNTAGGING_DESCRIPTION="Allow users to remove the system tags from verses for themselves (only)." +COM_GETBIBLE_CONFIG_ALLOW_UNTAGGING_LABEL="Allow Untagging" +COM_GETBIBLE_CONFIG_ALL_WORDS="All Words" +COM_GETBIBLE_CONFIG_ANY_WORDS="Any Words" +COM_GETBIBLE_CONFIG_APP="App" +COM_GETBIBLE_CONFIG_APP_MENU_DESCRIPTION="Select the menu item of the app page." +COM_GETBIBLE_CONFIG_APP_MENU_LABEL="Bible App Menu Item" +COM_GETBIBLE_CONFIG_ARRAY="array" +COM_GETBIBLE_CONFIG_AUTHOR="Author Info" +COM_GETBIBLE_CONFIG_AUTHOR_EMAIL_DESC="The email address of the author of this component." +COM_GETBIBLE_CONFIG_AUTHOR_EMAIL_LABEL="Author Email" +COM_GETBIBLE_CONFIG_AUTHOR_NAME_DESC="The name of the author of this component." +COM_GETBIBLE_CONFIG_AUTHOR_NAME_LABEL="Author Name" +COM_GETBIBLE_CONFIG_AUTO_LOAD="Auto" +COM_GETBIBLE_CONFIG_BOOKS_CARD_STYLE_LABEL="Books Card Style" +COM_GETBIBLE_CONFIG_BOOKS_ICON_DESCRIPTION="Set the books custom icon" +COM_GETBIBLE_CONFIG_BOOKS_ICON_HINT="album" +COM_GETBIBLE_CONFIG_BOOKS_ICON_LABEL="Books Icon" +COM_GETBIBLE_CONFIG_BOOKS_ICON_MESSAGE="Error! Please add some icon name here." +COM_GETBIBLE_CONFIG_BOOKS_TAB_DESCRIPTION="The books tab name" +COM_GETBIBLE_CONFIG_BOOKS_TAB_HINT="Books" +COM_GETBIBLE_CONFIG_BOOKS_TAB_LABEL="Books Tab" +COM_GETBIBLE_CONFIG_BOOKS_TAB_MESSAGE="Error! Please add some name here." +COM_GETBIBLE_CONFIG_BOTTOM="Bottom" +COM_GETBIBLE_CONFIG_BOTTOM_MENU_TYPE_LABEL="Bottom Menu Type" +COM_GETBIBLE_CONFIG_BREAK="break" +COM_GETBIBLE_CONFIG_CASE_INSENSITIVE="Case Insensitive" +COM_GETBIBLE_CONFIG_CASE_SENSITIVE="Case Sensitive" +COM_GETBIBLE_CONFIG_CHAPTERS_CARD_STYLE_LABEL="Chapters Card Style" +COM_GETBIBLE_CONFIG_CHAPTERS_ICON_DESCRIPTION="Set the chapters custom icon" +COM_GETBIBLE_CONFIG_CHAPTERS_ICON_HINT="grid" +COM_GETBIBLE_CONFIG_CHAPTERS_ICON_LABEL="Chapters Icon" +COM_GETBIBLE_CONFIG_CHAPTERS_ICON_MESSAGE="Error! Please add some icon name here." +COM_GETBIBLE_CONFIG_CHAPTERS_TAB_DESCRIPTION="The chapters tab name" +COM_GETBIBLE_CONFIG_CHAPTERS_TAB_HINT="Chapters" +COM_GETBIBLE_CONFIG_CHAPTERS_TAB_LABEL="Chapters Tab" +COM_GETBIBLE_CONFIG_CHAPTERS_TAB_MESSAGE="Error! Please add some name here." +COM_GETBIBLE_CONFIG_CHECK_TIMER_DESC="Set the intervals for the auto checkin fuction of tables that checks out the items to an user." +COM_GETBIBLE_CONFIG_CHECK_TIMER_LABEL="Check in timer" +COM_GETBIBLE_CONFIG_CHECK_TIMER_OPTION_FIVE="Once a week" +COM_GETBIBLE_CONFIG_CHECK_TIMER_OPTION_FOUR="Every second day" +COM_GETBIBLE_CONFIG_CHECK_TIMER_OPTION_ONE="Every five hours" +COM_GETBIBLE_CONFIG_CHECK_TIMER_OPTION_SIX="Never" +COM_GETBIBLE_CONFIG_CHECK_TIMER_OPTION_THREE="Once a day" +COM_GETBIBLE_CONFIG_CHECK_TIMER_OPTION_TWO="Every twelve hours" +COM_GETBIBLE_CONFIG_CLASS_HINT="Blank for none" +COM_GETBIBLE_CONFIG_CLASS_LABEL="Class" +COM_GETBIBLE_CONFIG_CLASS_MESSAGE="Error! Please add some Class here." +COM_GETBIBLE_CONFIG_CUSTOM_ICONS_DESCRIPTION="Use this option to set custom icons found at https://getuikit.com/docs/icon" +COM_GETBIBLE_CONFIG_CUSTOM_ICONS_LABEL="Set Custom Icons" +COM_GETBIBLE_CONFIG_CUSTOM_TABS_LABEL="Custom Tabs" +COM_GETBIBLE_CONFIG_DEBUG_DESCRIPTION="Show Debugging Information" +COM_GETBIBLE_CONFIG_DEBUG_LABEL="Debugging" +COM_GETBIBLE_CONFIG_DEFAULT="default" +COM_GETBIBLE_CONFIG_DEFAULT_FORMAT_SHARE_LABEL="Default Format Share" +COM_GETBIBLE_CONFIG_DETAILS_CARD_STYLE_LABEL="Details Card Style" +COM_GETBIBLE_CONFIG_DETAILS_ICON_DESCRIPTION="Set the details custom icon" +COM_GETBIBLE_CONFIG_DETAILS_ICON_HINT="info" +COM_GETBIBLE_CONFIG_DETAILS_ICON_LABEL="Details Icon" +COM_GETBIBLE_CONFIG_DETAILS_ICON_MESSAGE="Error! Please add some icon name here." +COM_GETBIBLE_CONFIG_DETAILS_TAB_DESCRIPTION="The details tab name" +COM_GETBIBLE_CONFIG_DETAILS_TAB_HINT="Details" +COM_GETBIBLE_CONFIG_DETAILS_TAB_LABEL="Details Tab" +COM_GETBIBLE_CONFIG_DETAILS_TAB_MESSAGE="Error! Please add some name here." +COM_GETBIBLE_CONFIG_DIV="div" +COM_GETBIBLE_CONFIG_DONT_LOAD="Not" +COM_GETBIBLE_CONFIG_ENABLE_OPEN_AI_DESCRIPTION="Enable Openai" +COM_GETBIBLE_CONFIG_ENABLE_OPEN_AI_LABEL="Enable Openai" +COM_GETBIBLE_CONFIG_ENABLE_OPEN_AI_ORG_DESCRIPTION="Enable Organisation Openai" +COM_GETBIBLE_CONFIG_ENABLE_OPEN_AI_ORG_LABEL="Enable Organisation Openai" +COM_GETBIBLE_CONFIG_EXACT_MATCH="Exact Match" +COM_GETBIBLE_CONFIG_EXACT_PHRASE="Exact Phrase" +COM_GETBIBLE_CONFIG_FORCE_LOAD="Force" +COM_GETBIBLE_CONFIG_GLOBAL_DESC="The Global Parameters" +COM_GETBIBLE_CONFIG_GLOBAL_LABEL="Global" +COM_GETBIBLE_CONFIG_GPT35TURBO="gpt-3.5-turbo" +COM_GETBIBLE_CONFIG_GPT35TURBO0613="gpt-3.5-turbo-0613" +COM_GETBIBLE_CONFIG_GPT35TURBO16K="gpt-3.5-turbo-16k" +COM_GETBIBLE_CONFIG_GPT35TURBO16K0613="gpt-3.5-turbo-16k-0613" +COM_GETBIBLE_CONFIG_GPT4="gpt-4" +COM_GETBIBLE_CONFIG_GPT40613="gpt-4-0613" +COM_GETBIBLE_CONFIG_GPT432K="gpt-4-32k" +COM_GETBIBLE_CONFIG_GPT432K0613="gpt-4-32k-0613" +COM_GETBIBLE_CONFIG_HIDE="Hide" +COM_GETBIBLE_CONFIG_HTML="HTML" +COM_GETBIBLE_CONFIG_JQUERY_LOAD="Load jQuery" +COM_GETBIBLE_CONFIG_JQUERY_LOAD_DESC="Would you like to load the Joomla jQuery Framework?" +COM_GETBIBLE_CONFIG_JQUERY_LOAD_LABEL="Load Joomla jQuery" +COM_GETBIBLE_CONFIG_JQUERY_REMOVE="Remove jQuery" +COM_GETBIBLE_CONFIG_LIST="list" +COM_GETBIBLE_CONFIG_LOCAL_LINK_SHARE_LABEL="Local Link Share" +COM_GETBIBLE_CONFIG_MARKDOWN="Markdown" +COM_GETBIBLE_CONFIG_NAME="Name" +COM_GETBIBLE_CONFIG_NAME_DESCRIPTION="Name" +COM_GETBIBLE_CONFIG_NAME_HINT="Tab Name" +COM_GETBIBLE_CONFIG_NAME_LABEL="Tab" +COM_GETBIBLE_CONFIG_NAME_MESSAGE="Error! Please add some name here." +COM_GETBIBLE_CONFIG_NO="No" +COM_GETBIBLE_CONFIG_NONE="None" +COM_GETBIBLE_CONFIG_NOTES="Notes" +COM_GETBIBLE_CONFIG_ONLY_EXTRA="Only Extra" +COM_GETBIBLE_CONFIG_OPENAI_DOCUMENTATION_NOTE_DESCRIPTION="

Please review the OpenAI API documentation for creating a chat conversation at this link. The document provides a comprehensive guide on parameters and methods to create chat completion using OpenAI's model. It includes instructions on:

  • How to post a request to create model responses
  • The format for the request body including role, model, messages, and optional parameters such as name, content, and function_call
  • Different ways to control the model's response such as temperature and top_p
  • How to control the number of generated chat completion choices, the stop sequences, and maximum number of tokens
  • Utilizing penalties and biases for managing the output
  • Additional features like streaming and user tracking for abuse monitoring
" +COM_GETBIBLE_CONFIG_OPENAI_DOCUMENTATION_NOTE_LABEL="Documentation" +COM_GETBIBLE_CONFIG_OPENAI_FREQUENCY_PENALTY_DESCRIPTION="Penalty for new tokens based on their frequency in the text" +COM_GETBIBLE_CONFIG_OPENAI_FREQUENCY_PENALTY_LABEL="Frequency Penalty" +COM_GETBIBLE_CONFIG_OPENAI_FREQUENCY_PENALTY_NOTE_DESCRIPTION="

The "frequency_penalty" is another optional parameter that defaults to 0. This is also a value between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.

  • For example, a high frequency penalty discourages the model from excessively repeating the same words or phrases, encouraging it to produce more diverse and creative text.
" +COM_GETBIBLE_CONFIG_OPENAI_FREQUENCY_PENALTY_NOTE_LABEL="Frequency Penalty" +COM_GETBIBLE_CONFIG_OPENAI_MAX_TOKENS_DESCRIPTION="Maximum number of tokens to generate." +COM_GETBIBLE_CONFIG_OPENAI_MAX_TOKENS_LABEL="Max Tokens" +COM_GETBIBLE_CONFIG_OPENAI_MAX_TOKENS_NOTE_DESCRIPTION="

The "max_tokens" parameter sets the maximum number of tokens to generate in the chat completion. This is an optional parameter that defaults to infinity if not specified.

  • Note that the total length of both the input tokens and the generated tokens is limited by the model's context length. For instance, if a model has a context length of 100 tokens and you've used 20 tokens in your input, you could generate up to 80 additional tokens.
" +COM_GETBIBLE_CONFIG_OPENAI_MAX_TOKENS_NOTE_LABEL="Max Tokens" +COM_GETBIBLE_CONFIG_OPENAI_MODEL_DESCRIPTION="ID of the model to use." +COM_GETBIBLE_CONFIG_OPENAI_MODEL_LABEL="Model" +COM_GETBIBLE_CONFIG_OPENAI_N_DESCRIPTION="The number of chat completion choices to generate" +COM_GETBIBLE_CONFIG_OPENAI_N_LABEL="Number AI Response Per/Prompt" +COM_GETBIBLE_CONFIG_OPENAI_N_NOTE_DESCRIPTION="

The "n" parameter determines how many independent completions to generate for each input message. This can be used when you want multiple distinct responses for a single prompt.

  • Setting "n" to 3, for instance, would make the model generate 3 separate responses for each input message.
" +COM_GETBIBLE_CONFIG_OPENAI_N_NOTE_LABEL="Number AI Response Per/Prompt" +COM_GETBIBLE_CONFIG_OPENAI_ORG_TOKEN_DESCRIPTION="Your Organisation Token" +COM_GETBIBLE_CONFIG_OPENAI_ORG_TOKEN_HINT="// get your token from your Organisation on Open AI" +COM_GETBIBLE_CONFIG_OPENAI_ORG_TOKEN_LABEL="Openai Organisation Token" +COM_GETBIBLE_CONFIG_OPENAI_ORG_TOKEN_NOTE_DESCRIPTION="

How to Get an OpenAI Organization API Token

  1. Sign In to OpenAI: Visit OpenAI and click on the 'Sign In' button to access your account.
  2. Access the Organization Settings: Navigate to the organization settings page. This is typically accessible from your dashboard or account settings. Look for a section or tab labeled 'Organization' or 'Organization Settings.'
  3. Create a New Organization API Key: From the organization settings page, find the section for API keys. There should be an option to create a new API key. Click on this and follow the prompts to create your new organization API key.
  4. Copy the API Key: Once created, your new organization API key will be displayed. Make sure to copy and store this key securely. Just like personal API keys, you won't be able to view this key again for security reasons, so it's essential to save it somewhere safe.
  5. Use the Organization API Key: You can now use this organization API key to make requests to the OpenAI API on behalf of your organization. Include this key in the headers of your HTTP requests, just like you would with a personal API key.

Remember, organization API keys represent access to your entire organization's OpenAI account, so be especially careful with these. Don't share them publicly, and make sure only trusted individuals within your organization have access. If you believe an organization API key has been compromised, delete it and create a new one immediately.

" +COM_GETBIBLE_CONFIG_OPENAI_ORG_TOKEN_NOTE_LABEL="Get Open AI Organization Token" +COM_GETBIBLE_CONFIG_OPENAI_PRESENCE_PENALTY_DESCRIPTION="Penalty for new tokens based on whether they appear in the text" +COM_GETBIBLE_CONFIG_OPENAI_PRESENCE_PENALTY_LABEL="Presence Penalty" +COM_GETBIBLE_CONFIG_OPENAI_PRESENCE_PENALTY_NOTE_DESCRIPTION="

The "presence_penalty" is an optional parameter that defaults to 0. This is a value between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.

  • For example, a high presence penalty encourages the model to generate text involving a wider variety of topics or themes, rather than focusing on a single topic or repeatedly using the same phrases.
" +COM_GETBIBLE_CONFIG_OPENAI_PRESENCE_PENALTY_NOTE_LABEL="Presence Penalty" +COM_GETBIBLE_CONFIG_OPENAI_TEMPERATURE_DESCRIPTION="The sampling temperature to use" +COM_GETBIBLE_CONFIG_OPENAI_TEMPERATURE_LABEL="Temperature" +COM_GETBIBLE_CONFIG_OPENAI_TEMPERATURE_NOTE_DESCRIPTION="

The "temperature" is a parameter that controls the randomness of the model's output. Its value ranges between 0 and 2. A higher temperature value results in more randomness, while a lower value results in less randomness. This affects the selection of the next word during text generation.

  • At a higher value like 2, the model has a greater probability of picking less likely words, which may lead to more diverse and creative outputs.
  • At a lower value like 0.2, the model's output becomes more deterministic, primarily choosing words with the highest predicted probabilities, leading to more focused and predictable responses.
" +COM_GETBIBLE_CONFIG_OPENAI_TEMPERATURE_NOTE_LABEL="Temperature" +COM_GETBIBLE_CONFIG_OPENAI_TOKEN_DESCRIPTION="Your Openai Token" +COM_GETBIBLE_CONFIG_OPENAI_TOKEN_HINT="// get your token from Open AI" +COM_GETBIBLE_CONFIG_OPENAI_TOKEN_LABEL="Openai Token" +COM_GETBIBLE_CONFIG_OPENAI_TOKEN_NOTE_DESCRIPTION="

How to Get an OpenAI API Token

  1. Sign Up on OpenAI: Visit OpenAI and click on the 'Sign Up' button to create a new account. You'll need to provide some basic information like your name and email address.
  2. Confirm your Email: After signing up, you'll receive an email from OpenAI to verify your email address. Click on the verification link to confirm your account.
  3. Access the Dashboard: Once your email is verified, log in to your OpenAI account and navigate to the Dashboard. You should see an option to create a new API key.
  4. Create a New API Key: Click on the 'Create New API Key' button. You'll be asked to name your API key and specify whether it has read and/or write access. Be sure to select the appropriate access level based on your needs.
  5. Copy your API Key: After creating the key, it will be displayed on your screen. Make sure to copy it and store it securely. You won't be able to view this key again for security reasons, so it's essential that you save it somewhere safe.
  6. Use your API Key: Now that you have your API key, you can use it to make requests to the OpenAI API. Typically, you will include this key in the headers of your HTTP requests.

Keep in mind that OpenAI's API has usage limits depending on your type of account (free, pay-as-you-go, etc.), so make sure you understand these limits to avoid unexpected charges or service interruptions. You can find information about usage limits on the OpenAI Pricing page.

Additionally, remember to keep your API key secure. Do not share it publicly or commit it to public repositories. If you believe your API key has been compromised, you can delete it and generate a new one from your OpenAI dashboard.

" +COM_GETBIBLE_CONFIG_OPENAI_TOKEN_NOTE_LABEL="Get Open AI Token" +COM_GETBIBLE_CONFIG_OPENAI_TOP_P_DESCRIPTION="The nucleus sampling parameter" +COM_GETBIBLE_CONFIG_OPENAI_TOP_P_LABEL="Top P" +COM_GETBIBLE_CONFIG_OPENAI_TOP_P_NOTE_DESCRIPTION="

The "top_p" parameter is used for "nucleus sampling," an alternative to the temperature-based sampling. It defines a threshold for the cumulative probability of the chosen tokens. Rather than considering all possible tokens for the next word, it only considers the smallest set of tokens whose cumulative probability exceeds the set "top_p" value.

  • Setting "top_p" to 0.1 means the model will only consider the tokens comprising the top 10% probability mass for the next word.
  • If "top_p" is set to 0.9, the model considers a wider range of tokens for the next word but still limits to those within the top 90% of the probability distribution.
" +COM_GETBIBLE_CONFIG_OPENAI_TOP_P_NOTE_LABEL="Top P" +COM_GETBIBLE_CONFIG_OPEN_AI="Open AI" +COM_GETBIBLE_CONFIG_PARAGRAPH="Paragraph" +COM_GETBIBLE_CONFIG_PARTIAL_MATCH="Partial Match" +COM_GETBIBLE_CONFIG_PER_LINE="Per Line" +COM_GETBIBLE_CONFIG_PLAIN_TEXT="Plain Text" +COM_GETBIBLE_CONFIG_POSITION_DESCRIPTION="Position" +COM_GETBIBLE_CONFIG_POSITION_HINT="ModulePosition" +COM_GETBIBLE_CONFIG_POSITION_LABEL="Module" +COM_GETBIBLE_CONFIG_POSITION_MESSAGE="Error! Please add some position name here." +COM_GETBIBLE_CONFIG_PREVIOUS_NEXT_NAVIGATION_DESCRIPTION="Show the previous and next navigation buttons" +COM_GETBIBLE_CONFIG_PREVIOUS_NEXT_NAVIGATION_LABEL="Show Previous and Next Navigation" +COM_GETBIBLE_CONFIG_PRIMARY="primary" +COM_GETBIBLE_CONFIG_REMOVE="Remove" +COM_GETBIBLE_CONFIG_SCRIPTURE_CARD_STYLE_LABEL="Scripture Card Style" +COM_GETBIBLE_CONFIG_SCRIPTURE_ICON_DESCRIPTION="Set the scripture custom icon" +COM_GETBIBLE_CONFIG_SCRIPTURE_ICON_HINT="heart" +COM_GETBIBLE_CONFIG_SCRIPTURE_ICON_LABEL="Scripture Icon" +COM_GETBIBLE_CONFIG_SCRIPTURE_ICON_MESSAGE="Error! Please add some icon name here." +COM_GETBIBLE_CONFIG_SCRIPTURE_TAB_DESCRIPTION="The scripture tab name" +COM_GETBIBLE_CONFIG_SCRIPTURE_TAB_HINT="Scripture" +COM_GETBIBLE_CONFIG_SCRIPTURE_TAB_LABEL="Scripture Tab" +COM_GETBIBLE_CONFIG_SCRIPTURE_TAB_MESSAGE="Error! Please add some name here." +COM_GETBIBLE_CONFIG_SEARCH="Search" +COM_GETBIBLE_CONFIG_SEARCH_CASE_DESCRIPTION="Search behaviour around each word case." +COM_GETBIBLE_CONFIG_SEARCH_CASE_LABEL="Case" +COM_GETBIBLE_CONFIG_SEARCH_FOUND_COLOR_DESCRIPTION="Select the search word found colour here." +COM_GETBIBLE_CONFIG_SEARCH_FOUND_COLOR_LABEL="Search Found Colour" +COM_GETBIBLE_CONFIG_SEARCH_MATCH_DESCRIPTION="Search behaviour around each word match." +COM_GETBIBLE_CONFIG_SEARCH_MATCH_LABEL="Match" +COM_GETBIBLE_CONFIG_SEARCH_WORDS_DESCRIPTION="Search behaviour around each word." +COM_GETBIBLE_CONFIG_SEARCH_WORDS_LABEL="Words" +COM_GETBIBLE_CONFIG_SECONDARY="secondary" +COM_GETBIBLE_CONFIG_SEPARATOR_LABEL="Separator" +COM_GETBIBLE_CONFIG_SETTINGS_CARD_STYLE_LABEL="Settings Card Style" +COM_GETBIBLE_CONFIG_SETTINGS_ICON_DESCRIPTION="Set the settings custom icon" +COM_GETBIBLE_CONFIG_SETTINGS_ICON_HINT="settings" +COM_GETBIBLE_CONFIG_SETTINGS_ICON_LABEL="Settings Icon" +COM_GETBIBLE_CONFIG_SETTINGS_ICON_MESSAGE="Error! Please add some icon name here." +COM_GETBIBLE_CONFIG_SETTINGS_TAB_DESCRIPTION="The settings tab name" +COM_GETBIBLE_CONFIG_SETTINGS_TAB_HINT="Settings" +COM_GETBIBLE_CONFIG_SETTINGS_TAB_LABEL="Settings Tab" +COM_GETBIBLE_CONFIG_SETTINGS_TAB_MESSAGE="Error! Please add some name here." +COM_GETBIBLE_CONFIG_SET_CUSTOM_TABS_DESCRIPTION="Set your own custom tabs" +COM_GETBIBLE_CONFIG_SET_CUSTOM_TABS_LABEL="Set Custom Tabs" +COM_GETBIBLE_CONFIG_SET_DEFAULT_TAB_NAMES_DESCRIPTION="Activate the option to set the default tab names." +COM_GETBIBLE_CONFIG_SET_DEFAULT_TAB_NAMES_LABEL="Set Default Tab Names" +COM_GETBIBLE_CONFIG_SHARE="Share" +COM_GETBIBLE_CONFIG_SHOW="Show" +COM_GETBIBLE_CONFIG_SHOW_API_LINK_DESCRIPTION="Show API link" +COM_GETBIBLE_CONFIG_SHOW_API_LINK_LABEL="API Link" +COM_GETBIBLE_CONFIG_SHOW_BOOKS_CARD_LABEL="Show Books Card" +COM_GETBIBLE_CONFIG_SHOW_BOOKS_ICON_LABEL="Show Books Icon" +COM_GETBIBLE_CONFIG_SHOW_BOOKS_TAB_TEXT_LABEL="Show Books Tab Text" +COM_GETBIBLE_CONFIG_SHOW_BOTTOM_MENU_LABEL="Show Bottom Menu" +COM_GETBIBLE_CONFIG_SHOW_CHAPTERS_CARD_LABEL="Show Chapters Card" +COM_GETBIBLE_CONFIG_SHOW_CHAPTERS_ICON_LABEL="Show Chapters Icon" +COM_GETBIBLE_CONFIG_SHOW_CHAPTERS_TAB_TEXT_LABEL="Show Chapters Tab Text" +COM_GETBIBLE_CONFIG_SHOW_DETAILS_CARD_LABEL="Show Details Card" +COM_GETBIBLE_CONFIG_SHOW_DETAILS_DESCRIPTION="Show the details tab" +COM_GETBIBLE_CONFIG_SHOW_DETAILS_ICON_LABEL="Show Details Icon" +COM_GETBIBLE_CONFIG_SHOW_DETAILS_LABEL="Show Details" +COM_GETBIBLE_CONFIG_SHOW_DETAILS_TAB_TEXT_LABEL="Show Details Tab Text" +COM_GETBIBLE_CONFIG_SHOW_GETBIBLE_LINK_DESCRIPTION="Show GetBible link" +COM_GETBIBLE_CONFIG_SHOW_GETBIBLE_LINK_LABEL="GetBible Link" +COM_GETBIBLE_CONFIG_SHOW_GETBIBLE_LOGO_DESCRIPTION="Show GetBible Logo" +COM_GETBIBLE_CONFIG_SHOW_GETBIBLE_LOGO_LABEL="GetBible Logo" +COM_GETBIBLE_CONFIG_SHOW_HASH_VALIDATION_DESCRIPTION="Show hash validation details" +COM_GETBIBLE_CONFIG_SHOW_HASH_VALIDATION_LABEL="Hash Validation" +COM_GETBIBLE_CONFIG_SHOW_HEADER_LABEL="Show Header" +COM_GETBIBLE_CONFIG_SHOW_INSTALL_BUTTON_DESCRIPTION="Show install translation button on the Bible app page. This is normally only needed during the setup of your application on your website the first time." +COM_GETBIBLE_CONFIG_SHOW_INSTALL_BUTTON_LABEL="Show Install Button" +COM_GETBIBLE_CONFIG_SHOW_SCRIPTURE_CARD_LABEL="Show Scripture Card" +COM_GETBIBLE_CONFIG_SHOW_SCRIPTURE_ICON_LABEL="Show Scripture Icon" +COM_GETBIBLE_CONFIG_SHOW_SCRIPTURE_TAB_TEXT_LABEL="Show Scripture Tab Text" +COM_GETBIBLE_CONFIG_SHOW_SETTINGS_CARD_LABEL="Show Settings Card" +COM_GETBIBLE_CONFIG_SHOW_SETTINGS_DESCRIPTION="Show the settings tab" +COM_GETBIBLE_CONFIG_SHOW_SETTINGS_ICON_LABEL="Show Settings Icon" +COM_GETBIBLE_CONFIG_SHOW_SETTINGS_LABEL="Show Settings" +COM_GETBIBLE_CONFIG_SHOW_SETTINGS_TAB_TEXT_LABEL="Show Settings Tab Text" +COM_GETBIBLE_CONFIG_SHOW_TOP_MENU_LABEL="Show Top Menu" +COM_GETBIBLE_CONFIG_SHOW_TRANSLATIONS_CARD_LABEL="Show Translations Card" +COM_GETBIBLE_CONFIG_SHOW_TRANSLATIONS_ICON_LABEL="Show Translations Icon" +COM_GETBIBLE_CONFIG_SHOW_TRANSLATIONS_TAB_TEXT_LABEL="Show Translations Tab Text" +COM_GETBIBLE_CONFIG_SUBNAVPILL="subnav-pill" +COM_GETBIBLE_CONFIG_TABLE_SELECTION_COLOR_DESCRIPTION="Select the table selection colour here." +COM_GETBIBLE_CONFIG_TABLE_SELECTION_COLOR_LABEL="Table Selection Colour" +COM_GETBIBLE_CONFIG_TABS="tabs" +COM_GETBIBLE_CONFIG_TAG="Tag" +COM_GETBIBLE_CONFIG_TEXT_REFERENCE_SHARE_LABEL="Text Reference Share" +COM_GETBIBLE_CONFIG_TOP="Top" +COM_GETBIBLE_CONFIG_TOP_MENU_TYPE_LABEL="Top Menu Type" +COM_GETBIBLE_CONFIG_TRANSLATIONS_CARD_STYLE_LABEL="Translations Card Style" +COM_GETBIBLE_CONFIG_TRANSLATIONS_ICON_DESCRIPTION="Set the translations custom icon" +COM_GETBIBLE_CONFIG_TRANSLATIONS_ICON_HINT="world" +COM_GETBIBLE_CONFIG_TRANSLATIONS_ICON_LABEL="Translations Icon" +COM_GETBIBLE_CONFIG_TRANSLATIONS_ICON_MESSAGE="Error! Please add some icon name here." +COM_GETBIBLE_CONFIG_TRANSLATIONS_TAB_DESCRIPTION="The translations tab name" +COM_GETBIBLE_CONFIG_TRANSLATIONS_TAB_HINT="Translations" +COM_GETBIBLE_CONFIG_TRANSLATIONS_TAB_LABEL="Translations Tab" +COM_GETBIBLE_CONFIG_TRANSLATIONS_TAB_MESSAGE="Error! Please add some name here." +COM_GETBIBLE_CONFIG_TYPE_TRANSLATION_SHARE_LABEL="Type Translation Share" +COM_GETBIBLE_CONFIG_UIKIT_DESC="The Parameters for the uikit are set here.
Uikit is a lightweight and modular front-end frameworkfor developing fast and powerful web interfaces. For more info visit https://getuikit.com/" +COM_GETBIBLE_CONFIG_UIKIT_LABEL="Uikit3 Settings" +COM_GETBIBLE_CONFIG_UIKIT_LOAD_DESC="Set the uikit loading option." +COM_GETBIBLE_CONFIG_UIKIT_LOAD_LABEL="Loading Options" +COM_GETBIBLE_CONFIG_UIKIT_MIN_DESC="Should the minified version of uikit files be loaded?" +COM_GETBIBLE_CONFIG_UIKIT_MIN_LABEL="Load Minified" +COM_GETBIBLE_CONFIG_VERSE_LAYOUT_SHARE_LABEL="Verse Layout Share" +COM_GETBIBLE_CONFIG_VERSE_NUMBER_SHARE_LABEL="Verse Number Share" +COM_GETBIBLE_CONFIG_VERSE_PER_LINE_DESCRIPTION="Load each Verse on its own line" +COM_GETBIBLE_CONFIG_VERSE_PER_LINE_LABEL="Verse Per Line" +COM_GETBIBLE_CONFIG_VERSE_SELECTED_COLOR_DESCRIPTION="Select the verse selected colour here." +COM_GETBIBLE_CONFIG_VERSE_SELECTED_COLOR_LABEL="Verse Selected Colour" +COM_GETBIBLE_CONFIG_YES="Yes" +COM_GETBIBLE_CONTRIBUTOR="Contributor" +COM_GETBIBLE_CONTRIBUTORS="Contributors" +COM_GETBIBLE_CREATE_NEW_S="Create New %s" +COM_GETBIBLE_DASH="Dashboard" +COM_GETBIBLE_DASHBOARD="Get Bible Dashboard" +COM_GETBIBLE_DASHBOARD_BOOKS="Books

" +COM_GETBIBLE_DASHBOARD_CHAPTERS="Chapters

" +COM_GETBIBLE_DASHBOARD_LINKERS="Linkers

" +COM_GETBIBLE_DASHBOARD_NOTES="Notes

" +COM_GETBIBLE_DASHBOARD_OPEN_AI_RESPONSES="Open Ai Responses

" +COM_GETBIBLE_DASHBOARD_PROMPTS="Prompts

" +COM_GETBIBLE_DASHBOARD_TAGGED_VERSES="Tagged Verses

" +COM_GETBIBLE_DASHBOARD_TAGS="Tags

" +COM_GETBIBLE_DASHBOARD_TRANSLATIONS="Translations

" +COM_GETBIBLE_DASHBOARD_VERSES="Verses

" +COM_GETBIBLE_DATE="Date" +COM_GETBIBLE_DOWNLOAD_UPDATE="Download Update" +COM_GETBIBLE_EDIT_CREATED_BY="Edit Created By" +COM_GETBIBLE_EDIT_CREATED_BY_DESC="Allows users in this group to edit created by." +COM_GETBIBLE_EDIT_CREATED_DATE="Edit Created Date" +COM_GETBIBLE_EDIT_CREATED_DATE_DESC="Allows users in this group to edit created date." +COM_GETBIBLE_EDIT_S="Edit %s" +COM_GETBIBLE_EDIT_VERSIONS="Edit Version" +COM_GETBIBLE_EDIT_VERSIONS_DESC="Allows users in this group to edit versions." +COM_GETBIBLE_EMPTY_TRASH="Empty trash" +COM_GETBIBLE_EXIT_TRASH="Exit trash" +COM_GETBIBLE_FAVOURITE_VERSE_COULD_NOT_BE_CHANGED="Favourite verse could not be changed." +COM_GETBIBLE_FAVOURITE_VERSE_COULD_NOT_BE_STORED="Favourite verse could not be stored." +COM_GETBIBLE_FAVOURITE_VERSE_SUCCESSFULLY_SET="Favourite verse successfully set." +COM_GETBIBLE_FILTER_ABBREVIATION_ASCENDING="Abbreviation ascending" +COM_GETBIBLE_FILTER_ABBREVIATION_DESCENDING="Abbreviation descending" +COM_GETBIBLE_FILTER_ACCESS_ASCENDING="Access ascending" +COM_GETBIBLE_FILTER_ACCESS_DESCENDING="Access descending" +COM_GETBIBLE_FILTER_BOOK_NUMBER_ASCENDING="Book Number ascending" +COM_GETBIBLE_FILTER_BOOK_NUMBER_DESCENDING="Book Number descending" +COM_GETBIBLE_FILTER_CACHE_BEHAVIOUR_ASCENDING="Cache Behaviour ascending" +COM_GETBIBLE_FILTER_CACHE_BEHAVIOUR_DESCENDING="Cache Behaviour descending" +COM_GETBIBLE_FILTER_CHAPTER_ASCENDING="Chapter ascending" +COM_GETBIBLE_FILTER_CHAPTER_DESCENDING="Chapter descending" +COM_GETBIBLE_FILTER_DIRECTIONAL_ASCENDING="Directional ascending" +COM_GETBIBLE_FILTER_DIRECTIONAL_DESCENDING="Directional descending" +COM_GETBIBLE_FILTER_LANGUAGE_ASCENDING="Language ascending" +COM_GETBIBLE_FILTER_LANGUAGE_DESCENDING="Language descending" +COM_GETBIBLE_FILTER_LINKER_ASCENDING="Linker ascending" +COM_GETBIBLE_FILTER_LINKER_DESCENDING="Linker descending" +COM_GETBIBLE_FILTER_MODEL_ASCENDING="Model ascending" +COM_GETBIBLE_FILTER_MODEL_DESCENDING="Model descending" +COM_GETBIBLE_FILTER_NAME_ASCENDING="Name ascending" +COM_GETBIBLE_FILTER_NAME_DESCENDING="Name descending" +COM_GETBIBLE_FILTER_NUMBER_ASCENDING="Number ascending" +COM_GETBIBLE_FILTER_NUMBER_DESCENDING="Number descending" +COM_GETBIBLE_FILTER_OPEN_AI_RESPONSE_ASCENDING="Open AI Response ascending" +COM_GETBIBLE_FILTER_OPEN_AI_RESPONSE_DESCENDING="Open AI Response descending" +COM_GETBIBLE_FILTER_PROMPT_ASCENDING="Prompt ascending" +COM_GETBIBLE_FILTER_PROMPT_DESCENDING="Prompt descending" +COM_GETBIBLE_FILTER_PROMPT_INTEGRATION_SCOPE_ASCENDING="Prompt Integration Scope ascending" +COM_GETBIBLE_FILTER_PROMPT_INTEGRATION_SCOPE_DESCENDING="Prompt Integration Scope descending" +COM_GETBIBLE_FILTER_PUBLISHED="Status" +COM_GETBIBLE_FILTER_PUBLISHED_BOOKS="Status options for books" +COM_GETBIBLE_FILTER_PUBLISHED_CHAPTERS="Status options for chapters" +COM_GETBIBLE_FILTER_PUBLISHED_LINKERS="Status options for linkers" +COM_GETBIBLE_FILTER_PUBLISHED_NOTES="Status options for notes" +COM_GETBIBLE_FILTER_PUBLISHED_OPEN_AI_MESSAGES="Status options for open ai messages" +COM_GETBIBLE_FILTER_PUBLISHED_OPEN_AI_RESPONSES="Status options for open ai responses" +COM_GETBIBLE_FILTER_PUBLISHED_PASSWORDS="Status options for passwords" +COM_GETBIBLE_FILTER_PUBLISHED_PROMPTS="Status options for prompts" +COM_GETBIBLE_FILTER_PUBLISHED_TAGGED_VERSES="Status options for tagged verses" +COM_GETBIBLE_FILTER_PUBLISHED_TAGS="Status options for tags" +COM_GETBIBLE_FILTER_PUBLISHED_TRANSLATIONS="Status options for translations" +COM_GETBIBLE_FILTER_PUBLISHED_VERSES="Status options for verses" +COM_GETBIBLE_FILTER_RESPONSE_ID_ASCENDING="Response ID ascending" +COM_GETBIBLE_FILTER_RESPONSE_ID_DESCENDING="Response ID descending" +COM_GETBIBLE_FILTER_RESPONSE_MODEL_ASCENDING="Response model ascending" +COM_GETBIBLE_FILTER_RESPONSE_MODEL_DESCENDING="Response model descending" +COM_GETBIBLE_FILTER_RESPONSE_OBJECT_ENDPOINT_ASCENDING="Response object (end-point) ascending" +COM_GETBIBLE_FILTER_RESPONSE_OBJECT_ENDPOINT_DESCENDING="Response object (end-point) descending" +COM_GETBIBLE_FILTER_ROLE_ASCENDING="Role ascending" +COM_GETBIBLE_FILTER_ROLE_DESCENDING="Role descending" +COM_GETBIBLE_FILTER_SEARCH="Searchlinkers" +COM_GETBIBLE_FILTER_SEARCH_BOOKS="Search the book items. Prefix with ID: to search for an item by ID." +COM_GETBIBLE_FILTER_SEARCH_CHAPTERS="Search the chapter items. Prefix with ID: to search for an item by ID." +COM_GETBIBLE_FILTER_SEARCH_LINKERS="Search the linker items. Prefix with ID: to search for an item by ID." +COM_GETBIBLE_FILTER_SEARCH_NOTES="Search the note items. Prefix with ID: to search for an item by ID." +COM_GETBIBLE_FILTER_SEARCH_OPEN_AI_MESSAGES="Search the open ai message items. Prefix with ID: to search for an item by ID." +COM_GETBIBLE_FILTER_SEARCH_OPEN_AI_RESPONSES="Search the open ai response items. Prefix with ID: to search for an item by ID." +COM_GETBIBLE_FILTER_SEARCH_PASSWORDS="Search the password items. Prefix with ID: to search for an item by ID." +COM_GETBIBLE_FILTER_SEARCH_PROMPTS="Search the prompt items. Prefix with ID: to search for an item by ID." +COM_GETBIBLE_FILTER_SEARCH_TAGGED_VERSES="Search the tagged verse items. Prefix with ID: to search for an item by ID." +COM_GETBIBLE_FILTER_SEARCH_TAGS="Search the tag items. Prefix with ID: to search for an item by ID." +COM_GETBIBLE_FILTER_SEARCH_TRANSLATIONS="Search the translation items. Prefix with ID: to search for an item by ID." +COM_GETBIBLE_FILTER_SEARCH_VERSES="Search the verse items. Prefix with ID: to search for an item by ID." +COM_GETBIBLE_FILTER_SELECT_ACCESS="Select Access" +COM_GETBIBLE_FILTER_SELECT_BOOK_NUMBER="Select Book Number" +COM_GETBIBLE_FILTER_SELECT_CACHE_BEHAVIOUR="Select Cache Behaviour" +COM_GETBIBLE_FILTER_SELECT_CHAPTER="Select Chapter" +COM_GETBIBLE_FILTER_SELECT_DIRECTIONAL="Select Directional" +COM_GETBIBLE_FILTER_SELECT_LINKER="Select Linker" +COM_GETBIBLE_FILTER_SELECT_MODEL="Select Model" +COM_GETBIBLE_FILTER_SELECT_NAME="Select Name" +COM_GETBIBLE_FILTER_SELECT_NUMBER="Select Number" +COM_GETBIBLE_FILTER_SELECT_OPEN_AI_RESPONSE="Select Open AI Response" +COM_GETBIBLE_FILTER_SELECT_PROMPT="Select Prompt" +COM_GETBIBLE_FILTER_SELECT_RESPONSE_ID="Select Response ID" +COM_GETBIBLE_FILTER_SELECT_RESPONSE_MODEL="Select Response model" +COM_GETBIBLE_FILTER_SELECT_ROLE="Select Role" +COM_GETBIBLE_FILTER_SELECT_SOURCE="Select Source" +COM_GETBIBLE_FILTER_SELECT_TAG="Select Tag" +COM_GETBIBLE_FILTER_SELECT_TARGET_TRANSLATION="Select Target Translation" +COM_GETBIBLE_FILTER_SELECT_TRANSLATION="Select Translation" +COM_GETBIBLE_FILTER_SELECT_VERSE="Select Verse" +COM_GETBIBLE_FILTER_SOURCE_ASCENDING="Source ascending" +COM_GETBIBLE_FILTER_SOURCE_DESCENDING="Source descending" +COM_GETBIBLE_FILTER_TAG_ASCENDING="Tag ascending" +COM_GETBIBLE_FILTER_TAG_DESCENDING="Tag descending" +COM_GETBIBLE_FILTER_TOTAL_TOKENS_ASCENDING="Total Tokens ascending" +COM_GETBIBLE_FILTER_TOTAL_TOKENS_DESCENDING="Total Tokens descending" +COM_GETBIBLE_FILTER_TRANSLATION_ASCENDING="Translation ascending" +COM_GETBIBLE_FILTER_TRANSLATION_DESCENDING="Translation descending" +COM_GETBIBLE_FILTER_VERSE_ASCENDING="Verse ascending" +COM_GETBIBLE_FILTER_VERSE_DESCENDING="Verse descending" +COM_GETBIBLE_GET_TOKEN="Get Token" +COM_GETBIBLE_GET_TOKEN_FROM_VDM_TO_GET_UPDATE_NOTICE_AND_ADD_IT_TO_YOUR_GLOBAL_OPTIONS="Get token from VDM to get update notice, and add it to your global options." +COM_GETBIBLE_HELP_MANAGER="Help" +COM_GETBIBLE_HTWOCURL_NOT_FOUNDHTWOPPLEASE_SETUP_CURL_ON_YOUR_SYSTEM_OR_BGETBIBLEB_WILL_NOT_FUNCTION_CORRECTLYP="

Curl Not Found!

Please setup curl on your system, or getbible will not function correctly!

" +COM_GETBIBLE_INACTIVE="Inactive" +COM_GETBIBLE_INCORRECT_FAVOURITE_VERSE_SELECTED="Incorrect favourite verse selected." +COM_GETBIBLE_INVALID_SESSION_KEY_VALUE="Invalid session key value." +COM_GETBIBLE_KEEP_ORIGINAL_ACCESS="- Keep Original Access -" +COM_GETBIBLE_KEEP_ORIGINAL_CATEGORY="- Keep Original Category -" +COM_GETBIBLE_KEEP_ORIGINAL_STATE="- Keep Original State -" +COM_GETBIBLE_LICENSE="License" +COM_GETBIBLE_LINKER="Linker" +COM_GETBIBLE_LINKERS="Linkers" +COM_GETBIBLE_LINKERS_ACCESS="Linkers Access" +COM_GETBIBLE_LINKERS_ACCESS_DESC="Allows the users in this group to access access linkers" +COM_GETBIBLE_LINKERS_BATCH_OPTIONS="Batch process the selected Linkers" +COM_GETBIBLE_LINKERS_BATCH_TIP="All changes will be applied to all selected Linkers" +COM_GETBIBLE_LINKERS_BATCH_USE="Linkers Batch Use" +COM_GETBIBLE_LINKERS_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch linkers" +COM_GETBIBLE_LINKERS_CREATE="Linkers Create" +COM_GETBIBLE_LINKERS_CREATE_DESC="Allows the users in this group to create create linkers" +COM_GETBIBLE_LINKERS_DASHBOARD_LIST="Linkers Dashboard List" +COM_GETBIBLE_LINKERS_DASHBOARD_LIST_DESC="Allows the users in this group to dashboard list of linker" +COM_GETBIBLE_LINKERS_DELETE="Linkers Delete" +COM_GETBIBLE_LINKERS_DELETE_DESC="Allows the users in this group to delete delete linkers" +COM_GETBIBLE_LINKERS_EDIT="Linkers Edit" +COM_GETBIBLE_LINKERS_EDIT_CREATED_BY="Linkers Edit Created By" +COM_GETBIBLE_LINKERS_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by linkers" +COM_GETBIBLE_LINKERS_EDIT_CREATED_DATE="Linkers Edit Created Date" +COM_GETBIBLE_LINKERS_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created linkers" +COM_GETBIBLE_LINKERS_EDIT_DESC="Allows the users in this group to edit the linker" +COM_GETBIBLE_LINKERS_EDIT_GUID="Linkers Edit Guid" +COM_GETBIBLE_LINKERS_EDIT_GUID_DESC="Allows the users in this group to edit guid of linker" +COM_GETBIBLE_LINKERS_EDIT_NAME="Linkers Edit Name" +COM_GETBIBLE_LINKERS_EDIT_NAME_DESC="Allows the users in this group to edit name of linker" +COM_GETBIBLE_LINKERS_EDIT_OWN="Linkers Edit Own" +COM_GETBIBLE_LINKERS_EDIT_OWN_DESC="Allows the users in this group to edit edit own linkers created by them" +COM_GETBIBLE_LINKERS_EDIT_STATE="Linkers Edit State" +COM_GETBIBLE_LINKERS_EDIT_STATE_DESC="Allows the users in this group to update the state of the linker" +COM_GETBIBLE_LINKERS_N_ITEMS_ARCHIVED="%s Linkers archived." +COM_GETBIBLE_LINKERS_N_ITEMS_ARCHIVED_1="%s Linker archived." +COM_GETBIBLE_LINKERS_N_ITEMS_CHECKED_IN_0="No Linker successfully checked in." +COM_GETBIBLE_LINKERS_N_ITEMS_CHECKED_IN_1="%d Linker successfully checked in." +COM_GETBIBLE_LINKERS_N_ITEMS_CHECKED_IN_MORE="%d Linkers successfully checked in." +COM_GETBIBLE_LINKERS_N_ITEMS_DELETED="%s Linkers deleted." +COM_GETBIBLE_LINKERS_N_ITEMS_DELETED_1="%s Linker deleted." +COM_GETBIBLE_LINKERS_N_ITEMS_FAILED_PUBLISHING="%s Linkers failed publishing." +COM_GETBIBLE_LINKERS_N_ITEMS_FAILED_PUBLISHING_1="%s Linker failed publishing." +COM_GETBIBLE_LINKERS_N_ITEMS_FEATURED="%s Linkers featured." +COM_GETBIBLE_LINKERS_N_ITEMS_FEATURED_1="%s Linker featured." +COM_GETBIBLE_LINKERS_N_ITEMS_PUBLISHED="%s Linkers published." +COM_GETBIBLE_LINKERS_N_ITEMS_PUBLISHED_1="%s Linker published." +COM_GETBIBLE_LINKERS_N_ITEMS_TRASHED="%s Linkers trashed." +COM_GETBIBLE_LINKERS_N_ITEMS_TRASHED_1="%s Linker trashed." +COM_GETBIBLE_LINKERS_N_ITEMS_UNFEATURED="%s Linkers unfeatured." +COM_GETBIBLE_LINKERS_N_ITEMS_UNFEATURED_1="%s Linker unfeatured." +COM_GETBIBLE_LINKERS_N_ITEMS_UNPUBLISHED="%s Linkers unpublished." +COM_GETBIBLE_LINKERS_N_ITEMS_UNPUBLISHED_1="%s Linker unpublished." +COM_GETBIBLE_LINKERS_SUBMENU="Linkers Submenu" +COM_GETBIBLE_LINKERS_SUBMENU_DESC="Allows the users in this group to submenu of linker" +COM_GETBIBLE_LINKER_CREATED_BY_DESC="The user that created this Linker." +COM_GETBIBLE_LINKER_CREATED_BY_LABEL="Created By" +COM_GETBIBLE_LINKER_CREATED_DATE_DESC="The date this Linker was created." +COM_GETBIBLE_LINKER_CREATED_DATE_LABEL="Created Date" +COM_GETBIBLE_LINKER_DETAILS="Details" +COM_GETBIBLE_LINKER_EDIT="Editing the Linker" +COM_GETBIBLE_LINKER_ERROR_UNIQUE_ALIAS="Another Linker has the same alias." +COM_GETBIBLE_LINKER_GUID_DESCRIPTION="Globally Unique Identifier" +COM_GETBIBLE_LINKER_GUID_HINT="Auto Generated" +COM_GETBIBLE_LINKER_GUID_LABEL="GUID" +COM_GETBIBLE_LINKER_ID="Id" +COM_GETBIBLE_LINKER_MODIFIED_BY_DESC="The last user that modified this Linker." +COM_GETBIBLE_LINKER_MODIFIED_BY_LABEL="Modified By" +COM_GETBIBLE_LINKER_MODIFIED_DATE_DESC="The date this Linker was modified." +COM_GETBIBLE_LINKER_MODIFIED_DATE_LABEL="Modified Date" +COM_GETBIBLE_LINKER_NAME_HINT="Name Here" +COM_GETBIBLE_LINKER_NAME_LABEL="Name" +COM_GETBIBLE_LINKER_NAME_MESSAGE="Error! Please add name here." +COM_GETBIBLE_LINKER_NEW="A New Linker" +COM_GETBIBLE_LINKER_NOTES="Notes" +COM_GETBIBLE_LINKER_ORDERING_LABEL="Ordering" +COM_GETBIBLE_LINKER_PASSWORDS="Passwords" +COM_GETBIBLE_LINKER_PERMISSION="Permissions" +COM_GETBIBLE_LINKER_PUBLISHING="Publishing" +COM_GETBIBLE_LINKER_SAVE_WARNING="Alias already existed so a number was added at the end. You can re-edit the Linker to customise the alias." +COM_GETBIBLE_LINKER_STATUS="Status" +COM_GETBIBLE_LINKER_TAGS="Tags" +COM_GETBIBLE_LINKER_VERSION_DESC="A count of the number of times this Linker has been revised." +COM_GETBIBLE_LINKER_VERSION_LABEL="Version" +COM_GETBIBLE_NEW="New" +COM_GETBIBLE_NOTE="Note" +COM_GETBIBLE_NOTES="Notes" +COM_GETBIBLE_NOTES_ACCESS="Notes Access" +COM_GETBIBLE_NOTES_ACCESS_DESC="Allows the users in this group to access access notes" +COM_GETBIBLE_NOTES_BATCH_OPTIONS="Batch process the selected Notes" +COM_GETBIBLE_NOTES_BATCH_TIP="All changes will be applied to all selected Notes" +COM_GETBIBLE_NOTES_BATCH_USE="Notes Batch Use" +COM_GETBIBLE_NOTES_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch notes" +COM_GETBIBLE_NOTES_CREATE="Notes Create" +COM_GETBIBLE_NOTES_CREATE_DESC="Allows the users in this group to create create notes" +COM_GETBIBLE_NOTES_DASHBOARD_LIST="Notes Dashboard List" +COM_GETBIBLE_NOTES_DASHBOARD_LIST_DESC="Allows the users in this group to dashboard list of note" +COM_GETBIBLE_NOTES_DELETE="Notes Delete" +COM_GETBIBLE_NOTES_DELETE_DESC="Allows the users in this group to delete delete notes" +COM_GETBIBLE_NOTES_EDIT="Notes Edit" +COM_GETBIBLE_NOTES_EDIT_ACCESS="Notes Edit Access" +COM_GETBIBLE_NOTES_EDIT_ACCESS_DESC="Allows the users in this group to change the access of the edit access notes" +COM_GETBIBLE_NOTES_EDIT_BOOK_NR="Notes Edit Book Nr" +COM_GETBIBLE_NOTES_EDIT_BOOK_NR_DESC="Allows the users in this group to edit book nr of note" +COM_GETBIBLE_NOTES_EDIT_CHAPTER="Notes Edit Chapter" +COM_GETBIBLE_NOTES_EDIT_CHAPTER_DESC="Allows the users in this group to edit chapter of note" +COM_GETBIBLE_NOTES_EDIT_CREATED_BY="Notes Edit Created By" +COM_GETBIBLE_NOTES_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by notes" +COM_GETBIBLE_NOTES_EDIT_CREATED_DATE="Notes Edit Created Date" +COM_GETBIBLE_NOTES_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created notes" +COM_GETBIBLE_NOTES_EDIT_DESC="Allows the users in this group to edit the note" +COM_GETBIBLE_NOTES_EDIT_GUID="Notes Edit Guid" +COM_GETBIBLE_NOTES_EDIT_GUID_DESC="Allows the users in this group to edit guid of note" +COM_GETBIBLE_NOTES_EDIT_LINKER="Notes Edit Linker" +COM_GETBIBLE_NOTES_EDIT_LINKER_DESC="Allows the users in this group to edit linker of note" +COM_GETBIBLE_NOTES_EDIT_NOTE="Notes Edit Note" +COM_GETBIBLE_NOTES_EDIT_NOTE_DESC="Allows the users in this group to edit note of note" +COM_GETBIBLE_NOTES_EDIT_OWN="Notes Edit Own" +COM_GETBIBLE_NOTES_EDIT_OWN_DESC="Allows the users in this group to edit edit own notes created by them" +COM_GETBIBLE_NOTES_EDIT_STATE="Notes Edit State" +COM_GETBIBLE_NOTES_EDIT_STATE_DESC="Allows the users in this group to update the state of the note" +COM_GETBIBLE_NOTES_EDIT_VERSE="Notes Edit Verse" +COM_GETBIBLE_NOTES_EDIT_VERSE_DESC="Allows the users in this group to edit verse of note" +COM_GETBIBLE_NOTES_EDIT_VERSION="Notes Edit Version" +COM_GETBIBLE_NOTES_EDIT_VERSION_DESC="Allows users in this group to edit versions of version notes" +COM_GETBIBLE_NOTES_N_ITEMS_ARCHIVED="%s Notes archived." +COM_GETBIBLE_NOTES_N_ITEMS_ARCHIVED_1="%s Note archived." +COM_GETBIBLE_NOTES_N_ITEMS_CHECKED_IN_0="No Note successfully checked in." +COM_GETBIBLE_NOTES_N_ITEMS_CHECKED_IN_1="%d Note successfully checked in." +COM_GETBIBLE_NOTES_N_ITEMS_CHECKED_IN_MORE="%d Notes successfully checked in." +COM_GETBIBLE_NOTES_N_ITEMS_DELETED="%s Notes deleted." +COM_GETBIBLE_NOTES_N_ITEMS_DELETED_1="%s Note deleted." +COM_GETBIBLE_NOTES_N_ITEMS_FAILED_PUBLISHING="%s Notes failed publishing." +COM_GETBIBLE_NOTES_N_ITEMS_FAILED_PUBLISHING_1="%s Note failed publishing." +COM_GETBIBLE_NOTES_N_ITEMS_FEATURED="%s Notes featured." +COM_GETBIBLE_NOTES_N_ITEMS_FEATURED_1="%s Note featured." +COM_GETBIBLE_NOTES_N_ITEMS_PUBLISHED="%s Notes published." +COM_GETBIBLE_NOTES_N_ITEMS_PUBLISHED_1="%s Note published." +COM_GETBIBLE_NOTES_N_ITEMS_TRASHED="%s Notes trashed." +COM_GETBIBLE_NOTES_N_ITEMS_TRASHED_1="%s Note trashed." +COM_GETBIBLE_NOTES_N_ITEMS_UNFEATURED="%s Notes unfeatured." +COM_GETBIBLE_NOTES_N_ITEMS_UNFEATURED_1="%s Note unfeatured." +COM_GETBIBLE_NOTES_N_ITEMS_UNPUBLISHED="%s Notes unpublished." +COM_GETBIBLE_NOTES_N_ITEMS_UNPUBLISHED_1="%s Note unpublished." +COM_GETBIBLE_NOTES_SUBMENU="Notes Submenu" +COM_GETBIBLE_NOTES_SUBMENU_DESC="Allows the users in this group to submenu of note" +COM_GETBIBLE_NOTE_ACCESS_LABEL="Access" +COM_GETBIBLE_NOTE_ALREADY_EXIST_BUT_COULD_NOT_BE_REACTIVATED="Note already exist, but could not be reactivated." +COM_GETBIBLE_NOTE_ALREADY_EXIST_BUT_COULD_NOT_UPDATE_THE_NOTE_TEXT="Note already exist, but could not update the note text." +COM_GETBIBLE_NOTE_BOOK_NR_DESCRIPTION="Select the book number" +COM_GETBIBLE_NOTE_BOOK_NR_LABEL="Book Number" +COM_GETBIBLE_NOTE_CHAPTER_DESCRIPTION="Select the chapter number" +COM_GETBIBLE_NOTE_CHAPTER_LABEL="Chapter" +COM_GETBIBLE_NOTE_CREATED_BY_DESC="The user that created this Note." +COM_GETBIBLE_NOTE_CREATED_BY_LABEL="Created By" +COM_GETBIBLE_NOTE_CREATED_DATE_DESC="The date this Note was created." +COM_GETBIBLE_NOTE_CREATED_DATE_LABEL="Created Date" +COM_GETBIBLE_NOTE_DETAILS="Details" +COM_GETBIBLE_NOTE_EDIT="Editing the Note" +COM_GETBIBLE_NOTE_ERROR_UNIQUE_ALIAS="Another Note has the same alias." +COM_GETBIBLE_NOTE_GUID_DESCRIPTION="Globally Unique Identifier" +COM_GETBIBLE_NOTE_GUID_HINT="Auto Generated" +COM_GETBIBLE_NOTE_GUID_LABEL="GUID" +COM_GETBIBLE_NOTE_ID="Id" +COM_GETBIBLE_NOTE_LINKER_DESCRIPTION="Globally Unique Linker" +COM_GETBIBLE_NOTE_LINKER_LABEL="Linker" +COM_GETBIBLE_NOTE_MODIFIED_BY_DESC="The last user that modified this Note." +COM_GETBIBLE_NOTE_MODIFIED_BY_LABEL="Modified By" +COM_GETBIBLE_NOTE_MODIFIED_DATE_DESC="The date this Note was modified." +COM_GETBIBLE_NOTE_MODIFIED_DATE_LABEL="Modified Date" +COM_GETBIBLE_NOTE_NEW="A New Note" +COM_GETBIBLE_NOTE_NOTE_DESCRIPTION="Text Area" +COM_GETBIBLE_NOTE_NOTE_HINT="add note here" +COM_GETBIBLE_NOTE_NOTE_LABEL="Text" +COM_GETBIBLE_NOTE_ORDERING_LABEL="Ordering" +COM_GETBIBLE_NOTE_PERMISSION="Permissions" +COM_GETBIBLE_NOTE_PRIVATE="Private" +COM_GETBIBLE_NOTE_PUBLIC="Public" +COM_GETBIBLE_NOTE_PUBLISHING="Publishing" +COM_GETBIBLE_NOTE_SAVE_WARNING="Alias already existed so a number was added at the end. You can re-edit the Note to customise the alias." +COM_GETBIBLE_NOTE_STATUS="Status" +COM_GETBIBLE_NOTE_VERSE_DESCRIPTION="Select the verse number" +COM_GETBIBLE_NOTE_VERSE_LABEL="Verse" +COM_GETBIBLE_NOTE_VERSION_DESC="A count of the number of times this Note has been revised." +COM_GETBIBLE_NOTE_VERSION_LABEL="Version" +COM_GETBIBLE_NOT_FOUND_OR_ACCESS_DENIED="Not found, or access denied." +COM_GETBIBLE_NO_ACCESS_GRANTED="No Access Granted!" +COM_GETBIBLE_OPEN_AI_DISABLED="Open AI (disabled)" +COM_GETBIBLE_OPEN_AI_MESSAGE="Open AI Message" +COM_GETBIBLE_OPEN_AI_MESSAGES="Open AI Messages" +COM_GETBIBLE_OPEN_AI_MESSAGES_ACCESS="Open Ai Messages Access" +COM_GETBIBLE_OPEN_AI_MESSAGES_ACCESS_DESC="Allows the users in this group to access access open ai messages" +COM_GETBIBLE_OPEN_AI_MESSAGES_BATCH_OPTIONS="Batch process the selected Open AI Messages" +COM_GETBIBLE_OPEN_AI_MESSAGES_BATCH_TIP="All changes will be applied to all selected Open AI Messages" +COM_GETBIBLE_OPEN_AI_MESSAGES_BATCH_USE="Open Ai Messages Batch Use" +COM_GETBIBLE_OPEN_AI_MESSAGES_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch open ai messages" +COM_GETBIBLE_OPEN_AI_MESSAGES_CREATE="Open Ai Messages Create" +COM_GETBIBLE_OPEN_AI_MESSAGES_CREATE_DESC="Allows the users in this group to create create open ai messages" +COM_GETBIBLE_OPEN_AI_MESSAGES_DELETE="Open Ai Messages Delete" +COM_GETBIBLE_OPEN_AI_MESSAGES_DELETE_DESC="Allows the users in this group to delete delete open ai messages" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT="Open Ai Messages Edit" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_CONTENT="Open Ai Messages Edit Content" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_CONTENT_DESC="Allows the users in this group to edit content of open ai message" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_CREATED_BY="Open Ai Messages Edit Created By" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by open ai messages" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_CREATED_DATE="Open Ai Messages Edit Created Date" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created open ai messages" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_DESC="Allows the users in this group to edit the open ai message" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_INDEX="Open Ai Messages Edit Index" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_INDEX_DESC="Allows the users in this group to edit index of open ai message" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_NAME="Open Ai Messages Edit Name" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_NAME_DESC="Allows the users in this group to edit name of open ai message" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_OPEN_AI_RESPONSE="Open Ai Messages Edit Open Ai Response" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_OPEN_AI_RESPONSE_DESC="Allows the users in this group to edit open ai response of open ai message" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_OWN="Open Ai Messages Edit Own" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_OWN_DESC="Allows the users in this group to edit edit own open ai messages created by them" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_PROMPT="Open Ai Messages Edit Prompt" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_PROMPT_DESC="Allows the users in this group to edit prompt of open ai message" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_ROLE="Open Ai Messages Edit Role" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_ROLE_DESC="Allows the users in this group to edit role of open ai message" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_SOURCE="Open Ai Messages Edit Source" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_SOURCE_DESC="Allows the users in this group to edit source of open ai message" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_STATE="Open Ai Messages Edit State" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_STATE_DESC="Allows the users in this group to update the state of the open ai message" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_VERSION="Open Ai Messages Edit Version" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_VERSION_DESC="Allows users in this group to edit versions of version open ai messages" +COM_GETBIBLE_OPEN_AI_MESSAGES_N_ITEMS_ARCHIVED="%s Open AI Messages archived." +COM_GETBIBLE_OPEN_AI_MESSAGES_N_ITEMS_ARCHIVED_1="%s Open AI Message archived." +COM_GETBIBLE_OPEN_AI_MESSAGES_N_ITEMS_CHECKED_IN_0="No Open AI Message successfully checked in." +COM_GETBIBLE_OPEN_AI_MESSAGES_N_ITEMS_CHECKED_IN_1="%d Open AI Message successfully checked in." +COM_GETBIBLE_OPEN_AI_MESSAGES_N_ITEMS_CHECKED_IN_MORE="%d Open AI Messages successfully checked in." +COM_GETBIBLE_OPEN_AI_MESSAGES_N_ITEMS_DELETED="%s Open AI Messages deleted." +COM_GETBIBLE_OPEN_AI_MESSAGES_N_ITEMS_DELETED_1="%s Open AI Message deleted." +COM_GETBIBLE_OPEN_AI_MESSAGES_N_ITEMS_FAILED_PUBLISHING="%s Open AI Messages failed publishing." +COM_GETBIBLE_OPEN_AI_MESSAGES_N_ITEMS_FAILED_PUBLISHING_1="%s Open AI Message failed publishing." +COM_GETBIBLE_OPEN_AI_MESSAGES_N_ITEMS_FEATURED="%s Open AI Messages featured." +COM_GETBIBLE_OPEN_AI_MESSAGES_N_ITEMS_FEATURED_1="%s Open AI Message featured." +COM_GETBIBLE_OPEN_AI_MESSAGES_N_ITEMS_PUBLISHED="%s Open AI Messages published." +COM_GETBIBLE_OPEN_AI_MESSAGES_N_ITEMS_PUBLISHED_1="%s Open AI Message published." +COM_GETBIBLE_OPEN_AI_MESSAGES_N_ITEMS_TRASHED="%s Open AI Messages trashed." +COM_GETBIBLE_OPEN_AI_MESSAGES_N_ITEMS_TRASHED_1="%s Open AI Message trashed." +COM_GETBIBLE_OPEN_AI_MESSAGES_N_ITEMS_UNFEATURED="%s Open AI Messages unfeatured." +COM_GETBIBLE_OPEN_AI_MESSAGES_N_ITEMS_UNFEATURED_1="%s Open AI Message unfeatured." +COM_GETBIBLE_OPEN_AI_MESSAGES_N_ITEMS_UNPUBLISHED="%s Open AI Messages unpublished." +COM_GETBIBLE_OPEN_AI_MESSAGES_N_ITEMS_UNPUBLISHED_1="%s Open AI Message unpublished." +COM_GETBIBLE_OPEN_AI_MESSAGE_ASSISTANT="assistant" +COM_GETBIBLE_OPEN_AI_MESSAGE_CONTENT_HINT="the response content will go here..." +COM_GETBIBLE_OPEN_AI_MESSAGE_CONTENT_LABEL="Content" +COM_GETBIBLE_OPEN_AI_MESSAGE_CREATED_BY_DESC="The user that created this Open AI Message." +COM_GETBIBLE_OPEN_AI_MESSAGE_CREATED_BY_LABEL="Created By" +COM_GETBIBLE_OPEN_AI_MESSAGE_CREATED_DATE_DESC="The date this Open AI Message was created." +COM_GETBIBLE_OPEN_AI_MESSAGE_CREATED_DATE_LABEL="Created Date" +COM_GETBIBLE_OPEN_AI_MESSAGE_EDIT="Editing the Open AI Message" +COM_GETBIBLE_OPEN_AI_MESSAGE_ERROR_UNIQUE_ALIAS="Another Open AI Message has the same alias." +COM_GETBIBLE_OPEN_AI_MESSAGE_FUNCTION="function" +COM_GETBIBLE_OPEN_AI_MESSAGE_ID="Id" +COM_GETBIBLE_OPEN_AI_MESSAGE_INDEX_DESCRIPTION="Message index" +COM_GETBIBLE_OPEN_AI_MESSAGE_INDEX_LABEL="Index" +COM_GETBIBLE_OPEN_AI_MESSAGE_MESSAGE="Message" +COM_GETBIBLE_OPEN_AI_MESSAGE_MODIFIED_BY_DESC="The last user that modified this Open AI Message." +COM_GETBIBLE_OPEN_AI_MESSAGE_MODIFIED_BY_LABEL="Modified By" +COM_GETBIBLE_OPEN_AI_MESSAGE_MODIFIED_DATE_DESC="The date this Open AI Message was modified." +COM_GETBIBLE_OPEN_AI_MESSAGE_MODIFIED_DATE_LABEL="Modified Date" +COM_GETBIBLE_OPEN_AI_MESSAGE_NAME_DESCRIPTION="Name" +COM_GETBIBLE_OPEN_AI_MESSAGE_NAME_HINT="add the author name here... (optional)" +COM_GETBIBLE_OPEN_AI_MESSAGE_NAME_LABEL="Author" +COM_GETBIBLE_OPEN_AI_MESSAGE_NAME_MESSAGE="Error! Please add some text here." +COM_GETBIBLE_OPEN_AI_MESSAGE_NEW="A New Open AI Message" +COM_GETBIBLE_OPEN_AI_MESSAGE_OPEN_AI="Open AI" +COM_GETBIBLE_OPEN_AI_MESSAGE_OPEN_AI_RESPONSE_LABEL="Open AI Response" +COM_GETBIBLE_OPEN_AI_MESSAGE_ORDERING_LABEL="Ordering" +COM_GETBIBLE_OPEN_AI_MESSAGE_PERMISSION="Permissions" +COM_GETBIBLE_OPEN_AI_MESSAGE_PROMPT="Prompt" +COM_GETBIBLE_OPEN_AI_MESSAGE_PROMPT_LABEL="Prompt" +COM_GETBIBLE_OPEN_AI_MESSAGE_PUBLISHING="Publishing" +COM_GETBIBLE_OPEN_AI_MESSAGE_ROLE_LABEL="Role" +COM_GETBIBLE_OPEN_AI_MESSAGE_SAVE_WARNING="Alias already existed so a number was added at the end. You can re-edit the Open AI Message to customise the alias." +COM_GETBIBLE_OPEN_AI_MESSAGE_SOURCE_DESCRIPTION="Source of message" +COM_GETBIBLE_OPEN_AI_MESSAGE_SOURCE_LABEL="Source" +COM_GETBIBLE_OPEN_AI_MESSAGE_STATUS="Status" +COM_GETBIBLE_OPEN_AI_MESSAGE_SYSTEM="system" +COM_GETBIBLE_OPEN_AI_MESSAGE_USER="user" +COM_GETBIBLE_OPEN_AI_MESSAGE_VERSION_DESC="A count of the number of times this Open AI Message has been revised." +COM_GETBIBLE_OPEN_AI_MESSAGE_VERSION_LABEL="Version" +COM_GETBIBLE_OPEN_AI_RESPONSE="Open AI Response" +COM_GETBIBLE_OPEN_AI_RESPONSES="Open AI Responses" +COM_GETBIBLE_OPEN_AI_RESPONSES_ACCESS="Open Ai Responses Access" +COM_GETBIBLE_OPEN_AI_RESPONSES_ACCESS_DESC="Allows the users in this group to access access open ai responses" +COM_GETBIBLE_OPEN_AI_RESPONSES_BATCH_OPTIONS="Batch process the selected Open AI Responses" +COM_GETBIBLE_OPEN_AI_RESPONSES_BATCH_TIP="All changes will be applied to all selected Open AI Responses" +COM_GETBIBLE_OPEN_AI_RESPONSES_BATCH_USE="Open Ai Responses Batch Use" +COM_GETBIBLE_OPEN_AI_RESPONSES_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch open ai responses" +COM_GETBIBLE_OPEN_AI_RESPONSES_CREATE="Open Ai Responses Create" +COM_GETBIBLE_OPEN_AI_RESPONSES_CREATE_DESC="Allows the users in this group to create create open ai responses" +COM_GETBIBLE_OPEN_AI_RESPONSES_DASHBOARD_LIST="Open Ai Responses Dashboard List" +COM_GETBIBLE_OPEN_AI_RESPONSES_DASHBOARD_LIST_DESC="Allows the users in this group to dashboard list of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_DELETE="Open Ai Responses Delete" +COM_GETBIBLE_OPEN_AI_RESPONSES_DELETE_DESC="Allows the users in this group to delete delete open ai responses" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT="Open Ai Responses Edit" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_ABBREVIATION="Open Ai Responses Edit Abbreviation" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_ABBREVIATION_DESC="Allows the users in this group to edit abbreviation of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_BOOK="Open Ai Responses Edit Book" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_BOOK_DESC="Allows the users in this group to edit book of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_CHAPTER="Open Ai Responses Edit Chapter" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_CHAPTER_DESC="Allows the users in this group to edit chapter of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_COMPLETION_TOKENS="Open Ai Responses Edit Completion Tokens" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_COMPLETION_TOKENS_DESC="Allows the users in this group to edit completion tokens of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_CREATED_BY="Open Ai Responses Edit Created By" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by open ai responses" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_CREATED_DATE="Open Ai Responses Edit Created Date" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created open ai responses" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_DESC="Allows the users in this group to edit the open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_FREQUENCY_PENALTY="Open Ai Responses Edit Frequency Penalty" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_FREQUENCY_PENALTY_DESC="Allows the users in this group to edit frequency penalty of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_LANGUAGE="Open Ai Responses Edit Language" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_LANGUAGE_DESC="Allows the users in this group to edit language of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_LCSH="Open Ai Responses Edit Lcsh" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_LCSH_DESC="Allows the users in this group to edit lcsh of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_MAX_TOKENS="Open Ai Responses Edit Max Tokens" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_MAX_TOKENS_DESC="Allows the users in this group to edit max tokens of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_MODEL="Open Ai Responses Edit Model" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_MODEL_DESC="Allows the users in this group to edit model of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_N="Open Ai Responses Edit N" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_N_DESC="Allows the users in this group to edit n of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_OWN="Open Ai Responses Edit Own" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_OWN_DESC="Allows the users in this group to edit edit own open ai responses created by them" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_PRESENCE_PENALTY="Open Ai Responses Edit Presence Penalty" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_PRESENCE_PENALTY_DESC="Allows the users in this group to edit presence penalty of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_PROMPT="Open Ai Responses Edit Prompt" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_PROMPT_DESC="Allows the users in this group to edit prompt of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_PROMPT_TOKENS="Open Ai Responses Edit Prompt Tokens" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_PROMPT_TOKENS_DESC="Allows the users in this group to edit prompt tokens of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_RESPONSE_CREATED="Open Ai Responses Edit Response Created" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_RESPONSE_CREATED_DESC="Allows the users in this group to edit response created of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_RESPONSE_ID="Open Ai Responses Edit Response Id" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_RESPONSE_ID_DESC="Allows the users in this group to edit response id of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_RESPONSE_MODEL="Open Ai Responses Edit Response Model" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_RESPONSE_MODEL_DESC="Allows the users in this group to edit response model of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_RESPONSE_OBJECT="Open Ai Responses Edit Response Object" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_RESPONSE_OBJECT_DESC="Allows the users in this group to edit response object of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_SELECTED_WORD="Open Ai Responses Edit Selected Word" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_SELECTED_WORD_DESC="Allows the users in this group to edit selected word of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_STATE="Open Ai Responses Edit State" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_STATE_DESC="Allows the users in this group to update the state of the open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_TEMPERATURE="Open Ai Responses Edit Temperature" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_TEMPERATURE_DESC="Allows the users in this group to edit temperature of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_TOP_P="Open Ai Responses Edit Top P" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_TOP_P_DESC="Allows the users in this group to edit top p of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_TOTAL_TOKENS="Open Ai Responses Edit Total Tokens" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_TOTAL_TOKENS_DESC="Allows the users in this group to edit total tokens of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_VERSE="Open Ai Responses Edit Verse" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_VERSE_DESC="Allows the users in this group to edit verse of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_VERSION="Open Ai Responses Edit Version" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_VERSION_DESC="Allows users in this group to edit versions of version open ai responses" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_WORD="Open Ai Responses Edit Word" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_WORD_DESC="Allows the users in this group to edit word of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_N_ITEMS_ARCHIVED="%s Open AI Responses archived." +COM_GETBIBLE_OPEN_AI_RESPONSES_N_ITEMS_ARCHIVED_1="%s Open AI Response archived." +COM_GETBIBLE_OPEN_AI_RESPONSES_N_ITEMS_CHECKED_IN_0="No Open AI Response successfully checked in." +COM_GETBIBLE_OPEN_AI_RESPONSES_N_ITEMS_CHECKED_IN_1="%d Open AI Response successfully checked in." +COM_GETBIBLE_OPEN_AI_RESPONSES_N_ITEMS_CHECKED_IN_MORE="%d Open AI Responses successfully checked in." +COM_GETBIBLE_OPEN_AI_RESPONSES_N_ITEMS_DELETED="%s Open AI Responses deleted." +COM_GETBIBLE_OPEN_AI_RESPONSES_N_ITEMS_DELETED_1="%s Open AI Response deleted." +COM_GETBIBLE_OPEN_AI_RESPONSES_N_ITEMS_FAILED_PUBLISHING="%s Open AI Responses failed publishing." +COM_GETBIBLE_OPEN_AI_RESPONSES_N_ITEMS_FAILED_PUBLISHING_1="%s Open AI Response failed publishing." +COM_GETBIBLE_OPEN_AI_RESPONSES_N_ITEMS_FEATURED="%s Open AI Responses featured." +COM_GETBIBLE_OPEN_AI_RESPONSES_N_ITEMS_FEATURED_1="%s Open AI Response featured." +COM_GETBIBLE_OPEN_AI_RESPONSES_N_ITEMS_PUBLISHED="%s Open AI Responses published." +COM_GETBIBLE_OPEN_AI_RESPONSES_N_ITEMS_PUBLISHED_1="%s Open AI Response published." +COM_GETBIBLE_OPEN_AI_RESPONSES_N_ITEMS_TRASHED="%s Open AI Responses trashed." +COM_GETBIBLE_OPEN_AI_RESPONSES_N_ITEMS_TRASHED_1="%s Open AI Response trashed." +COM_GETBIBLE_OPEN_AI_RESPONSES_N_ITEMS_UNFEATURED="%s Open AI Responses unfeatured." +COM_GETBIBLE_OPEN_AI_RESPONSES_N_ITEMS_UNFEATURED_1="%s Open AI Response unfeatured." +COM_GETBIBLE_OPEN_AI_RESPONSES_N_ITEMS_UNPUBLISHED="%s Open AI Responses unpublished." +COM_GETBIBLE_OPEN_AI_RESPONSES_N_ITEMS_UNPUBLISHED_1="%s Open AI Response unpublished." +COM_GETBIBLE_OPEN_AI_RESPONSES_SUBMENU="Open Ai Responses Submenu" +COM_GETBIBLE_OPEN_AI_RESPONSES_SUBMENU_DESC="Allows the users in this group to submenu of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSE_ABBREVIATION_DESCRIPTION="Select a Bible translation" +COM_GETBIBLE_OPEN_AI_RESPONSE_ABBREVIATION_LABEL="Target Translation" +COM_GETBIBLE_OPEN_AI_RESPONSE_BIBLE="Bible" +COM_GETBIBLE_OPEN_AI_RESPONSE_BOOK_DESCRIPTION="The book number" +COM_GETBIBLE_OPEN_AI_RESPONSE_BOOK_HINT="Book Number" +COM_GETBIBLE_OPEN_AI_RESPONSE_BOOK_LABEL="Book" +COM_GETBIBLE_OPEN_AI_RESPONSE_CHAPTER_DESCRIPTION="The chapter number" +COM_GETBIBLE_OPEN_AI_RESPONSE_CHAPTER_HINT="Chapter Number" +COM_GETBIBLE_OPEN_AI_RESPONSE_CHAPTER_LABEL="Chapter" +COM_GETBIBLE_OPEN_AI_RESPONSE_COMPLETION_TOKENS_DESCRIPTION="Completion number of tokens used." +COM_GETBIBLE_OPEN_AI_RESPONSE_COMPLETION_TOKENS_LABEL="Completion Tokens" +COM_GETBIBLE_OPEN_AI_RESPONSE_CREATED_BY_DESC="The user that created this Open AI Response." +COM_GETBIBLE_OPEN_AI_RESPONSE_CREATED_BY_LABEL="Created By" +COM_GETBIBLE_OPEN_AI_RESPONSE_CREATED_DATE_DESC="The date this Open AI Response was created." +COM_GETBIBLE_OPEN_AI_RESPONSE_CREATED_DATE_LABEL="Created Date" +COM_GETBIBLE_OPEN_AI_RESPONSE_DETAILS="Details" +COM_GETBIBLE_OPEN_AI_RESPONSE_EDIT="Editing the Open AI Response" +COM_GETBIBLE_OPEN_AI_RESPONSE_ERROR_UNIQUE_ALIAS="Another Open AI Response has the same alias." +COM_GETBIBLE_OPEN_AI_RESPONSE_FREQUENCY_PENALTY_DESCRIPTION="Penalty for new tokens based on their frequency in the text" +COM_GETBIBLE_OPEN_AI_RESPONSE_FREQUENCY_PENALTY_LABEL="Frequency Penalty" +COM_GETBIBLE_OPEN_AI_RESPONSE_GPT35TURBO="gpt-3.5-turbo" +COM_GETBIBLE_OPEN_AI_RESPONSE_GPT35TURBO0613="gpt-3.5-turbo-0613" +COM_GETBIBLE_OPEN_AI_RESPONSE_GPT35TURBO16K="gpt-3.5-turbo-16k" +COM_GETBIBLE_OPEN_AI_RESPONSE_GPT35TURBO16K0613="gpt-3.5-turbo-16k-0613" +COM_GETBIBLE_OPEN_AI_RESPONSE_GPT4="gpt-4" +COM_GETBIBLE_OPEN_AI_RESPONSE_GPT40613="gpt-4-0613" +COM_GETBIBLE_OPEN_AI_RESPONSE_GPT432K="gpt-4-32k" +COM_GETBIBLE_OPEN_AI_RESPONSE_GPT432K0613="gpt-4-32k-0613" +COM_GETBIBLE_OPEN_AI_RESPONSE_ID="Id" +COM_GETBIBLE_OPEN_AI_RESPONSE_LANGUAGE_DESCRIPTION="The translation language" +COM_GETBIBLE_OPEN_AI_RESPONSE_LANGUAGE_HINT="Language" +COM_GETBIBLE_OPEN_AI_RESPONSE_LANGUAGE_LABEL="Language" +COM_GETBIBLE_OPEN_AI_RESPONSE_LCSH_DESCRIPTION="The library of congress subject headings" +COM_GETBIBLE_OPEN_AI_RESPONSE_LCSH_HINT="LCSH" +COM_GETBIBLE_OPEN_AI_RESPONSE_LCSH_LABEL="LCSH" +COM_GETBIBLE_OPEN_AI_RESPONSE_MAX_TOKENS_DESCRIPTION="Maximum number of tokens to generate." +COM_GETBIBLE_OPEN_AI_RESPONSE_MAX_TOKENS_LABEL="Max Tokens" +COM_GETBIBLE_OPEN_AI_RESPONSE_MESSAGE="Message" +COM_GETBIBLE_OPEN_AI_RESPONSE_MODEL_DESCRIPTION="ID of the model to use." +COM_GETBIBLE_OPEN_AI_RESPONSE_MODEL_LABEL="Model" +COM_GETBIBLE_OPEN_AI_RESPONSE_MODIFIED_BY_DESC="The last user that modified this Open AI Response." +COM_GETBIBLE_OPEN_AI_RESPONSE_MODIFIED_BY_LABEL="Modified By" +COM_GETBIBLE_OPEN_AI_RESPONSE_MODIFIED_DATE_DESC="The date this Open AI Response was modified." +COM_GETBIBLE_OPEN_AI_RESPONSE_MODIFIED_DATE_LABEL="Modified Date" +COM_GETBIBLE_OPEN_AI_RESPONSE_NEW="A New Open AI Response" +COM_GETBIBLE_OPEN_AI_RESPONSE_N_DESCRIPTION="The number of chat completion choices to generate" +COM_GETBIBLE_OPEN_AI_RESPONSE_N_LABEL="Number AI Response Per/Prompt" +COM_GETBIBLE_OPEN_AI_RESPONSE_ORDERING_LABEL="Ordering" +COM_GETBIBLE_OPEN_AI_RESPONSE_PERMISSION="Permissions" +COM_GETBIBLE_OPEN_AI_RESPONSE_PRESENCE_PENALTY_DESCRIPTION="Penalty for new tokens based on whether they appear in the text" +COM_GETBIBLE_OPEN_AI_RESPONSE_PRESENCE_PENALTY_LABEL="Presence Penalty" +COM_GETBIBLE_OPEN_AI_RESPONSE_PROMPT="Prompt" +COM_GETBIBLE_OPEN_AI_RESPONSE_PROMPT_LABEL="Prompt" +COM_GETBIBLE_OPEN_AI_RESPONSE_PROMPT_TOKENS_DESCRIPTION="Prompt number of tokens used." +COM_GETBIBLE_OPEN_AI_RESPONSE_PROMPT_TOKENS_LABEL="Prompt Tokens" +COM_GETBIBLE_OPEN_AI_RESPONSE_PUBLISHING="Publishing" +COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_CREATED_DESCRIPTION="The response created" +COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_CREATED_HINT="a time stamp" +COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_CREATED_LABEL="Response created" +COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_ID_DESCRIPTION="The response ID" +COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_ID_HINT="auto assigned id" +COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_ID_LABEL="Response ID" +COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_ID_MESSAGE="Error! Please add some text here." +COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_MODEL_DESCRIPTION="The response model" +COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_MODEL_HINT="gpt-4" +COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_MODEL_LABEL="Response model" +COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_OBJECT_DESCRIPTION="The response object" +COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_OBJECT_HINT="end-point" +COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_OBJECT_LABEL="Response object (end-point)" +COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_OBJECT_MESSAGE="Error! Please add some text here." +COM_GETBIBLE_OPEN_AI_RESPONSE_SAVE_WARNING="Alias already existed so a number was added at the end. You can re-edit the Open AI Response to customise the alias." +COM_GETBIBLE_OPEN_AI_RESPONSE_SELECTED_WORD_DESCRIPTION="The word/s selected" +COM_GETBIBLE_OPEN_AI_RESPONSE_SELECTED_WORD_HINT="Actual Selected Word/s" +COM_GETBIBLE_OPEN_AI_RESPONSE_SELECTED_WORD_LABEL="Selected Word/s" +COM_GETBIBLE_OPEN_AI_RESPONSE_STATUS="Status" +COM_GETBIBLE_OPEN_AI_RESPONSE_TEMPERATURE_DESCRIPTION="The sampling temperature to use" +COM_GETBIBLE_OPEN_AI_RESPONSE_TEMPERATURE_LABEL="Temperature" +COM_GETBIBLE_OPEN_AI_RESPONSE_TOP_P_DESCRIPTION="The nucleus sampling parameter" +COM_GETBIBLE_OPEN_AI_RESPONSE_TOP_P_LABEL="Top P" +COM_GETBIBLE_OPEN_AI_RESPONSE_TOTAL_TOKENS_DESCRIPTION="Total number of tokens used." +COM_GETBIBLE_OPEN_AI_RESPONSE_TOTAL_TOKENS_LABEL="Total Tokens" +COM_GETBIBLE_OPEN_AI_RESPONSE_VERSE_DESCRIPTION="The verse numbers" +COM_GETBIBLE_OPEN_AI_RESPONSE_VERSE_HINT="Verse Numbers" +COM_GETBIBLE_OPEN_AI_RESPONSE_VERSE_LABEL="Verse" +COM_GETBIBLE_OPEN_AI_RESPONSE_VERSION_DESC="A count of the number of times this Open AI Response has been revised." +COM_GETBIBLE_OPEN_AI_RESPONSE_VERSION_LABEL="Version" +COM_GETBIBLE_OPEN_AI_RESPONSE_WORD_DESCRIPTION="The word/s numbers" +COM_GETBIBLE_OPEN_AI_RESPONSE_WORD_HINT="Word/s Number/s" +COM_GETBIBLE_OPEN_AI_RESPONSE_WORD_LABEL="Word/s" +COM_GETBIBLE_OUT_OF_DATE="Out of date" +COM_GETBIBLE_PASSWORD="Password" +COM_GETBIBLE_PASSWORDS="Passwords" +COM_GETBIBLE_PASSWORDS_ACCESS="Passwords Access" +COM_GETBIBLE_PASSWORDS_ACCESS_DESC="Allows the users in this group to access access passwords" +COM_GETBIBLE_PASSWORDS_ACCESS_PASSWORD="Passwords Access Password" +COM_GETBIBLE_PASSWORDS_ACCESS_PASSWORD_DESC="Allows the users in this group to access password of password" +COM_GETBIBLE_PASSWORDS_BATCH_OPTIONS="Batch process the selected Passwords" +COM_GETBIBLE_PASSWORDS_BATCH_TIP="All changes will be applied to all selected Passwords" +COM_GETBIBLE_PASSWORDS_BATCH_USE="Passwords Batch Use" +COM_GETBIBLE_PASSWORDS_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch passwords" +COM_GETBIBLE_PASSWORDS_CREATE="Passwords Create" +COM_GETBIBLE_PASSWORDS_CREATE_DESC="Allows the users in this group to create create passwords" +COM_GETBIBLE_PASSWORDS_DELETE="Passwords Delete" +COM_GETBIBLE_PASSWORDS_DELETE_DESC="Allows the users in this group to delete delete passwords" +COM_GETBIBLE_PASSWORDS_EDIT="Passwords Edit" +COM_GETBIBLE_PASSWORDS_EDIT_CREATED_BY="Passwords Edit Created By" +COM_GETBIBLE_PASSWORDS_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by passwords" +COM_GETBIBLE_PASSWORDS_EDIT_CREATED_DATE="Passwords Edit Created Date" +COM_GETBIBLE_PASSWORDS_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created passwords" +COM_GETBIBLE_PASSWORDS_EDIT_DESC="Allows the users in this group to edit the password" +COM_GETBIBLE_PASSWORDS_EDIT_GUID="Passwords Edit Guid" +COM_GETBIBLE_PASSWORDS_EDIT_GUID_DESC="Allows the users in this group to edit guid of password" +COM_GETBIBLE_PASSWORDS_EDIT_LINKER="Passwords Edit Linker" +COM_GETBIBLE_PASSWORDS_EDIT_LINKER_DESC="Allows the users in this group to edit linker of password" +COM_GETBIBLE_PASSWORDS_EDIT_NAME="Passwords Edit Name" +COM_GETBIBLE_PASSWORDS_EDIT_NAME_DESC="Allows the users in this group to edit name of password" +COM_GETBIBLE_PASSWORDS_EDIT_OWN="Passwords Edit Own" +COM_GETBIBLE_PASSWORDS_EDIT_OWN_DESC="Allows the users in this group to edit edit own passwords created by them" +COM_GETBIBLE_PASSWORDS_EDIT_PASSWORD="Passwords Edit Password" +COM_GETBIBLE_PASSWORDS_EDIT_PASSWORD_DESC="Allows the users in this group to edit password of password" +COM_GETBIBLE_PASSWORDS_EDIT_STATE="Passwords Edit State" +COM_GETBIBLE_PASSWORDS_EDIT_STATE_DESC="Allows the users in this group to update the state of the password" +COM_GETBIBLE_PASSWORDS_N_ITEMS_ARCHIVED="%s Passwords archived." +COM_GETBIBLE_PASSWORDS_N_ITEMS_ARCHIVED_1="%s Password archived." +COM_GETBIBLE_PASSWORDS_N_ITEMS_CHECKED_IN_0="No Password successfully checked in." +COM_GETBIBLE_PASSWORDS_N_ITEMS_CHECKED_IN_1="%d Password successfully checked in." +COM_GETBIBLE_PASSWORDS_N_ITEMS_CHECKED_IN_MORE="%d Passwords successfully checked in." +COM_GETBIBLE_PASSWORDS_N_ITEMS_DELETED="%s Passwords deleted." +COM_GETBIBLE_PASSWORDS_N_ITEMS_DELETED_1="%s Password deleted." +COM_GETBIBLE_PASSWORDS_N_ITEMS_FAILED_PUBLISHING="%s Passwords failed publishing." +COM_GETBIBLE_PASSWORDS_N_ITEMS_FAILED_PUBLISHING_1="%s Password failed publishing." +COM_GETBIBLE_PASSWORDS_N_ITEMS_FEATURED="%s Passwords featured." +COM_GETBIBLE_PASSWORDS_N_ITEMS_FEATURED_1="%s Password featured." +COM_GETBIBLE_PASSWORDS_N_ITEMS_PUBLISHED="%s Passwords published." +COM_GETBIBLE_PASSWORDS_N_ITEMS_PUBLISHED_1="%s Password published." +COM_GETBIBLE_PASSWORDS_N_ITEMS_TRASHED="%s Passwords trashed." +COM_GETBIBLE_PASSWORDS_N_ITEMS_TRASHED_1="%s Password trashed." +COM_GETBIBLE_PASSWORDS_N_ITEMS_UNFEATURED="%s Passwords unfeatured." +COM_GETBIBLE_PASSWORDS_N_ITEMS_UNFEATURED_1="%s Password unfeatured." +COM_GETBIBLE_PASSWORDS_N_ITEMS_UNPUBLISHED="%s Passwords unpublished." +COM_GETBIBLE_PASSWORDS_N_ITEMS_UNPUBLISHED_1="%s Password unpublished." +COM_GETBIBLE_PASSWORDS_VIEW_PASSWORD="Passwords View Password" +COM_GETBIBLE_PASSWORDS_VIEW_PASSWORD_DESC="Allows the users in this group to view password of password" +COM_GETBIBLE_PASSWORD_CREATED_BY_DESC="The user that created this Password." +COM_GETBIBLE_PASSWORD_CREATED_BY_LABEL="Created By" +COM_GETBIBLE_PASSWORD_CREATED_DATE_DESC="The date this Password was created." +COM_GETBIBLE_PASSWORD_CREATED_DATE_LABEL="Created Date" +COM_GETBIBLE_PASSWORD_DETAILS="Details" +COM_GETBIBLE_PASSWORD_EDIT="Editing the Password" +COM_GETBIBLE_PASSWORD_ERROR_UNIQUE_ALIAS="Another Password has the same alias." +COM_GETBIBLE_PASSWORD_GUID_DESCRIPTION="Globally Unique Identifier" +COM_GETBIBLE_PASSWORD_GUID_HINT="Auto Generated" +COM_GETBIBLE_PASSWORD_GUID_LABEL="GUID" +COM_GETBIBLE_PASSWORD_ID="Id" +COM_GETBIBLE_PASSWORD_LINKER_DESCRIPTION="Globally Unique Linker" +COM_GETBIBLE_PASSWORD_LINKER_LABEL="Linker" +COM_GETBIBLE_PASSWORD_MODIFIED_BY_DESC="The last user that modified this Password." +COM_GETBIBLE_PASSWORD_MODIFIED_BY_LABEL="Modified By" +COM_GETBIBLE_PASSWORD_MODIFIED_DATE_DESC="The date this Password was modified." +COM_GETBIBLE_PASSWORD_MODIFIED_DATE_LABEL="Modified Date" +COM_GETBIBLE_PASSWORD_NAME_HINT="Name Here" +COM_GETBIBLE_PASSWORD_NAME_LABEL="Name" +COM_GETBIBLE_PASSWORD_NAME_MESSAGE="Error! Please add name here." +COM_GETBIBLE_PASSWORD_NEW="A New Password" +COM_GETBIBLE_PASSWORD_ORDERING_LABEL="Ordering" +COM_GETBIBLE_PASSWORD_PASSWORD_DESCRIPTION="Your Password" +COM_GETBIBLE_PASSWORD_PASSWORD_HINT="// share password" +COM_GETBIBLE_PASSWORD_PASSWORD_LABEL="Password" +COM_GETBIBLE_PASSWORD_PERMISSION="Permissions" +COM_GETBIBLE_PASSWORD_PUBLISHING="Publishing" +COM_GETBIBLE_PASSWORD_SAVE_WARNING="Alias already existed so a number was added at the end. You can re-edit the Password to customise the alias." +COM_GETBIBLE_PASSWORD_STATUS="Status" +COM_GETBIBLE_PASSWORD_TO_SHORT_USE_A_LONGER_PASSWORD="Password to short, use a longer password." +COM_GETBIBLE_PASSWORD_VERSION_DESC="A count of the number of times this Password has been revised." +COM_GETBIBLE_PASSWORD_VERSION_LABEL="Version" +COM_GETBIBLE_PLEASE_CHECK_AGAIN_LATTER="Please check again latter." +COM_GETBIBLE_PROMPT="Prompt" +COM_GETBIBLE_PROMPTS="Prompts" +COM_GETBIBLE_PROMPTS_ACCESS="Prompts Access" +COM_GETBIBLE_PROMPTS_ACCESS_DESC="Allows the users in this group to access access prompts" +COM_GETBIBLE_PROMPTS_ACCESS_TEMPERATURE_OVERRIDE="Prompts Access Temperature Override" +COM_GETBIBLE_PROMPTS_ACCESS_TEMPERATURE_OVERRIDE_DESC="Allows the users in this group to access temperature override of prompt" +COM_GETBIBLE_PROMPTS_BATCH_OPTIONS="Batch process the selected Prompts" +COM_GETBIBLE_PROMPTS_BATCH_TIP="All changes will be applied to all selected Prompts" +COM_GETBIBLE_PROMPTS_BATCH_USE="Prompts Batch Use" +COM_GETBIBLE_PROMPTS_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch prompts" +COM_GETBIBLE_PROMPTS_CREATE="Prompts Create" +COM_GETBIBLE_PROMPTS_CREATE_DESC="Allows the users in this group to create create prompts" +COM_GETBIBLE_PROMPTS_DASHBOARD_LIST="Prompts Dashboard List" +COM_GETBIBLE_PROMPTS_DASHBOARD_LIST_DESC="Allows the users in this group to dashboard list of prompt" +COM_GETBIBLE_PROMPTS_DELETE="Prompts Delete" +COM_GETBIBLE_PROMPTS_DELETE_DESC="Allows the users in this group to delete delete prompts" +COM_GETBIBLE_PROMPTS_EDIT="Prompts Edit" +COM_GETBIBLE_PROMPTS_EDIT_ABBREVIATION="Prompts Edit Abbreviation" +COM_GETBIBLE_PROMPTS_EDIT_ABBREVIATION_DESC="Allows the users in this group to edit abbreviation of prompt" +COM_GETBIBLE_PROMPTS_EDIT_AI_ORG_TOKEN_OVERRIDE="Prompts Edit Ai Org Token Override" +COM_GETBIBLE_PROMPTS_EDIT_AI_ORG_TOKEN_OVERRIDE_DESC="Allows the users in this group to edit ai org token override of prompt" +COM_GETBIBLE_PROMPTS_EDIT_CACHE_BEHAVIOUR="Prompts Edit Cache Behaviour" +COM_GETBIBLE_PROMPTS_EDIT_CACHE_BEHAVIOUR_DESC="Allows the users in this group to edit cache behaviour of prompt" +COM_GETBIBLE_PROMPTS_EDIT_CREATED_BY="Prompts Edit Created By" +COM_GETBIBLE_PROMPTS_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by prompts" +COM_GETBIBLE_PROMPTS_EDIT_CREATED_DATE="Prompts Edit Created Date" +COM_GETBIBLE_PROMPTS_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created prompts" +COM_GETBIBLE_PROMPTS_EDIT_DESC="Allows the users in this group to edit the prompt" +COM_GETBIBLE_PROMPTS_EDIT_FREQUENCY_PENALTY="Prompts Edit Frequency Penalty" +COM_GETBIBLE_PROMPTS_EDIT_FREQUENCY_PENALTY_DESC="Allows the users in this group to edit frequency penalty of prompt" +COM_GETBIBLE_PROMPTS_EDIT_FREQUENCY_PENALTY_OVERRIDE="Prompts Edit Frequency Penalty Override" +COM_GETBIBLE_PROMPTS_EDIT_FREQUENCY_PENALTY_OVERRIDE_DESC="Allows the users in this group to edit frequency penalty override of prompt" +COM_GETBIBLE_PROMPTS_EDIT_GUID="Prompts Edit Guid" +COM_GETBIBLE_PROMPTS_EDIT_GUID_DESC="Allows the users in this group to edit guid of prompt" +COM_GETBIBLE_PROMPTS_EDIT_INTEGRATION="Prompts Edit Integration" +COM_GETBIBLE_PROMPTS_EDIT_INTEGRATION_DESC="Allows the users in this group to edit integration of prompt" +COM_GETBIBLE_PROMPTS_EDIT_MAX_TOKENS="Prompts Edit Max Tokens" +COM_GETBIBLE_PROMPTS_EDIT_MAX_TOKENS_DESC="Allows the users in this group to edit max tokens of prompt" +COM_GETBIBLE_PROMPTS_EDIT_MAX_TOKENS_OVERRIDE="Prompts Edit Max Tokens Override" +COM_GETBIBLE_PROMPTS_EDIT_MAX_TOKENS_OVERRIDE_DESC="Allows the users in this group to edit max tokens override of prompt" +COM_GETBIBLE_PROMPTS_EDIT_MESSAGES="Prompts Edit Messages" +COM_GETBIBLE_PROMPTS_EDIT_MESSAGES_DESC="Allows the users in this group to edit messages of prompt" +COM_GETBIBLE_PROMPTS_EDIT_MODEL="Prompts Edit Model" +COM_GETBIBLE_PROMPTS_EDIT_MODEL_DESC="Allows the users in this group to edit model of prompt" +COM_GETBIBLE_PROMPTS_EDIT_N="Prompts Edit N" +COM_GETBIBLE_PROMPTS_EDIT_NAME="Prompts Edit Name" +COM_GETBIBLE_PROMPTS_EDIT_NAME_DESC="Allows the users in this group to edit name of prompt" +COM_GETBIBLE_PROMPTS_EDIT_N_DESC="Allows the users in this group to edit n of prompt" +COM_GETBIBLE_PROMPTS_EDIT_N_OVERRIDE="Prompts Edit N Override" +COM_GETBIBLE_PROMPTS_EDIT_N_OVERRIDE_DESC="Allows the users in this group to edit n override of prompt" +COM_GETBIBLE_PROMPTS_EDIT_ORG_TOKEN="Prompts Edit Org Token" +COM_GETBIBLE_PROMPTS_EDIT_ORG_TOKEN_DESC="Allows the users in this group to edit org token of prompt" +COM_GETBIBLE_PROMPTS_EDIT_OWN="Prompts Edit Own" +COM_GETBIBLE_PROMPTS_EDIT_OWN_DESC="Allows the users in this group to edit edit own prompts created by them" +COM_GETBIBLE_PROMPTS_EDIT_PRESENCE_PENALTY="Prompts Edit Presence Penalty" +COM_GETBIBLE_PROMPTS_EDIT_PRESENCE_PENALTY_DESC="Allows the users in this group to edit presence penalty of prompt" +COM_GETBIBLE_PROMPTS_EDIT_PRESENCE_PENALTY_OVERRIDE="Prompts Edit Presence Penalty Override" +COM_GETBIBLE_PROMPTS_EDIT_PRESENCE_PENALTY_OVERRIDE_DESC="Allows the users in this group to edit presence penalty override of prompt" +COM_GETBIBLE_PROMPTS_EDIT_RESPONSE_RETRIEVAL="Prompts Edit Response Retrieval" +COM_GETBIBLE_PROMPTS_EDIT_RESPONSE_RETRIEVAL_DESC="Allows the users in this group to edit response retrieval of prompt" +COM_GETBIBLE_PROMPTS_EDIT_STATE="Prompts Edit State" +COM_GETBIBLE_PROMPTS_EDIT_STATE_DESC="Allows the users in this group to update the state of the prompt" +COM_GETBIBLE_PROMPTS_EDIT_TEMPERATURE="Prompts Edit Temperature" +COM_GETBIBLE_PROMPTS_EDIT_TEMPERATURE_DESC="Allows the users in this group to edit temperature of prompt" +COM_GETBIBLE_PROMPTS_EDIT_TOKEN="Prompts Edit Token" +COM_GETBIBLE_PROMPTS_EDIT_TOKEN_DESC="Allows the users in this group to edit token of prompt" +COM_GETBIBLE_PROMPTS_EDIT_TOKEN_OVERRIDE="Prompts Edit Token Override" +COM_GETBIBLE_PROMPTS_EDIT_TOKEN_OVERRIDE_DESC="Allows the users in this group to edit token override of prompt" +COM_GETBIBLE_PROMPTS_EDIT_TOP_P="Prompts Edit Top P" +COM_GETBIBLE_PROMPTS_EDIT_TOP_P_DESC="Allows the users in this group to edit top p of prompt" +COM_GETBIBLE_PROMPTS_EDIT_TOP_P_OVERRIDE="Prompts Edit Top P Override" +COM_GETBIBLE_PROMPTS_EDIT_TOP_P_OVERRIDE_DESC="Allows the users in this group to edit top p override of prompt" +COM_GETBIBLE_PROMPTS_EDIT_VERSION="Prompts Edit Version" +COM_GETBIBLE_PROMPTS_EDIT_VERSION_DESC="Allows users in this group to edit versions of version prompts" +COM_GETBIBLE_PROMPTS_N_ITEMS_ARCHIVED="%s Prompts archived." +COM_GETBIBLE_PROMPTS_N_ITEMS_ARCHIVED_1="%s Prompt archived." +COM_GETBIBLE_PROMPTS_N_ITEMS_CHECKED_IN_0="No Prompt successfully checked in." +COM_GETBIBLE_PROMPTS_N_ITEMS_CHECKED_IN_1="%d Prompt successfully checked in." +COM_GETBIBLE_PROMPTS_N_ITEMS_CHECKED_IN_MORE="%d Prompts successfully checked in." +COM_GETBIBLE_PROMPTS_N_ITEMS_DELETED="%s Prompts deleted." +COM_GETBIBLE_PROMPTS_N_ITEMS_DELETED_1="%s Prompt deleted." +COM_GETBIBLE_PROMPTS_N_ITEMS_FAILED_PUBLISHING="%s Prompts failed publishing." +COM_GETBIBLE_PROMPTS_N_ITEMS_FAILED_PUBLISHING_1="%s Prompt failed publishing." +COM_GETBIBLE_PROMPTS_N_ITEMS_FEATURED="%s Prompts featured." +COM_GETBIBLE_PROMPTS_N_ITEMS_FEATURED_1="%s Prompt featured." +COM_GETBIBLE_PROMPTS_N_ITEMS_PUBLISHED="%s Prompts published." +COM_GETBIBLE_PROMPTS_N_ITEMS_PUBLISHED_1="%s Prompt published." +COM_GETBIBLE_PROMPTS_N_ITEMS_TRASHED="%s Prompts trashed." +COM_GETBIBLE_PROMPTS_N_ITEMS_TRASHED_1="%s Prompt trashed." +COM_GETBIBLE_PROMPTS_N_ITEMS_UNFEATURED="%s Prompts unfeatured." +COM_GETBIBLE_PROMPTS_N_ITEMS_UNFEATURED_1="%s Prompt unfeatured." +COM_GETBIBLE_PROMPTS_N_ITEMS_UNPUBLISHED="%s Prompts unpublished." +COM_GETBIBLE_PROMPTS_N_ITEMS_UNPUBLISHED_1="%s Prompt unpublished." +COM_GETBIBLE_PROMPTS_SUBMENU="Prompts Submenu" +COM_GETBIBLE_PROMPTS_SUBMENU_DESC="Allows the users in this group to submenu of prompt" +COM_GETBIBLE_PROMPT_ABBREVIATION_DESCRIPTION="Select a Bible translation" +COM_GETBIBLE_PROMPT_ABBREVIATION_LABEL="Target Translation" +COM_GETBIBLE_PROMPT_ADVANCED_CACHING_VERSECONTEX="Advanced Caching - Verse/Contex" +COM_GETBIBLE_PROMPT_AI_ORG_TOKEN_OVERRIDE_DESCRIPTION="Would you like to override the global openai organisation token value." +COM_GETBIBLE_PROMPT_AI_ORG_TOKEN_OVERRIDE_LABEL="Openai Organisation Token (override)" +COM_GETBIBLE_PROMPT_ASSISTANT="assistant" +COM_GETBIBLE_PROMPT_BASIC_CACHING_WORDSLANGUAGE="Basic Caching - Words/Language" +COM_GETBIBLE_PROMPT_CACHE_ADVANCE_NOTE_DESCRIPTION="

Recommended: Cache responses related to specific verses from a particular book, chapter, and translation. Provides more context-specific accuracy, but potentially more costly.

The "Advanced Caching - Verse/Context" strategy is our recommended choice for queries that focus on the interpretation of specific verses from a particular book, chapter, and translation of the Bible. Here's a breakdown of its operation and considerations:

  • Function: When a query is made, the system checks the cache for prior responses tied to the same verse within the same book, chapter, and translation. If a match is discovered, the cached response is delivered, improving speed while also managing costs.
  • Pros: This strategy offers improved context-specific accuracy by considering the specific verse, chapter, and book where the word or phrase is located. This results in more precise interpretations and a superior user experience.
  • Cons: As a trade-off for its higher accuracy, this method may be more costly than the "Basic Caching - Words/Language" strategy due to the necessity of caching a wider range of unique queries.
  • Recommendation: Despite the potential increased cost, we strongly advocate for this method due to its emphasis on context and accuracy.
" +COM_GETBIBLE_PROMPT_CACHE_ADVANCE_NOTE_LABEL="Discover the Advanced Caching Strategy" +COM_GETBIBLE_PROMPT_CACHE_BASIC_NOTE_DESCRIPTION="

Cache responses based on specific words or phrases within a particular language.

The "Basic Caching - Words/Language" strategy is designed to handle queries that focus on the meaning or interpretation of specific words or phrases within a given language. Here's how it works and what to consider:

  • Function: When a query is initiated, the system searches the cache to determine if the same word or phrase has been previously requested in the same language. If a match is found, the cached response is given, enhancing speed and managing costs.
  • Pros: This method can be more cost-effective and faster as it avoids repeated API calls for identical queries.
  • Cons: The major drawback of this approach is its potential for less accurate interpretations. It doesn't take into account the specific context provided by the verse, chapter, and book of the Bible where the word or phrase is found.
  • Recommendation: While this method can be efficient, for more contextually accurate responses, consider the "Advanced Caching - Verse/Context" strategy.
" +COM_GETBIBLE_PROMPT_CACHE_BASIC_NOTE_LABEL="Understand the Basic Caching Strategy" +COM_GETBIBLE_PROMPT_CACHE_BEHAVIOUR_DESCRIPTION="Determine the caching behaviour of this prompt. Be aware, this is a crucial setting that significantly impacts the prompt's operation." +COM_GETBIBLE_PROMPT_CACHE_BEHAVIOUR_LABEL="Cache Behaviour" +COM_GETBIBLE_PROMPT_CACHE_CAPACITY_DESCRIPTION="Determine the maximum number of unique responses to be stored in the cache for each word (in the 'Basic Caching - Words/Language' strategy) or each verse (in the 'Advanced Caching - Verse/Context' strategy), before additional calls to OpenAI's API are halted. This setting helps manage your usage of OpenAI's services by setting a limit on the variety of cached responses." +COM_GETBIBLE_PROMPT_CACHE_CAPACITY_LABEL="Cache Capacity" +COM_GETBIBLE_PROMPT_CACHE_CAPACITY_NOTE_DESCRIPTION="

The 'Cache Capacity' feature is an essential tool designed to help you manage the usage of OpenAI's API services more efficiently and cost-effectively. It functions by setting an upper limit on the number of unique responses that the system stores in the cache before it stops making additional calls to OpenAI's API.

In the 'Basic Caching - Words/Language' strategy, a 'unique response' refers to the cached answer to a query about a specific word or phrase in a particular language. Once the number of cached responses for each unique word or phrase reaches the defined 'Cache Capacity', the system will not initiate new API calls for that word or phrase. Instead, it will deliver already cached responses, either at random or in total, depending on your 'Response Retrieval' settings.

Similarly, in the 'Advanced Caching - Verse/Context' strategy, a 'unique response' pertains to the cached answer to a query about a specific verse from a particular book, chapter, and translation of the Bible. When the cache capacity for each unique verse is reached, the system will refrain from making new API calls for that verse, and deliver the responses from the cache, again following your 'Response Retrieval' preferences.

By using the 'Cache Capacity' feature, you gain control over the diversity of responses that are cached and reduce the potential costs of repeated API calls. Please note that the 'Cache Capacity' applies separately to each word or phrase in the basic strategy, and to each verse in the advanced strategy, allowing for fine-tuned control over the caching process.

However, keep in mind that setting the 'Cache Capacity' too low might limit the variety of responses, while setting it too high may lead to increased caching costs. Therefore, it's crucial to find a balance that suits your specific needs and the nature of your application.

" +COM_GETBIBLE_PROMPT_CACHE_CAPACITY_NOTE_LABEL="Cache Capacity Details" +COM_GETBIBLE_PROMPT_CACHE_PERSISTENTLY_EXPANSIVE_CACHING_NOTE_DESCRIPTION="

Persistently Expansive Caching Strategy

Intended for use in testing or by experienced users, this strategy always caches responses but does not use the cache to respond to subsequent queries.

Our "Persistently Expansive Caching" strategy represents a significant shift in our caching paradigms. Contrary to 'none,' where caching was non-existent, and unlike 'basic' or 'advanced,' where previous responses are used to inform future ones, this strategy stores every interaction but doesn't utilize this cache to respond to subsequent similar queries. Here are some crucial aspects to bear in mind:

  • Function: Every query initiated will invoke an API call to OpenAI, and its response will be cached. However, unlike our other strategies, the system will not use this cache to respond to future similar queries. This strategy ensures a fresh interaction with OpenAI for each query, providing unique responses each time.
  • Pros: You will have a comprehensive record of all interactions with OpenAI, helpful for deep-dive analyses, or rigorous testing scenarios. This method ensures the most recent and contextually accurate responses from OpenAI at all times.
  • Cons: This method is the most resource-intensive and expansive of our caching strategies. Each query incurs a new cost, regardless of whether the same question has been asked before. It can rapidly escalate expenses if not managed prudently.
  • Warning: We still recommend using this strategy sparingly and mostly for testing purposes due to its extensive resource and cost implications. It should be employed by experienced users who fully understand its expansive nature and have strategies to manage the associated costs effectively.

While 'Persistently Expansive Caching' offers the advantage of fresh interactions and comprehensive caching, remember the virtues of 'Basic' and 'Advanced' caching strategies. These strategies balance cost, speed, and accuracy by smartly utilizing cache to respond to repeat queries, thereby optimizing your OpenAI interactions. Your choice should align with your unique requirements, your cost management strategies, and your desired balance between speed, cost, and accuracy.

" +COM_GETBIBLE_PROMPT_CACHE_PERSISTENTLY_EXPANSIVE_CACHING_NOTE_LABEL="Persistently Expansive Caching" +COM_GETBIBLE_PROMPT_CONTENT_DESCRIPTION="Content" +COM_GETBIBLE_PROMPT_CONTENT_HINT="add the prompt content here..." +COM_GETBIBLE_PROMPT_CONTENT_LABEL="Prompt" +COM_GETBIBLE_PROMPT_CREATED_BY_DESC="The user that created this Prompt." +COM_GETBIBLE_PROMPT_CREATED_BY_LABEL="Created By" +COM_GETBIBLE_PROMPT_CREATED_DATE_DESC="The date this Prompt was created." +COM_GETBIBLE_PROMPT_CREATED_DATE_LABEL="Created Date" +COM_GETBIBLE_PROMPT_EDIT="Editing the Prompt" +COM_GETBIBLE_PROMPT_ERROR_UNIQUE_ALIAS="Another Prompt has the same alias." +COM_GETBIBLE_PROMPT_FREQUENCY_PENALTY_DESCRIPTION="Penalty for new tokens based on their frequency in the text" +COM_GETBIBLE_PROMPT_FREQUENCY_PENALTY_LABEL="Frequency Penalty" +COM_GETBIBLE_PROMPT_FREQUENCY_PENALTY_NOTE_DESCRIPTION="

The "frequency_penalty" is another optional parameter that defaults to 0. This is also a value between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.

  • For example, a high frequency penalty discourages the model from excessively repeating the same words or phrases, encouraging it to produce more diverse and creative text.
" +COM_GETBIBLE_PROMPT_FREQUENCY_PENALTY_NOTE_LABEL="Frequency Penalty" +COM_GETBIBLE_PROMPT_FREQUENCY_PENALTY_OVERRIDE_DESCRIPTION="Would you like to override the global frequency penalty value." +COM_GETBIBLE_PROMPT_FREQUENCY_PENALTY_OVERRIDE_LABEL="Frequency Penalty" +COM_GETBIBLE_PROMPT_FUNCTION="function" +COM_GETBIBLE_PROMPT_GPT35TURBO="gpt-3.5-turbo" +COM_GETBIBLE_PROMPT_GPT35TURBO0613="gpt-3.5-turbo-0613" +COM_GETBIBLE_PROMPT_GPT35TURBO16K="gpt-3.5-turbo-16k" +COM_GETBIBLE_PROMPT_GPT35TURBO16K0613="gpt-3.5-turbo-16k-0613" +COM_GETBIBLE_PROMPT_GPT4="gpt-4" +COM_GETBIBLE_PROMPT_GPT40613="gpt-4-0613" +COM_GETBIBLE_PROMPT_GPT432K="gpt-4-32k" +COM_GETBIBLE_PROMPT_GPT432K0613="gpt-4-32k-0613" +COM_GETBIBLE_PROMPT_GUID_DESCRIPTION="Globally Unique Identifier" +COM_GETBIBLE_PROMPT_GUID_HINT="Auto Generated" +COM_GETBIBLE_PROMPT_GUID_LABEL="GUID" +COM_GETBIBLE_PROMPT_ID="Id" +COM_GETBIBLE_PROMPT_INTEGRATION_DESCRIPTION="Determine the extent of Bible text that this prompt can encompass when interacting with OpenAI API." +COM_GETBIBLE_PROMPT_INTEGRATION_LABEL="Prompt Integration Scope" +COM_GETBIBLE_PROMPT_INTEGRATION_NOTE_DESCRIPTION="

The 'Prompt Integration Scope' feature is instrumental in defining the scope of the Bible text that your prompt can integrate with when querying the OpenAI API. Depending on your selection, this directly impacts how the application interacts with OpenAI's services and how responses are cached and presented to the user.

  • Word-Based: If you select this option, your prompt will be available whenever a single word is selected within the application. This strategy is more granular and allows for highly targeted queries based on individual words. However, this option can lead to a higher number of API calls if the selected word varies frequently. Note that the caching behavior in this case will be based on the selected word(s).
  • Verse-Based: Opting for this will make your prompt available for entire verses. It does not target individual words within a verse but treats the verse as a whole. This approach results in fewer API calls as long as the verse remains the same. Note that caching in this mode will be linked to the specific verse, not to individual words in the verse. This option only utilizes the placeholder [selected_verse].
  • Selection-Based: With this selection, your prompt becomes available when one or more words across one or more verses are selected. This gives maximum flexibility but can also lead to increased API calls, especially if the selections change frequently. The caching strategy in this case will be tied to the specific word(s) and verse(s) selected.

Choosing the right 'Prompt Integration Scope' is vital as it directly affects the positioning and availability of the prompt in the GUI, the interaction with the OpenAI API, and the caching strategy and behavior. Be sure to select the option that best suits the nature of your queries and the needs of your users.

" +COM_GETBIBLE_PROMPT_INTEGRATION_NOTE_LABEL="Prompt Integration Scope Details" +COM_GETBIBLE_PROMPT_MAX_TOKENS_DESCRIPTION="Maximum number of tokens to generate." +COM_GETBIBLE_PROMPT_MAX_TOKENS_LABEL="Max Tokens" +COM_GETBIBLE_PROMPT_MAX_TOKENS_NOTE_DESCRIPTION="

The "max_tokens" parameter sets the maximum number of tokens to generate in the chat completion. This is an optional parameter that defaults to infinity if not specified.

  • Note that the total length of both the input tokens and the generated tokens is limited by the model's context length. For instance, if a model has a context length of 100 tokens and you've used 20 tokens in your input, you could generate up to 80 additional tokens.
" +COM_GETBIBLE_PROMPT_MAX_TOKENS_NOTE_LABEL="Max Tokens" +COM_GETBIBLE_PROMPT_MAX_TOKENS_OVERRIDE_DESCRIPTION="Would you like to override the global max tokens value." +COM_GETBIBLE_PROMPT_MAX_TOKENS_OVERRIDE_LABEL="Max Tokens" +COM_GETBIBLE_PROMPT_MESSAGES_LABEL="Prompt Messages" +COM_GETBIBLE_PROMPT_MODEL_DESCRIPTION="ID of the model to use." +COM_GETBIBLE_PROMPT_MODEL_LABEL="Model" +COM_GETBIBLE_PROMPT_MODIFIED_BY_DESC="The last user that modified this Prompt." +COM_GETBIBLE_PROMPT_MODIFIED_BY_LABEL="Modified By" +COM_GETBIBLE_PROMPT_MODIFIED_DATE_DESC="The date this Prompt was modified." +COM_GETBIBLE_PROMPT_MODIFIED_DATE_LABEL="Modified Date" +COM_GETBIBLE_PROMPT_NAME_DESCRIPTION="Name" +COM_GETBIBLE_PROMPT_NAME_HINT="Name Here" +COM_GETBIBLE_PROMPT_NAME_LABEL="Name" +COM_GETBIBLE_PROMPT_NAME_MESSAGE="Error! Please add name here." +COM_GETBIBLE_PROMPT_NEW="A New Prompt" +COM_GETBIBLE_PROMPT_N_DESCRIPTION="The number of chat completion choices to generate" +COM_GETBIBLE_PROMPT_N_LABEL="Number AI Response Per/Prompt" +COM_GETBIBLE_PROMPT_N_NOTE_DESCRIPTION="

The "n" parameter determines how many independent completions to generate for each input message. This can be used when you want multiple distinct responses for a single prompt.

  • Setting "n" to 3, for instance, would make the model generate 3 separate responses for each input message.
" +COM_GETBIBLE_PROMPT_N_NOTE_LABEL="Number AI Response Per/Prompt" +COM_GETBIBLE_PROMPT_N_OVERRIDE_DESCRIPTION="Would you like to override the global n value." +COM_GETBIBLE_PROMPT_N_OVERRIDE_LABEL="Number AI Response Per/Prompt" +COM_GETBIBLE_PROMPT_OPENAI_DOCUMENTATION_NOTE_DESCRIPTION="

Please review the OpenAI API documentation for creating a chat conversation at this link. The document provides a comprehensive guide on parameters and methods to create chat completion using OpenAI's model. It includes instructions on:

  • How to post a request to create model responses
  • The format for the request body including role, model, messages, and optional parameters such as name, content, and function_call
  • Different ways to control the model's response such as temperature and top_p
  • How to control the number of generated chat completion choices, the stop sequences, and maximum number of tokens
  • Utilizing penalties and biases for managing the output
  • Additional features like streaming and user tracking for abuse monitoring
" +COM_GETBIBLE_PROMPT_OPENAI_DOCUMENTATION_NOTE_LABEL="Chat Completion (end-point)" +COM_GETBIBLE_PROMPT_OPENAI_PROMPTS_PLACEHOLDERS_ADVANCED_CACHING_NOTE_DESCRIPTION="

You can use the following placeholders in the prompts:

[translation_name][translation_language][translation_lcsh][translation_abbreviation][book_name][chapter_number][chapter_name][chapter_text][verse_number][verse_name][verse_text][selected_word_number][selected_word_text]
Utilizing these placeholders is crucial to enhancing the distinctiveness of responses from Open AI. Be aware that using the [chapter_text] placeholder loads the complete text of the chapter. This significantly increases the size of the query and might cause failures in certain circumstances. Exercise caution and restraint when implementing the [chapter_text] placeholder!" +COM_GETBIBLE_PROMPT_OPENAI_PROMPTS_PLACEHOLDERS_ADVANCED_CACHING_NOTE_LABEL="Prompts Placeholders (Advanced Caching)" +COM_GETBIBLE_PROMPT_OPENAI_PROMPTS_PLACEHOLDERS_BASIC_CACHING_NOTE_DESCRIPTION="

You can use the following placeholders in the prompts:

[translation_language][translation_lcsh][selected_word_text]
Utilizing these placeholders is crucial to enhancing the distinctiveness of responses from Open AI. Please not that only these placeholders are available in basic caching mode." +COM_GETBIBLE_PROMPT_OPENAI_PROMPTS_PLACEHOLDERS_BASIC_CACHING_NOTE_LABEL="Prompts Placeholders (Basic Caching)" +COM_GETBIBLE_PROMPT_OPENAI_PROMPTS_PLACEHOLDERS_NONE_CACHING_NOTE_DESCRIPTION="

You can use the following placeholders in the prompts:

[translation_name][translation_language][translation_lcsh][translation_abbreviation][book_name][chapter_number][chapter_name][chapter_text][verse_number][verse_name][verse_text][selected_word_number][selected_word_text]
Utilizing these placeholders is crucial to enhancing the distinctiveness of responses from Open AI. Be aware that using the [chapter_text] placeholder loads the complete text of the chapter. This significantly increases the size of the query and might cause failures in certain circumstances. Exercise caution and restraint when implementing the [chapter_text] placeholder!" +COM_GETBIBLE_PROMPT_OPENAI_PROMPTS_PLACEHOLDERS_NONE_CACHING_NOTE_LABEL="Prompts Placeholders (No Caching)" +COM_GETBIBLE_PROMPT_OPEN_AI="Open AI" +COM_GETBIBLE_PROMPT_ORDERING_LABEL="Ordering" +COM_GETBIBLE_PROMPT_ORG_TOKEN_DESCRIPTION="Your Organisation Token" +COM_GETBIBLE_PROMPT_ORG_TOKEN_HINT="// get your token from your Organisation on Open AI" +COM_GETBIBLE_PROMPT_ORG_TOKEN_LABEL="Openai Organisation Token" +COM_GETBIBLE_PROMPT_OVERRIDE="Override" +COM_GETBIBLE_PROMPT_PERMISSION="Permissions" +COM_GETBIBLE_PROMPT_PERSISTENTLY_EXPANSIVE_CACHING="Persistently Expansive Caching" +COM_GETBIBLE_PROMPT_PRESENCE_PENALTY_DESCRIPTION="Penalty for new tokens based on whether they appear in the text" +COM_GETBIBLE_PROMPT_PRESENCE_PENALTY_LABEL="Presence Penalty" +COM_GETBIBLE_PROMPT_PRESENCE_PENALTY_NOTE_DESCRIPTION="

The "presence_penalty" is an optional parameter that defaults to 0. This is a value between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.

  • For example, a high presence penalty encourages the model to generate text involving a wider variety of topics or themes, rather than focusing on a single topic or repeatedly using the same phrases.
" +COM_GETBIBLE_PROMPT_PRESENCE_PENALTY_NOTE_LABEL="Presence Penalty" +COM_GETBIBLE_PROMPT_PRESENCE_PENALTY_OVERRIDE_DESCRIPTION="Would you like to override the global presence penalty value." +COM_GETBIBLE_PROMPT_PRESENCE_PENALTY_OVERRIDE_LABEL="Presence Penalty" +COM_GETBIBLE_PROMPT_PROMPT="Prompt" +COM_GETBIBLE_PROMPT_PUBLISHING="Publishing" +COM_GETBIBLE_PROMPT_RANDOM="Random" +COM_GETBIBLE_PROMPT_RESPONSE_RETRIEVAL_DESCRIPTION="Choose how cached responses are delivered: either a 'Total Retrieval' of all relevant cached responses or a 'Random Retrieval' of a single relevant response from the cache." +COM_GETBIBLE_PROMPT_RESPONSE_RETRIEVAL_LABEL="Response Retrieval" +COM_GETBIBLE_PROMPT_RESPONSE_RETRIEVAL_NOTE_DESCRIPTION="

The 'Response Retrieval' feature provides you with control over how cached responses are served when a cache hit occurs. You have two options to choose from:

  • Total Retrieval: This option delivers all cached responses that are relevant to a query. For instance, if multiple unique responses are stored in the cache for a particular word or verse, 'Total Retrieval' will present all of these responses.
  • Random Retrieval: With this selection, the system will pick and present a single relevant response from the cache at random for a given query.

These settings can be applied to both the 'Basic Caching - Words/Language' and the 'Advanced Caching - Verse/Context' strategies, adding an extra layer of flexibility to how you manage and utilize your cached data.

Remember, the choice between 'Total Retrieval' and 'Random Retrieval' can impact the user experience. 'Total Retrieval' may provide a more comprehensive overview of possible responses, while 'Random Retrieval' might offer a more streamlined and varied experience.

" +COM_GETBIBLE_PROMPT_RESPONSE_RETRIEVAL_NOTE_LABEL="Response Retrieval" +COM_GETBIBLE_PROMPT_ROLE_DESCRIPTION="Role" +COM_GETBIBLE_PROMPT_ROLE_LABEL="Prompt" +COM_GETBIBLE_PROMPT_SAVE_WARNING="Alias already existed so a number was added at the end. You can re-edit the Prompt to customise the alias." +COM_GETBIBLE_PROMPT_SELECTIONBASED="Selection-Based" +COM_GETBIBLE_PROMPT_SELECT_AN_OPTION="Select an option" +COM_GETBIBLE_PROMPT_STATUS="Status" +COM_GETBIBLE_PROMPT_SYSTEM="system" +COM_GETBIBLE_PROMPT_TEMPERATURE_DESCRIPTION="The sampling temperature to use" +COM_GETBIBLE_PROMPT_TEMPERATURE_LABEL="Temperature" +COM_GETBIBLE_PROMPT_TEMPERATURE_NOTE_DESCRIPTION="

The "temperature" is a parameter that controls the randomness of the model's output. Its value ranges between 0 and 2. A higher temperature value results in more randomness, while a lower value results in less randomness. This affects the selection of the next word during text generation.

  • At a higher value like 2, the model has a greater probability of picking less likely words, which may lead to more diverse and creative outputs.
  • At a lower value like 0.2, the model's output becomes more deterministic, primarily choosing words with the highest predicted probabilities, leading to more focused and predictable responses.
" +COM_GETBIBLE_PROMPT_TEMPERATURE_NOTE_LABEL="Temperature" +COM_GETBIBLE_PROMPT_TEMPERATURE_OVERRIDE_DESCRIPTION="Would you like to override the global temperature value." +COM_GETBIBLE_PROMPT_TEMPERATURE_OVERRIDE_LABEL="Temperature" +COM_GETBIBLE_PROMPT_TOKEN_DESCRIPTION="Your Openai Token" +COM_GETBIBLE_PROMPT_TOKEN_HINT="// get your token from Open AI" +COM_GETBIBLE_PROMPT_TOKEN_LABEL="Openai Token" +COM_GETBIBLE_PROMPT_TOKEN_OVERRIDE_DESCRIPTION="Would you like to override the global openai token value." +COM_GETBIBLE_PROMPT_TOKEN_OVERRIDE_LABEL="Openai Token" +COM_GETBIBLE_PROMPT_TOP_P_DESCRIPTION="The nucleus sampling parameter" +COM_GETBIBLE_PROMPT_TOP_P_LABEL="Top P" +COM_GETBIBLE_PROMPT_TOP_P_NOTE_DESCRIPTION="

The "top_p" parameter is used for "nucleus sampling," an alternative to the temperature-based sampling. It defines a threshold for the cumulative probability of the chosen tokens. Rather than considering all possible tokens for the next word, it only considers the smallest set of tokens whose cumulative probability exceeds the set "top_p" value.

  • Setting "top_p" to 0.1 means the model will only consider the tokens comprising the top 10% probability mass for the next word.
  • If "top_p" is set to 0.9, the model considers a wider range of tokens for the next word but still limits to those within the top 90% of the probability distribution.
" +COM_GETBIBLE_PROMPT_TOP_P_NOTE_LABEL="Top P" +COM_GETBIBLE_PROMPT_TOP_P_OVERRIDE_DESCRIPTION="Would you like to override the global top p value." +COM_GETBIBLE_PROMPT_TOP_P_OVERRIDE_LABEL="Top P" +COM_GETBIBLE_PROMPT_TOTAL="Total" +COM_GETBIBLE_PROMPT_USER="user" +COM_GETBIBLE_PROMPT_USE_GLOBAL="Use Global" +COM_GETBIBLE_PROMPT_VERSEBASED="Verse-Based" +COM_GETBIBLE_PROMPT_VERSION_DESC="A count of the number of times this Prompt has been revised." +COM_GETBIBLE_PROMPT_VERSION_LABEL="Version" +COM_GETBIBLE_PROMPT_WORDBASED="Word-Based" +COM_GETBIBLE_PUBLISHED="Published" +COM_GETBIBLE_SAVE_SUCCESS="Great! Item successfully saved." +COM_GETBIBLE_SAVE_WARNING="The value already existed so please select another." +COM_GETBIBLE_SELECT_AN_OPTION="Select an option" +COM_GETBIBLE_SESSION_KEY_COULD_NOT_BE_STORED="Session key could not be stored." +COM_GETBIBLE_SUBMENU_BOOKS="Books" +COM_GETBIBLE_SUBMENU_CHAPTERS="Chapters" +COM_GETBIBLE_SUBMENU_DASHBOARD="Dashboard" +COM_GETBIBLE_SUBMENU_LINKERS="Linkers" +COM_GETBIBLE_SUBMENU_NOTES="Notes" +COM_GETBIBLE_SUBMENU_OPEN_AI_RESPONSES="Open AI Responses" +COM_GETBIBLE_SUBMENU_PROMPTS="Prompts" +COM_GETBIBLE_SUBMENU_TAGGED_VERSES="Tagged Verses" +COM_GETBIBLE_SUBMENU_TAGS="Tags" +COM_GETBIBLE_SUBMENU_TRANSLATIONS="Translations" +COM_GETBIBLE_SUBMENU_VERSES="Verses" +COM_GETBIBLE_TAG="Tag" +COM_GETBIBLE_TAGGED_VERSE="Tagged Verse" +COM_GETBIBLE_TAGGED_VERSES="Tagged Verses" +COM_GETBIBLE_TAGGED_VERSES_ACCESS="Tagged Verses Access" +COM_GETBIBLE_TAGGED_VERSES_ACCESS_DESC="Allows the users in this group to access access tagged verses" +COM_GETBIBLE_TAGGED_VERSES_BATCH_OPTIONS="Batch process the selected Tagged Verses" +COM_GETBIBLE_TAGGED_VERSES_BATCH_TIP="All changes will be applied to all selected Tagged Verses" +COM_GETBIBLE_TAGGED_VERSES_BATCH_USE="Tagged Verses Batch Use" +COM_GETBIBLE_TAGGED_VERSES_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch tagged verses" +COM_GETBIBLE_TAGGED_VERSES_CREATE="Tagged Verses Create" +COM_GETBIBLE_TAGGED_VERSES_CREATE_DESC="Allows the users in this group to create create tagged verses" +COM_GETBIBLE_TAGGED_VERSES_DASHBOARD_LIST="Tagged Verses Dashboard List" +COM_GETBIBLE_TAGGED_VERSES_DASHBOARD_LIST_DESC="Allows the users in this group to dashboard list of tagged verse" +COM_GETBIBLE_TAGGED_VERSES_DELETE="Tagged Verses Delete" +COM_GETBIBLE_TAGGED_VERSES_DELETE_DESC="Allows the users in this group to delete delete tagged verses" +COM_GETBIBLE_TAGGED_VERSES_EDIT="Tagged Verses Edit" +COM_GETBIBLE_TAGGED_VERSES_EDIT_ABBREVIATION="Tagged Verses Edit Abbreviation" +COM_GETBIBLE_TAGGED_VERSES_EDIT_ABBREVIATION_DESC="Allows the users in this group to edit abbreviation of tagged verse" +COM_GETBIBLE_TAGGED_VERSES_EDIT_ACCESS="Tagged Verses Edit Access" +COM_GETBIBLE_TAGGED_VERSES_EDIT_ACCESS_DESC="Allows the users in this group to change the access of the edit access tagged verses" +COM_GETBIBLE_TAGGED_VERSES_EDIT_BOOK_NR="Tagged Verses Edit Book Nr" +COM_GETBIBLE_TAGGED_VERSES_EDIT_BOOK_NR_DESC="Allows the users in this group to edit book nr of tagged verse" +COM_GETBIBLE_TAGGED_VERSES_EDIT_CHAPTER="Tagged Verses Edit Chapter" +COM_GETBIBLE_TAGGED_VERSES_EDIT_CHAPTER_DESC="Allows the users in this group to edit chapter of tagged verse" +COM_GETBIBLE_TAGGED_VERSES_EDIT_CREATED_BY="Tagged Verses Edit Created By" +COM_GETBIBLE_TAGGED_VERSES_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by tagged verses" +COM_GETBIBLE_TAGGED_VERSES_EDIT_CREATED_DATE="Tagged Verses Edit Created Date" +COM_GETBIBLE_TAGGED_VERSES_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created tagged verses" +COM_GETBIBLE_TAGGED_VERSES_EDIT_DESC="Allows the users in this group to edit the tagged verse" +COM_GETBIBLE_TAGGED_VERSES_EDIT_GUID="Tagged Verses Edit Guid" +COM_GETBIBLE_TAGGED_VERSES_EDIT_GUID_DESC="Allows the users in this group to edit guid of tagged verse" +COM_GETBIBLE_TAGGED_VERSES_EDIT_LINKER="Tagged Verses Edit Linker" +COM_GETBIBLE_TAGGED_VERSES_EDIT_LINKER_DESC="Allows the users in this group to edit linker of tagged verse" +COM_GETBIBLE_TAGGED_VERSES_EDIT_OWN="Tagged Verses Edit Own" +COM_GETBIBLE_TAGGED_VERSES_EDIT_OWN_DESC="Allows the users in this group to edit edit own tagged verses created by them" +COM_GETBIBLE_TAGGED_VERSES_EDIT_STATE="Tagged Verses Edit State" +COM_GETBIBLE_TAGGED_VERSES_EDIT_STATE_DESC="Allows the users in this group to update the state of the tagged verse" +COM_GETBIBLE_TAGGED_VERSES_EDIT_TAG="Tagged Verses Edit Tag" +COM_GETBIBLE_TAGGED_VERSES_EDIT_TAG_DESC="Allows the users in this group to edit tag of tagged verse" +COM_GETBIBLE_TAGGED_VERSES_EDIT_VERSE="Tagged Verses Edit Verse" +COM_GETBIBLE_TAGGED_VERSES_EDIT_VERSE_DESC="Allows the users in this group to edit verse of tagged verse" +COM_GETBIBLE_TAGGED_VERSES_EDIT_VERSION="Tagged Verses Edit Version" +COM_GETBIBLE_TAGGED_VERSES_EDIT_VERSION_DESC="Allows users in this group to edit versions of version tagged verses" +COM_GETBIBLE_TAGGED_VERSES_N_ITEMS_ARCHIVED="%s Tagged Verses archived." +COM_GETBIBLE_TAGGED_VERSES_N_ITEMS_ARCHIVED_1="%s Tagged Verse archived." +COM_GETBIBLE_TAGGED_VERSES_N_ITEMS_CHECKED_IN_0="No Tagged Verse successfully checked in." +COM_GETBIBLE_TAGGED_VERSES_N_ITEMS_CHECKED_IN_1="%d Tagged Verse successfully checked in." +COM_GETBIBLE_TAGGED_VERSES_N_ITEMS_CHECKED_IN_MORE="%d Tagged Verses successfully checked in." +COM_GETBIBLE_TAGGED_VERSES_N_ITEMS_DELETED="%s Tagged Verses deleted." +COM_GETBIBLE_TAGGED_VERSES_N_ITEMS_DELETED_1="%s Tagged Verse deleted." +COM_GETBIBLE_TAGGED_VERSES_N_ITEMS_FAILED_PUBLISHING="%s Tagged Verses failed publishing." +COM_GETBIBLE_TAGGED_VERSES_N_ITEMS_FAILED_PUBLISHING_1="%s Tagged Verse failed publishing." +COM_GETBIBLE_TAGGED_VERSES_N_ITEMS_FEATURED="%s Tagged Verses featured." +COM_GETBIBLE_TAGGED_VERSES_N_ITEMS_FEATURED_1="%s Tagged Verse featured." +COM_GETBIBLE_TAGGED_VERSES_N_ITEMS_PUBLISHED="%s Tagged Verses published." +COM_GETBIBLE_TAGGED_VERSES_N_ITEMS_PUBLISHED_1="%s Tagged Verse published." +COM_GETBIBLE_TAGGED_VERSES_N_ITEMS_TRASHED="%s Tagged Verses trashed." +COM_GETBIBLE_TAGGED_VERSES_N_ITEMS_TRASHED_1="%s Tagged Verse trashed." +COM_GETBIBLE_TAGGED_VERSES_N_ITEMS_UNFEATURED="%s Tagged Verses unfeatured." +COM_GETBIBLE_TAGGED_VERSES_N_ITEMS_UNFEATURED_1="%s Tagged Verse unfeatured." +COM_GETBIBLE_TAGGED_VERSES_N_ITEMS_UNPUBLISHED="%s Tagged Verses unpublished." +COM_GETBIBLE_TAGGED_VERSES_N_ITEMS_UNPUBLISHED_1="%s Tagged Verse unpublished." +COM_GETBIBLE_TAGGED_VERSES_REFERENCE="Reference" +COM_GETBIBLE_TAGGED_VERSES_SUBMENU="Tagged Verses Submenu" +COM_GETBIBLE_TAGGED_VERSES_SUBMENU_DESC="Allows the users in this group to submenu of tagged verse" +COM_GETBIBLE_TAGGED_VERSE_ABBREVIATION_DESCRIPTION="Select a Bible translation" +COM_GETBIBLE_TAGGED_VERSE_ABBREVIATION_LABEL="Translation" +COM_GETBIBLE_TAGGED_VERSE_ACCESS_LABEL="Access" +COM_GETBIBLE_TAGGED_VERSE_ALREADY_EXIST_BUT_COULD_NOT_BE_REACTIVATED="Tagged verse already exist, but could not be reactivated." +COM_GETBIBLE_TAGGED_VERSE_BOOK_NR_DESCRIPTION="Select the book number" +COM_GETBIBLE_TAGGED_VERSE_BOOK_NR_LABEL="Book Number" +COM_GETBIBLE_TAGGED_VERSE_CHAPTER_DESCRIPTION="Select the chapter number" +COM_GETBIBLE_TAGGED_VERSE_CHAPTER_LABEL="Chapter" +COM_GETBIBLE_TAGGED_VERSE_CREATED_BY_DESC="The user that created this Tagged Verse." +COM_GETBIBLE_TAGGED_VERSE_CREATED_BY_LABEL="Created By" +COM_GETBIBLE_TAGGED_VERSE_CREATED_DATE_DESC="The date this Tagged Verse was created." +COM_GETBIBLE_TAGGED_VERSE_CREATED_DATE_LABEL="Created Date" +COM_GETBIBLE_TAGGED_VERSE_DETAILS="Details" +COM_GETBIBLE_TAGGED_VERSE_EDIT="Editing the Tagged Verse" +COM_GETBIBLE_TAGGED_VERSE_ERROR_UNIQUE_ALIAS="Another Tagged Verse has the same alias." +COM_GETBIBLE_TAGGED_VERSE_GUID_DESCRIPTION="Globally Unique Identifier" +COM_GETBIBLE_TAGGED_VERSE_GUID_HINT="Auto Generated" +COM_GETBIBLE_TAGGED_VERSE_GUID_LABEL="GUID" +COM_GETBIBLE_TAGGED_VERSE_ID="Id" +COM_GETBIBLE_TAGGED_VERSE_LINKER_DESCRIPTION="Globally Unique Linker" +COM_GETBIBLE_TAGGED_VERSE_LINKER_LABEL="Linker" +COM_GETBIBLE_TAGGED_VERSE_MODIFIED_BY_DESC="The last user that modified this Tagged Verse." +COM_GETBIBLE_TAGGED_VERSE_MODIFIED_BY_LABEL="Modified By" +COM_GETBIBLE_TAGGED_VERSE_MODIFIED_DATE_DESC="The date this Tagged Verse was modified." +COM_GETBIBLE_TAGGED_VERSE_MODIFIED_DATE_LABEL="Modified Date" +COM_GETBIBLE_TAGGED_VERSE_NEW="A New Tagged Verse" +COM_GETBIBLE_TAGGED_VERSE_ORDERING_LABEL="Ordering" +COM_GETBIBLE_TAGGED_VERSE_PERMISSION="Permissions" +COM_GETBIBLE_TAGGED_VERSE_PRIVATE="Private" +COM_GETBIBLE_TAGGED_VERSE_PUBLIC="Public" +COM_GETBIBLE_TAGGED_VERSE_PUBLISHING="Publishing" +COM_GETBIBLE_TAGGED_VERSE_SAVE_WARNING="Alias already existed so a number was added at the end. You can re-edit the Tagged Verse to customise the alias." +COM_GETBIBLE_TAGGED_VERSE_STATUS="Status" +COM_GETBIBLE_TAGGED_VERSE_TAG_LABEL="Tag" +COM_GETBIBLE_TAGGED_VERSE_VERSE_DESCRIPTION="Select the verse number" +COM_GETBIBLE_TAGGED_VERSE_VERSE_LABEL="Verse" +COM_GETBIBLE_TAGGED_VERSE_VERSION_DESC="A count of the number of times this Tagged Verse has been revised." +COM_GETBIBLE_TAGGED_VERSE_VERSION_LABEL="Version" +COM_GETBIBLE_TAGS="Tags" +COM_GETBIBLE_TAGS_ACCESS="Tags Access" +COM_GETBIBLE_TAGS_ACCESS_DESC="Allows the users in this group to access access tags" +COM_GETBIBLE_TAGS_BATCH_OPTIONS="Batch process the selected Tags" +COM_GETBIBLE_TAGS_BATCH_TIP="All changes will be applied to all selected Tags" +COM_GETBIBLE_TAGS_BATCH_USE="Tags Batch Use" +COM_GETBIBLE_TAGS_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch tags" +COM_GETBIBLE_TAGS_CREATE="Tags Create" +COM_GETBIBLE_TAGS_CREATE_DESC="Allows the users in this group to create create tags" +COM_GETBIBLE_TAGS_DASHBOARD_LIST="Tags Dashboard List" +COM_GETBIBLE_TAGS_DASHBOARD_LIST_DESC="Allows the users in this group to dashboard list of tag" +COM_GETBIBLE_TAGS_DELETE="Tags Delete" +COM_GETBIBLE_TAGS_DELETE_DESC="Allows the users in this group to delete delete tags" +COM_GETBIBLE_TAGS_EDIT="Tags Edit" +COM_GETBIBLE_TAGS_EDIT_ACCESS="Tags Edit Access" +COM_GETBIBLE_TAGS_EDIT_ACCESS_DESC="Allows the users in this group to change the access of the edit access tags" +COM_GETBIBLE_TAGS_EDIT_CREATED_BY="Tags Edit Created By" +COM_GETBIBLE_TAGS_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by tags" +COM_GETBIBLE_TAGS_EDIT_CREATED_DATE="Tags Edit Created Date" +COM_GETBIBLE_TAGS_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created tags" +COM_GETBIBLE_TAGS_EDIT_DESC="Allows the users in this group to edit the tag" +COM_GETBIBLE_TAGS_EDIT_DESCRIPTION="Tags Edit Description" +COM_GETBIBLE_TAGS_EDIT_DESCRIPTION_DESC="Allows the users in this group to edit description of tag" +COM_GETBIBLE_TAGS_EDIT_GUID="Tags Edit Guid" +COM_GETBIBLE_TAGS_EDIT_GUID_DESC="Allows the users in this group to edit guid of tag" +COM_GETBIBLE_TAGS_EDIT_LINKER="Tags Edit Linker" +COM_GETBIBLE_TAGS_EDIT_LINKER_DESC="Allows the users in this group to edit linker of tag" +COM_GETBIBLE_TAGS_EDIT_NAME="Tags Edit Name" +COM_GETBIBLE_TAGS_EDIT_NAME_DESC="Allows the users in this group to edit name of tag" +COM_GETBIBLE_TAGS_EDIT_OWN="Tags Edit Own" +COM_GETBIBLE_TAGS_EDIT_OWN_DESC="Allows the users in this group to edit edit own tags created by them" +COM_GETBIBLE_TAGS_EDIT_STATE="Tags Edit State" +COM_GETBIBLE_TAGS_EDIT_STATE_DESC="Allows the users in this group to update the state of the tag" +COM_GETBIBLE_TAGS_EDIT_VERSION="Tags Edit Version" +COM_GETBIBLE_TAGS_EDIT_VERSION_DESC="Allows users in this group to edit versions of version tags" +COM_GETBIBLE_TAGS_N_ITEMS_ARCHIVED="%s Tags archived." +COM_GETBIBLE_TAGS_N_ITEMS_ARCHIVED_1="%s Tag archived." +COM_GETBIBLE_TAGS_N_ITEMS_CHECKED_IN_0="No Tag successfully checked in." +COM_GETBIBLE_TAGS_N_ITEMS_CHECKED_IN_1="%d Tag successfully checked in." +COM_GETBIBLE_TAGS_N_ITEMS_CHECKED_IN_MORE="%d Tags successfully checked in." +COM_GETBIBLE_TAGS_N_ITEMS_DELETED="%s Tags deleted." +COM_GETBIBLE_TAGS_N_ITEMS_DELETED_1="%s Tag deleted." +COM_GETBIBLE_TAGS_N_ITEMS_FAILED_PUBLISHING="%s Tags failed publishing." +COM_GETBIBLE_TAGS_N_ITEMS_FAILED_PUBLISHING_1="%s Tag failed publishing." +COM_GETBIBLE_TAGS_N_ITEMS_FEATURED="%s Tags featured." +COM_GETBIBLE_TAGS_N_ITEMS_FEATURED_1="%s Tag featured." +COM_GETBIBLE_TAGS_N_ITEMS_PUBLISHED="%s Tags published." +COM_GETBIBLE_TAGS_N_ITEMS_PUBLISHED_1="%s Tag published." +COM_GETBIBLE_TAGS_N_ITEMS_TRASHED="%s Tags trashed." +COM_GETBIBLE_TAGS_N_ITEMS_TRASHED_1="%s Tag trashed." +COM_GETBIBLE_TAGS_N_ITEMS_UNFEATURED="%s Tags unfeatured." +COM_GETBIBLE_TAGS_N_ITEMS_UNFEATURED_1="%s Tag unfeatured." +COM_GETBIBLE_TAGS_N_ITEMS_UNPUBLISHED="%s Tags unpublished." +COM_GETBIBLE_TAGS_N_ITEMS_UNPUBLISHED_1="%s Tag unpublished." +COM_GETBIBLE_TAGS_SUBMENU="Tags Submenu" +COM_GETBIBLE_TAGS_SUBMENU_DESC="Allows the users in this group to submenu of tag" +COM_GETBIBLE_TAG_ACCESS_LABEL="Access" +COM_GETBIBLE_TAG_ALREADY_EXIST_BUT_COULD_NOT_BE_REACTIVATED="Tag already exist, but could not be reactivated." +COM_GETBIBLE_TAG_CREATED_BY_DESC="The user that created this Tag." +COM_GETBIBLE_TAG_CREATED_BY_LABEL="Created By" +COM_GETBIBLE_TAG_CREATED_DATE_DESC="The date this Tag was created." +COM_GETBIBLE_TAG_CREATED_DATE_LABEL="Created Date" +COM_GETBIBLE_TAG_DESCRIPTION_DESCRIPTION="Add Description Here" +COM_GETBIBLE_TAG_DESCRIPTION_HINT="Add Description Here" +COM_GETBIBLE_TAG_DESCRIPTION_LABEL="Description" +COM_GETBIBLE_TAG_DETAILS="Details" +COM_GETBIBLE_TAG_EDIT="Editing the Tag" +COM_GETBIBLE_TAG_ERROR_UNIQUE_ALIAS="Another Tag has the same alias." +COM_GETBIBLE_TAG_GUID_DESCRIPTION="Globally Unique Identifier" +COM_GETBIBLE_TAG_GUID_HINT="Auto Generated" +COM_GETBIBLE_TAG_GUID_LABEL="GUID" +COM_GETBIBLE_TAG_ID="Id" +COM_GETBIBLE_TAG_LINKER_DESCRIPTION="Globally Unique Linker" +COM_GETBIBLE_TAG_LINKER_LABEL="Linker" +COM_GETBIBLE_TAG_MODIFIED_BY_DESC="The last user that modified this Tag." +COM_GETBIBLE_TAG_MODIFIED_BY_LABEL="Modified By" +COM_GETBIBLE_TAG_MODIFIED_DATE_DESC="The date this Tag was modified." +COM_GETBIBLE_TAG_MODIFIED_DATE_LABEL="Modified Date" +COM_GETBIBLE_TAG_NAME_HINT="Name Here" +COM_GETBIBLE_TAG_NAME_LABEL="Name" +COM_GETBIBLE_TAG_NAME_MESSAGE="Error! Please add name here." +COM_GETBIBLE_TAG_NEW="A New Tag" +COM_GETBIBLE_TAG_ORDERING_LABEL="Ordering" +COM_GETBIBLE_TAG_PERMISSION="Permissions" +COM_GETBIBLE_TAG_PRIVATE="Private" +COM_GETBIBLE_TAG_PUBLIC="Public" +COM_GETBIBLE_TAG_PUBLISHING="Publishing" +COM_GETBIBLE_TAG_SAVE_WARNING="Alias already existed so a number was added at the end. You can re-edit the Tag to customise the alias." +COM_GETBIBLE_TAG_STATUS="Status" +COM_GETBIBLE_TAG_VERSION_DESC="A count of the number of times this Tag has been revised." +COM_GETBIBLE_TAG_VERSION_LABEL="Version" +COM_GETBIBLE_THE_NOTE_WAS_SUCCESSFULLY_CREATED="The note was successfully created." +COM_GETBIBLE_THE_NOTE_WAS_SUCCESSFULLY_UPDATED="The note was successfully updated." +COM_GETBIBLE_THE_NOTICE_BOARD_IS_LOADING="The notice board is loading" +COM_GETBIBLE_THE_README_IS_LOADING="The readme is loading" +COM_GETBIBLE_THE_TAG_SELECTED_IS_NOT_ACTIVE_PLEASE_SELECT_AN_ACTIVE_TAG="The tag selected is not active, please select an active tag." +COM_GETBIBLE_THE_TAG_WAS_SUCCESSFULLY_REMOVED_FROM_THE_VERSE="The tag was successfully removed from the verse." +COM_GETBIBLE_THE_TAG_WAS_SUCCESSFULLY_SET="The tag was successfully set." +COM_GETBIBLE_THE_VERSE_WAS_SUCCESSFULLY_TAGGED="The verse was successfully tagged." +COM_GETBIBLE_THE_WIKI_CAN_ONLY_BE_LOADED_WHEN_YOUR_JCB_SYSTEM_HAS_INTERNET_CONNECTION="The wiki can only be loaded when your JCB system has internet connection." +COM_GETBIBLE_THE_WIKI_IS_LOADING="The wiki is loading" +COM_GETBIBLE_THIS_IS_A_GLOBAL_TAG_SET_BY_US_AT_BSB_FOR_YOUR_CONVENIENCE_WE_HOLD_THE_PRIVILEGE_TO_MODIFY_THESE_TAGS_IF_YOU_BELIEVE_ITS_SET_IN_ERROR_KINDLY_INFORM_US="This is a global tag, set by us at %s for your convenience. We hold the privilege to modify these tags. If you believe it's set in error, kindly inform us." +COM_GETBIBLE_THIS_TAG_COULD_NOT_BE_REMOVED="This tag could not be removed." +COM_GETBIBLE_TRANSLATION="Translation" +COM_GETBIBLE_TRANSLATIONS="Translations" +COM_GETBIBLE_TRANSLATIONS_ACCESS="Translations Access" +COM_GETBIBLE_TRANSLATIONS_ACCESS_DESC="Allows the users in this group to access access translations" +COM_GETBIBLE_TRANSLATIONS_BATCH_OPTIONS="Batch process the selected Translations" +COM_GETBIBLE_TRANSLATIONS_BATCH_TIP="All changes will be applied to all selected Translations" +COM_GETBIBLE_TRANSLATIONS_BATCH_USE="Translations Batch Use" +COM_GETBIBLE_TRANSLATIONS_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch translations" +COM_GETBIBLE_TRANSLATIONS_CREATE="Translations Create" +COM_GETBIBLE_TRANSLATIONS_CREATE_DESC="Allows the users in this group to create create translations" +COM_GETBIBLE_TRANSLATIONS_DASHBOARD_LIST="Translations Dashboard List" +COM_GETBIBLE_TRANSLATIONS_DASHBOARD_LIST_DESC="Allows the users in this group to dashboard list of translation" +COM_GETBIBLE_TRANSLATIONS_DELETE="Translations Delete" +COM_GETBIBLE_TRANSLATIONS_DELETE_DESC="Allows the users in this group to delete delete translations" +COM_GETBIBLE_TRANSLATIONS_EDIT="Translations Edit" +COM_GETBIBLE_TRANSLATIONS_EDIT_ABBREVIATION="Translations Edit Abbreviation" +COM_GETBIBLE_TRANSLATIONS_EDIT_ABBREVIATION_DESC="Allows the users in this group to edit abbreviation of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_CREATED_BY="Translations Edit Created By" +COM_GETBIBLE_TRANSLATIONS_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by translations" +COM_GETBIBLE_TRANSLATIONS_EDIT_CREATED_DATE="Translations Edit Created Date" +COM_GETBIBLE_TRANSLATIONS_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created translations" +COM_GETBIBLE_TRANSLATIONS_EDIT_DESC="Allows the users in this group to edit the translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DIRECTION="Translations Edit Direction" +COM_GETBIBLE_TRANSLATIONS_EDIT_DIRECTION_DESC="Allows the users in this group to edit direction of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_ABBREVIATION="Translations Edit Distribution Abbreviation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_ABBREVIATION_DESC="Allows the users in this group to edit distribution abbreviation of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_ABOUT="Translations Edit Distribution About" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_ABOUT_DESC="Allows the users in this group to edit distribution about of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_HISTORY="Translations Edit Distribution History" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_HISTORY_DESC="Allows the users in this group to edit distribution history of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_LCSH="Translations Edit Distribution Lcsh" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_LCSH_DESC="Allows the users in this group to edit distribution lcsh of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_LICENSE="Translations Edit Distribution License" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_LICENSE_DESC="Allows the users in this group to edit distribution license of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_SOURCE="Translations Edit Distribution Source" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_SOURCETYPE="Translations Edit Distribution Sourcetype" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_SOURCETYPE_DESC="Allows the users in this group to edit distribution sourcetype of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_SOURCE_DESC="Allows the users in this group to edit distribution source of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_VERSIFICATION="Translations Edit Distribution Versification" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_VERSIFICATION_DESC="Allows the users in this group to edit distribution versification of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_VERSION="Translations Edit Distribution Version" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_VERSION_DATE="Translations Edit Distribution Version Date" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_VERSION_DATE_DESC="Allows the users in this group to edit distribution version date of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_VERSION_DESC="Allows the users in this group to edit distribution version of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_ENCODING="Translations Edit Encoding" +COM_GETBIBLE_TRANSLATIONS_EDIT_ENCODING_DESC="Allows the users in this group to edit encoding of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_LANG="Translations Edit Lang" +COM_GETBIBLE_TRANSLATIONS_EDIT_LANGUAGE="Translations Edit Language" +COM_GETBIBLE_TRANSLATIONS_EDIT_LANGUAGE_DESC="Allows the users in this group to edit language of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_LANG_DESC="Allows the users in this group to edit lang of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_OWN="Translations Edit Own" +COM_GETBIBLE_TRANSLATIONS_EDIT_OWN_DESC="Allows the users in this group to edit edit own translations created by them" +COM_GETBIBLE_TRANSLATIONS_EDIT_SHA="Translations Edit Sha" +COM_GETBIBLE_TRANSLATIONS_EDIT_SHA_DESC="Allows the users in this group to edit sha of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_STATE="Translations Edit State" +COM_GETBIBLE_TRANSLATIONS_EDIT_STATE_DESC="Allows the users in this group to update the state of the translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_TRANSLATION="Translations Edit Translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_TRANSLATION_DESC="Allows the users in this group to edit translation of translation" +COM_GETBIBLE_TRANSLATIONS_N_ITEMS_ARCHIVED="%s Translations archived." +COM_GETBIBLE_TRANSLATIONS_N_ITEMS_ARCHIVED_1="%s Translation archived." +COM_GETBIBLE_TRANSLATIONS_N_ITEMS_CHECKED_IN_0="No Translation successfully checked in." +COM_GETBIBLE_TRANSLATIONS_N_ITEMS_CHECKED_IN_1="%d Translation successfully checked in." +COM_GETBIBLE_TRANSLATIONS_N_ITEMS_CHECKED_IN_MORE="%d Translations successfully checked in." +COM_GETBIBLE_TRANSLATIONS_N_ITEMS_DELETED="%s Translations deleted." +COM_GETBIBLE_TRANSLATIONS_N_ITEMS_DELETED_1="%s Translation deleted." +COM_GETBIBLE_TRANSLATIONS_N_ITEMS_FAILED_PUBLISHING="%s Translations failed publishing." +COM_GETBIBLE_TRANSLATIONS_N_ITEMS_FAILED_PUBLISHING_1="%s Translation failed publishing." +COM_GETBIBLE_TRANSLATIONS_N_ITEMS_FEATURED="%s Translations featured." +COM_GETBIBLE_TRANSLATIONS_N_ITEMS_FEATURED_1="%s Translation featured." +COM_GETBIBLE_TRANSLATIONS_N_ITEMS_PUBLISHED="%s Translations published." +COM_GETBIBLE_TRANSLATIONS_N_ITEMS_PUBLISHED_1="%s Translation published." +COM_GETBIBLE_TRANSLATIONS_N_ITEMS_TRASHED="%s Translations trashed." +COM_GETBIBLE_TRANSLATIONS_N_ITEMS_TRASHED_1="%s Translation trashed." +COM_GETBIBLE_TRANSLATIONS_N_ITEMS_UNFEATURED="%s Translations unfeatured." +COM_GETBIBLE_TRANSLATIONS_N_ITEMS_UNFEATURED_1="%s Translation unfeatured." +COM_GETBIBLE_TRANSLATIONS_N_ITEMS_UNPUBLISHED="%s Translations unpublished." +COM_GETBIBLE_TRANSLATIONS_N_ITEMS_UNPUBLISHED_1="%s Translation unpublished." +COM_GETBIBLE_TRANSLATIONS_SUBMENU="Translations Submenu" +COM_GETBIBLE_TRANSLATIONS_SUBMENU_DESC="Allows the users in this group to submenu of translation" +COM_GETBIBLE_TRANSLATION_ABBREVIATION_DESCRIPTION="Enter some abbreviation" +COM_GETBIBLE_TRANSLATION_ABBREVIATION_HINT="kjv" +COM_GETBIBLE_TRANSLATION_ABBREVIATION_LABEL="Abbreviation" +COM_GETBIBLE_TRANSLATION_ABBREVIATION_MESSAGE="Error! Please add some abbreviation here." +COM_GETBIBLE_TRANSLATION_CREATED_BY_DESC="The user that created this Translation." +COM_GETBIBLE_TRANSLATION_CREATED_BY_LABEL="Created By" +COM_GETBIBLE_TRANSLATION_CREATED_DATE_DESC="The date this Translation was created." +COM_GETBIBLE_TRANSLATION_CREATED_DATE_LABEL="Created Date" +COM_GETBIBLE_TRANSLATION_DESCRIPTION_HINT="history version desc" +COM_GETBIBLE_TRANSLATION_DESCRIPTION_LABEL="Description" +COM_GETBIBLE_TRANSLATION_DESCRIPTION_MESSAGE="Error! Please add some history version description here." +COM_GETBIBLE_TRANSLATION_DETAILS="Details" +COM_GETBIBLE_TRANSLATION_DEXTROSINISTRAL_RTL="Dextrosinistral (RTL)" +COM_GETBIBLE_TRANSLATION_DIRECTION_DESCRIPTION="Select Right-to-Left (RTL) or Left-to-Right (LTR)" +COM_GETBIBLE_TRANSLATION_DIRECTION_LABEL="Directional" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_ABBREVIATION_DESCRIPTION="Enter some distribution abbreviation" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_ABBREVIATION_HINT="kjv" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_ABBREVIATION_LABEL="Distribution Abbreviation" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_ABBREVIATION_MESSAGE="Error! Please add some distribution abbreviation here." +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_ABOUT_DESCRIPTION="Enter some distribution about" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_ABOUT_LABEL="Distribution About" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_ABOUT_MESSAGE="Error! Please add some distribution about here." +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_HISTORY_LABEL="Distribution History" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_LCSH_DESCRIPTION="Enter some distribution lcsh" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_LCSH_HINT="Bible. English." +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_LCSH_LABEL="Library of Congress Subject Headings" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_LCSH_MESSAGE="Error! Please add some distribution lcsh here." +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_LICENSE_DESCRIPTION="Add Translation Distribution License Here" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_LICENSE_HINT="Add Distribution License Here" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_LICENSE_LABEL="Distribution License" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_SOURCETYPE_DESCRIPTION="Enter some distribution source type" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_SOURCETYPE_HINT="OSIS" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_SOURCETYPE_LABEL="Distribution Source Type" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_SOURCETYPE_MESSAGE="Error! Please add some distribution source type here." +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_SOURCE_DESCRIPTION="Enter some distribution source" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_SOURCE_LABEL="Distribution Source" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_SOURCE_MESSAGE="Error! Please add some distribution source here." +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_VERSIFICATION_DESCRIPTION="Enter some distribution versification" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_VERSIFICATION_LABEL="Distribution Versification" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_VERSIFICATION_MESSAGE="Error! Please add some distribution versification here." +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_VERSION_DATE_DESCRIPTION="Enter some distribution version date" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_VERSION_DATE_HINT="2002-09-05" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_VERSION_DATE_LABEL="Distribution Version Date" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_VERSION_DATE_MESSAGE="Error! Please add some distribution version date here." +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_VERSION_DESCRIPTION="Enter some distribution version" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_VERSION_HINT="1.0" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_VERSION_LABEL="Distribution Version" +COM_GETBIBLE_TRANSLATION_DISTRIBUTION_VERSION_MESSAGE="Error! Please add some distribution version here." +COM_GETBIBLE_TRANSLATION_ENCODING_DESCRIPTION="Enter some encoding" +COM_GETBIBLE_TRANSLATION_ENCODING_LABEL="Encoding" +COM_GETBIBLE_TRANSLATION_ENCODING_MESSAGE="Error! Please add some encoding here." +COM_GETBIBLE_TRANSLATION_ERROR_UNIQUE_ALIAS="Another Translation has the same alias." +COM_GETBIBLE_TRANSLATION_ID="Id" +COM_GETBIBLE_TRANSLATION_LANGUAGE_DESCRIPTION="The translation language." +COM_GETBIBLE_TRANSLATION_LANGUAGE_HINT="English" +COM_GETBIBLE_TRANSLATION_LANGUAGE_LABEL="Language" +COM_GETBIBLE_TRANSLATION_LANGUAGE_MESSAGE="Error! Please add language tag here." +COM_GETBIBLE_TRANSLATION_LANG_DESCRIPTION="Enter some language abbreviation" +COM_GETBIBLE_TRANSLATION_LANG_HINT="en" +COM_GETBIBLE_TRANSLATION_LANG_LABEL="Two Letter Language Abbreviation" +COM_GETBIBLE_TRANSLATION_LANG_MESSAGE="Error! Please add some language abbreviation here." +COM_GETBIBLE_TRANSLATION_MODIFIED_BY_DESC="The last user that modified this Translation." +COM_GETBIBLE_TRANSLATION_MODIFIED_BY_LABEL="Modified By" +COM_GETBIBLE_TRANSLATION_MODIFIED_DATE_DESC="The date this Translation was modified." +COM_GETBIBLE_TRANSLATION_MODIFIED_DATE_LABEL="Modified Date" +COM_GETBIBLE_TRANSLATION_ORDERING_LABEL="Ordering" +COM_GETBIBLE_TRANSLATION_PERMISSION="Permissions" +COM_GETBIBLE_TRANSLATION_PUBLISHING="Publishing" +COM_GETBIBLE_TRANSLATION_READONLY="Translation :: Readonly" +COM_GETBIBLE_TRANSLATION_SAVE_WARNING="Alias already existed so a number was added at the end. You can re-edit the Translation to customise the alias." +COM_GETBIBLE_TRANSLATION_SHA_DESCRIPTION="Enter some checksum sha" +COM_GETBIBLE_TRANSLATION_SHA_LABEL="Checksum" +COM_GETBIBLE_TRANSLATION_SHA_MESSAGE="Error! Please add some checksum sha here." +COM_GETBIBLE_TRANSLATION_SINISTRODEXTRAL_LTR="Sinistrodextral (LTR)" +COM_GETBIBLE_TRANSLATION_STATUS="Status" +COM_GETBIBLE_TRANSLATION_TRANSLATION_DESCRIPTION="Enter some translation" +COM_GETBIBLE_TRANSLATION_TRANSLATION_HINT="King James Version" +COM_GETBIBLE_TRANSLATION_TRANSLATION_LABEL="Translation" +COM_GETBIBLE_TRANSLATION_TRANSLATION_MESSAGE="Error! Please add some translation here." +COM_GETBIBLE_TRANSLATION_VERSION_DESC="A count of the number of times this Translation has been revised." +COM_GETBIBLE_TRANSLATION_VERSION_HINT="history_1.0" +COM_GETBIBLE_TRANSLATION_VERSION_LABEL="Version" +COM_GETBIBLE_TRANSLATION_VERSION_MESSAGE="Error! Please add some history version here." +COM_GETBIBLE_TRASHED="Trashed" +COM_GETBIBLE_TRASHED_ITEMS="Trashed items" +COM_GETBIBLE_TRASH_AREA="Trash Area" +COM_GETBIBLE_TYPE_BOOK="Book" +COM_GETBIBLE_TYPE_CHAPTER="Chapter" +COM_GETBIBLE_TYPE_LINKER="Linker" +COM_GETBIBLE_TYPE_NOTE="Note" +COM_GETBIBLE_TYPE_OPEN_AI_MESSAGE="Open AI Message" +COM_GETBIBLE_TYPE_OPEN_AI_RESPONSE="Open AI Response" +COM_GETBIBLE_TYPE_PASSWORD="Password" +COM_GETBIBLE_TYPE_PROMPT="Prompt" +COM_GETBIBLE_TYPE_TAG="Tag" +COM_GETBIBLE_TYPE_TAGGED_VERSE="Tagged Verse" +COM_GETBIBLE_TYPE_TRANSLATION="Translation" +COM_GETBIBLE_TYPE_VERSE="Verse" +COM_GETBIBLE_UP_TO_DATE="Up to date" +COM_GETBIBLE_USE_BATCH="Use Batch" +COM_GETBIBLE_USE_BATCH_DESC="Allows users in this group to use batch copy/update method." +COM_GETBIBLE_VERSE="Verse" +COM_GETBIBLE_VERSES="Verses" +COM_GETBIBLE_VERSES_ACCESS="Verses Access" +COM_GETBIBLE_VERSES_ACCESS_DESC="Allows the users in this group to access access verses" +COM_GETBIBLE_VERSES_BATCH_OPTIONS="Batch process the selected Verses" +COM_GETBIBLE_VERSES_BATCH_TIP="All changes will be applied to all selected Verses" +COM_GETBIBLE_VERSES_BATCH_USE="Verses Batch Use" +COM_GETBIBLE_VERSES_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch verses" +COM_GETBIBLE_VERSES_CREATE="Verses Create" +COM_GETBIBLE_VERSES_CREATE_DESC="Allows the users in this group to create create verses" +COM_GETBIBLE_VERSES_DASHBOARD_LIST="Verses Dashboard List" +COM_GETBIBLE_VERSES_DASHBOARD_LIST_DESC="Allows the users in this group to dashboard list of verse" +COM_GETBIBLE_VERSES_DELETE="Verses Delete" +COM_GETBIBLE_VERSES_DELETE_DESC="Allows the users in this group to delete delete verses" +COM_GETBIBLE_VERSES_EDIT="Verses Edit" +COM_GETBIBLE_VERSES_EDIT_ABBREVIATION="Verses Edit Abbreviation" +COM_GETBIBLE_VERSES_EDIT_ABBREVIATION_DESC="Allows the users in this group to edit abbreviation of verse" +COM_GETBIBLE_VERSES_EDIT_BOOK_NR="Verses Edit Book Nr" +COM_GETBIBLE_VERSES_EDIT_BOOK_NR_DESC="Allows the users in this group to edit book nr of verse" +COM_GETBIBLE_VERSES_EDIT_CHAPTER="Verses Edit Chapter" +COM_GETBIBLE_VERSES_EDIT_CHAPTER_DESC="Allows the users in this group to edit chapter of verse" +COM_GETBIBLE_VERSES_EDIT_CREATED_BY="Verses Edit Created By" +COM_GETBIBLE_VERSES_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by verses" +COM_GETBIBLE_VERSES_EDIT_CREATED_DATE="Verses Edit Created Date" +COM_GETBIBLE_VERSES_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created verses" +COM_GETBIBLE_VERSES_EDIT_DESC="Allows the users in this group to edit the verse" +COM_GETBIBLE_VERSES_EDIT_NAME="Verses Edit Name" +COM_GETBIBLE_VERSES_EDIT_NAME_DESC="Allows the users in this group to edit name of verse" +COM_GETBIBLE_VERSES_EDIT_OWN="Verses Edit Own" +COM_GETBIBLE_VERSES_EDIT_OWN_DESC="Allows the users in this group to edit edit own verses created by them" +COM_GETBIBLE_VERSES_EDIT_STATE="Verses Edit State" +COM_GETBIBLE_VERSES_EDIT_STATE_DESC="Allows the users in this group to update the state of the verse" +COM_GETBIBLE_VERSES_EDIT_TEXT="Verses Edit Text" +COM_GETBIBLE_VERSES_EDIT_TEXT_DESC="Allows the users in this group to edit text of verse" +COM_GETBIBLE_VERSES_EDIT_VERSE="Verses Edit Verse" +COM_GETBIBLE_VERSES_EDIT_VERSE_DESC="Allows the users in this group to edit verse of verse" +COM_GETBIBLE_VERSES_N_ITEMS_ARCHIVED="%s Verses archived." +COM_GETBIBLE_VERSES_N_ITEMS_ARCHIVED_1="%s Verse archived." +COM_GETBIBLE_VERSES_N_ITEMS_CHECKED_IN_0="No Verse successfully checked in." +COM_GETBIBLE_VERSES_N_ITEMS_CHECKED_IN_1="%d Verse successfully checked in." +COM_GETBIBLE_VERSES_N_ITEMS_CHECKED_IN_MORE="%d Verses successfully checked in." +COM_GETBIBLE_VERSES_N_ITEMS_DELETED="%s Verses deleted." +COM_GETBIBLE_VERSES_N_ITEMS_DELETED_1="%s Verse deleted." +COM_GETBIBLE_VERSES_N_ITEMS_FAILED_PUBLISHING="%s Verses failed publishing." +COM_GETBIBLE_VERSES_N_ITEMS_FAILED_PUBLISHING_1="%s Verse failed publishing." +COM_GETBIBLE_VERSES_N_ITEMS_FEATURED="%s Verses featured." +COM_GETBIBLE_VERSES_N_ITEMS_FEATURED_1="%s Verse featured." +COM_GETBIBLE_VERSES_N_ITEMS_PUBLISHED="%s Verses published." +COM_GETBIBLE_VERSES_N_ITEMS_PUBLISHED_1="%s Verse published." +COM_GETBIBLE_VERSES_N_ITEMS_TRASHED="%s Verses trashed." +COM_GETBIBLE_VERSES_N_ITEMS_TRASHED_1="%s Verse trashed." +COM_GETBIBLE_VERSES_N_ITEMS_UNFEATURED="%s Verses unfeatured." +COM_GETBIBLE_VERSES_N_ITEMS_UNFEATURED_1="%s Verse unfeatured." +COM_GETBIBLE_VERSES_N_ITEMS_UNPUBLISHED="%s Verses unpublished." +COM_GETBIBLE_VERSES_N_ITEMS_UNPUBLISHED_1="%s Verse unpublished." +COM_GETBIBLE_VERSES_SUBMENU="Verses Submenu" +COM_GETBIBLE_VERSES_SUBMENU_DESC="Allows the users in this group to submenu of verse" +COM_GETBIBLE_VERSE_ABBREVIATION_DESCRIPTION="Select a Bible translation" +COM_GETBIBLE_VERSE_ABBREVIATION_LABEL="Translation" +COM_GETBIBLE_VERSE_BOOK_NR_DESCRIPTION="Select the book number" +COM_GETBIBLE_VERSE_BOOK_NR_LABEL="Book Number" +COM_GETBIBLE_VERSE_CHAPTER_DESCRIPTION="Select the chapter number" +COM_GETBIBLE_VERSE_CHAPTER_LABEL="Chapter" +COM_GETBIBLE_VERSE_CREATED_BY_DESC="The user that created this Verse." +COM_GETBIBLE_VERSE_CREATED_BY_LABEL="Created By" +COM_GETBIBLE_VERSE_CREATED_DATE_DESC="The date this Verse was created." +COM_GETBIBLE_VERSE_CREATED_DATE_LABEL="Created Date" +COM_GETBIBLE_VERSE_DETAILS="Details" +COM_GETBIBLE_VERSE_ERROR_UNIQUE_ALIAS="Another Verse has the same alias." +COM_GETBIBLE_VERSE_ID="Id" +COM_GETBIBLE_VERSE_MODIFIED_BY_DESC="The last user that modified this Verse." +COM_GETBIBLE_VERSE_MODIFIED_BY_LABEL="Modified By" +COM_GETBIBLE_VERSE_MODIFIED_DATE_DESC="The date this Verse was modified." +COM_GETBIBLE_VERSE_MODIFIED_DATE_LABEL="Modified Date" +COM_GETBIBLE_VERSE_NAME_DESCRIPTION="Enter Name Here" +COM_GETBIBLE_VERSE_NAME_HINT="Name Here" +COM_GETBIBLE_VERSE_NAME_LABEL="Name" +COM_GETBIBLE_VERSE_NAME_MESSAGE="Error! Please add name here." +COM_GETBIBLE_VERSE_ORDERING_LABEL="Ordering" +COM_GETBIBLE_VERSE_PERMISSION="Permissions" +COM_GETBIBLE_VERSE_PUBLISHING="Publishing" +COM_GETBIBLE_VERSE_READONLY="Verse :: Readonly" +COM_GETBIBLE_VERSE_SAVE_WARNING="Alias already existed so a number was added at the end. You can re-edit the Verse to customise the alias." +COM_GETBIBLE_VERSE_STATUS="Status" +COM_GETBIBLE_VERSE_TEXT_DESCRIPTION="The Holy Scripture (do not change)" +COM_GETBIBLE_VERSE_TEXT_HINT="// Will be added during install of translations" +COM_GETBIBLE_VERSE_TEXT_LABEL="Scripture (verse)" +COM_GETBIBLE_VERSE_VERSE_DESCRIPTION="Select the verse number" +COM_GETBIBLE_VERSE_VERSE_LABEL="Verse" +COM_GETBIBLE_VERSE_VERSION_DESC="A count of the number of times this Verse has been revised." +COM_GETBIBLE_VERSE_VERSION_LABEL="Version" +COM_GETBIBLE_VERSION="Version" +COM_GETBIBLE_WEBSITE="Website" +COM_GETBIBLE_WITHOUT_SELECTING_THE_CORRECT_FAVOURITE_VERSE_YOU_CANT_PERFORM_THE_INITIAL_ACTION="Without selecting the correct favourite verse, you can't perform the initial action." +COM_GETBIBLE_YOU_ARE_CURRENTLY_VIEWING_THE_TRASHED_ITEMS="You are currently viewing the trashed items." +COM_GETBIBLE_YOU_ARE_CURRENTLY_VIEWING_THE_TRASH_AREA_AND_YOU_DONT_HAVE_ANY_ITEMS_IN_TRASH_AT_THE_MOMENT="You are currently viewing the trash area, and you don't have any items in trash at the moment!" +COM_GETBIBLE_YOU_CAN_DIRECTLY_DOWNLOAD_THE_LATEST_UPDATE_OR_USE_THE_JOOMLA_UPDATE_AREA="You can directly download the latest update, or use the Joomla update area." +COM_GETBIBLE_YOU_WILL_HAVE_TO_ENABLE_OPEN_AI_IN_THE_GLOBAL_OPTIONS_OF_YOUR_COMPONENT_SINCE_IT_IS_CURRENTLY_DISABLED="You will have to enable Open AI in the global options of your component, since it is currently disabled." \ No newline at end of file diff --git a/admin/language/en-GB/en-GB.com_getbible.sys.ini b/admin/language/en-GB/en-GB.com_getbible.sys.ini new file mode 100644 index 0000000..ef86291 --- /dev/null +++ b/admin/language/en-GB/en-GB.com_getbible.sys.ini @@ -0,0 +1,523 @@ +COM_GETBIBLE="Get Bible" +COM_GETBIBLE_BOOKS_ACCESS="Books Access" +COM_GETBIBLE_BOOKS_ACCESS_DESC="Allows the users in this group to access access books" +COM_GETBIBLE_BOOKS_BATCH_USE="Books Batch Use" +COM_GETBIBLE_BOOKS_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch books" +COM_GETBIBLE_BOOKS_CREATE="Books Create" +COM_GETBIBLE_BOOKS_CREATE_DESC="Allows the users in this group to create create books" +COM_GETBIBLE_BOOKS_DASHBOARD_LIST="Books Dashboard List" +COM_GETBIBLE_BOOKS_DASHBOARD_LIST_DESC="Allows the users in this group to dashboard list of book" +COM_GETBIBLE_BOOKS_DELETE="Books Delete" +COM_GETBIBLE_BOOKS_DELETE_DESC="Allows the users in this group to delete delete books" +COM_GETBIBLE_BOOKS_EDIT="Books Edit" +COM_GETBIBLE_BOOKS_EDIT_ABBREVIATION="Books Edit Abbreviation" +COM_GETBIBLE_BOOKS_EDIT_ABBREVIATION_DESC="Allows the users in this group to edit abbreviation of book" +COM_GETBIBLE_BOOKS_EDIT_CREATED_BY="Books Edit Created By" +COM_GETBIBLE_BOOKS_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by books" +COM_GETBIBLE_BOOKS_EDIT_CREATED_DATE="Books Edit Created Date" +COM_GETBIBLE_BOOKS_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created books" +COM_GETBIBLE_BOOKS_EDIT_DESC="Allows the users in this group to edit the book" +COM_GETBIBLE_BOOKS_EDIT_NAME="Books Edit Name" +COM_GETBIBLE_BOOKS_EDIT_NAME_DESC="Allows the users in this group to edit name of book" +COM_GETBIBLE_BOOKS_EDIT_NR="Books Edit Nr" +COM_GETBIBLE_BOOKS_EDIT_NR_DESC="Allows the users in this group to edit nr of book" +COM_GETBIBLE_BOOKS_EDIT_OWN="Books Edit Own" +COM_GETBIBLE_BOOKS_EDIT_OWN_DESC="Allows the users in this group to edit edit own books created by them" +COM_GETBIBLE_BOOKS_EDIT_SHA="Books Edit Sha" +COM_GETBIBLE_BOOKS_EDIT_SHA_DESC="Allows the users in this group to edit sha of book" +COM_GETBIBLE_BOOKS_EDIT_STATE="Books Edit State" +COM_GETBIBLE_BOOKS_EDIT_STATE_DESC="Allows the users in this group to update the state of the book" +COM_GETBIBLE_BOOKS_SUBMENU="Books Submenu" +COM_GETBIBLE_BOOKS_SUBMENU_DESC="Allows the users in this group to submenu of book" +COM_GETBIBLE_CHAPTERS_ACCESS="Chapters Access" +COM_GETBIBLE_CHAPTERS_ACCESS_DESC="Allows the users in this group to access access chapters" +COM_GETBIBLE_CHAPTERS_BATCH_USE="Chapters Batch Use" +COM_GETBIBLE_CHAPTERS_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch chapters" +COM_GETBIBLE_CHAPTERS_CREATE="Chapters Create" +COM_GETBIBLE_CHAPTERS_CREATE_DESC="Allows the users in this group to create create chapters" +COM_GETBIBLE_CHAPTERS_DASHBOARD_LIST="Chapters Dashboard List" +COM_GETBIBLE_CHAPTERS_DASHBOARD_LIST_DESC="Allows the users in this group to dashboard list of chapter" +COM_GETBIBLE_CHAPTERS_DELETE="Chapters Delete" +COM_GETBIBLE_CHAPTERS_DELETE_DESC="Allows the users in this group to delete delete chapters" +COM_GETBIBLE_CHAPTERS_EDIT="Chapters Edit" +COM_GETBIBLE_CHAPTERS_EDIT_ABBREVIATION="Chapters Edit Abbreviation" +COM_GETBIBLE_CHAPTERS_EDIT_ABBREVIATION_DESC="Allows the users in this group to edit abbreviation of chapter" +COM_GETBIBLE_CHAPTERS_EDIT_BOOK_NR="Chapters Edit Book Nr" +COM_GETBIBLE_CHAPTERS_EDIT_BOOK_NR_DESC="Allows the users in this group to edit book nr of chapter" +COM_GETBIBLE_CHAPTERS_EDIT_CHAPTER="Chapters Edit Chapter" +COM_GETBIBLE_CHAPTERS_EDIT_CHAPTER_DESC="Allows the users in this group to edit chapter of chapter" +COM_GETBIBLE_CHAPTERS_EDIT_CREATED_BY="Chapters Edit Created By" +COM_GETBIBLE_CHAPTERS_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by chapters" +COM_GETBIBLE_CHAPTERS_EDIT_CREATED_DATE="Chapters Edit Created Date" +COM_GETBIBLE_CHAPTERS_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created chapters" +COM_GETBIBLE_CHAPTERS_EDIT_DESC="Allows the users in this group to edit the chapter" +COM_GETBIBLE_CHAPTERS_EDIT_NAME="Chapters Edit Name" +COM_GETBIBLE_CHAPTERS_EDIT_NAME_DESC="Allows the users in this group to edit name of chapter" +COM_GETBIBLE_CHAPTERS_EDIT_OWN="Chapters Edit Own" +COM_GETBIBLE_CHAPTERS_EDIT_OWN_DESC="Allows the users in this group to edit edit own chapters created by them" +COM_GETBIBLE_CHAPTERS_EDIT_SHA="Chapters Edit Sha" +COM_GETBIBLE_CHAPTERS_EDIT_SHA_DESC="Allows the users in this group to edit sha of chapter" +COM_GETBIBLE_CHAPTERS_EDIT_STATE="Chapters Edit State" +COM_GETBIBLE_CHAPTERS_EDIT_STATE_DESC="Allows the users in this group to update the state of the chapter" +COM_GETBIBLE_CHAPTERS_SUBMENU="Chapters Submenu" +COM_GETBIBLE_CHAPTERS_SUBMENU_DESC="Allows the users in this group to submenu of chapter" +COM_GETBIBLE_CONFIGURATION="Get Bible Configuration" +COM_GETBIBLE_EDIT_CREATED_BY="Edit Created By" +COM_GETBIBLE_EDIT_CREATED_BY_DESC="Allows users in this group to edit created by." +COM_GETBIBLE_EDIT_CREATED_DATE="Edit Created Date" +COM_GETBIBLE_EDIT_CREATED_DATE_DESC="Allows users in this group to edit created date." +COM_GETBIBLE_EDIT_VERSIONS="Edit Version" +COM_GETBIBLE_EDIT_VERSIONS_DESC="Allows users in this group to edit versions." +COM_GETBIBLE_LINKERS_ACCESS="Linkers Access" +COM_GETBIBLE_LINKERS_ACCESS_DESC="Allows the users in this group to access access linkers" +COM_GETBIBLE_LINKERS_BATCH_USE="Linkers Batch Use" +COM_GETBIBLE_LINKERS_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch linkers" +COM_GETBIBLE_LINKERS_CREATE="Linkers Create" +COM_GETBIBLE_LINKERS_CREATE_DESC="Allows the users in this group to create create linkers" +COM_GETBIBLE_LINKERS_DASHBOARD_LIST="Linkers Dashboard List" +COM_GETBIBLE_LINKERS_DASHBOARD_LIST_DESC="Allows the users in this group to dashboard list of linker" +COM_GETBIBLE_LINKERS_DELETE="Linkers Delete" +COM_GETBIBLE_LINKERS_DELETE_DESC="Allows the users in this group to delete delete linkers" +COM_GETBIBLE_LINKERS_EDIT="Linkers Edit" +COM_GETBIBLE_LINKERS_EDIT_CREATED_BY="Linkers Edit Created By" +COM_GETBIBLE_LINKERS_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by linkers" +COM_GETBIBLE_LINKERS_EDIT_CREATED_DATE="Linkers Edit Created Date" +COM_GETBIBLE_LINKERS_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created linkers" +COM_GETBIBLE_LINKERS_EDIT_DESC="Allows the users in this group to edit the linker" +COM_GETBIBLE_LINKERS_EDIT_GUID="Linkers Edit Guid" +COM_GETBIBLE_LINKERS_EDIT_GUID_DESC="Allows the users in this group to edit guid of linker" +COM_GETBIBLE_LINKERS_EDIT_NAME="Linkers Edit Name" +COM_GETBIBLE_LINKERS_EDIT_NAME_DESC="Allows the users in this group to edit name of linker" +COM_GETBIBLE_LINKERS_EDIT_OWN="Linkers Edit Own" +COM_GETBIBLE_LINKERS_EDIT_OWN_DESC="Allows the users in this group to edit edit own linkers created by them" +COM_GETBIBLE_LINKERS_EDIT_STATE="Linkers Edit State" +COM_GETBIBLE_LINKERS_EDIT_STATE_DESC="Allows the users in this group to update the state of the linker" +COM_GETBIBLE_LINKERS_SUBMENU="Linkers Submenu" +COM_GETBIBLE_LINKERS_SUBMENU_DESC="Allows the users in this group to submenu of linker" +COM_GETBIBLE_MENU="Get Bible" +COM_GETBIBLE_MENU_API_DESC="Api" +COM_GETBIBLE_MENU_API_OPTION="Api" +COM_GETBIBLE_MENU_API_TITLE="Api" +COM_GETBIBLE_MENU_APP_DESC="App" +COM_GETBIBLE_MENU_APP_OPTION="App" +COM_GETBIBLE_MENU_APP_TITLE="App" +COM_GETBIBLE_MENU_BOOKS="Books" +COM_GETBIBLE_MENU_CHAPTERS="Chapters" +COM_GETBIBLE_MENU_LINKERS="Linkers" +COM_GETBIBLE_MENU_NOTES="Notes" +COM_GETBIBLE_MENU_OPEN_AI_RESPONSES="Open AI Responses" +COM_GETBIBLE_MENU_PROMPTS="Prompts" +COM_GETBIBLE_MENU_TAGGED_VERSES="Tagged Verses" +COM_GETBIBLE_MENU_TAGS="Tags" +COM_GETBIBLE_MENU_TRANSLATIONS="Translations" +COM_GETBIBLE_MENU_VERSES="Verses" +COM_GETBIBLE_NOTES_ACCESS="Notes Access" +COM_GETBIBLE_NOTES_ACCESS_DESC="Allows the users in this group to access access notes" +COM_GETBIBLE_NOTES_BATCH_USE="Notes Batch Use" +COM_GETBIBLE_NOTES_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch notes" +COM_GETBIBLE_NOTES_CREATE="Notes Create" +COM_GETBIBLE_NOTES_CREATE_DESC="Allows the users in this group to create create notes" +COM_GETBIBLE_NOTES_DASHBOARD_LIST="Notes Dashboard List" +COM_GETBIBLE_NOTES_DASHBOARD_LIST_DESC="Allows the users in this group to dashboard list of note" +COM_GETBIBLE_NOTES_DELETE="Notes Delete" +COM_GETBIBLE_NOTES_DELETE_DESC="Allows the users in this group to delete delete notes" +COM_GETBIBLE_NOTES_EDIT="Notes Edit" +COM_GETBIBLE_NOTES_EDIT_ACCESS="Notes Edit Access" +COM_GETBIBLE_NOTES_EDIT_ACCESS_DESC="Allows the users in this group to change the access of the edit access notes" +COM_GETBIBLE_NOTES_EDIT_BOOK_NR="Notes Edit Book Nr" +COM_GETBIBLE_NOTES_EDIT_BOOK_NR_DESC="Allows the users in this group to edit book nr of note" +COM_GETBIBLE_NOTES_EDIT_CHAPTER="Notes Edit Chapter" +COM_GETBIBLE_NOTES_EDIT_CHAPTER_DESC="Allows the users in this group to edit chapter of note" +COM_GETBIBLE_NOTES_EDIT_CREATED_BY="Notes Edit Created By" +COM_GETBIBLE_NOTES_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by notes" +COM_GETBIBLE_NOTES_EDIT_CREATED_DATE="Notes Edit Created Date" +COM_GETBIBLE_NOTES_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created notes" +COM_GETBIBLE_NOTES_EDIT_DESC="Allows the users in this group to edit the note" +COM_GETBIBLE_NOTES_EDIT_GUID="Notes Edit Guid" +COM_GETBIBLE_NOTES_EDIT_GUID_DESC="Allows the users in this group to edit guid of note" +COM_GETBIBLE_NOTES_EDIT_LINKER="Notes Edit Linker" +COM_GETBIBLE_NOTES_EDIT_LINKER_DESC="Allows the users in this group to edit linker of note" +COM_GETBIBLE_NOTES_EDIT_NOTE="Notes Edit Note" +COM_GETBIBLE_NOTES_EDIT_NOTE_DESC="Allows the users in this group to edit note of note" +COM_GETBIBLE_NOTES_EDIT_OWN="Notes Edit Own" +COM_GETBIBLE_NOTES_EDIT_OWN_DESC="Allows the users in this group to edit edit own notes created by them" +COM_GETBIBLE_NOTES_EDIT_STATE="Notes Edit State" +COM_GETBIBLE_NOTES_EDIT_STATE_DESC="Allows the users in this group to update the state of the note" +COM_GETBIBLE_NOTES_EDIT_VERSE="Notes Edit Verse" +COM_GETBIBLE_NOTES_EDIT_VERSE_DESC="Allows the users in this group to edit verse of note" +COM_GETBIBLE_NOTES_EDIT_VERSION="Notes Edit Version" +COM_GETBIBLE_NOTES_EDIT_VERSION_DESC="Allows users in this group to edit versions of version notes" +COM_GETBIBLE_NOTES_SUBMENU="Notes Submenu" +COM_GETBIBLE_NOTES_SUBMENU_DESC="Allows the users in this group to submenu of note" +COM_GETBIBLE_OPEN_AI_MESSAGES_ACCESS="Open Ai Messages Access" +COM_GETBIBLE_OPEN_AI_MESSAGES_ACCESS_DESC="Allows the users in this group to access access open ai messages" +COM_GETBIBLE_OPEN_AI_MESSAGES_BATCH_USE="Open Ai Messages Batch Use" +COM_GETBIBLE_OPEN_AI_MESSAGES_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch open ai messages" +COM_GETBIBLE_OPEN_AI_MESSAGES_CREATE="Open Ai Messages Create" +COM_GETBIBLE_OPEN_AI_MESSAGES_CREATE_DESC="Allows the users in this group to create create open ai messages" +COM_GETBIBLE_OPEN_AI_MESSAGES_DELETE="Open Ai Messages Delete" +COM_GETBIBLE_OPEN_AI_MESSAGES_DELETE_DESC="Allows the users in this group to delete delete open ai messages" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT="Open Ai Messages Edit" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_CONTENT="Open Ai Messages Edit Content" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_CONTENT_DESC="Allows the users in this group to edit content of open ai message" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_CREATED_BY="Open Ai Messages Edit Created By" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by open ai messages" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_CREATED_DATE="Open Ai Messages Edit Created Date" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created open ai messages" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_DESC="Allows the users in this group to edit the open ai message" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_INDEX="Open Ai Messages Edit Index" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_INDEX_DESC="Allows the users in this group to edit index of open ai message" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_NAME="Open Ai Messages Edit Name" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_NAME_DESC="Allows the users in this group to edit name of open ai message" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_OPEN_AI_RESPONSE="Open Ai Messages Edit Open Ai Response" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_OPEN_AI_RESPONSE_DESC="Allows the users in this group to edit open ai response of open ai message" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_OWN="Open Ai Messages Edit Own" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_OWN_DESC="Allows the users in this group to edit edit own open ai messages created by them" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_PROMPT="Open Ai Messages Edit Prompt" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_PROMPT_DESC="Allows the users in this group to edit prompt of open ai message" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_ROLE="Open Ai Messages Edit Role" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_ROLE_DESC="Allows the users in this group to edit role of open ai message" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_SOURCE="Open Ai Messages Edit Source" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_SOURCE_DESC="Allows the users in this group to edit source of open ai message" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_STATE="Open Ai Messages Edit State" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_STATE_DESC="Allows the users in this group to update the state of the open ai message" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_VERSION="Open Ai Messages Edit Version" +COM_GETBIBLE_OPEN_AI_MESSAGES_EDIT_VERSION_DESC="Allows users in this group to edit versions of version open ai messages" +COM_GETBIBLE_OPEN_AI_RESPONSES_ACCESS="Open Ai Responses Access" +COM_GETBIBLE_OPEN_AI_RESPONSES_ACCESS_DESC="Allows the users in this group to access access open ai responses" +COM_GETBIBLE_OPEN_AI_RESPONSES_BATCH_USE="Open Ai Responses Batch Use" +COM_GETBIBLE_OPEN_AI_RESPONSES_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch open ai responses" +COM_GETBIBLE_OPEN_AI_RESPONSES_CREATE="Open Ai Responses Create" +COM_GETBIBLE_OPEN_AI_RESPONSES_CREATE_DESC="Allows the users in this group to create create open ai responses" +COM_GETBIBLE_OPEN_AI_RESPONSES_DASHBOARD_LIST="Open Ai Responses Dashboard List" +COM_GETBIBLE_OPEN_AI_RESPONSES_DASHBOARD_LIST_DESC="Allows the users in this group to dashboard list of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_DELETE="Open Ai Responses Delete" +COM_GETBIBLE_OPEN_AI_RESPONSES_DELETE_DESC="Allows the users in this group to delete delete open ai responses" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT="Open Ai Responses Edit" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_ABBREVIATION="Open Ai Responses Edit Abbreviation" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_ABBREVIATION_DESC="Allows the users in this group to edit abbreviation of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_BOOK="Open Ai Responses Edit Book" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_BOOK_DESC="Allows the users in this group to edit book of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_CHAPTER="Open Ai Responses Edit Chapter" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_CHAPTER_DESC="Allows the users in this group to edit chapter of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_COMPLETION_TOKENS="Open Ai Responses Edit Completion Tokens" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_COMPLETION_TOKENS_DESC="Allows the users in this group to edit completion tokens of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_CREATED_BY="Open Ai Responses Edit Created By" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by open ai responses" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_CREATED_DATE="Open Ai Responses Edit Created Date" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created open ai responses" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_DESC="Allows the users in this group to edit the open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_FREQUENCY_PENALTY="Open Ai Responses Edit Frequency Penalty" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_FREQUENCY_PENALTY_DESC="Allows the users in this group to edit frequency penalty of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_LANGUAGE="Open Ai Responses Edit Language" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_LANGUAGE_DESC="Allows the users in this group to edit language of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_LCSH="Open Ai Responses Edit Lcsh" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_LCSH_DESC="Allows the users in this group to edit lcsh of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_MAX_TOKENS="Open Ai Responses Edit Max Tokens" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_MAX_TOKENS_DESC="Allows the users in this group to edit max tokens of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_MODEL="Open Ai Responses Edit Model" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_MODEL_DESC="Allows the users in this group to edit model of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_N="Open Ai Responses Edit N" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_N_DESC="Allows the users in this group to edit n of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_OWN="Open Ai Responses Edit Own" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_OWN_DESC="Allows the users in this group to edit edit own open ai responses created by them" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_PRESENCE_PENALTY="Open Ai Responses Edit Presence Penalty" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_PRESENCE_PENALTY_DESC="Allows the users in this group to edit presence penalty of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_PROMPT="Open Ai Responses Edit Prompt" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_PROMPT_DESC="Allows the users in this group to edit prompt of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_PROMPT_TOKENS="Open Ai Responses Edit Prompt Tokens" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_PROMPT_TOKENS_DESC="Allows the users in this group to edit prompt tokens of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_RESPONSE_CREATED="Open Ai Responses Edit Response Created" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_RESPONSE_CREATED_DESC="Allows the users in this group to edit response created of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_RESPONSE_ID="Open Ai Responses Edit Response Id" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_RESPONSE_ID_DESC="Allows the users in this group to edit response id of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_RESPONSE_MODEL="Open Ai Responses Edit Response Model" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_RESPONSE_MODEL_DESC="Allows the users in this group to edit response model of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_RESPONSE_OBJECT="Open Ai Responses Edit Response Object" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_RESPONSE_OBJECT_DESC="Allows the users in this group to edit response object of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_SELECTED_WORD="Open Ai Responses Edit Selected Word" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_SELECTED_WORD_DESC="Allows the users in this group to edit selected word of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_STATE="Open Ai Responses Edit State" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_STATE_DESC="Allows the users in this group to update the state of the open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_TEMPERATURE="Open Ai Responses Edit Temperature" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_TEMPERATURE_DESC="Allows the users in this group to edit temperature of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_TOP_P="Open Ai Responses Edit Top P" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_TOP_P_DESC="Allows the users in this group to edit top p of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_TOTAL_TOKENS="Open Ai Responses Edit Total Tokens" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_TOTAL_TOKENS_DESC="Allows the users in this group to edit total tokens of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_VERSE="Open Ai Responses Edit Verse" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_VERSE_DESC="Allows the users in this group to edit verse of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_VERSION="Open Ai Responses Edit Version" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_VERSION_DESC="Allows users in this group to edit versions of version open ai responses" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_WORD="Open Ai Responses Edit Word" +COM_GETBIBLE_OPEN_AI_RESPONSES_EDIT_WORD_DESC="Allows the users in this group to edit word of open ai response" +COM_GETBIBLE_OPEN_AI_RESPONSES_SUBMENU="Open Ai Responses Submenu" +COM_GETBIBLE_OPEN_AI_RESPONSES_SUBMENU_DESC="Allows the users in this group to submenu of open ai response" +COM_GETBIBLE_PASSWORDS_ACCESS="Passwords Access" +COM_GETBIBLE_PASSWORDS_ACCESS_DESC="Allows the users in this group to access access passwords" +COM_GETBIBLE_PASSWORDS_ACCESS_PASSWORD="Passwords Access Password" +COM_GETBIBLE_PASSWORDS_ACCESS_PASSWORD_DESC="Allows the users in this group to access password of password" +COM_GETBIBLE_PASSWORDS_BATCH_USE="Passwords Batch Use" +COM_GETBIBLE_PASSWORDS_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch passwords" +COM_GETBIBLE_PASSWORDS_CREATE="Passwords Create" +COM_GETBIBLE_PASSWORDS_CREATE_DESC="Allows the users in this group to create create passwords" +COM_GETBIBLE_PASSWORDS_DELETE="Passwords Delete" +COM_GETBIBLE_PASSWORDS_DELETE_DESC="Allows the users in this group to delete delete passwords" +COM_GETBIBLE_PASSWORDS_EDIT="Passwords Edit" +COM_GETBIBLE_PASSWORDS_EDIT_CREATED_BY="Passwords Edit Created By" +COM_GETBIBLE_PASSWORDS_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by passwords" +COM_GETBIBLE_PASSWORDS_EDIT_CREATED_DATE="Passwords Edit Created Date" +COM_GETBIBLE_PASSWORDS_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created passwords" +COM_GETBIBLE_PASSWORDS_EDIT_DESC="Allows the users in this group to edit the password" +COM_GETBIBLE_PASSWORDS_EDIT_GUID="Passwords Edit Guid" +COM_GETBIBLE_PASSWORDS_EDIT_GUID_DESC="Allows the users in this group to edit guid of password" +COM_GETBIBLE_PASSWORDS_EDIT_LINKER="Passwords Edit Linker" +COM_GETBIBLE_PASSWORDS_EDIT_LINKER_DESC="Allows the users in this group to edit linker of password" +COM_GETBIBLE_PASSWORDS_EDIT_NAME="Passwords Edit Name" +COM_GETBIBLE_PASSWORDS_EDIT_NAME_DESC="Allows the users in this group to edit name of password" +COM_GETBIBLE_PASSWORDS_EDIT_OWN="Passwords Edit Own" +COM_GETBIBLE_PASSWORDS_EDIT_OWN_DESC="Allows the users in this group to edit edit own passwords created by them" +COM_GETBIBLE_PASSWORDS_EDIT_PASSWORD="Passwords Edit Password" +COM_GETBIBLE_PASSWORDS_EDIT_PASSWORD_DESC="Allows the users in this group to edit password of password" +COM_GETBIBLE_PASSWORDS_EDIT_STATE="Passwords Edit State" +COM_GETBIBLE_PASSWORDS_EDIT_STATE_DESC="Allows the users in this group to update the state of the password" +COM_GETBIBLE_PASSWORDS_VIEW_PASSWORD="Passwords View Password" +COM_GETBIBLE_PASSWORDS_VIEW_PASSWORD_DESC="Allows the users in this group to view password of password" +COM_GETBIBLE_PROMPTS_ACCESS="Prompts Access" +COM_GETBIBLE_PROMPTS_ACCESS_DESC="Allows the users in this group to access access prompts" +COM_GETBIBLE_PROMPTS_ACCESS_TEMPERATURE_OVERRIDE="Prompts Access Temperature Override" +COM_GETBIBLE_PROMPTS_ACCESS_TEMPERATURE_OVERRIDE_DESC="Allows the users in this group to access temperature override of prompt" +COM_GETBIBLE_PROMPTS_BATCH_USE="Prompts Batch Use" +COM_GETBIBLE_PROMPTS_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch prompts" +COM_GETBIBLE_PROMPTS_CREATE="Prompts Create" +COM_GETBIBLE_PROMPTS_CREATE_DESC="Allows the users in this group to create create prompts" +COM_GETBIBLE_PROMPTS_DASHBOARD_LIST="Prompts Dashboard List" +COM_GETBIBLE_PROMPTS_DASHBOARD_LIST_DESC="Allows the users in this group to dashboard list of prompt" +COM_GETBIBLE_PROMPTS_DELETE="Prompts Delete" +COM_GETBIBLE_PROMPTS_DELETE_DESC="Allows the users in this group to delete delete prompts" +COM_GETBIBLE_PROMPTS_EDIT="Prompts Edit" +COM_GETBIBLE_PROMPTS_EDIT_ABBREVIATION="Prompts Edit Abbreviation" +COM_GETBIBLE_PROMPTS_EDIT_ABBREVIATION_DESC="Allows the users in this group to edit abbreviation of prompt" +COM_GETBIBLE_PROMPTS_EDIT_AI_ORG_TOKEN_OVERRIDE="Prompts Edit Ai Org Token Override" +COM_GETBIBLE_PROMPTS_EDIT_AI_ORG_TOKEN_OVERRIDE_DESC="Allows the users in this group to edit ai org token override of prompt" +COM_GETBIBLE_PROMPTS_EDIT_CACHE_BEHAVIOUR="Prompts Edit Cache Behaviour" +COM_GETBIBLE_PROMPTS_EDIT_CACHE_BEHAVIOUR_DESC="Allows the users in this group to edit cache behaviour of prompt" +COM_GETBIBLE_PROMPTS_EDIT_CREATED_BY="Prompts Edit Created By" +COM_GETBIBLE_PROMPTS_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by prompts" +COM_GETBIBLE_PROMPTS_EDIT_CREATED_DATE="Prompts Edit Created Date" +COM_GETBIBLE_PROMPTS_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created prompts" +COM_GETBIBLE_PROMPTS_EDIT_DESC="Allows the users in this group to edit the prompt" +COM_GETBIBLE_PROMPTS_EDIT_FREQUENCY_PENALTY="Prompts Edit Frequency Penalty" +COM_GETBIBLE_PROMPTS_EDIT_FREQUENCY_PENALTY_DESC="Allows the users in this group to edit frequency penalty of prompt" +COM_GETBIBLE_PROMPTS_EDIT_FREQUENCY_PENALTY_OVERRIDE="Prompts Edit Frequency Penalty Override" +COM_GETBIBLE_PROMPTS_EDIT_FREQUENCY_PENALTY_OVERRIDE_DESC="Allows the users in this group to edit frequency penalty override of prompt" +COM_GETBIBLE_PROMPTS_EDIT_GUID="Prompts Edit Guid" +COM_GETBIBLE_PROMPTS_EDIT_GUID_DESC="Allows the users in this group to edit guid of prompt" +COM_GETBIBLE_PROMPTS_EDIT_INTEGRATION="Prompts Edit Integration" +COM_GETBIBLE_PROMPTS_EDIT_INTEGRATION_DESC="Allows the users in this group to edit integration of prompt" +COM_GETBIBLE_PROMPTS_EDIT_MAX_TOKENS="Prompts Edit Max Tokens" +COM_GETBIBLE_PROMPTS_EDIT_MAX_TOKENS_DESC="Allows the users in this group to edit max tokens of prompt" +COM_GETBIBLE_PROMPTS_EDIT_MAX_TOKENS_OVERRIDE="Prompts Edit Max Tokens Override" +COM_GETBIBLE_PROMPTS_EDIT_MAX_TOKENS_OVERRIDE_DESC="Allows the users in this group to edit max tokens override of prompt" +COM_GETBIBLE_PROMPTS_EDIT_MESSAGES="Prompts Edit Messages" +COM_GETBIBLE_PROMPTS_EDIT_MESSAGES_DESC="Allows the users in this group to edit messages of prompt" +COM_GETBIBLE_PROMPTS_EDIT_MODEL="Prompts Edit Model" +COM_GETBIBLE_PROMPTS_EDIT_MODEL_DESC="Allows the users in this group to edit model of prompt" +COM_GETBIBLE_PROMPTS_EDIT_N="Prompts Edit N" +COM_GETBIBLE_PROMPTS_EDIT_NAME="Prompts Edit Name" +COM_GETBIBLE_PROMPTS_EDIT_NAME_DESC="Allows the users in this group to edit name of prompt" +COM_GETBIBLE_PROMPTS_EDIT_N_DESC="Allows the users in this group to edit n of prompt" +COM_GETBIBLE_PROMPTS_EDIT_N_OVERRIDE="Prompts Edit N Override" +COM_GETBIBLE_PROMPTS_EDIT_N_OVERRIDE_DESC="Allows the users in this group to edit n override of prompt" +COM_GETBIBLE_PROMPTS_EDIT_ORG_TOKEN="Prompts Edit Org Token" +COM_GETBIBLE_PROMPTS_EDIT_ORG_TOKEN_DESC="Allows the users in this group to edit org token of prompt" +COM_GETBIBLE_PROMPTS_EDIT_OWN="Prompts Edit Own" +COM_GETBIBLE_PROMPTS_EDIT_OWN_DESC="Allows the users in this group to edit edit own prompts created by them" +COM_GETBIBLE_PROMPTS_EDIT_PRESENCE_PENALTY="Prompts Edit Presence Penalty" +COM_GETBIBLE_PROMPTS_EDIT_PRESENCE_PENALTY_DESC="Allows the users in this group to edit presence penalty of prompt" +COM_GETBIBLE_PROMPTS_EDIT_PRESENCE_PENALTY_OVERRIDE="Prompts Edit Presence Penalty Override" +COM_GETBIBLE_PROMPTS_EDIT_PRESENCE_PENALTY_OVERRIDE_DESC="Allows the users in this group to edit presence penalty override of prompt" +COM_GETBIBLE_PROMPTS_EDIT_RESPONSE_RETRIEVAL="Prompts Edit Response Retrieval" +COM_GETBIBLE_PROMPTS_EDIT_RESPONSE_RETRIEVAL_DESC="Allows the users in this group to edit response retrieval of prompt" +COM_GETBIBLE_PROMPTS_EDIT_STATE="Prompts Edit State" +COM_GETBIBLE_PROMPTS_EDIT_STATE_DESC="Allows the users in this group to update the state of the prompt" +COM_GETBIBLE_PROMPTS_EDIT_TEMPERATURE="Prompts Edit Temperature" +COM_GETBIBLE_PROMPTS_EDIT_TEMPERATURE_DESC="Allows the users in this group to edit temperature of prompt" +COM_GETBIBLE_PROMPTS_EDIT_TOKEN="Prompts Edit Token" +COM_GETBIBLE_PROMPTS_EDIT_TOKEN_DESC="Allows the users in this group to edit token of prompt" +COM_GETBIBLE_PROMPTS_EDIT_TOKEN_OVERRIDE="Prompts Edit Token Override" +COM_GETBIBLE_PROMPTS_EDIT_TOKEN_OVERRIDE_DESC="Allows the users in this group to edit token override of prompt" +COM_GETBIBLE_PROMPTS_EDIT_TOP_P="Prompts Edit Top P" +COM_GETBIBLE_PROMPTS_EDIT_TOP_P_DESC="Allows the users in this group to edit top p of prompt" +COM_GETBIBLE_PROMPTS_EDIT_TOP_P_OVERRIDE="Prompts Edit Top P Override" +COM_GETBIBLE_PROMPTS_EDIT_TOP_P_OVERRIDE_DESC="Allows the users in this group to edit top p override of prompt" +COM_GETBIBLE_PROMPTS_EDIT_VERSION="Prompts Edit Version" +COM_GETBIBLE_PROMPTS_EDIT_VERSION_DESC="Allows users in this group to edit versions of version prompts" +COM_GETBIBLE_PROMPTS_SUBMENU="Prompts Submenu" +COM_GETBIBLE_PROMPTS_SUBMENU_DESC="Allows the users in this group to submenu of prompt" +COM_GETBIBLE_TAGGED_VERSES_ACCESS="Tagged Verses Access" +COM_GETBIBLE_TAGGED_VERSES_ACCESS_DESC="Allows the users in this group to access access tagged verses" +COM_GETBIBLE_TAGGED_VERSES_BATCH_USE="Tagged Verses Batch Use" +COM_GETBIBLE_TAGGED_VERSES_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch tagged verses" +COM_GETBIBLE_TAGGED_VERSES_CREATE="Tagged Verses Create" +COM_GETBIBLE_TAGGED_VERSES_CREATE_DESC="Allows the users in this group to create create tagged verses" +COM_GETBIBLE_TAGGED_VERSES_DASHBOARD_LIST="Tagged Verses Dashboard List" +COM_GETBIBLE_TAGGED_VERSES_DASHBOARD_LIST_DESC="Allows the users in this group to dashboard list of tagged verse" +COM_GETBIBLE_TAGGED_VERSES_DELETE="Tagged Verses Delete" +COM_GETBIBLE_TAGGED_VERSES_DELETE_DESC="Allows the users in this group to delete delete tagged verses" +COM_GETBIBLE_TAGGED_VERSES_EDIT="Tagged Verses Edit" +COM_GETBIBLE_TAGGED_VERSES_EDIT_ABBREVIATION="Tagged Verses Edit Abbreviation" +COM_GETBIBLE_TAGGED_VERSES_EDIT_ABBREVIATION_DESC="Allows the users in this group to edit abbreviation of tagged verse" +COM_GETBIBLE_TAGGED_VERSES_EDIT_ACCESS="Tagged Verses Edit Access" +COM_GETBIBLE_TAGGED_VERSES_EDIT_ACCESS_DESC="Allows the users in this group to change the access of the edit access tagged verses" +COM_GETBIBLE_TAGGED_VERSES_EDIT_BOOK_NR="Tagged Verses Edit Book Nr" +COM_GETBIBLE_TAGGED_VERSES_EDIT_BOOK_NR_DESC="Allows the users in this group to edit book nr of tagged verse" +COM_GETBIBLE_TAGGED_VERSES_EDIT_CHAPTER="Tagged Verses Edit Chapter" +COM_GETBIBLE_TAGGED_VERSES_EDIT_CHAPTER_DESC="Allows the users in this group to edit chapter of tagged verse" +COM_GETBIBLE_TAGGED_VERSES_EDIT_CREATED_BY="Tagged Verses Edit Created By" +COM_GETBIBLE_TAGGED_VERSES_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by tagged verses" +COM_GETBIBLE_TAGGED_VERSES_EDIT_CREATED_DATE="Tagged Verses Edit Created Date" +COM_GETBIBLE_TAGGED_VERSES_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created tagged verses" +COM_GETBIBLE_TAGGED_VERSES_EDIT_DESC="Allows the users in this group to edit the tagged verse" +COM_GETBIBLE_TAGGED_VERSES_EDIT_GUID="Tagged Verses Edit Guid" +COM_GETBIBLE_TAGGED_VERSES_EDIT_GUID_DESC="Allows the users in this group to edit guid of tagged verse" +COM_GETBIBLE_TAGGED_VERSES_EDIT_LINKER="Tagged Verses Edit Linker" +COM_GETBIBLE_TAGGED_VERSES_EDIT_LINKER_DESC="Allows the users in this group to edit linker of tagged verse" +COM_GETBIBLE_TAGGED_VERSES_EDIT_OWN="Tagged Verses Edit Own" +COM_GETBIBLE_TAGGED_VERSES_EDIT_OWN_DESC="Allows the users in this group to edit edit own tagged verses created by them" +COM_GETBIBLE_TAGGED_VERSES_EDIT_STATE="Tagged Verses Edit State" +COM_GETBIBLE_TAGGED_VERSES_EDIT_STATE_DESC="Allows the users in this group to update the state of the tagged verse" +COM_GETBIBLE_TAGGED_VERSES_EDIT_TAG="Tagged Verses Edit Tag" +COM_GETBIBLE_TAGGED_VERSES_EDIT_TAG_DESC="Allows the users in this group to edit tag of tagged verse" +COM_GETBIBLE_TAGGED_VERSES_EDIT_VERSE="Tagged Verses Edit Verse" +COM_GETBIBLE_TAGGED_VERSES_EDIT_VERSE_DESC="Allows the users in this group to edit verse of tagged verse" +COM_GETBIBLE_TAGGED_VERSES_EDIT_VERSION="Tagged Verses Edit Version" +COM_GETBIBLE_TAGGED_VERSES_EDIT_VERSION_DESC="Allows users in this group to edit versions of version tagged verses" +COM_GETBIBLE_TAGGED_VERSES_SUBMENU="Tagged Verses Submenu" +COM_GETBIBLE_TAGGED_VERSES_SUBMENU_DESC="Allows the users in this group to submenu of tagged verse" +COM_GETBIBLE_TAGS_ACCESS="Tags Access" +COM_GETBIBLE_TAGS_ACCESS_DESC="Allows the users in this group to access access tags" +COM_GETBIBLE_TAGS_BATCH_USE="Tags Batch Use" +COM_GETBIBLE_TAGS_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch tags" +COM_GETBIBLE_TAGS_CREATE="Tags Create" +COM_GETBIBLE_TAGS_CREATE_DESC="Allows the users in this group to create create tags" +COM_GETBIBLE_TAGS_DASHBOARD_LIST="Tags Dashboard List" +COM_GETBIBLE_TAGS_DASHBOARD_LIST_DESC="Allows the users in this group to dashboard list of tag" +COM_GETBIBLE_TAGS_DELETE="Tags Delete" +COM_GETBIBLE_TAGS_DELETE_DESC="Allows the users in this group to delete delete tags" +COM_GETBIBLE_TAGS_EDIT="Tags Edit" +COM_GETBIBLE_TAGS_EDIT_ACCESS="Tags Edit Access" +COM_GETBIBLE_TAGS_EDIT_ACCESS_DESC="Allows the users in this group to change the access of the edit access tags" +COM_GETBIBLE_TAGS_EDIT_CREATED_BY="Tags Edit Created By" +COM_GETBIBLE_TAGS_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by tags" +COM_GETBIBLE_TAGS_EDIT_CREATED_DATE="Tags Edit Created Date" +COM_GETBIBLE_TAGS_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created tags" +COM_GETBIBLE_TAGS_EDIT_DESC="Allows the users in this group to edit the tag" +COM_GETBIBLE_TAGS_EDIT_DESCRIPTION="Tags Edit Description" +COM_GETBIBLE_TAGS_EDIT_DESCRIPTION_DESC="Allows the users in this group to edit description of tag" +COM_GETBIBLE_TAGS_EDIT_GUID="Tags Edit Guid" +COM_GETBIBLE_TAGS_EDIT_GUID_DESC="Allows the users in this group to edit guid of tag" +COM_GETBIBLE_TAGS_EDIT_LINKER="Tags Edit Linker" +COM_GETBIBLE_TAGS_EDIT_LINKER_DESC="Allows the users in this group to edit linker of tag" +COM_GETBIBLE_TAGS_EDIT_NAME="Tags Edit Name" +COM_GETBIBLE_TAGS_EDIT_NAME_DESC="Allows the users in this group to edit name of tag" +COM_GETBIBLE_TAGS_EDIT_OWN="Tags Edit Own" +COM_GETBIBLE_TAGS_EDIT_OWN_DESC="Allows the users in this group to edit edit own tags created by them" +COM_GETBIBLE_TAGS_EDIT_STATE="Tags Edit State" +COM_GETBIBLE_TAGS_EDIT_STATE_DESC="Allows the users in this group to update the state of the tag" +COM_GETBIBLE_TAGS_EDIT_VERSION="Tags Edit Version" +COM_GETBIBLE_TAGS_EDIT_VERSION_DESC="Allows users in this group to edit versions of version tags" +COM_GETBIBLE_TAGS_SUBMENU="Tags Submenu" +COM_GETBIBLE_TAGS_SUBMENU_DESC="Allows the users in this group to submenu of tag" +COM_GETBIBLE_TRANSLATIONS_ACCESS="Translations Access" +COM_GETBIBLE_TRANSLATIONS_ACCESS_DESC="Allows the users in this group to access access translations" +COM_GETBIBLE_TRANSLATIONS_BATCH_USE="Translations Batch Use" +COM_GETBIBLE_TRANSLATIONS_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch translations" +COM_GETBIBLE_TRANSLATIONS_CREATE="Translations Create" +COM_GETBIBLE_TRANSLATIONS_CREATE_DESC="Allows the users in this group to create create translations" +COM_GETBIBLE_TRANSLATIONS_DASHBOARD_LIST="Translations Dashboard List" +COM_GETBIBLE_TRANSLATIONS_DASHBOARD_LIST_DESC="Allows the users in this group to dashboard list of translation" +COM_GETBIBLE_TRANSLATIONS_DELETE="Translations Delete" +COM_GETBIBLE_TRANSLATIONS_DELETE_DESC="Allows the users in this group to delete delete translations" +COM_GETBIBLE_TRANSLATIONS_EDIT="Translations Edit" +COM_GETBIBLE_TRANSLATIONS_EDIT_ABBREVIATION="Translations Edit Abbreviation" +COM_GETBIBLE_TRANSLATIONS_EDIT_ABBREVIATION_DESC="Allows the users in this group to edit abbreviation of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_CREATED_BY="Translations Edit Created By" +COM_GETBIBLE_TRANSLATIONS_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by translations" +COM_GETBIBLE_TRANSLATIONS_EDIT_CREATED_DATE="Translations Edit Created Date" +COM_GETBIBLE_TRANSLATIONS_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created translations" +COM_GETBIBLE_TRANSLATIONS_EDIT_DESC="Allows the users in this group to edit the translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DIRECTION="Translations Edit Direction" +COM_GETBIBLE_TRANSLATIONS_EDIT_DIRECTION_DESC="Allows the users in this group to edit direction of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_ABBREVIATION="Translations Edit Distribution Abbreviation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_ABBREVIATION_DESC="Allows the users in this group to edit distribution abbreviation of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_ABOUT="Translations Edit Distribution About" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_ABOUT_DESC="Allows the users in this group to edit distribution about of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_HISTORY="Translations Edit Distribution History" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_HISTORY_DESC="Allows the users in this group to edit distribution history of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_LCSH="Translations Edit Distribution Lcsh" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_LCSH_DESC="Allows the users in this group to edit distribution lcsh of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_LICENSE="Translations Edit Distribution License" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_LICENSE_DESC="Allows the users in this group to edit distribution license of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_SOURCE="Translations Edit Distribution Source" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_SOURCETYPE="Translations Edit Distribution Sourcetype" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_SOURCETYPE_DESC="Allows the users in this group to edit distribution sourcetype of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_SOURCE_DESC="Allows the users in this group to edit distribution source of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_VERSIFICATION="Translations Edit Distribution Versification" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_VERSIFICATION_DESC="Allows the users in this group to edit distribution versification of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_VERSION="Translations Edit Distribution Version" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_VERSION_DATE="Translations Edit Distribution Version Date" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_VERSION_DATE_DESC="Allows the users in this group to edit distribution version date of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_DISTRIBUTION_VERSION_DESC="Allows the users in this group to edit distribution version of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_ENCODING="Translations Edit Encoding" +COM_GETBIBLE_TRANSLATIONS_EDIT_ENCODING_DESC="Allows the users in this group to edit encoding of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_LANG="Translations Edit Lang" +COM_GETBIBLE_TRANSLATIONS_EDIT_LANGUAGE="Translations Edit Language" +COM_GETBIBLE_TRANSLATIONS_EDIT_LANGUAGE_DESC="Allows the users in this group to edit language of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_LANG_DESC="Allows the users in this group to edit lang of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_OWN="Translations Edit Own" +COM_GETBIBLE_TRANSLATIONS_EDIT_OWN_DESC="Allows the users in this group to edit edit own translations created by them" +COM_GETBIBLE_TRANSLATIONS_EDIT_SHA="Translations Edit Sha" +COM_GETBIBLE_TRANSLATIONS_EDIT_SHA_DESC="Allows the users in this group to edit sha of translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_STATE="Translations Edit State" +COM_GETBIBLE_TRANSLATIONS_EDIT_STATE_DESC="Allows the users in this group to update the state of the translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_TRANSLATION="Translations Edit Translation" +COM_GETBIBLE_TRANSLATIONS_EDIT_TRANSLATION_DESC="Allows the users in this group to edit translation of translation" +COM_GETBIBLE_TRANSLATIONS_SUBMENU="Translations Submenu" +COM_GETBIBLE_TRANSLATIONS_SUBMENU_DESC="Allows the users in this group to submenu of translation" +COM_GETBIBLE_USE_BATCH="Use Batch" +COM_GETBIBLE_USE_BATCH_DESC="Allows users in this group to use batch copy/update method." +COM_GETBIBLE_VERSES_ACCESS="Verses Access" +COM_GETBIBLE_VERSES_ACCESS_DESC="Allows the users in this group to access access verses" +COM_GETBIBLE_VERSES_BATCH_USE="Verses Batch Use" +COM_GETBIBLE_VERSES_BATCH_USE_DESC="Allows users in this group to use batch copy/update method of batch verses" +COM_GETBIBLE_VERSES_CREATE="Verses Create" +COM_GETBIBLE_VERSES_CREATE_DESC="Allows the users in this group to create create verses" +COM_GETBIBLE_VERSES_DASHBOARD_LIST="Verses Dashboard List" +COM_GETBIBLE_VERSES_DASHBOARD_LIST_DESC="Allows the users in this group to dashboard list of verse" +COM_GETBIBLE_VERSES_DELETE="Verses Delete" +COM_GETBIBLE_VERSES_DELETE_DESC="Allows the users in this group to delete delete verses" +COM_GETBIBLE_VERSES_EDIT="Verses Edit" +COM_GETBIBLE_VERSES_EDIT_ABBREVIATION="Verses Edit Abbreviation" +COM_GETBIBLE_VERSES_EDIT_ABBREVIATION_DESC="Allows the users in this group to edit abbreviation of verse" +COM_GETBIBLE_VERSES_EDIT_BOOK_NR="Verses Edit Book Nr" +COM_GETBIBLE_VERSES_EDIT_BOOK_NR_DESC="Allows the users in this group to edit book nr of verse" +COM_GETBIBLE_VERSES_EDIT_CHAPTER="Verses Edit Chapter" +COM_GETBIBLE_VERSES_EDIT_CHAPTER_DESC="Allows the users in this group to edit chapter of verse" +COM_GETBIBLE_VERSES_EDIT_CREATED_BY="Verses Edit Created By" +COM_GETBIBLE_VERSES_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by verses" +COM_GETBIBLE_VERSES_EDIT_CREATED_DATE="Verses Edit Created Date" +COM_GETBIBLE_VERSES_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created verses" +COM_GETBIBLE_VERSES_EDIT_DESC="Allows the users in this group to edit the verse" +COM_GETBIBLE_VERSES_EDIT_NAME="Verses Edit Name" +COM_GETBIBLE_VERSES_EDIT_NAME_DESC="Allows the users in this group to edit name of verse" +COM_GETBIBLE_VERSES_EDIT_OWN="Verses Edit Own" +COM_GETBIBLE_VERSES_EDIT_OWN_DESC="Allows the users in this group to edit edit own verses created by them" +COM_GETBIBLE_VERSES_EDIT_STATE="Verses Edit State" +COM_GETBIBLE_VERSES_EDIT_STATE_DESC="Allows the users in this group to update the state of the verse" +COM_GETBIBLE_VERSES_EDIT_TEXT="Verses Edit Text" +COM_GETBIBLE_VERSES_EDIT_TEXT_DESC="Allows the users in this group to edit text of verse" +COM_GETBIBLE_VERSES_EDIT_VERSE="Verses Edit Verse" +COM_GETBIBLE_VERSES_EDIT_VERSE_DESC="Allows the users in this group to edit verse of verse" +COM_GETBIBLE_VERSES_SUBMENU="Verses Submenu" +COM_GETBIBLE_VERSES_SUBMENU_DESC="Allows the users in this group to submenu of verse" \ No newline at end of file diff --git a/admin/language/en-GB/index.html b/admin/language/en-GB/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/language/en-GB/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/language/index.html b/admin/language/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/language/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/layouts/batchselection.php b/admin/layouts/batchselection.php new file mode 100644 index 0000000..8d8a328 --- /dev/null +++ b/admin/layouts/batchselection.php @@ -0,0 +1,54 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('JPATH_BASE') or die; + +JHtmlBehavior::core(); +$divWrapper = range(1,120,2); +$counter = 0; +?> +ListSelection) : ?> +
+ ListSelection as $ListSelection) : ?> +
+
+ + +
+
+ +
+
+ + + +
+
+
+ + +
+
+ \ No newline at end of file diff --git a/admin/layouts/book/details_above.php b/admin/layouts/book/details_above.php new file mode 100644 index 0000000..c896606 --- /dev/null +++ b/admin/layouts/book/details_above.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'name', + 'nr' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + +
+ + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + +
+ diff --git a/admin/layouts/book/details_left.php b/admin/layouts/book/details_left.php new file mode 100644 index 0000000..88f95d4 --- /dev/null +++ b/admin/layouts/book/details_left.php @@ -0,0 +1,48 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'abbreviation' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/book/details_right.php b/admin/layouts/book/details_right.php new file mode 100644 index 0000000..e4e14f4 --- /dev/null +++ b/admin/layouts/book/details_right.php @@ -0,0 +1,48 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'sha' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/book/index.html b/admin/layouts/book/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/layouts/book/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/layouts/book/publishing.php b/admin/layouts/book/publishing.php new file mode 100644 index 0000000..df756a0 --- /dev/null +++ b/admin/layouts/book/publishing.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'title', + 'created', + 'created_by', + 'modified', + 'modified_by' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/book/publlshing.php b/admin/layouts/book/publlshing.php new file mode 100644 index 0000000..171f8c2 --- /dev/null +++ b/admin/layouts/book/publlshing.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'published', + 'ordering', + 'access', + 'version', + 'hits', + 'id' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/chapter/details_above.php b/admin/layouts/chapter/details_above.php new file mode 100644 index 0000000..a21caa4 --- /dev/null +++ b/admin/layouts/chapter/details_above.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'name', + 'chapter', + 'book_nr' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + +
+ + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + +
+ diff --git a/admin/layouts/chapter/details_left.php b/admin/layouts/chapter/details_left.php new file mode 100644 index 0000000..88f95d4 --- /dev/null +++ b/admin/layouts/chapter/details_left.php @@ -0,0 +1,48 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'abbreviation' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/chapter/details_right.php b/admin/layouts/chapter/details_right.php new file mode 100644 index 0000000..e4e14f4 --- /dev/null +++ b/admin/layouts/chapter/details_right.php @@ -0,0 +1,48 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'sha' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/chapter/index.html b/admin/layouts/chapter/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/layouts/chapter/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/layouts/chapter/publishing.php b/admin/layouts/chapter/publishing.php new file mode 100644 index 0000000..df756a0 --- /dev/null +++ b/admin/layouts/chapter/publishing.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'title', + 'created', + 'created_by', + 'modified', + 'modified_by' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/chapter/publlshing.php b/admin/layouts/chapter/publlshing.php new file mode 100644 index 0000000..171f8c2 --- /dev/null +++ b/admin/layouts/chapter/publlshing.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'published', + 'ordering', + 'access', + 'version', + 'hits', + 'id' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/index.html b/admin/layouts/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/layouts/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/layouts/linker/details_left.php b/admin/layouts/linker/details_left.php new file mode 100644 index 0000000..e867d90 --- /dev/null +++ b/admin/layouts/linker/details_left.php @@ -0,0 +1,48 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'name' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/linker/index.html b/admin/layouts/linker/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/layouts/linker/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/layouts/linker/notes_fullwidth.php b/admin/layouts/linker/notes_fullwidth.php new file mode 100644 index 0000000..57a7669 --- /dev/null +++ b/admin/layouts/linker/notes_fullwidth.php @@ -0,0 +1,149 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// set the defaults +$items = $displayData->vvwnotes; +$user = JFactory::getUser(); +$id = $displayData->item->id; +// set the edit URL +$edit = "index.php?option=com_getbible&view=notes&task=note.edit"; +// set a return value +$return = ($id) ? "index.php?option=com_getbible&view=linker&layout=edit&id=" . $id : ""; +// check for a return value +$jinput = JFactory::getApplication()->input; +if ($_return = $jinput->get('return', null, 'base64')) +{ + $return .= "&return=" . $_return; +} +// check if return value was set +if (GetbibleHelper::checkString($return)) +{ + // set the referral values + $ref = ($id) ? "&ref=linker&refid=" . $id . "&return=" . urlencode(base64_encode($return)) : "&return=" . urlencode(base64_encode($return)); +} +else +{ + $ref = ($id) ? "&ref=linker&refid=" . $id : ""; +} +// set the create new URL +$new = "index.php?option=com_getbible&view=notes&task=note.edit" . $ref; +// set the create new and close URL +$close_new = "index.php?option=com_getbible&view=notes&task=note.edit"; +// load the action object +$can = GetbibleHelper::getActions('note'); + +?> +
+get('note.create')): ?> +
+ + +


+ + + + + + + + + + + + + + $item): ?> + authorise('core.manage', 'com_checkin') || $item->checked_out == $user->id || $item->checked_out == 0; + $userChkOut = JFactory::getUser($item->checked_out); + $canDo = GetbibleHelper::getActions('note',$item,'notes'); + ?> + + + + + published == 1): ?> + + published == 0): ?> + + published == 2): ?> + + published == -2): ?> + + + + + + + + + + + +
+ + + + + + + + + +
+ get('note.edit')): ?> + escape($item->book_nr); ?> + checked_out): ?> + name, $item->checked_out_time, 'notes.', $canCheckin); ?> + + + escape($item->book_nr); ?> + + + escape($item->linker_name); ?> + + access); ?> + + + + + + + + + + + + + + + + + + id; ?> +
+ +
+ +
+ +
+ +
diff --git a/admin/layouts/linker/passwords_fullwidth.php b/admin/layouts/linker/passwords_fullwidth.php new file mode 100644 index 0000000..43406bd --- /dev/null +++ b/admin/layouts/linker/passwords_fullwidth.php @@ -0,0 +1,149 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// set the defaults +$items = $displayData->vvxpasswords; +$user = JFactory::getUser(); +$id = $displayData->item->id; +// set the edit URL +$edit = "index.php?option=com_getbible&view=passwords&task=password.edit"; +// set a return value +$return = ($id) ? "index.php?option=com_getbible&view=linker&layout=edit&id=" . $id : ""; +// check for a return value +$jinput = JFactory::getApplication()->input; +if ($_return = $jinput->get('return', null, 'base64')) +{ + $return .= "&return=" . $_return; +} +// check if return value was set +if (GetbibleHelper::checkString($return)) +{ + // set the referral values + $ref = ($id) ? "&ref=linker&refid=" . $id . "&return=" . urlencode(base64_encode($return)) : "&return=" . urlencode(base64_encode($return)); +} +else +{ + $ref = ($id) ? "&ref=linker&refid=" . $id : ""; +} +// set the create new URL +$new = "index.php?option=com_getbible&view=passwords&task=password.edit" . $ref; +// set the create new and close URL +$close_new = "index.php?option=com_getbible&view=passwords&task=password.edit"; +// load the action object +$can = GetbibleHelper::getActions('password'); + +?> +
+get('password.create')): ?> +
+ + +


+ + + + + + + + + + + + + + $item): ?> + authorise('core.manage', 'com_checkin') || $item->checked_out == $user->id || $item->checked_out == 0; + $userChkOut = JFactory::getUser($item->checked_out); + $canDo = GetbibleHelper::getActions('password',$item,'passwords'); + ?> + + + + + published == 1): ?> + + published == 0): ?> + + published == 2): ?> + + published == -2): ?> + + + + + + + + + + + +
+ + + + + + + + + +
+ get('password.edit')): ?> + escape($item->name); ?> + checked_out): ?> + name, $item->checked_out_time, 'passwords.', $canCheckin); ?> + + + escape($item->name); ?> + + + escape($item->linker_name); ?> + + escape($item->guid); ?> + + + + + + + + + + + + + + + + + + id; ?> +
+ +
+ +
+ +
+ +
diff --git a/admin/layouts/linker/publishing.php b/admin/layouts/linker/publishing.php new file mode 100644 index 0000000..72020c7 --- /dev/null +++ b/admin/layouts/linker/publishing.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'guid', + 'title', + 'created', + 'created_by', + 'modified', + 'modified_by' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/linker/publlshing.php b/admin/layouts/linker/publlshing.php new file mode 100644 index 0000000..171f8c2 --- /dev/null +++ b/admin/layouts/linker/publlshing.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'published', + 'ordering', + 'access', + 'version', + 'hits', + 'id' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/linker/tags_fullwidth.php b/admin/layouts/linker/tags_fullwidth.php new file mode 100644 index 0000000..1c4775e --- /dev/null +++ b/admin/layouts/linker/tags_fullwidth.php @@ -0,0 +1,169 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// set the defaults +$items = $displayData->vvvtags; +$user = JFactory::getUser(); +$id = $displayData->item->id; +// set the edit URL +$edit = "index.php?option=com_getbible&view=tagged_verses&task=tagged_verse.edit"; +// set a return value +$return = ($id) ? "index.php?option=com_getbible&view=linker&layout=edit&id=" . $id : ""; +// check for a return value +$jinput = JFactory::getApplication()->input; +if ($_return = $jinput->get('return', null, 'base64')) +{ + $return .= "&return=" . $_return; +} +// check if return value was set +if (GetbibleHelper::checkString($return)) +{ + // set the referral values + $ref = ($id) ? "&ref=linker&refid=" . $id . "&return=" . urlencode(base64_encode($return)) : "&return=" . urlencode(base64_encode($return)); +} +else +{ + $ref = ($id) ? "&ref=linker&refid=" . $id : ""; +} +// set the create new URL +$new = "index.php?option=com_getbible&view=tagged_verses&task=tagged_verse.edit" . $ref; +// set the create new and close URL +$close_new = "index.php?option=com_getbible&view=tagged_verses&task=tagged_verse.edit"; +// load the action object +$can = GetbibleHelper::getActions('tagged_verse'); + +?> +
+get('tagged_verse.create')): ?> +
+ + +


+ + + + + + + + + + + + + + + + $item): ?> + authorise('core.manage', 'com_checkin') || $item->checked_out == $user->id || $item->checked_out == 0; + $userChkOut = JFactory::getUser($item->checked_out); + $canDo = GetbibleHelper::getActions('tagged_verse',$item,'tagged_verses'); + ?> + + + + + + + published == 1): ?> + + published == 0): ?> + + published == 2): ?> + + published == -2): ?> + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ get('tagged_verse.edit')): ?> + escape($item->book_nr); ?> + checked_out): ?> + name, $item->checked_out_time, 'tagged_verses.', $canCheckin); ?> + + + escape($item->book_nr); ?> + + + authorise('translation.edit', 'com_getbible.translation.' . (int) $item->abbreviation_id)): ?> + escape($item->abbreviation_translation); ?> + + escape($item->abbreviation_translation); ?> + + + access); ?> + + escape($item->linker_name); ?> + + authorise('tag.edit', 'com_getbible.tag.' . (int) $item->tag_id)): ?> + escape($item->tag_name); ?> + + escape($item->tag_name); ?> + + + + + + + + + + + + + + + + + + + id; ?> +
+ +
+ +
+ +
+ +
diff --git a/admin/layouts/note/details_above.php b/admin/layouts/note/details_above.php new file mode 100644 index 0000000..2c98398 --- /dev/null +++ b/admin/layouts/note/details_above.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'access', + 'linker' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + +
+ + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + +
+ diff --git a/admin/layouts/note/details_left.php b/admin/layouts/note/details_left.php new file mode 100644 index 0000000..42b9831 --- /dev/null +++ b/admin/layouts/note/details_left.php @@ -0,0 +1,50 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'book_nr', + 'chapter', + 'verse' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/note/details_right.php b/admin/layouts/note/details_right.php new file mode 100644 index 0000000..118fdfe --- /dev/null +++ b/admin/layouts/note/details_right.php @@ -0,0 +1,48 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'note' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/note/index.html b/admin/layouts/note/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/layouts/note/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/layouts/note/publishing.php b/admin/layouts/note/publishing.php new file mode 100644 index 0000000..72020c7 --- /dev/null +++ b/admin/layouts/note/publishing.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'guid', + 'title', + 'created', + 'created_by', + 'modified', + 'modified_by' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/note/publlshing.php b/admin/layouts/note/publlshing.php new file mode 100644 index 0000000..1c6d9d7 --- /dev/null +++ b/admin/layouts/note/publlshing.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'published', + 'ordering', + 'version', + 'hits', + 'id' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/open_ai_message/index.html b/admin/layouts/open_ai_message/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/layouts/open_ai_message/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/layouts/open_ai_message/message_above.php b/admin/layouts/open_ai_message/message_above.php new file mode 100644 index 0000000..b97d180 --- /dev/null +++ b/admin/layouts/open_ai_message/message_above.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'role', + 'open_ai_response', + 'prompt' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + +
+ + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + +
+ diff --git a/admin/layouts/open_ai_message/message_fullwidth.php b/admin/layouts/open_ai_message/message_fullwidth.php new file mode 100644 index 0000000..d78d9bc --- /dev/null +++ b/admin/layouts/open_ai_message/message_fullwidth.php @@ -0,0 +1,50 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'content' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + +
+ + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + +
+ diff --git a/admin/layouts/open_ai_message/message_left.php b/admin/layouts/open_ai_message/message_left.php new file mode 100644 index 0000000..5269e14 --- /dev/null +++ b/admin/layouts/open_ai_message/message_left.php @@ -0,0 +1,49 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'source', + 'index' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/open_ai_message/message_right.php b/admin/layouts/open_ai_message/message_right.php new file mode 100644 index 0000000..e867d90 --- /dev/null +++ b/admin/layouts/open_ai_message/message_right.php @@ -0,0 +1,48 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'name' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/open_ai_message/publishing.php b/admin/layouts/open_ai_message/publishing.php new file mode 100644 index 0000000..df756a0 --- /dev/null +++ b/admin/layouts/open_ai_message/publishing.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'title', + 'created', + 'created_by', + 'modified', + 'modified_by' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/open_ai_message/publlshing.php b/admin/layouts/open_ai_message/publlshing.php new file mode 100644 index 0000000..171f8c2 --- /dev/null +++ b/admin/layouts/open_ai_message/publlshing.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'published', + 'ordering', + 'access', + 'version', + 'hits', + 'id' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/open_ai_response/bible_left.php b/admin/layouts/open_ai_response/bible_left.php new file mode 100644 index 0000000..e6c3c51 --- /dev/null +++ b/admin/layouts/open_ai_response/bible_left.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'abbreviation', + 'language', + 'lcsh', + 'book' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/open_ai_response/bible_right.php b/admin/layouts/open_ai_response/bible_right.php new file mode 100644 index 0000000..95d5418 --- /dev/null +++ b/admin/layouts/open_ai_response/bible_right.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'chapter', + 'verse', + 'word', + 'selected_word' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/open_ai_response/details_above.php b/admin/layouts/open_ai_response/details_above.php new file mode 100644 index 0000000..e748888 --- /dev/null +++ b/admin/layouts/open_ai_response/details_above.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'response_id', + 'prompt' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + +
+ + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + +
+ diff --git a/admin/layouts/open_ai_response/details_left.php b/admin/layouts/open_ai_response/details_left.php new file mode 100644 index 0000000..551ca06 --- /dev/null +++ b/admin/layouts/open_ai_response/details_left.php @@ -0,0 +1,50 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'response_object', + 'response_model', + 'response_created' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/open_ai_response/details_right.php b/admin/layouts/open_ai_response/details_right.php new file mode 100644 index 0000000..3476e89 --- /dev/null +++ b/admin/layouts/open_ai_response/details_right.php @@ -0,0 +1,50 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'prompt_tokens', + 'completion_tokens', + 'total_tokens' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/open_ai_response/index.html b/admin/layouts/open_ai_response/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/layouts/open_ai_response/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/layouts/open_ai_response/message_fullwidth.php b/admin/layouts/open_ai_response/message_fullwidth.php new file mode 100644 index 0000000..08279a6 --- /dev/null +++ b/admin/layouts/open_ai_response/message_fullwidth.php @@ -0,0 +1,147 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// set the defaults +$items = $displayData->vvymessage; +$user = JFactory::getUser(); +$id = $displayData->item->id; +// set the edit URL +$edit = "index.php?option=com_getbible&view=open_ai_messages&task=open_ai_message.edit"; +// set a return value +$return = ($id) ? "index.php?option=com_getbible&view=open_ai_response&layout=edit&id=" . $id : ""; +// check for a return value +$jinput = JFactory::getApplication()->input; +if ($_return = $jinput->get('return', null, 'base64')) +{ + $return .= "&return=" . $_return; +} +// check if return value was set +if (GetbibleHelper::checkString($return)) +{ + // set the referral values + $ref = ($id) ? "&ref=open_ai_response&refid=" . $id . "&return=" . urlencode(base64_encode($return)) : "&return=" . urlencode(base64_encode($return)); +} +else +{ + $ref = ($id) ? "&ref=open_ai_response&refid=" . $id : ""; +} + +?> +
+ + + + + + + + + + + + + + $item): ?> + authorise('core.manage', 'com_checkin') || $item->checked_out == $user->id || $item->checked_out == 0; + $userChkOut = JFactory::getUser($item->checked_out); + $canDo = GetbibleHelper::getActions('open_ai_message',$item,'open_ai_messages'); + ?> + + + + + + published == 1): ?> + + published == 0): ?> + + published == 2): ?> + + published == -2): ?> + + + + + + + + + + + +
+ + + + + + + + + + + +
+ get('open_ai_message.edit')): ?> + role); ?> + checked_out): ?> + name, $item->checked_out_time, 'open_ai_messages.', $canCheckin); ?> + + + role); ?> + + + escape($item->open_ai_response_response_id); ?> + + authorise('prompt.edit', 'com_getbible.prompt.' . (int) $item->prompt_id)): ?> + escape($item->prompt_name); ?> + + escape($item->prompt_name); ?> + + + source); ?> + + + + + + + + + + + + + + + + + + id; ?> +
+ +
+ +
+ +
+ +
diff --git a/admin/layouts/open_ai_response/prompt_left.php b/admin/layouts/open_ai_response/prompt_left.php new file mode 100644 index 0000000..5265614 --- /dev/null +++ b/admin/layouts/open_ai_response/prompt_left.php @@ -0,0 +1,50 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'max_tokens', + 'temperature', + 'top_p' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/open_ai_response/prompt_right.php b/admin/layouts/open_ai_response/prompt_right.php new file mode 100644 index 0000000..7ff9ded --- /dev/null +++ b/admin/layouts/open_ai_response/prompt_right.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'model', + 'presence_penalty', + 'frequency_penalty', + 'n' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/open_ai_response/publishing.php b/admin/layouts/open_ai_response/publishing.php new file mode 100644 index 0000000..df756a0 --- /dev/null +++ b/admin/layouts/open_ai_response/publishing.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'title', + 'created', + 'created_by', + 'modified', + 'modified_by' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/open_ai_response/publlshing.php b/admin/layouts/open_ai_response/publlshing.php new file mode 100644 index 0000000..171f8c2 --- /dev/null +++ b/admin/layouts/open_ai_response/publlshing.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'published', + 'ordering', + 'access', + 'version', + 'hits', + 'id' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/password/details_above.php b/admin/layouts/password/details_above.php new file mode 100644 index 0000000..c787fff --- /dev/null +++ b/admin/layouts/password/details_above.php @@ -0,0 +1,50 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'linker' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + +
+ + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + +
+ diff --git a/admin/layouts/password/details_left.php b/admin/layouts/password/details_left.php new file mode 100644 index 0000000..e867d90 --- /dev/null +++ b/admin/layouts/password/details_left.php @@ -0,0 +1,48 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'name' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/password/details_right.php b/admin/layouts/password/details_right.php new file mode 100644 index 0000000..e142f5b --- /dev/null +++ b/admin/layouts/password/details_right.php @@ -0,0 +1,48 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'password' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/password/index.html b/admin/layouts/password/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/layouts/password/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/layouts/password/publishing.php b/admin/layouts/password/publishing.php new file mode 100644 index 0000000..72020c7 --- /dev/null +++ b/admin/layouts/password/publishing.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'guid', + 'title', + 'created', + 'created_by', + 'modified', + 'modified_by' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/password/publlshing.php b/admin/layouts/password/publlshing.php new file mode 100644 index 0000000..171f8c2 --- /dev/null +++ b/admin/layouts/password/publlshing.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'published', + 'ordering', + 'access', + 'version', + 'hits', + 'id' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/prompt/index.html b/admin/layouts/prompt/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/layouts/prompt/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/layouts/prompt/open_ai_left.php b/admin/layouts/prompt/open_ai_left.php new file mode 100644 index 0000000..7edddf8 --- /dev/null +++ b/admin/layouts/prompt/open_ai_left.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('JPATH_BASE') or die('Restricted access'); +use VDM\Joomla\Utilities\Component\Helper; + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +$params = Helper::getParams('com_getbible'); +$active = $params->get('enable_open_ai', 0); + +// only load the fields if the OPEN AI is activated +$fields = []; +if ($active == 1) +{ + // get the fields + $fields = $displayData->get($fields_tab_layout) ?: array( + 'max_tokens_override', + 'max_tokens', + 'max_tokens_note', + 'temperature_override', + 'temperature', + 'temperature_note', + 'top_p_override', + 'top_p', + 'top_p_note', + 'n_override', + 'n', + 'n_note' + ); +} + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + +
+

+

+
+ diff --git a/admin/layouts/prompt/open_ai_right.php b/admin/layouts/prompt/open_ai_right.php new file mode 100644 index 0000000..06e75fb --- /dev/null +++ b/admin/layouts/prompt/open_ai_right.php @@ -0,0 +1,68 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('JPATH_BASE') or die('Restricted access'); +use VDM\Joomla\Utilities\Component\Helper; + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +$params = Helper::getParams('com_getbible'); +$active = $params->get('enable_open_ai', 0); + +// only load the fields if the OPEN AI is activated +$fields = []; +if ($active == 1) +{ + // get the fields + $fields = $displayData->get($fields_tab_layout) ?: array( + 'token_override', + 'token', + 'ai_org_token_override', + 'org_token', + 'model', + 'openai_documentation_note', + 'presence_penalty_override', + 'presence_penalty', + 'presence_penalty_note', + 'frequency_penalty_override', + 'frequency_penalty', + 'frequency_penalty_note' + ); +} + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/prompt/prompt_above.php b/admin/layouts/prompt/prompt_above.php new file mode 100644 index 0000000..03d1854 --- /dev/null +++ b/admin/layouts/prompt/prompt_above.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'name', + 'abbreviation' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + +
+ + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + +
+ diff --git a/admin/layouts/prompt/prompt_fullwidth.php b/admin/layouts/prompt/prompt_fullwidth.php new file mode 100644 index 0000000..6059cd2 --- /dev/null +++ b/admin/layouts/prompt/prompt_fullwidth.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'openai_prompts_placeholders_basic_caching_note', + 'openai_prompts_placeholders_advanced_caching_note', + 'openai_prompts_placeholders_none_caching_note', + 'messages' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + +
+ + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + +
+ diff --git a/admin/layouts/prompt/prompt_left.php b/admin/layouts/prompt/prompt_left.php new file mode 100644 index 0000000..97ffcaf --- /dev/null +++ b/admin/layouts/prompt/prompt_left.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'integration', + 'integration_note', + 'cache_behaviour', + 'cache_persistently_expansive_caching_note', + 'cache_basic_note', + 'cache_advance_note' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/prompt/prompt_right.php b/admin/layouts/prompt/prompt_right.php new file mode 100644 index 0000000..f99214b --- /dev/null +++ b/admin/layouts/prompt/prompt_right.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'cache_capacity', + 'cache_capacity_note', + 'response_retrieval', + 'response_retrieval_note' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/prompt/publishing.php b/admin/layouts/prompt/publishing.php new file mode 100644 index 0000000..72020c7 --- /dev/null +++ b/admin/layouts/prompt/publishing.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'guid', + 'title', + 'created', + 'created_by', + 'modified', + 'modified_by' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/prompt/publlshing.php b/admin/layouts/prompt/publlshing.php new file mode 100644 index 0000000..171f8c2 --- /dev/null +++ b/admin/layouts/prompt/publlshing.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'published', + 'ordering', + 'access', + 'version', + 'hits', + 'id' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/tag/details_above.php b/admin/layouts/tag/details_above.php new file mode 100644 index 0000000..2c98398 --- /dev/null +++ b/admin/layouts/tag/details_above.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'access', + 'linker' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + +
+ + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + +
+ diff --git a/admin/layouts/tag/details_fullwidth.php b/admin/layouts/tag/details_fullwidth.php new file mode 100644 index 0000000..bb29c45 --- /dev/null +++ b/admin/layouts/tag/details_fullwidth.php @@ -0,0 +1,50 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'description' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + +
+ + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + +
+ diff --git a/admin/layouts/tag/details_left.php b/admin/layouts/tag/details_left.php new file mode 100644 index 0000000..e867d90 --- /dev/null +++ b/admin/layouts/tag/details_left.php @@ -0,0 +1,48 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'name' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/tag/index.html b/admin/layouts/tag/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/layouts/tag/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/layouts/tag/publishing.php b/admin/layouts/tag/publishing.php new file mode 100644 index 0000000..72020c7 --- /dev/null +++ b/admin/layouts/tag/publishing.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'guid', + 'title', + 'created', + 'created_by', + 'modified', + 'modified_by' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/tag/publlshing.php b/admin/layouts/tag/publlshing.php new file mode 100644 index 0000000..1c6d9d7 --- /dev/null +++ b/admin/layouts/tag/publlshing.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'published', + 'ordering', + 'version', + 'hits', + 'id' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/tagged_verse/details_above.php b/admin/layouts/tagged_verse/details_above.php new file mode 100644 index 0000000..a26fbde --- /dev/null +++ b/admin/layouts/tagged_verse/details_above.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'tag', + 'access', + 'linker' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + +
+ + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + +
+ diff --git a/admin/layouts/tagged_verse/details_left.php b/admin/layouts/tagged_verse/details_left.php new file mode 100644 index 0000000..9871257 --- /dev/null +++ b/admin/layouts/tagged_verse/details_left.php @@ -0,0 +1,49 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'abbreviation', + 'book_nr' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/tagged_verse/details_right.php b/admin/layouts/tagged_verse/details_right.php new file mode 100644 index 0000000..558b01a --- /dev/null +++ b/admin/layouts/tagged_verse/details_right.php @@ -0,0 +1,49 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'chapter', + 'verse' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/tagged_verse/index.html b/admin/layouts/tagged_verse/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/layouts/tagged_verse/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/layouts/tagged_verse/publishing.php b/admin/layouts/tagged_verse/publishing.php new file mode 100644 index 0000000..72020c7 --- /dev/null +++ b/admin/layouts/tagged_verse/publishing.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'guid', + 'title', + 'created', + 'created_by', + 'modified', + 'modified_by' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/tagged_verse/publlshing.php b/admin/layouts/tagged_verse/publlshing.php new file mode 100644 index 0000000..1c6d9d7 --- /dev/null +++ b/admin/layouts/tagged_verse/publlshing.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'published', + 'ordering', + 'version', + 'hits', + 'id' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/translation/details_above.php b/admin/layouts/translation/details_above.php new file mode 100644 index 0000000..fe171d8 --- /dev/null +++ b/admin/layouts/translation/details_above.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'translation', + 'abbreviation', + 'direction' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + +
+ + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + +
+ diff --git a/admin/layouts/translation/details_fullwidth.php b/admin/layouts/translation/details_fullwidth.php new file mode 100644 index 0000000..b430e43 --- /dev/null +++ b/admin/layouts/translation/details_fullwidth.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'distribution_about', + 'distribution_history' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + +
+ + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + +
+ diff --git a/admin/layouts/translation/details_left.php b/admin/layouts/translation/details_left.php new file mode 100644 index 0000000..3593ad1 --- /dev/null +++ b/admin/layouts/translation/details_left.php @@ -0,0 +1,54 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'distribution_abbreviation', + 'distribution_versification', + 'distribution_version', + 'distribution_version_date', + 'distribution_lcsh', + 'encoding', + 'sha' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/translation/details_right.php b/admin/layouts/translation/details_right.php new file mode 100644 index 0000000..b42845e --- /dev/null +++ b/admin/layouts/translation/details_right.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'language', + 'lang', + 'distribution_sourcetype', + 'distribution_source', + 'distribution_license' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/translation/index.html b/admin/layouts/translation/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/layouts/translation/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/layouts/translation/publishing.php b/admin/layouts/translation/publishing.php new file mode 100644 index 0000000..df756a0 --- /dev/null +++ b/admin/layouts/translation/publishing.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'title', + 'created', + 'created_by', + 'modified', + 'modified_by' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/translation/publlshing.php b/admin/layouts/translation/publlshing.php new file mode 100644 index 0000000..171f8c2 --- /dev/null +++ b/admin/layouts/translation/publlshing.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'published', + 'ordering', + 'access', + 'version', + 'hits', + 'id' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/trashhelper.php b/admin/layouts/trashhelper.php new file mode 100644 index 0000000..95bc7c9 --- /dev/null +++ b/admin/layouts/trashhelper.php @@ -0,0 +1,79 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('JPATH_BASE') or die('Restricted access'); + + + +?> +state->get('filter.published') == -2 && ($displayData->canState && $displayData->canDelete)) : ?> + +
+ items)): ?> +

+ + +

+

+ +

+ + +

+

+ + + +
+ diff --git a/admin/layouts/verse/details_above.php b/admin/layouts/verse/details_above.php new file mode 100644 index 0000000..c662ca5 --- /dev/null +++ b/admin/layouts/verse/details_above.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'book_nr', + 'chapter', + 'verse' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + +
+ + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + +
+ diff --git a/admin/layouts/verse/details_fullwidth.php b/admin/layouts/verse/details_fullwidth.php new file mode 100644 index 0000000..fc8106f --- /dev/null +++ b/admin/layouts/verse/details_fullwidth.php @@ -0,0 +1,50 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'text' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + +
+ + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + +
+ diff --git a/admin/layouts/verse/details_left.php b/admin/layouts/verse/details_left.php new file mode 100644 index 0000000..88f95d4 --- /dev/null +++ b/admin/layouts/verse/details_left.php @@ -0,0 +1,48 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'abbreviation' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/verse/details_right.php b/admin/layouts/verse/details_right.php new file mode 100644 index 0000000..e867d90 --- /dev/null +++ b/admin/layouts/verse/details_right.php @@ -0,0 +1,48 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'name' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/verse/index.html b/admin/layouts/verse/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/layouts/verse/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/layouts/verse/publishing.php b/admin/layouts/verse/publishing.php new file mode 100644 index 0000000..df756a0 --- /dev/null +++ b/admin/layouts/verse/publishing.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'title', + 'created', + 'created_by', + 'modified', + 'modified_by' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/verse/publlshing.php b/admin/layouts/verse/publlshing.php new file mode 100644 index 0000000..171f8c2 --- /dev/null +++ b/admin/layouts/verse/publlshing.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'published', + 'ordering', + 'access', + 'version', + 'hits', + 'id' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: array(); + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/models/ajax.php b/admin/models/ajax.php new file mode 100644 index 0000000..f5c4064 --- /dev/null +++ b/admin/models/ajax.php @@ -0,0 +1,255 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\ListModel; +use Joomla\Utilities\ArrayHelper; +use Joomla\Registry\Registry; +use Joomla\CMS\Language\Text; +use VDM\Joomla\Utilities\FileHelper; +use VDM\Joomla\Gitea\Factory; + +/** + * Getbible Ajax List Model + */ +class GetbibleModelAjax extends ListModel +{ + protected $app_params; + + public function __construct() + { + parent::__construct(); + // get params + $this->app_params = JComponentHelper::getParams('com_getbible'); + + } + + // Used in translation + + /** + * Check and if a notice is new (per/user) + * + * @param string|null $notice The current notice + * + * @return bool true if is new + * @since 2.0.0 + */ + public function isNew(?string $notice): bool + { + // first get the file path + $path_filename = FileHelper::getPath('path', 'usernotice', 'md', JFactory::getUser()->username, JPATH_COMPONENT_ADMINISTRATOR); + + // check if the file is set + if (($content = FileHelper::getContent($path_filename, FALSE)) !== FALSE) + { + if ($notice == $content) + { + return false; + } + } + return true; + } + + /** + * Check if a notice has been read (per/user) + * + * @param string|null $notice The current notice + * + * @return bool true if is read + * @since 2.0.0 + */ + public function isRead(?string $notice): bool + { + // first get the file path + $path_filename = FileHelper::getPath('path', 'usernotice', 'md', JFactory::getUser()->username, JPATH_COMPONENT_ADMINISTRATOR); + + // set as read if not already set + if (($content = FileHelper::getContent($path_filename, FALSE)) !== FALSE) + { + if ($notice == $content) + { + return true; + } + } + + return FileHelper::write($path_filename, $notice); + } + + /** + * get Current Version + * + * @param string|null $message The error messages if any. + * + * @return array The array of the notice or error message + * @since 2.3.0 + */ + public function getVersion($version = null) + { + // get the token if set + $token = $this->app_params->get('gitea_token', false); + + // only add if token is set + if ($token) + { + try + { + // load the API details + Factory::_('Gitea.Repository.Tags')->load_('https://git.vdm.dev', $token); + + // get the repository tags + $tags = Factory::_('Gitea.Repository.Tags')->list('getBible', 'joomla-component'); + } + catch (DomainException $e) + { + return $this->getTokenForVersion($e->getMessage()); + } + catch (InvalidArgumentException $e) + { + return $this->getTokenForVersion($e->getMessage()); + } + catch (Exception $e) + { + return $this->getTokenForVersion($e->getMessage()); + } + // do we have tags returned + if (isset($tags[0]) && isset($tags[0]->name)) + { + // get the version + $manifest = GetbibleHelper::manifest(); + $local_version = (string) $manifest->version; + $current_version = trim($tags[0]->name, 'vV'); + + // now check if this version is out dated + if ($current_version === $local_version) + { + return ['notice' => '' . Text::_('COM_GETBIBLE_UP_TO_DATE') . '']; + } + else + { + // check if this is beta version + $current_array = array_map(function ($v) { return (int) $v; }, (array) explode('.', $current_version)); + $local_array = array_map(function ($v) { return (int) $v; }, (array) explode('.', $local_version)); + if (($local_array[0] > $current_array[0]) || + ($local_array[0] == $current_array[0] && $local_array[1] > $current_array[1]) || + ($local_array[0] == $current_array[0] && $local_array[1] == $current_array[1] && $local_array[2] > $current_array[2])) + { + return ['notice' => '' . Text::_('COM_GETBIBLE_BETA_RELEASE') . '']; + } + else + { + // download link of the latest version + $download = "https://git.vdm.dev/api/v1/repos/joomla/[[[gitea_package_name]]]/archive/" . $tags[0]->name . ".zip?access_token=" . $token; + + return ['notice' => '' . Text::_('COM_GETBIBLE_OUT_OF_DATE') . '! ' . Text::_('COM_GETBIBLE_DOWNLOAD_UPDATE') . '!']; + } + } + } + } + + return $this->getTokenForVersion(); + } + + /** + * Instructions to get Token for version + * + * @param string|null $message The error messages if any. + * + * @return array The array of the error message + * @since 2.3.0 + */ + protected function getTokenForVersion(?string $message = null): array + { + // the URL + $url = 'https://git.vdm.dev/user/settings/applications'; + + // create link + $a = ''; + $_a = ''; + + if ($message) + { + return ['error' => $a . $message . $a_ . Text::_('COM_GETBIBLE_GET_TOKEN') . $_a]; + } + + return ['error' => $a . Text::_('COM_GETBIBLE_GET_TOKEN_FROM_VDM_TO_GET_UPDATE_NOTICE_AND_ADD_IT_TO_YOUR_GLOBAL_OPTIONS') . $a_ . Text::_('COM_GETBIBLE_GET_TOKEN') . $_a]; + } + + /** + * get Wiki Page + * + * @param string|null $message The error messages if any. + * + * @return array The array of the page or error message + * @since 2.3.0 + */ + public function getWiki(string $name = 'Home'): array + { + try + { + // load the API details + // Factory::_('Gitea.Repository.Wiki')->load_('https://git.vdm.dev', ''); + + // get the gitea wiki page im markdown + $wiki = Factory::_('Gitea.Repository.Wiki')->get('getBible', 'joomla-component', $name); + + // now render the page in HTML + $page = Factory::_('Gitea.Miscellaneous.Markdown')->render($wiki->content, true); + } + catch (DomainException $e) + { + return $this->getTokenForWiki($e->getMessage()); + } + catch (InvalidArgumentException $e) + { + return $this->getTokenForWiki($e->getMessage()); + } + catch (Exception $e) + { + return $this->getTokenForWiki($e->getMessage()); + } + + // get the html + if (isset($page)) + { + return ['page' => $page]; + } + + return $this->getTokenForWiki(); + } + + /** + * Instructions to get Token for wiki + * + * @param string|null $message The error messages if any. + * + * @return array The array of the error message + * @since 2.3.0 + */ + protected function getTokenForWiki(?string $message = null): array + { + if ($message) + { + return ['error' => $message]; + } + + return ['error' => Text::_('COM_GETBIBLE_THE_WIKI_CAN_ONLY_BE_LOADED_WHEN_YOUR_JCB_SYSTEM_HAS_INTERNET_CONNECTION')]; + } +} diff --git a/admin/models/book.php b/admin/models/book.php new file mode 100644 index 0000000..b750adc --- /dev/null +++ b/admin/models/book.php @@ -0,0 +1,951 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\AdminModel; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; + +/** + * Getbible Book Admin Model + */ +class GetbibleModelBook extends AdminModel +{ + /** + * The tab layout fields array. + * + * @var array + */ + protected $tabLayoutFields = array( + 'details' => array( + 'left' => array( + 'abbreviation' + ), + 'right' => array( + 'sha' + ), + 'above' => array( + 'name', + 'nr' + ) + ) + ); + + /** + * @var string The prefix to use with controller messages. + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE'; + + /** + * The type alias for this content type. + * + * @var string + * @since 3.2 + */ + public $typeAlias = 'com_getbible.book'; + + /** + * Returns a Table object, always creating it + * + * @param type $type The table type to instantiate + * @param string $prefix A prefix for the table class name. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JTable A database object + * + * @since 1.6 + */ + public function getTable($type = 'book', $prefix = 'GetbibleTable', $config = array()) + { + // add table path for when model gets used from other component + $this->addTablePath(JPATH_ADMINISTRATOR . '/components/com_getbible/tables'); + // get instance of the table + return JTable::getInstance($type, $prefix, $config); + }###ADMIN_CUSTOM_BUTTONS_METHOD### + + /** + * Method to get a single record. + * + * @param integer $pk The id of the primary key. + * + * @return mixed Object on success, false on failure. + * + * @since 1.6 + */ + public function getItem($pk = null) + { + if ($item = parent::getItem($pk)) + { + if (!empty($item->params) && !is_array($item->params)) + { + // Convert the params field to an array. + $registry = new Registry; + $registry->loadString($item->params); + $item->params = $registry->toArray(); + } + + if (!empty($item->metadata)) + { + // Convert the metadata field to an array. + $registry = new Registry; + $registry->loadString($item->metadata); + $item->metadata = $registry->toArray(); + } + } + + return $item; + } + + /** + * Method to get the record form. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * @param array $options Optional array of options for the form creation. + * + * @return mixed A JForm object on success, false on failure + * + * @since 1.6 + */ + public function getForm($data = array(), $loadData = true, $options = array('control' => 'jform')) + { + // set load data option + $options['load_data'] = $loadData; + // check if xpath was set in options + $xpath = false; + if (isset($options['xpath'])) + { + $xpath = $options['xpath']; + unset($options['xpath']); + } + // check if clear form was set in options + $clear = false; + if (isset($options['clear'])) + { + $clear = $options['clear']; + unset($options['clear']); + } + + // Get the form. + $form = $this->loadForm('com_getbible.book', 'book', $options, $clear, $xpath); + + if (empty($form)) + { + return false; + } + + $jinput = JFactory::getApplication()->input; + + // The front end calls this model and uses a_id to avoid id clashes so we need to check for that first. + if ($jinput->get('a_id')) + { + $id = $jinput->get('a_id', 0, 'INT'); + } + // The back end uses id so we use that the rest of the time and set it to 0 by default. + else + { + $id = $jinput->get('id', 0, 'INT'); + } + + $user = JFactory::getUser(); + + // Check for existing item. + // Modify the form based on Edit State access controls. + if ($id != 0 && (!$user->authorise('book.edit.state', 'com_getbible.book.' . (int) $id)) + || ($id == 0 && !$user->authorise('book.edit.state', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('ordering', 'disabled', 'true'); + $form->setFieldAttribute('published', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('ordering', 'filter', 'unset'); + $form->setFieldAttribute('published', 'filter', 'unset'); + } + // If this is a new item insure the greated by is set. + if (0 == $id) + { + // Set the created_by to this user + $form->setValue('created_by', null, $user->id); + } + // Modify the form based on Edit Creaded By access controls. + if ($id != 0 && (!$user->authorise('book.edit.created_by', 'com_getbible.book.' . (int) $id)) + || ($id == 0 && !$user->authorise('book.edit.created_by', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created_by', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('created_by', 'readonly', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created_by', 'filter', 'unset'); + } + // Modify the form based on Edit Creaded Date access controls. + if ($id != 0 && (!$user->authorise('book.edit.created', 'com_getbible.book.' . (int) $id)) + || ($id == 0 && !$user->authorise('book.edit.created', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created', 'filter', 'unset'); + } + // Modify the form based on Edit Name access controls. + if ($id != 0 && (!$user->authorise('book.edit.name', 'com_getbible.book.' . (int) $id)) + || ($id == 0 && !$user->authorise('book.edit.name', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('name', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('name', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('name')) + { + // Disable fields while saving. + $form->setFieldAttribute('name', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('name', 'required', 'false'); + } + } + // Modify the form based on Edit Abbreviation access controls. + if ($id != 0 && (!$user->authorise('book.edit.abbreviation', 'com_getbible.book.' . (int) $id)) + || ($id == 0 && !$user->authorise('book.edit.abbreviation', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('abbreviation', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('abbreviation', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('abbreviation')) + { + // Disable fields while saving. + $form->setFieldAttribute('abbreviation', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('abbreviation', 'required', 'false'); + } + } + // Modify the form based on Edit Nr access controls. + if ($id != 0 && (!$user->authorise('book.edit.nr', 'com_getbible.book.' . (int) $id)) + || ($id == 0 && !$user->authorise('book.edit.nr', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('nr', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('nr', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('nr')) + { + // Disable fields while saving. + $form->setFieldAttribute('nr', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('nr', 'required', 'false'); + } + } + // Modify the form based on Edit Sha access controls. + if ($id != 0 && (!$user->authorise('book.edit.sha', 'com_getbible.book.' . (int) $id)) + || ($id == 0 && !$user->authorise('book.edit.sha', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('sha', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('sha', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('sha')) + { + // Disable fields while saving. + $form->setFieldAttribute('sha', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('sha', 'required', 'false'); + } + } + // Only load these values if no id is found + if (0 == $id) + { + // Set redirected view name + $redirectedView = $jinput->get('ref', null, 'STRING'); + // Set field name (or fall back to view name) + $redirectedField = $jinput->get('field', $redirectedView, 'STRING'); + // Set redirected view id + $redirectedId = $jinput->get('refid', 0, 'INT'); + // Set field id (or fall back to redirected view id) + $redirectedValue = $jinput->get('field_id', $redirectedId, 'INT'); + if (0 != $redirectedValue && $redirectedField) + { + // Now set the local-redirected field default value + $form->setValue($redirectedField, null, $redirectedValue); + } + } + return $form; + } + + /** + * Method to get the script that have to be included on the form + * + * @return string script files + */ + public function getScript() + { + return 'media/com_getbible/js/book.js'; + } + + /** + * Method to test whether a record can be deleted. + * + * @param object $record A record object. + * + * @return boolean True if allowed to delete the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canDelete($record) + { + if (!empty($record->id)) + { + if ($record->published != -2) + { + return; + } + + $user = JFactory::getUser(); + // The record has been set. Check the record permissions. + return $user->authorise('book.delete', 'com_getbible.book.' . (int) $record->id); + } + return false; + } + + /** + * Method to test whether a record can have its state edited. + * + * @param object $record A record object. + * + * @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canEditState($record) + { + $user = JFactory::getUser(); + $recordId = (!empty($record->id)) ? $record->id : 0; + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('book.edit.state', 'com_getbible.book.' . (int) $recordId); + if (!$permission && !is_null($permission)) + { + return false; + } + } + // In the absense of better information, revert to the component permissions. + return $user->authorise('book.edit.state', 'com_getbible'); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * @since 2.5 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // Check specific edit permission then general edit permission. + $user = JFactory::getUser(); + + return $user->authorise('book.edit', 'com_getbible.book.'. ((int) isset($data[$key]) ? $data[$key] : 0)) or $user->authorise('book.edit', 'com_getbible'); + } + + /** + * Prepare and sanitise the table data prior to saving. + * + * @param JTable $table A JTable object. + * + * @return void + * + * @since 1.6 + */ + protected function prepareTable($table) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if (isset($table->name)) + { + $table->name = htmlspecialchars_decode($table->name, ENT_QUOTES); + } + + if (isset($table->alias) && empty($table->alias)) + { + $table->generateAlias(); + } + + if (empty($table->id)) + { + $table->created = $date->toSql(); + // set the user + if ($table->created_by == 0 || empty($table->created_by)) + { + $table->created_by = $user->id; + } + // Set ordering to the last item if not set + if (empty($table->ordering)) + { + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select('MAX(ordering)') + ->from($db->quoteName('#__getbible_book')); + $db->setQuery($query); + $max = $db->loadResult(); + + $table->ordering = $max + 1; + } + } + else + { + $table->modified = $date->toSql(); + $table->modified_by = $user->id; + } + + if (!empty($table->id)) + { + // Increment the items version number. + $table->version++; + } + } + + /** + * Method to get the data that should be injected in the form. + * + * @return mixed The data for the form. + * + * @since 1.6 + */ + protected function loadFormData() + { + // Check the session for previously entered form data. + $data = JFactory::getApplication()->getUserState('com_getbible.edit.book.data', array()); + + if (empty($data)) + { + $data = $this->getItem(); + // run the perprocess of the data + $this->preprocessData('com_getbible.book', $data); + } + + return $data; + } + + /** + * Method to get the unique fields of this table. + * + * @return mixed An array of field names, boolean false if none is set. + * + * @since 3.0 + */ + protected function getUniqueFields() + { + return false; + } + + /** + * Method to delete one or more records. + * + * @param array &$pks An array of record primary keys. + * + * @return boolean True if successful, false if an error occurs. + * + * @since 12.2 + */ + public function delete(&$pks) + { + if (!parent::delete($pks)) + { + return false; + } + + return true; + } + + /** + * Method to change the published state of one or more records. + * + * @param array &$pks A list of the primary keys to change. + * @param integer $value The value of the published state. + * + * @return boolean True on success. + * + * @since 12.2 + */ + public function publish(&$pks, $value = 1) + { + if (!parent::publish($pks, $value)) + { + return false; + } + + return true; + } + + /** + * Method to perform batch operations on an item or a set of items. + * + * @param array $commands An array of commands to perform. + * @param array $pks An array of item ids. + * @param array $contexts An array of item contexts. + * + * @return boolean Returns true on success, false on failure. + * + * @since 12.2 + */ + public function batch($commands, $pks, $contexts) + { + // Sanitize ids. + $pks = array_unique($pks); + ArrayHelper::toInteger($pks); + + // Remove any values of zero. + if (array_search(0, $pks, true)) + { + unset($pks[array_search(0, $pks, true)]); + } + + if (empty($pks)) + { + $this->setError(JText::_('JGLOBAL_NO_ITEM_SELECTED')); + return false; + } + + $done = false; + + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->contentType = new JUcmType; + $this->type = $this->contentType->getTypeByTable($this->tableClassName); + $this->canDo = GetbibleHelper::getActions('book'); + $this->batchSet = true; + + if (!$this->canDo->get('core.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + return false; + } + + if ($this->type == false) + { + $type = new JUcmType; + $this->type = $type->getTypeByAlias($this->typeAlias); + } + + $this->tagsObserver = $this->table->getObserverOfClass('JTableObserverTags'); + + if (!empty($commands['move_copy'])) + { + $cmd = ArrayHelper::getValue($commands, 'move_copy', 'c'); + + if ($cmd == 'c') + { + $result = $this->batchCopy($commands, $pks, $contexts); + + if (is_array($result)) + { + foreach ($result as $old => $new) + { + $contexts[$new] = $contexts[$old]; + } + $pks = array_values($result); + } + else + { + return false; + } + } + elseif ($cmd == 'm' && !$this->batchMove($commands, $pks, $contexts)) + { + return false; + } + + $done = true; + } + + if (!$done) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + + return false; + } + + // Clear the cache + $this->cleanCache(); + + return true; + } + + /** + * Batch copy items to a new category or current. + * + * @param integer $values The new values. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return mixed An array of new IDs on success, boolean false on failure. + * + * @since 12.2 + */ + protected function batchCopy($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('book'); + } + + if (!$this->canDo->get('book.create') && !$this->canDo->get('book.batch')) + { + return false; + } + + // get list of unique fields + $uniqueFields = $this->getUniqueFields(); + // remove move_copy from array + unset($values['move_copy']); + + // make sure published is set + if (!isset($values['published'])) + { + $values['published'] = 0; + } + elseif (isset($values['published']) && !$this->canDo->get('book.edit.state')) + { + $values['published'] = 0; + } + + $newIds = array(); + // Parent exists so let's proceed + while (!empty($pks)) + { + // Pop the first ID off the stack + $pk = array_shift($pks); + + $this->table->reset(); + + // only allow copy if user may edit this item. + if (!$this->user->authorise('book.edit', $contexts[$pk])) + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // Only for strings + if (GetbibleHelper::checkString($this->table->name) && !is_numeric($this->table->name)) + { + $this->table->name = $this->generateUnique('name',$this->table->name); + } + + // insert all set values + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + if (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + // update all unique fields + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $this->table->$uniqueField = $this->generateUnique($uniqueField,$this->table->$uniqueField); + } + } + + // Reset the ID because we are making a copy + $this->table->id = 0; + + // TODO: Deal with ordering? + // $this->table->ordering = 1; + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + + // Get the new item ID + $newId = $this->table->get('id'); + + // Add the new ID to the array + $newIds[$pk] = $newId; + } + + // Clean the cache + $this->cleanCache(); + + return $newIds; + } + + /** + * Batch move items to a new category + * + * @param integer $value The new category ID. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 12.2 + */ + protected function batchMove($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('book'); + } + + if (!$this->canDo->get('book.edit') && !$this->canDo->get('book.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // make sure published only updates if user has the permission. + if (isset($values['published']) && !$this->canDo->get('book.edit.state')) + { + unset($values['published']); + } + // remove move_copy from array + unset($values['move_copy']); + + // Parent exists so we proceed + foreach ($pks as $pk) + { + if (!$this->user->authorise('book.edit', $contexts[$pk])) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // insert all set values. + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + // Do special action for access. + if ('access' === $key && strlen($value) > 0) + { + $this->table->$key = $value; + } + elseif (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + } + + // Clean the cache + $this->cleanCache(); + + return true; + } + + /** + * Method to save the form data. + * + * @param array $data The form data. + * + * @return boolean True on success. + * + * @since 1.6 + */ + public function save($data) + { + $input = JFactory::getApplication()->input; + $filter = JFilterInput::getInstance(); + + // set the metadata to the Item Data + if (isset($data['metadata']) && isset($data['metadata']['author'])) + { + $data['metadata']['author'] = $filter->clean($data['metadata']['author'], 'TRIM'); + + $metadata = new JRegistry; + $metadata->loadArray($data['metadata']); + $data['metadata'] = (string) $metadata; + } + + // Set the Params Items to data + if (isset($data['params']) && is_array($data['params'])) + { + $params = new JRegistry; + $params->loadArray($data['params']); + $data['params'] = (string) $params; + } + + // Alter the unique field for save as copy + if ($input->get('task') === 'save2copy') + { + // Automatic handling of other unique fields + $uniqueFields = $this->getUniqueFields(); + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $data[$uniqueField] = $this->generateUnique($uniqueField,$data[$uniqueField]); + } + } + } + + if (parent::save($data)) + { + return true; + } + return false; + } + + /** + * Method to generate a unique value. + * + * @param string $field name. + * @param string $value data. + * + * @return string New value. + * + * @since 3.0 + */ + protected function generateUnique($field,$value) + { + + // set field value unique + $table = $this->getTable(); + + while ($table->load(array($field => $value))) + { + $value = StringHelper::increment($value); + } + + return $value; + } + + /** + * Method to change the title + * + * @param string $title The title. + * + * @return array Contains the modified title and alias. + * + */ + protected function _generateNewTitle($title) + { + + // Alter the title + $table = $this->getTable(); + + while ($table->load(array('title' => $title))) + { + $title = StringHelper::increment($title); + } + + return $title; + } +} diff --git a/admin/models/books.php b/admin/models/books.php new file mode 100644 index 0000000..37069d2 --- /dev/null +++ b/admin/models/books.php @@ -0,0 +1,380 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\ListModel; +use Joomla\Utilities\ArrayHelper; + +/** + * Books List Model + */ +class GetbibleModelBooks extends ListModel +{ + public function __construct($config = array()) + { + if (empty($config['filter_fields'])) + { + $config['filter_fields'] = array( + 'a.id','id', + 'a.published','published', + 'a.access','access', + 'a.ordering','ordering', + 'a.created_by','created_by', + 'a.modified_by','modified_by', + 'a.name','name', + 'g.translation','abbreviation', + 'a.nr','nr' + ); + } + + parent::__construct($config); + } + + /** + * Method to auto-populate the model state. + * + * Note. Calling getState in this method will result in recursion. + * + * @param string $ordering An optional ordering field. + * @param string $direction An optional direction (asc|desc). + * + * @return void + * + */ + protected function populateState($ordering = null, $direction = null) + { + $app = JFactory::getApplication(); + + // Adjust the context to support modal layouts. + if ($layout = $app->input->get('layout')) + { + $this->context .= '.' . $layout; + } + + // Check if the form was submitted + $formSubmited = $app->input->post->get('form_submited'); + + $access = $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', 0, 'int'); + if ($formSubmited) + { + $access = $app->input->post->get('access'); + $this->setState('filter.access', $access); + } + + $published = $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', ''); + $this->setState('filter.published', $published); + + $created_by = $this->getUserStateFromRequest($this->context . '.filter.created_by', 'filter_created_by', ''); + $this->setState('filter.created_by', $created_by); + + $created = $this->getUserStateFromRequest($this->context . '.filter.created', 'filter_created'); + $this->setState('filter.created', $created); + + $sorting = $this->getUserStateFromRequest($this->context . '.filter.sorting', 'filter_sorting', 0, 'int'); + $this->setState('filter.sorting', $sorting); + + $search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search'); + $this->setState('filter.search', $search); + + $name = $this->getUserStateFromRequest($this->context . '.filter.name', 'filter_name'); + if ($formSubmited) + { + $name = $app->input->post->get('name'); + $this->setState('filter.name', $name); + } + + $abbreviation = $this->getUserStateFromRequest($this->context . '.filter.abbreviation', 'filter_abbreviation'); + if ($formSubmited) + { + $abbreviation = $app->input->post->get('abbreviation'); + $this->setState('filter.abbreviation', $abbreviation); + } + + $nr = $this->getUserStateFromRequest($this->context . '.filter.nr', 'filter_nr'); + if ($formSubmited) + { + $nr = $app->input->post->get('nr'); + $this->setState('filter.nr', $nr); + } + + // List state information. + parent::populateState($ordering, $direction); + } + + /** + * Method to get an array of data items. + * + * @return mixed An array of data items on success, false on failure. + */ + public function getItems() + { + // Check in items + $this->checkInNow(); + + // load parent items + $items = parent::getItems(); + + // Set values to display correctly. + if (GetbibleHelper::checkArray($items)) + { + // Get the user object if not set. + if (!isset($user) || !GetbibleHelper::checkObject($user)) + { + $user = JFactory::getUser(); + } + foreach ($items as $nr => &$item) + { + // Remove items the user can't access. + $access = ($user->authorise('book.access', 'com_getbible.book.' . (int) $item->id) && $user->authorise('book.access', 'com_getbible')); + if (!$access) + { + unset($items[$nr]); + continue; + } + + } + } + + // return items + return $items; + } + + /** + * Method to build an SQL query to load the list data. + * + * @return string An SQL query + */ + protected function getListQuery() + { + // Get the user object. + $user = JFactory::getUser(); + // Create a new query object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + + // Select some fields + $query->select('a.*'); + + // From the getbible_item table + $query->from($db->quoteName('#__getbible_book', 'a')); + + // From the getbible_translation table. + $query->select($db->quoteName(['g.translation','g.id'],['abbreviation_translation','abbreviation_id'])); + $query->join('LEFT', $db->quoteName('#__getbible_translation', 'g') . ' ON (' . $db->quoteName('a.abbreviation') . ' = ' . $db->quoteName('g.abbreviation') . ')'); + + // Filter by published state + $published = $this->getState('filter.published'); + if (is_numeric($published)) + { + $query->where('a.published = ' . (int) $published); + } + elseif ($published === '') + { + $query->where('(a.published = 0 OR a.published = 1)'); + } + + // Join over the asset groups. + $query->select('ag.title AS access_level'); + $query->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access'); + // Filter by access level. + $_access = $this->getState('filter.access'); + if ($_access && is_numeric($_access)) + { + $query->where('a.access = ' . (int) $_access); + } + elseif (GetbibleHelper::checkArray($_access)) + { + // Secure the array for the query + $_access = ArrayHelper::toInteger($_access); + // Filter by the Access Array. + $query->where('a.access IN (' . implode(',', $_access) . ')'); + } + // Implement View Level Access + if (!$user->authorise('core.options', 'com_getbible')) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + // Filter by search. + $search = $this->getState('filter.search'); + if (!empty($search)) + { + if (stripos($search, 'id:') === 0) + { + $query->where('a.id = ' . (int) substr($search, 3)); + } + else + { + $search = $db->quote('%' . $db->escape($search) . '%'); + $query->where('(a.name LIKE '.$search.' OR a.abbreviation LIKE '.$search.' OR g.translation LIKE '.$search.' OR a.sha LIKE '.$search.')'); + } + } + + // Filter by Name. + $_name = $this->getState('filter.name'); + if (is_numeric($_name)) + { + if (is_float($_name)) + { + $query->where('a.name = ' . (float) $_name); + } + else + { + $query->where('a.name = ' . (int) $_name); + } + } + elseif (GetbibleHelper::checkString($_name)) + { + $query->where('a.name = ' . $db->quote($db->escape($_name))); + } + // Filter by Abbreviation. + $_abbreviation = $this->getState('filter.abbreviation'); + if (is_numeric($_abbreviation)) + { + if (is_float($_abbreviation)) + { + $query->where('a.abbreviation = ' . (float) $_abbreviation); + } + else + { + $query->where('a.abbreviation = ' . (int) $_abbreviation); + } + } + elseif (GetbibleHelper::checkString($_abbreviation)) + { + $query->where('a.abbreviation = ' . $db->quote($db->escape($_abbreviation))); + } + // Filter by Nr. + $_nr = $this->getState('filter.nr'); + if (is_numeric($_nr)) + { + if (is_float($_nr)) + { + $query->where('a.nr = ' . (float) $_nr); + } + else + { + $query->where('a.nr = ' . (int) $_nr); + } + } + elseif (GetbibleHelper::checkString($_nr)) + { + $query->where('a.nr = ' . $db->quote($db->escape($_nr))); + } + + // Add the list ordering clause. + $orderCol = $this->state->get('list.ordering', 'a.id'); + $orderDirn = $this->state->get('list.direction', 'desc'); + if ($orderCol != '') + { + $query->order($db->escape($orderCol . ' ' . $orderDirn)); + } + + return $query; + } + + /** + * Method to get a store id based on model configuration state. + * + * @return string A store id. + * + */ + protected function getStoreId($id = '') + { + // Compile the store id. + $id .= ':' . $this->getState('filter.id'); + $id .= ':' . $this->getState('filter.search'); + $id .= ':' . $this->getState('filter.published'); + // Check if the value is an array + $_access = $this->getState('filter.access'); + if (GetbibleHelper::checkArray($_access)) + { + $id .= ':' . implode(':', $_access); + } + // Check if this is only an number or string + elseif (is_numeric($_access) + || GetbibleHelper::checkString($_access)) + { + $id .= ':' . $_access; + } + $id .= ':' . $this->getState('filter.ordering'); + $id .= ':' . $this->getState('filter.created_by'); + $id .= ':' . $this->getState('filter.modified_by'); + $id .= ':' . $this->getState('filter.name'); + $id .= ':' . $this->getState('filter.abbreviation'); + $id .= ':' . $this->getState('filter.nr'); + + return parent::getStoreId($id); + } + + /** + * Build an SQL query to checkin all items left checked out longer then a set time. + * + * @return a bool + * + */ + protected function checkInNow() + { + // Get set check in time + $time = JComponentHelper::getParams('com_getbible')->get('check_in'); + + if ($time) + { + + // Get a db connection. + $db = JFactory::getDbo(); + // Reset query. + $query = $db->getQuery(true); + $query->select('*'); + $query->from($db->quoteName('#__getbible_book')); + // Only select items that are checked out. + $query->where($db->quoteName('checked_out') . '!=0'); + $db->setQuery($query, 0, 1); + $db->execute(); + if ($db->getNumRows()) + { + // Get Yesterdays date. + $date = JFactory::getDate()->modify($time)->toSql(); + // Reset query. + $query = $db->getQuery(true); + + // Fields to update. + $fields = array( + $db->quoteName('checked_out_time') . '=\'0000-00-00 00:00:00\'', + $db->quoteName('checked_out') . '=0' + ); + + // Conditions for which records should be updated. + $conditions = array( + $db->quoteName('checked_out') . '!=0', + $db->quoteName('checked_out_time') . '<\''.$date.'\'' + ); + + // Check table. + $query->update($db->quoteName('#__getbible_book'))->set($fields)->where($conditions); + + $db->setQuery($query); + + $db->execute(); + } + } + + return false; + } +} diff --git a/admin/models/chapter.php b/admin/models/chapter.php new file mode 100644 index 0000000..b4b85dc --- /dev/null +++ b/admin/models/chapter.php @@ -0,0 +1,969 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\AdminModel; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; + +/** + * Getbible Chapter Admin Model + */ +class GetbibleModelChapter extends AdminModel +{ + /** + * The tab layout fields array. + * + * @var array + */ + protected $tabLayoutFields = array( + 'details' => array( + 'left' => array( + 'abbreviation' + ), + 'right' => array( + 'sha' + ), + 'above' => array( + 'name', + 'chapter', + 'book_nr' + ) + ) + ); + + /** + * @var string The prefix to use with controller messages. + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE'; + + /** + * The type alias for this content type. + * + * @var string + * @since 3.2 + */ + public $typeAlias = 'com_getbible.chapter'; + + /** + * Returns a Table object, always creating it + * + * @param type $type The table type to instantiate + * @param string $prefix A prefix for the table class name. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JTable A database object + * + * @since 1.6 + */ + public function getTable($type = 'chapter', $prefix = 'GetbibleTable', $config = array()) + { + // add table path for when model gets used from other component + $this->addTablePath(JPATH_ADMINISTRATOR . '/components/com_getbible/tables'); + // get instance of the table + return JTable::getInstance($type, $prefix, $config); + }###ADMIN_CUSTOM_BUTTONS_METHOD### + + /** + * Method to get a single record. + * + * @param integer $pk The id of the primary key. + * + * @return mixed Object on success, false on failure. + * + * @since 1.6 + */ + public function getItem($pk = null) + { + if ($item = parent::getItem($pk)) + { + if (!empty($item->params) && !is_array($item->params)) + { + // Convert the params field to an array. + $registry = new Registry; + $registry->loadString($item->params); + $item->params = $registry->toArray(); + } + + if (!empty($item->metadata)) + { + // Convert the metadata field to an array. + $registry = new Registry; + $registry->loadString($item->metadata); + $item->metadata = $registry->toArray(); + } + } + + return $item; + } + + /** + * Method to get the record form. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * @param array $options Optional array of options for the form creation. + * + * @return mixed A JForm object on success, false on failure + * + * @since 1.6 + */ + public function getForm($data = array(), $loadData = true, $options = array('control' => 'jform')) + { + // set load data option + $options['load_data'] = $loadData; + // check if xpath was set in options + $xpath = false; + if (isset($options['xpath'])) + { + $xpath = $options['xpath']; + unset($options['xpath']); + } + // check if clear form was set in options + $clear = false; + if (isset($options['clear'])) + { + $clear = $options['clear']; + unset($options['clear']); + } + + // Get the form. + $form = $this->loadForm('com_getbible.chapter', 'chapter', $options, $clear, $xpath); + + if (empty($form)) + { + return false; + } + + $jinput = JFactory::getApplication()->input; + + // The front end calls this model and uses a_id to avoid id clashes so we need to check for that first. + if ($jinput->get('a_id')) + { + $id = $jinput->get('a_id', 0, 'INT'); + } + // The back end uses id so we use that the rest of the time and set it to 0 by default. + else + { + $id = $jinput->get('id', 0, 'INT'); + } + + $user = JFactory::getUser(); + + // Check for existing item. + // Modify the form based on Edit State access controls. + if ($id != 0 && (!$user->authorise('chapter.edit.state', 'com_getbible.chapter.' . (int) $id)) + || ($id == 0 && !$user->authorise('chapter.edit.state', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('ordering', 'disabled', 'true'); + $form->setFieldAttribute('published', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('ordering', 'filter', 'unset'); + $form->setFieldAttribute('published', 'filter', 'unset'); + } + // If this is a new item insure the greated by is set. + if (0 == $id) + { + // Set the created_by to this user + $form->setValue('created_by', null, $user->id); + } + // Modify the form based on Edit Creaded By access controls. + if ($id != 0 && (!$user->authorise('chapter.edit.created_by', 'com_getbible.chapter.' . (int) $id)) + || ($id == 0 && !$user->authorise('chapter.edit.created_by', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created_by', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('created_by', 'readonly', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created_by', 'filter', 'unset'); + } + // Modify the form based on Edit Creaded Date access controls. + if ($id != 0 && (!$user->authorise('chapter.edit.created', 'com_getbible.chapter.' . (int) $id)) + || ($id == 0 && !$user->authorise('chapter.edit.created', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created', 'filter', 'unset'); + } + // Modify the form based on Edit Name access controls. + if ($id != 0 && (!$user->authorise('chapter.edit.name', 'com_getbible.chapter.' . (int) $id)) + || ($id == 0 && !$user->authorise('chapter.edit.name', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('name', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('name', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('name')) + { + // Disable fields while saving. + $form->setFieldAttribute('name', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('name', 'required', 'false'); + } + } + // Modify the form based on Edit Chapter access controls. + if ($id != 0 && (!$user->authorise('chapter.edit.chapter', 'com_getbible.chapter.' . (int) $id)) + || ($id == 0 && !$user->authorise('chapter.edit.chapter', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('chapter', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('chapter', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('chapter')) + { + // Disable fields while saving. + $form->setFieldAttribute('chapter', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('chapter', 'required', 'false'); + } + } + // Modify the form based on Edit Book Nr access controls. + if ($id != 0 && (!$user->authorise('chapter.edit.book_nr', 'com_getbible.chapter.' . (int) $id)) + || ($id == 0 && !$user->authorise('chapter.edit.book_nr', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('book_nr', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('book_nr', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('book_nr')) + { + // Disable fields while saving. + $form->setFieldAttribute('book_nr', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('book_nr', 'required', 'false'); + } + } + // Modify the form based on Edit Abbreviation access controls. + if ($id != 0 && (!$user->authorise('chapter.edit.abbreviation', 'com_getbible.chapter.' . (int) $id)) + || ($id == 0 && !$user->authorise('chapter.edit.abbreviation', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('abbreviation', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('abbreviation', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('abbreviation')) + { + // Disable fields while saving. + $form->setFieldAttribute('abbreviation', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('abbreviation', 'required', 'false'); + } + } + // Modify the form based on Edit Sha access controls. + if ($id != 0 && (!$user->authorise('chapter.edit.sha', 'com_getbible.chapter.' . (int) $id)) + || ($id == 0 && !$user->authorise('chapter.edit.sha', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('sha', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('sha', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('sha')) + { + // Disable fields while saving. + $form->setFieldAttribute('sha', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('sha', 'required', 'false'); + } + } + // Only load these values if no id is found + if (0 == $id) + { + // Set redirected view name + $redirectedView = $jinput->get('ref', null, 'STRING'); + // Set field name (or fall back to view name) + $redirectedField = $jinput->get('field', $redirectedView, 'STRING'); + // Set redirected view id + $redirectedId = $jinput->get('refid', 0, 'INT'); + // Set field id (or fall back to redirected view id) + $redirectedValue = $jinput->get('field_id', $redirectedId, 'INT'); + if (0 != $redirectedValue && $redirectedField) + { + // Now set the local-redirected field default value + $form->setValue($redirectedField, null, $redirectedValue); + } + } + return $form; + } + + /** + * Method to get the script that have to be included on the form + * + * @return string script files + */ + public function getScript() + { + return 'media/com_getbible/js/chapter.js'; + } + + /** + * Method to test whether a record can be deleted. + * + * @param object $record A record object. + * + * @return boolean True if allowed to delete the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canDelete($record) + { + if (!empty($record->id)) + { + if ($record->published != -2) + { + return; + } + + $user = JFactory::getUser(); + // The record has been set. Check the record permissions. + return $user->authorise('chapter.delete', 'com_getbible.chapter.' . (int) $record->id); + } + return false; + } + + /** + * Method to test whether a record can have its state edited. + * + * @param object $record A record object. + * + * @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canEditState($record) + { + $user = JFactory::getUser(); + $recordId = (!empty($record->id)) ? $record->id : 0; + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('chapter.edit.state', 'com_getbible.chapter.' . (int) $recordId); + if (!$permission && !is_null($permission)) + { + return false; + } + } + // In the absense of better information, revert to the component permissions. + return $user->authorise('chapter.edit.state', 'com_getbible'); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * @since 2.5 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // Check specific edit permission then general edit permission. + $user = JFactory::getUser(); + + return $user->authorise('chapter.edit', 'com_getbible.chapter.'. ((int) isset($data[$key]) ? $data[$key] : 0)) or $user->authorise('chapter.edit', 'com_getbible'); + } + + /** + * Prepare and sanitise the table data prior to saving. + * + * @param JTable $table A JTable object. + * + * @return void + * + * @since 1.6 + */ + protected function prepareTable($table) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if (isset($table->name)) + { + $table->name = htmlspecialchars_decode($table->name, ENT_QUOTES); + } + + if (isset($table->alias) && empty($table->alias)) + { + $table->generateAlias(); + } + + if (empty($table->id)) + { + $table->created = $date->toSql(); + // set the user + if ($table->created_by == 0 || empty($table->created_by)) + { + $table->created_by = $user->id; + } + // Set ordering to the last item if not set + if (empty($table->ordering)) + { + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select('MAX(ordering)') + ->from($db->quoteName('#__getbible_chapter')); + $db->setQuery($query); + $max = $db->loadResult(); + + $table->ordering = $max + 1; + } + } + else + { + $table->modified = $date->toSql(); + $table->modified_by = $user->id; + } + + if (!empty($table->id)) + { + // Increment the items version number. + $table->version++; + } + } + + /** + * Method to get the data that should be injected in the form. + * + * @return mixed The data for the form. + * + * @since 1.6 + */ + protected function loadFormData() + { + // Check the session for previously entered form data. + $data = JFactory::getApplication()->getUserState('com_getbible.edit.chapter.data', array()); + + if (empty($data)) + { + $data = $this->getItem(); + // run the perprocess of the data + $this->preprocessData('com_getbible.chapter', $data); + } + + return $data; + } + + /** + * Method to get the unique fields of this table. + * + * @return mixed An array of field names, boolean false if none is set. + * + * @since 3.0 + */ + protected function getUniqueFields() + { + return false; + } + + /** + * Method to delete one or more records. + * + * @param array &$pks An array of record primary keys. + * + * @return boolean True if successful, false if an error occurs. + * + * @since 12.2 + */ + public function delete(&$pks) + { + if (!parent::delete($pks)) + { + return false; + } + + return true; + } + + /** + * Method to change the published state of one or more records. + * + * @param array &$pks A list of the primary keys to change. + * @param integer $value The value of the published state. + * + * @return boolean True on success. + * + * @since 12.2 + */ + public function publish(&$pks, $value = 1) + { + if (!parent::publish($pks, $value)) + { + return false; + } + + return true; + } + + /** + * Method to perform batch operations on an item or a set of items. + * + * @param array $commands An array of commands to perform. + * @param array $pks An array of item ids. + * @param array $contexts An array of item contexts. + * + * @return boolean Returns true on success, false on failure. + * + * @since 12.2 + */ + public function batch($commands, $pks, $contexts) + { + // Sanitize ids. + $pks = array_unique($pks); + ArrayHelper::toInteger($pks); + + // Remove any values of zero. + if (array_search(0, $pks, true)) + { + unset($pks[array_search(0, $pks, true)]); + } + + if (empty($pks)) + { + $this->setError(JText::_('JGLOBAL_NO_ITEM_SELECTED')); + return false; + } + + $done = false; + + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->contentType = new JUcmType; + $this->type = $this->contentType->getTypeByTable($this->tableClassName); + $this->canDo = GetbibleHelper::getActions('chapter'); + $this->batchSet = true; + + if (!$this->canDo->get('core.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + return false; + } + + if ($this->type == false) + { + $type = new JUcmType; + $this->type = $type->getTypeByAlias($this->typeAlias); + } + + $this->tagsObserver = $this->table->getObserverOfClass('JTableObserverTags'); + + if (!empty($commands['move_copy'])) + { + $cmd = ArrayHelper::getValue($commands, 'move_copy', 'c'); + + if ($cmd == 'c') + { + $result = $this->batchCopy($commands, $pks, $contexts); + + if (is_array($result)) + { + foreach ($result as $old => $new) + { + $contexts[$new] = $contexts[$old]; + } + $pks = array_values($result); + } + else + { + return false; + } + } + elseif ($cmd == 'm' && !$this->batchMove($commands, $pks, $contexts)) + { + return false; + } + + $done = true; + } + + if (!$done) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + + return false; + } + + // Clear the cache + $this->cleanCache(); + + return true; + } + + /** + * Batch copy items to a new category or current. + * + * @param integer $values The new values. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return mixed An array of new IDs on success, boolean false on failure. + * + * @since 12.2 + */ + protected function batchCopy($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('chapter'); + } + + if (!$this->canDo->get('chapter.create') && !$this->canDo->get('chapter.batch')) + { + return false; + } + + // get list of unique fields + $uniqueFields = $this->getUniqueFields(); + // remove move_copy from array + unset($values['move_copy']); + + // make sure published is set + if (!isset($values['published'])) + { + $values['published'] = 0; + } + elseif (isset($values['published']) && !$this->canDo->get('chapter.edit.state')) + { + $values['published'] = 0; + } + + $newIds = array(); + // Parent exists so let's proceed + while (!empty($pks)) + { + // Pop the first ID off the stack + $pk = array_shift($pks); + + $this->table->reset(); + + // only allow copy if user may edit this item. + if (!$this->user->authorise('chapter.edit', $contexts[$pk])) + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // Only for strings + if (GetbibleHelper::checkString($this->table->name) && !is_numeric($this->table->name)) + { + $this->table->name = $this->generateUnique('name',$this->table->name); + } + + // insert all set values + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + if (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + // update all unique fields + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $this->table->$uniqueField = $this->generateUnique($uniqueField,$this->table->$uniqueField); + } + } + + // Reset the ID because we are making a copy + $this->table->id = 0; + + // TODO: Deal with ordering? + // $this->table->ordering = 1; + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + + // Get the new item ID + $newId = $this->table->get('id'); + + // Add the new ID to the array + $newIds[$pk] = $newId; + } + + // Clean the cache + $this->cleanCache(); + + return $newIds; + } + + /** + * Batch move items to a new category + * + * @param integer $value The new category ID. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 12.2 + */ + protected function batchMove($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('chapter'); + } + + if (!$this->canDo->get('chapter.edit') && !$this->canDo->get('chapter.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // make sure published only updates if user has the permission. + if (isset($values['published']) && !$this->canDo->get('chapter.edit.state')) + { + unset($values['published']); + } + // remove move_copy from array + unset($values['move_copy']); + + // Parent exists so we proceed + foreach ($pks as $pk) + { + if (!$this->user->authorise('chapter.edit', $contexts[$pk])) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // insert all set values. + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + // Do special action for access. + if ('access' === $key && strlen($value) > 0) + { + $this->table->$key = $value; + } + elseif (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + } + + // Clean the cache + $this->cleanCache(); + + return true; + } + + /** + * Method to save the form data. + * + * @param array $data The form data. + * + * @return boolean True on success. + * + * @since 1.6 + */ + public function save($data) + { + $input = JFactory::getApplication()->input; + $filter = JFilterInput::getInstance(); + + // set the metadata to the Item Data + if (isset($data['metadata']) && isset($data['metadata']['author'])) + { + $data['metadata']['author'] = $filter->clean($data['metadata']['author'], 'TRIM'); + + $metadata = new JRegistry; + $metadata->loadArray($data['metadata']); + $data['metadata'] = (string) $metadata; + } + + // Set the Params Items to data + if (isset($data['params']) && is_array($data['params'])) + { + $params = new JRegistry; + $params->loadArray($data['params']); + $data['params'] = (string) $params; + } + + // Alter the unique field for save as copy + if ($input->get('task') === 'save2copy') + { + // Automatic handling of other unique fields + $uniqueFields = $this->getUniqueFields(); + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $data[$uniqueField] = $this->generateUnique($uniqueField,$data[$uniqueField]); + } + } + } + + if (parent::save($data)) + { + return true; + } + return false; + } + + /** + * Method to generate a unique value. + * + * @param string $field name. + * @param string $value data. + * + * @return string New value. + * + * @since 3.0 + */ + protected function generateUnique($field,$value) + { + + // set field value unique + $table = $this->getTable(); + + while ($table->load(array($field => $value))) + { + $value = StringHelper::increment($value); + } + + return $value; + } + + /** + * Method to change the title + * + * @param string $title The title. + * + * @return array Contains the modified title and alias. + * + */ + protected function _generateNewTitle($title) + { + + // Alter the title + $table = $this->getTable(); + + while ($table->load(array('title' => $title))) + { + $title = StringHelper::increment($title); + } + + return $title; + } +} diff --git a/admin/models/chapters.php b/admin/models/chapters.php new file mode 100644 index 0000000..440faff --- /dev/null +++ b/admin/models/chapters.php @@ -0,0 +1,457 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\ListModel; +use Joomla\Utilities\ArrayHelper; + +/** + * Chapters List Model + */ +class GetbibleModelChapters extends ListModel +{ + public function __construct($config = array()) + { + if (empty($config['filter_fields'])) + { + $config['filter_fields'] = array( + 'a.id','id', + 'a.published','published', + 'a.access','access', + 'a.ordering','ordering', + 'a.created_by','created_by', + 'a.modified_by','modified_by', + 'a.chapter','chapter', + 'a.book_nr','book_nr', + 'g.translation','abbreviation', + 'a.name','name' + ); + } + + parent::__construct($config); + } + + /** + * Method to auto-populate the model state. + * + * Note. Calling getState in this method will result in recursion. + * + * @param string $ordering An optional ordering field. + * @param string $direction An optional direction (asc|desc). + * + * @return void + * + */ + protected function populateState($ordering = null, $direction = null) + { + $app = JFactory::getApplication(); + + // Adjust the context to support modal layouts. + if ($layout = $app->input->get('layout')) + { + $this->context .= '.' . $layout; + } + + // Check if the form was submitted + $formSubmited = $app->input->post->get('form_submited'); + + $access = $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', 0, 'int'); + if ($formSubmited) + { + $access = $app->input->post->get('access'); + $this->setState('filter.access', $access); + } + + $published = $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', ''); + $this->setState('filter.published', $published); + + $created_by = $this->getUserStateFromRequest($this->context . '.filter.created_by', 'filter_created_by', ''); + $this->setState('filter.created_by', $created_by); + + $created = $this->getUserStateFromRequest($this->context . '.filter.created', 'filter_created'); + $this->setState('filter.created', $created); + + $sorting = $this->getUserStateFromRequest($this->context . '.filter.sorting', 'filter_sorting', 0, 'int'); + $this->setState('filter.sorting', $sorting); + + $search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search'); + $this->setState('filter.search', $search); + + $chapter = $this->getUserStateFromRequest($this->context . '.filter.chapter', 'filter_chapter'); + if ($formSubmited) + { + $chapter = $app->input->post->get('chapter'); + $this->setState('filter.chapter', $chapter); + } + + $book_nr = $this->getUserStateFromRequest($this->context . '.filter.book_nr', 'filter_book_nr'); + if ($formSubmited) + { + $book_nr = $app->input->post->get('book_nr'); + $this->setState('filter.book_nr', $book_nr); + } + + $abbreviation = $this->getUserStateFromRequest($this->context . '.filter.abbreviation', 'filter_abbreviation'); + if ($formSubmited) + { + $abbreviation = $app->input->post->get('abbreviation'); + $this->setState('filter.abbreviation', $abbreviation); + } + + $name = $this->getUserStateFromRequest($this->context . '.filter.name', 'filter_name'); + if ($formSubmited) + { + $name = $app->input->post->get('name'); + $this->setState('filter.name', $name); + } + + // List state information. + parent::populateState($ordering, $direction); + } + + /** + * Method to get an array of data items. + * + * @return mixed An array of data items on success, false on failure. + */ + public function getItems() + { + // Check in items + $this->checkInNow(); + + // load parent items + $items = parent::getItems(); + + // Set values to display correctly. + if (GetbibleHelper::checkArray($items)) + { + // Get the user object if not set. + if (!isset($user) || !GetbibleHelper::checkObject($user)) + { + $user = JFactory::getUser(); + } + foreach ($items as $nr => &$item) + { + // Remove items the user can't access. + $access = ($user->authorise('chapter.access', 'com_getbible.chapter.' . (int) $item->id) && $user->authorise('chapter.access', 'com_getbible')); + if (!$access) + { + unset($items[$nr]); + continue; + } + + } + } + + // return items + return $items; + } + + /** + * Method to build an SQL query to load the list data. + * + * @return string An SQL query + */ + protected function getListQuery() + { + // Get the user object. + $user = JFactory::getUser(); + // Create a new query object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + + // Select some fields + $query->select('a.*'); + + // From the getbible_item table + $query->from($db->quoteName('#__getbible_chapter', 'a')); + + // From the getbible_translation table. + $query->select($db->quoteName(['g.translation','g.id'],['abbreviation_translation','abbreviation_id'])); + $query->join('LEFT', $db->quoteName('#__getbible_translation', 'g') . ' ON (' . $db->quoteName('a.abbreviation') . ' = ' . $db->quoteName('g.abbreviation') . ')'); + + // Filter by published state + $published = $this->getState('filter.published'); + if (is_numeric($published)) + { + $query->where('a.published = ' . (int) $published); + } + elseif ($published === '') + { + $query->where('(a.published = 0 OR a.published = 1)'); + } + + // Join over the asset groups. + $query->select('ag.title AS access_level'); + $query->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access'); + // Filter by access level. + $_access = $this->getState('filter.access'); + if ($_access && is_numeric($_access)) + { + $query->where('a.access = ' . (int) $_access); + } + elseif (GetbibleHelper::checkArray($_access)) + { + // Secure the array for the query + $_access = ArrayHelper::toInteger($_access); + // Filter by the Access Array. + $query->where('a.access IN (' . implode(',', $_access) . ')'); + } + // Implement View Level Access + if (!$user->authorise('core.options', 'com_getbible')) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + // Filter by search. + $search = $this->getState('filter.search'); + if (!empty($search)) + { + if (stripos($search, 'id:') === 0) + { + $query->where('a.id = ' . (int) substr($search, 3)); + } + else + { + $search = $db->quote('%' . $db->escape($search) . '%'); + $query->where('(a.name LIKE '.$search.' OR a.chapter LIKE '.$search.' OR a.abbreviation LIKE '.$search.' OR g.translation LIKE '.$search.' OR a.sha LIKE '.$search.')'); + } + } + + // Filter by Chapter. + $_chapter = $this->getState('filter.chapter'); + if (is_numeric($_chapter)) + { + if (is_float($_chapter)) + { + $query->where('a.chapter = ' . (float) $_chapter); + } + else + { + $query->where('a.chapter = ' . (int) $_chapter); + } + } + elseif (GetbibleHelper::checkString($_chapter)) + { + $query->where('a.chapter = ' . $db->quote($db->escape($_chapter))); + } + elseif (GetbibleHelper::checkArray($_chapter)) + { + // Secure the array for the query + $_chapter = array_map( function ($val) use(&$db) { + if (is_numeric($val)) + { + if (is_float($val)) + { + return (float) $val; + } + else + { + return (int) $val; + } + } + elseif (GetbibleHelper::checkString($val)) + { + return $db->quote($db->escape($val)); + } + }, $_chapter); + // Filter by the Chapter Array. + $query->where('a.chapter IN (' . implode(',', $_chapter) . ')'); + } + // Filter by Book_nr. + $_book_nr = $this->getState('filter.book_nr'); + if (is_numeric($_book_nr)) + { + if (is_float($_book_nr)) + { + $query->where('a.book_nr = ' . (float) $_book_nr); + } + else + { + $query->where('a.book_nr = ' . (int) $_book_nr); + } + } + elseif (GetbibleHelper::checkString($_book_nr)) + { + $query->where('a.book_nr = ' . $db->quote($db->escape($_book_nr))); + } + elseif (GetbibleHelper::checkArray($_book_nr)) + { + // Secure the array for the query + $_book_nr = array_map( function ($val) use(&$db) { + if (is_numeric($val)) + { + if (is_float($val)) + { + return (float) $val; + } + else + { + return (int) $val; + } + } + elseif (GetbibleHelper::checkString($val)) + { + return $db->quote($db->escape($val)); + } + }, $_book_nr); + // Filter by the Book_nr Array. + $query->where('a.book_nr IN (' . implode(',', $_book_nr) . ')'); + } + // Filter by Abbreviation. + $_abbreviation = $this->getState('filter.abbreviation'); + if (is_numeric($_abbreviation)) + { + if (is_float($_abbreviation)) + { + $query->where('a.abbreviation = ' . (float) $_abbreviation); + } + else + { + $query->where('a.abbreviation = ' . (int) $_abbreviation); + } + } + elseif (GetbibleHelper::checkString($_abbreviation)) + { + $query->where('a.abbreviation = ' . $db->quote($db->escape($_abbreviation))); + } + + // Add the list ordering clause. + $orderCol = $this->state->get('list.ordering', 'a.id'); + $orderDirn = $this->state->get('list.direction', 'desc'); + if ($orderCol != '') + { + $query->order($db->escape($orderCol . ' ' . $orderDirn)); + } + + return $query; + } + + /** + * Method to get a store id based on model configuration state. + * + * @return string A store id. + * + */ + protected function getStoreId($id = '') + { + // Compile the store id. + $id .= ':' . $this->getState('filter.id'); + $id .= ':' . $this->getState('filter.search'); + $id .= ':' . $this->getState('filter.published'); + // Check if the value is an array + $_access = $this->getState('filter.access'); + if (GetbibleHelper::checkArray($_access)) + { + $id .= ':' . implode(':', $_access); + } + // Check if this is only an number or string + elseif (is_numeric($_access) + || GetbibleHelper::checkString($_access)) + { + $id .= ':' . $_access; + } + $id .= ':' . $this->getState('filter.ordering'); + $id .= ':' . $this->getState('filter.created_by'); + $id .= ':' . $this->getState('filter.modified_by'); + // Check if the value is an array + $_chapter = $this->getState('filter.chapter'); + if (GetbibleHelper::checkArray($_chapter)) + { + $id .= ':' . implode(':', $_chapter); + } + // Check if this is only an number or string + elseif (is_numeric($_chapter) + || GetbibleHelper::checkString($_chapter)) + { + $id .= ':' . $_chapter; + } + // Check if the value is an array + $_book_nr = $this->getState('filter.book_nr'); + if (GetbibleHelper::checkArray($_book_nr)) + { + $id .= ':' . implode(':', $_book_nr); + } + // Check if this is only an number or string + elseif (is_numeric($_book_nr) + || GetbibleHelper::checkString($_book_nr)) + { + $id .= ':' . $_book_nr; + } + $id .= ':' . $this->getState('filter.abbreviation'); + $id .= ':' . $this->getState('filter.name'); + + return parent::getStoreId($id); + } + + /** + * Build an SQL query to checkin all items left checked out longer then a set time. + * + * @return a bool + * + */ + protected function checkInNow() + { + // Get set check in time + $time = JComponentHelper::getParams('com_getbible')->get('check_in'); + + if ($time) + { + + // Get a db connection. + $db = JFactory::getDbo(); + // Reset query. + $query = $db->getQuery(true); + $query->select('*'); + $query->from($db->quoteName('#__getbible_chapter')); + // Only select items that are checked out. + $query->where($db->quoteName('checked_out') . '!=0'); + $db->setQuery($query, 0, 1); + $db->execute(); + if ($db->getNumRows()) + { + // Get Yesterdays date. + $date = JFactory::getDate()->modify($time)->toSql(); + // Reset query. + $query = $db->getQuery(true); + + // Fields to update. + $fields = array( + $db->quoteName('checked_out_time') . '=\'0000-00-00 00:00:00\'', + $db->quoteName('checked_out') . '=0' + ); + + // Conditions for which records should be updated. + $conditions = array( + $db->quoteName('checked_out') . '!=0', + $db->quoteName('checked_out_time') . '<\''.$date.'\'' + ); + + // Check table. + $query->update($db->quoteName('#__getbible_chapter'))->set($fields)->where($conditions); + + $db->setQuery($query); + + $db->execute(); + } + } + + return false; + } +} diff --git a/admin/models/fields/booksfiltername.php b/admin/models/fields/booksfiltername.php new file mode 100644 index 0000000..3684864 --- /dev/null +++ b/admin/models/fields/booksfiltername.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Booksfiltername Form Field class for the Getbible component + */ +class JFormFieldBooksfiltername extends JFormFieldList +{ + /** + * The booksfiltername field type. + * + * @var string + */ + public $type = 'booksfiltername'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('name')); + $query->from($db->quoteName('#__getbible_book')); + $query->order($db->quoteName('name') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_NAME') . ' -'); + + if ($_results) + { + $_results = array_unique($_results); + foreach ($_results as $name) + { + // Now add the name and its text to the options array + $_filter[] = JHtml::_('select.option', $name, $name); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/booksfilternr.php b/admin/models/fields/booksfilternr.php new file mode 100644 index 0000000..4276585 --- /dev/null +++ b/admin/models/fields/booksfilternr.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Booksfilternr Form Field class for the Getbible component + */ +class JFormFieldBooksfilternr extends JFormFieldList +{ + /** + * The booksfilternr field type. + * + * @var string + */ + public $type = 'booksfilternr'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('nr')); + $query->from($db->quoteName('#__getbible_book')); + $query->order($db->quoteName('nr') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_NUMBER') . ' -'); + + if ($_results) + { + $_results = array_unique($_results); + foreach ($_results as $nr) + { + // Now add the nr and its text to the options array + $_filter[] = JHtml::_('select.option', $nr, $nr); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/chaptersfilterbooknr.php b/admin/models/fields/chaptersfilterbooknr.php new file mode 100644 index 0000000..cde748b --- /dev/null +++ b/admin/models/fields/chaptersfilterbooknr.php @@ -0,0 +1,72 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Chaptersfilterbooknr Form Field class for the Getbible component + */ +class JFormFieldChaptersfilterbooknr extends JFormFieldList +{ + /** + * The chaptersfilterbooknr field type. + * + * @var string + */ + public $type = 'chaptersfilterbooknr'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('book_nr')); + $query->from($db->quoteName('#__getbible_chapter')); + $query->order($db->quoteName('book_nr') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + + if ($_results) + { + $_results = array_unique($_results); + foreach ($_results as $book_nr) + { + // Now add the book_nr and its text to the options array + $_filter[] = JHtml::_('select.option', $book_nr, $book_nr); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/chaptersfilterchapter.php b/admin/models/fields/chaptersfilterchapter.php new file mode 100644 index 0000000..c6f366d --- /dev/null +++ b/admin/models/fields/chaptersfilterchapter.php @@ -0,0 +1,72 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Chaptersfilterchapter Form Field class for the Getbible component + */ +class JFormFieldChaptersfilterchapter extends JFormFieldList +{ + /** + * The chaptersfilterchapter field type. + * + * @var string + */ + public $type = 'chaptersfilterchapter'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('chapter')); + $query->from($db->quoteName('#__getbible_chapter')); + $query->order($db->quoteName('chapter') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + + if ($_results) + { + $_results = array_unique($_results); + foreach ($_results as $chapter) + { + // Now add the chapter and its text to the options array + $_filter[] = JHtml::_('select.option', $chapter, $chapter); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/index.html b/admin/models/fields/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/models/fields/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/models/fields/linkers.php b/admin/models/fields/linkers.php new file mode 100644 index 0000000..353f9dd --- /dev/null +++ b/admin/models/fields/linkers.php @@ -0,0 +1,183 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Linkers Form Field class for the Getbible component + */ +class JFormFieldLinkers extends JFormFieldList +{ + /** + * The linkers field type. + * + * @var string + */ + public $type = 'linkers'; + + /** + * Override to add new button + * + * @return string The field input markup. + * + * @since 3.2 + */ + protected function getInput() + { + // see if we should add buttons + $set_button = $this->getAttribute('button'); + // get html + $html = parent::getInput(); + // if true set button + if ($set_button === 'true') + { + $button = array(); + $script = array(); + $button_code_name = $this->getAttribute('name'); + // get the input from url + $app = JFactory::getApplication(); + $jinput = $app->input; + // get the view name & id + $values = $jinput->getArray(array( + 'id' => 'int', + 'view' => 'word' + )); + // check if new item + $ref = ''; + $refJ = ''; + if (!is_null($values['id']) && strlen($values['view'])) + { + // only load referral if not new item. + $ref = '&ref=' . $values['view'] . '&refid=' . $values['id']; + $refJ = '&ref=' . $values['view'] . '&refid=' . $values['id']; + // get the return value. + $_uri = (string) JUri::getInstance(); + $_return = urlencode(base64_encode($_uri)); + // load return value. + $ref .= '&return=' . $_return; + $refJ .= '&return=' . $_return; + } + // get button label + $button_label = trim($button_code_name); + $button_label = preg_replace('/_+/', ' ', $button_label); + $button_label = preg_replace('/\s+/', ' ', $button_label); + $button_label = preg_replace("/[^A-Za-z ]/", '', $button_label); + $button_label = ucfirst(strtolower($button_label)); + // get user object + $user = JFactory::getUser(); + // only add if user allowed to create linker + if ($user->authorise('linker.create', 'com_getbible') && $app->isAdmin()) // TODO for now only in admin area. + { + // build Create button + $button[] = ' + '; + } + // only add if user allowed to edit linker + if ($user->authorise('linker.edit', 'com_getbible') && $app->isAdmin()) // TODO for now only in admin area. + { + // build edit button + $button[] = ''; + // build script + $script[] = " + jQuery(document).ready(function() { + jQuery('#adminForm').on('change', '#jform_".$button_code_name."',function (e) { + e.preventDefault(); + var ".$button_code_name."Value = jQuery('#jform_".$button_code_name."').val(); + ".$button_code_name."Button(".$button_code_name."Value); + }); + var ".$button_code_name."Value = jQuery('#jform_".$button_code_name."').val(); + ".$button_code_name."Button(".$button_code_name."Value); + }); + function ".$button_code_name."Button(value) { + if (value > 0) { + // hide the create button + jQuery('#".$button_code_name."Create').hide(); + // show edit button + jQuery('#".$button_code_name."Edit').show(); + var url = 'index.php?option=com_getbible&view=linkers&task=linker.edit&id='+value+'".$refJ."'; + jQuery('#".$button_code_name."Edit').attr('href', url); + } else { + // show the create button + jQuery('#".$button_code_name."Create').show(); + // hide edit button + jQuery('#".$button_code_name."Edit').hide(); + } + }"; + } + // check if button was created for linker field. + if (is_array($button) && count($button) > 0) + { + // Load the needed script. + $document = JFactory::getDocument(); + $document->addScriptDeclaration(implode(' ',$script)); + // return the button attached to input field. + return '
' .$html . implode('',$button).'
'; + } + } + return $html; + } + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get the user object. + $user = JFactory::getUser(); + // Get the databse object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + $query->select($db->quoteName(array('a.guid','a.name'),array('guid','linker_name'))); + $query->from($db->quoteName('#__getbible_linker', 'a')); + $query->where($db->quoteName('a.published') . ' = 1'); + $query->order('a.name ASC'); + // Implement View Level Access (if set in table) + if (!$user->authorise('core.options', 'com_getbible')) + { + $columns = $db->getTableColumns('#__getbible_linker'); + if(isset($columns['access'])) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + } + $db->setQuery((string)$query); + $items = $db->loadObjectList(); + $options = array(); + if ($items) + { + if ($this->multiple === false) + { + $options[] = JHtml::_('select.option', '', JText::_('COM_GETBIBLE_SELECT_AN_OPTION')); + } + foreach($items as $item) + { + $options[] = JHtml::_('select.option', $item->guid, $item->linker_name . ' (' . substr($item->guid, 0, 8) . ')'); + } + } + return $options; + } +} diff --git a/admin/models/fields/linkersfiltername.php b/admin/models/fields/linkersfiltername.php new file mode 100644 index 0000000..61be658 --- /dev/null +++ b/admin/models/fields/linkersfiltername.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Linkersfiltername Form Field class for the Getbible component + */ +class JFormFieldLinkersfiltername extends JFormFieldList +{ + /** + * The linkersfiltername field type. + * + * @var string + */ + public $type = 'linkersfiltername'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('name')); + $query->from($db->quoteName('#__getbible_linker')); + $query->order($db->quoteName('name') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_NAME') . ' -'); + + if ($_results) + { + $_results = array_unique($_results); + foreach ($_results as $name) + { + // Now add the name and its text to the options array + $_filter[] = JHtml::_('select.option', $name, $name); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/notesfilteraccess.php b/admin/models/fields/notesfilteraccess.php new file mode 100644 index 0000000..bfd55ca --- /dev/null +++ b/admin/models/fields/notesfilteraccess.php @@ -0,0 +1,77 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Notesfilteraccess Form Field class for the Getbible component + */ +class JFormFieldNotesfilteraccess extends JFormFieldList +{ + /** + * The notesfilteraccess field type. + * + * @var string + */ + public $type = 'notesfilteraccess'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('access')); + $query->from($db->quoteName('#__getbible_note')); + $query->order($db->quoteName('access') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_ACCESS') . ' -'); + + if ($_results) + { + // get notesmodel + $_model = GetbibleHelper::getModel('notes'); + $_results = array_unique($_results); + foreach ($_results as $access) + { + // Translate the access selection + $_text = $_model->selectionTranslation($access,'access'); + // Now add the access and its text to the options array + $_filter[] = JHtml::_('select.option', $access, JText::_($_text)); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/notesfilterbooknr.php b/admin/models/fields/notesfilterbooknr.php new file mode 100644 index 0000000..ed521db --- /dev/null +++ b/admin/models/fields/notesfilterbooknr.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Notesfilterbooknr Form Field class for the Getbible component + */ +class JFormFieldNotesfilterbooknr extends JFormFieldList +{ + /** + * The notesfilterbooknr field type. + * + * @var string + */ + public $type = 'notesfilterbooknr'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('book_nr')); + $query->from($db->quoteName('#__getbible_note')); + $query->order($db->quoteName('book_nr') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_BOOK_NUMBER') . ' -'); + + if ($_results) + { + $_results = array_unique($_results); + foreach ($_results as $book_nr) + { + // Now add the book_nr and its text to the options array + $_filter[] = JHtml::_('select.option', $book_nr, $book_nr); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/notesfilterchapter.php b/admin/models/fields/notesfilterchapter.php new file mode 100644 index 0000000..406af4f --- /dev/null +++ b/admin/models/fields/notesfilterchapter.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Notesfilterchapter Form Field class for the Getbible component + */ +class JFormFieldNotesfilterchapter extends JFormFieldList +{ + /** + * The notesfilterchapter field type. + * + * @var string + */ + public $type = 'notesfilterchapter'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('chapter')); + $query->from($db->quoteName('#__getbible_note')); + $query->order($db->quoteName('chapter') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_CHAPTER') . ' -'); + + if ($_results) + { + $_results = array_unique($_results); + foreach ($_results as $chapter) + { + // Now add the chapter and its text to the options array + $_filter[] = JHtml::_('select.option', $chapter, $chapter); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/notesfilterverse.php b/admin/models/fields/notesfilterverse.php new file mode 100644 index 0000000..514fc29 --- /dev/null +++ b/admin/models/fields/notesfilterverse.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Notesfilterverse Form Field class for the Getbible component + */ +class JFormFieldNotesfilterverse extends JFormFieldList +{ + /** + * The notesfilterverse field type. + * + * @var string + */ + public $type = 'notesfilterverse'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('verse')); + $query->from($db->quoteName('#__getbible_note')); + $query->order($db->quoteName('verse') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_VERSE') . ' -'); + + if ($_results) + { + $_results = array_unique($_results); + foreach ($_results as $verse) + { + // Now add the verse and its text to the options array + $_filter[] = JHtml::_('select.option', $verse, $verse); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/openaimessagesfilterrole.php b/admin/models/fields/openaimessagesfilterrole.php new file mode 100644 index 0000000..b4f9067 --- /dev/null +++ b/admin/models/fields/openaimessagesfilterrole.php @@ -0,0 +1,77 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Openaimessagesfilterrole Form Field class for the Getbible component + */ +class JFormFieldOpenaimessagesfilterrole extends JFormFieldList +{ + /** + * The openaimessagesfilterrole field type. + * + * @var string + */ + public $type = 'openaimessagesfilterrole'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('role')); + $query->from($db->quoteName('#__getbible_open_ai_message')); + $query->order($db->quoteName('role') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_ROLE') . ' -'); + + if ($_results) + { + // get open_ai_messagesmodel + $_model = GetbibleHelper::getModel('open_ai_messages'); + $_results = array_unique($_results); + foreach ($_results as $role) + { + // Translate the role selection + $_text = $_model->selectionTranslation($role,'role'); + // Now add the role and its text to the options array + $_filter[] = JHtml::_('select.option', $role, JText::_($_text)); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/openaimessagesfiltersource.php b/admin/models/fields/openaimessagesfiltersource.php new file mode 100644 index 0000000..6d1cd1f --- /dev/null +++ b/admin/models/fields/openaimessagesfiltersource.php @@ -0,0 +1,77 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Openaimessagesfiltersource Form Field class for the Getbible component + */ +class JFormFieldOpenaimessagesfiltersource extends JFormFieldList +{ + /** + * The openaimessagesfiltersource field type. + * + * @var string + */ + public $type = 'openaimessagesfiltersource'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('source')); + $query->from($db->quoteName('#__getbible_open_ai_message')); + $query->order($db->quoteName('source') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_SOURCE') . ' -'); + + if ($_results) + { + // get open_ai_messagesmodel + $_model = GetbibleHelper::getModel('open_ai_messages'); + $_results = array_unique($_results); + foreach ($_results as $source) + { + // Translate the source selection + $_text = $_model->selectionTranslation($source,'source'); + // Now add the source and its text to the options array + $_filter[] = JHtml::_('select.option', $source, JText::_($_text)); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/openairesponses.php b/admin/models/fields/openairesponses.php new file mode 100644 index 0000000..8816b75 --- /dev/null +++ b/admin/models/fields/openairesponses.php @@ -0,0 +1,78 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Openairesponses Form Field class for the Getbible component + */ +class JFormFieldOpenairesponses extends JFormFieldList +{ + /** + * The openairesponses field type. + * + * @var string + */ + public $type = 'openairesponses'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get the user object. + $user = JFactory::getUser(); + // Get the databse object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + $query->select($db->quoteName(array('a.response_id','a.response_id'),array('response_id','open_ai_response_response_id'))); + $query->from($db->quoteName('#__getbible_open_ai_response', 'a')); + $query->order('a.response_id ASC'); + // Implement View Level Access (if set in table) + if (!$user->authorise('core.options', 'com_getbible')) + { + $columns = $db->getTableColumns('#__getbible_open_ai_response'); + if(isset($columns['access'])) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + } + $db->setQuery((string)$query); + $items = $db->loadObjectList(); + $options = array(); + if ($items) + { + if ($this->multiple === false) + { + $options[] = JHtml::_('select.option', '', JText::_('COM_GETBIBLE_SELECT_AN_OPTION')); + } + foreach($items as $item) + { + $options[] = JHtml::_('select.option', $item->response_id, $item->open_ai_response_response_id); + } + } + return $options; + } +} diff --git a/admin/models/fields/openairesponsesfilterresponseid.php b/admin/models/fields/openairesponsesfilterresponseid.php new file mode 100644 index 0000000..5e19576 --- /dev/null +++ b/admin/models/fields/openairesponsesfilterresponseid.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Openairesponsesfilterresponseid Form Field class for the Getbible component + */ +class JFormFieldOpenairesponsesfilterresponseid extends JFormFieldList +{ + /** + * The openairesponsesfilterresponseid field type. + * + * @var string + */ + public $type = 'openairesponsesfilterresponseid'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('response_id')); + $query->from($db->quoteName('#__getbible_open_ai_response')); + $query->order($db->quoteName('response_id') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_RESPONSE_ID') . ' -'); + + if ($_results) + { + $_results = array_unique($_results); + foreach ($_results as $response_id) + { + // Now add the response_id and its text to the options array + $_filter[] = JHtml::_('select.option', $response_id, $response_id); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/openairesponsesfilterresponsemodel.php b/admin/models/fields/openairesponsesfilterresponsemodel.php new file mode 100644 index 0000000..13741ae --- /dev/null +++ b/admin/models/fields/openairesponsesfilterresponsemodel.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Openairesponsesfilterresponsemodel Form Field class for the Getbible component + */ +class JFormFieldOpenairesponsesfilterresponsemodel extends JFormFieldList +{ + /** + * The openairesponsesfilterresponsemodel field type. + * + * @var string + */ + public $type = 'openairesponsesfilterresponsemodel'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('response_model')); + $query->from($db->quoteName('#__getbible_open_ai_response')); + $query->order($db->quoteName('response_model') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_RESPONSE_MODEL') . ' -'); + + if ($_results) + { + $_results = array_unique($_results); + foreach ($_results as $response_model) + { + // Now add the response_model and its text to the options array + $_filter[] = JHtml::_('select.option', $response_model, $response_model); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/passwordsfiltername.php b/admin/models/fields/passwordsfiltername.php new file mode 100644 index 0000000..bc0b3f8 --- /dev/null +++ b/admin/models/fields/passwordsfiltername.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Passwordsfiltername Form Field class for the Getbible component + */ +class JFormFieldPasswordsfiltername extends JFormFieldList +{ + /** + * The passwordsfiltername field type. + * + * @var string + */ + public $type = 'passwordsfiltername'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('name')); + $query->from($db->quoteName('#__getbible_password')); + $query->order($db->quoteName('name') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_NAME') . ' -'); + + if ($_results) + { + $_results = array_unique($_results); + foreach ($_results as $name) + { + // Now add the name and its text to the options array + $_filter[] = JHtml::_('select.option', $name, $name); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/prompts.php b/admin/models/fields/prompts.php new file mode 100644 index 0000000..dbfa2b2 --- /dev/null +++ b/admin/models/fields/prompts.php @@ -0,0 +1,78 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Prompts Form Field class for the Getbible component + */ +class JFormFieldPrompts extends JFormFieldList +{ + /** + * The prompts field type. + * + * @var string + */ + public $type = 'prompts'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get the user object. + $user = JFactory::getUser(); + // Get the databse object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + $query->select($db->quoteName(array('a.guid','a.name'),array('guid','prompt_name'))); + $query->from($db->quoteName('#__getbible_prompt', 'a')); + $query->order('a.name ASC'); + // Implement View Level Access (if set in table) + if (!$user->authorise('core.options', 'com_getbible')) + { + $columns = $db->getTableColumns('#__getbible_prompt'); + if(isset($columns['access'])) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + } + $db->setQuery((string)$query); + $items = $db->loadObjectList(); + $options = array(); + if ($items) + { + if ($this->multiple === false) + { + $options[] = JHtml::_('select.option', '', JText::_('COM_GETBIBLE_SELECT_AN_OPTION')); + } + foreach($items as $item) + { + $options[] = JHtml::_('select.option', $item->guid, $item->prompt_name . ' (' . $item->guid . ')'); + } + } + return $options; + } +} diff --git a/admin/models/fields/promptsfiltercachebehaviour.php b/admin/models/fields/promptsfiltercachebehaviour.php new file mode 100644 index 0000000..c3796fc --- /dev/null +++ b/admin/models/fields/promptsfiltercachebehaviour.php @@ -0,0 +1,77 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Promptsfiltercachebehaviour Form Field class for the Getbible component + */ +class JFormFieldPromptsfiltercachebehaviour extends JFormFieldList +{ + /** + * The promptsfiltercachebehaviour field type. + * + * @var string + */ + public $type = 'promptsfiltercachebehaviour'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('cache_behaviour')); + $query->from($db->quoteName('#__getbible_prompt')); + $query->order($db->quoteName('cache_behaviour') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_CACHE_BEHAVIOUR') . ' -'); + + if ($_results) + { + // get promptsmodel + $_model = GetbibleHelper::getModel('prompts'); + $_results = array_unique($_results); + foreach ($_results as $cache_behaviour) + { + // Translate the cache_behaviour selection + $_text = $_model->selectionTranslation($cache_behaviour,'cache_behaviour'); + // Now add the cache_behaviour and its text to the options array + $_filter[] = JHtml::_('select.option', $cache_behaviour, JText::_($_text)); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/promptsfiltermodel.php b/admin/models/fields/promptsfiltermodel.php new file mode 100644 index 0000000..fcd3556 --- /dev/null +++ b/admin/models/fields/promptsfiltermodel.php @@ -0,0 +1,77 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Promptsfiltermodel Form Field class for the Getbible component + */ +class JFormFieldPromptsfiltermodel extends JFormFieldList +{ + /** + * The promptsfiltermodel field type. + * + * @var string + */ + public $type = 'promptsfiltermodel'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('model')); + $query->from($db->quoteName('#__getbible_prompt')); + $query->order($db->quoteName('model') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_MODEL') . ' -'); + + if ($_results) + { + // get promptsmodel + $_model = GetbibleHelper::getModel('prompts'); + $_results = array_unique($_results); + foreach ($_results as $model) + { + // Translate the model selection + $_text = $_model->selectionTranslation($model,'model'); + // Now add the model and its text to the options array + $_filter[] = JHtml::_('select.option', $model, JText::_($_text)); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/promptsfiltername.php b/admin/models/fields/promptsfiltername.php new file mode 100644 index 0000000..d116c01 --- /dev/null +++ b/admin/models/fields/promptsfiltername.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Promptsfiltername Form Field class for the Getbible component + */ +class JFormFieldPromptsfiltername extends JFormFieldList +{ + /** + * The promptsfiltername field type. + * + * @var string + */ + public $type = 'promptsfiltername'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('name')); + $query->from($db->quoteName('#__getbible_prompt')); + $query->order($db->quoteName('name') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_NAME') . ' -'); + + if ($_results) + { + $_results = array_unique($_results); + foreach ($_results as $name) + { + // Now add the name and its text to the options array + $_filter[] = JHtml::_('select.option', $name, $name); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/tagers.php b/admin/models/fields/tagers.php new file mode 100644 index 0000000..315797b --- /dev/null +++ b/admin/models/fields/tagers.php @@ -0,0 +1,183 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Tagers Form Field class for the Getbible component + */ +class JFormFieldTagers extends JFormFieldList +{ + /** + * The tagers field type. + * + * @var string + */ + public $type = 'tagers'; + + /** + * Override to add new button + * + * @return string The field input markup. + * + * @since 3.2 + */ + protected function getInput() + { + // see if we should add buttons + $set_button = $this->getAttribute('button'); + // get html + $html = parent::getInput(); + // if true set button + if ($set_button === 'true') + { + $button = array(); + $script = array(); + $button_code_name = $this->getAttribute('name'); + // get the input from url + $app = JFactory::getApplication(); + $jinput = $app->input; + // get the view name & id + $values = $jinput->getArray(array( + 'id' => 'int', + 'view' => 'word' + )); + // check if new item + $ref = ''; + $refJ = ''; + if (!is_null($values['id']) && strlen($values['view'])) + { + // only load referral if not new item. + $ref = '&ref=' . $values['view'] . '&refid=' . $values['id']; + $refJ = '&ref=' . $values['view'] . '&refid=' . $values['id']; + // get the return value. + $_uri = (string) JUri::getInstance(); + $_return = urlencode(base64_encode($_uri)); + // load return value. + $ref .= '&return=' . $_return; + $refJ .= '&return=' . $_return; + } + // get button label + $button_label = trim($button_code_name); + $button_label = preg_replace('/_+/', ' ', $button_label); + $button_label = preg_replace('/\s+/', ' ', $button_label); + $button_label = preg_replace("/[^A-Za-z ]/", '', $button_label); + $button_label = ucfirst(strtolower($button_label)); + // get user object + $user = JFactory::getUser(); + // only add if user allowed to create tag + if ($user->authorise('tag.create', 'com_getbible') && $app->isAdmin()) // TODO for now only in admin area. + { + // build Create button + $button[] = ' + '; + } + // only add if user allowed to edit tag + if ($user->authorise('tag.edit', 'com_getbible') && $app->isAdmin()) // TODO for now only in admin area. + { + // build edit button + $button[] = ''; + // build script + $script[] = " + jQuery(document).ready(function() { + jQuery('#adminForm').on('change', '#jform_".$button_code_name."',function (e) { + e.preventDefault(); + var ".$button_code_name."Value = jQuery('#jform_".$button_code_name."').val(); + ".$button_code_name."Button(".$button_code_name."Value); + }); + var ".$button_code_name."Value = jQuery('#jform_".$button_code_name."').val(); + ".$button_code_name."Button(".$button_code_name."Value); + }); + function ".$button_code_name."Button(value) { + if (value > 0) { + // hide the create button + jQuery('#".$button_code_name."Create').hide(); + // show edit button + jQuery('#".$button_code_name."Edit').show(); + var url = 'index.php?option=com_getbible&view=tags&task=tag.edit&id='+value+'".$refJ."'; + jQuery('#".$button_code_name."Edit').attr('href', url); + } else { + // show the create button + jQuery('#".$button_code_name."Create').show(); + // hide edit button + jQuery('#".$button_code_name."Edit').hide(); + } + }"; + } + // check if button was created for tag field. + if (is_array($button) && count($button) > 0) + { + // Load the needed script. + $document = JFactory::getDocument(); + $document->addScriptDeclaration(implode(' ',$script)); + // return the button attached to input field. + return '
' .$html . implode('',$button).'
'; + } + } + return $html; + } + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get the user object. + $user = JFactory::getUser(); + // Get the databse object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + $query->select($db->quoteName(array('a.guid','a.name'),array('guid','tag_name'))); + $query->from($db->quoteName('#__getbible_tag', 'a')); + $query->where($db->quoteName('a.published') . ' = 1'); + $query->order('a.name ASC'); + // Implement View Level Access (if set in table) + if (!$user->authorise('core.options', 'com_getbible')) + { + $columns = $db->getTableColumns('#__getbible_tag'); + if(isset($columns['access'])) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + } + $db->setQuery((string)$query); + $items = $db->loadObjectList(); + $options = array(); + if ($items) + { + if ($this->multiple === false) + { + $options[] = JHtml::_('select.option', '', JText::_('COM_GETBIBLE_SELECT_AN_OPTION')); + } + foreach($items as $item) + { + $options[] = JHtml::_('select.option', $item->guid, $item->tag_name . ' (' . substr($item->guid, 0, 8) . ')'); + } + } + return $options; + } +} diff --git a/admin/models/fields/taggedversesfilteraccess.php b/admin/models/fields/taggedversesfilteraccess.php new file mode 100644 index 0000000..98be0bd --- /dev/null +++ b/admin/models/fields/taggedversesfilteraccess.php @@ -0,0 +1,77 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Taggedversesfilteraccess Form Field class for the Getbible component + */ +class JFormFieldTaggedversesfilteraccess extends JFormFieldList +{ + /** + * The taggedversesfilteraccess field type. + * + * @var string + */ + public $type = 'taggedversesfilteraccess'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('access')); + $query->from($db->quoteName('#__getbible_tagged_verse')); + $query->order($db->quoteName('access') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_ACCESS') . ' -'); + + if ($_results) + { + // get tagged_versesmodel + $_model = GetbibleHelper::getModel('tagged_verses'); + $_results = array_unique($_results); + foreach ($_results as $access) + { + // Translate the access selection + $_text = $_model->selectionTranslation($access,'access'); + // Now add the access and its text to the options array + $_filter[] = JHtml::_('select.option', $access, JText::_($_text)); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/taggedversesfilterbooknr.php b/admin/models/fields/taggedversesfilterbooknr.php new file mode 100644 index 0000000..d86ad5d --- /dev/null +++ b/admin/models/fields/taggedversesfilterbooknr.php @@ -0,0 +1,72 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Taggedversesfilterbooknr Form Field class for the Getbible component + */ +class JFormFieldTaggedversesfilterbooknr extends JFormFieldList +{ + /** + * The taggedversesfilterbooknr field type. + * + * @var string + */ + public $type = 'taggedversesfilterbooknr'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('book_nr')); + $query->from($db->quoteName('#__getbible_tagged_verse')); + $query->order($db->quoteName('book_nr') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + + if ($_results) + { + $_results = array_unique($_results); + foreach ($_results as $book_nr) + { + // Now add the book_nr and its text to the options array + $_filter[] = JHtml::_('select.option', $book_nr, $book_nr); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/taggedversesfilterchapter.php b/admin/models/fields/taggedversesfilterchapter.php new file mode 100644 index 0000000..a1b3e19 --- /dev/null +++ b/admin/models/fields/taggedversesfilterchapter.php @@ -0,0 +1,72 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Taggedversesfilterchapter Form Field class for the Getbible component + */ +class JFormFieldTaggedversesfilterchapter extends JFormFieldList +{ + /** + * The taggedversesfilterchapter field type. + * + * @var string + */ + public $type = 'taggedversesfilterchapter'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('chapter')); + $query->from($db->quoteName('#__getbible_tagged_verse')); + $query->order($db->quoteName('chapter') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + + if ($_results) + { + $_results = array_unique($_results); + foreach ($_results as $chapter) + { + // Now add the chapter and its text to the options array + $_filter[] = JHtml::_('select.option', $chapter, $chapter); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/taggedversesfilterverse.php b/admin/models/fields/taggedversesfilterverse.php new file mode 100644 index 0000000..c6e1254 --- /dev/null +++ b/admin/models/fields/taggedversesfilterverse.php @@ -0,0 +1,72 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Taggedversesfilterverse Form Field class for the Getbible component + */ +class JFormFieldTaggedversesfilterverse extends JFormFieldList +{ + /** + * The taggedversesfilterverse field type. + * + * @var string + */ + public $type = 'taggedversesfilterverse'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('verse')); + $query->from($db->quoteName('#__getbible_tagged_verse')); + $query->order($db->quoteName('verse') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + + if ($_results) + { + $_results = array_unique($_results); + foreach ($_results as $verse) + { + // Now add the verse and its text to the options array + $_filter[] = JHtml::_('select.option', $verse, $verse); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/tagsfilteraccess.php b/admin/models/fields/tagsfilteraccess.php new file mode 100644 index 0000000..5bbc513 --- /dev/null +++ b/admin/models/fields/tagsfilteraccess.php @@ -0,0 +1,77 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Tagsfilteraccess Form Field class for the Getbible component + */ +class JFormFieldTagsfilteraccess extends JFormFieldList +{ + /** + * The tagsfilteraccess field type. + * + * @var string + */ + public $type = 'tagsfilteraccess'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('access')); + $query->from($db->quoteName('#__getbible_tag')); + $query->order($db->quoteName('access') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_ACCESS') . ' -'); + + if ($_results) + { + // get tagsmodel + $_model = GetbibleHelper::getModel('tags'); + $_results = array_unique($_results); + foreach ($_results as $access) + { + // Translate the access selection + $_text = $_model->selectionTranslation($access,'access'); + // Now add the access and its text to the options array + $_filter[] = JHtml::_('select.option', $access, JText::_($_text)); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/targettranslations.php b/admin/models/fields/targettranslations.php new file mode 100644 index 0000000..29e9b34 --- /dev/null +++ b/admin/models/fields/targettranslations.php @@ -0,0 +1,80 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Targettranslations Form Field class for the Getbible component + */ +class JFormFieldTargettranslations extends JFormFieldList +{ + /** + * The targettranslations field type. + * + * @var string + */ + public $type = 'targettranslations'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get the user object. + $user = JFactory::getUser(); + // Get the databse object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + $query->select($db->quoteName(array('a.abbreviation','a.translation'),array('abbreviation','abbreviation_translation'))); + $query->from($db->quoteName('#__getbible_translation', 'a')); + $query->where($db->quoteName('a.published') . ' = 1'); + $query->order('a.translation ASC'); + // Implement View Level Access (if set in table) + if (!$user->authorise('core.options', 'com_getbible')) + { + $columns = $db->getTableColumns('#__getbible_translation'); + if(isset($columns['access'])) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + } + $db->setQuery((string)$query); + $items = $db->loadObjectList(); + $options = array(); + if ($items) + { + if ($this->multiple === false) + { + $options[] = JHtml::_('select.option', '', JText::_('COM_GETBIBLE_SELECT_AN_OPTION')); + } + $options[] = JHtml::_('select.option', 'all', JText::_('COM_GETBIBLE_ALL_TRANSLATIONS')); + foreach($items as $item) + { + $options[] = JHtml::_('select.option', $item->abbreviation, $item->abbreviation_translation.' (' .$item->abbreviation.')'); + } + } + return $options; + } +} diff --git a/admin/models/fields/translations.php b/admin/models/fields/translations.php new file mode 100644 index 0000000..e2e65d6 --- /dev/null +++ b/admin/models/fields/translations.php @@ -0,0 +1,79 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Translations Form Field class for the Getbible component + */ +class JFormFieldTranslations extends JFormFieldList +{ + /** + * The translations field type. + * + * @var string + */ + public $type = 'translations'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get the user object. + $user = JFactory::getUser(); + // Get the databse object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + $query->select($db->quoteName(array('a.abbreviation','a.translation'),array('abbreviation','abbreviation_translation'))); + $query->from($db->quoteName('#__getbible_translation', 'a')); + $query->where($db->quoteName('a.published') . ' = 1'); + $query->order('a.translation ASC'); + // Implement View Level Access (if set in table) + if (!$user->authorise('core.options', 'com_getbible')) + { + $columns = $db->getTableColumns('#__getbible_translation'); + if(isset($columns['access'])) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + } + $db->setQuery((string)$query); + $items = $db->loadObjectList(); + $options = array(); + if ($items) + { + if ($this->multiple === false) + { + $options[] = JHtml::_('select.option', '', JText::_('COM_GETBIBLE_SELECT_AN_OPTION')); + } + foreach($items as $item) + { + $options[] = JHtml::_('select.option', $item->abbreviation, $item->abbreviation_translation.' (' .$item->abbreviation.')'); + } + } + return $options; + } +} diff --git a/admin/models/fields/translationsfilterdirection.php b/admin/models/fields/translationsfilterdirection.php new file mode 100644 index 0000000..23c3d5c --- /dev/null +++ b/admin/models/fields/translationsfilterdirection.php @@ -0,0 +1,77 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Translationsfilterdirection Form Field class for the Getbible component + */ +class JFormFieldTranslationsfilterdirection extends JFormFieldList +{ + /** + * The translationsfilterdirection field type. + * + * @var string + */ + public $type = 'translationsfilterdirection'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('direction')); + $query->from($db->quoteName('#__getbible_translation')); + $query->order($db->quoteName('direction') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_DIRECTIONAL') . ' -'); + + if ($_results) + { + // get translationsmodel + $_model = GetbibleHelper::getModel('translations'); + $_results = array_unique($_results); + foreach ($_results as $direction) + { + // Translate the direction selection + $_text = $_model->selectionTranslation($direction,'direction'); + // Now add the direction and its text to the options array + $_filter[] = JHtml::_('select.option', $direction, JText::_($_text)); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/versesfilterbooknr.php b/admin/models/fields/versesfilterbooknr.php new file mode 100644 index 0000000..3a06f5b --- /dev/null +++ b/admin/models/fields/versesfilterbooknr.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Versesfilterbooknr Form Field class for the Getbible component + */ +class JFormFieldVersesfilterbooknr extends JFormFieldList +{ + /** + * The versesfilterbooknr field type. + * + * @var string + */ + public $type = 'versesfilterbooknr'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('book_nr')); + $query->from($db->quoteName('#__getbible_verse')); + $query->order($db->quoteName('book_nr') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_BOOK_NUMBER') . ' -'); + + if ($_results) + { + $_results = array_unique($_results); + foreach ($_results as $book_nr) + { + // Now add the book_nr and its text to the options array + $_filter[] = JHtml::_('select.option', $book_nr, $book_nr); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/versesfilterchapter.php b/admin/models/fields/versesfilterchapter.php new file mode 100644 index 0000000..757b747 --- /dev/null +++ b/admin/models/fields/versesfilterchapter.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Versesfilterchapter Form Field class for the Getbible component + */ +class JFormFieldVersesfilterchapter extends JFormFieldList +{ + /** + * The versesfilterchapter field type. + * + * @var string + */ + public $type = 'versesfilterchapter'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('chapter')); + $query->from($db->quoteName('#__getbible_verse')); + $query->order($db->quoteName('chapter') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_CHAPTER') . ' -'); + + if ($_results) + { + $_results = array_unique($_results); + foreach ($_results as $chapter) + { + // Now add the chapter and its text to the options array + $_filter[] = JHtml::_('select.option', $chapter, $chapter); + } + } + return $_filter; + } +} diff --git a/admin/models/fields/versesfilterverse.php b/admin/models/fields/versesfilterverse.php new file mode 100644 index 0000000..dc5bac4 --- /dev/null +++ b/admin/models/fields/versesfilterverse.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import the list field type +jimport('joomla.form.helper'); +JFormHelper::loadFieldClass('list'); + +/** + * Versesfilterverse Form Field class for the Getbible component + */ +class JFormFieldVersesfilterverse extends JFormFieldList +{ + /** + * The versesfilterverse field type. + * + * @var string + */ + public $type = 'versesfilterverse'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + */ + protected function getOptions() + { + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Select the text. + $query->select($db->quoteName('verse')); + $query->from($db->quoteName('#__getbible_verse')); + $query->order($db->quoteName('verse') . ' ASC'); + + // Reset the query using our newly populated query object. + $db->setQuery($query); + + $_results = $db->loadColumn(); + $_filter = array(); + $_filter[] = JHtml::_('select.option', '', '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_VERSE') . ' -'); + + if ($_results) + { + $_results = array_unique($_results); + foreach ($_results as $verse) + { + // Now add the verse and its text to the options array + $_filter[] = JHtml::_('select.option', $verse, $verse); + } + } + return $_filter; + } +} diff --git a/admin/models/forms/book.xml b/admin/models/forms/book.xml new file mode 100644 index 0000000..637d005 --- /dev/null +++ b/admin/models/forms/book.xml @@ -0,0 +1,184 @@ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + +
+
\ No newline at end of file diff --git a/admin/models/forms/chapter.xml b/admin/models/forms/chapter.xml new file mode 100644 index 0000000..04ebb2a --- /dev/null +++ b/admin/models/forms/chapter.xml @@ -0,0 +1,196 @@ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + +
+
\ No newline at end of file diff --git a/admin/models/forms/filter_books.xml b/admin/models/forms/filter_books.xml new file mode 100644 index 0000000..7d73d57 --- /dev/null +++ b/admin/models/forms/filter_books.xml @@ -0,0 +1,92 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/admin/models/forms/filter_chapters.xml b/admin/models/forms/filter_chapters.xml new file mode 100644 index 0000000..8416068 --- /dev/null +++ b/admin/models/forms/filter_chapters.xml @@ -0,0 +1,96 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/admin/models/forms/filter_linkers.xml b/admin/models/forms/filter_linkers.xml new file mode 100644 index 0000000..a0dcc2b --- /dev/null +++ b/admin/models/forms/filter_linkers.xml @@ -0,0 +1,74 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/admin/models/forms/filter_notes.xml b/admin/models/forms/filter_notes.xml new file mode 100644 index 0000000..eb993ae --- /dev/null +++ b/admin/models/forms/filter_notes.xml @@ -0,0 +1,97 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/admin/models/forms/filter_open_ai_messages.xml b/admin/models/forms/filter_open_ai_messages.xml new file mode 100644 index 0000000..e063789 --- /dev/null +++ b/admin/models/forms/filter_open_ai_messages.xml @@ -0,0 +1,101 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/admin/models/forms/filter_open_ai_responses.xml b/admin/models/forms/filter_open_ai_responses.xml new file mode 100644 index 0000000..d202ba3 --- /dev/null +++ b/admin/models/forms/filter_open_ai_responses.xml @@ -0,0 +1,96 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/admin/models/forms/filter_passwords.xml b/admin/models/forms/filter_passwords.xml new file mode 100644 index 0000000..4e85b64 --- /dev/null +++ b/admin/models/forms/filter_passwords.xml @@ -0,0 +1,83 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/admin/models/forms/filter_prompts.xml b/admin/models/forms/filter_prompts.xml new file mode 100644 index 0000000..5e4de04 --- /dev/null +++ b/admin/models/forms/filter_prompts.xml @@ -0,0 +1,101 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/admin/models/forms/filter_tagged_verses.xml b/admin/models/forms/filter_tagged_verses.xml new file mode 100644 index 0000000..e2b8cc8 --- /dev/null +++ b/admin/models/forms/filter_tagged_verses.xml @@ -0,0 +1,119 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/admin/models/forms/filter_tags.xml b/admin/models/forms/filter_tags.xml new file mode 100644 index 0000000..3e20fac --- /dev/null +++ b/admin/models/forms/filter_tags.xml @@ -0,0 +1,76 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/admin/models/forms/filter_translations.xml b/admin/models/forms/filter_translations.xml new file mode 100644 index 0000000..7c772f2 --- /dev/null +++ b/admin/models/forms/filter_translations.xml @@ -0,0 +1,80 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/admin/models/forms/filter_verses.xml b/admin/models/forms/filter_verses.xml new file mode 100644 index 0000000..cdaccbf --- /dev/null +++ b/admin/models/forms/filter_verses.xml @@ -0,0 +1,101 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/admin/models/forms/index.html b/admin/models/forms/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/models/forms/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/models/forms/linker.xml b/admin/models/forms/linker.xml new file mode 100644 index 0000000..6996ada --- /dev/null +++ b/admin/models/forms/linker.xml @@ -0,0 +1,148 @@ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + +
+
\ No newline at end of file diff --git a/admin/models/forms/note.xml b/admin/models/forms/note.xml new file mode 100644 index 0000000..637b0f6 --- /dev/null +++ b/admin/models/forms/note.xml @@ -0,0 +1,200 @@ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + +
+
\ No newline at end of file diff --git a/admin/models/forms/open_ai_message.xml b/admin/models/forms/open_ai_message.xml new file mode 100644 index 0000000..8b344ae --- /dev/null +++ b/admin/models/forms/open_ai_message.xml @@ -0,0 +1,212 @@ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + +
+
\ No newline at end of file diff --git a/admin/models/forms/open_ai_response.xml b/admin/models/forms/open_ai_response.xml new file mode 100644 index 0000000..d321225 --- /dev/null +++ b/admin/models/forms/open_ai_response.xml @@ -0,0 +1,419 @@ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + +
+
\ No newline at end of file diff --git a/admin/models/forms/password.xml b/admin/models/forms/password.xml new file mode 100644 index 0000000..9617f3e --- /dev/null +++ b/admin/models/forms/password.xml @@ -0,0 +1,174 @@ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + +
+
\ No newline at end of file diff --git a/admin/models/forms/prompt.xml b/admin/models/forms/prompt.xml new file mode 100644 index 0000000..317ad61 --- /dev/null +++ b/admin/models/forms/prompt.xml @@ -0,0 +1,571 @@ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + +
+ \ No newline at end of file diff --git a/admin/models/forms/tag.xml b/admin/models/forms/tag.xml new file mode 100644 index 0000000..a65e7f4 --- /dev/null +++ b/admin/models/forms/tag.xml @@ -0,0 +1,178 @@ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + +
+
\ No newline at end of file diff --git a/admin/models/forms/tagged_verse.xml b/admin/models/forms/tagged_verse.xml new file mode 100644 index 0000000..c19c1e3 --- /dev/null +++ b/admin/models/forms/tagged_verse.xml @@ -0,0 +1,209 @@ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + +
+
\ No newline at end of file diff --git a/admin/models/forms/translation.xml b/admin/models/forms/translation.xml new file mode 100644 index 0000000..c253374 --- /dev/null +++ b/admin/models/forms/translation.xml @@ -0,0 +1,415 @@ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + +
+ \ No newline at end of file diff --git a/admin/models/forms/verse.xml b/admin/models/forms/verse.xml new file mode 100644 index 0000000..19d7c39 --- /dev/null +++ b/admin/models/forms/verse.xml @@ -0,0 +1,209 @@ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + +
+
\ No newline at end of file diff --git a/admin/models/getbible.php b/admin/models/getbible.php new file mode 100644 index 0000000..a676612 --- /dev/null +++ b/admin/models/getbible.php @@ -0,0 +1,431 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\ListModel; +use Joomla\Utilities\ArrayHelper; +use Joomla\Registry\Registry; + +/** + * Getbible List Model + */ +class GetbibleModelGetbible extends ListModel +{ + public function getIcons() + { + // load user for access menus + $user = JFactory::getUser(); + // reset icon array + $icons = array(); + // view groups array + $viewGroups = array( + 'main' => array('png.linkers', 'png.notes', 'png.tagged_verses', 'png.prompts', 'png.open_ai_responses', 'png.tags', 'png.translations', 'png.books', 'png.chapters', 'png.verses') + ); + // view access array + $viewAccess = array( + 'linker.create' => 'linker.create', + 'linkers.access' => 'linker.access', + 'linker.access' => 'linker.access', + 'linkers.submenu' => 'linker.submenu', + 'linkers.dashboard_list' => 'linker.dashboard_list', + 'note.create' => 'note.create', + 'notes.access' => 'note.access', + 'note.access' => 'note.access', + 'notes.submenu' => 'note.submenu', + 'notes.dashboard_list' => 'note.dashboard_list', + 'tagged_verse.create' => 'tagged_verse.create', + 'tagged_verses.access' => 'tagged_verse.access', + 'tagged_verse.access' => 'tagged_verse.access', + 'tagged_verses.submenu' => 'tagged_verse.submenu', + 'tagged_verses.dashboard_list' => 'tagged_verse.dashboard_list', + 'prompt.create' => 'prompt.create', + 'prompts.access' => 'prompt.access', + 'prompt.access' => 'prompt.access', + 'prompts.submenu' => 'prompt.submenu', + 'prompts.dashboard_list' => 'prompt.dashboard_list', + 'open_ai_response.create' => 'open_ai_response.create', + 'open_ai_responses.access' => 'open_ai_response.access', + 'open_ai_response.access' => 'open_ai_response.access', + 'open_ai_responses.submenu' => 'open_ai_response.submenu', + 'open_ai_responses.dashboard_list' => 'open_ai_response.dashboard_list', + 'open_ai_message.create' => 'open_ai_message.create', + 'open_ai_messages.access' => 'open_ai_message.access', + 'open_ai_message.access' => 'open_ai_message.access', + 'password.create' => 'password.create', + 'passwords.access' => 'password.access', + 'password.access' => 'password.access', + 'tag.create' => 'tag.create', + 'tags.access' => 'tag.access', + 'tag.access' => 'tag.access', + 'tags.submenu' => 'tag.submenu', + 'tags.dashboard_list' => 'tag.dashboard_list', + 'translation.create' => 'translation.create', + 'translations.access' => 'translation.access', + 'translation.access' => 'translation.access', + 'translations.submenu' => 'translation.submenu', + 'translations.dashboard_list' => 'translation.dashboard_list', + 'book.create' => 'book.create', + 'books.access' => 'book.access', + 'book.access' => 'book.access', + 'books.submenu' => 'book.submenu', + 'books.dashboard_list' => 'book.dashboard_list', + 'chapter.create' => 'chapter.create', + 'chapters.access' => 'chapter.access', + 'chapter.access' => 'chapter.access', + 'chapters.submenu' => 'chapter.submenu', + 'chapters.dashboard_list' => 'chapter.dashboard_list', + 'verse.create' => 'verse.create', + 'verses.access' => 'verse.access', + 'verse.access' => 'verse.access', + 'verses.submenu' => 'verse.submenu', + 'verses.dashboard_list' => 'verse.dashboard_list'); + // loop over the $views + foreach($viewGroups as $group => $views) + { + $i = 0; + if (GetbibleHelper::checkArray($views)) + { + foreach($views as $view) + { + $add = false; + // external views (links) + if (strpos($view,'||') !== false) + { + $dwd = explode('||', $view); + if (count($dwd) == 3) + { + list($type, $name, $url) = $dwd; + $viewName = $name; + $alt = $name; + $url = $url; + $image = $name . '.' . $type; + $name = 'COM_GETBIBLE_DASHBOARD_' . GetbibleHelper::safeString($name,'U'); + } + } + // internal views + elseif (strpos($view,'.') !== false) + { + $dwd = explode('.', $view); + if (count($dwd) == 3) + { + list($type, $name, $action) = $dwd; + } + elseif (count($dwd) == 2) + { + list($type, $name) = $dwd; + $action = false; + } + if ($action) + { + $viewName = $name; + switch($action) + { + case 'add': + $url = 'index.php?option=com_getbible&view=' . $name . '&layout=edit'; + $image = $name . '_' . $action. '.' . $type; + $alt = $name . ' ' . $action; + $name = 'COM_GETBIBLE_DASHBOARD_'.GetbibleHelper::safeString($name,'U').'_ADD'; + $add = true; + break; + default: + // check for new convention (more stable) + if (strpos($action, '_qpo0O0oqp_') !== false) + { + list($action, $extension) = (array) explode('_qpo0O0oqp_', $action); + $extension = str_replace('_po0O0oq_', '.', $extension); + } + else + { + $extension = 'com_getbible.' . $name; + } + $url = 'index.php?option=com_categories&view=categories&extension=' . $extension; + $image = $name . '_' . $action . '.' . $type; + $alt = $viewName . ' ' . $action; + $name = 'COM_GETBIBLE_DASHBOARD_' . GetbibleHelper::safeString($name,'U') . '_' . GetbibleHelper::safeString($action,'U'); + break; + } + } + else + { + $viewName = $name; + $alt = $name; + $url = 'index.php?option=com_getbible&view=' . $name; + $image = $name . '.' . $type; + $name = 'COM_GETBIBLE_DASHBOARD_' . GetbibleHelper::safeString($name,'U'); + $hover = false; + } + } + else + { + $viewName = $view; + $alt = $view; + $url = 'index.php?option=com_getbible&view=' . $view; + $image = $view . '.png'; + $name = ucwords($view).'

'; + $hover = false; + } + // first make sure the view access is set + if (GetbibleHelper::checkArray($viewAccess)) + { + // setup some defaults + $dashboard_add = false; + $dashboard_list = false; + $accessTo = ''; + $accessAdd = ''; + // access checking start + $accessCreate = (isset($viewAccess[$viewName.'.create'])) ? GetbibleHelper::checkString($viewAccess[$viewName.'.create']):false; + $accessAccess = (isset($viewAccess[$viewName.'.access'])) ? GetbibleHelper::checkString($viewAccess[$viewName.'.access']):false; + // set main controllers + $accessDashboard_add = (isset($viewAccess[$viewName.'.dashboard_add'])) ? GetbibleHelper::checkString($viewAccess[$viewName.'.dashboard_add']):false; + $accessDashboard_list = (isset($viewAccess[$viewName.'.dashboard_list'])) ? GetbibleHelper::checkString($viewAccess[$viewName.'.dashboard_list']):false; + // check for adding access + if ($add && $accessCreate) + { + $accessAdd = $viewAccess[$viewName.'.create']; + } + elseif ($add) + { + $accessAdd = 'core.create'; + } + // check if access to view is set + if ($accessAccess) + { + $accessTo = $viewAccess[$viewName.'.access']; + } + // set main access controllers + if ($accessDashboard_add) + { + $dashboard_add = $user->authorise($viewAccess[$viewName.'.dashboard_add'], 'com_getbible'); + } + if ($accessDashboard_list) + { + $dashboard_list = $user->authorise($viewAccess[$viewName.'.dashboard_list'], 'com_getbible'); + } + if (GetbibleHelper::checkString($accessAdd) && GetbibleHelper::checkString($accessTo)) + { + // check access + if($user->authorise($accessAdd, 'com_getbible') && $user->authorise($accessTo, 'com_getbible') && $dashboard_add) + { + $icons[$group][$i] = new StdClass; + $icons[$group][$i]->url = $url; + $icons[$group][$i]->name = $name; + $icons[$group][$i]->image = $image; + $icons[$group][$i]->alt = $alt; + } + } + elseif (GetbibleHelper::checkString($accessTo)) + { + // check access + if($user->authorise($accessTo, 'com_getbible') && $dashboard_list) + { + $icons[$group][$i] = new StdClass; + $icons[$group][$i]->url = $url; + $icons[$group][$i]->name = $name; + $icons[$group][$i]->image = $image; + $icons[$group][$i]->alt = $alt; + } + } + elseif (GetbibleHelper::checkString($accessAdd)) + { + // check access + if($user->authorise($accessAdd, 'com_getbible') && $dashboard_add) + { + $icons[$group][$i] = new StdClass; + $icons[$group][$i]->url = $url; + $icons[$group][$i]->name = $name; + $icons[$group][$i]->image = $image; + $icons[$group][$i]->alt = $alt; + } + } + else + { + $icons[$group][$i] = new StdClass; + $icons[$group][$i]->url = $url; + $icons[$group][$i]->name = $name; + $icons[$group][$i]->image = $image; + $icons[$group][$i]->alt = $alt; + } + } + else + { + $icons[$group][$i] = new StdClass; + $icons[$group][$i]->url = $url; + $icons[$group][$i]->name = $name; + $icons[$group][$i]->image = $image; + $icons[$group][$i]->alt = $alt; + } + $i++; + } + } + else + { + $icons[$group][$i] = false; + } + } + return $icons; + } + + + public function getWiki() + { + // the call URL + $call_url = JUri::base() . 'index.php?option=com_getbible&task=ajax.getWiki&format=json&raw=true&' . JSession::getFormToken() . '=1&name=Home'; + $document = JFactory::getDocument(); + $document->addScriptDeclaration(' + function getWikiPage(){ + + fetch("' . $call_url . '").then((response) => { + if (response.ok) { + return response.json(); + } + }).then((result) => { + if (typeof result.page !== "undefined") { + document.getElementById("wiki-md").innerHTML = result.page; + } else if (typeof result.error !== "undefined") { + document.getElementById("wiki-md-error").innerHTML = result.error + } + }); + } + setTimeout(getWikiPage, 1000);'); + + return '
'.JText::_('COM_GETBIBLE_THE_WIKI_IS_LOADING').'..
'; + } + + + public function getNoticeboard() + { + // get the document to load the scripts + $document = JFactory::getDocument(); + $document->addScript(JURI::root() . "media/com_getbible/js/marked.js"); + $document->addScriptDeclaration(' + var token = "'.JSession::getFormToken().'"; + var noticeboard = "https://vdm.bz/getbible-noticeboard-md"; + jQuery(document).ready(function () { + jQuery.get(noticeboard) + .success(function(board) { + if (board.length > 5) { + jQuery("#noticeboard-md").html(marked.parse(board)); + getIS(1,board).done(function(result) { + if (result){ + jQuery("#cpanel_tabTabs a").each(function() { + if (this.href.indexOf("#vast_development_method") >= 0 || this.href.indexOf("#notice_board") >= 0) { + var textVDM = jQuery(this).text(); + jQuery(this).html("1 "+textVDM); + jQuery(this).attr("id","vdm-new-notice"); + jQuery("#vdm-new-notice").click(function() { + getIS(2,board).done(function(result) { + if (result) { + jQuery(".vdm-new-notice").fadeOut(500); + } + }); + }); + } + }); + } + }); + } else { + jQuery("#noticeboard-md").html("'.JText::_('COM_GETBIBLE_ALL_IS_GOOD_PLEASE_CHECK_AGAIN_LATTER').'"); + } + }) + .error(function(jqXHR, textStatus, errorThrown) { + jQuery("#noticeboard-md").html("'.JText::_('COM_GETBIBLE_ALL_IS_GOOD_PLEASE_CHECK_AGAIN_LATTER').'"); + }); + }); + // to check is READ/NEW + function getIS(type,notice){ + if(type == 1){ + var getUrl = "index.php?option=com_getbible&task=ajax.isNew&format=json&raw=true"; + } else if (type == 2) { + var getUrl = "index.php?option=com_getbible&task=ajax.isRead&format=json&raw=true"; + } + if(token.length > 0 && notice.length){ + var request = token+"=1¬ice="+notice; + } + return jQuery.ajax({ + type: "POST", + url: getUrl, + dataType: "json", + data: request, + jsonp: false + }); + } + +// nice little dot trick :) +jQuery(document).ready( function($) { + var x=0; + setInterval(function() { + var dots = ""; + x++; + for (var y=0; y < x%8; y++) { + dots+="."; + } + $(".loading-dots").text(dots); + } , 500); +});'); + + return '
'.JText::_('COM_GETBIBLE_THE_NOTICE_BOARD_IS_LOADING').'..
'; + } + + public function getReadme() + { + $document = JFactory::getDocument(); + $document->addScriptDeclaration(' + var getreadme = "'. JURI::root() . 'administrator/components/com_getbible/README.txt"; + jQuery(document).ready(function () { + jQuery.get(getreadme) + .success(function(readme) { + jQuery("#readme-md").html(marked.parse(readme)); + }) + .error(function(jqXHR, textStatus, errorThrown) { + jQuery("#readme-md").html("'.JText::_('COM_GETBIBLE_PLEASE_CHECK_AGAIN_LATTER').'"); + }); + });'); + + return '
'.JText::_('COM_GETBIBLE_THE_README_IS_LOADING').'..
'; + } + + /** + * get Current Version Bay adding JavaScript to the Page + * + * @return void + * @since 2.3.0 + */ + public function getVersion() + { + // the call URL + $call_url = JUri::base() . 'index.php?option=com_getbible&task=ajax.getVersion&format=json&raw=true&' . JSession::getFormToken() . '=1&version=1'; + $document = JFactory::getDocument(); + $document->addScriptDeclaration(' + function getComponentVersionStatus() { + fetch("' . $call_url . '").then((response) => { + if (response.ok) { + return response.json(); + } + }).then((result) => { + if (typeof result.notice !== "undefined") { + document.getElementById("component-update-notice").innerHTML = result.notice; + } else if (typeof result.error !== "undefined") { + document.getElementById("component-update-notice").innerHTML = result.error; + } + }); + } + setTimeout(getComponentVersionStatus, 800);'); + } + +} diff --git a/admin/models/index.html b/admin/models/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/models/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/models/linker.php b/admin/models/linker.php new file mode 100644 index 0000000..7c018aa --- /dev/null +++ b/admin/models/linker.php @@ -0,0 +1,1280 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\AdminModel; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; +use VDM\Joomla\Utilities\GuidHelper; +use VDM\Joomla\Utilities\GetHelper; + +/** + * Getbible Linker Admin Model + */ +class GetbibleModelLinker extends AdminModel +{ + /** + * The tab layout fields array. + * + * @var array + */ + protected $tabLayoutFields = array( + 'details' => array( + 'left' => array( + 'name' + ) + ) + ); + + /** + * @var string The prefix to use with controller messages. + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE'; + + /** + * The type alias for this content type. + * + * @var string + * @since 3.2 + */ + public $typeAlias = 'com_getbible.linker'; + + /** + * Returns a Table object, always creating it + * + * @param type $type The table type to instantiate + * @param string $prefix A prefix for the table class name. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JTable A database object + * + * @since 1.6 + */ + public function getTable($type = 'linker', $prefix = 'GetbibleTable', $config = array()) + { + // add table path for when model gets used from other component + $this->addTablePath(JPATH_ADMINISTRATOR . '/components/com_getbible/tables'); + // get instance of the table + return JTable::getInstance($type, $prefix, $config); + } + + /** + * Method to get a single record. + * + * @param integer $pk The id of the primary key. + * + * @return mixed Object on success, false on failure. + * + * @since 1.6 + */ + public function getItem($pk = null) + { + if ($item = parent::getItem($pk)) + { + if (!empty($item->params) && !is_array($item->params)) + { + // Convert the params field to an array. + $registry = new Registry; + $registry->loadString($item->params); + $item->params = $registry->toArray(); + } + + if (!empty($item->metadata)) + { + // Convert the metadata field to an array. + $registry = new Registry; + $registry->loadString($item->metadata); + $item->metadata = $registry->toArray(); + } + } + $this->linkervvvv = $item->guid; + $this->linkervvvw = $item->guid; + $this->linkervvvx = $item->guid; + + return $item; + } + + /** + * Method to get list data. + * + * @return mixed An array of data items on success, false on failure. + */ + public function getVvvtags() + { + // Get the user object. + $user = JFactory::getUser(); + // Create a new query object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + + // Select some fields + $query->select('a.*'); + + // From the getbible_tagged_verse table + $query->from($db->quoteName('#__getbible_tagged_verse', 'a')); + + // From the getbible_translation table. + $query->select($db->quoteName(['g.translation','g.id'],['abbreviation_translation','abbreviation_id'])); + $query->join('LEFT', $db->quoteName('#__getbible_translation', 'g') . ' ON (' . $db->quoteName('a.abbreviation') . ' = ' . $db->quoteName('g.abbreviation') . ')'); + + // From the getbible_linker table. + $query->select($db->quoteName(['h.name','h.id'],['linker_name','linker_id'])); + $query->join('LEFT', $db->quoteName('#__getbible_linker', 'h') . ' ON (' . $db->quoteName('a.linker') . ' = ' . $db->quoteName('h.guid') . ')'); + + // From the getbible_tag table. + $query->select($db->quoteName(['i.name','i.id'],['tag_name','tag_id'])); + $query->join('LEFT', $db->quoteName('#__getbible_tag', 'i') . ' ON (' . $db->quoteName('a.tag') . ' = ' . $db->quoteName('i.guid') . ')'); + + // Filter by linkervvvv global. + $linkervvvv = $this->linkervvvv; + if (is_numeric($linkervvvv )) + { + $query->where('a.linker = ' . (int) $linkervvvv ); + } + elseif (is_string($linkervvvv)) + { + $query->where('a.linker = ' . $db->quote($linkervvvv)); + } + else + { + $query->where('a.linker = -5'); + } + + // Join over the asset groups. + $query->select('ag.title AS access_level'); + $query->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access'); + // Implement View Level Access + if (!$user->authorise('core.options', 'com_getbible')) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + + // Order the results by ordering + $query->order('a.published ASC'); + $query->order('a.ordering ASC'); + + // Load the items + $db->setQuery($query); + $db->execute(); + if ($db->getNumRows()) + { + $items = $db->loadObjectList(); + + // Set values to display correctly. + if (GetbibleHelper::checkArray($items)) + { + // Get the user object if not set. + if (!isset($user) || !GetbibleHelper::checkObject($user)) + { + $user = JFactory::getUser(); + } + foreach ($items as $nr => &$item) + { + // Remove items the user can't access. + $access = ($user->authorise('tagged_verse.access', 'com_getbible.tagged_verse.' . (int) $item->id) && $user->authorise('tagged_verse.access', 'com_getbible')); + if (!$access) + { + unset($items[$nr]); + continue; + } + + $item->book_nr = $item->book_nr . ' ' . $item->chapter . ':' . $item->verse; + } + } + + // set selection value to a translatable value + if (GetbibleHelper::checkArray($items)) + { + foreach ($items as $nr => &$item) + { + // convert access + $item->access = $this->selectionTranslationVvvtags($item->access, 'access'); + } + } + + return $items; + } + return false; + } + + /** + * Method to convert selection values to translatable string. + * + * @return translatable string + */ + public function selectionTranslationVvvtags($value,$name) + { + // Array of access language strings + if ($name === 'access') + { + $accessArray = array( + 1 => 'COM_GETBIBLE_TAGGED_VERSE_PUBLIC', + 0 => 'COM_GETBIBLE_TAGGED_VERSE_PRIVATE' + ); + // Now check if value is found in this array + if (isset($accessArray[$value]) && GetbibleHelper::checkString($accessArray[$value])) + { + return $accessArray[$value]; + } + } + return $value; + } + + /** + * Method to get list data. + * + * @return mixed An array of data items on success, false on failure. + */ + public function getVvwnotes() + { + // Get the user object. + $user = JFactory::getUser(); + // Create a new query object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + + // Select some fields + $query->select('a.*'); + + // From the getbible_note table + $query->from($db->quoteName('#__getbible_note', 'a')); + + // From the getbible_linker table. + $query->select($db->quoteName(['g.name','g.id'],['linker_name','linker_id'])); + $query->join('LEFT', $db->quoteName('#__getbible_linker', 'g') . ' ON (' . $db->quoteName('a.linker') . ' = ' . $db->quoteName('g.guid') . ')'); + + // Filter by linkervvvw global. + $linkervvvw = $this->linkervvvw; + if (is_numeric($linkervvvw )) + { + $query->where('a.linker = ' . (int) $linkervvvw ); + } + elseif (is_string($linkervvvw)) + { + $query->where('a.linker = ' . $db->quote($linkervvvw)); + } + else + { + $query->where('a.linker = -5'); + } + + // Join over the asset groups. + $query->select('ag.title AS access_level'); + $query->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access'); + // Implement View Level Access + if (!$user->authorise('core.options', 'com_getbible')) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + + // Order the results by ordering + $query->order('a.published ASC'); + $query->order('a.ordering ASC'); + + // Load the items + $db->setQuery($query); + $db->execute(); + if ($db->getNumRows()) + { + $items = $db->loadObjectList(); + + // Set values to display correctly. + if (GetbibleHelper::checkArray($items)) + { + // Get the user object if not set. + if (!isset($user) || !GetbibleHelper::checkObject($user)) + { + $user = JFactory::getUser(); + } + foreach ($items as $nr => &$item) + { + // Remove items the user can't access. + $access = ($user->authorise('note.access', 'com_getbible.note.' . (int) $item->id) && $user->authorise('note.access', 'com_getbible')); + if (!$access) + { + unset($items[$nr]); + continue; + } + + $item->book_nr = $item->book_nr . ' ' . $item->chapter . ':' . $item->verse; + } + } + + // set selection value to a translatable value + if (GetbibleHelper::checkArray($items)) + { + foreach ($items as $nr => &$item) + { + // convert access + $item->access = $this->selectionTranslationVvwnotes($item->access, 'access'); + } + } + + return $items; + } + return false; + } + + /** + * Method to convert selection values to translatable string. + * + * @return translatable string + */ + public function selectionTranslationVvwnotes($value,$name) + { + // Array of access language strings + if ($name === 'access') + { + $accessArray = array( + 1 => 'COM_GETBIBLE_NOTE_PUBLIC', + 0 => 'COM_GETBIBLE_NOTE_PRIVATE' + ); + // Now check if value is found in this array + if (isset($accessArray[$value]) && GetbibleHelper::checkString($accessArray[$value])) + { + return $accessArray[$value]; + } + } + return $value; + } + + /** + * Method to get list data. + * + * @return mixed An array of data items on success, false on failure. + */ + public function getVvxpasswords() + { + // Get the user object. + $user = JFactory::getUser(); + // Create a new query object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + + // Select some fields + $query->select('a.*'); + + // From the getbible_password table + $query->from($db->quoteName('#__getbible_password', 'a')); + + // From the getbible_linker table. + $query->select($db->quoteName(['g.name','g.id'],['linker_name','linker_id'])); + $query->join('LEFT', $db->quoteName('#__getbible_linker', 'g') . ' ON (' . $db->quoteName('a.linker') . ' = ' . $db->quoteName('g.guid') . ')'); + + // Filter by linkervvvx global. + $linkervvvx = $this->linkervvvx; + if (is_numeric($linkervvvx )) + { + $query->where('a.linker = ' . (int) $linkervvvx ); + } + elseif (is_string($linkervvvx)) + { + $query->where('a.linker = ' . $db->quote($linkervvvx)); + } + else + { + $query->where('a.linker = -5'); + } + + // Join over the asset groups. + $query->select('ag.title AS access_level'); + $query->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access'); + // Filter by access level. + $_access = $this->getState('filter.access'); + if ($_access && is_numeric($_access)) + { + $query->where('a.access = ' . (int) $_access); + } + elseif (GetbibleHelper::checkArray($_access)) + { + // Secure the array for the query + $_access = ArrayHelper::toInteger($_access); + // Filter by the Access Array. + $query->where('a.access IN (' . implode(',', $_access) . ')'); + } + // Implement View Level Access + if (!$user->authorise('core.options', 'com_getbible')) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + + // Order the results by ordering + $query->order('a.published ASC'); + $query->order('a.ordering ASC'); + + // Load the items + $db->setQuery($query); + $db->execute(); + if ($db->getNumRows()) + { + $items = $db->loadObjectList(); + + // Set values to display correctly. + if (GetbibleHelper::checkArray($items)) + { + // Get the user object if not set. + if (!isset($user) || !GetbibleHelper::checkObject($user)) + { + $user = JFactory::getUser(); + } + foreach ($items as $nr => &$item) + { + // Remove items the user can't access. + $access = ($user->authorise('password.access', 'com_getbible.password.' . (int) $item->id) && $user->authorise('password.access', 'com_getbible')); + if (!$access) + { + unset($items[$nr]); + continue; + } + + } + } + return $items; + } + return false; + } + + /** + * Method to get the record form. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * @param array $options Optional array of options for the form creation. + * + * @return mixed A JForm object on success, false on failure + * + * @since 1.6 + */ + public function getForm($data = array(), $loadData = true, $options = array('control' => 'jform')) + { + // set load data option + $options['load_data'] = $loadData; + // check if xpath was set in options + $xpath = false; + if (isset($options['xpath'])) + { + $xpath = $options['xpath']; + unset($options['xpath']); + } + // check if clear form was set in options + $clear = false; + if (isset($options['clear'])) + { + $clear = $options['clear']; + unset($options['clear']); + } + + // Get the form. + $form = $this->loadForm('com_getbible.linker', 'linker', $options, $clear, $xpath); + + if (empty($form)) + { + return false; + } + + $jinput = JFactory::getApplication()->input; + + // The front end calls this model and uses a_id to avoid id clashes so we need to check for that first. + if ($jinput->get('a_id')) + { + $id = $jinput->get('a_id', 0, 'INT'); + } + // The back end uses id so we use that the rest of the time and set it to 0 by default. + else + { + $id = $jinput->get('id', 0, 'INT'); + } + + $user = JFactory::getUser(); + + // Check for existing item. + // Modify the form based on Edit State access controls. + if ($id != 0 && (!$user->authorise('linker.edit.state', 'com_getbible.linker.' . (int) $id)) + || ($id == 0 && !$user->authorise('linker.edit.state', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('ordering', 'disabled', 'true'); + $form->setFieldAttribute('published', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('ordering', 'filter', 'unset'); + $form->setFieldAttribute('published', 'filter', 'unset'); + } + // If this is a new item insure the greated by is set. + if (0 == $id) + { + // Set the created_by to this user + $form->setValue('created_by', null, $user->id); + } + // Modify the form based on Edit Creaded By access controls. + if ($id != 0 && (!$user->authorise('linker.edit.created_by', 'com_getbible.linker.' . (int) $id)) + || ($id == 0 && !$user->authorise('linker.edit.created_by', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created_by', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('created_by', 'readonly', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created_by', 'filter', 'unset'); + } + // Modify the form based on Edit Creaded Date access controls. + if ($id != 0 && (!$user->authorise('linker.edit.created', 'com_getbible.linker.' . (int) $id)) + || ($id == 0 && !$user->authorise('linker.edit.created', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created', 'filter', 'unset'); + } + // Modify the form based on Edit Name access controls. + if ($id != 0 && (!$user->authorise('linker.edit.name', 'com_getbible.linker.' . (int) $id)) + || ($id == 0 && !$user->authorise('linker.edit.name', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('name', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('name', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('name')) + { + // Disable fields while saving. + $form->setFieldAttribute('name', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('name', 'required', 'false'); + } + } + // Modify the form based on Edit Guid access controls. + if ($id != 0 && (!$user->authorise('linker.edit.guid', 'com_getbible.linker.' . (int) $id)) + || ($id == 0 && !$user->authorise('linker.edit.guid', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('guid', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('guid', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('guid')) + { + // Disable fields while saving. + $form->setFieldAttribute('guid', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('guid', 'required', 'false'); + } + } + // Only load these values if no id is found + if (0 == $id) + { + // Set redirected view name + $redirectedView = $jinput->get('ref', null, 'STRING'); + // Set field name (or fall back to view name) + $redirectedField = $jinput->get('field', $redirectedView, 'STRING'); + // Set redirected view id + $redirectedId = $jinput->get('refid', 0, 'INT'); + // Set field id (or fall back to redirected view id) + $redirectedValue = $jinput->get('field_id', $redirectedId, 'INT'); + if (0 != $redirectedValue && $redirectedField) + { + // Now set the local-redirected field default value + $form->setValue($redirectedField, null, $redirectedValue); + } + } + + // Only load the GUID if new item (or empty) + if (0 == $id || !($val = $form->getValue('guid'))) + { + $form->setValue('guid', null, GuidHelper::get()); + } + + return $form; + } + + /** + * Method to get the script that have to be included on the form + * + * @return string script files + */ + public function getScript() + { + return 'media/com_getbible/js/linker.js'; + } + + /** + * Method to test whether a record can be deleted. + * + * @param object $record A record object. + * + * @return boolean True if allowed to delete the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canDelete($record) + { + if (!empty($record->id)) + { + if ($record->published != -2) + { + return; + } + + $user = JFactory::getUser(); + // The record has been set. Check the record permissions. + return $user->authorise('linker.delete', 'com_getbible.linker.' . (int) $record->id); + } + return false; + } + + /** + * Method to test whether a record can have its state edited. + * + * @param object $record A record object. + * + * @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canEditState($record) + { + $user = JFactory::getUser(); + $recordId = (!empty($record->id)) ? $record->id : 0; + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('linker.edit.state', 'com_getbible.linker.' . (int) $recordId); + if (!$permission && !is_null($permission)) + { + return false; + } + } + // In the absense of better information, revert to the component permissions. + return $user->authorise('linker.edit.state', 'com_getbible'); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * @since 2.5 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // Check specific edit permission then general edit permission. + $user = JFactory::getUser(); + + return $user->authorise('linker.edit', 'com_getbible.linker.'. ((int) isset($data[$key]) ? $data[$key] : 0)) or $user->authorise('linker.edit', 'com_getbible'); + } + + /** + * Prepare and sanitise the table data prior to saving. + * + * @param JTable $table A JTable object. + * + * @return void + * + * @since 1.6 + */ + protected function prepareTable($table) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if (isset($table->name)) + { + $table->name = htmlspecialchars_decode($table->name, ENT_QUOTES); + } + + if (isset($table->alias) && empty($table->alias)) + { + $table->generateAlias(); + } + + if (empty($table->id)) + { + $table->created = $date->toSql(); + // set the user + if ($table->created_by == 0 || empty($table->created_by)) + { + $table->created_by = $user->id; + } + // Set ordering to the last item if not set + if (empty($table->ordering)) + { + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select('MAX(ordering)') + ->from($db->quoteName('#__getbible_linker')); + $db->setQuery($query); + $max = $db->loadResult(); + + $table->ordering = $max + 1; + } + } + else + { + $table->modified = $date->toSql(); + $table->modified_by = $user->id; + } + + if (!empty($table->id)) + { + // Increment the items version number. + $table->version++; + } + } + + /** + * Method to get the data that should be injected in the form. + * + * @return mixed The data for the form. + * + * @since 1.6 + */ + protected function loadFormData() + { + // Check the session for previously entered form data. + $data = JFactory::getApplication()->getUserState('com_getbible.edit.linker.data', array()); + + if (empty($data)) + { + $data = $this->getItem(); + // run the perprocess of the data + $this->preprocessData('com_getbible.linker', $data); + } + + return $data; + } + + /** + * Method to get the unique fields of this table. + * + * @return mixed An array of field names, boolean false if none is set. + * + * @since 3.0 + */ + protected function getUniqueFields() + { + return array('guid'); + } + + /** + * Method to delete one or more records. + * + * @param array &$pks An array of record primary keys. + * + * @return boolean True if successful, false if an error occurs. + * + * @since 12.2 + */ + public function delete(&$pks) + { + if (!parent::delete($pks)) + { + return false; + } + + return true; + } + + /** + * Method to change the published state of one or more records. + * + * @param array &$pks A list of the primary keys to change. + * @param integer $value The value of the published state. + * + * @return boolean True on success. + * + * @since 12.2 + */ + public function publish(&$pks, $value = 1) + { + if (!parent::publish($pks, $value)) + { + return false; + } + + return true; + } + + /** + * Method to perform batch operations on an item or a set of items. + * + * @param array $commands An array of commands to perform. + * @param array $pks An array of item ids. + * @param array $contexts An array of item contexts. + * + * @return boolean Returns true on success, false on failure. + * + * @since 12.2 + */ + public function batch($commands, $pks, $contexts) + { + // Sanitize ids. + $pks = array_unique($pks); + ArrayHelper::toInteger($pks); + + // Remove any values of zero. + if (array_search(0, $pks, true)) + { + unset($pks[array_search(0, $pks, true)]); + } + + if (empty($pks)) + { + $this->setError(JText::_('JGLOBAL_NO_ITEM_SELECTED')); + return false; + } + + $done = false; + + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->contentType = new JUcmType; + $this->type = $this->contentType->getTypeByTable($this->tableClassName); + $this->canDo = GetbibleHelper::getActions('linker'); + $this->batchSet = true; + + if (!$this->canDo->get('core.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + return false; + } + + if ($this->type == false) + { + $type = new JUcmType; + $this->type = $type->getTypeByAlias($this->typeAlias); + } + + $this->tagsObserver = $this->table->getObserverOfClass('JTableObserverTags'); + + if (!empty($commands['move_copy'])) + { + $cmd = ArrayHelper::getValue($commands, 'move_copy', 'c'); + + if ($cmd == 'c') + { + $result = $this->batchCopy($commands, $pks, $contexts); + + if (is_array($result)) + { + foreach ($result as $old => $new) + { + $contexts[$new] = $contexts[$old]; + } + $pks = array_values($result); + } + else + { + return false; + } + } + elseif ($cmd == 'm' && !$this->batchMove($commands, $pks, $contexts)) + { + return false; + } + + $done = true; + } + + if (!$done) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + + return false; + } + + // Clear the cache + $this->cleanCache(); + + return true; + } + + /** + * Batch copy items to a new category or current. + * + * @param integer $values The new values. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return mixed An array of new IDs on success, boolean false on failure. + * + * @since 12.2 + */ + protected function batchCopy($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('linker'); + } + + if (!$this->canDo->get('linker.create') && !$this->canDo->get('linker.batch')) + { + return false; + } + + // get list of unique fields + $uniqueFields = $this->getUniqueFields(); + // remove move_copy from array + unset($values['move_copy']); + + // make sure published is set + if (!isset($values['published'])) + { + $values['published'] = 0; + } + elseif (isset($values['published']) && !$this->canDo->get('linker.edit.state')) + { + $values['published'] = 0; + } + + $newIds = array(); + // Parent exists so let's proceed + while (!empty($pks)) + { + // Pop the first ID off the stack + $pk = array_shift($pks); + + $this->table->reset(); + + // only allow copy if user may edit this item. + if (!$this->user->authorise('linker.edit', $contexts[$pk])) + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // Only for strings + if (GetbibleHelper::checkString($this->table->name) && !is_numeric($this->table->name)) + { + $this->table->name = $this->generateUnique('name',$this->table->name); + } + + // insert all set values + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + if (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + // update all unique fields + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $this->table->$uniqueField = $this->generateUnique($uniqueField,$this->table->$uniqueField); + } + } + + // Reset the ID because we are making a copy + $this->table->id = 0; + + // TODO: Deal with ordering? + // $this->table->ordering = 1; + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + + // Get the new item ID + $newId = $this->table->get('id'); + + // Add the new ID to the array + $newIds[$pk] = $newId; + } + + // Clean the cache + $this->cleanCache(); + + return $newIds; + } + + /** + * Batch move items to a new category + * + * @param integer $value The new category ID. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 12.2 + */ + protected function batchMove($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('linker'); + } + + if (!$this->canDo->get('linker.edit') && !$this->canDo->get('linker.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // make sure published only updates if user has the permission. + if (isset($values['published']) && !$this->canDo->get('linker.edit.state')) + { + unset($values['published']); + } + // remove move_copy from array + unset($values['move_copy']); + + // Parent exists so we proceed + foreach ($pks as $pk) + { + if (!$this->user->authorise('linker.edit', $contexts[$pk])) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // insert all set values. + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + // Do special action for access. + if ('access' === $key && strlen($value) > 0) + { + $this->table->$key = $value; + } + elseif (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + } + + // Clean the cache + $this->cleanCache(); + + return true; + } + + /** + * Method to save the form data. + * + * @param array $data The form data. + * + * @return boolean True on success. + * + * @since 1.6 + */ + public function save($data) + { + $input = JFactory::getApplication()->input; + $filter = JFilterInput::getInstance(); + + // set the metadata to the Item Data + if (isset($data['metadata']) && isset($data['metadata']['author'])) + { + $data['metadata']['author'] = $filter->clean($data['metadata']['author'], 'TRIM'); + + $metadata = new JRegistry; + $metadata->loadArray($data['metadata']); + $data['metadata'] = (string) $metadata; + } + + + // Set the GUID if empty or not valid + if (empty($data['guid']) && $data['id'] > 0) + { + // get the existing one + $data['guid'] = (string) GetHelper::var('linker', $data['id'], 'id', 'guid'); + } + + // Set the GUID if empty or not valid + while (!GuidHelper::valid($data['guid'], "linker", $data['id'])) + { + // must always be set + $data['guid'] = (string) GuidHelper::get(); + } + + // Set the Params Items to data + if (isset($data['params']) && is_array($data['params'])) + { + $params = new JRegistry; + $params->loadArray($data['params']); + $data['params'] = (string) $params; + } + + // Alter the unique field for save as copy + if ($input->get('task') === 'save2copy') + { + // Automatic handling of other unique fields + $uniqueFields = $this->getUniqueFields(); + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $data[$uniqueField] = $this->generateUnique($uniqueField,$data[$uniqueField]); + } + } + } + + if (parent::save($data)) + { + return true; + } + return false; + } + + /** + * Method to generate a unique value. + * + * @param string $field name. + * @param string $value data. + * + * @return string New value. + * + * @since 3.0 + */ + protected function generateUnique($field,$value) + { + + // set field value unique + $table = $this->getTable(); + + while ($table->load(array($field => $value))) + { + $value = StringHelper::increment($value); + } + + return $value; + } + + /** + * Method to change the title + * + * @param string $title The title. + * + * @return array Contains the modified title and alias. + * + */ + protected function _generateNewTitle($title) + { + + // Alter the title + $table = $this->getTable(); + + while ($table->load(array('title' => $title))) + { + $title = StringHelper::increment($title); + } + + return $title; + } +} diff --git a/admin/models/linkers.php b/admin/models/linkers.php new file mode 100644 index 0000000..55fa01b --- /dev/null +++ b/admin/models/linkers.php @@ -0,0 +1,324 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\ListModel; +use Joomla\Utilities\ArrayHelper; + +/** + * Linkers List Model + */ +class GetbibleModelLinkers extends ListModel +{ + public function __construct($config = array()) + { + if (empty($config['filter_fields'])) + { + $config['filter_fields'] = array( + 'a.id','id', + 'a.published','published', + 'a.access','access', + 'a.ordering','ordering', + 'a.created_by','created_by', + 'a.modified_by','modified_by', + 'a.name','name' + ); + } + + parent::__construct($config); + } + + /** + * Method to auto-populate the model state. + * + * Note. Calling getState in this method will result in recursion. + * + * @param string $ordering An optional ordering field. + * @param string $direction An optional direction (asc|desc). + * + * @return void + * + */ + protected function populateState($ordering = null, $direction = null) + { + $app = JFactory::getApplication(); + + // Adjust the context to support modal layouts. + if ($layout = $app->input->get('layout')) + { + $this->context .= '.' . $layout; + } + + // Check if the form was submitted + $formSubmited = $app->input->post->get('form_submited'); + + $access = $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', 0, 'int'); + if ($formSubmited) + { + $access = $app->input->post->get('access'); + $this->setState('filter.access', $access); + } + + $published = $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', ''); + $this->setState('filter.published', $published); + + $created_by = $this->getUserStateFromRequest($this->context . '.filter.created_by', 'filter_created_by', ''); + $this->setState('filter.created_by', $created_by); + + $created = $this->getUserStateFromRequest($this->context . '.filter.created', 'filter_created'); + $this->setState('filter.created', $created); + + $sorting = $this->getUserStateFromRequest($this->context . '.filter.sorting', 'filter_sorting', 0, 'int'); + $this->setState('filter.sorting', $sorting); + + $search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search'); + $this->setState('filter.search', $search); + + $name = $this->getUserStateFromRequest($this->context . '.filter.name', 'filter_name'); + if ($formSubmited) + { + $name = $app->input->post->get('name'); + $this->setState('filter.name', $name); + } + + // List state information. + parent::populateState($ordering, $direction); + } + + /** + * Method to get an array of data items. + * + * @return mixed An array of data items on success, false on failure. + */ + public function getItems() + { + // Check in items + $this->checkInNow(); + + // load parent items + $items = parent::getItems(); + + // Set values to display correctly. + if (GetbibleHelper::checkArray($items)) + { + // Get the user object if not set. + if (!isset($user) || !GetbibleHelper::checkObject($user)) + { + $user = JFactory::getUser(); + } + foreach ($items as $nr => &$item) + { + // Remove items the user can't access. + $access = ($user->authorise('linker.access', 'com_getbible.linker.' . (int) $item->id) && $user->authorise('linker.access', 'com_getbible')); + if (!$access) + { + unset($items[$nr]); + continue; + } + + } + } + + // return items + return $items; + } + + /** + * Method to build an SQL query to load the list data. + * + * @return string An SQL query + */ + protected function getListQuery() + { + // Get the user object. + $user = JFactory::getUser(); + // Create a new query object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + + // Select some fields + $query->select('a.*'); + + // From the getbible_item table + $query->from($db->quoteName('#__getbible_linker', 'a')); + + // Filter by published state + $published = $this->getState('filter.published'); + if (is_numeric($published)) + { + $query->where('a.published = ' . (int) $published); + } + elseif ($published === '') + { + $query->where('(a.published = 0 OR a.published = 1)'); + } + + // Join over the asset groups. + $query->select('ag.title AS access_level'); + $query->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access'); + // Filter by access level. + $_access = $this->getState('filter.access'); + if ($_access && is_numeric($_access)) + { + $query->where('a.access = ' . (int) $_access); + } + elseif (GetbibleHelper::checkArray($_access)) + { + // Secure the array for the query + $_access = ArrayHelper::toInteger($_access); + // Filter by the Access Array. + $query->where('a.access IN (' . implode(',', $_access) . ')'); + } + // Implement View Level Access + if (!$user->authorise('core.options', 'com_getbible')) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + // Filter by search. + $search = $this->getState('filter.search'); + if (!empty($search)) + { + if (stripos($search, 'id:') === 0) + { + $query->where('a.id = ' . (int) substr($search, 3)); + } + else + { + $search = $db->quote('%' . $db->escape($search) . '%'); + $query->where('(a.name LIKE '.$search.')'); + } + } + + // Filter by Name. + $_name = $this->getState('filter.name'); + if (is_numeric($_name)) + { + if (is_float($_name)) + { + $query->where('a.name = ' . (float) $_name); + } + else + { + $query->where('a.name = ' . (int) $_name); + } + } + elseif (GetbibleHelper::checkString($_name)) + { + $query->where('a.name = ' . $db->quote($db->escape($_name))); + } + + // Add the list ordering clause. + $orderCol = $this->state->get('list.ordering', 'a.id'); + $orderDirn = $this->state->get('list.direction', 'desc'); + if ($orderCol != '') + { + $query->order($db->escape($orderCol . ' ' . $orderDirn)); + } + + return $query; + } + + /** + * Method to get a store id based on model configuration state. + * + * @return string A store id. + * + */ + protected function getStoreId($id = '') + { + // Compile the store id. + $id .= ':' . $this->getState('filter.id'); + $id .= ':' . $this->getState('filter.search'); + $id .= ':' . $this->getState('filter.published'); + // Check if the value is an array + $_access = $this->getState('filter.access'); + if (GetbibleHelper::checkArray($_access)) + { + $id .= ':' . implode(':', $_access); + } + // Check if this is only an number or string + elseif (is_numeric($_access) + || GetbibleHelper::checkString($_access)) + { + $id .= ':' . $_access; + } + $id .= ':' . $this->getState('filter.ordering'); + $id .= ':' . $this->getState('filter.created_by'); + $id .= ':' . $this->getState('filter.modified_by'); + $id .= ':' . $this->getState('filter.name'); + + return parent::getStoreId($id); + } + + /** + * Build an SQL query to checkin all items left checked out longer then a set time. + * + * @return a bool + * + */ + protected function checkInNow() + { + // Get set check in time + $time = JComponentHelper::getParams('com_getbible')->get('check_in'); + + if ($time) + { + + // Get a db connection. + $db = JFactory::getDbo(); + // Reset query. + $query = $db->getQuery(true); + $query->select('*'); + $query->from($db->quoteName('#__getbible_linker')); + // Only select items that are checked out. + $query->where($db->quoteName('checked_out') . '!=0'); + $db->setQuery($query, 0, 1); + $db->execute(); + if ($db->getNumRows()) + { + // Get Yesterdays date. + $date = JFactory::getDate()->modify($time)->toSql(); + // Reset query. + $query = $db->getQuery(true); + + // Fields to update. + $fields = array( + $db->quoteName('checked_out_time') . '=\'0000-00-00 00:00:00\'', + $db->quoteName('checked_out') . '=0' + ); + + // Conditions for which records should be updated. + $conditions = array( + $db->quoteName('checked_out') . '!=0', + $db->quoteName('checked_out_time') . '<\''.$date.'\'' + ); + + // Check table. + $query->update($db->quoteName('#__getbible_linker'))->set($fields)->where($conditions); + + $db->setQuery($query); + + $db->execute(); + } + } + + return false; + } +} diff --git a/admin/models/note.php b/admin/models/note.php new file mode 100644 index 0000000..3481114 --- /dev/null +++ b/admin/models/note.php @@ -0,0 +1,992 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\AdminModel; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; +use VDM\Joomla\Utilities\GuidHelper; +use VDM\Joomla\Utilities\GetHelper; + +/** + * Getbible Note Admin Model + */ +class GetbibleModelNote extends AdminModel +{ + /** + * The tab layout fields array. + * + * @var array + */ + protected $tabLayoutFields = array( + 'details' => array( + 'left' => array( + 'book_nr', + 'chapter', + 'verse' + ), + 'right' => array( + 'note' + ), + 'above' => array( + 'access', + 'linker' + ) + ) + ); + + /** + * @var string The prefix to use with controller messages. + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE'; + + /** + * The type alias for this content type. + * + * @var string + * @since 3.2 + */ + public $typeAlias = 'com_getbible.note'; + + /** + * Returns a Table object, always creating it + * + * @param type $type The table type to instantiate + * @param string $prefix A prefix for the table class name. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JTable A database object + * + * @since 1.6 + */ + public function getTable($type = 'note', $prefix = 'GetbibleTable', $config = array()) + { + // add table path for when model gets used from other component + $this->addTablePath(JPATH_ADMINISTRATOR . '/components/com_getbible/tables'); + // get instance of the table + return JTable::getInstance($type, $prefix, $config); + } + + /** + * Method to get a single record. + * + * @param integer $pk The id of the primary key. + * + * @return mixed Object on success, false on failure. + * + * @since 1.6 + */ + public function getItem($pk = null) + { + if ($item = parent::getItem($pk)) + { + if (!empty($item->params) && !is_array($item->params)) + { + // Convert the params field to an array. + $registry = new Registry; + $registry->loadString($item->params); + $item->params = $registry->toArray(); + } + + if (!empty($item->metadata)) + { + // Convert the metadata field to an array. + $registry = new Registry; + $registry->loadString($item->metadata); + $item->metadata = $registry->toArray(); + } + } + + return $item; + } + + /** + * Method to get the record form. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * @param array $options Optional array of options for the form creation. + * + * @return mixed A JForm object on success, false on failure + * + * @since 1.6 + */ + public function getForm($data = array(), $loadData = true, $options = array('control' => 'jform')) + { + // set load data option + $options['load_data'] = $loadData; + // check if xpath was set in options + $xpath = false; + if (isset($options['xpath'])) + { + $xpath = $options['xpath']; + unset($options['xpath']); + } + // check if clear form was set in options + $clear = false; + if (isset($options['clear'])) + { + $clear = $options['clear']; + unset($options['clear']); + } + + // Get the form. + $form = $this->loadForm('com_getbible.note', 'note', $options, $clear, $xpath); + + if (empty($form)) + { + return false; + } + + $jinput = JFactory::getApplication()->input; + + // The front end calls this model and uses a_id to avoid id clashes so we need to check for that first. + if ($jinput->get('a_id')) + { + $id = $jinput->get('a_id', 0, 'INT'); + } + // The back end uses id so we use that the rest of the time and set it to 0 by default. + else + { + $id = $jinput->get('id', 0, 'INT'); + } + + $user = JFactory::getUser(); + + // Check for existing item. + // Modify the form based on Edit State access controls. + if ($id != 0 && (!$user->authorise('note.edit.state', 'com_getbible.note.' . (int) $id)) + || ($id == 0 && !$user->authorise('note.edit.state', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('ordering', 'disabled', 'true'); + $form->setFieldAttribute('published', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('ordering', 'filter', 'unset'); + $form->setFieldAttribute('published', 'filter', 'unset'); + } + // If this is a new item insure the greated by is set. + if (0 == $id) + { + // Set the created_by to this user + $form->setValue('created_by', null, $user->id); + } + // Modify the form based on Edit Creaded By access controls. + if ($id != 0 && (!$user->authorise('note.edit.created_by', 'com_getbible.note.' . (int) $id)) + || ($id == 0 && !$user->authorise('note.edit.created_by', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created_by', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('created_by', 'readonly', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created_by', 'filter', 'unset'); + } + // Modify the form based on Edit Creaded Date access controls. + if ($id != 0 && (!$user->authorise('note.edit.created', 'com_getbible.note.' . (int) $id)) + || ($id == 0 && !$user->authorise('note.edit.created', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created', 'filter', 'unset'); + } + // Modify the form based on Edit Access 'access' controls. + if ($id != 0 && (!$user->authorise('note.edit.access', 'com_getbible.note.' . (int) $id)) + || ($id == 0 && !$user->authorise('note.edit.access', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('access', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('access', 'filter', 'unset'); + } + // Modify the form based on Edit Book Nr access controls. + if ($id != 0 && (!$user->authorise('note.edit.book_nr', 'com_getbible.note.' . (int) $id)) + || ($id == 0 && !$user->authorise('note.edit.book_nr', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('book_nr', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('book_nr', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('book_nr')) + { + // Disable fields while saving. + $form->setFieldAttribute('book_nr', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('book_nr', 'required', 'false'); + } + } + // Modify the form based on Edit Linker access controls. + if ($id != 0 && (!$user->authorise('note.edit.linker', 'com_getbible.note.' . (int) $id)) + || ($id == 0 && !$user->authorise('note.edit.linker', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('linker', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('linker', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('linker')) + { + // Disable fields while saving. + $form->setFieldAttribute('linker', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('linker', 'required', 'false'); + } + } + // Modify the form based on Edit Guid access controls. + if ($id != 0 && (!$user->authorise('note.edit.guid', 'com_getbible.note.' . (int) $id)) + || ($id == 0 && !$user->authorise('note.edit.guid', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('guid', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('guid', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('guid')) + { + // Disable fields while saving. + $form->setFieldAttribute('guid', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('guid', 'required', 'false'); + } + } + // Modify the form based on Edit Note access controls. + if ($id != 0 && (!$user->authorise('note.edit.note', 'com_getbible.note.' . (int) $id)) + || ($id == 0 && !$user->authorise('note.edit.note', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('note', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('note', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('note')) + { + // Disable fields while saving. + $form->setFieldAttribute('note', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('note', 'required', 'false'); + } + } + // Modify the form based on Edit Verse access controls. + if ($id != 0 && (!$user->authorise('note.edit.verse', 'com_getbible.note.' . (int) $id)) + || ($id == 0 && !$user->authorise('note.edit.verse', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('verse', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('verse', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('verse')) + { + // Disable fields while saving. + $form->setFieldAttribute('verse', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('verse', 'required', 'false'); + } + } + // Modify the form based on Edit Chapter access controls. + if ($id != 0 && (!$user->authorise('note.edit.chapter', 'com_getbible.note.' . (int) $id)) + || ($id == 0 && !$user->authorise('note.edit.chapter', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('chapter', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('chapter', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('chapter')) + { + // Disable fields while saving. + $form->setFieldAttribute('chapter', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('chapter', 'required', 'false'); + } + } + // Only load these values if no id is found + if (0 == $id) + { + // Set redirected view name + $redirectedView = $jinput->get('ref', null, 'STRING'); + // Set field name (or fall back to view name) + $redirectedField = $jinput->get('field', $redirectedView, 'STRING'); + // Set redirected view id + $redirectedId = $jinput->get('refid', 0, 'INT'); + // Set field id (or fall back to redirected view id) + $redirectedValue = $jinput->get('field_id', $redirectedId, 'INT'); + if (0 != $redirectedValue && $redirectedField) + { + // Now set the local-redirected field default value + $form->setValue($redirectedField, null, $redirectedValue); + } + } + + // Only load the GUID if new item (or empty) + if (0 == $id || !($val = $form->getValue('guid'))) + { + $form->setValue('guid', null, GuidHelper::get()); + } + + return $form; + } + + /** + * Method to get the script that have to be included on the form + * + * @return string script files + */ + public function getScript() + { + return 'media/com_getbible/js/note.js'; + } + + /** + * Method to test whether a record can be deleted. + * + * @param object $record A record object. + * + * @return boolean True if allowed to delete the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canDelete($record) + { + if (!empty($record->id)) + { + if ($record->published != -2) + { + return; + } + + $user = JFactory::getUser(); + // The record has been set. Check the record permissions. + return $user->authorise('note.delete', 'com_getbible.note.' . (int) $record->id); + } + return false; + } + + /** + * Method to test whether a record can have its state edited. + * + * @param object $record A record object. + * + * @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canEditState($record) + { + $user = JFactory::getUser(); + $recordId = (!empty($record->id)) ? $record->id : 0; + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('note.edit.state', 'com_getbible.note.' . (int) $recordId); + if (!$permission && !is_null($permission)) + { + return false; + } + } + // In the absense of better information, revert to the component permissions. + return $user->authorise('note.edit.state', 'com_getbible'); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * @since 2.5 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // Check specific edit permission then general edit permission. + $user = JFactory::getUser(); + + return $user->authorise('note.edit', 'com_getbible.note.'. ((int) isset($data[$key]) ? $data[$key] : 0)) or $user->authorise('note.edit', 'com_getbible'); + } + + /** + * Prepare and sanitise the table data prior to saving. + * + * @param JTable $table A JTable object. + * + * @return void + * + * @since 1.6 + */ + protected function prepareTable($table) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if (isset($table->name)) + { + $table->name = htmlspecialchars_decode($table->name, ENT_QUOTES); + } + + if (isset($table->alias) && empty($table->alias)) + { + $table->generateAlias(); + } + + if (empty($table->id)) + { + $table->created = $date->toSql(); + // set the user + if ($table->created_by == 0 || empty($table->created_by)) + { + $table->created_by = $user->id; + } + // Set ordering to the last item if not set + if (empty($table->ordering)) + { + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select('MAX(ordering)') + ->from($db->quoteName('#__getbible_note')); + $db->setQuery($query); + $max = $db->loadResult(); + + $table->ordering = $max + 1; + } + } + else + { + $table->modified = $date->toSql(); + $table->modified_by = $user->id; + } + + if (!empty($table->id)) + { + // Increment the items version number. + $table->version++; + } + } + + /** + * Method to get the data that should be injected in the form. + * + * @return mixed The data for the form. + * + * @since 1.6 + */ + protected function loadFormData() + { + // Check the session for previously entered form data. + $data = JFactory::getApplication()->getUserState('com_getbible.edit.note.data', array()); + + if (empty($data)) + { + $data = $this->getItem(); + // run the perprocess of the data + $this->preprocessData('com_getbible.note', $data); + } + + return $data; + } + + /** + * Method to get the unique fields of this table. + * + * @return mixed An array of field names, boolean false if none is set. + * + * @since 3.0 + */ + protected function getUniqueFields() + { + return array('guid'); + } + + /** + * Method to delete one or more records. + * + * @param array &$pks An array of record primary keys. + * + * @return boolean True if successful, false if an error occurs. + * + * @since 12.2 + */ + public function delete(&$pks) + { + if (!parent::delete($pks)) + { + return false; + } + + return true; + } + + /** + * Method to change the published state of one or more records. + * + * @param array &$pks A list of the primary keys to change. + * @param integer $value The value of the published state. + * + * @return boolean True on success. + * + * @since 12.2 + */ + public function publish(&$pks, $value = 1) + { + if (!parent::publish($pks, $value)) + { + return false; + } + + return true; + } + + /** + * Method to perform batch operations on an item or a set of items. + * + * @param array $commands An array of commands to perform. + * @param array $pks An array of item ids. + * @param array $contexts An array of item contexts. + * + * @return boolean Returns true on success, false on failure. + * + * @since 12.2 + */ + public function batch($commands, $pks, $contexts) + { + // Sanitize ids. + $pks = array_unique($pks); + ArrayHelper::toInteger($pks); + + // Remove any values of zero. + if (array_search(0, $pks, true)) + { + unset($pks[array_search(0, $pks, true)]); + } + + if (empty($pks)) + { + $this->setError(JText::_('JGLOBAL_NO_ITEM_SELECTED')); + return false; + } + + $done = false; + + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->contentType = new JUcmType; + $this->type = $this->contentType->getTypeByTable($this->tableClassName); + $this->canDo = GetbibleHelper::getActions('note'); + $this->batchSet = true; + + if (!$this->canDo->get('core.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + return false; + } + + if ($this->type == false) + { + $type = new JUcmType; + $this->type = $type->getTypeByAlias($this->typeAlias); + } + + $this->tagsObserver = $this->table->getObserverOfClass('JTableObserverTags'); + + if (!empty($commands['move_copy'])) + { + $cmd = ArrayHelper::getValue($commands, 'move_copy', 'c'); + + if ($cmd == 'c') + { + $result = $this->batchCopy($commands, $pks, $contexts); + + if (is_array($result)) + { + foreach ($result as $old => $new) + { + $contexts[$new] = $contexts[$old]; + } + $pks = array_values($result); + } + else + { + return false; + } + } + elseif ($cmd == 'm' && !$this->batchMove($commands, $pks, $contexts)) + { + return false; + } + + $done = true; + } + + if (!$done) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + + return false; + } + + // Clear the cache + $this->cleanCache(); + + return true; + } + + /** + * Batch copy items to a new category or current. + * + * @param integer $values The new values. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return mixed An array of new IDs on success, boolean false on failure. + * + * @since 12.2 + */ + protected function batchCopy($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('note'); + } + + if (!$this->canDo->get('note.create') && !$this->canDo->get('note.batch')) + { + return false; + } + + // get list of unique fields + $uniqueFields = $this->getUniqueFields(); + // remove move_copy from array + unset($values['move_copy']); + + // make sure published is set + if (!isset($values['published'])) + { + $values['published'] = 0; + } + elseif (isset($values['published']) && !$this->canDo->get('note.edit.state')) + { + $values['published'] = 0; + } + + $newIds = array(); + // Parent exists so let's proceed + while (!empty($pks)) + { + // Pop the first ID off the stack + $pk = array_shift($pks); + + $this->table->reset(); + + // only allow copy if user may edit this item. + if (!$this->user->authorise('note.edit', $contexts[$pk])) + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // insert all set values + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + if (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + // update all unique fields + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $this->table->$uniqueField = $this->generateUnique($uniqueField,$this->table->$uniqueField); + } + } + + // Reset the ID because we are making a copy + $this->table->id = 0; + + // TODO: Deal with ordering? + // $this->table->ordering = 1; + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + + // Get the new item ID + $newId = $this->table->get('id'); + + // Add the new ID to the array + $newIds[$pk] = $newId; + } + + // Clean the cache + $this->cleanCache(); + + return $newIds; + } + + /** + * Batch move items to a new category + * + * @param integer $value The new category ID. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 12.2 + */ + protected function batchMove($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('note'); + } + + if (!$this->canDo->get('note.edit') && !$this->canDo->get('note.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // make sure published only updates if user has the permission. + if (isset($values['published']) && !$this->canDo->get('note.edit.state')) + { + unset($values['published']); + } + // remove move_copy from array + unset($values['move_copy']); + + // Parent exists so we proceed + foreach ($pks as $pk) + { + if (!$this->user->authorise('note.edit', $contexts[$pk])) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // insert all set values. + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + // Do special action for access. + if ('access' === $key && strlen($value) > 0) + { + $this->table->$key = $value; + } + elseif (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + } + + // Clean the cache + $this->cleanCache(); + + return true; + } + + /** + * Method to save the form data. + * + * @param array $data The form data. + * + * @return boolean True on success. + * + * @since 1.6 + */ + public function save($data) + { + $input = JFactory::getApplication()->input; + $filter = JFilterInput::getInstance(); + + // set the metadata to the Item Data + if (isset($data['metadata']) && isset($data['metadata']['author'])) + { + $data['metadata']['author'] = $filter->clean($data['metadata']['author'], 'TRIM'); + + $metadata = new JRegistry; + $metadata->loadArray($data['metadata']); + $data['metadata'] = (string) $metadata; + } + + + // Set the GUID if empty or not valid + if (empty($data['guid']) && $data['id'] > 0) + { + // get the existing one + $data['guid'] = (string) GetHelper::var('note', $data['id'], 'id', 'guid'); + } + + // Set the GUID if empty or not valid + while (!GuidHelper::valid($data['guid'], "note", $data['id'])) + { + // must always be set + $data['guid'] = (string) GuidHelper::get(); + } + + // Set the Params Items to data + if (isset($data['params']) && is_array($data['params'])) + { + $params = new JRegistry; + $params->loadArray($data['params']); + $data['params'] = (string) $params; + } + + // Alter the unique field for save as copy + if ($input->get('task') === 'save2copy') + { + // Automatic handling of other unique fields + $uniqueFields = $this->getUniqueFields(); + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $data[$uniqueField] = $this->generateUnique($uniqueField,$data[$uniqueField]); + } + } + } + + if (parent::save($data)) + { + return true; + } + return false; + } + + /** + * Method to generate a unique value. + * + * @param string $field name. + * @param string $value data. + * + * @return string New value. + * + * @since 3.0 + */ + protected function generateUnique($field,$value) + { + + // set field value unique + $table = $this->getTable(); + + while ($table->load(array($field => $value))) + { + $value = StringHelper::increment($value); + } + + return $value; + } +} diff --git a/admin/models/notes.php b/admin/models/notes.php new file mode 100644 index 0000000..f41fa53 --- /dev/null +++ b/admin/models/notes.php @@ -0,0 +1,433 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\ListModel; +use Joomla\Utilities\ArrayHelper; + +/** + * Notes List Model + */ +class GetbibleModelNotes extends ListModel +{ + public function __construct($config = array()) + { + if (empty($config['filter_fields'])) + { + $config['filter_fields'] = array( + 'a.id','id', + 'a.published','published', + 'a.access','access', + 'a.ordering','ordering', + 'a.created_by','created_by', + 'a.modified_by','modified_by', + 'a.book_nr','book_nr', + 'g.name','linker', + 'a.verse','verse', + 'a.chapter','chapter' + ); + } + + parent::__construct($config); + } + + /** + * Method to auto-populate the model state. + * + * Note. Calling getState in this method will result in recursion. + * + * @param string $ordering An optional ordering field. + * @param string $direction An optional direction (asc|desc). + * + * @return void + * + */ + protected function populateState($ordering = null, $direction = null) + { + $app = JFactory::getApplication(); + + // Adjust the context to support modal layouts. + if ($layout = $app->input->get('layout')) + { + $this->context .= '.' . $layout; + } + + // Check if the form was submitted + $formSubmited = $app->input->post->get('form_submited'); + + $published = $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', ''); + $this->setState('filter.published', $published); + + $created_by = $this->getUserStateFromRequest($this->context . '.filter.created_by', 'filter_created_by', ''); + $this->setState('filter.created_by', $created_by); + + $created = $this->getUserStateFromRequest($this->context . '.filter.created', 'filter_created'); + $this->setState('filter.created', $created); + + $sorting = $this->getUserStateFromRequest($this->context . '.filter.sorting', 'filter_sorting', 0, 'int'); + $this->setState('filter.sorting', $sorting); + + $search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search'); + $this->setState('filter.search', $search); + + $book_nr = $this->getUserStateFromRequest($this->context . '.filter.book_nr', 'filter_book_nr'); + if ($formSubmited) + { + $book_nr = $app->input->post->get('book_nr'); + $this->setState('filter.book_nr', $book_nr); + } + + $linker = $this->getUserStateFromRequest($this->context . '.filter.linker', 'filter_linker'); + if ($formSubmited) + { + $linker = $app->input->post->get('linker'); + $this->setState('filter.linker', $linker); + } + + $access = $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access'); + if ($formSubmited) + { + $access = $app->input->post->get('access'); + $this->setState('filter.access', $access); + } + + $verse = $this->getUserStateFromRequest($this->context . '.filter.verse', 'filter_verse'); + if ($formSubmited) + { + $verse = $app->input->post->get('verse'); + $this->setState('filter.verse', $verse); + } + + $chapter = $this->getUserStateFromRequest($this->context . '.filter.chapter', 'filter_chapter'); + if ($formSubmited) + { + $chapter = $app->input->post->get('chapter'); + $this->setState('filter.chapter', $chapter); + } + + // List state information. + parent::populateState($ordering, $direction); + } + + /** + * Method to get an array of data items. + * + * @return mixed An array of data items on success, false on failure. + */ + public function getItems() + { + // Check in items + $this->checkInNow(); + + // load parent items + $items = parent::getItems(); + + // Set values to display correctly. + if (GetbibleHelper::checkArray($items)) + { + // Get the user object if not set. + if (!isset($user) || !GetbibleHelper::checkObject($user)) + { + $user = JFactory::getUser(); + } + foreach ($items as $nr => &$item) + { + // Remove items the user can't access. + $access = ($user->authorise('note.access', 'com_getbible.note.' . (int) $item->id) && $user->authorise('note.access', 'com_getbible')); + if (!$access) + { + unset($items[$nr]); + continue; + } + + $item->book_nr = $item->book_nr . ' ' . $item->chapter . ':' . $item->verse; + } + } + + // set selection value to a translatable value + if (GetbibleHelper::checkArray($items)) + { + foreach ($items as $nr => &$item) + { + // convert access + $item->access = $this->selectionTranslation($item->access, 'access'); + } + } + + + // return items + return $items; + } + + /** + * Method to convert selection values to translatable string. + * + * @return translatable string + */ + public function selectionTranslation($value,$name) + { + // Array of access language strings + if ($name === 'access') + { + $accessArray = array( + 1 => 'COM_GETBIBLE_NOTE_PUBLIC', + 0 => 'COM_GETBIBLE_NOTE_PRIVATE' + ); + // Now check if value is found in this array + if (isset($accessArray[$value]) && GetbibleHelper::checkString($accessArray[$value])) + { + return $accessArray[$value]; + } + } + return $value; + } + + /** + * Method to build an SQL query to load the list data. + * + * @return string An SQL query + */ + protected function getListQuery() + { + // Get the user object. + $user = JFactory::getUser(); + // Create a new query object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + + // Select some fields + $query->select('a.*'); + + // From the getbible_item table + $query->from($db->quoteName('#__getbible_note', 'a')); + + // From the getbible_linker table. + $query->select($db->quoteName(['g.name','g.id'],['linker_name','linker_id'])); + $query->join('LEFT', $db->quoteName('#__getbible_linker', 'g') . ' ON (' . $db->quoteName('a.linker') . ' = ' . $db->quoteName('g.guid') . ')'); + + // Filter by published state + $published = $this->getState('filter.published'); + if (is_numeric($published)) + { + $query->where('a.published = ' . (int) $published); + } + elseif ($published === '') + { + $query->where('(a.published = 0 OR a.published = 1)'); + } + + // Join over the asset groups. + $query->select('ag.title AS access_level'); + $query->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access'); + // Implement View Level Access + if (!$user->authorise('core.options', 'com_getbible')) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + // Filter by search. + $search = $this->getState('filter.search'); + if (!empty($search)) + { + if (stripos($search, 'id:') === 0) + { + $query->where('a.id = ' . (int) substr($search, 3)); + } + else + { + $search = $db->quote('%' . $db->escape($search) . '%'); + $query->where('(a.book_nr LIKE '.$search.' OR a.linker LIKE '.$search.' OR g.name LIKE '.$search.' OR a.note LIKE '.$search.')'); + } + } + + // Filter by Book_nr. + $_book_nr = $this->getState('filter.book_nr'); + if (is_numeric($_book_nr)) + { + if (is_float($_book_nr)) + { + $query->where('a.book_nr = ' . (float) $_book_nr); + } + else + { + $query->where('a.book_nr = ' . (int) $_book_nr); + } + } + elseif (GetbibleHelper::checkString($_book_nr)) + { + $query->where('a.book_nr = ' . $db->quote($db->escape($_book_nr))); + } + // Filter by Linker. + $_linker = $this->getState('filter.linker'); + if (is_numeric($_linker)) + { + if (is_float($_linker)) + { + $query->where('a.linker = ' . (float) $_linker); + } + else + { + $query->where('a.linker = ' . (int) $_linker); + } + } + elseif (GetbibleHelper::checkString($_linker)) + { + $query->where('a.linker = ' . $db->quote($db->escape($_linker))); + } + // Filter by Access. + $_access = $this->getState('filter.access'); + if (is_numeric($_access)) + { + if (is_float($_access)) + { + $query->where('a.access = ' . (float) $_access); + } + else + { + $query->where('a.access = ' . (int) $_access); + } + } + elseif (GetbibleHelper::checkString($_access)) + { + $query->where('a.access = ' . $db->quote($db->escape($_access))); + } + // Filter by Verse. + $_verse = $this->getState('filter.verse'); + if (is_numeric($_verse)) + { + if (is_float($_verse)) + { + $query->where('a.verse = ' . (float) $_verse); + } + else + { + $query->where('a.verse = ' . (int) $_verse); + } + } + elseif (GetbibleHelper::checkString($_verse)) + { + $query->where('a.verse = ' . $db->quote($db->escape($_verse))); + } + // Filter by Chapter. + $_chapter = $this->getState('filter.chapter'); + if (is_numeric($_chapter)) + { + if (is_float($_chapter)) + { + $query->where('a.chapter = ' . (float) $_chapter); + } + else + { + $query->where('a.chapter = ' . (int) $_chapter); + } + } + elseif (GetbibleHelper::checkString($_chapter)) + { + $query->where('a.chapter = ' . $db->quote($db->escape($_chapter))); + } + + // Add the list ordering clause. + $orderCol = $this->state->get('list.ordering', 'a.id'); + $orderDirn = $this->state->get('list.direction', 'desc'); + if ($orderCol != '') + { + $query->order($db->escape($orderCol . ' ' . $orderDirn)); + } + + return $query; + } + + /** + * Method to get a store id based on model configuration state. + * + * @return string A store id. + * + */ + protected function getStoreId($id = '') + { + // Compile the store id. + $id .= ':' . $this->getState('filter.id'); + $id .= ':' . $this->getState('filter.search'); + $id .= ':' . $this->getState('filter.published'); + $id .= ':' . $this->getState('filter.ordering'); + $id .= ':' . $this->getState('filter.created_by'); + $id .= ':' . $this->getState('filter.modified_by'); + $id .= ':' . $this->getState('filter.book_nr'); + $id .= ':' . $this->getState('filter.linker'); + $id .= ':' . $this->getState('filter.verse'); + $id .= ':' . $this->getState('filter.chapter'); + + return parent::getStoreId($id); + } + + /** + * Build an SQL query to checkin all items left checked out longer then a set time. + * + * @return a bool + * + */ + protected function checkInNow() + { + // Get set check in time + $time = JComponentHelper::getParams('com_getbible')->get('check_in'); + + if ($time) + { + + // Get a db connection. + $db = JFactory::getDbo(); + // Reset query. + $query = $db->getQuery(true); + $query->select('*'); + $query->from($db->quoteName('#__getbible_note')); + // Only select items that are checked out. + $query->where($db->quoteName('checked_out') . '!=0'); + $db->setQuery($query, 0, 1); + $db->execute(); + if ($db->getNumRows()) + { + // Get Yesterdays date. + $date = JFactory::getDate()->modify($time)->toSql(); + // Reset query. + $query = $db->getQuery(true); + + // Fields to update. + $fields = array( + $db->quoteName('checked_out_time') . '=\'0000-00-00 00:00:00\'', + $db->quoteName('checked_out') . '=0' + ); + + // Conditions for which records should be updated. + $conditions = array( + $db->quoteName('checked_out') . '!=0', + $db->quoteName('checked_out_time') . '<\''.$date.'\'' + ); + + // Check table. + $query->update($db->quoteName('#__getbible_note'))->set($fields)->where($conditions); + + $db->setQuery($query); + + $db->execute(); + } + } + + return false; + } +} diff --git a/admin/models/open_ai_message.php b/admin/models/open_ai_message.php new file mode 100644 index 0000000..a9a8321 --- /dev/null +++ b/admin/models/open_ai_message.php @@ -0,0 +1,1010 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\AdminModel; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; + +/** + * Getbible Open_ai_message Admin Model + */ +class GetbibleModelOpen_ai_message extends AdminModel +{ + /** + * The tab layout fields array. + * + * @var array + */ + protected $tabLayoutFields = array( + 'message' => array( + 'left' => array( + 'source', + 'index' + ), + 'right' => array( + 'name' + ), + 'fullwidth' => array( + 'content' + ), + 'above' => array( + 'role', + 'open_ai_response', + 'prompt' + ) + ) + ); + + /** + * @var string The prefix to use with controller messages. + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE'; + + /** + * The type alias for this content type. + * + * @var string + * @since 3.2 + */ + public $typeAlias = 'com_getbible.open_ai_message'; + + /** + * Returns a Table object, always creating it + * + * @param type $type The table type to instantiate + * @param string $prefix A prefix for the table class name. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JTable A database object + * + * @since 1.6 + */ + public function getTable($type = 'open_ai_message', $prefix = 'GetbibleTable', $config = array()) + { + // add table path for when model gets used from other component + $this->addTablePath(JPATH_ADMINISTRATOR . '/components/com_getbible/tables'); + // get instance of the table + return JTable::getInstance($type, $prefix, $config); + } + + /** + * Method to get a single record. + * + * @param integer $pk The id of the primary key. + * + * @return mixed Object on success, false on failure. + * + * @since 1.6 + */ + public function getItem($pk = null) + { + if ($item = parent::getItem($pk)) + { + if (!empty($item->params) && !is_array($item->params)) + { + // Convert the params field to an array. + $registry = new Registry; + $registry->loadString($item->params); + $item->params = $registry->toArray(); + } + + if (!empty($item->metadata)) + { + // Convert the metadata field to an array. + $registry = new Registry; + $registry->loadString($item->metadata); + $item->metadata = $registry->toArray(); + } + } + + return $item; + } + + /** + * Method to get the record form. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * @param array $options Optional array of options for the form creation. + * + * @return mixed A JForm object on success, false on failure + * + * @since 1.6 + */ + public function getForm($data = array(), $loadData = true, $options = array('control' => 'jform')) + { + // set load data option + $options['load_data'] = $loadData; + // check if xpath was set in options + $xpath = false; + if (isset($options['xpath'])) + { + $xpath = $options['xpath']; + unset($options['xpath']); + } + // check if clear form was set in options + $clear = false; + if (isset($options['clear'])) + { + $clear = $options['clear']; + unset($options['clear']); + } + + // Get the form. + $form = $this->loadForm('com_getbible.open_ai_message', 'open_ai_message', $options, $clear, $xpath); + + if (empty($form)) + { + return false; + } + + $jinput = JFactory::getApplication()->input; + + // The front end calls this model and uses a_id to avoid id clashes so we need to check for that first. + if ($jinput->get('a_id')) + { + $id = $jinput->get('a_id', 0, 'INT'); + } + // The back end uses id so we use that the rest of the time and set it to 0 by default. + else + { + $id = $jinput->get('id', 0, 'INT'); + } + + $user = JFactory::getUser(); + + // Check for existing item. + // Modify the form based on Edit State access controls. + if ($id != 0 && (!$user->authorise('open_ai_message.edit.state', 'com_getbible.open_ai_message.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_message.edit.state', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('ordering', 'disabled', 'true'); + $form->setFieldAttribute('published', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('ordering', 'filter', 'unset'); + $form->setFieldAttribute('published', 'filter', 'unset'); + } + // If this is a new item insure the greated by is set. + if (0 == $id) + { + // Set the created_by to this user + $form->setValue('created_by', null, $user->id); + } + // Modify the form based on Edit Creaded By access controls. + if ($id != 0 && (!$user->authorise('open_ai_message.edit.created_by', 'com_getbible.open_ai_message.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_message.edit.created_by', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created_by', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('created_by', 'readonly', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created_by', 'filter', 'unset'); + } + // Modify the form based on Edit Creaded Date access controls. + if ($id != 0 && (!$user->authorise('open_ai_message.edit.created', 'com_getbible.open_ai_message.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_message.edit.created', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created', 'filter', 'unset'); + } + // Modify the form based on Edit Role access controls. + if ($id != 0 && (!$user->authorise('open_ai_message.edit.role', 'com_getbible.open_ai_message.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_message.edit.role', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('role', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('role', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('role')) + { + // Disable fields while saving. + $form->setFieldAttribute('role', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('role', 'required', 'false'); + } + } + // Modify the form based on Edit Open Ai Response access controls. + if ($id != 0 && (!$user->authorise('open_ai_message.edit.open_ai_response', 'com_getbible.open_ai_message.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_message.edit.open_ai_response', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('open_ai_response', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('open_ai_response', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('open_ai_response')) + { + // Disable fields while saving. + $form->setFieldAttribute('open_ai_response', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('open_ai_response', 'required', 'false'); + } + } + // Modify the form based on Edit Prompt access controls. + if ($id != 0 && (!$user->authorise('open_ai_message.edit.prompt', 'com_getbible.open_ai_message.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_message.edit.prompt', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('prompt', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('prompt', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('prompt')) + { + // Disable fields while saving. + $form->setFieldAttribute('prompt', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('prompt', 'required', 'false'); + } + } + // Modify the form based on Edit Source access controls. + if ($id != 0 && (!$user->authorise('open_ai_message.edit.source', 'com_getbible.open_ai_message.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_message.edit.source', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('source', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('source', 'readonly', 'true'); + // Disable radio button for display. + $class = $form->getFieldAttribute('source', 'class', ''); + $form->setFieldAttribute('source', 'class', $class.' disabled no-click'); + // If there is no value continue. + if (!$form->getValue('source')) + { + // Disable fields while saving. + $form->setFieldAttribute('source', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('source', 'required', 'false'); + } + } + // Modify the form based on Edit Content access controls. + if ($id != 0 && (!$user->authorise('open_ai_message.edit.content', 'com_getbible.open_ai_message.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_message.edit.content', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('content', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('content', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('content')) + { + // Disable fields while saving. + $form->setFieldAttribute('content', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('content', 'required', 'false'); + } + } + // Modify the form based on Edit Name access controls. + if ($id != 0 && (!$user->authorise('open_ai_message.edit.name', 'com_getbible.open_ai_message.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_message.edit.name', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('name', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('name', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('name')) + { + // Disable fields while saving. + $form->setFieldAttribute('name', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('name', 'required', 'false'); + } + } + // Modify the form based on Edit Index access controls. + if ($id != 0 && (!$user->authorise('open_ai_message.edit.index', 'com_getbible.open_ai_message.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_message.edit.index', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('index', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('index', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('index')) + { + // Disable fields while saving. + $form->setFieldAttribute('index', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('index', 'required', 'false'); + } + } + // Only load these values if no id is found + if (0 == $id) + { + // Set redirected view name + $redirectedView = $jinput->get('ref', null, 'STRING'); + // Set field name (or fall back to view name) + $redirectedField = $jinput->get('field', $redirectedView, 'STRING'); + // Set redirected view id + $redirectedId = $jinput->get('refid', 0, 'INT'); + // Set field id (or fall back to redirected view id) + $redirectedValue = $jinput->get('field_id', $redirectedId, 'INT'); + if (0 != $redirectedValue && $redirectedField) + { + // Now set the local-redirected field default value + $form->setValue($redirectedField, null, $redirectedValue); + } + } + return $form; + } + + /** + * Method to get the script that have to be included on the form + * + * @return string script files + */ + public function getScript() + { + return 'media/com_getbible/js/open_ai_message.js'; + } + + /** + * Method to test whether a record can be deleted. + * + * @param object $record A record object. + * + * @return boolean True if allowed to delete the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canDelete($record) + { + if (!empty($record->id)) + { + if ($record->published != -2) + { + return; + } + + $user = JFactory::getUser(); + // The record has been set. Check the record permissions. + return $user->authorise('open_ai_message.delete', 'com_getbible.open_ai_message.' . (int) $record->id); + } + return false; + } + + /** + * Method to test whether a record can have its state edited. + * + * @param object $record A record object. + * + * @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canEditState($record) + { + $user = JFactory::getUser(); + $recordId = (!empty($record->id)) ? $record->id : 0; + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('open_ai_message.edit.state', 'com_getbible.open_ai_message.' . (int) $recordId); + if (!$permission && !is_null($permission)) + { + return false; + } + } + // In the absense of better information, revert to the component permissions. + return $user->authorise('open_ai_message.edit.state', 'com_getbible'); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * @since 2.5 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // Check specific edit permission then general edit permission. + $user = JFactory::getUser(); + + return $user->authorise('open_ai_message.edit', 'com_getbible.open_ai_message.'. ((int) isset($data[$key]) ? $data[$key] : 0)) or $user->authorise('open_ai_message.edit', 'com_getbible'); + } + + /** + * Prepare and sanitise the table data prior to saving. + * + * @param JTable $table A JTable object. + * + * @return void + * + * @since 1.6 + */ + protected function prepareTable($table) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if (isset($table->name)) + { + $table->name = htmlspecialchars_decode($table->name, ENT_QUOTES); + } + + if (isset($table->alias) && empty($table->alias)) + { + $table->generateAlias(); + } + + if (empty($table->id)) + { + $table->created = $date->toSql(); + // set the user + if ($table->created_by == 0 || empty($table->created_by)) + { + $table->created_by = $user->id; + } + // Set ordering to the last item if not set + if (empty($table->ordering)) + { + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select('MAX(ordering)') + ->from($db->quoteName('#__getbible_open_ai_message')); + $db->setQuery($query); + $max = $db->loadResult(); + + $table->ordering = $max + 1; + } + } + else + { + $table->modified = $date->toSql(); + $table->modified_by = $user->id; + } + + if (!empty($table->id)) + { + // Increment the items version number. + $table->version++; + } + } + + /** + * Method to get the data that should be injected in the form. + * + * @return mixed The data for the form. + * + * @since 1.6 + */ + protected function loadFormData() + { + // Check the session for previously entered form data. + $data = JFactory::getApplication()->getUserState('com_getbible.edit.open_ai_message.data', array()); + + if (empty($data)) + { + $data = $this->getItem(); + // run the perprocess of the data + $this->preprocessData('com_getbible.open_ai_message', $data); + } + + return $data; + } + + /** + * Method to get the unique fields of this table. + * + * @return mixed An array of field names, boolean false if none is set. + * + * @since 3.0 + */ + protected function getUniqueFields() + { + return false; + } + + /** + * Method to delete one or more records. + * + * @param array &$pks An array of record primary keys. + * + * @return boolean True if successful, false if an error occurs. + * + * @since 12.2 + */ + public function delete(&$pks) + { + if (!parent::delete($pks)) + { + return false; + } + + return true; + } + + /** + * Method to change the published state of one or more records. + * + * @param array &$pks A list of the primary keys to change. + * @param integer $value The value of the published state. + * + * @return boolean True on success. + * + * @since 12.2 + */ + public function publish(&$pks, $value = 1) + { + if (!parent::publish($pks, $value)) + { + return false; + } + + return true; + } + + /** + * Method to perform batch operations on an item or a set of items. + * + * @param array $commands An array of commands to perform. + * @param array $pks An array of item ids. + * @param array $contexts An array of item contexts. + * + * @return boolean Returns true on success, false on failure. + * + * @since 12.2 + */ + public function batch($commands, $pks, $contexts) + { + // Sanitize ids. + $pks = array_unique($pks); + ArrayHelper::toInteger($pks); + + // Remove any values of zero. + if (array_search(0, $pks, true)) + { + unset($pks[array_search(0, $pks, true)]); + } + + if (empty($pks)) + { + $this->setError(JText::_('JGLOBAL_NO_ITEM_SELECTED')); + return false; + } + + $done = false; + + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->contentType = new JUcmType; + $this->type = $this->contentType->getTypeByTable($this->tableClassName); + $this->canDo = GetbibleHelper::getActions('open_ai_message'); + $this->batchSet = true; + + if (!$this->canDo->get('core.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + return false; + } + + if ($this->type == false) + { + $type = new JUcmType; + $this->type = $type->getTypeByAlias($this->typeAlias); + } + + $this->tagsObserver = $this->table->getObserverOfClass('JTableObserverTags'); + + if (!empty($commands['move_copy'])) + { + $cmd = ArrayHelper::getValue($commands, 'move_copy', 'c'); + + if ($cmd == 'c') + { + $result = $this->batchCopy($commands, $pks, $contexts); + + if (is_array($result)) + { + foreach ($result as $old => $new) + { + $contexts[$new] = $contexts[$old]; + } + $pks = array_values($result); + } + else + { + return false; + } + } + elseif ($cmd == 'm' && !$this->batchMove($commands, $pks, $contexts)) + { + return false; + } + + $done = true; + } + + if (!$done) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + + return false; + } + + // Clear the cache + $this->cleanCache(); + + return true; + } + + /** + * Batch copy items to a new category or current. + * + * @param integer $values The new values. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return mixed An array of new IDs on success, boolean false on failure. + * + * @since 12.2 + */ + protected function batchCopy($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('open_ai_message'); + } + + if (!$this->canDo->get('open_ai_message.create') && !$this->canDo->get('open_ai_message.batch')) + { + return false; + } + + // get list of unique fields + $uniqueFields = $this->getUniqueFields(); + // remove move_copy from array + unset($values['move_copy']); + + // make sure published is set + if (!isset($values['published'])) + { + $values['published'] = 0; + } + elseif (isset($values['published']) && !$this->canDo->get('open_ai_message.edit.state')) + { + $values['published'] = 0; + } + + $newIds = array(); + // Parent exists so let's proceed + while (!empty($pks)) + { + // Pop the first ID off the stack + $pk = array_shift($pks); + + $this->table->reset(); + + // only allow copy if user may edit this item. + if (!$this->user->authorise('open_ai_message.edit', $contexts[$pk])) + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // Only for strings + if (GetbibleHelper::checkString($this->table->role) && !is_numeric($this->table->role)) + { + $this->table->role = $this->generateUnique('role',$this->table->role); + } + + // insert all set values + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + if (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + // update all unique fields + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $this->table->$uniqueField = $this->generateUnique($uniqueField,$this->table->$uniqueField); + } + } + + // Reset the ID because we are making a copy + $this->table->id = 0; + + // TODO: Deal with ordering? + // $this->table->ordering = 1; + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + + // Get the new item ID + $newId = $this->table->get('id'); + + // Add the new ID to the array + $newIds[$pk] = $newId; + } + + // Clean the cache + $this->cleanCache(); + + return $newIds; + } + + /** + * Batch move items to a new category + * + * @param integer $value The new category ID. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 12.2 + */ + protected function batchMove($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('open_ai_message'); + } + + if (!$this->canDo->get('open_ai_message.edit') && !$this->canDo->get('open_ai_message.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // make sure published only updates if user has the permission. + if (isset($values['published']) && !$this->canDo->get('open_ai_message.edit.state')) + { + unset($values['published']); + } + // remove move_copy from array + unset($values['move_copy']); + + // Parent exists so we proceed + foreach ($pks as $pk) + { + if (!$this->user->authorise('open_ai_message.edit', $contexts[$pk])) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // insert all set values. + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + // Do special action for access. + if ('access' === $key && strlen($value) > 0) + { + $this->table->$key = $value; + } + elseif (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + } + + // Clean the cache + $this->cleanCache(); + + return true; + } + + /** + * Method to save the form data. + * + * @param array $data The form data. + * + * @return boolean True on success. + * + * @since 1.6 + */ + public function save($data) + { + $input = JFactory::getApplication()->input; + $filter = JFilterInput::getInstance(); + + // set the metadata to the Item Data + if (isset($data['metadata']) && isset($data['metadata']['author'])) + { + $data['metadata']['author'] = $filter->clean($data['metadata']['author'], 'TRIM'); + + $metadata = new JRegistry; + $metadata->loadArray($data['metadata']); + $data['metadata'] = (string) $metadata; + } + + // Set the Params Items to data + if (isset($data['params']) && is_array($data['params'])) + { + $params = new JRegistry; + $params->loadArray($data['params']); + $data['params'] = (string) $params; + } + + // Alter the unique field for save as copy + if ($input->get('task') === 'save2copy') + { + // Automatic handling of other unique fields + $uniqueFields = $this->getUniqueFields(); + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $data[$uniqueField] = $this->generateUnique($uniqueField,$data[$uniqueField]); + } + } + } + + if (parent::save($data)) + { + return true; + } + return false; + } + + /** + * Method to generate a unique value. + * + * @param string $field name. + * @param string $value data. + * + * @return string New value. + * + * @since 3.0 + */ + protected function generateUnique($field,$value) + { + + // set field value unique + $table = $this->getTable(); + + while ($table->load(array($field => $value))) + { + $value = StringHelper::increment($value); + } + + return $value; + } + + /** + * Method to change the title + * + * @param string $title The title. + * + * @return array Contains the modified title and alias. + * + */ + protected function _generateNewTitle($title) + { + + // Alter the title + $table = $this->getTable(); + + while ($table->load(array('title' => $title))) + { + $title = StringHelper::increment($title); + } + + return $title; + } +} diff --git a/admin/models/open_ai_messages.php b/admin/models/open_ai_messages.php new file mode 100644 index 0000000..2023545 --- /dev/null +++ b/admin/models/open_ai_messages.php @@ -0,0 +1,461 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\ListModel; +use Joomla\Utilities\ArrayHelper; + +/** + * Open_ai_messages List Model + */ +class GetbibleModelOpen_ai_messages extends ListModel +{ + public function __construct($config = array()) + { + if (empty($config['filter_fields'])) + { + $config['filter_fields'] = array( + 'a.id','id', + 'a.published','published', + 'a.access','access', + 'a.ordering','ordering', + 'a.created_by','created_by', + 'a.modified_by','modified_by', + 'a.role','role', + 'g.response_id','open_ai_response', + 'h.name','prompt', + 'a.source','source' + ); + } + + parent::__construct($config); + } + + /** + * Method to auto-populate the model state. + * + * Note. Calling getState in this method will result in recursion. + * + * @param string $ordering An optional ordering field. + * @param string $direction An optional direction (asc|desc). + * + * @return void + * + */ + protected function populateState($ordering = null, $direction = null) + { + $app = JFactory::getApplication(); + + // Adjust the context to support modal layouts. + if ($layout = $app->input->get('layout')) + { + $this->context .= '.' . $layout; + } + + // Check if the form was submitted + $formSubmited = $app->input->post->get('form_submited'); + + $access = $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', 0, 'int'); + if ($formSubmited) + { + $access = $app->input->post->get('access'); + $this->setState('filter.access', $access); + } + + $published = $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', ''); + $this->setState('filter.published', $published); + + $created_by = $this->getUserStateFromRequest($this->context . '.filter.created_by', 'filter_created_by', ''); + $this->setState('filter.created_by', $created_by); + + $created = $this->getUserStateFromRequest($this->context . '.filter.created', 'filter_created'); + $this->setState('filter.created', $created); + + $sorting = $this->getUserStateFromRequest($this->context . '.filter.sorting', 'filter_sorting', 0, 'int'); + $this->setState('filter.sorting', $sorting); + + $search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search'); + $this->setState('filter.search', $search); + + $role = $this->getUserStateFromRequest($this->context . '.filter.role', 'filter_role'); + if ($formSubmited) + { + $role = $app->input->post->get('role'); + $this->setState('filter.role', $role); + } + + $open_ai_response = $this->getUserStateFromRequest($this->context . '.filter.open_ai_response', 'filter_open_ai_response'); + if ($formSubmited) + { + $open_ai_response = $app->input->post->get('open_ai_response'); + $this->setState('filter.open_ai_response', $open_ai_response); + } + + $prompt = $this->getUserStateFromRequest($this->context . '.filter.prompt', 'filter_prompt'); + if ($formSubmited) + { + $prompt = $app->input->post->get('prompt'); + $this->setState('filter.prompt', $prompt); + } + + $source = $this->getUserStateFromRequest($this->context . '.filter.source', 'filter_source'); + if ($formSubmited) + { + $source = $app->input->post->get('source'); + $this->setState('filter.source', $source); + } + + // List state information. + parent::populateState($ordering, $direction); + } + + /** + * Method to get an array of data items. + * + * @return mixed An array of data items on success, false on failure. + */ + public function getItems() + { + // Check in items + $this->checkInNow(); + + // load parent items + $items = parent::getItems(); + + // Set values to display correctly. + if (GetbibleHelper::checkArray($items)) + { + // Get the user object if not set. + if (!isset($user) || !GetbibleHelper::checkObject($user)) + { + $user = JFactory::getUser(); + } + foreach ($items as $nr => &$item) + { + // Remove items the user can't access. + $access = ($user->authorise('open_ai_message.access', 'com_getbible.open_ai_message.' . (int) $item->id) && $user->authorise('open_ai_message.access', 'com_getbible')); + if (!$access) + { + unset($items[$nr]); + continue; + } + + } + } + + // set selection value to a translatable value + if (GetbibleHelper::checkArray($items)) + { + foreach ($items as $nr => &$item) + { + // convert role + $item->role = $this->selectionTranslation($item->role, 'role'); + // convert source + $item->source = $this->selectionTranslation($item->source, 'source'); + } + } + + + // return items + return $items; + } + + /** + * Method to convert selection values to translatable string. + * + * @return translatable string + */ + public function selectionTranslation($value,$name) + { + // Array of role language strings + if ($name === 'role') + { + $roleArray = array( + 'system' => 'COM_GETBIBLE_OPEN_AI_MESSAGE_SYSTEM', + 'user' => 'COM_GETBIBLE_OPEN_AI_MESSAGE_USER', + 'assistant' => 'COM_GETBIBLE_OPEN_AI_MESSAGE_ASSISTANT', + 'function' => 'COM_GETBIBLE_OPEN_AI_MESSAGE_FUNCTION' + ); + // Now check if value is found in this array + if (isset($roleArray[$value]) && GetbibleHelper::checkString($roleArray[$value])) + { + return $roleArray[$value]; + } + } + // Array of source language strings + if ($name === 'source') + { + $sourceArray = array( + 1 => 'COM_GETBIBLE_OPEN_AI_MESSAGE_PROMPT', + 2 => 'COM_GETBIBLE_OPEN_AI_MESSAGE_OPEN_AI' + ); + // Now check if value is found in this array + if (isset($sourceArray[$value]) && GetbibleHelper::checkString($sourceArray[$value])) + { + return $sourceArray[$value]; + } + } + return $value; + } + + /** + * Method to build an SQL query to load the list data. + * + * @return string An SQL query + */ + protected function getListQuery() + { + // Get the user object. + $user = JFactory::getUser(); + // Create a new query object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + + // Select some fields + $query->select('a.*'); + + // From the getbible_item table + $query->from($db->quoteName('#__getbible_open_ai_message', 'a')); + + // From the getbible_open_ai_response table. + $query->select($db->quoteName(['g.response_id','g.id'],['open_ai_response_response_id','open_ai_response_id'])); + $query->join('LEFT', $db->quoteName('#__getbible_open_ai_response', 'g') . ' ON (' . $db->quoteName('a.open_ai_response') . ' = ' . $db->quoteName('g.response_id') . ')'); + + // From the getbible_prompt table. + $query->select($db->quoteName(['h.name','h.id'],['prompt_name','prompt_id'])); + $query->join('LEFT', $db->quoteName('#__getbible_prompt', 'h') . ' ON (' . $db->quoteName('a.prompt') . ' = ' . $db->quoteName('h.guid') . ')'); + + // Filter by published state + $published = $this->getState('filter.published'); + if (is_numeric($published)) + { + $query->where('a.published = ' . (int) $published); + } + elseif ($published === '') + { + $query->where('(a.published = 0 OR a.published = 1)'); + } + + // Join over the asset groups. + $query->select('ag.title AS access_level'); + $query->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access'); + // Filter by access level. + $_access = $this->getState('filter.access'); + if ($_access && is_numeric($_access)) + { + $query->where('a.access = ' . (int) $_access); + } + elseif (GetbibleHelper::checkArray($_access)) + { + // Secure the array for the query + $_access = ArrayHelper::toInteger($_access); + // Filter by the Access Array. + $query->where('a.access IN (' . implode(',', $_access) . ')'); + } + // Implement View Level Access + if (!$user->authorise('core.options', 'com_getbible')) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + // Filter by search. + $search = $this->getState('filter.search'); + if (!empty($search)) + { + if (stripos($search, 'id:') === 0) + { + $query->where('a.id = ' . (int) substr($search, 3)); + } + else + { + $search = $db->quote('%' . $db->escape($search) . '%'); + $query->where('(a.content LIKE '.$search.')'); + } + } + + // Filter by Role. + $_role = $this->getState('filter.role'); + if (is_numeric($_role)) + { + if (is_float($_role)) + { + $query->where('a.role = ' . (float) $_role); + } + else + { + $query->where('a.role = ' . (int) $_role); + } + } + elseif (GetbibleHelper::checkString($_role)) + { + $query->where('a.role = ' . $db->quote($db->escape($_role))); + } + // Filter by Open_ai_response. + $_open_ai_response = $this->getState('filter.open_ai_response'); + if (is_numeric($_open_ai_response)) + { + if (is_float($_open_ai_response)) + { + $query->where('a.open_ai_response = ' . (float) $_open_ai_response); + } + else + { + $query->where('a.open_ai_response = ' . (int) $_open_ai_response); + } + } + elseif (GetbibleHelper::checkString($_open_ai_response)) + { + $query->where('a.open_ai_response = ' . $db->quote($db->escape($_open_ai_response))); + } + // Filter by Prompt. + $_prompt = $this->getState('filter.prompt'); + if (is_numeric($_prompt)) + { + if (is_float($_prompt)) + { + $query->where('a.prompt = ' . (float) $_prompt); + } + else + { + $query->where('a.prompt = ' . (int) $_prompt); + } + } + elseif (GetbibleHelper::checkString($_prompt)) + { + $query->where('a.prompt = ' . $db->quote($db->escape($_prompt))); + } + // Filter by Source. + $_source = $this->getState('filter.source'); + if (is_numeric($_source)) + { + if (is_float($_source)) + { + $query->where('a.source = ' . (float) $_source); + } + else + { + $query->where('a.source = ' . (int) $_source); + } + } + elseif (GetbibleHelper::checkString($_source)) + { + $query->where('a.source = ' . $db->quote($db->escape($_source))); + } + + // Add the list ordering clause. + $orderCol = $this->state->get('list.ordering', 'a.id'); + $orderDirn = $this->state->get('list.direction', 'desc'); + if ($orderCol != '') + { + $query->order($db->escape($orderCol . ' ' . $orderDirn)); + } + + return $query; + } + + /** + * Method to get a store id based on model configuration state. + * + * @return string A store id. + * + */ + protected function getStoreId($id = '') + { + // Compile the store id. + $id .= ':' . $this->getState('filter.id'); + $id .= ':' . $this->getState('filter.search'); + $id .= ':' . $this->getState('filter.published'); + // Check if the value is an array + $_access = $this->getState('filter.access'); + if (GetbibleHelper::checkArray($_access)) + { + $id .= ':' . implode(':', $_access); + } + // Check if this is only an number or string + elseif (is_numeric($_access) + || GetbibleHelper::checkString($_access)) + { + $id .= ':' . $_access; + } + $id .= ':' . $this->getState('filter.ordering'); + $id .= ':' . $this->getState('filter.created_by'); + $id .= ':' . $this->getState('filter.modified_by'); + $id .= ':' . $this->getState('filter.role'); + $id .= ':' . $this->getState('filter.open_ai_response'); + $id .= ':' . $this->getState('filter.prompt'); + $id .= ':' . $this->getState('filter.source'); + + return parent::getStoreId($id); + } + + /** + * Build an SQL query to checkin all items left checked out longer then a set time. + * + * @return a bool + * + */ + protected function checkInNow() + { + // Get set check in time + $time = JComponentHelper::getParams('com_getbible')->get('check_in'); + + if ($time) + { + + // Get a db connection. + $db = JFactory::getDbo(); + // Reset query. + $query = $db->getQuery(true); + $query->select('*'); + $query->from($db->quoteName('#__getbible_open_ai_message')); + // Only select items that are checked out. + $query->where($db->quoteName('checked_out') . '!=0'); + $db->setQuery($query, 0, 1); + $db->execute(); + if ($db->getNumRows()) + { + // Get Yesterdays date. + $date = JFactory::getDate()->modify($time)->toSql(); + // Reset query. + $query = $db->getQuery(true); + + // Fields to update. + $fields = array( + $db->quoteName('checked_out_time') . '=\'0000-00-00 00:00:00\'', + $db->quoteName('checked_out') . '=0' + ); + + // Conditions for which records should be updated. + $conditions = array( + $db->quoteName('checked_out') . '!=0', + $db->quoteName('checked_out_time') . '<\''.$date.'\'' + ); + + // Check table. + $query->update($db->quoteName('#__getbible_open_ai_message'))->set($fields)->where($conditions); + + $db->setQuery($query); + + $db->execute(); + } + } + + return false; + } +} diff --git a/admin/models/open_ai_response.php b/admin/models/open_ai_response.php new file mode 100644 index 0000000..aeb1fb3 --- /dev/null +++ b/admin/models/open_ai_response.php @@ -0,0 +1,1458 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\AdminModel; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; + +/** + * Getbible Open_ai_response Admin Model + */ +class GetbibleModelOpen_ai_response extends AdminModel +{ + /** + * The tab layout fields array. + * + * @var array + */ + protected $tabLayoutFields = array( + 'details' => array( + 'left' => array( + 'response_object', + 'response_model', + 'response_created' + ), + 'right' => array( + 'prompt_tokens', + 'completion_tokens', + 'total_tokens' + ), + 'above' => array( + 'response_id', + 'prompt' + ) + ), + 'prompt' => array( + 'left' => array( + 'max_tokens', + 'temperature', + 'top_p' + ), + 'right' => array( + 'model', + 'presence_penalty', + 'frequency_penalty', + 'n' + ) + ), + 'bible' => array( + 'left' => array( + 'abbreviation', + 'language', + 'lcsh', + 'book' + ), + 'right' => array( + 'chapter', + 'verse', + 'word', + 'selected_word' + ) + ) + ); + + /** + * @var string The prefix to use with controller messages. + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE'; + + /** + * The type alias for this content type. + * + * @var string + * @since 3.2 + */ + public $typeAlias = 'com_getbible.open_ai_response'; + + /** + * Returns a Table object, always creating it + * + * @param type $type The table type to instantiate + * @param string $prefix A prefix for the table class name. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JTable A database object + * + * @since 1.6 + */ + public function getTable($type = 'open_ai_response', $prefix = 'GetbibleTable', $config = array()) + { + // add table path for when model gets used from other component + $this->addTablePath(JPATH_ADMINISTRATOR . '/components/com_getbible/tables'); + // get instance of the table + return JTable::getInstance($type, $prefix, $config); + } + + /** + * Method to get a single record. + * + * @param integer $pk The id of the primary key. + * + * @return mixed Object on success, false on failure. + * + * @since 1.6 + */ + public function getItem($pk = null) + { + if ($item = parent::getItem($pk)) + { + if (!empty($item->params) && !is_array($item->params)) + { + // Convert the params field to an array. + $registry = new Registry; + $registry->loadString($item->params); + $item->params = $registry->toArray(); + } + + if (!empty($item->metadata)) + { + // Convert the metadata field to an array. + $registry = new Registry; + $registry->loadString($item->metadata); + $item->metadata = $registry->toArray(); + } + } + $this->open_ai_responsevvvy = $item->response_id; + + return $item; + } + + /** + * Method to get list data. + * + * @return mixed An array of data items on success, false on failure. + */ + public function getVvymessage() + { + // Get the user object. + $user = JFactory::getUser(); + // Create a new query object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + + // Select some fields + $query->select('a.*'); + + // From the getbible_open_ai_message table + $query->from($db->quoteName('#__getbible_open_ai_message', 'a')); + + // From the getbible_open_ai_response table. + $query->select($db->quoteName(['g.response_id','g.id'],['open_ai_response_response_id','open_ai_response_id'])); + $query->join('LEFT', $db->quoteName('#__getbible_open_ai_response', 'g') . ' ON (' . $db->quoteName('a.open_ai_response') . ' = ' . $db->quoteName('g.response_id') . ')'); + + // From the getbible_prompt table. + $query->select($db->quoteName(['h.name','h.id'],['prompt_name','prompt_id'])); + $query->join('LEFT', $db->quoteName('#__getbible_prompt', 'h') . ' ON (' . $db->quoteName('a.prompt') . ' = ' . $db->quoteName('h.guid') . ')'); + + // Filter by open_ai_responsevvvy global. + $open_ai_responsevvvy = $this->open_ai_responsevvvy; + if (is_numeric($open_ai_responsevvvy )) + { + $query->where('a.open_ai_response = ' . (int) $open_ai_responsevvvy ); + } + elseif (is_string($open_ai_responsevvvy)) + { + $query->where('a.open_ai_response = ' . $db->quote($open_ai_responsevvvy)); + } + else + { + $query->where('a.open_ai_response = -5'); + } + + // Join over the asset groups. + $query->select('ag.title AS access_level'); + $query->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access'); + // Filter by access level. + $_access = $this->getState('filter.access'); + if ($_access && is_numeric($_access)) + { + $query->where('a.access = ' . (int) $_access); + } + elseif (GetbibleHelper::checkArray($_access)) + { + // Secure the array for the query + $_access = ArrayHelper::toInteger($_access); + // Filter by the Access Array. + $query->where('a.access IN (' . implode(',', $_access) . ')'); + } + // Implement View Level Access + if (!$user->authorise('core.options', 'com_getbible')) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + + // Order the results by ordering + $query->order('a.published ASC'); + $query->order('a.ordering ASC'); + + // Load the items + $db->setQuery($query); + $db->execute(); + if ($db->getNumRows()) + { + $items = $db->loadObjectList(); + + // Set values to display correctly. + if (GetbibleHelper::checkArray($items)) + { + // Get the user object if not set. + if (!isset($user) || !GetbibleHelper::checkObject($user)) + { + $user = JFactory::getUser(); + } + foreach ($items as $nr => &$item) + { + // Remove items the user can't access. + $access = ($user->authorise('open_ai_message.access', 'com_getbible.open_ai_message.' . (int) $item->id) && $user->authorise('open_ai_message.access', 'com_getbible')); + if (!$access) + { + unset($items[$nr]); + continue; + } + + } + } + + // set selection value to a translatable value + if (GetbibleHelper::checkArray($items)) + { + foreach ($items as $nr => &$item) + { + // convert role + $item->role = $this->selectionTranslationVvymessage($item->role, 'role'); + // convert source + $item->source = $this->selectionTranslationVvymessage($item->source, 'source'); + } + } + + return $items; + } + return false; + } + + /** + * Method to convert selection values to translatable string. + * + * @return translatable string + */ + public function selectionTranslationVvymessage($value,$name) + { + // Array of role language strings + if ($name === 'role') + { + $roleArray = array( + 'system' => 'COM_GETBIBLE_OPEN_AI_MESSAGE_SYSTEM', + 'user' => 'COM_GETBIBLE_OPEN_AI_MESSAGE_USER', + 'assistant' => 'COM_GETBIBLE_OPEN_AI_MESSAGE_ASSISTANT', + 'function' => 'COM_GETBIBLE_OPEN_AI_MESSAGE_FUNCTION' + ); + // Now check if value is found in this array + if (isset($roleArray[$value]) && GetbibleHelper::checkString($roleArray[$value])) + { + return $roleArray[$value]; + } + } + // Array of source language strings + if ($name === 'source') + { + $sourceArray = array( + 1 => 'COM_GETBIBLE_OPEN_AI_MESSAGE_PROMPT', + 2 => 'COM_GETBIBLE_OPEN_AI_MESSAGE_OPEN_AI' + ); + // Now check if value is found in this array + if (isset($sourceArray[$value]) && GetbibleHelper::checkString($sourceArray[$value])) + { + return $sourceArray[$value]; + } + } + return $value; + } + + /** + * Method to get the record form. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * @param array $options Optional array of options for the form creation. + * + * @return mixed A JForm object on success, false on failure + * + * @since 1.6 + */ + public function getForm($data = array(), $loadData = true, $options = array('control' => 'jform')) + { + // set load data option + $options['load_data'] = $loadData; + // check if xpath was set in options + $xpath = false; + if (isset($options['xpath'])) + { + $xpath = $options['xpath']; + unset($options['xpath']); + } + // check if clear form was set in options + $clear = false; + if (isset($options['clear'])) + { + $clear = $options['clear']; + unset($options['clear']); + } + + // Get the form. + $form = $this->loadForm('com_getbible.open_ai_response', 'open_ai_response', $options, $clear, $xpath); + + if (empty($form)) + { + return false; + } + + $jinput = JFactory::getApplication()->input; + + // The front end calls this model and uses a_id to avoid id clashes so we need to check for that first. + if ($jinput->get('a_id')) + { + $id = $jinput->get('a_id', 0, 'INT'); + } + // The back end uses id so we use that the rest of the time and set it to 0 by default. + else + { + $id = $jinput->get('id', 0, 'INT'); + } + + $user = JFactory::getUser(); + + // Check for existing item. + // Modify the form based on Edit State access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.state', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.state', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('ordering', 'disabled', 'true'); + $form->setFieldAttribute('published', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('ordering', 'filter', 'unset'); + $form->setFieldAttribute('published', 'filter', 'unset'); + } + // If this is a new item insure the greated by is set. + if (0 == $id) + { + // Set the created_by to this user + $form->setValue('created_by', null, $user->id); + } + // Modify the form based on Edit Creaded By access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.created_by', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.created_by', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created_by', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('created_by', 'readonly', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created_by', 'filter', 'unset'); + } + // Modify the form based on Edit Creaded Date access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.created', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.created', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created', 'filter', 'unset'); + } + // Modify the form based on Edit Response Id access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.response_id', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.response_id', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('response_id', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('response_id', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('response_id')) + { + // Disable fields while saving. + $form->setFieldAttribute('response_id', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('response_id', 'required', 'false'); + } + } + // Modify the form based on Edit Prompt access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.prompt', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.prompt', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('prompt', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('prompt', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('prompt')) + { + // Disable fields while saving. + $form->setFieldAttribute('prompt', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('prompt', 'required', 'false'); + } + } + // Modify the form based on Edit Response Object access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.response_object', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.response_object', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('response_object', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('response_object', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('response_object')) + { + // Disable fields while saving. + $form->setFieldAttribute('response_object', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('response_object', 'required', 'false'); + } + } + // Modify the form based on Edit Response Model access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.response_model', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.response_model', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('response_model', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('response_model', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('response_model')) + { + // Disable fields while saving. + $form->setFieldAttribute('response_model', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('response_model', 'required', 'false'); + } + } + // Modify the form based on Edit Total Tokens access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.total_tokens', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.total_tokens', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('total_tokens', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('total_tokens', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('total_tokens')) + { + // Disable fields while saving. + $form->setFieldAttribute('total_tokens', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('total_tokens', 'required', 'false'); + } + } + // Modify the form based on Edit N access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.n', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.n', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('n', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('n', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('n')) + { + // Disable fields while saving. + $form->setFieldAttribute('n', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('n', 'required', 'false'); + } + } + // Modify the form based on Edit Frequency Penalty access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.frequency_penalty', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.frequency_penalty', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('frequency_penalty', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('frequency_penalty', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('frequency_penalty')) + { + // Disable fields while saving. + $form->setFieldAttribute('frequency_penalty', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('frequency_penalty', 'required', 'false'); + } + } + // Modify the form based on Edit Presence Penalty access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.presence_penalty', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.presence_penalty', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('presence_penalty', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('presence_penalty', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('presence_penalty')) + { + // Disable fields while saving. + $form->setFieldAttribute('presence_penalty', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('presence_penalty', 'required', 'false'); + } + } + // Modify the form based on Edit Word access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.word', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.word', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('word', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('word', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('word')) + { + // Disable fields while saving. + $form->setFieldAttribute('word', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('word', 'required', 'false'); + } + } + // Modify the form based on Edit Chapter access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.chapter', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.chapter', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('chapter', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('chapter', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('chapter')) + { + // Disable fields while saving. + $form->setFieldAttribute('chapter', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('chapter', 'required', 'false'); + } + } + // Modify the form based on Edit Lcsh access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.lcsh', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.lcsh', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('lcsh', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('lcsh', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('lcsh')) + { + // Disable fields while saving. + $form->setFieldAttribute('lcsh', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('lcsh', 'required', 'false'); + } + } + // Modify the form based on Edit Completion Tokens access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.completion_tokens', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.completion_tokens', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('completion_tokens', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('completion_tokens', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('completion_tokens')) + { + // Disable fields while saving. + $form->setFieldAttribute('completion_tokens', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('completion_tokens', 'required', 'false'); + } + } + // Modify the form based on Edit Prompt Tokens access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.prompt_tokens', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.prompt_tokens', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('prompt_tokens', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('prompt_tokens', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('prompt_tokens')) + { + // Disable fields while saving. + $form->setFieldAttribute('prompt_tokens', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('prompt_tokens', 'required', 'false'); + } + } + // Modify the form based on Edit Response Created access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.response_created', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.response_created', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('response_created', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('response_created', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('response_created')) + { + // Disable fields while saving. + $form->setFieldAttribute('response_created', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('response_created', 'required', 'false'); + } + } + // Modify the form based on Edit Abbreviation access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.abbreviation', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.abbreviation', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('abbreviation', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('abbreviation', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('abbreviation')) + { + // Disable fields while saving. + $form->setFieldAttribute('abbreviation', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('abbreviation', 'required', 'false'); + } + } + // Modify the form based on Edit Language access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.language', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.language', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('language', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('language', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('language')) + { + // Disable fields while saving. + $form->setFieldAttribute('language', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('language', 'required', 'false'); + } + } + // Modify the form based on Edit Max Tokens access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.max_tokens', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.max_tokens', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('max_tokens', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('max_tokens', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('max_tokens')) + { + // Disable fields while saving. + $form->setFieldAttribute('max_tokens', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('max_tokens', 'required', 'false'); + } + } + // Modify the form based on Edit Book access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.book', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.book', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('book', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('book', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('book')) + { + // Disable fields while saving. + $form->setFieldAttribute('book', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('book', 'required', 'false'); + } + } + // Modify the form based on Edit Temperature access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.temperature', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.temperature', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('temperature', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('temperature', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('temperature')) + { + // Disable fields while saving. + $form->setFieldAttribute('temperature', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('temperature', 'required', 'false'); + } + } + // Modify the form based on Edit Verse access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.verse', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.verse', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('verse', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('verse', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('verse')) + { + // Disable fields while saving. + $form->setFieldAttribute('verse', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('verse', 'required', 'false'); + } + } + // Modify the form based on Edit Top P access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.top_p', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.top_p', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('top_p', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('top_p', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('top_p')) + { + // Disable fields while saving. + $form->setFieldAttribute('top_p', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('top_p', 'required', 'false'); + } + } + // Modify the form based on Edit Selected Word access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.selected_word', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.selected_word', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('selected_word', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('selected_word', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('selected_word')) + { + // Disable fields while saving. + $form->setFieldAttribute('selected_word', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('selected_word', 'required', 'false'); + } + } + // Modify the form based on Edit Model access controls. + if ($id != 0 && (!$user->authorise('open_ai_response.edit.model', 'com_getbible.open_ai_response.' . (int) $id)) + || ($id == 0 && !$user->authorise('open_ai_response.edit.model', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('model', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('model', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('model')) + { + // Disable fields while saving. + $form->setFieldAttribute('model', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('model', 'required', 'false'); + } + } + // Only load these values if no id is found + if (0 == $id) + { + // Set redirected view name + $redirectedView = $jinput->get('ref', null, 'STRING'); + // Set field name (or fall back to view name) + $redirectedField = $jinput->get('field', $redirectedView, 'STRING'); + // Set redirected view id + $redirectedId = $jinput->get('refid', 0, 'INT'); + // Set field id (or fall back to redirected view id) + $redirectedValue = $jinput->get('field_id', $redirectedId, 'INT'); + if (0 != $redirectedValue && $redirectedField) + { + // Now set the local-redirected field default value + $form->setValue($redirectedField, null, $redirectedValue); + } + } + return $form; + } + + /** + * Method to get the script that have to be included on the form + * + * @return string script files + */ + public function getScript() + { + return 'media/com_getbible/js/open_ai_response.js'; + } + + /** + * Method to test whether a record can be deleted. + * + * @param object $record A record object. + * + * @return boolean True if allowed to delete the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canDelete($record) + { + if (!empty($record->id)) + { + if ($record->published != -2) + { + return; + } + + $user = JFactory::getUser(); + // The record has been set. Check the record permissions. + return $user->authorise('open_ai_response.delete', 'com_getbible.open_ai_response.' . (int) $record->id); + } + return false; + } + + /** + * Method to test whether a record can have its state edited. + * + * @param object $record A record object. + * + * @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canEditState($record) + { + $user = JFactory::getUser(); + $recordId = (!empty($record->id)) ? $record->id : 0; + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('open_ai_response.edit.state', 'com_getbible.open_ai_response.' . (int) $recordId); + if (!$permission && !is_null($permission)) + { + return false; + } + } + // In the absense of better information, revert to the component permissions. + return $user->authorise('open_ai_response.edit.state', 'com_getbible'); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * @since 2.5 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // Check specific edit permission then general edit permission. + $user = JFactory::getUser(); + + return $user->authorise('open_ai_response.edit', 'com_getbible.open_ai_response.'. ((int) isset($data[$key]) ? $data[$key] : 0)) or $user->authorise('open_ai_response.edit', 'com_getbible'); + } + + /** + * Prepare and sanitise the table data prior to saving. + * + * @param JTable $table A JTable object. + * + * @return void + * + * @since 1.6 + */ + protected function prepareTable($table) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if (isset($table->name)) + { + $table->name = htmlspecialchars_decode($table->name, ENT_QUOTES); + } + + if (isset($table->alias) && empty($table->alias)) + { + $table->generateAlias(); + } + + if (empty($table->id)) + { + $table->created = $date->toSql(); + // set the user + if ($table->created_by == 0 || empty($table->created_by)) + { + $table->created_by = $user->id; + } + // Set ordering to the last item if not set + if (empty($table->ordering)) + { + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select('MAX(ordering)') + ->from($db->quoteName('#__getbible_open_ai_response')); + $db->setQuery($query); + $max = $db->loadResult(); + + $table->ordering = $max + 1; + } + } + else + { + $table->modified = $date->toSql(); + $table->modified_by = $user->id; + } + + if (!empty($table->id)) + { + // Increment the items version number. + $table->version++; + } + } + + /** + * Method to get the data that should be injected in the form. + * + * @return mixed The data for the form. + * + * @since 1.6 + */ + protected function loadFormData() + { + // Check the session for previously entered form data. + $data = JFactory::getApplication()->getUserState('com_getbible.edit.open_ai_response.data', array()); + + if (empty($data)) + { + $data = $this->getItem(); + // run the perprocess of the data + $this->preprocessData('com_getbible.open_ai_response', $data); + } + + return $data; + } + + /** + * Method to get the unique fields of this table. + * + * @return mixed An array of field names, boolean false if none is set. + * + * @since 3.0 + */ + protected function getUniqueFields() + { + return false; + } + + /** + * Method to delete one or more records. + * + * @param array &$pks An array of record primary keys. + * + * @return boolean True if successful, false if an error occurs. + * + * @since 12.2 + */ + public function delete(&$pks) + { + if (!parent::delete($pks)) + { + return false; + } + + return true; + } + + /** + * Method to change the published state of one or more records. + * + * @param array &$pks A list of the primary keys to change. + * @param integer $value The value of the published state. + * + * @return boolean True on success. + * + * @since 12.2 + */ + public function publish(&$pks, $value = 1) + { + if (!parent::publish($pks, $value)) + { + return false; + } + + return true; + } + + /** + * Method to perform batch operations on an item or a set of items. + * + * @param array $commands An array of commands to perform. + * @param array $pks An array of item ids. + * @param array $contexts An array of item contexts. + * + * @return boolean Returns true on success, false on failure. + * + * @since 12.2 + */ + public function batch($commands, $pks, $contexts) + { + // Sanitize ids. + $pks = array_unique($pks); + ArrayHelper::toInteger($pks); + + // Remove any values of zero. + if (array_search(0, $pks, true)) + { + unset($pks[array_search(0, $pks, true)]); + } + + if (empty($pks)) + { + $this->setError(JText::_('JGLOBAL_NO_ITEM_SELECTED')); + return false; + } + + $done = false; + + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->contentType = new JUcmType; + $this->type = $this->contentType->getTypeByTable($this->tableClassName); + $this->canDo = GetbibleHelper::getActions('open_ai_response'); + $this->batchSet = true; + + if (!$this->canDo->get('core.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + return false; + } + + if ($this->type == false) + { + $type = new JUcmType; + $this->type = $type->getTypeByAlias($this->typeAlias); + } + + $this->tagsObserver = $this->table->getObserverOfClass('JTableObserverTags'); + + if (!empty($commands['move_copy'])) + { + $cmd = ArrayHelper::getValue($commands, 'move_copy', 'c'); + + if ($cmd == 'c') + { + $result = $this->batchCopy($commands, $pks, $contexts); + + if (is_array($result)) + { + foreach ($result as $old => $new) + { + $contexts[$new] = $contexts[$old]; + } + $pks = array_values($result); + } + else + { + return false; + } + } + elseif ($cmd == 'm' && !$this->batchMove($commands, $pks, $contexts)) + { + return false; + } + + $done = true; + } + + if (!$done) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + + return false; + } + + // Clear the cache + $this->cleanCache(); + + return true; + } + + /** + * Batch copy items to a new category or current. + * + * @param integer $values The new values. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return mixed An array of new IDs on success, boolean false on failure. + * + * @since 12.2 + */ + protected function batchCopy($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('open_ai_response'); + } + + if (!$this->canDo->get('open_ai_response.create') && !$this->canDo->get('open_ai_response.batch')) + { + return false; + } + + // get list of unique fields + $uniqueFields = $this->getUniqueFields(); + // remove move_copy from array + unset($values['move_copy']); + + // make sure published is set + if (!isset($values['published'])) + { + $values['published'] = 0; + } + elseif (isset($values['published']) && !$this->canDo->get('open_ai_response.edit.state')) + { + $values['published'] = 0; + } + + $newIds = array(); + // Parent exists so let's proceed + while (!empty($pks)) + { + // Pop the first ID off the stack + $pk = array_shift($pks); + + $this->table->reset(); + + // only allow copy if user may edit this item. + if (!$this->user->authorise('open_ai_response.edit', $contexts[$pk])) + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // Only for strings + if (GetbibleHelper::checkString($this->table->response_id) && !is_numeric($this->table->response_id)) + { + $this->table->response_id = $this->generateUnique('response_id',$this->table->response_id); + } + + // insert all set values + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + if (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + // update all unique fields + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $this->table->$uniqueField = $this->generateUnique($uniqueField,$this->table->$uniqueField); + } + } + + // Reset the ID because we are making a copy + $this->table->id = 0; + + // TODO: Deal with ordering? + // $this->table->ordering = 1; + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + + // Get the new item ID + $newId = $this->table->get('id'); + + // Add the new ID to the array + $newIds[$pk] = $newId; + } + + // Clean the cache + $this->cleanCache(); + + return $newIds; + } + + /** + * Batch move items to a new category + * + * @param integer $value The new category ID. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 12.2 + */ + protected function batchMove($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('open_ai_response'); + } + + if (!$this->canDo->get('open_ai_response.edit') && !$this->canDo->get('open_ai_response.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // make sure published only updates if user has the permission. + if (isset($values['published']) && !$this->canDo->get('open_ai_response.edit.state')) + { + unset($values['published']); + } + // remove move_copy from array + unset($values['move_copy']); + + // Parent exists so we proceed + foreach ($pks as $pk) + { + if (!$this->user->authorise('open_ai_response.edit', $contexts[$pk])) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // insert all set values. + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + // Do special action for access. + if ('access' === $key && strlen($value) > 0) + { + $this->table->$key = $value; + } + elseif (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + } + + // Clean the cache + $this->cleanCache(); + + return true; + } + + /** + * Method to save the form data. + * + * @param array $data The form data. + * + * @return boolean True on success. + * + * @since 1.6 + */ + public function save($data) + { + $input = JFactory::getApplication()->input; + $filter = JFilterInput::getInstance(); + + // set the metadata to the Item Data + if (isset($data['metadata']) && isset($data['metadata']['author'])) + { + $data['metadata']['author'] = $filter->clean($data['metadata']['author'], 'TRIM'); + + $metadata = new JRegistry; + $metadata->loadArray($data['metadata']); + $data['metadata'] = (string) $metadata; + } + + // Set the Params Items to data + if (isset($data['params']) && is_array($data['params'])) + { + $params = new JRegistry; + $params->loadArray($data['params']); + $data['params'] = (string) $params; + } + + // Alter the unique field for save as copy + if ($input->get('task') === 'save2copy') + { + // Automatic handling of other unique fields + $uniqueFields = $this->getUniqueFields(); + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $data[$uniqueField] = $this->generateUnique($uniqueField,$data[$uniqueField]); + } + } + } + + if (parent::save($data)) + { + return true; + } + return false; + } + + /** + * Method to generate a unique value. + * + * @param string $field name. + * @param string $value data. + * + * @return string New value. + * + * @since 3.0 + */ + protected function generateUnique($field,$value) + { + + // set field value unique + $table = $this->getTable(); + + while ($table->load(array($field => $value))) + { + $value = StringHelper::increment($value); + } + + return $value; + } + + /** + * Method to change the title + * + * @param string $title The title. + * + * @return array Contains the modified title and alias. + * + */ + protected function _generateNewTitle($title) + { + + // Alter the title + $table = $this->getTable(); + + while ($table->load(array('title' => $title))) + { + $title = StringHelper::increment($title); + } + + return $title; + } +} diff --git a/admin/models/open_ai_responses.php b/admin/models/open_ai_responses.php new file mode 100644 index 0000000..bc2fe45 --- /dev/null +++ b/admin/models/open_ai_responses.php @@ -0,0 +1,398 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\ListModel; +use Joomla\Utilities\ArrayHelper; + +/** + * Open_ai_responses List Model + */ +class GetbibleModelOpen_ai_responses extends ListModel +{ + public function __construct($config = array()) + { + if (empty($config['filter_fields'])) + { + $config['filter_fields'] = array( + 'a.id','id', + 'a.published','published', + 'a.access','access', + 'a.ordering','ordering', + 'a.created_by','created_by', + 'a.modified_by','modified_by', + 'a.response_id','response_id', + 'g.name','prompt', + 'a.response_model','response_model', + 'a.response_object','response_object', + 'a.total_tokens','total_tokens' + ); + } + + parent::__construct($config); + } + + /** + * Method to auto-populate the model state. + * + * Note. Calling getState in this method will result in recursion. + * + * @param string $ordering An optional ordering field. + * @param string $direction An optional direction (asc|desc). + * + * @return void + * + */ + protected function populateState($ordering = null, $direction = null) + { + $app = JFactory::getApplication(); + + // Adjust the context to support modal layouts. + if ($layout = $app->input->get('layout')) + { + $this->context .= '.' . $layout; + } + + // Check if the form was submitted + $formSubmited = $app->input->post->get('form_submited'); + + $access = $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', 0, 'int'); + if ($formSubmited) + { + $access = $app->input->post->get('access'); + $this->setState('filter.access', $access); + } + + $published = $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', ''); + $this->setState('filter.published', $published); + + $created_by = $this->getUserStateFromRequest($this->context . '.filter.created_by', 'filter_created_by', ''); + $this->setState('filter.created_by', $created_by); + + $created = $this->getUserStateFromRequest($this->context . '.filter.created', 'filter_created'); + $this->setState('filter.created', $created); + + $sorting = $this->getUserStateFromRequest($this->context . '.filter.sorting', 'filter_sorting', 0, 'int'); + $this->setState('filter.sorting', $sorting); + + $search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search'); + $this->setState('filter.search', $search); + + $response_id = $this->getUserStateFromRequest($this->context . '.filter.response_id', 'filter_response_id'); + if ($formSubmited) + { + $response_id = $app->input->post->get('response_id'); + $this->setState('filter.response_id', $response_id); + } + + $prompt = $this->getUserStateFromRequest($this->context . '.filter.prompt', 'filter_prompt'); + if ($formSubmited) + { + $prompt = $app->input->post->get('prompt'); + $this->setState('filter.prompt', $prompt); + } + + $response_model = $this->getUserStateFromRequest($this->context . '.filter.response_model', 'filter_response_model'); + if ($formSubmited) + { + $response_model = $app->input->post->get('response_model'); + $this->setState('filter.response_model', $response_model); + } + + $response_object = $this->getUserStateFromRequest($this->context . '.filter.response_object', 'filter_response_object'); + if ($formSubmited) + { + $response_object = $app->input->post->get('response_object'); + $this->setState('filter.response_object', $response_object); + } + + $total_tokens = $this->getUserStateFromRequest($this->context . '.filter.total_tokens', 'filter_total_tokens'); + if ($formSubmited) + { + $total_tokens = $app->input->post->get('total_tokens'); + $this->setState('filter.total_tokens', $total_tokens); + } + + // List state information. + parent::populateState($ordering, $direction); + } + + /** + * Method to get an array of data items. + * + * @return mixed An array of data items on success, false on failure. + */ + public function getItems() + { + // Check in items + $this->checkInNow(); + + // load parent items + $items = parent::getItems(); + + // Set values to display correctly. + if (GetbibleHelper::checkArray($items)) + { + // Get the user object if not set. + if (!isset($user) || !GetbibleHelper::checkObject($user)) + { + $user = JFactory::getUser(); + } + foreach ($items as $nr => &$item) + { + // Remove items the user can't access. + $access = ($user->authorise('open_ai_response.access', 'com_getbible.open_ai_response.' . (int) $item->id) && $user->authorise('open_ai_response.access', 'com_getbible')); + if (!$access) + { + unset($items[$nr]); + continue; + } + + } + } + + // return items + return $items; + } + + /** + * Method to build an SQL query to load the list data. + * + * @return string An SQL query + */ + protected function getListQuery() + { + // Get the user object. + $user = JFactory::getUser(); + // Create a new query object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + + // Select some fields + $query->select('a.*'); + + // From the getbible_item table + $query->from($db->quoteName('#__getbible_open_ai_response', 'a')); + + // From the getbible_prompt table. + $query->select($db->quoteName(['g.name','g.id'],['prompt_name','prompt_id'])); + $query->join('LEFT', $db->quoteName('#__getbible_prompt', 'g') . ' ON (' . $db->quoteName('a.prompt') . ' = ' . $db->quoteName('g.guid') . ')'); + + // Filter by published state + $published = $this->getState('filter.published'); + if (is_numeric($published)) + { + $query->where('a.published = ' . (int) $published); + } + elseif ($published === '') + { + $query->where('(a.published = 0 OR a.published = 1)'); + } + + // Join over the asset groups. + $query->select('ag.title AS access_level'); + $query->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access'); + // Filter by access level. + $_access = $this->getState('filter.access'); + if ($_access && is_numeric($_access)) + { + $query->where('a.access = ' . (int) $_access); + } + elseif (GetbibleHelper::checkArray($_access)) + { + // Secure the array for the query + $_access = ArrayHelper::toInteger($_access); + // Filter by the Access Array. + $query->where('a.access IN (' . implode(',', $_access) . ')'); + } + // Implement View Level Access + if (!$user->authorise('core.options', 'com_getbible')) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + // Filter by search. + $search = $this->getState('filter.search'); + if (!empty($search)) + { + if (stripos($search, 'id:') === 0) + { + $query->where('a.id = ' . (int) substr($search, 3)); + } + else + { + $search = $db->quote('%' . $db->escape($search) . '%'); + $query->where('(a.response_object LIKE '.$search.' OR a.response_model LIKE '.$search.')'); + } + } + + // Filter by Response_id. + $_response_id = $this->getState('filter.response_id'); + if (is_numeric($_response_id)) + { + if (is_float($_response_id)) + { + $query->where('a.response_id = ' . (float) $_response_id); + } + else + { + $query->where('a.response_id = ' . (int) $_response_id); + } + } + elseif (GetbibleHelper::checkString($_response_id)) + { + $query->where('a.response_id = ' . $db->quote($db->escape($_response_id))); + } + // Filter by Prompt. + $_prompt = $this->getState('filter.prompt'); + if (is_numeric($_prompt)) + { + if (is_float($_prompt)) + { + $query->where('a.prompt = ' . (float) $_prompt); + } + else + { + $query->where('a.prompt = ' . (int) $_prompt); + } + } + elseif (GetbibleHelper::checkString($_prompt)) + { + $query->where('a.prompt = ' . $db->quote($db->escape($_prompt))); + } + // Filter by Response_model. + $_response_model = $this->getState('filter.response_model'); + if (is_numeric($_response_model)) + { + if (is_float($_response_model)) + { + $query->where('a.response_model = ' . (float) $_response_model); + } + else + { + $query->where('a.response_model = ' . (int) $_response_model); + } + } + elseif (GetbibleHelper::checkString($_response_model)) + { + $query->where('a.response_model = ' . $db->quote($db->escape($_response_model))); + } + + // Add the list ordering clause. + $orderCol = $this->state->get('list.ordering', 'a.id'); + $orderDirn = $this->state->get('list.direction', 'desc'); + if ($orderCol != '') + { + $query->order($db->escape($orderCol . ' ' . $orderDirn)); + } + + return $query; + } + + /** + * Method to get a store id based on model configuration state. + * + * @return string A store id. + * + */ + protected function getStoreId($id = '') + { + // Compile the store id. + $id .= ':' . $this->getState('filter.id'); + $id .= ':' . $this->getState('filter.search'); + $id .= ':' . $this->getState('filter.published'); + // Check if the value is an array + $_access = $this->getState('filter.access'); + if (GetbibleHelper::checkArray($_access)) + { + $id .= ':' . implode(':', $_access); + } + // Check if this is only an number or string + elseif (is_numeric($_access) + || GetbibleHelper::checkString($_access)) + { + $id .= ':' . $_access; + } + $id .= ':' . $this->getState('filter.ordering'); + $id .= ':' . $this->getState('filter.created_by'); + $id .= ':' . $this->getState('filter.modified_by'); + $id .= ':' . $this->getState('filter.response_id'); + $id .= ':' . $this->getState('filter.prompt'); + $id .= ':' . $this->getState('filter.response_model'); + $id .= ':' . $this->getState('filter.response_object'); + $id .= ':' . $this->getState('filter.total_tokens'); + + return parent::getStoreId($id); + } + + /** + * Build an SQL query to checkin all items left checked out longer then a set time. + * + * @return a bool + * + */ + protected function checkInNow() + { + // Get set check in time + $time = JComponentHelper::getParams('com_getbible')->get('check_in'); + + if ($time) + { + + // Get a db connection. + $db = JFactory::getDbo(); + // Reset query. + $query = $db->getQuery(true); + $query->select('*'); + $query->from($db->quoteName('#__getbible_open_ai_response')); + // Only select items that are checked out. + $query->where($db->quoteName('checked_out') . '!=0'); + $db->setQuery($query, 0, 1); + $db->execute(); + if ($db->getNumRows()) + { + // Get Yesterdays date. + $date = JFactory::getDate()->modify($time)->toSql(); + // Reset query. + $query = $db->getQuery(true); + + // Fields to update. + $fields = array( + $db->quoteName('checked_out_time') . '=\'0000-00-00 00:00:00\'', + $db->quoteName('checked_out') . '=0' + ); + + // Conditions for which records should be updated. + $conditions = array( + $db->quoteName('checked_out') . '!=0', + $db->quoteName('checked_out_time') . '<\''.$date.'\'' + ); + + // Check table. + $query->update($db->quoteName('#__getbible_open_ai_response'))->set($fields)->where($conditions); + + $db->setQuery($query); + + $db->execute(); + } + } + + return false; + } +} diff --git a/admin/models/password.php b/admin/models/password.php new file mode 100644 index 0000000..10d9895 --- /dev/null +++ b/admin/models/password.php @@ -0,0 +1,1005 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\AdminModel; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; +use VDM\Joomla\Utilities\GuidHelper; +use VDM\Joomla\Utilities\GetHelper; + +/** + * Getbible Password Admin Model + */ +class GetbibleModelPassword extends AdminModel +{ + /** + * The tab layout fields array. + * + * @var array + */ + protected $tabLayoutFields = array( + 'details' => array( + 'left' => array( + 'name' + ), + 'right' => array( + 'password' + ), + 'above' => array( + 'linker' + ) + ) + ); + + /** + * @var string The prefix to use with controller messages. + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE'; + + /** + * The type alias for this content type. + * + * @var string + * @since 3.2 + */ + public $typeAlias = 'com_getbible.password'; + + /** + * Returns a Table object, always creating it + * + * @param type $type The table type to instantiate + * @param string $prefix A prefix for the table class name. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JTable A database object + * + * @since 1.6 + */ + public function getTable($type = 'password', $prefix = 'GetbibleTable', $config = array()) + { + // add table path for when model gets used from other component + $this->addTablePath(JPATH_ADMINISTRATOR . '/components/com_getbible/tables'); + // get instance of the table + return JTable::getInstance($type, $prefix, $config); + } + + /** + * Method to get a single record. + * + * @param integer $pk The id of the primary key. + * + * @return mixed Object on success, false on failure. + * + * @since 1.6 + */ + public function getItem($pk = null) + { + if ($item = parent::getItem($pk)) + { + if (!empty($item->params) && !is_array($item->params)) + { + // Convert the params field to an array. + $registry = new Registry; + $registry->loadString($item->params); + $item->params = $registry->toArray(); + } + + if (!empty($item->metadata)) + { + // Convert the metadata field to an array. + $registry = new Registry; + $registry->loadString($item->metadata); + $item->metadata = $registry->toArray(); + } + } + + return $item; + } + + /** + * Method to get the record form. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * @param array $options Optional array of options for the form creation. + * + * @return mixed A JForm object on success, false on failure + * + * @since 1.6 + */ + public function getForm($data = array(), $loadData = true, $options = array('control' => 'jform')) + { + // set load data option + $options['load_data'] = $loadData; + // check if xpath was set in options + $xpath = false; + if (isset($options['xpath'])) + { + $xpath = $options['xpath']; + unset($options['xpath']); + } + // check if clear form was set in options + $clear = false; + if (isset($options['clear'])) + { + $clear = $options['clear']; + unset($options['clear']); + } + + // Get the form. + $form = $this->loadForm('com_getbible.password', 'password', $options, $clear, $xpath); + + if (empty($form)) + { + return false; + } + + $jinput = JFactory::getApplication()->input; + + // The front end calls this model and uses a_id to avoid id clashes so we need to check for that first. + if ($jinput->get('a_id')) + { + $id = $jinput->get('a_id', 0, 'INT'); + } + // The back end uses id so we use that the rest of the time and set it to 0 by default. + else + { + $id = $jinput->get('id', 0, 'INT'); + } + + $user = JFactory::getUser(); + + // Check for existing item. + // Modify the form based on Edit State access controls. + if ($id != 0 && (!$user->authorise('password.edit.state', 'com_getbible.password.' . (int) $id)) + || ($id == 0 && !$user->authorise('password.edit.state', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('ordering', 'disabled', 'true'); + $form->setFieldAttribute('published', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('ordering', 'filter', 'unset'); + $form->setFieldAttribute('published', 'filter', 'unset'); + } + // If this is a new item insure the greated by is set. + if (0 == $id) + { + // Set the created_by to this user + $form->setValue('created_by', null, $user->id); + } + // Modify the form based on Edit Creaded By access controls. + if ($id != 0 && (!$user->authorise('password.edit.created_by', 'com_getbible.password.' . (int) $id)) + || ($id == 0 && !$user->authorise('password.edit.created_by', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created_by', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('created_by', 'readonly', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created_by', 'filter', 'unset'); + } + // Modify the form based on Edit Creaded Date access controls. + if ($id != 0 && (!$user->authorise('password.edit.created', 'com_getbible.password.' . (int) $id)) + || ($id == 0 && !$user->authorise('password.edit.created', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created', 'filter', 'unset'); + } + // Modify the form based on Edit Name access controls. + if ($id != 0 && (!$user->authorise('password.edit.name', 'com_getbible.password.' . (int) $id)) + || ($id == 0 && !$user->authorise('password.edit.name', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('name', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('name', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('name')) + { + // Disable fields while saving. + $form->setFieldAttribute('name', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('name', 'required', 'false'); + } + } + // Modify the form based on Edit Linker access controls. + if ($id != 0 && (!$user->authorise('password.edit.linker', 'com_getbible.password.' . (int) $id)) + || ($id == 0 && !$user->authorise('password.edit.linker', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('linker', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('linker', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('linker')) + { + // Disable fields while saving. + $form->setFieldAttribute('linker', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('linker', 'required', 'false'); + } + } + // Modify the form based on Edit Guid access controls. + if ($id != 0 && (!$user->authorise('password.edit.guid', 'com_getbible.password.' . (int) $id)) + || ($id == 0 && !$user->authorise('password.edit.guid', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('guid', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('guid', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('guid')) + { + // Disable fields while saving. + $form->setFieldAttribute('guid', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('guid', 'required', 'false'); + } + } + // Modify the form based on Edit Password access controls. + if ($id != 0 && (!$user->authorise('password.edit.password', 'com_getbible.password.' . (int) $id)) + || ($id == 0 && !$user->authorise('password.edit.password', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('password', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('password', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('password')) + { + // Disable fields while saving. + $form->setFieldAttribute('password', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('password', 'required', 'false'); + } + } + // Modify the from the form based on Password access controls. + if ($id != 0 && (!$user->authorise('password.access.password', 'com_getbible.password.' . (int) $id)) + || ($id == 0 && !$user->authorise('password.access.password', 'com_getbible'))) + { + // Remove the field + $form->removeField('password'); + } + // Modify the form based on View Password access controls. + if ($id != 0 && (!$user->authorise('password.view.password', 'com_getbible.password.' . (int) $id)) + || ($id == 0 && !$user->authorise('password.view.password', 'com_getbible'))) + { + // Make the field hidded. + $form->setFieldAttribute('password', 'type', 'hidden'); + // If there is no value continue. + if (!($val = $form->getValue('password'))) + { + // Disable fields while saving. + $form->setFieldAttribute('password', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('password', 'required', 'false'); + // Make sure + $form->setValue('password', null, ''); + } + elseif (GetbibleHelper::checkArray($val)) + { + // We have to unset then (TODO) + // Hiddend field can not handel array value + // Even if we convert to json we get an error + $form->removeField('password'); + } + } + // Only load these values if no id is found + if (0 == $id) + { + // Set redirected view name + $redirectedView = $jinput->get('ref', null, 'STRING'); + // Set field name (or fall back to view name) + $redirectedField = $jinput->get('field', $redirectedView, 'STRING'); + // Set redirected view id + $redirectedId = $jinput->get('refid', 0, 'INT'); + // Set field id (or fall back to redirected view id) + $redirectedValue = $jinput->get('field_id', $redirectedId, 'INT'); + if (0 != $redirectedValue && $redirectedField) + { + // Now set the local-redirected field default value + $form->setValue($redirectedField, null, $redirectedValue); + } + } + + // Only load the GUID if new item (or empty) + if (0 == $id || !($val = $form->getValue('guid'))) + { + $form->setValue('guid', null, GuidHelper::get()); + } + + return $form; + } + + /** + * Method to get the script that have to be included on the form + * + * @return string script files + */ + public function getScript() + { + return 'media/com_getbible/js/password.js'; + } + + /** + * Method to test whether a record can be deleted. + * + * @param object $record A record object. + * + * @return boolean True if allowed to delete the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canDelete($record) + { + if (!empty($record->id)) + { + if ($record->published != -2) + { + return; + } + + $user = JFactory::getUser(); + // The record has been set. Check the record permissions. + return $user->authorise('password.delete', 'com_getbible.password.' . (int) $record->id); + } + return false; + } + + /** + * Method to test whether a record can have its state edited. + * + * @param object $record A record object. + * + * @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canEditState($record) + { + $user = JFactory::getUser(); + $recordId = (!empty($record->id)) ? $record->id : 0; + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('password.edit.state', 'com_getbible.password.' . (int) $recordId); + if (!$permission && !is_null($permission)) + { + return false; + } + } + // In the absense of better information, revert to the component permissions. + return $user->authorise('password.edit.state', 'com_getbible'); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * @since 2.5 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // Check specific edit permission then general edit permission. + $user = JFactory::getUser(); + + return $user->authorise('password.edit', 'com_getbible.password.'. ((int) isset($data[$key]) ? $data[$key] : 0)) or $user->authorise('password.edit', 'com_getbible'); + } + + /** + * Prepare and sanitise the table data prior to saving. + * + * @param JTable $table A JTable object. + * + * @return void + * + * @since 1.6 + */ + protected function prepareTable($table) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if (isset($table->name)) + { + $table->name = htmlspecialchars_decode($table->name, ENT_QUOTES); + } + + if (isset($table->alias) && empty($table->alias)) + { + $table->generateAlias(); + } + + if (empty($table->id)) + { + $table->created = $date->toSql(); + // set the user + if ($table->created_by == 0 || empty($table->created_by)) + { + $table->created_by = $user->id; + } + // Set ordering to the last item if not set + if (empty($table->ordering)) + { + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select('MAX(ordering)') + ->from($db->quoteName('#__getbible_password')); + $db->setQuery($query); + $max = $db->loadResult(); + + $table->ordering = $max + 1; + } + } + else + { + $table->modified = $date->toSql(); + $table->modified_by = $user->id; + } + + if (!empty($table->id)) + { + // Increment the items version number. + $table->version++; + } + } + + /** + * Method to get the data that should be injected in the form. + * + * @return mixed The data for the form. + * + * @since 1.6 + */ + protected function loadFormData() + { + // Check the session for previously entered form data. + $data = JFactory::getApplication()->getUserState('com_getbible.edit.password.data', array()); + + if (empty($data)) + { + $data = $this->getItem(); + // run the perprocess of the data + $this->preprocessData('com_getbible.password', $data); + } + + return $data; + } + + /** + * Method to get the unique fields of this table. + * + * @return mixed An array of field names, boolean false if none is set. + * + * @since 3.0 + */ + protected function getUniqueFields() + { + return array('guid'); + } + + /** + * Method to delete one or more records. + * + * @param array &$pks An array of record primary keys. + * + * @return boolean True if successful, false if an error occurs. + * + * @since 12.2 + */ + public function delete(&$pks) + { + if (!parent::delete($pks)) + { + return false; + } + + return true; + } + + /** + * Method to change the published state of one or more records. + * + * @param array &$pks A list of the primary keys to change. + * @param integer $value The value of the published state. + * + * @return boolean True on success. + * + * @since 12.2 + */ + public function publish(&$pks, $value = 1) + { + if (!parent::publish($pks, $value)) + { + return false; + } + + return true; + } + + /** + * Method to perform batch operations on an item or a set of items. + * + * @param array $commands An array of commands to perform. + * @param array $pks An array of item ids. + * @param array $contexts An array of item contexts. + * + * @return boolean Returns true on success, false on failure. + * + * @since 12.2 + */ + public function batch($commands, $pks, $contexts) + { + // Sanitize ids. + $pks = array_unique($pks); + ArrayHelper::toInteger($pks); + + // Remove any values of zero. + if (array_search(0, $pks, true)) + { + unset($pks[array_search(0, $pks, true)]); + } + + if (empty($pks)) + { + $this->setError(JText::_('JGLOBAL_NO_ITEM_SELECTED')); + return false; + } + + $done = false; + + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->contentType = new JUcmType; + $this->type = $this->contentType->getTypeByTable($this->tableClassName); + $this->canDo = GetbibleHelper::getActions('password'); + $this->batchSet = true; + + if (!$this->canDo->get('core.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + return false; + } + + if ($this->type == false) + { + $type = new JUcmType; + $this->type = $type->getTypeByAlias($this->typeAlias); + } + + $this->tagsObserver = $this->table->getObserverOfClass('JTableObserverTags'); + + if (!empty($commands['move_copy'])) + { + $cmd = ArrayHelper::getValue($commands, 'move_copy', 'c'); + + if ($cmd == 'c') + { + $result = $this->batchCopy($commands, $pks, $contexts); + + if (is_array($result)) + { + foreach ($result as $old => $new) + { + $contexts[$new] = $contexts[$old]; + } + $pks = array_values($result); + } + else + { + return false; + } + } + elseif ($cmd == 'm' && !$this->batchMove($commands, $pks, $contexts)) + { + return false; + } + + $done = true; + } + + if (!$done) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + + return false; + } + + // Clear the cache + $this->cleanCache(); + + return true; + } + + /** + * Batch copy items to a new category or current. + * + * @param integer $values The new values. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return mixed An array of new IDs on success, boolean false on failure. + * + * @since 12.2 + */ + protected function batchCopy($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('password'); + } + + if (!$this->canDo->get('password.create') && !$this->canDo->get('password.batch')) + { + return false; + } + + // get list of unique fields + $uniqueFields = $this->getUniqueFields(); + // remove move_copy from array + unset($values['move_copy']); + + // make sure published is set + if (!isset($values['published'])) + { + $values['published'] = 0; + } + elseif (isset($values['published']) && !$this->canDo->get('password.edit.state')) + { + $values['published'] = 0; + } + + $newIds = array(); + // Parent exists so let's proceed + while (!empty($pks)) + { + // Pop the first ID off the stack + $pk = array_shift($pks); + + $this->table->reset(); + + // only allow copy if user may edit this item. + if (!$this->user->authorise('password.edit', $contexts[$pk])) + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // Only for strings + if (GetbibleHelper::checkString($this->table->name) && !is_numeric($this->table->name)) + { + $this->table->name = $this->generateUnique('name',$this->table->name); + } + + // insert all set values + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + if (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + // update all unique fields + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $this->table->$uniqueField = $this->generateUnique($uniqueField,$this->table->$uniqueField); + } + } + + // Reset the ID because we are making a copy + $this->table->id = 0; + + // TODO: Deal with ordering? + // $this->table->ordering = 1; + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + + // Get the new item ID + $newId = $this->table->get('id'); + + // Add the new ID to the array + $newIds[$pk] = $newId; + } + + // Clean the cache + $this->cleanCache(); + + return $newIds; + } + + /** + * Batch move items to a new category + * + * @param integer $value The new category ID. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 12.2 + */ + protected function batchMove($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('password'); + } + + if (!$this->canDo->get('password.edit') && !$this->canDo->get('password.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // make sure published only updates if user has the permission. + if (isset($values['published']) && !$this->canDo->get('password.edit.state')) + { + unset($values['published']); + } + // remove move_copy from array + unset($values['move_copy']); + + // Parent exists so we proceed + foreach ($pks as $pk) + { + if (!$this->user->authorise('password.edit', $contexts[$pk])) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // insert all set values. + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + // Do special action for access. + if ('access' === $key && strlen($value) > 0) + { + $this->table->$key = $value; + } + elseif (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + } + + // Clean the cache + $this->cleanCache(); + + return true; + } + + /** + * Method to save the form data. + * + * @param array $data The form data. + * + * @return boolean True on success. + * + * @since 1.6 + */ + public function save($data) + { + $input = JFactory::getApplication()->input; + $filter = JFilterInput::getInstance(); + + // set the metadata to the Item Data + if (isset($data['metadata']) && isset($data['metadata']['author'])) + { + $data['metadata']['author'] = $filter->clean($data['metadata']['author'], 'TRIM'); + + $metadata = new JRegistry; + $metadata->loadArray($data['metadata']); + $data['metadata'] = (string) $metadata; + } + + + // Set the GUID if empty or not valid + if (empty($data['guid']) && $data['id'] > 0) + { + // get the existing one + $data['guid'] = (string) GetHelper::var('password', $data['id'], 'id', 'guid'); + } + + // Set the GUID if empty or not valid + while (!GuidHelper::valid($data['guid'], "password", $data['id'])) + { + // must always be set + $data['guid'] = (string) GuidHelper::get(); + } + + // Set the Params Items to data + if (isset($data['params']) && is_array($data['params'])) + { + $params = new JRegistry; + $params->loadArray($data['params']); + $data['params'] = (string) $params; + } + + // Alter the unique field for save as copy + if ($input->get('task') === 'save2copy') + { + // Automatic handling of other unique fields + $uniqueFields = $this->getUniqueFields(); + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $data[$uniqueField] = $this->generateUnique($uniqueField,$data[$uniqueField]); + } + } + } + + if (parent::save($data)) + { + return true; + } + return false; + } + + /** + * Method to generate a unique value. + * + * @param string $field name. + * @param string $value data. + * + * @return string New value. + * + * @since 3.0 + */ + protected function generateUnique($field,$value) + { + + // set field value unique + $table = $this->getTable(); + + while ($table->load(array($field => $value))) + { + $value = StringHelper::increment($value); + } + + return $value; + } + + /** + * Method to change the title + * + * @param string $title The title. + * + * @return array Contains the modified title and alias. + * + */ + protected function _generateNewTitle($title) + { + + // Alter the title + $table = $this->getTable(); + + while ($table->load(array('title' => $title))) + { + $title = StringHelper::increment($title); + } + + return $title; + } +} diff --git a/admin/models/passwords.php b/admin/models/passwords.php new file mode 100644 index 0000000..2eadcbb --- /dev/null +++ b/admin/models/passwords.php @@ -0,0 +1,354 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\ListModel; +use Joomla\Utilities\ArrayHelper; + +/** + * Passwords List Model + */ +class GetbibleModelPasswords extends ListModel +{ + public function __construct($config = array()) + { + if (empty($config['filter_fields'])) + { + $config['filter_fields'] = array( + 'a.id','id', + 'a.published','published', + 'a.access','access', + 'a.ordering','ordering', + 'a.created_by','created_by', + 'a.modified_by','modified_by', + 'a.name','name', + 'g.name','linker' + ); + } + + parent::__construct($config); + } + + /** + * Method to auto-populate the model state. + * + * Note. Calling getState in this method will result in recursion. + * + * @param string $ordering An optional ordering field. + * @param string $direction An optional direction (asc|desc). + * + * @return void + * + */ + protected function populateState($ordering = null, $direction = null) + { + $app = JFactory::getApplication(); + + // Adjust the context to support modal layouts. + if ($layout = $app->input->get('layout')) + { + $this->context .= '.' . $layout; + } + + // Check if the form was submitted + $formSubmited = $app->input->post->get('form_submited'); + + $access = $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', 0, 'int'); + if ($formSubmited) + { + $access = $app->input->post->get('access'); + $this->setState('filter.access', $access); + } + + $published = $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', ''); + $this->setState('filter.published', $published); + + $created_by = $this->getUserStateFromRequest($this->context . '.filter.created_by', 'filter_created_by', ''); + $this->setState('filter.created_by', $created_by); + + $created = $this->getUserStateFromRequest($this->context . '.filter.created', 'filter_created'); + $this->setState('filter.created', $created); + + $sorting = $this->getUserStateFromRequest($this->context . '.filter.sorting', 'filter_sorting', 0, 'int'); + $this->setState('filter.sorting', $sorting); + + $search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search'); + $this->setState('filter.search', $search); + + $name = $this->getUserStateFromRequest($this->context . '.filter.name', 'filter_name'); + if ($formSubmited) + { + $name = $app->input->post->get('name'); + $this->setState('filter.name', $name); + } + + $linker = $this->getUserStateFromRequest($this->context . '.filter.linker', 'filter_linker'); + if ($formSubmited) + { + $linker = $app->input->post->get('linker'); + $this->setState('filter.linker', $linker); + } + + // List state information. + parent::populateState($ordering, $direction); + } + + /** + * Method to get an array of data items. + * + * @return mixed An array of data items on success, false on failure. + */ + public function getItems() + { + // Check in items + $this->checkInNow(); + + // load parent items + $items = parent::getItems(); + + // Set values to display correctly. + if (GetbibleHelper::checkArray($items)) + { + // Get the user object if not set. + if (!isset($user) || !GetbibleHelper::checkObject($user)) + { + $user = JFactory::getUser(); + } + foreach ($items as $nr => &$item) + { + // Remove items the user can't access. + $access = ($user->authorise('password.access', 'com_getbible.password.' . (int) $item->id) && $user->authorise('password.access', 'com_getbible')); + if (!$access) + { + unset($items[$nr]); + continue; + } + + } + } + + // return items + return $items; + } + + /** + * Method to build an SQL query to load the list data. + * + * @return string An SQL query + */ + protected function getListQuery() + { + // Get the user object. + $user = JFactory::getUser(); + // Create a new query object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + + // Select some fields + $query->select('a.*'); + + // From the getbible_item table + $query->from($db->quoteName('#__getbible_password', 'a')); + + // From the getbible_linker table. + $query->select($db->quoteName(['g.name','g.id'],['linker_name','linker_id'])); + $query->join('LEFT', $db->quoteName('#__getbible_linker', 'g') . ' ON (' . $db->quoteName('a.linker') . ' = ' . $db->quoteName('g.guid') . ')'); + + // Filter by published state + $published = $this->getState('filter.published'); + if (is_numeric($published)) + { + $query->where('a.published = ' . (int) $published); + } + elseif ($published === '') + { + $query->where('(a.published = 0 OR a.published = 1)'); + } + + // Join over the asset groups. + $query->select('ag.title AS access_level'); + $query->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access'); + // Filter by access level. + $_access = $this->getState('filter.access'); + if ($_access && is_numeric($_access)) + { + $query->where('a.access = ' . (int) $_access); + } + elseif (GetbibleHelper::checkArray($_access)) + { + // Secure the array for the query + $_access = ArrayHelper::toInteger($_access); + // Filter by the Access Array. + $query->where('a.access IN (' . implode(',', $_access) . ')'); + } + // Implement View Level Access + if (!$user->authorise('core.options', 'com_getbible')) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + // Filter by search. + $search = $this->getState('filter.search'); + if (!empty($search)) + { + if (stripos($search, 'id:') === 0) + { + $query->where('a.id = ' . (int) substr($search, 3)); + } + else + { + $search = $db->quote('%' . $db->escape($search) . '%'); + $query->where('(a.name LIKE '.$search.' OR a.linker LIKE '.$search.' OR g.name LIKE '.$search.')'); + } + } + + // Filter by Name. + $_name = $this->getState('filter.name'); + if (is_numeric($_name)) + { + if (is_float($_name)) + { + $query->where('a.name = ' . (float) $_name); + } + else + { + $query->where('a.name = ' . (int) $_name); + } + } + elseif (GetbibleHelper::checkString($_name)) + { + $query->where('a.name = ' . $db->quote($db->escape($_name))); + } + // Filter by Linker. + $_linker = $this->getState('filter.linker'); + if (is_numeric($_linker)) + { + if (is_float($_linker)) + { + $query->where('a.linker = ' . (float) $_linker); + } + else + { + $query->where('a.linker = ' . (int) $_linker); + } + } + elseif (GetbibleHelper::checkString($_linker)) + { + $query->where('a.linker = ' . $db->quote($db->escape($_linker))); + } + + // Add the list ordering clause. + $orderCol = $this->state->get('list.ordering', 'a.id'); + $orderDirn = $this->state->get('list.direction', 'desc'); + if ($orderCol != '') + { + $query->order($db->escape($orderCol . ' ' . $orderDirn)); + } + + return $query; + } + + /** + * Method to get a store id based on model configuration state. + * + * @return string A store id. + * + */ + protected function getStoreId($id = '') + { + // Compile the store id. + $id .= ':' . $this->getState('filter.id'); + $id .= ':' . $this->getState('filter.search'); + $id .= ':' . $this->getState('filter.published'); + // Check if the value is an array + $_access = $this->getState('filter.access'); + if (GetbibleHelper::checkArray($_access)) + { + $id .= ':' . implode(':', $_access); + } + // Check if this is only an number or string + elseif (is_numeric($_access) + || GetbibleHelper::checkString($_access)) + { + $id .= ':' . $_access; + } + $id .= ':' . $this->getState('filter.ordering'); + $id .= ':' . $this->getState('filter.created_by'); + $id .= ':' . $this->getState('filter.modified_by'); + $id .= ':' . $this->getState('filter.name'); + $id .= ':' . $this->getState('filter.linker'); + + return parent::getStoreId($id); + } + + /** + * Build an SQL query to checkin all items left checked out longer then a set time. + * + * @return a bool + * + */ + protected function checkInNow() + { + // Get set check in time + $time = JComponentHelper::getParams('com_getbible')->get('check_in'); + + if ($time) + { + + // Get a db connection. + $db = JFactory::getDbo(); + // Reset query. + $query = $db->getQuery(true); + $query->select('*'); + $query->from($db->quoteName('#__getbible_password')); + // Only select items that are checked out. + $query->where($db->quoteName('checked_out') . '!=0'); + $db->setQuery($query, 0, 1); + $db->execute(); + if ($db->getNumRows()) + { + // Get Yesterdays date. + $date = JFactory::getDate()->modify($time)->toSql(); + // Reset query. + $query = $db->getQuery(true); + + // Fields to update. + $fields = array( + $db->quoteName('checked_out_time') . '=\'0000-00-00 00:00:00\'', + $db->quoteName('checked_out') . '=0' + ); + + // Conditions for which records should be updated. + $conditions = array( + $db->quoteName('checked_out') . '!=0', + $db->quoteName('checked_out_time') . '<\''.$date.'\'' + ); + + // Check table. + $query->update($db->quoteName('#__getbible_password'))->set($fields)->where($conditions); + + $db->setQuery($query); + + $db->execute(); + } + } + + return false; + } +} diff --git a/admin/models/prompt.php b/admin/models/prompt.php new file mode 100644 index 0000000..4b1ef8b --- /dev/null +++ b/admin/models/prompt.php @@ -0,0 +1,1397 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\AdminModel; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; +use VDM\Joomla\Utilities\GuidHelper; +use VDM\Joomla\Utilities\GetHelper; + +/** + * Getbible Prompt Admin Model + */ +class GetbibleModelPrompt extends AdminModel +{ + /** + * The tab layout fields array. + * + * @var array + */ + protected $tabLayoutFields = array( + 'prompt' => array( + 'left' => array( + 'integration', + 'integration_note', + 'cache_behaviour', + 'cache_persistently_expansive_caching_note', + 'cache_basic_note', + 'cache_advance_note' + ), + 'right' => array( + 'cache_capacity', + 'cache_capacity_note', + 'response_retrieval', + 'response_retrieval_note' + ), + 'fullwidth' => array( + 'openai_prompts_placeholders_basic_caching_note', + 'openai_prompts_placeholders_advanced_caching_note', + 'openai_prompts_placeholders_none_caching_note', + 'messages' + ), + 'above' => array( + 'name', + 'abbreviation' + ) + ), + 'open_ai' => array( + 'left' => array( + 'max_tokens_override', + 'max_tokens', + 'max_tokens_note', + 'temperature_override', + 'temperature', + 'temperature_note', + 'top_p_override', + 'top_p', + 'top_p_note', + 'n_override', + 'n', + 'n_note' + ), + 'right' => array( + 'token_override', + 'token', + 'ai_org_token_override', + 'org_token', + 'model', + 'openai_documentation_note', + 'presence_penalty_override', + 'presence_penalty', + 'presence_penalty_note', + 'frequency_penalty_override', + 'frequency_penalty', + 'frequency_penalty_note' + ) + ) + ); + + /** + * @var string The prefix to use with controller messages. + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE'; + + /** + * The type alias for this content type. + * + * @var string + * @since 3.2 + */ + public $typeAlias = 'com_getbible.prompt'; + + /** + * Returns a Table object, always creating it + * + * @param type $type The table type to instantiate + * @param string $prefix A prefix for the table class name. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JTable A database object + * + * @since 1.6 + */ + public function getTable($type = 'prompt', $prefix = 'GetbibleTable', $config = array()) + { + // add table path for when model gets used from other component + $this->addTablePath(JPATH_ADMINISTRATOR . '/components/com_getbible/tables'); + // get instance of the table + return JTable::getInstance($type, $prefix, $config); + } + + /** + * Method to get a single record. + * + * @param integer $pk The id of the primary key. + * + * @return mixed Object on success, false on failure. + * + * @since 1.6 + */ + public function getItem($pk = null) + { + if ($item = parent::getItem($pk)) + { + if (!empty($item->params) && !is_array($item->params)) + { + // Convert the params field to an array. + $registry = new Registry; + $registry->loadString($item->params); + $item->params = $registry->toArray(); + } + + if (!empty($item->metadata)) + { + // Convert the metadata field to an array. + $registry = new Registry; + $registry->loadString($item->metadata); + $item->metadata = $registry->toArray(); + } + + if (!empty($item->messages)) + { + // Convert the messages field to an array. + $messages = new Registry; + $messages->loadString($item->messages); + $item->messages = $messages->toArray(); + } + } + + return $item; + } + + /** + * Method to get the record form. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * @param array $options Optional array of options for the form creation. + * + * @return mixed A JForm object on success, false on failure + * + * @since 1.6 + */ + public function getForm($data = array(), $loadData = true, $options = array('control' => 'jform')) + { + // set load data option + $options['load_data'] = $loadData; + // check if xpath was set in options + $xpath = false; + if (isset($options['xpath'])) + { + $xpath = $options['xpath']; + unset($options['xpath']); + } + // check if clear form was set in options + $clear = false; + if (isset($options['clear'])) + { + $clear = $options['clear']; + unset($options['clear']); + } + + // Get the form. + $form = $this->loadForm('com_getbible.prompt', 'prompt', $options, $clear, $xpath); + + if (empty($form)) + { + return false; + } + + $jinput = JFactory::getApplication()->input; + + // The front end calls this model and uses a_id to avoid id clashes so we need to check for that first. + if ($jinput->get('a_id')) + { + $id = $jinput->get('a_id', 0, 'INT'); + } + // The back end uses id so we use that the rest of the time and set it to 0 by default. + else + { + $id = $jinput->get('id', 0, 'INT'); + } + + $user = JFactory::getUser(); + + // Check for existing item. + // Modify the form based on Edit State access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.state', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.state', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('ordering', 'disabled', 'true'); + $form->setFieldAttribute('published', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('ordering', 'filter', 'unset'); + $form->setFieldAttribute('published', 'filter', 'unset'); + } + // If this is a new item insure the greated by is set. + if (0 == $id) + { + // Set the created_by to this user + $form->setValue('created_by', null, $user->id); + } + // Modify the form based on Edit Creaded By access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.created_by', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.created_by', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created_by', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('created_by', 'readonly', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created_by', 'filter', 'unset'); + } + // Modify the form based on Edit Creaded Date access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.created', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.created', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created', 'filter', 'unset'); + } + // Modify the form based on Edit Name access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.name', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.name', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('name', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('name', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('name')) + { + // Disable fields while saving. + $form->setFieldAttribute('name', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('name', 'required', 'false'); + } + } + // Modify the form based on Edit Integration access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.integration', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.integration', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('integration', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('integration', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('integration')) + { + // Disable fields while saving. + $form->setFieldAttribute('integration', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('integration', 'required', 'false'); + } + } + // Modify the form based on Edit Cache Behaviour access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.cache_behaviour', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.cache_behaviour', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('cache_behaviour', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('cache_behaviour', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('cache_behaviour')) + { + // Disable fields while saving. + $form->setFieldAttribute('cache_behaviour', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('cache_behaviour', 'required', 'false'); + } + } + // Modify the form based on Edit Abbreviation access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.abbreviation', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.abbreviation', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('abbreviation', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('abbreviation', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('abbreviation')) + { + // Disable fields while saving. + $form->setFieldAttribute('abbreviation', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('abbreviation', 'required', 'false'); + } + } + // Modify the form based on Edit Guid access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.guid', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.guid', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('guid', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('guid', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('guid')) + { + // Disable fields while saving. + $form->setFieldAttribute('guid', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('guid', 'required', 'false'); + } + } + // Modify the form based on Edit Model access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.model', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.model', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('model', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('model', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('model')) + { + // Disable fields while saving. + $form->setFieldAttribute('model', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('model', 'required', 'false'); + } + } + // Modify the form based on Edit Presence Penalty access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.presence_penalty', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.presence_penalty', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('presence_penalty', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('presence_penalty', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('presence_penalty')) + { + // Disable fields while saving. + $form->setFieldAttribute('presence_penalty', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('presence_penalty', 'required', 'false'); + } + } + // Modify the form based on Edit Org Token access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.org_token', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.org_token', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('org_token', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('org_token', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('org_token')) + { + // Disable fields while saving. + $form->setFieldAttribute('org_token', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('org_token', 'required', 'false'); + } + } + // Modify the form based on Edit Token access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.token', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.token', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('token', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('token', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('token')) + { + // Disable fields while saving. + $form->setFieldAttribute('token', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('token', 'required', 'false'); + } + } + // Modify the form based on Edit N Override access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.n_override', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.n_override', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('n_override', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('n_override', 'readonly', 'true'); + // Disable radio button for display. + $class = $form->getFieldAttribute('n_override', 'class', ''); + $form->setFieldAttribute('n_override', 'class', $class.' disabled no-click'); + // If there is no value continue. + if (!$form->getValue('n_override')) + { + // Disable fields while saving. + $form->setFieldAttribute('n_override', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('n_override', 'required', 'false'); + } + } + // Modify the form based on Edit Messages access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.messages', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.messages', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('messages', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('messages', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('messages')) + { + // Disable fields while saving. + $form->setFieldAttribute('messages', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('messages', 'required', 'false'); + } + } + // Modify the form based on Edit Response Retrieval access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.response_retrieval', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.response_retrieval', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('response_retrieval', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('response_retrieval', 'readonly', 'true'); + // Disable radio button for display. + $class = $form->getFieldAttribute('response_retrieval', 'class', ''); + $form->setFieldAttribute('response_retrieval', 'class', $class.' disabled no-click'); + // If there is no value continue. + if (!$form->getValue('response_retrieval')) + { + // Disable fields while saving. + $form->setFieldAttribute('response_retrieval', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('response_retrieval', 'required', 'false'); + } + } + // Modify the form based on Edit Frequency Penalty Override access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.frequency_penalty_override', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.frequency_penalty_override', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('frequency_penalty_override', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('frequency_penalty_override', 'readonly', 'true'); + // Disable radio button for display. + $class = $form->getFieldAttribute('frequency_penalty_override', 'class', ''); + $form->setFieldAttribute('frequency_penalty_override', 'class', $class.' disabled no-click'); + // If there is no value continue. + if (!$form->getValue('frequency_penalty_override')) + { + // Disable fields while saving. + $form->setFieldAttribute('frequency_penalty_override', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('frequency_penalty_override', 'required', 'false'); + } + } + // Modify the form based on Edit N access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.n', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.n', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('n', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('n', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('n')) + { + // Disable fields while saving. + $form->setFieldAttribute('n', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('n', 'required', 'false'); + } + } + // Modify the form based on Edit Max Tokens Override access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.max_tokens_override', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.max_tokens_override', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('max_tokens_override', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('max_tokens_override', 'readonly', 'true'); + // Disable radio button for display. + $class = $form->getFieldAttribute('max_tokens_override', 'class', ''); + $form->setFieldAttribute('max_tokens_override', 'class', $class.' disabled no-click'); + // If there is no value continue. + if (!$form->getValue('max_tokens_override')) + { + // Disable fields while saving. + $form->setFieldAttribute('max_tokens_override', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('max_tokens_override', 'required', 'false'); + } + } + // Modify the form based on Edit Token Override access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.token_override', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.token_override', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('token_override', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('token_override', 'readonly', 'true'); + // Disable radio button for display. + $class = $form->getFieldAttribute('token_override', 'class', ''); + $form->setFieldAttribute('token_override', 'class', $class.' disabled no-click'); + // If there is no value continue. + if (!$form->getValue('token_override')) + { + // Disable fields while saving. + $form->setFieldAttribute('token_override', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('token_override', 'required', 'false'); + } + } + // Modify the form based on Edit Max Tokens access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.max_tokens', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.max_tokens', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('max_tokens', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('max_tokens', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('max_tokens')) + { + // Disable fields while saving. + $form->setFieldAttribute('max_tokens', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('max_tokens', 'required', 'false'); + } + } + // Modify the form based on Edit Ai Org Token Override access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.ai_org_token_override', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.ai_org_token_override', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('ai_org_token_override', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('ai_org_token_override', 'readonly', 'true'); + // Disable radio button for display. + $class = $form->getFieldAttribute('ai_org_token_override', 'class', ''); + $form->setFieldAttribute('ai_org_token_override', 'class', $class.' disabled no-click'); + // If there is no value continue. + if (!$form->getValue('ai_org_token_override')) + { + // Disable fields while saving. + $form->setFieldAttribute('ai_org_token_override', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('ai_org_token_override', 'required', 'false'); + } + } + // Modify the from the form based on Temperature Override access controls. + if ($id != 0 && (!$user->authorise('prompt.access.temperature_override', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.access.temperature_override', 'com_getbible'))) + { + // Remove the field + $form->removeField('temperature_override'); + } + // Modify the form based on Edit Presence Penalty Override access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.presence_penalty_override', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.presence_penalty_override', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('presence_penalty_override', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('presence_penalty_override', 'readonly', 'true'); + // Disable radio button for display. + $class = $form->getFieldAttribute('presence_penalty_override', 'class', ''); + $form->setFieldAttribute('presence_penalty_override', 'class', $class.' disabled no-click'); + // If there is no value continue. + if (!$form->getValue('presence_penalty_override')) + { + // Disable fields while saving. + $form->setFieldAttribute('presence_penalty_override', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('presence_penalty_override', 'required', 'false'); + } + } + // Modify the form based on Edit Top P Override access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.top_p_override', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.top_p_override', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('top_p_override', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('top_p_override', 'readonly', 'true'); + // Disable radio button for display. + $class = $form->getFieldAttribute('top_p_override', 'class', ''); + $form->setFieldAttribute('top_p_override', 'class', $class.' disabled no-click'); + // If there is no value continue. + if (!$form->getValue('top_p_override')) + { + // Disable fields while saving. + $form->setFieldAttribute('top_p_override', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('top_p_override', 'required', 'false'); + } + } + // Modify the form based on Edit Frequency Penalty access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.frequency_penalty', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.frequency_penalty', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('frequency_penalty', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('frequency_penalty', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('frequency_penalty')) + { + // Disable fields while saving. + $form->setFieldAttribute('frequency_penalty', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('frequency_penalty', 'required', 'false'); + } + } + // Modify the form based on Edit Top P access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.top_p', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.top_p', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('top_p', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('top_p', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('top_p')) + { + // Disable fields while saving. + $form->setFieldAttribute('top_p', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('top_p', 'required', 'false'); + } + } + // Modify the form based on Edit Temperature access controls. + if ($id != 0 && (!$user->authorise('prompt.edit.temperature', 'com_getbible.prompt.' . (int) $id)) + || ($id == 0 && !$user->authorise('prompt.edit.temperature', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('temperature', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('temperature', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('temperature')) + { + // Disable fields while saving. + $form->setFieldAttribute('temperature', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('temperature', 'required', 'false'); + } + } + // Only load these values if no id is found + if (0 == $id) + { + // Set redirected view name + $redirectedView = $jinput->get('ref', null, 'STRING'); + // Set field name (or fall back to view name) + $redirectedField = $jinput->get('field', $redirectedView, 'STRING'); + // Set redirected view id + $redirectedId = $jinput->get('refid', 0, 'INT'); + // Set field id (or fall back to redirected view id) + $redirectedValue = $jinput->get('field_id', $redirectedId, 'INT'); + if (0 != $redirectedValue && $redirectedField) + { + // Now set the local-redirected field default value + $form->setValue($redirectedField, null, $redirectedValue); + } + } + + // Only load the GUID if new item (or empty) + if (0 == $id || !($val = $form->getValue('guid'))) + { + $form->setValue('guid', null, GuidHelper::get()); + } + + return $form; + } + + /** + * Method to get the script that have to be included on the form + * + * @return string script files + */ + public function getScript() + { + return 'media/com_getbible/js/prompt.js'; + } + + /** + * Method to test whether a record can be deleted. + * + * @param object $record A record object. + * + * @return boolean True if allowed to delete the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canDelete($record) + { + if (!empty($record->id)) + { + if ($record->published != -2) + { + return; + } + + $user = JFactory::getUser(); + // The record has been set. Check the record permissions. + return $user->authorise('prompt.delete', 'com_getbible.prompt.' . (int) $record->id); + } + return false; + } + + /** + * Method to test whether a record can have its state edited. + * + * @param object $record A record object. + * + * @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canEditState($record) + { + $user = JFactory::getUser(); + $recordId = (!empty($record->id)) ? $record->id : 0; + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('prompt.edit.state', 'com_getbible.prompt.' . (int) $recordId); + if (!$permission && !is_null($permission)) + { + return false; + } + } + // In the absense of better information, revert to the component permissions. + return $user->authorise('prompt.edit.state', 'com_getbible'); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * @since 2.5 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // Check specific edit permission then general edit permission. + $user = JFactory::getUser(); + + return $user->authorise('prompt.edit', 'com_getbible.prompt.'. ((int) isset($data[$key]) ? $data[$key] : 0)) or $user->authorise('prompt.edit', 'com_getbible'); + } + + /** + * Prepare and sanitise the table data prior to saving. + * + * @param JTable $table A JTable object. + * + * @return void + * + * @since 1.6 + */ + protected function prepareTable($table) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if (isset($table->name)) + { + $table->name = htmlspecialchars_decode($table->name, ENT_QUOTES); + } + + if (isset($table->alias) && empty($table->alias)) + { + $table->generateAlias(); + } + + if (empty($table->id)) + { + $table->created = $date->toSql(); + // set the user + if ($table->created_by == 0 || empty($table->created_by)) + { + $table->created_by = $user->id; + } + // Set ordering to the last item if not set + if (empty($table->ordering)) + { + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select('MAX(ordering)') + ->from($db->quoteName('#__getbible_prompt')); + $db->setQuery($query); + $max = $db->loadResult(); + + $table->ordering = $max + 1; + } + } + else + { + $table->modified = $date->toSql(); + $table->modified_by = $user->id; + } + + if (!empty($table->id)) + { + // Increment the items version number. + $table->version++; + } + } + + /** + * Method to get the data that should be injected in the form. + * + * @return mixed The data for the form. + * + * @since 1.6 + */ + protected function loadFormData() + { + // Check the session for previously entered form data. + $data = JFactory::getApplication()->getUserState('com_getbible.edit.prompt.data', array()); + + if (empty($data)) + { + $data = $this->getItem(); + // run the perprocess of the data + $this->preprocessData('com_getbible.prompt', $data); + } + + return $data; + } + + /** + * Method to get the unique fields of this table. + * + * @return mixed An array of field names, boolean false if none is set. + * + * @since 3.0 + */ + protected function getUniqueFields() + { + return array('guid'); + } + + /** + * Method to delete one or more records. + * + * @param array &$pks An array of record primary keys. + * + * @return boolean True if successful, false if an error occurs. + * + * @since 12.2 + */ + public function delete(&$pks) + { + if (!parent::delete($pks)) + { + return false; + } + + return true; + } + + /** + * Method to change the published state of one or more records. + * + * @param array &$pks A list of the primary keys to change. + * @param integer $value The value of the published state. + * + * @return boolean True on success. + * + * @since 12.2 + */ + public function publish(&$pks, $value = 1) + { + if (!parent::publish($pks, $value)) + { + return false; + } + + return true; + } + + /** + * Method to perform batch operations on an item or a set of items. + * + * @param array $commands An array of commands to perform. + * @param array $pks An array of item ids. + * @param array $contexts An array of item contexts. + * + * @return boolean Returns true on success, false on failure. + * + * @since 12.2 + */ + public function batch($commands, $pks, $contexts) + { + // Sanitize ids. + $pks = array_unique($pks); + ArrayHelper::toInteger($pks); + + // Remove any values of zero. + if (array_search(0, $pks, true)) + { + unset($pks[array_search(0, $pks, true)]); + } + + if (empty($pks)) + { + $this->setError(JText::_('JGLOBAL_NO_ITEM_SELECTED')); + return false; + } + + $done = false; + + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->contentType = new JUcmType; + $this->type = $this->contentType->getTypeByTable($this->tableClassName); + $this->canDo = GetbibleHelper::getActions('prompt'); + $this->batchSet = true; + + if (!$this->canDo->get('core.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + return false; + } + + if ($this->type == false) + { + $type = new JUcmType; + $this->type = $type->getTypeByAlias($this->typeAlias); + } + + $this->tagsObserver = $this->table->getObserverOfClass('JTableObserverTags'); + + if (!empty($commands['move_copy'])) + { + $cmd = ArrayHelper::getValue($commands, 'move_copy', 'c'); + + if ($cmd == 'c') + { + $result = $this->batchCopy($commands, $pks, $contexts); + + if (is_array($result)) + { + foreach ($result as $old => $new) + { + $contexts[$new] = $contexts[$old]; + } + $pks = array_values($result); + } + else + { + return false; + } + } + elseif ($cmd == 'm' && !$this->batchMove($commands, $pks, $contexts)) + { + return false; + } + + $done = true; + } + + if (!$done) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + + return false; + } + + // Clear the cache + $this->cleanCache(); + + return true; + } + + /** + * Batch copy items to a new category or current. + * + * @param integer $values The new values. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return mixed An array of new IDs on success, boolean false on failure. + * + * @since 12.2 + */ + protected function batchCopy($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('prompt'); + } + + if (!$this->canDo->get('prompt.create') && !$this->canDo->get('prompt.batch')) + { + return false; + } + + // get list of unique fields + $uniqueFields = $this->getUniqueFields(); + // remove move_copy from array + unset($values['move_copy']); + + // make sure published is set + if (!isset($values['published'])) + { + $values['published'] = 0; + } + elseif (isset($values['published']) && !$this->canDo->get('prompt.edit.state')) + { + $values['published'] = 0; + } + + $newIds = array(); + // Parent exists so let's proceed + while (!empty($pks)) + { + // Pop the first ID off the stack + $pk = array_shift($pks); + + $this->table->reset(); + + // only allow copy if user may edit this item. + if (!$this->user->authorise('prompt.edit', $contexts[$pk])) + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // Only for strings + if (GetbibleHelper::checkString($this->table->name) && !is_numeric($this->table->name)) + { + $this->table->name = $this->generateUnique('name',$this->table->name); + } + + // insert all set values + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + if (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + // update all unique fields + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $this->table->$uniqueField = $this->generateUnique($uniqueField,$this->table->$uniqueField); + } + } + + // Reset the ID because we are making a copy + $this->table->id = 0; + + // TODO: Deal with ordering? + // $this->table->ordering = 1; + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + + // Get the new item ID + $newId = $this->table->get('id'); + + // Add the new ID to the array + $newIds[$pk] = $newId; + } + + // Clean the cache + $this->cleanCache(); + + return $newIds; + } + + /** + * Batch move items to a new category + * + * @param integer $value The new category ID. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 12.2 + */ + protected function batchMove($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('prompt'); + } + + if (!$this->canDo->get('prompt.edit') && !$this->canDo->get('prompt.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // make sure published only updates if user has the permission. + if (isset($values['published']) && !$this->canDo->get('prompt.edit.state')) + { + unset($values['published']); + } + // remove move_copy from array + unset($values['move_copy']); + + // Parent exists so we proceed + foreach ($pks as $pk) + { + if (!$this->user->authorise('prompt.edit', $contexts[$pk])) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // insert all set values. + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + // Do special action for access. + if ('access' === $key && strlen($value) > 0) + { + $this->table->$key = $value; + } + elseif (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + } + + // Clean the cache + $this->cleanCache(); + + return true; + } + + /** + * Method to save the form data. + * + * @param array $data The form data. + * + * @return boolean True on success. + * + * @since 1.6 + */ + public function save($data) + { + $input = JFactory::getApplication()->input; + $filter = JFilterInput::getInstance(); + + // set the metadata to the Item Data + if (isset($data['metadata']) && isset($data['metadata']['author'])) + { + $data['metadata']['author'] = $filter->clean($data['metadata']['author'], 'TRIM'); + + $metadata = new JRegistry; + $metadata->loadArray($data['metadata']); + $data['metadata'] = (string) $metadata; + } + + + // Set the GUID if empty or not valid + if (empty($data['guid']) && $data['id'] > 0) + { + // get the existing one + $data['guid'] = (string) GetHelper::var('prompt', $data['id'], 'id', 'guid'); + } + + // Set the GUID if empty or not valid + while (!GuidHelper::valid($data['guid'], "prompt", $data['id'])) + { + // must always be set + $data['guid'] = (string) GuidHelper::get(); + } + + // Set the messages items to data. + if (isset($data['messages']) && is_array($data['messages'])) + { + $messages = new JRegistry; + $messages->loadArray($data['messages']); + $data['messages'] = (string) $messages; + } + // Also check permission since the value may be removed due to permissions + // Then we do not want to clear it out, but simple ignore the empty messages + elseif (!isset($data['messages']) + && JFactory::getUser()->authorise('prompt.edit.messages', 'com_getbible')) + { + // Set the empty messages to data + $data['messages'] = ''; + } + + // Set the Params Items to data + if (isset($data['params']) && is_array($data['params'])) + { + $params = new JRegistry; + $params->loadArray($data['params']); + $data['params'] = (string) $params; + } + + // Alter the unique field for save as copy + if ($input->get('task') === 'save2copy') + { + // Automatic handling of other unique fields + $uniqueFields = $this->getUniqueFields(); + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $data[$uniqueField] = $this->generateUnique($uniqueField,$data[$uniqueField]); + } + } + } + + if (parent::save($data)) + { + return true; + } + return false; + } + + /** + * Method to generate a unique value. + * + * @param string $field name. + * @param string $value data. + * + * @return string New value. + * + * @since 3.0 + */ + protected function generateUnique($field,$value) + { + + // set field value unique + $table = $this->getTable(); + + while ($table->load(array($field => $value))) + { + $value = StringHelper::increment($value); + } + + return $value; + } + + /** + * Method to change the title + * + * @param string $title The title. + * + * @return array Contains the modified title and alias. + * + */ + protected function _generateNewTitle($title) + { + + // Alter the title + $table = $this->getTable(); + + while ($table->load(array('title' => $title))) + { + $title = StringHelper::increment($title); + } + + return $title; + } +} diff --git a/admin/models/prompts.php b/admin/models/prompts.php new file mode 100644 index 0000000..84776e3 --- /dev/null +++ b/admin/models/prompts.php @@ -0,0 +1,488 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\ListModel; +use Joomla\Utilities\ArrayHelper; + +/** + * Prompts List Model + */ +class GetbibleModelPrompts extends ListModel +{ + public function __construct($config = array()) + { + if (empty($config['filter_fields'])) + { + $config['filter_fields'] = array( + 'a.id','id', + 'a.published','published', + 'a.access','access', + 'a.ordering','ordering', + 'a.created_by','created_by', + 'a.modified_by','modified_by', + 'a.name','name', + 'a.cache_behaviour','cache_behaviour', + 'g.translation','abbreviation', + 'a.model','model', + 'a.integration','integration' + ); + } + + parent::__construct($config); + } + + /** + * Method to auto-populate the model state. + * + * Note. Calling getState in this method will result in recursion. + * + * @param string $ordering An optional ordering field. + * @param string $direction An optional direction (asc|desc). + * + * @return void + * + */ + protected function populateState($ordering = null, $direction = null) + { + $app = JFactory::getApplication(); + + // Adjust the context to support modal layouts. + if ($layout = $app->input->get('layout')) + { + $this->context .= '.' . $layout; + } + + // Check if the form was submitted + $formSubmited = $app->input->post->get('form_submited'); + + $access = $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', 0, 'int'); + if ($formSubmited) + { + $access = $app->input->post->get('access'); + $this->setState('filter.access', $access); + } + + $published = $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', ''); + $this->setState('filter.published', $published); + + $created_by = $this->getUserStateFromRequest($this->context . '.filter.created_by', 'filter_created_by', ''); + $this->setState('filter.created_by', $created_by); + + $created = $this->getUserStateFromRequest($this->context . '.filter.created', 'filter_created'); + $this->setState('filter.created', $created); + + $sorting = $this->getUserStateFromRequest($this->context . '.filter.sorting', 'filter_sorting', 0, 'int'); + $this->setState('filter.sorting', $sorting); + + $search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search'); + $this->setState('filter.search', $search); + + $name = $this->getUserStateFromRequest($this->context . '.filter.name', 'filter_name'); + if ($formSubmited) + { + $name = $app->input->post->get('name'); + $this->setState('filter.name', $name); + } + + $cache_behaviour = $this->getUserStateFromRequest($this->context . '.filter.cache_behaviour', 'filter_cache_behaviour'); + if ($formSubmited) + { + $cache_behaviour = $app->input->post->get('cache_behaviour'); + $this->setState('filter.cache_behaviour', $cache_behaviour); + } + + $abbreviation = $this->getUserStateFromRequest($this->context . '.filter.abbreviation', 'filter_abbreviation'); + if ($formSubmited) + { + $abbreviation = $app->input->post->get('abbreviation'); + $this->setState('filter.abbreviation', $abbreviation); + } + + $model = $this->getUserStateFromRequest($this->context . '.filter.model', 'filter_model'); + if ($formSubmited) + { + $model = $app->input->post->get('model'); + $this->setState('filter.model', $model); + } + + $integration = $this->getUserStateFromRequest($this->context . '.filter.integration', 'filter_integration'); + if ($formSubmited) + { + $integration = $app->input->post->get('integration'); + $this->setState('filter.integration', $integration); + } + + // List state information. + parent::populateState($ordering, $direction); + } + + /** + * Method to get an array of data items. + * + * @return mixed An array of data items on success, false on failure. + */ + public function getItems() + { + // Check in items + $this->checkInNow(); + + // load parent items + $items = parent::getItems(); + + // Set values to display correctly. + if (GetbibleHelper::checkArray($items)) + { + // Get the user object if not set. + if (!isset($user) || !GetbibleHelper::checkObject($user)) + { + $user = JFactory::getUser(); + } + foreach ($items as $nr => &$item) + { + // Remove items the user can't access. + $access = ($user->authorise('prompt.access', 'com_getbible.prompt.' . (int) $item->id) && $user->authorise('prompt.access', 'com_getbible')); + if (!$access) + { + unset($items[$nr]); + continue; + } + + } + } + + // set selection value to a translatable value + if (GetbibleHelper::checkArray($items)) + { + foreach ($items as $nr => &$item) + { + // convert integration + $item->integration = $this->selectionTranslation($item->integration, 'integration'); + // convert cache_behaviour + $item->cache_behaviour = $this->selectionTranslation($item->cache_behaviour, 'cache_behaviour'); + // convert model + $item->model = $this->selectionTranslation($item->model, 'model'); + } + } + + + // return items + return $items; + } + + /** + * Method to convert selection values to translatable string. + * + * @return translatable string + */ + public function selectionTranslation($value,$name) + { + // Array of integration language strings + if ($name === 'integration') + { + $integrationArray = array( + 1 => 'COM_GETBIBLE_PROMPT_WORDBASED', + 2 => 'COM_GETBIBLE_PROMPT_VERSEBASED', + 3 => 'COM_GETBIBLE_PROMPT_SELECTIONBASED' + ); + // Now check if value is found in this array + if (isset($integrationArray[$value]) && GetbibleHelper::checkString($integrationArray[$value])) + { + return $integrationArray[$value]; + } + } + // Array of cache_behaviour language strings + if ($name === 'cache_behaviour') + { + $cache_behaviourArray = array( + 0 => 'COM_GETBIBLE_PROMPT_PERSISTENTLY_EXPANSIVE_CACHING', + 1 => 'COM_GETBIBLE_PROMPT_BASIC_CACHING_WORDSLANGUAGE', + 2 => 'COM_GETBIBLE_PROMPT_ADVANCED_CACHING_VERSECONTEX' + ); + // Now check if value is found in this array + if (isset($cache_behaviourArray[$value]) && GetbibleHelper::checkString($cache_behaviourArray[$value])) + { + return $cache_behaviourArray[$value]; + } + } + // Array of model language strings + if ($name === 'model') + { + $modelArray = array( + 0 => 'COM_GETBIBLE_PROMPT_USE_GLOBAL', + 'gpt-4' => 'COM_GETBIBLE_PROMPT_GPT4', + 'gpt-4-0613' => 'COM_GETBIBLE_PROMPT_GPT40613', + 'gpt-4-32k' => 'COM_GETBIBLE_PROMPT_GPT432K', + 'gpt-4-32k-0613' => 'COM_GETBIBLE_PROMPT_GPT432K0613', + 'gpt-3.5-turbo' => 'COM_GETBIBLE_PROMPT_GPT35TURBO', + 'gpt-3.5-turbo-0613' => 'COM_GETBIBLE_PROMPT_GPT35TURBO0613', + 'gpt-3.5-turbo-16k' => 'COM_GETBIBLE_PROMPT_GPT35TURBO16K', + 'gpt-3.5-turbo-16k-0613' => 'COM_GETBIBLE_PROMPT_GPT35TURBO16K0613' + ); + // Now check if value is found in this array + if (isset($modelArray[$value]) && GetbibleHelper::checkString($modelArray[$value])) + { + return $modelArray[$value]; + } + } + return $value; + } + + /** + * Method to build an SQL query to load the list data. + * + * @return string An SQL query + */ + protected function getListQuery() + { + // Get the user object. + $user = JFactory::getUser(); + // Create a new query object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + + // Select some fields + $query->select('a.*'); + + // From the getbible_item table + $query->from($db->quoteName('#__getbible_prompt', 'a')); + + // From the getbible_translation table. + $query->select($db->quoteName(['g.translation','g.id'],['abbreviation_translation','abbreviation_id'])); + $query->join('LEFT', $db->quoteName('#__getbible_translation', 'g') . ' ON (' . $db->quoteName('a.abbreviation') . ' = ' . $db->quoteName('g.abbreviation') . ')'); + + // Filter by published state + $published = $this->getState('filter.published'); + if (is_numeric($published)) + { + $query->where('a.published = ' . (int) $published); + } + elseif ($published === '') + { + $query->where('(a.published = 0 OR a.published = 1)'); + } + + // Join over the asset groups. + $query->select('ag.title AS access_level'); + $query->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access'); + // Filter by access level. + $_access = $this->getState('filter.access'); + if ($_access && is_numeric($_access)) + { + $query->where('a.access = ' . (int) $_access); + } + elseif (GetbibleHelper::checkArray($_access)) + { + // Secure the array for the query + $_access = ArrayHelper::toInteger($_access); + // Filter by the Access Array. + $query->where('a.access IN (' . implode(',', $_access) . ')'); + } + // Implement View Level Access + if (!$user->authorise('core.options', 'com_getbible')) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + // Filter by search. + $search = $this->getState('filter.search'); + if (!empty($search)) + { + if (stripos($search, 'id:') === 0) + { + $query->where('a.id = ' . (int) substr($search, 3)); + } + else + { + $search = $db->quote('%' . $db->escape($search) . '%'); + $query->where('(a.name LIKE '.$search.' OR a.model LIKE '.$search.')'); + } + } + + // Filter by Name. + $_name = $this->getState('filter.name'); + if (is_numeric($_name)) + { + if (is_float($_name)) + { + $query->where('a.name = ' . (float) $_name); + } + else + { + $query->where('a.name = ' . (int) $_name); + } + } + elseif (GetbibleHelper::checkString($_name)) + { + $query->where('a.name = ' . $db->quote($db->escape($_name))); + } + // Filter by Cache_behaviour. + $_cache_behaviour = $this->getState('filter.cache_behaviour'); + if (is_numeric($_cache_behaviour)) + { + if (is_float($_cache_behaviour)) + { + $query->where('a.cache_behaviour = ' . (float) $_cache_behaviour); + } + else + { + $query->where('a.cache_behaviour = ' . (int) $_cache_behaviour); + } + } + elseif (GetbibleHelper::checkString($_cache_behaviour)) + { + $query->where('a.cache_behaviour = ' . $db->quote($db->escape($_cache_behaviour))); + } + // Filter by Abbreviation. + $_abbreviation = $this->getState('filter.abbreviation'); + if (is_numeric($_abbreviation)) + { + if (is_float($_abbreviation)) + { + $query->where('a.abbreviation = ' . (float) $_abbreviation); + } + else + { + $query->where('a.abbreviation = ' . (int) $_abbreviation); + } + } + elseif (GetbibleHelper::checkString($_abbreviation)) + { + $query->where('a.abbreviation = ' . $db->quote($db->escape($_abbreviation))); + } + // Filter by Model. + $_model = $this->getState('filter.model'); + if (is_numeric($_model)) + { + if (is_float($_model)) + { + $query->where('a.model = ' . (float) $_model); + } + else + { + $query->where('a.model = ' . (int) $_model); + } + } + elseif (GetbibleHelper::checkString($_model)) + { + $query->where('a.model = ' . $db->quote($db->escape($_model))); + } + + // Add the list ordering clause. + $orderCol = $this->state->get('list.ordering', 'a.id'); + $orderDirn = $this->state->get('list.direction', 'desc'); + if ($orderCol != '') + { + $query->order($db->escape($orderCol . ' ' . $orderDirn)); + } + + return $query; + } + + /** + * Method to get a store id based on model configuration state. + * + * @return string A store id. + * + */ + protected function getStoreId($id = '') + { + // Compile the store id. + $id .= ':' . $this->getState('filter.id'); + $id .= ':' . $this->getState('filter.search'); + $id .= ':' . $this->getState('filter.published'); + // Check if the value is an array + $_access = $this->getState('filter.access'); + if (GetbibleHelper::checkArray($_access)) + { + $id .= ':' . implode(':', $_access); + } + // Check if this is only an number or string + elseif (is_numeric($_access) + || GetbibleHelper::checkString($_access)) + { + $id .= ':' . $_access; + } + $id .= ':' . $this->getState('filter.ordering'); + $id .= ':' . $this->getState('filter.created_by'); + $id .= ':' . $this->getState('filter.modified_by'); + $id .= ':' . $this->getState('filter.name'); + $id .= ':' . $this->getState('filter.cache_behaviour'); + $id .= ':' . $this->getState('filter.abbreviation'); + $id .= ':' . $this->getState('filter.model'); + $id .= ':' . $this->getState('filter.integration'); + + return parent::getStoreId($id); + } + + /** + * Build an SQL query to checkin all items left checked out longer then a set time. + * + * @return a bool + * + */ + protected function checkInNow() + { + // Get set check in time + $time = JComponentHelper::getParams('com_getbible')->get('check_in'); + + if ($time) + { + + // Get a db connection. + $db = JFactory::getDbo(); + // Reset query. + $query = $db->getQuery(true); + $query->select('*'); + $query->from($db->quoteName('#__getbible_prompt')); + // Only select items that are checked out. + $query->where($db->quoteName('checked_out') . '!=0'); + $db->setQuery($query, 0, 1); + $db->execute(); + if ($db->getNumRows()) + { + // Get Yesterdays date. + $date = JFactory::getDate()->modify($time)->toSql(); + // Reset query. + $query = $db->getQuery(true); + + // Fields to update. + $fields = array( + $db->quoteName('checked_out_time') . '=\'0000-00-00 00:00:00\'', + $db->quoteName('checked_out') . '=0' + ); + + // Conditions for which records should be updated. + $conditions = array( + $db->quoteName('checked_out') . '!=0', + $db->quoteName('checked_out_time') . '<\''.$date.'\'' + ); + + // Check table. + $query->update($db->quoteName('#__getbible_prompt'))->set($fields)->where($conditions); + + $db->setQuery($query); + + $db->execute(); + } + } + + return false; + } +} diff --git a/admin/models/rules/guid.php b/admin/models/rules/guid.php new file mode 100644 index 0000000..41b1d73 --- /dev/null +++ b/admin/models/rules/guid.php @@ -0,0 +1,60 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('JPATH_PLATFORM') or die; + +use Joomla\CMS\Form\Form; +use Joomla\CMS\Form\FormRule; +use Joomla\Registry\Registry; + +/** + * Form Rule (Guid) class for the Joomla Platform. + */ +class JFormRuleGuid extends FormRule +{ + /** + * Method to test for a Globally Unique Identifier. + * + * @param \SimpleXMLElement $element The SimpleXMLElement object representing the `` tag for the form field object. + * @param mixed $value The form field value to validate. + * @param string $group The field name group control value. This acts as an array container for the field. + * For example if the field has name="foo" and the group value is set to "bar" then the + * full field name would end up being "bar[foo]". + * @param Registry $input An optional Registry object with the entire data set to validate against the entire form. + * @param Form $form The form object for which the field is being tested. + * + * @return boolean True if the value is valid, false otherwise. + * + */ + public function test(\SimpleXMLElement $element, $value, $group = null, Registry $input = null, Form $form = null) + { + $value = trim($value); + + // If the field is empty and not required, the field is valid. + $required = ((string) $element['required'] == 'true' || (string) $element['required'] == 'required'); + + if (!$required && empty($value)) + { + return true; + } + + // thanks to Lewie https://stackoverflow.com/a/1515456/1429677 + return preg_match("/^(\{)?[a-f\d]{8}(-[a-f\d]{4}){4}[a-f\d]{8}(?(1)\})$/i", $value); + } + +} diff --git a/admin/models/rules/index.html b/admin/models/rules/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/models/rules/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/models/rules/int.php b/admin/models/rules/int.php new file mode 100644 index 0000000..daac7f5 --- /dev/null +++ b/admin/models/rules/int.php @@ -0,0 +1,62 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('JPATH_PLATFORM') or die; + +use Joomla\CMS\Form\Form; +use Joomla\CMS\Form\FormRule; +use Joomla\Registry\Registry; + +/** + * Form Rule (Int) class for the Joomla Platform. + */ +class JFormRuleInt extends FormRule +{ + /** + * Method to test that an integer value was added. + * + * @param \SimpleXMLElement $element The SimpleXMLElement object representing the `` tag for the form field object. + * @param mixed $value The form field value to validate. + * @param string $group The field name group control value. This acts as an array container for the field. + * For example if the field has name="foo" and the group value is set to "bar" then the + * full field name would end up being "bar[foo]". + * @param Registry $input An optional Registry object with the entire data set to validate against the entire form. + * @param Form $form The form object for which the field is being tested. + * + * @return boolean True if the value is valid integer, false otherwise. + * + */ + public function test(\SimpleXMLElement $element, $value, $group = null, Registry $input = null, Form $form = null) + { + // Check if the field is required. + $required = ((string) $element['required'] == 'true' || (string) $element['required'] == 'required'); + + // If the value is empty and the field is not required return True. + if (($value === '' || $value === null) && ! $required) + { + return true; + } + + // now validate the value to be an integer + // we need to validate a string with the integer in it + // since this is how Joomla passes the value to the test method + // so we use type coercion along with is_numeric + return is_numeric($value) && is_int(+$value); + // if you have a better idea... lets hear it. + } +} diff --git a/admin/models/rules/numbershyphens.php b/admin/models/rules/numbershyphens.php new file mode 100644 index 0000000..fd20cce --- /dev/null +++ b/admin/models/rules/numbershyphens.php @@ -0,0 +1,60 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('JPATH_PLATFORM') or die; + +use Joomla\CMS\Form\Form; +use Joomla\CMS\Form\FormRule; +use Joomla\Registry\Registry; + +/** + * Form Rule (Numbershyphens) class for the Joomla Platform. + */ +class JFormRuleNumbershyphens extends FormRule +{ + /** + * Method to test if the input is a number or a sequence of numbers separated by hyphens. + * + * @param \SimpleXMLElement $element The SimpleXMLElement object representing the `` tag for the form field object. + * @param mixed $value The form field value to validate. + * @param string $group The field name group control value. This acts as an array container for the field. + * For example if the field has name="foo" and the group value is set to "bar" then the + * full field name would end up being "bar[foo]". + * @param Registry $input An optional Registry object with the entire data set to validate against the entire form. + * @param Form $form The form object for which the field is being tested. + * + * @return boolean True if the value is valid, false otherwise. + * + * @since 1.7.0 + */ + public function test(\SimpleXMLElement $element, $value, $group = null, Registry $input = null, Form $form = null) + { + $value = trim($value); + + // If the field is empty and not required, the field is valid. + $required = ((string) $element['required'] == 'true' || (string) $element['required'] == 'required'); + + if (!$required && empty($value)) + { + return true; // we allow empty values if not required + } + + // Check if the value is a number or a sequence of numbers separated by hyphens. + return preg_match('/^(\d+-)*\d+$/', $value) === 1; + } +} diff --git a/admin/models/tag.php b/admin/models/tag.php new file mode 100644 index 0000000..d9fd24d --- /dev/null +++ b/admin/models/tag.php @@ -0,0 +1,984 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\AdminModel; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; +use VDM\Joomla\Utilities\GuidHelper; +use VDM\Joomla\Utilities\GetHelper; + +/** + * Getbible Tag Admin Model + */ +class GetbibleModelTag extends AdminModel +{ + /** + * The tab layout fields array. + * + * @var array + */ + protected $tabLayoutFields = array( + 'details' => array( + 'left' => array( + 'name' + ), + 'fullwidth' => array( + 'description' + ), + 'above' => array( + 'access', + 'linker' + ) + ) + ); + + /** + * @var string The prefix to use with controller messages. + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE'; + + /** + * The type alias for this content type. + * + * @var string + * @since 3.2 + */ + public $typeAlias = 'com_getbible.tag'; + + /** + * Returns a Table object, always creating it + * + * @param type $type The table type to instantiate + * @param string $prefix A prefix for the table class name. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JTable A database object + * + * @since 1.6 + */ + public function getTable($type = 'tag', $prefix = 'GetbibleTable', $config = array()) + { + // add table path for when model gets used from other component + $this->addTablePath(JPATH_ADMINISTRATOR . '/components/com_getbible/tables'); + // get instance of the table + return JTable::getInstance($type, $prefix, $config); + } + + /** + * Method to get a single record. + * + * @param integer $pk The id of the primary key. + * + * @return mixed Object on success, false on failure. + * + * @since 1.6 + */ + public function getItem($pk = null) + { + if ($item = parent::getItem($pk)) + { + if (!empty($item->params) && !is_array($item->params)) + { + // Convert the params field to an array. + $registry = new Registry; + $registry->loadString($item->params); + $item->params = $registry->toArray(); + } + + if (!empty($item->metadata)) + { + // Convert the metadata field to an array. + $registry = new Registry; + $registry->loadString($item->metadata); + $item->metadata = $registry->toArray(); + } + } + + return $item; + } + + /** + * Method to get the record form. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * @param array $options Optional array of options for the form creation. + * + * @return mixed A JForm object on success, false on failure + * + * @since 1.6 + */ + public function getForm($data = array(), $loadData = true, $options = array('control' => 'jform')) + { + // set load data option + $options['load_data'] = $loadData; + // check if xpath was set in options + $xpath = false; + if (isset($options['xpath'])) + { + $xpath = $options['xpath']; + unset($options['xpath']); + } + // check if clear form was set in options + $clear = false; + if (isset($options['clear'])) + { + $clear = $options['clear']; + unset($options['clear']); + } + + // Get the form. + $form = $this->loadForm('com_getbible.tag', 'tag', $options, $clear, $xpath); + + if (empty($form)) + { + return false; + } + + $jinput = JFactory::getApplication()->input; + + // The front end calls this model and uses a_id to avoid id clashes so we need to check for that first. + if ($jinput->get('a_id')) + { + $id = $jinput->get('a_id', 0, 'INT'); + } + // The back end uses id so we use that the rest of the time and set it to 0 by default. + else + { + $id = $jinput->get('id', 0, 'INT'); + } + + $user = JFactory::getUser(); + + // Check for existing item. + // Modify the form based on Edit State access controls. + if ($id != 0 && (!$user->authorise('tag.edit.state', 'com_getbible.tag.' . (int) $id)) + || ($id == 0 && !$user->authorise('tag.edit.state', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('ordering', 'disabled', 'true'); + $form->setFieldAttribute('published', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('ordering', 'filter', 'unset'); + $form->setFieldAttribute('published', 'filter', 'unset'); + } + // If this is a new item insure the greated by is set. + if (0 == $id) + { + // Set the created_by to this user + $form->setValue('created_by', null, $user->id); + } + // Modify the form based on Edit Creaded By access controls. + if ($id != 0 && (!$user->authorise('tag.edit.created_by', 'com_getbible.tag.' . (int) $id)) + || ($id == 0 && !$user->authorise('tag.edit.created_by', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created_by', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('created_by', 'readonly', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created_by', 'filter', 'unset'); + } + // Modify the form based on Edit Creaded Date access controls. + if ($id != 0 && (!$user->authorise('tag.edit.created', 'com_getbible.tag.' . (int) $id)) + || ($id == 0 && !$user->authorise('tag.edit.created', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created', 'filter', 'unset'); + } + // Modify the form based on Edit Access 'access' controls. + if ($id != 0 && (!$user->authorise('tag.edit.access', 'com_getbible.tag.' . (int) $id)) + || ($id == 0 && !$user->authorise('tag.edit.access', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('access', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('access', 'filter', 'unset'); + } + // Modify the form based on Edit Name access controls. + if ($id != 0 && (!$user->authorise('tag.edit.name', 'com_getbible.tag.' . (int) $id)) + || ($id == 0 && !$user->authorise('tag.edit.name', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('name', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('name', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('name')) + { + // Disable fields while saving. + $form->setFieldAttribute('name', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('name', 'required', 'false'); + } + } + // Modify the form based on Edit Linker access controls. + if ($id != 0 && (!$user->authorise('tag.edit.linker', 'com_getbible.tag.' . (int) $id)) + || ($id == 0 && !$user->authorise('tag.edit.linker', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('linker', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('linker', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('linker')) + { + // Disable fields while saving. + $form->setFieldAttribute('linker', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('linker', 'required', 'false'); + } + } + // Modify the form based on Edit Guid access controls. + if ($id != 0 && (!$user->authorise('tag.edit.guid', 'com_getbible.tag.' . (int) $id)) + || ($id == 0 && !$user->authorise('tag.edit.guid', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('guid', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('guid', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('guid')) + { + // Disable fields while saving. + $form->setFieldAttribute('guid', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('guid', 'required', 'false'); + } + } + // Modify the form based on Edit Description access controls. + if ($id != 0 && (!$user->authorise('tag.edit.description', 'com_getbible.tag.' . (int) $id)) + || ($id == 0 && !$user->authorise('tag.edit.description', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('description', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('description', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('description')) + { + // Disable fields while saving. + $form->setFieldAttribute('description', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('description', 'required', 'false'); + } + } + // Only load these values if no id is found + if (0 == $id) + { + // Set redirected view name + $redirectedView = $jinput->get('ref', null, 'STRING'); + // Set field name (or fall back to view name) + $redirectedField = $jinput->get('field', $redirectedView, 'STRING'); + // Set redirected view id + $redirectedId = $jinput->get('refid', 0, 'INT'); + // Set field id (or fall back to redirected view id) + $redirectedValue = $jinput->get('field_id', $redirectedId, 'INT'); + if (0 != $redirectedValue && $redirectedField) + { + // Now set the local-redirected field default value + $form->setValue($redirectedField, null, $redirectedValue); + } + } + + // Only load the GUID if new item (or empty) + if (0 == $id || !($val = $form->getValue('guid'))) + { + $form->setValue('guid', null, GuidHelper::get()); + } + + return $form; + } + + /** + * Method to get the script that have to be included on the form + * + * @return string script files + */ + public function getScript() + { + return 'media/com_getbible/js/tag.js'; + } + + /** + * Method to test whether a record can be deleted. + * + * @param object $record A record object. + * + * @return boolean True if allowed to delete the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canDelete($record) + { + if (!empty($record->id)) + { + if ($record->published != -2) + { + return; + } + + $user = JFactory::getUser(); + // The record has been set. Check the record permissions. + return $user->authorise('tag.delete', 'com_getbible.tag.' . (int) $record->id); + } + return false; + } + + /** + * Method to test whether a record can have its state edited. + * + * @param object $record A record object. + * + * @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canEditState($record) + { + $user = JFactory::getUser(); + $recordId = (!empty($record->id)) ? $record->id : 0; + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('tag.edit.state', 'com_getbible.tag.' . (int) $recordId); + if (!$permission && !is_null($permission)) + { + return false; + } + } + // In the absense of better information, revert to the component permissions. + return $user->authorise('tag.edit.state', 'com_getbible'); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * @since 2.5 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // Check specific edit permission then general edit permission. + $user = JFactory::getUser(); + + return $user->authorise('tag.edit', 'com_getbible.tag.'. ((int) isset($data[$key]) ? $data[$key] : 0)) or $user->authorise('tag.edit', 'com_getbible'); + } + + /** + * Prepare and sanitise the table data prior to saving. + * + * @param JTable $table A JTable object. + * + * @return void + * + * @since 1.6 + */ + protected function prepareTable($table) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if (isset($table->name)) + { + $table->name = htmlspecialchars_decode($table->name, ENT_QUOTES); + } + + if (isset($table->alias) && empty($table->alias)) + { + $table->generateAlias(); + } + + if (empty($table->id)) + { + $table->created = $date->toSql(); + // set the user + if ($table->created_by == 0 || empty($table->created_by)) + { + $table->created_by = $user->id; + } + // Set ordering to the last item if not set + if (empty($table->ordering)) + { + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select('MAX(ordering)') + ->from($db->quoteName('#__getbible_tag')); + $db->setQuery($query); + $max = $db->loadResult(); + + $table->ordering = $max + 1; + } + } + else + { + $table->modified = $date->toSql(); + $table->modified_by = $user->id; + } + + if (!empty($table->id)) + { + // Increment the items version number. + $table->version++; + } + } + + /** + * Method to get the data that should be injected in the form. + * + * @return mixed The data for the form. + * + * @since 1.6 + */ + protected function loadFormData() + { + // Check the session for previously entered form data. + $data = JFactory::getApplication()->getUserState('com_getbible.edit.tag.data', array()); + + if (empty($data)) + { + $data = $this->getItem(); + // run the perprocess of the data + $this->preprocessData('com_getbible.tag', $data); + } + + return $data; + } + + /** + * Method to get the unique fields of this table. + * + * @return mixed An array of field names, boolean false if none is set. + * + * @since 3.0 + */ + protected function getUniqueFields() + { + return array('guid'); + } + + /** + * Method to delete one or more records. + * + * @param array &$pks An array of record primary keys. + * + * @return boolean True if successful, false if an error occurs. + * + * @since 12.2 + */ + public function delete(&$pks) + { + if (!parent::delete($pks)) + { + return false; + } + + return true; + } + + /** + * Method to change the published state of one or more records. + * + * @param array &$pks A list of the primary keys to change. + * @param integer $value The value of the published state. + * + * @return boolean True on success. + * + * @since 12.2 + */ + public function publish(&$pks, $value = 1) + { + if (!parent::publish($pks, $value)) + { + return false; + } + + return true; + } + + /** + * Method to perform batch operations on an item or a set of items. + * + * @param array $commands An array of commands to perform. + * @param array $pks An array of item ids. + * @param array $contexts An array of item contexts. + * + * @return boolean Returns true on success, false on failure. + * + * @since 12.2 + */ + public function batch($commands, $pks, $contexts) + { + // Sanitize ids. + $pks = array_unique($pks); + ArrayHelper::toInteger($pks); + + // Remove any values of zero. + if (array_search(0, $pks, true)) + { + unset($pks[array_search(0, $pks, true)]); + } + + if (empty($pks)) + { + $this->setError(JText::_('JGLOBAL_NO_ITEM_SELECTED')); + return false; + } + + $done = false; + + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->contentType = new JUcmType; + $this->type = $this->contentType->getTypeByTable($this->tableClassName); + $this->canDo = GetbibleHelper::getActions('tag'); + $this->batchSet = true; + + if (!$this->canDo->get('core.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + return false; + } + + if ($this->type == false) + { + $type = new JUcmType; + $this->type = $type->getTypeByAlias($this->typeAlias); + } + + $this->tagsObserver = $this->table->getObserverOfClass('JTableObserverTags'); + + if (!empty($commands['move_copy'])) + { + $cmd = ArrayHelper::getValue($commands, 'move_copy', 'c'); + + if ($cmd == 'c') + { + $result = $this->batchCopy($commands, $pks, $contexts); + + if (is_array($result)) + { + foreach ($result as $old => $new) + { + $contexts[$new] = $contexts[$old]; + } + $pks = array_values($result); + } + else + { + return false; + } + } + elseif ($cmd == 'm' && !$this->batchMove($commands, $pks, $contexts)) + { + return false; + } + + $done = true; + } + + if (!$done) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + + return false; + } + + // Clear the cache + $this->cleanCache(); + + return true; + } + + /** + * Batch copy items to a new category or current. + * + * @param integer $values The new values. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return mixed An array of new IDs on success, boolean false on failure. + * + * @since 12.2 + */ + protected function batchCopy($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('tag'); + } + + if (!$this->canDo->get('tag.create') && !$this->canDo->get('tag.batch')) + { + return false; + } + + // get list of unique fields + $uniqueFields = $this->getUniqueFields(); + // remove move_copy from array + unset($values['move_copy']); + + // make sure published is set + if (!isset($values['published'])) + { + $values['published'] = 0; + } + elseif (isset($values['published']) && !$this->canDo->get('tag.edit.state')) + { + $values['published'] = 0; + } + + $newIds = array(); + // Parent exists so let's proceed + while (!empty($pks)) + { + // Pop the first ID off the stack + $pk = array_shift($pks); + + $this->table->reset(); + + // only allow copy if user may edit this item. + if (!$this->user->authorise('tag.edit', $contexts[$pk])) + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // Only for strings + if (GetbibleHelper::checkString($this->table->name) && !is_numeric($this->table->name)) + { + $this->table->name = $this->generateUnique('name',$this->table->name); + } + + // insert all set values + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + if (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + // update all unique fields + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $this->table->$uniqueField = $this->generateUnique($uniqueField,$this->table->$uniqueField); + } + } + + // Reset the ID because we are making a copy + $this->table->id = 0; + + // TODO: Deal with ordering? + // $this->table->ordering = 1; + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + + // Get the new item ID + $newId = $this->table->get('id'); + + // Add the new ID to the array + $newIds[$pk] = $newId; + } + + // Clean the cache + $this->cleanCache(); + + return $newIds; + } + + /** + * Batch move items to a new category + * + * @param integer $value The new category ID. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 12.2 + */ + protected function batchMove($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('tag'); + } + + if (!$this->canDo->get('tag.edit') && !$this->canDo->get('tag.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // make sure published only updates if user has the permission. + if (isset($values['published']) && !$this->canDo->get('tag.edit.state')) + { + unset($values['published']); + } + // remove move_copy from array + unset($values['move_copy']); + + // Parent exists so we proceed + foreach ($pks as $pk) + { + if (!$this->user->authorise('tag.edit', $contexts[$pk])) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // insert all set values. + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + // Do special action for access. + if ('access' === $key && strlen($value) > 0) + { + $this->table->$key = $value; + } + elseif (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + } + + // Clean the cache + $this->cleanCache(); + + return true; + } + + /** + * Method to save the form data. + * + * @param array $data The form data. + * + * @return boolean True on success. + * + * @since 1.6 + */ + public function save($data) + { + $input = JFactory::getApplication()->input; + $filter = JFilterInput::getInstance(); + + // set the metadata to the Item Data + if (isset($data['metadata']) && isset($data['metadata']['author'])) + { + $data['metadata']['author'] = $filter->clean($data['metadata']['author'], 'TRIM'); + + $metadata = new JRegistry; + $metadata->loadArray($data['metadata']); + $data['metadata'] = (string) $metadata; + } + + + // Set the GUID if empty or not valid + if (empty($data['guid']) && $data['id'] > 0) + { + // get the existing one + $data['guid'] = (string) GetHelper::var('tag', $data['id'], 'id', 'guid'); + } + + // Set the GUID if empty or not valid + while (!GuidHelper::valid($data['guid'], "tag", $data['id'])) + { + // must always be set + $data['guid'] = (string) GuidHelper::get(); + } + + // Set the Params Items to data + if (isset($data['params']) && is_array($data['params'])) + { + $params = new JRegistry; + $params->loadArray($data['params']); + $data['params'] = (string) $params; + } + + // Alter the unique field for save as copy + if ($input->get('task') === 'save2copy') + { + // Automatic handling of other unique fields + $uniqueFields = $this->getUniqueFields(); + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $data[$uniqueField] = $this->generateUnique($uniqueField,$data[$uniqueField]); + } + } + } + + if (parent::save($data)) + { + return true; + } + return false; + } + + /** + * Method to generate a unique value. + * + * @param string $field name. + * @param string $value data. + * + * @return string New value. + * + * @since 3.0 + */ + protected function generateUnique($field,$value) + { + + // set field value unique + $table = $this->getTable(); + + while ($table->load(array($field => $value))) + { + $value = StringHelper::increment($value); + } + + return $value; + } + + /** + * Method to change the title + * + * @param string $title The title. + * + * @return array Contains the modified title and alias. + * + */ + protected function _generateNewTitle($title) + { + + // Alter the title + $table = $this->getTable(); + + while ($table->load(array('title' => $title))) + { + $title = StringHelper::increment($title); + } + + return $title; + } +} diff --git a/admin/models/tagged_verse.php b/admin/models/tagged_verse.php new file mode 100644 index 0000000..849ba2b --- /dev/null +++ b/admin/models/tagged_verse.php @@ -0,0 +1,1010 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\AdminModel; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; +use VDM\Joomla\Utilities\GuidHelper; +use VDM\Joomla\Utilities\GetHelper; + +/** + * Getbible Tagged_verse Admin Model + */ +class GetbibleModelTagged_verse extends AdminModel +{ + /** + * The tab layout fields array. + * + * @var array + */ + protected $tabLayoutFields = array( + 'details' => array( + 'left' => array( + 'abbreviation', + 'book_nr' + ), + 'right' => array( + 'chapter', + 'verse' + ), + 'above' => array( + 'tag', + 'access', + 'linker' + ) + ) + ); + + /** + * @var string The prefix to use with controller messages. + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE'; + + /** + * The type alias for this content type. + * + * @var string + * @since 3.2 + */ + public $typeAlias = 'com_getbible.tagged_verse'; + + /** + * Returns a Table object, always creating it + * + * @param type $type The table type to instantiate + * @param string $prefix A prefix for the table class name. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JTable A database object + * + * @since 1.6 + */ + public function getTable($type = 'tagged_verse', $prefix = 'GetbibleTable', $config = array()) + { + // add table path for when model gets used from other component + $this->addTablePath(JPATH_ADMINISTRATOR . '/components/com_getbible/tables'); + // get instance of the table + return JTable::getInstance($type, $prefix, $config); + } + + /** + * Method to get a single record. + * + * @param integer $pk The id of the primary key. + * + * @return mixed Object on success, false on failure. + * + * @since 1.6 + */ + public function getItem($pk = null) + { + if ($item = parent::getItem($pk)) + { + if (!empty($item->params) && !is_array($item->params)) + { + // Convert the params field to an array. + $registry = new Registry; + $registry->loadString($item->params); + $item->params = $registry->toArray(); + } + + if (!empty($item->metadata)) + { + // Convert the metadata field to an array. + $registry = new Registry; + $registry->loadString($item->metadata); + $item->metadata = $registry->toArray(); + } + } + + return $item; + } + + /** + * Method to get the record form. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * @param array $options Optional array of options for the form creation. + * + * @return mixed A JForm object on success, false on failure + * + * @since 1.6 + */ + public function getForm($data = array(), $loadData = true, $options = array('control' => 'jform')) + { + // set load data option + $options['load_data'] = $loadData; + // check if xpath was set in options + $xpath = false; + if (isset($options['xpath'])) + { + $xpath = $options['xpath']; + unset($options['xpath']); + } + // check if clear form was set in options + $clear = false; + if (isset($options['clear'])) + { + $clear = $options['clear']; + unset($options['clear']); + } + + // Get the form. + $form = $this->loadForm('com_getbible.tagged_verse', 'tagged_verse', $options, $clear, $xpath); + + if (empty($form)) + { + return false; + } + + $jinput = JFactory::getApplication()->input; + + // The front end calls this model and uses a_id to avoid id clashes so we need to check for that first. + if ($jinput->get('a_id')) + { + $id = $jinput->get('a_id', 0, 'INT'); + } + // The back end uses id so we use that the rest of the time and set it to 0 by default. + else + { + $id = $jinput->get('id', 0, 'INT'); + } + + $user = JFactory::getUser(); + + // Check for existing item. + // Modify the form based on Edit State access controls. + if ($id != 0 && (!$user->authorise('tagged_verse.edit.state', 'com_getbible.tagged_verse.' . (int) $id)) + || ($id == 0 && !$user->authorise('tagged_verse.edit.state', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('ordering', 'disabled', 'true'); + $form->setFieldAttribute('published', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('ordering', 'filter', 'unset'); + $form->setFieldAttribute('published', 'filter', 'unset'); + } + // If this is a new item insure the greated by is set. + if (0 == $id) + { + // Set the created_by to this user + $form->setValue('created_by', null, $user->id); + } + // Modify the form based on Edit Creaded By access controls. + if ($id != 0 && (!$user->authorise('tagged_verse.edit.created_by', 'com_getbible.tagged_verse.' . (int) $id)) + || ($id == 0 && !$user->authorise('tagged_verse.edit.created_by', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created_by', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('created_by', 'readonly', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created_by', 'filter', 'unset'); + } + // Modify the form based on Edit Creaded Date access controls. + if ($id != 0 && (!$user->authorise('tagged_verse.edit.created', 'com_getbible.tagged_verse.' . (int) $id)) + || ($id == 0 && !$user->authorise('tagged_verse.edit.created', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created', 'filter', 'unset'); + } + // Modify the form based on Edit Access 'access' controls. + if ($id != 0 && (!$user->authorise('tagged_verse.edit.access', 'com_getbible.tagged_verse.' . (int) $id)) + || ($id == 0 && !$user->authorise('tagged_verse.edit.access', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('access', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('access', 'filter', 'unset'); + } + // Modify the form based on Edit Book Nr access controls. + if ($id != 0 && (!$user->authorise('tagged_verse.edit.book_nr', 'com_getbible.tagged_verse.' . (int) $id)) + || ($id == 0 && !$user->authorise('tagged_verse.edit.book_nr', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('book_nr', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('book_nr', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('book_nr')) + { + // Disable fields while saving. + $form->setFieldAttribute('book_nr', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('book_nr', 'required', 'false'); + } + } + // Modify the form based on Edit Abbreviation access controls. + if ($id != 0 && (!$user->authorise('tagged_verse.edit.abbreviation', 'com_getbible.tagged_verse.' . (int) $id)) + || ($id == 0 && !$user->authorise('tagged_verse.edit.abbreviation', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('abbreviation', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('abbreviation', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('abbreviation')) + { + // Disable fields while saving. + $form->setFieldAttribute('abbreviation', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('abbreviation', 'required', 'false'); + } + } + // Modify the form based on Edit Linker access controls. + if ($id != 0 && (!$user->authorise('tagged_verse.edit.linker', 'com_getbible.tagged_verse.' . (int) $id)) + || ($id == 0 && !$user->authorise('tagged_verse.edit.linker', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('linker', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('linker', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('linker')) + { + // Disable fields while saving. + $form->setFieldAttribute('linker', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('linker', 'required', 'false'); + } + } + // Modify the form based on Edit Tag access controls. + if ($id != 0 && (!$user->authorise('tagged_verse.edit.tag', 'com_getbible.tagged_verse.' . (int) $id)) + || ($id == 0 && !$user->authorise('tagged_verse.edit.tag', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('tag', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('tag', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('tag')) + { + // Disable fields while saving. + $form->setFieldAttribute('tag', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('tag', 'required', 'false'); + } + } + // Modify the form based on Edit Guid access controls. + if ($id != 0 && (!$user->authorise('tagged_verse.edit.guid', 'com_getbible.tagged_verse.' . (int) $id)) + || ($id == 0 && !$user->authorise('tagged_verse.edit.guid', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('guid', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('guid', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('guid')) + { + // Disable fields while saving. + $form->setFieldAttribute('guid', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('guid', 'required', 'false'); + } + } + // Modify the form based on Edit Verse access controls. + if ($id != 0 && (!$user->authorise('tagged_verse.edit.verse', 'com_getbible.tagged_verse.' . (int) $id)) + || ($id == 0 && !$user->authorise('tagged_verse.edit.verse', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('verse', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('verse', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('verse')) + { + // Disable fields while saving. + $form->setFieldAttribute('verse', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('verse', 'required', 'false'); + } + } + // Modify the form based on Edit Chapter access controls. + if ($id != 0 && (!$user->authorise('tagged_verse.edit.chapter', 'com_getbible.tagged_verse.' . (int) $id)) + || ($id == 0 && !$user->authorise('tagged_verse.edit.chapter', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('chapter', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('chapter', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('chapter')) + { + // Disable fields while saving. + $form->setFieldAttribute('chapter', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('chapter', 'required', 'false'); + } + } + // Only load these values if no id is found + if (0 == $id) + { + // Set redirected view name + $redirectedView = $jinput->get('ref', null, 'STRING'); + // Set field name (or fall back to view name) + $redirectedField = $jinput->get('field', $redirectedView, 'STRING'); + // Set redirected view id + $redirectedId = $jinput->get('refid', 0, 'INT'); + // Set field id (or fall back to redirected view id) + $redirectedValue = $jinput->get('field_id', $redirectedId, 'INT'); + if (0 != $redirectedValue && $redirectedField) + { + // Now set the local-redirected field default value + $form->setValue($redirectedField, null, $redirectedValue); + } + } + + // Only load the GUID if new item (or empty) + if (0 == $id || !($val = $form->getValue('guid'))) + { + $form->setValue('guid', null, GuidHelper::get()); + } + + return $form; + } + + /** + * Method to get the script that have to be included on the form + * + * @return string script files + */ + public function getScript() + { + return 'media/com_getbible/js/tagged_verse.js'; + } + + /** + * Method to test whether a record can be deleted. + * + * @param object $record A record object. + * + * @return boolean True if allowed to delete the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canDelete($record) + { + if (!empty($record->id)) + { + if ($record->published != -2) + { + return; + } + + $user = JFactory::getUser(); + // The record has been set. Check the record permissions. + return $user->authorise('tagged_verse.delete', 'com_getbible.tagged_verse.' . (int) $record->id); + } + return false; + } + + /** + * Method to test whether a record can have its state edited. + * + * @param object $record A record object. + * + * @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canEditState($record) + { + $user = JFactory::getUser(); + $recordId = (!empty($record->id)) ? $record->id : 0; + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('tagged_verse.edit.state', 'com_getbible.tagged_verse.' . (int) $recordId); + if (!$permission && !is_null($permission)) + { + return false; + } + } + // In the absense of better information, revert to the component permissions. + return $user->authorise('tagged_verse.edit.state', 'com_getbible'); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * @since 2.5 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // Check specific edit permission then general edit permission. + $user = JFactory::getUser(); + + return $user->authorise('tagged_verse.edit', 'com_getbible.tagged_verse.'. ((int) isset($data[$key]) ? $data[$key] : 0)) or $user->authorise('tagged_verse.edit', 'com_getbible'); + } + + /** + * Prepare and sanitise the table data prior to saving. + * + * @param JTable $table A JTable object. + * + * @return void + * + * @since 1.6 + */ + protected function prepareTable($table) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if (isset($table->name)) + { + $table->name = htmlspecialchars_decode($table->name, ENT_QUOTES); + } + + if (isset($table->alias) && empty($table->alias)) + { + $table->generateAlias(); + } + + if (empty($table->id)) + { + $table->created = $date->toSql(); + // set the user + if ($table->created_by == 0 || empty($table->created_by)) + { + $table->created_by = $user->id; + } + // Set ordering to the last item if not set + if (empty($table->ordering)) + { + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select('MAX(ordering)') + ->from($db->quoteName('#__getbible_tagged_verse')); + $db->setQuery($query); + $max = $db->loadResult(); + + $table->ordering = $max + 1; + } + } + else + { + $table->modified = $date->toSql(); + $table->modified_by = $user->id; + } + + if (!empty($table->id)) + { + // Increment the items version number. + $table->version++; + } + } + + /** + * Method to get the data that should be injected in the form. + * + * @return mixed The data for the form. + * + * @since 1.6 + */ + protected function loadFormData() + { + // Check the session for previously entered form data. + $data = JFactory::getApplication()->getUserState('com_getbible.edit.tagged_verse.data', array()); + + if (empty($data)) + { + $data = $this->getItem(); + // run the perprocess of the data + $this->preprocessData('com_getbible.tagged_verse', $data); + } + + return $data; + } + + /** + * Method to get the unique fields of this table. + * + * @return mixed An array of field names, boolean false if none is set. + * + * @since 3.0 + */ + protected function getUniqueFields() + { + return array('guid'); + } + + /** + * Method to delete one or more records. + * + * @param array &$pks An array of record primary keys. + * + * @return boolean True if successful, false if an error occurs. + * + * @since 12.2 + */ + public function delete(&$pks) + { + if (!parent::delete($pks)) + { + return false; + } + + return true; + } + + /** + * Method to change the published state of one or more records. + * + * @param array &$pks A list of the primary keys to change. + * @param integer $value The value of the published state. + * + * @return boolean True on success. + * + * @since 12.2 + */ + public function publish(&$pks, $value = 1) + { + if (!parent::publish($pks, $value)) + { + return false; + } + + return true; + } + + /** + * Method to perform batch operations on an item or a set of items. + * + * @param array $commands An array of commands to perform. + * @param array $pks An array of item ids. + * @param array $contexts An array of item contexts. + * + * @return boolean Returns true on success, false on failure. + * + * @since 12.2 + */ + public function batch($commands, $pks, $contexts) + { + // Sanitize ids. + $pks = array_unique($pks); + ArrayHelper::toInteger($pks); + + // Remove any values of zero. + if (array_search(0, $pks, true)) + { + unset($pks[array_search(0, $pks, true)]); + } + + if (empty($pks)) + { + $this->setError(JText::_('JGLOBAL_NO_ITEM_SELECTED')); + return false; + } + + $done = false; + + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->contentType = new JUcmType; + $this->type = $this->contentType->getTypeByTable($this->tableClassName); + $this->canDo = GetbibleHelper::getActions('tagged_verse'); + $this->batchSet = true; + + if (!$this->canDo->get('core.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + return false; + } + + if ($this->type == false) + { + $type = new JUcmType; + $this->type = $type->getTypeByAlias($this->typeAlias); + } + + $this->tagsObserver = $this->table->getObserverOfClass('JTableObserverTags'); + + if (!empty($commands['move_copy'])) + { + $cmd = ArrayHelper::getValue($commands, 'move_copy', 'c'); + + if ($cmd == 'c') + { + $result = $this->batchCopy($commands, $pks, $contexts); + + if (is_array($result)) + { + foreach ($result as $old => $new) + { + $contexts[$new] = $contexts[$old]; + } + $pks = array_values($result); + } + else + { + return false; + } + } + elseif ($cmd == 'm' && !$this->batchMove($commands, $pks, $contexts)) + { + return false; + } + + $done = true; + } + + if (!$done) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + + return false; + } + + // Clear the cache + $this->cleanCache(); + + return true; + } + + /** + * Batch copy items to a new category or current. + * + * @param integer $values The new values. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return mixed An array of new IDs on success, boolean false on failure. + * + * @since 12.2 + */ + protected function batchCopy($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('tagged_verse'); + } + + if (!$this->canDo->get('tagged_verse.create') && !$this->canDo->get('tagged_verse.batch')) + { + return false; + } + + // get list of unique fields + $uniqueFields = $this->getUniqueFields(); + // remove move_copy from array + unset($values['move_copy']); + + // make sure published is set + if (!isset($values['published'])) + { + $values['published'] = 0; + } + elseif (isset($values['published']) && !$this->canDo->get('tagged_verse.edit.state')) + { + $values['published'] = 0; + } + + $newIds = array(); + // Parent exists so let's proceed + while (!empty($pks)) + { + // Pop the first ID off the stack + $pk = array_shift($pks); + + $this->table->reset(); + + // only allow copy if user may edit this item. + if (!$this->user->authorise('tagged_verse.edit', $contexts[$pk])) + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // insert all set values + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + if (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + // update all unique fields + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $this->table->$uniqueField = $this->generateUnique($uniqueField,$this->table->$uniqueField); + } + } + + // Reset the ID because we are making a copy + $this->table->id = 0; + + // TODO: Deal with ordering? + // $this->table->ordering = 1; + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + + // Get the new item ID + $newId = $this->table->get('id'); + + // Add the new ID to the array + $newIds[$pk] = $newId; + } + + // Clean the cache + $this->cleanCache(); + + return $newIds; + } + + /** + * Batch move items to a new category + * + * @param integer $value The new category ID. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 12.2 + */ + protected function batchMove($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('tagged_verse'); + } + + if (!$this->canDo->get('tagged_verse.edit') && !$this->canDo->get('tagged_verse.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // make sure published only updates if user has the permission. + if (isset($values['published']) && !$this->canDo->get('tagged_verse.edit.state')) + { + unset($values['published']); + } + // remove move_copy from array + unset($values['move_copy']); + + // Parent exists so we proceed + foreach ($pks as $pk) + { + if (!$this->user->authorise('tagged_verse.edit', $contexts[$pk])) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // insert all set values. + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + // Do special action for access. + if ('access' === $key && strlen($value) > 0) + { + $this->table->$key = $value; + } + elseif (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + } + + // Clean the cache + $this->cleanCache(); + + return true; + } + + /** + * Method to save the form data. + * + * @param array $data The form data. + * + * @return boolean True on success. + * + * @since 1.6 + */ + public function save($data) + { + $input = JFactory::getApplication()->input; + $filter = JFilterInput::getInstance(); + + // set the metadata to the Item Data + if (isset($data['metadata']) && isset($data['metadata']['author'])) + { + $data['metadata']['author'] = $filter->clean($data['metadata']['author'], 'TRIM'); + + $metadata = new JRegistry; + $metadata->loadArray($data['metadata']); + $data['metadata'] = (string) $metadata; + } + + + // Set the GUID if empty or not valid + if (empty($data['guid']) && $data['id'] > 0) + { + // get the existing one + $data['guid'] = (string) GetHelper::var('tagged_verse', $data['id'], 'id', 'guid'); + } + + // Set the GUID if empty or not valid + while (!GuidHelper::valid($data['guid'], "tagged_verse", $data['id'])) + { + // must always be set + $data['guid'] = (string) GuidHelper::get(); + } + + // Set the Params Items to data + if (isset($data['params']) && is_array($data['params'])) + { + $params = new JRegistry; + $params->loadArray($data['params']); + $data['params'] = (string) $params; + } + + // Alter the unique field for save as copy + if ($input->get('task') === 'save2copy') + { + // Automatic handling of other unique fields + $uniqueFields = $this->getUniqueFields(); + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $data[$uniqueField] = $this->generateUnique($uniqueField,$data[$uniqueField]); + } + } + } + + if (parent::save($data)) + { + return true; + } + return false; + } + + /** + * Method to generate a unique value. + * + * @param string $field name. + * @param string $value data. + * + * @return string New value. + * + * @since 3.0 + */ + protected function generateUnique($field,$value) + { + + // set field value unique + $table = $this->getTable(); + + while ($table->load(array($field => $value))) + { + $value = StringHelper::increment($value); + } + + return $value; + } +} diff --git a/admin/models/tagged_verses.php b/admin/models/tagged_verses.php new file mode 100644 index 0000000..a99de09 --- /dev/null +++ b/admin/models/tagged_verses.php @@ -0,0 +1,629 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\ListModel; +use Joomla\Utilities\ArrayHelper; + +/** + * Tagged_verses List Model + */ +class GetbibleModelTagged_verses extends ListModel +{ + public function __construct($config = array()) + { + if (empty($config['filter_fields'])) + { + $config['filter_fields'] = array( + 'a.id','id', + 'a.published','published', + 'a.access','access', + 'a.ordering','ordering', + 'a.created_by','created_by', + 'a.modified_by','modified_by', + 'a.book_nr','book_nr', + 'g.translation','abbreviation', + 'h.name','linker', + 'i.name','tag', + 'a.verse','verse', + 'a.chapter','chapter' + ); + } + + parent::__construct($config); + } + + /** + * Method to auto-populate the model state. + * + * Note. Calling getState in this method will result in recursion. + * + * @param string $ordering An optional ordering field. + * @param string $direction An optional direction (asc|desc). + * + * @return void + * + */ + protected function populateState($ordering = null, $direction = null) + { + $app = JFactory::getApplication(); + + // Adjust the context to support modal layouts. + if ($layout = $app->input->get('layout')) + { + $this->context .= '.' . $layout; + } + + // Check if the form was submitted + $formSubmited = $app->input->post->get('form_submited'); + + $published = $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', ''); + $this->setState('filter.published', $published); + + $created_by = $this->getUserStateFromRequest($this->context . '.filter.created_by', 'filter_created_by', ''); + $this->setState('filter.created_by', $created_by); + + $created = $this->getUserStateFromRequest($this->context . '.filter.created', 'filter_created'); + $this->setState('filter.created', $created); + + $sorting = $this->getUserStateFromRequest($this->context . '.filter.sorting', 'filter_sorting', 0, 'int'); + $this->setState('filter.sorting', $sorting); + + $search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search'); + $this->setState('filter.search', $search); + + $book_nr = $this->getUserStateFromRequest($this->context . '.filter.book_nr', 'filter_book_nr'); + if ($formSubmited) + { + $book_nr = $app->input->post->get('book_nr'); + $this->setState('filter.book_nr', $book_nr); + } + + $abbreviation = $this->getUserStateFromRequest($this->context . '.filter.abbreviation', 'filter_abbreviation'); + if ($formSubmited) + { + $abbreviation = $app->input->post->get('abbreviation'); + $this->setState('filter.abbreviation', $abbreviation); + } + + $access = $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access'); + if ($formSubmited) + { + $access = $app->input->post->get('access'); + $this->setState('filter.access', $access); + } + + $linker = $this->getUserStateFromRequest($this->context . '.filter.linker', 'filter_linker'); + if ($formSubmited) + { + $linker = $app->input->post->get('linker'); + $this->setState('filter.linker', $linker); + } + + $tag = $this->getUserStateFromRequest($this->context . '.filter.tag', 'filter_tag'); + if ($formSubmited) + { + $tag = $app->input->post->get('tag'); + $this->setState('filter.tag', $tag); + } + + $verse = $this->getUserStateFromRequest($this->context . '.filter.verse', 'filter_verse'); + if ($formSubmited) + { + $verse = $app->input->post->get('verse'); + $this->setState('filter.verse', $verse); + } + + $chapter = $this->getUserStateFromRequest($this->context . '.filter.chapter', 'filter_chapter'); + if ($formSubmited) + { + $chapter = $app->input->post->get('chapter'); + $this->setState('filter.chapter', $chapter); + } + + // List state information. + parent::populateState($ordering, $direction); + } + + /** + * Method to get an array of data items. + * + * @return mixed An array of data items on success, false on failure. + */ + public function getItems() + { + // Check in items + $this->checkInNow(); + + // load parent items + $items = parent::getItems(); + + // Set values to display correctly. + if (GetbibleHelper::checkArray($items)) + { + // Get the user object if not set. + if (!isset($user) || !GetbibleHelper::checkObject($user)) + { + $user = JFactory::getUser(); + } + foreach ($items as $nr => &$item) + { + // Remove items the user can't access. + $access = ($user->authorise('tagged_verse.access', 'com_getbible.tagged_verse.' . (int) $item->id) && $user->authorise('tagged_verse.access', 'com_getbible')); + if (!$access) + { + unset($items[$nr]); + continue; + } + + $item->book_nr = $item->book_nr . ' ' . $item->chapter . ':' . $item->verse; + } + } + + // set selection value to a translatable value + if (GetbibleHelper::checkArray($items)) + { + foreach ($items as $nr => &$item) + { + // convert access + $item->access = $this->selectionTranslation($item->access, 'access'); + } + } + + + // return items + return $items; + } + + /** + * Method to convert selection values to translatable string. + * + * @return translatable string + */ + public function selectionTranslation($value,$name) + { + // Array of access language strings + if ($name === 'access') + { + $accessArray = array( + 1 => 'COM_GETBIBLE_TAGGED_VERSE_PUBLIC', + 0 => 'COM_GETBIBLE_TAGGED_VERSE_PRIVATE' + ); + // Now check if value is found in this array + if (isset($accessArray[$value]) && GetbibleHelper::checkString($accessArray[$value])) + { + return $accessArray[$value]; + } + } + return $value; + } + + /** + * Method to build an SQL query to load the list data. + * + * @return string An SQL query + */ + protected function getListQuery() + { + // Get the user object. + $user = JFactory::getUser(); + // Create a new query object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + + // Select some fields + $query->select('a.*'); + + // From the getbible_item table + $query->from($db->quoteName('#__getbible_tagged_verse', 'a')); + + // From the getbible_translation table. + $query->select($db->quoteName(['g.translation','g.id'],['abbreviation_translation','abbreviation_id'])); + $query->join('LEFT', $db->quoteName('#__getbible_translation', 'g') . ' ON (' . $db->quoteName('a.abbreviation') . ' = ' . $db->quoteName('g.abbreviation') . ')'); + + // From the getbible_linker table. + $query->select($db->quoteName(['h.name','h.id'],['linker_name','linker_id'])); + $query->join('LEFT', $db->quoteName('#__getbible_linker', 'h') . ' ON (' . $db->quoteName('a.linker') . ' = ' . $db->quoteName('h.guid') . ')'); + + // From the getbible_tag table. + $query->select($db->quoteName(['i.name','i.id'],['tag_name','tag_id'])); + $query->join('LEFT', $db->quoteName('#__getbible_tag', 'i') . ' ON (' . $db->quoteName('a.tag') . ' = ' . $db->quoteName('i.guid') . ')'); + + // Filter by published state + $published = $this->getState('filter.published'); + if (is_numeric($published)) + { + $query->where('a.published = ' . (int) $published); + } + elseif ($published === '') + { + $query->where('(a.published = 0 OR a.published = 1)'); + } + + // Join over the asset groups. + $query->select('ag.title AS access_level'); + $query->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access'); + // Implement View Level Access + if (!$user->authorise('core.options', 'com_getbible')) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + // Filter by search. + $search = $this->getState('filter.search'); + if (!empty($search)) + { + if (stripos($search, 'id:') === 0) + { + $query->where('a.id = ' . (int) substr($search, 3)); + } + else + { + $search = $db->quote('%' . $db->escape($search) . '%'); + $query->where('(a.tag LIKE '.$search.' OR i.name LIKE '.$search.')'); + } + } + + // Filter by Book_nr. + $_book_nr = $this->getState('filter.book_nr'); + if (is_numeric($_book_nr)) + { + if (is_float($_book_nr)) + { + $query->where('a.book_nr = ' . (float) $_book_nr); + } + else + { + $query->where('a.book_nr = ' . (int) $_book_nr); + } + } + elseif (GetbibleHelper::checkString($_book_nr)) + { + $query->where('a.book_nr = ' . $db->quote($db->escape($_book_nr))); + } + elseif (GetbibleHelper::checkArray($_book_nr)) + { + // Secure the array for the query + $_book_nr = array_map( function ($val) use(&$db) { + if (is_numeric($val)) + { + if (is_float($val)) + { + return (float) $val; + } + else + { + return (int) $val; + } + } + elseif (GetbibleHelper::checkString($val)) + { + return $db->quote($db->escape($val)); + } + }, $_book_nr); + // Filter by the Book_nr Array. + $query->where('a.book_nr IN (' . implode(',', $_book_nr) . ')'); + } + // Filter by Abbreviation. + $_abbreviation = $this->getState('filter.abbreviation'); + if (is_numeric($_abbreviation)) + { + if (is_float($_abbreviation)) + { + $query->where('a.abbreviation = ' . (float) $_abbreviation); + } + else + { + $query->where('a.abbreviation = ' . (int) $_abbreviation); + } + } + elseif (GetbibleHelper::checkString($_abbreviation)) + { + $query->where('a.abbreviation = ' . $db->quote($db->escape($_abbreviation))); + } + elseif (GetbibleHelper::checkArray($_abbreviation)) + { + // Secure the array for the query + $_abbreviation = array_map( function ($val) use(&$db) { + if (is_numeric($val)) + { + if (is_float($val)) + { + return (float) $val; + } + else + { + return (int) $val; + } + } + elseif (GetbibleHelper::checkString($val)) + { + return $db->quote($db->escape($val)); + } + }, $_abbreviation); + // Filter by the Abbreviation Array. + $query->where('a.abbreviation IN (' . implode(',', $_abbreviation) . ')'); + } + // Filter by Access. + $_access = $this->getState('filter.access'); + if (is_numeric($_access)) + { + if (is_float($_access)) + { + $query->where('a.access = ' . (float) $_access); + } + else + { + $query->where('a.access = ' . (int) $_access); + } + } + elseif (GetbibleHelper::checkString($_access)) + { + $query->where('a.access = ' . $db->quote($db->escape($_access))); + } + // Filter by Linker. + $_linker = $this->getState('filter.linker'); + if (is_numeric($_linker)) + { + if (is_float($_linker)) + { + $query->where('a.linker = ' . (float) $_linker); + } + else + { + $query->where('a.linker = ' . (int) $_linker); + } + } + elseif (GetbibleHelper::checkString($_linker)) + { + $query->where('a.linker = ' . $db->quote($db->escape($_linker))); + } + // Filter by Tag. + $_tag = $this->getState('filter.tag'); + if (is_numeric($_tag)) + { + if (is_float($_tag)) + { + $query->where('a.tag = ' . (float) $_tag); + } + else + { + $query->where('a.tag = ' . (int) $_tag); + } + } + elseif (GetbibleHelper::checkString($_tag)) + { + $query->where('a.tag = ' . $db->quote($db->escape($_tag))); + } + // Filter by Verse. + $_verse = $this->getState('filter.verse'); + if (is_numeric($_verse)) + { + if (is_float($_verse)) + { + $query->where('a.verse = ' . (float) $_verse); + } + else + { + $query->where('a.verse = ' . (int) $_verse); + } + } + elseif (GetbibleHelper::checkString($_verse)) + { + $query->where('a.verse = ' . $db->quote($db->escape($_verse))); + } + elseif (GetbibleHelper::checkArray($_verse)) + { + // Secure the array for the query + $_verse = array_map( function ($val) use(&$db) { + if (is_numeric($val)) + { + if (is_float($val)) + { + return (float) $val; + } + else + { + return (int) $val; + } + } + elseif (GetbibleHelper::checkString($val)) + { + return $db->quote($db->escape($val)); + } + }, $_verse); + // Filter by the Verse Array. + $query->where('a.verse IN (' . implode(',', $_verse) . ')'); + } + // Filter by Chapter. + $_chapter = $this->getState('filter.chapter'); + if (is_numeric($_chapter)) + { + if (is_float($_chapter)) + { + $query->where('a.chapter = ' . (float) $_chapter); + } + else + { + $query->where('a.chapter = ' . (int) $_chapter); + } + } + elseif (GetbibleHelper::checkString($_chapter)) + { + $query->where('a.chapter = ' . $db->quote($db->escape($_chapter))); + } + elseif (GetbibleHelper::checkArray($_chapter)) + { + // Secure the array for the query + $_chapter = array_map( function ($val) use(&$db) { + if (is_numeric($val)) + { + if (is_float($val)) + { + return (float) $val; + } + else + { + return (int) $val; + } + } + elseif (GetbibleHelper::checkString($val)) + { + return $db->quote($db->escape($val)); + } + }, $_chapter); + // Filter by the Chapter Array. + $query->where('a.chapter IN (' . implode(',', $_chapter) . ')'); + } + + // Add the list ordering clause. + $orderCol = $this->state->get('list.ordering', 'a.id'); + $orderDirn = $this->state->get('list.direction', 'desc'); + if ($orderCol != '') + { + $query->order($db->escape($orderCol . ' ' . $orderDirn)); + } + + return $query; + } + + /** + * Method to get a store id based on model configuration state. + * + * @return string A store id. + * + */ + protected function getStoreId($id = '') + { + // Compile the store id. + $id .= ':' . $this->getState('filter.id'); + $id .= ':' . $this->getState('filter.search'); + $id .= ':' . $this->getState('filter.published'); + $id .= ':' . $this->getState('filter.ordering'); + $id .= ':' . $this->getState('filter.created_by'); + $id .= ':' . $this->getState('filter.modified_by'); + // Check if the value is an array + $_book_nr = $this->getState('filter.book_nr'); + if (GetbibleHelper::checkArray($_book_nr)) + { + $id .= ':' . implode(':', $_book_nr); + } + // Check if this is only an number or string + elseif (is_numeric($_book_nr) + || GetbibleHelper::checkString($_book_nr)) + { + $id .= ':' . $_book_nr; + } + // Check if the value is an array + $_abbreviation = $this->getState('filter.abbreviation'); + if (GetbibleHelper::checkArray($_abbreviation)) + { + $id .= ':' . implode(':', $_abbreviation); + } + // Check if this is only an number or string + elseif (is_numeric($_abbreviation) + || GetbibleHelper::checkString($_abbreviation)) + { + $id .= ':' . $_abbreviation; + } + $id .= ':' . $this->getState('filter.linker'); + $id .= ':' . $this->getState('filter.tag'); + // Check if the value is an array + $_verse = $this->getState('filter.verse'); + if (GetbibleHelper::checkArray($_verse)) + { + $id .= ':' . implode(':', $_verse); + } + // Check if this is only an number or string + elseif (is_numeric($_verse) + || GetbibleHelper::checkString($_verse)) + { + $id .= ':' . $_verse; + } + // Check if the value is an array + $_chapter = $this->getState('filter.chapter'); + if (GetbibleHelper::checkArray($_chapter)) + { + $id .= ':' . implode(':', $_chapter); + } + // Check if this is only an number or string + elseif (is_numeric($_chapter) + || GetbibleHelper::checkString($_chapter)) + { + $id .= ':' . $_chapter; + } + + return parent::getStoreId($id); + } + + /** + * Build an SQL query to checkin all items left checked out longer then a set time. + * + * @return a bool + * + */ + protected function checkInNow() + { + // Get set check in time + $time = JComponentHelper::getParams('com_getbible')->get('check_in'); + + if ($time) + { + + // Get a db connection. + $db = JFactory::getDbo(); + // Reset query. + $query = $db->getQuery(true); + $query->select('*'); + $query->from($db->quoteName('#__getbible_tagged_verse')); + // Only select items that are checked out. + $query->where($db->quoteName('checked_out') . '!=0'); + $db->setQuery($query, 0, 1); + $db->execute(); + if ($db->getNumRows()) + { + // Get Yesterdays date. + $date = JFactory::getDate()->modify($time)->toSql(); + // Reset query. + $query = $db->getQuery(true); + + // Fields to update. + $fields = array( + $db->quoteName('checked_out_time') . '=\'0000-00-00 00:00:00\'', + $db->quoteName('checked_out') . '=0' + ); + + // Conditions for which records should be updated. + $conditions = array( + $db->quoteName('checked_out') . '!=0', + $db->quoteName('checked_out_time') . '<\''.$date.'\'' + ); + + // Check table. + $query->update($db->quoteName('#__getbible_tagged_verse'))->set($fields)->where($conditions); + + $db->setQuery($query); + + $db->execute(); + } + } + + return false; + } +} diff --git a/admin/models/tags.php b/admin/models/tags.php new file mode 100644 index 0000000..c607b79 --- /dev/null +++ b/admin/models/tags.php @@ -0,0 +1,363 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\ListModel; +use Joomla\Utilities\ArrayHelper; + +/** + * Tags List Model + */ +class GetbibleModelTags extends ListModel +{ + public function __construct($config = array()) + { + if (empty($config['filter_fields'])) + { + $config['filter_fields'] = array( + 'a.id','id', + 'a.published','published', + 'a.access','access', + 'a.ordering','ordering', + 'a.created_by','created_by', + 'a.modified_by','modified_by', + 'g.name','linker', + 'a.name','name' + ); + } + + parent::__construct($config); + } + + /** + * Method to auto-populate the model state. + * + * Note. Calling getState in this method will result in recursion. + * + * @param string $ordering An optional ordering field. + * @param string $direction An optional direction (asc|desc). + * + * @return void + * + */ + protected function populateState($ordering = null, $direction = null) + { + $app = JFactory::getApplication(); + + // Adjust the context to support modal layouts. + if ($layout = $app->input->get('layout')) + { + $this->context .= '.' . $layout; + } + + // Check if the form was submitted + $formSubmited = $app->input->post->get('form_submited'); + + $published = $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', ''); + $this->setState('filter.published', $published); + + $created_by = $this->getUserStateFromRequest($this->context . '.filter.created_by', 'filter_created_by', ''); + $this->setState('filter.created_by', $created_by); + + $created = $this->getUserStateFromRequest($this->context . '.filter.created', 'filter_created'); + $this->setState('filter.created', $created); + + $sorting = $this->getUserStateFromRequest($this->context . '.filter.sorting', 'filter_sorting', 0, 'int'); + $this->setState('filter.sorting', $sorting); + + $search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search'); + $this->setState('filter.search', $search); + + $linker = $this->getUserStateFromRequest($this->context . '.filter.linker', 'filter_linker'); + if ($formSubmited) + { + $linker = $app->input->post->get('linker'); + $this->setState('filter.linker', $linker); + } + + $access = $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access'); + if ($formSubmited) + { + $access = $app->input->post->get('access'); + $this->setState('filter.access', $access); + } + + $name = $this->getUserStateFromRequest($this->context . '.filter.name', 'filter_name'); + if ($formSubmited) + { + $name = $app->input->post->get('name'); + $this->setState('filter.name', $name); + } + + // List state information. + parent::populateState($ordering, $direction); + } + + /** + * Method to get an array of data items. + * + * @return mixed An array of data items on success, false on failure. + */ + public function getItems() + { + // Check in items + $this->checkInNow(); + + // load parent items + $items = parent::getItems(); + + // Set values to display correctly. + if (GetbibleHelper::checkArray($items)) + { + // Get the user object if not set. + if (!isset($user) || !GetbibleHelper::checkObject($user)) + { + $user = JFactory::getUser(); + } + foreach ($items as $nr => &$item) + { + // Remove items the user can't access. + $access = ($user->authorise('tag.access', 'com_getbible.tag.' . (int) $item->id) && $user->authorise('tag.access', 'com_getbible')); + if (!$access) + { + unset($items[$nr]); + continue; + } + + } + } + + // set selection value to a translatable value + if (GetbibleHelper::checkArray($items)) + { + foreach ($items as $nr => &$item) + { + // convert access + $item->access = $this->selectionTranslation($item->access, 'access'); + } + } + + + // return items + return $items; + } + + /** + * Method to convert selection values to translatable string. + * + * @return translatable string + */ + public function selectionTranslation($value,$name) + { + // Array of access language strings + if ($name === 'access') + { + $accessArray = array( + 1 => 'COM_GETBIBLE_TAG_PUBLIC', + 0 => 'COM_GETBIBLE_TAG_PRIVATE' + ); + // Now check if value is found in this array + if (isset($accessArray[$value]) && GetbibleHelper::checkString($accessArray[$value])) + { + return $accessArray[$value]; + } + } + return $value; + } + + /** + * Method to build an SQL query to load the list data. + * + * @return string An SQL query + */ + protected function getListQuery() + { + // Get the user object. + $user = JFactory::getUser(); + // Create a new query object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + + // Select some fields + $query->select('a.*'); + + // From the getbible_item table + $query->from($db->quoteName('#__getbible_tag', 'a')); + + // From the getbible_linker table. + $query->select($db->quoteName(['g.name','g.id'],['linker_name','linker_id'])); + $query->join('LEFT', $db->quoteName('#__getbible_linker', 'g') . ' ON (' . $db->quoteName('a.linker') . ' = ' . $db->quoteName('g.guid') . ')'); + + // Filter by published state + $published = $this->getState('filter.published'); + if (is_numeric($published)) + { + $query->where('a.published = ' . (int) $published); + } + elseif ($published === '') + { + $query->where('(a.published = 0 OR a.published = 1)'); + } + + // Join over the asset groups. + $query->select('ag.title AS access_level'); + $query->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access'); + // Implement View Level Access + if (!$user->authorise('core.options', 'com_getbible')) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + // Filter by search. + $search = $this->getState('filter.search'); + if (!empty($search)) + { + if (stripos($search, 'id:') === 0) + { + $query->where('a.id = ' . (int) substr($search, 3)); + } + else + { + $search = $db->quote('%' . $db->escape($search) . '%'); + $query->where('(a.name LIKE '.$search.' OR a.linker LIKE '.$search.' OR g.name LIKE '.$search.' OR a.description LIKE '.$search.')'); + } + } + + // Filter by Linker. + $_linker = $this->getState('filter.linker'); + if (is_numeric($_linker)) + { + if (is_float($_linker)) + { + $query->where('a.linker = ' . (float) $_linker); + } + else + { + $query->where('a.linker = ' . (int) $_linker); + } + } + elseif (GetbibleHelper::checkString($_linker)) + { + $query->where('a.linker = ' . $db->quote($db->escape($_linker))); + } + // Filter by Access. + $_access = $this->getState('filter.access'); + if (is_numeric($_access)) + { + if (is_float($_access)) + { + $query->where('a.access = ' . (float) $_access); + } + else + { + $query->where('a.access = ' . (int) $_access); + } + } + elseif (GetbibleHelper::checkString($_access)) + { + $query->where('a.access = ' . $db->quote($db->escape($_access))); + } + + // Add the list ordering clause. + $orderCol = $this->state->get('list.ordering', 'a.id'); + $orderDirn = $this->state->get('list.direction', 'desc'); + if ($orderCol != '') + { + $query->order($db->escape($orderCol . ' ' . $orderDirn)); + } + + return $query; + } + + /** + * Method to get a store id based on model configuration state. + * + * @return string A store id. + * + */ + protected function getStoreId($id = '') + { + // Compile the store id. + $id .= ':' . $this->getState('filter.id'); + $id .= ':' . $this->getState('filter.search'); + $id .= ':' . $this->getState('filter.published'); + $id .= ':' . $this->getState('filter.ordering'); + $id .= ':' . $this->getState('filter.created_by'); + $id .= ':' . $this->getState('filter.modified_by'); + $id .= ':' . $this->getState('filter.linker'); + $id .= ':' . $this->getState('filter.name'); + + return parent::getStoreId($id); + } + + /** + * Build an SQL query to checkin all items left checked out longer then a set time. + * + * @return a bool + * + */ + protected function checkInNow() + { + // Get set check in time + $time = JComponentHelper::getParams('com_getbible')->get('check_in'); + + if ($time) + { + + // Get a db connection. + $db = JFactory::getDbo(); + // Reset query. + $query = $db->getQuery(true); + $query->select('*'); + $query->from($db->quoteName('#__getbible_tag')); + // Only select items that are checked out. + $query->where($db->quoteName('checked_out') . '!=0'); + $db->setQuery($query, 0, 1); + $db->execute(); + if ($db->getNumRows()) + { + // Get Yesterdays date. + $date = JFactory::getDate()->modify($time)->toSql(); + // Reset query. + $query = $db->getQuery(true); + + // Fields to update. + $fields = array( + $db->quoteName('checked_out_time') . '=\'0000-00-00 00:00:00\'', + $db->quoteName('checked_out') . '=0' + ); + + // Conditions for which records should be updated. + $conditions = array( + $db->quoteName('checked_out') . '!=0', + $db->quoteName('checked_out_time') . '<\''.$date.'\'' + ); + + // Check table. + $query->update($db->quoteName('#__getbible_tag'))->set($fields)->where($conditions); + + $db->setQuery($query); + + $db->execute(); + } + } + + return false; + } +} diff --git a/admin/models/translation.php b/admin/models/translation.php new file mode 100644 index 0000000..b2ebca9 --- /dev/null +++ b/admin/models/translation.php @@ -0,0 +1,1214 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\AdminModel; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; + +/** + * Getbible Translation Admin Model + */ +class GetbibleModelTranslation extends AdminModel +{ + /** + * The tab layout fields array. + * + * @var array + */ + protected $tabLayoutFields = array( + 'details' => array( + 'left' => array( + 'distribution_abbreviation', + 'distribution_versification', + 'distribution_version', + 'distribution_version_date', + 'distribution_lcsh', + 'encoding', + 'sha' + ), + 'right' => array( + 'language', + 'lang', + 'distribution_sourcetype', + 'distribution_source', + 'distribution_license' + ), + 'fullwidth' => array( + 'distribution_about', + 'distribution_history' + ), + 'above' => array( + 'translation', + 'abbreviation', + 'direction' + ) + ) + ); + + /** + * @var string The prefix to use with controller messages. + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE'; + + /** + * The type alias for this content type. + * + * @var string + * @since 3.2 + */ + public $typeAlias = 'com_getbible.translation'; + + /** + * Returns a Table object, always creating it + * + * @param type $type The table type to instantiate + * @param string $prefix A prefix for the table class name. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JTable A database object + * + * @since 1.6 + */ + public function getTable($type = 'translation', $prefix = 'GetbibleTable', $config = array()) + { + // add table path for when model gets used from other component + $this->addTablePath(JPATH_ADMINISTRATOR . '/components/com_getbible/tables'); + // get instance of the table + return JTable::getInstance($type, $prefix, $config); + }###ADMIN_CUSTOM_BUTTONS_METHOD### + + /** + * Method to get a single record. + * + * @param integer $pk The id of the primary key. + * + * @return mixed Object on success, false on failure. + * + * @since 1.6 + */ + public function getItem($pk = null) + { + if ($item = parent::getItem($pk)) + { + if (!empty($item->params) && !is_array($item->params)) + { + // Convert the params field to an array. + $registry = new Registry; + $registry->loadString($item->params); + $item->params = $registry->toArray(); + } + + if (!empty($item->metadata)) + { + // Convert the metadata field to an array. + $registry = new Registry; + $registry->loadString($item->metadata); + $item->metadata = $registry->toArray(); + } + + if (!empty($item->distribution_history)) + { + // Convert the distribution_history field to an array. + $distribution_history = new Registry; + $distribution_history->loadString($item->distribution_history); + $item->distribution_history = $distribution_history->toArray(); + } + } + + return $item; + } + + /** + * Method to get the record form. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * @param array $options Optional array of options for the form creation. + * + * @return mixed A JForm object on success, false on failure + * + * @since 1.6 + */ + public function getForm($data = array(), $loadData = true, $options = array('control' => 'jform')) + { + // set load data option + $options['load_data'] = $loadData; + // check if xpath was set in options + $xpath = false; + if (isset($options['xpath'])) + { + $xpath = $options['xpath']; + unset($options['xpath']); + } + // check if clear form was set in options + $clear = false; + if (isset($options['clear'])) + { + $clear = $options['clear']; + unset($options['clear']); + } + + // Get the form. + $form = $this->loadForm('com_getbible.translation', 'translation', $options, $clear, $xpath); + + if (empty($form)) + { + return false; + } + + $jinput = JFactory::getApplication()->input; + + // The front end calls this model and uses a_id to avoid id clashes so we need to check for that first. + if ($jinput->get('a_id')) + { + $id = $jinput->get('a_id', 0, 'INT'); + } + // The back end uses id so we use that the rest of the time and set it to 0 by default. + else + { + $id = $jinput->get('id', 0, 'INT'); + } + + $user = JFactory::getUser(); + + // Check for existing item. + // Modify the form based on Edit State access controls. + if ($id != 0 && (!$user->authorise('translation.edit.state', 'com_getbible.translation.' . (int) $id)) + || ($id == 0 && !$user->authorise('translation.edit.state', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('ordering', 'disabled', 'true'); + $form->setFieldAttribute('published', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('ordering', 'filter', 'unset'); + $form->setFieldAttribute('published', 'filter', 'unset'); + } + // If this is a new item insure the greated by is set. + if (0 == $id) + { + // Set the created_by to this user + $form->setValue('created_by', null, $user->id); + } + // Modify the form based on Edit Creaded By access controls. + if ($id != 0 && (!$user->authorise('translation.edit.created_by', 'com_getbible.translation.' . (int) $id)) + || ($id == 0 && !$user->authorise('translation.edit.created_by', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created_by', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('created_by', 'readonly', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created_by', 'filter', 'unset'); + } + // Modify the form based on Edit Creaded Date access controls. + if ($id != 0 && (!$user->authorise('translation.edit.created', 'com_getbible.translation.' . (int) $id)) + || ($id == 0 && !$user->authorise('translation.edit.created', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created', 'filter', 'unset'); + } + // Modify the form based on Edit Translation access controls. + if ($id != 0 && (!$user->authorise('translation.edit.translation', 'com_getbible.translation.' . (int) $id)) + || ($id == 0 && !$user->authorise('translation.edit.translation', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('translation', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('translation', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('translation')) + { + // Disable fields while saving. + $form->setFieldAttribute('translation', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('translation', 'required', 'false'); + } + } + // Modify the form based on Edit Abbreviation access controls. + if ($id != 0 && (!$user->authorise('translation.edit.abbreviation', 'com_getbible.translation.' . (int) $id)) + || ($id == 0 && !$user->authorise('translation.edit.abbreviation', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('abbreviation', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('abbreviation', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('abbreviation')) + { + // Disable fields while saving. + $form->setFieldAttribute('abbreviation', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('abbreviation', 'required', 'false'); + } + } + // Modify the form based on Edit Language access controls. + if ($id != 0 && (!$user->authorise('translation.edit.language', 'com_getbible.translation.' . (int) $id)) + || ($id == 0 && !$user->authorise('translation.edit.language', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('language', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('language', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('language')) + { + // Disable fields while saving. + $form->setFieldAttribute('language', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('language', 'required', 'false'); + } + } + // Modify the form based on Edit Direction access controls. + if ($id != 0 && (!$user->authorise('translation.edit.direction', 'com_getbible.translation.' . (int) $id)) + || ($id == 0 && !$user->authorise('translation.edit.direction', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('direction', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('direction', 'readonly', 'true'); + // Disable radio button for display. + $class = $form->getFieldAttribute('direction', 'class', ''); + $form->setFieldAttribute('direction', 'class', $class.' disabled no-click'); + // If there is no value continue. + if (!$form->getValue('direction')) + { + // Disable fields while saving. + $form->setFieldAttribute('direction', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('direction', 'required', 'false'); + } + } + // Modify the form based on Edit Distribution History access controls. + if ($id != 0 && (!$user->authorise('translation.edit.distribution_history', 'com_getbible.translation.' . (int) $id)) + || ($id == 0 && !$user->authorise('translation.edit.distribution_history', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('distribution_history', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('distribution_history', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('distribution_history')) + { + // Disable fields while saving. + $form->setFieldAttribute('distribution_history', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('distribution_history', 'required', 'false'); + } + } + // Modify the form based on Edit Distribution About access controls. + if ($id != 0 && (!$user->authorise('translation.edit.distribution_about', 'com_getbible.translation.' . (int) $id)) + || ($id == 0 && !$user->authorise('translation.edit.distribution_about', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('distribution_about', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('distribution_about', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('distribution_about')) + { + // Disable fields while saving. + $form->setFieldAttribute('distribution_about', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('distribution_about', 'required', 'false'); + } + } + // Modify the form based on Edit Distribution License access controls. + if ($id != 0 && (!$user->authorise('translation.edit.distribution_license', 'com_getbible.translation.' . (int) $id)) + || ($id == 0 && !$user->authorise('translation.edit.distribution_license', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('distribution_license', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('distribution_license', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('distribution_license')) + { + // Disable fields while saving. + $form->setFieldAttribute('distribution_license', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('distribution_license', 'required', 'false'); + } + } + // Modify the form based on Edit Distribution Source access controls. + if ($id != 0 && (!$user->authorise('translation.edit.distribution_source', 'com_getbible.translation.' . (int) $id)) + || ($id == 0 && !$user->authorise('translation.edit.distribution_source', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('distribution_source', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('distribution_source', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('distribution_source')) + { + // Disable fields while saving. + $form->setFieldAttribute('distribution_source', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('distribution_source', 'required', 'false'); + } + } + // Modify the form based on Edit Distribution Sourcetype access controls. + if ($id != 0 && (!$user->authorise('translation.edit.distribution_sourcetype', 'com_getbible.translation.' . (int) $id)) + || ($id == 0 && !$user->authorise('translation.edit.distribution_sourcetype', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('distribution_sourcetype', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('distribution_sourcetype', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('distribution_sourcetype')) + { + // Disable fields while saving. + $form->setFieldAttribute('distribution_sourcetype', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('distribution_sourcetype', 'required', 'false'); + } + } + // Modify the form based on Edit Distribution Versification access controls. + if ($id != 0 && (!$user->authorise('translation.edit.distribution_versification', 'com_getbible.translation.' . (int) $id)) + || ($id == 0 && !$user->authorise('translation.edit.distribution_versification', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('distribution_versification', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('distribution_versification', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('distribution_versification')) + { + // Disable fields while saving. + $form->setFieldAttribute('distribution_versification', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('distribution_versification', 'required', 'false'); + } + } + // Modify the form based on Edit Sha access controls. + if ($id != 0 && (!$user->authorise('translation.edit.sha', 'com_getbible.translation.' . (int) $id)) + || ($id == 0 && !$user->authorise('translation.edit.sha', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('sha', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('sha', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('sha')) + { + // Disable fields while saving. + $form->setFieldAttribute('sha', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('sha', 'required', 'false'); + } + } + // Modify the form based on Edit Encoding access controls. + if ($id != 0 && (!$user->authorise('translation.edit.encoding', 'com_getbible.translation.' . (int) $id)) + || ($id == 0 && !$user->authorise('translation.edit.encoding', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('encoding', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('encoding', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('encoding')) + { + // Disable fields while saving. + $form->setFieldAttribute('encoding', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('encoding', 'required', 'false'); + } + } + // Modify the form based on Edit Distribution Lcsh access controls. + if ($id != 0 && (!$user->authorise('translation.edit.distribution_lcsh', 'com_getbible.translation.' . (int) $id)) + || ($id == 0 && !$user->authorise('translation.edit.distribution_lcsh', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('distribution_lcsh', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('distribution_lcsh', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('distribution_lcsh')) + { + // Disable fields while saving. + $form->setFieldAttribute('distribution_lcsh', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('distribution_lcsh', 'required', 'false'); + } + } + // Modify the form based on Edit Distribution Version Date access controls. + if ($id != 0 && (!$user->authorise('translation.edit.distribution_version_date', 'com_getbible.translation.' . (int) $id)) + || ($id == 0 && !$user->authorise('translation.edit.distribution_version_date', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('distribution_version_date', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('distribution_version_date', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('distribution_version_date')) + { + // Disable fields while saving. + $form->setFieldAttribute('distribution_version_date', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('distribution_version_date', 'required', 'false'); + } + } + // Modify the form based on Edit Distribution Version access controls. + if ($id != 0 && (!$user->authorise('translation.edit.distribution_version', 'com_getbible.translation.' . (int) $id)) + || ($id == 0 && !$user->authorise('translation.edit.distribution_version', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('distribution_version', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('distribution_version', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('distribution_version')) + { + // Disable fields while saving. + $form->setFieldAttribute('distribution_version', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('distribution_version', 'required', 'false'); + } + } + // Modify the form based on Edit Lang access controls. + if ($id != 0 && (!$user->authorise('translation.edit.lang', 'com_getbible.translation.' . (int) $id)) + || ($id == 0 && !$user->authorise('translation.edit.lang', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('lang', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('lang', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('lang')) + { + // Disable fields while saving. + $form->setFieldAttribute('lang', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('lang', 'required', 'false'); + } + } + // Modify the form based on Edit Distribution Abbreviation access controls. + if ($id != 0 && (!$user->authorise('translation.edit.distribution_abbreviation', 'com_getbible.translation.' . (int) $id)) + || ($id == 0 && !$user->authorise('translation.edit.distribution_abbreviation', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('distribution_abbreviation', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('distribution_abbreviation', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('distribution_abbreviation')) + { + // Disable fields while saving. + $form->setFieldAttribute('distribution_abbreviation', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('distribution_abbreviation', 'required', 'false'); + } + } + // Only load these values if no id is found + if (0 == $id) + { + // Set redirected view name + $redirectedView = $jinput->get('ref', null, 'STRING'); + // Set field name (or fall back to view name) + $redirectedField = $jinput->get('field', $redirectedView, 'STRING'); + // Set redirected view id + $redirectedId = $jinput->get('refid', 0, 'INT'); + // Set field id (or fall back to redirected view id) + $redirectedValue = $jinput->get('field_id', $redirectedId, 'INT'); + if (0 != $redirectedValue && $redirectedField) + { + // Now set the local-redirected field default value + $form->setValue($redirectedField, null, $redirectedValue); + } + } + return $form; + } + + /** + * Method to get the script that have to be included on the form + * + * @return string script files + */ + public function getScript() + { + return 'media/com_getbible/js/translation.js'; + } + + /** + * Method to test whether a record can be deleted. + * + * @param object $record A record object. + * + * @return boolean True if allowed to delete the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canDelete($record) + { + if (!empty($record->id)) + { + if ($record->published != -2) + { + return; + } + + $user = JFactory::getUser(); + // The record has been set. Check the record permissions. + return $user->authorise('translation.delete', 'com_getbible.translation.' . (int) $record->id); + } + return false; + } + + /** + * Method to test whether a record can have its state edited. + * + * @param object $record A record object. + * + * @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canEditState($record) + { + $user = JFactory::getUser(); + $recordId = (!empty($record->id)) ? $record->id : 0; + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('translation.edit.state', 'com_getbible.translation.' . (int) $recordId); + if (!$permission && !is_null($permission)) + { + return false; + } + } + // In the absense of better information, revert to the component permissions. + return $user->authorise('translation.edit.state', 'com_getbible'); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * @since 2.5 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // Check specific edit permission then general edit permission. + $user = JFactory::getUser(); + + return $user->authorise('translation.edit', 'com_getbible.translation.'. ((int) isset($data[$key]) ? $data[$key] : 0)) or $user->authorise('translation.edit', 'com_getbible'); + } + + /** + * Prepare and sanitise the table data prior to saving. + * + * @param JTable $table A JTable object. + * + * @return void + * + * @since 1.6 + */ + protected function prepareTable($table) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if (isset($table->name)) + { + $table->name = htmlspecialchars_decode($table->name, ENT_QUOTES); + } + + if (isset($table->alias) && empty($table->alias)) + { + $table->generateAlias(); + } + + if (empty($table->id)) + { + $table->created = $date->toSql(); + // set the user + if ($table->created_by == 0 || empty($table->created_by)) + { + $table->created_by = $user->id; + } + // Set ordering to the last item if not set + if (empty($table->ordering)) + { + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select('MAX(ordering)') + ->from($db->quoteName('#__getbible_translation')); + $db->setQuery($query); + $max = $db->loadResult(); + + $table->ordering = $max + 1; + } + } + else + { + $table->modified = $date->toSql(); + $table->modified_by = $user->id; + } + + if (!empty($table->id)) + { + // Increment the items version number. + $table->version++; + } + } + + /** + * Method to get the data that should be injected in the form. + * + * @return mixed The data for the form. + * + * @since 1.6 + */ + protected function loadFormData() + { + // Check the session for previously entered form data. + $data = JFactory::getApplication()->getUserState('com_getbible.edit.translation.data', array()); + + if (empty($data)) + { + $data = $this->getItem(); + // run the perprocess of the data + $this->preprocessData('com_getbible.translation', $data); + } + + return $data; + } + + /** + * Method to get the unique fields of this table. + * + * @return mixed An array of field names, boolean false if none is set. + * + * @since 3.0 + */ + protected function getUniqueFields() + { + return false; + } + + /** + * Method to delete one or more records. + * + * @param array &$pks An array of record primary keys. + * + * @return boolean True if successful, false if an error occurs. + * + * @since 12.2 + */ + public function delete(&$pks) + { + if (!parent::delete($pks)) + { + return false; + } + + return true; + } + + /** + * Method to change the published state of one or more records. + * + * @param array &$pks A list of the primary keys to change. + * @param integer $value The value of the published state. + * + * @return boolean True on success. + * + * @since 12.2 + */ + public function publish(&$pks, $value = 1) + { + if (!parent::publish($pks, $value)) + { + return false; + } + + return true; + } + + /** + * Method to perform batch operations on an item or a set of items. + * + * @param array $commands An array of commands to perform. + * @param array $pks An array of item ids. + * @param array $contexts An array of item contexts. + * + * @return boolean Returns true on success, false on failure. + * + * @since 12.2 + */ + public function batch($commands, $pks, $contexts) + { + // Sanitize ids. + $pks = array_unique($pks); + ArrayHelper::toInteger($pks); + + // Remove any values of zero. + if (array_search(0, $pks, true)) + { + unset($pks[array_search(0, $pks, true)]); + } + + if (empty($pks)) + { + $this->setError(JText::_('JGLOBAL_NO_ITEM_SELECTED')); + return false; + } + + $done = false; + + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->contentType = new JUcmType; + $this->type = $this->contentType->getTypeByTable($this->tableClassName); + $this->canDo = GetbibleHelper::getActions('translation'); + $this->batchSet = true; + + if (!$this->canDo->get('core.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + return false; + } + + if ($this->type == false) + { + $type = new JUcmType; + $this->type = $type->getTypeByAlias($this->typeAlias); + } + + $this->tagsObserver = $this->table->getObserverOfClass('JTableObserverTags'); + + if (!empty($commands['move_copy'])) + { + $cmd = ArrayHelper::getValue($commands, 'move_copy', 'c'); + + if ($cmd == 'c') + { + $result = $this->batchCopy($commands, $pks, $contexts); + + if (is_array($result)) + { + foreach ($result as $old => $new) + { + $contexts[$new] = $contexts[$old]; + } + $pks = array_values($result); + } + else + { + return false; + } + } + elseif ($cmd == 'm' && !$this->batchMove($commands, $pks, $contexts)) + { + return false; + } + + $done = true; + } + + if (!$done) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + + return false; + } + + // Clear the cache + $this->cleanCache(); + + return true; + } + + /** + * Batch copy items to a new category or current. + * + * @param integer $values The new values. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return mixed An array of new IDs on success, boolean false on failure. + * + * @since 12.2 + */ + protected function batchCopy($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('translation'); + } + + if (!$this->canDo->get('translation.create') && !$this->canDo->get('translation.batch')) + { + return false; + } + + // get list of unique fields + $uniqueFields = $this->getUniqueFields(); + // remove move_copy from array + unset($values['move_copy']); + + // make sure published is set + if (!isset($values['published'])) + { + $values['published'] = 0; + } + elseif (isset($values['published']) && !$this->canDo->get('translation.edit.state')) + { + $values['published'] = 0; + } + + $newIds = array(); + // Parent exists so let's proceed + while (!empty($pks)) + { + // Pop the first ID off the stack + $pk = array_shift($pks); + + $this->table->reset(); + + // only allow copy if user may edit this item. + if (!$this->user->authorise('translation.edit', $contexts[$pk])) + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // Only for strings + if (GetbibleHelper::checkString($this->table->translation) && !is_numeric($this->table->translation)) + { + $this->table->translation = $this->generateUnique('translation',$this->table->translation); + } + + // insert all set values + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + if (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + // update all unique fields + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $this->table->$uniqueField = $this->generateUnique($uniqueField,$this->table->$uniqueField); + } + } + + // Reset the ID because we are making a copy + $this->table->id = 0; + + // TODO: Deal with ordering? + // $this->table->ordering = 1; + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + + // Get the new item ID + $newId = $this->table->get('id'); + + // Add the new ID to the array + $newIds[$pk] = $newId; + } + + // Clean the cache + $this->cleanCache(); + + return $newIds; + } + + /** + * Batch move items to a new category + * + * @param integer $value The new category ID. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 12.2 + */ + protected function batchMove($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('translation'); + } + + if (!$this->canDo->get('translation.edit') && !$this->canDo->get('translation.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // make sure published only updates if user has the permission. + if (isset($values['published']) && !$this->canDo->get('translation.edit.state')) + { + unset($values['published']); + } + // remove move_copy from array + unset($values['move_copy']); + + // Parent exists so we proceed + foreach ($pks as $pk) + { + if (!$this->user->authorise('translation.edit', $contexts[$pk])) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // insert all set values. + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + // Do special action for access. + if ('access' === $key && strlen($value) > 0) + { + $this->table->$key = $value; + } + elseif (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + } + + // Clean the cache + $this->cleanCache(); + + return true; + } + + /** + * Method to save the form data. + * + * @param array $data The form data. + * + * @return boolean True on success. + * + * @since 1.6 + */ + public function save($data) + { + $input = JFactory::getApplication()->input; + $filter = JFilterInput::getInstance(); + + // set the metadata to the Item Data + if (isset($data['metadata']) && isset($data['metadata']['author'])) + { + $data['metadata']['author'] = $filter->clean($data['metadata']['author'], 'TRIM'); + + $metadata = new JRegistry; + $metadata->loadArray($data['metadata']); + $data['metadata'] = (string) $metadata; + } + + // Set the distribution_history items to data. + if (isset($data['distribution_history']) && is_array($data['distribution_history'])) + { + $distribution_history = new JRegistry; + $distribution_history->loadArray($data['distribution_history']); + $data['distribution_history'] = (string) $distribution_history; + } + // Also check permission since the value may be removed due to permissions + // Then we do not want to clear it out, but simple ignore the empty distribution_history + elseif (!isset($data['distribution_history']) + && JFactory::getUser()->authorise('translation.edit.distribution_history', 'com_getbible')) + { + // Set the empty distribution_history to data + $data['distribution_history'] = ''; + } + + // Set the Params Items to data + if (isset($data['params']) && is_array($data['params'])) + { + $params = new JRegistry; + $params->loadArray($data['params']); + $data['params'] = (string) $params; + } + + // Alter the unique field for save as copy + if ($input->get('task') === 'save2copy') + { + // Automatic handling of other unique fields + $uniqueFields = $this->getUniqueFields(); + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $data[$uniqueField] = $this->generateUnique($uniqueField,$data[$uniqueField]); + } + } + } + + if (parent::save($data)) + { + return true; + } + return false; + } + + /** + * Method to generate a unique value. + * + * @param string $field name. + * @param string $value data. + * + * @return string New value. + * + * @since 3.0 + */ + protected function generateUnique($field,$value) + { + + // set field value unique + $table = $this->getTable(); + + while ($table->load(array($field => $value))) + { + $value = StringHelper::increment($value); + } + + return $value; + } + + /** + * Method to change the title + * + * @param string $title The title. + * + * @return array Contains the modified title and alias. + * + */ + protected function _generateNewTitle($title) + { + + // Alter the title + $table = $this->getTable(); + + while ($table->load(array('title' => $title))) + { + $title = StringHelper::increment($title); + } + + return $title; + } +} diff --git a/admin/models/translations.php b/admin/models/translations.php new file mode 100644 index 0000000..7c66146 --- /dev/null +++ b/admin/models/translations.php @@ -0,0 +1,385 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\ListModel; +use Joomla\Utilities\ArrayHelper; + +/** + * Translations List Model + */ +class GetbibleModelTranslations extends ListModel +{ + public function __construct($config = array()) + { + if (empty($config['filter_fields'])) + { + $config['filter_fields'] = array( + 'a.id','id', + 'a.published','published', + 'a.access','access', + 'a.ordering','ordering', + 'a.created_by','created_by', + 'a.modified_by','modified_by', + 'a.direction','direction', + 'a.translation','translation', + 'a.abbreviation','abbreviation', + 'a.language','language' + ); + } + + parent::__construct($config); + } + + /** + * Method to auto-populate the model state. + * + * Note. Calling getState in this method will result in recursion. + * + * @param string $ordering An optional ordering field. + * @param string $direction An optional direction (asc|desc). + * + * @return void + * + */ + protected function populateState($ordering = null, $direction = null) + { + $app = JFactory::getApplication(); + + // Adjust the context to support modal layouts. + if ($layout = $app->input->get('layout')) + { + $this->context .= '.' . $layout; + } + + // Check if the form was submitted + $formSubmited = $app->input->post->get('form_submited'); + + $access = $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', 0, 'int'); + if ($formSubmited) + { + $access = $app->input->post->get('access'); + $this->setState('filter.access', $access); + } + + $published = $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', ''); + $this->setState('filter.published', $published); + + $created_by = $this->getUserStateFromRequest($this->context . '.filter.created_by', 'filter_created_by', ''); + $this->setState('filter.created_by', $created_by); + + $created = $this->getUserStateFromRequest($this->context . '.filter.created', 'filter_created'); + $this->setState('filter.created', $created); + + $sorting = $this->getUserStateFromRequest($this->context . '.filter.sorting', 'filter_sorting', 0, 'int'); + $this->setState('filter.sorting', $sorting); + + $search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search'); + $this->setState('filter.search', $search); + + $direction = $this->getUserStateFromRequest($this->context . '.filter.direction', 'filter_direction'); + if ($formSubmited) + { + $direction = $app->input->post->get('direction'); + $this->setState('filter.direction', $direction); + } + + $translation = $this->getUserStateFromRequest($this->context . '.filter.translation', 'filter_translation'); + if ($formSubmited) + { + $translation = $app->input->post->get('translation'); + $this->setState('filter.translation', $translation); + } + + $abbreviation = $this->getUserStateFromRequest($this->context . '.filter.abbreviation', 'filter_abbreviation'); + if ($formSubmited) + { + $abbreviation = $app->input->post->get('abbreviation'); + $this->setState('filter.abbreviation', $abbreviation); + } + + $language = $this->getUserStateFromRequest($this->context . '.filter.language', 'filter_language'); + if ($formSubmited) + { + $language = $app->input->post->get('language'); + $this->setState('filter.language', $language); + } + + // List state information. + parent::populateState($ordering, $direction); + } + + /** + * Method to get an array of data items. + * + * @return mixed An array of data items on success, false on failure. + */ + public function getItems() + { + // Check in items + $this->checkInNow(); + + // load parent items + $items = parent::getItems(); + + // Set values to display correctly. + if (GetbibleHelper::checkArray($items)) + { + // Get the user object if not set. + if (!isset($user) || !GetbibleHelper::checkObject($user)) + { + $user = JFactory::getUser(); + } + foreach ($items as $nr => &$item) + { + // Remove items the user can't access. + $access = ($user->authorise('translation.access', 'com_getbible.translation.' . (int) $item->id) && $user->authorise('translation.access', 'com_getbible')); + if (!$access) + { + unset($items[$nr]); + continue; + } + + } + } + + // set selection value to a translatable value + if (GetbibleHelper::checkArray($items)) + { + foreach ($items as $nr => &$item) + { + // convert direction + $item->direction = $this->selectionTranslation($item->direction, 'direction'); + } + } + + + // return items + return $items; + } + + /** + * Method to convert selection values to translatable string. + * + * @return translatable string + */ + public function selectionTranslation($value,$name) + { + // Array of direction language strings + if ($name === 'direction') + { + $directionArray = array( + 'LTR' => 'COM_GETBIBLE_TRANSLATION_SINISTRODEXTRAL_LTR', + 'RTL' => 'COM_GETBIBLE_TRANSLATION_DEXTROSINISTRAL_RTL' + ); + // Now check if value is found in this array + if (isset($directionArray[$value]) && GetbibleHelper::checkString($directionArray[$value])) + { + return $directionArray[$value]; + } + } + return $value; + } + + /** + * Method to build an SQL query to load the list data. + * + * @return string An SQL query + */ + protected function getListQuery() + { + // Get the user object. + $user = JFactory::getUser(); + // Create a new query object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + + // Select some fields + $query->select('a.*'); + + // From the getbible_item table + $query->from($db->quoteName('#__getbible_translation', 'a')); + + // Filter by published state + $published = $this->getState('filter.published'); + if (is_numeric($published)) + { + $query->where('a.published = ' . (int) $published); + } + elseif ($published === '') + { + $query->where('(a.published = 0 OR a.published = 1)'); + } + + // Join over the asset groups. + $query->select('ag.title AS access_level'); + $query->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access'); + // Filter by access level. + $_access = $this->getState('filter.access'); + if ($_access && is_numeric($_access)) + { + $query->where('a.access = ' . (int) $_access); + } + elseif (GetbibleHelper::checkArray($_access)) + { + // Secure the array for the query + $_access = ArrayHelper::toInteger($_access); + // Filter by the Access Array. + $query->where('a.access IN (' . implode(',', $_access) . ')'); + } + // Implement View Level Access + if (!$user->authorise('core.options', 'com_getbible')) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + // Filter by search. + $search = $this->getState('filter.search'); + if (!empty($search)) + { + if (stripos($search, 'id:') === 0) + { + $query->where('a.id = ' . (int) substr($search, 3)); + } + else + { + $search = $db->quote('%' . $db->escape($search) . '%'); + $query->where('(a.translation LIKE '.$search.' OR a.abbreviation LIKE '.$search.' OR a.language LIKE '.$search.' OR a.direction LIKE '.$search.' OR a.distribution_about LIKE '.$search.' OR a.distribution_license LIKE '.$search.' OR a.distribution_source LIKE '.$search.' OR a.distribution_sourcetype LIKE '.$search.' OR a.distribution_versification LIKE '.$search.' OR a.sha LIKE '.$search.' OR a.encoding LIKE '.$search.' OR a.distribution_lcsh LIKE '.$search.' OR a.distribution_version_date LIKE '.$search.' OR a.distribution_version LIKE '.$search.' OR a.lang LIKE '.$search.' OR a.distribution_abbreviation LIKE '.$search.')'); + } + } + + // Filter by Direction. + $_direction = $this->getState('filter.direction'); + if (is_numeric($_direction)) + { + if (is_float($_direction)) + { + $query->where('a.direction = ' . (float) $_direction); + } + else + { + $query->where('a.direction = ' . (int) $_direction); + } + } + elseif (GetbibleHelper::checkString($_direction)) + { + $query->where('a.direction = ' . $db->quote($db->escape($_direction))); + } + + // Add the list ordering clause. + $orderCol = $this->state->get('list.ordering', 'a.id'); + $orderDirn = $this->state->get('list.direction', 'desc'); + if ($orderCol != '') + { + $query->order($db->escape($orderCol . ' ' . $orderDirn)); + } + + return $query; + } + + /** + * Method to get a store id based on model configuration state. + * + * @return string A store id. + * + */ + protected function getStoreId($id = '') + { + // Compile the store id. + $id .= ':' . $this->getState('filter.id'); + $id .= ':' . $this->getState('filter.search'); + $id .= ':' . $this->getState('filter.published'); + // Check if the value is an array + $_access = $this->getState('filter.access'); + if (GetbibleHelper::checkArray($_access)) + { + $id .= ':' . implode(':', $_access); + } + // Check if this is only an number or string + elseif (is_numeric($_access) + || GetbibleHelper::checkString($_access)) + { + $id .= ':' . $_access; + } + $id .= ':' . $this->getState('filter.ordering'); + $id .= ':' . $this->getState('filter.created_by'); + $id .= ':' . $this->getState('filter.modified_by'); + $id .= ':' . $this->getState('filter.direction'); + $id .= ':' . $this->getState('filter.translation'); + $id .= ':' . $this->getState('filter.abbreviation'); + $id .= ':' . $this->getState('filter.language'); + + return parent::getStoreId($id); + } + + /** + * Build an SQL query to checkin all items left checked out longer then a set time. + * + * @return a bool + * + */ + protected function checkInNow() + { + // Get set check in time + $time = JComponentHelper::getParams('com_getbible')->get('check_in'); + + if ($time) + { + + // Get a db connection. + $db = JFactory::getDbo(); + // Reset query. + $query = $db->getQuery(true); + $query->select('*'); + $query->from($db->quoteName('#__getbible_translation')); + // Only select items that are checked out. + $query->where($db->quoteName('checked_out') . '!=0'); + $db->setQuery($query, 0, 1); + $db->execute(); + if ($db->getNumRows()) + { + // Get Yesterdays date. + $date = JFactory::getDate()->modify($time)->toSql(); + // Reset query. + $query = $db->getQuery(true); + + // Fields to update. + $fields = array( + $db->quoteName('checked_out_time') . '=\'0000-00-00 00:00:00\'', + $db->quoteName('checked_out') . '=0' + ); + + // Conditions for which records should be updated. + $conditions = array( + $db->quoteName('checked_out') . '!=0', + $db->quoteName('checked_out_time') . '<\''.$date.'\'' + ); + + // Check table. + $query->update($db->quoteName('#__getbible_translation'))->set($fields)->where($conditions); + + $db->setQuery($query); + + $db->execute(); + } + } + + return false; + } +} diff --git a/admin/models/verse.php b/admin/models/verse.php new file mode 100644 index 0000000..8e6759a --- /dev/null +++ b/admin/models/verse.php @@ -0,0 +1,989 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\AdminModel; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; + +/** + * Getbible Verse Admin Model + */ +class GetbibleModelVerse extends AdminModel +{ + /** + * The tab layout fields array. + * + * @var array + */ + protected $tabLayoutFields = array( + 'details' => array( + 'left' => array( + 'abbreviation' + ), + 'right' => array( + 'name' + ), + 'fullwidth' => array( + 'text' + ), + 'above' => array( + 'book_nr', + 'chapter', + 'verse' + ) + ) + ); + + /** + * @var string The prefix to use with controller messages. + * @since 1.6 + */ + protected $text_prefix = 'COM_GETBIBLE'; + + /** + * The type alias for this content type. + * + * @var string + * @since 3.2 + */ + public $typeAlias = 'com_getbible.verse'; + + /** + * Returns a Table object, always creating it + * + * @param type $type The table type to instantiate + * @param string $prefix A prefix for the table class name. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JTable A database object + * + * @since 1.6 + */ + public function getTable($type = 'verse', $prefix = 'GetbibleTable', $config = array()) + { + // add table path for when model gets used from other component + $this->addTablePath(JPATH_ADMINISTRATOR . '/components/com_getbible/tables'); + // get instance of the table + return JTable::getInstance($type, $prefix, $config); + }###ADMIN_CUSTOM_BUTTONS_METHOD### + + /** + * Method to get a single record. + * + * @param integer $pk The id of the primary key. + * + * @return mixed Object on success, false on failure. + * + * @since 1.6 + */ + public function getItem($pk = null) + { + if ($item = parent::getItem($pk)) + { + if (!empty($item->params) && !is_array($item->params)) + { + // Convert the params field to an array. + $registry = new Registry; + $registry->loadString($item->params); + $item->params = $registry->toArray(); + } + + if (!empty($item->metadata)) + { + // Convert the metadata field to an array. + $registry = new Registry; + $registry->loadString($item->metadata); + $item->metadata = $registry->toArray(); + } + } + + return $item; + } + + /** + * Method to get the record form. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * @param array $options Optional array of options for the form creation. + * + * @return mixed A JForm object on success, false on failure + * + * @since 1.6 + */ + public function getForm($data = array(), $loadData = true, $options = array('control' => 'jform')) + { + // set load data option + $options['load_data'] = $loadData; + // check if xpath was set in options + $xpath = false; + if (isset($options['xpath'])) + { + $xpath = $options['xpath']; + unset($options['xpath']); + } + // check if clear form was set in options + $clear = false; + if (isset($options['clear'])) + { + $clear = $options['clear']; + unset($options['clear']); + } + + // Get the form. + $form = $this->loadForm('com_getbible.verse', 'verse', $options, $clear, $xpath); + + if (empty($form)) + { + return false; + } + + $jinput = JFactory::getApplication()->input; + + // The front end calls this model and uses a_id to avoid id clashes so we need to check for that first. + if ($jinput->get('a_id')) + { + $id = $jinput->get('a_id', 0, 'INT'); + } + // The back end uses id so we use that the rest of the time and set it to 0 by default. + else + { + $id = $jinput->get('id', 0, 'INT'); + } + + $user = JFactory::getUser(); + + // Check for existing item. + // Modify the form based on Edit State access controls. + if ($id != 0 && (!$user->authorise('verse.edit.state', 'com_getbible.verse.' . (int) $id)) + || ($id == 0 && !$user->authorise('verse.edit.state', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('ordering', 'disabled', 'true'); + $form->setFieldAttribute('published', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('ordering', 'filter', 'unset'); + $form->setFieldAttribute('published', 'filter', 'unset'); + } + // If this is a new item insure the greated by is set. + if (0 == $id) + { + // Set the created_by to this user + $form->setValue('created_by', null, $user->id); + } + // Modify the form based on Edit Creaded By access controls. + if ($id != 0 && (!$user->authorise('verse.edit.created_by', 'com_getbible.verse.' . (int) $id)) + || ($id == 0 && !$user->authorise('verse.edit.created_by', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created_by', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('created_by', 'readonly', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created_by', 'filter', 'unset'); + } + // Modify the form based on Edit Creaded Date access controls. + if ($id != 0 && (!$user->authorise('verse.edit.created', 'com_getbible.verse.' . (int) $id)) + || ($id == 0 && !$user->authorise('verse.edit.created', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('created', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created', 'filter', 'unset'); + } + // Modify the form based on Edit Book Nr access controls. + if ($id != 0 && (!$user->authorise('verse.edit.book_nr', 'com_getbible.verse.' . (int) $id)) + || ($id == 0 && !$user->authorise('verse.edit.book_nr', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('book_nr', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('book_nr', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('book_nr')) + { + // Disable fields while saving. + $form->setFieldAttribute('book_nr', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('book_nr', 'required', 'false'); + } + } + // Modify the form based on Edit Chapter access controls. + if ($id != 0 && (!$user->authorise('verse.edit.chapter', 'com_getbible.verse.' . (int) $id)) + || ($id == 0 && !$user->authorise('verse.edit.chapter', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('chapter', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('chapter', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('chapter')) + { + // Disable fields while saving. + $form->setFieldAttribute('chapter', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('chapter', 'required', 'false'); + } + } + // Modify the form based on Edit Verse access controls. + if ($id != 0 && (!$user->authorise('verse.edit.verse', 'com_getbible.verse.' . (int) $id)) + || ($id == 0 && !$user->authorise('verse.edit.verse', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('verse', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('verse', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('verse')) + { + // Disable fields while saving. + $form->setFieldAttribute('verse', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('verse', 'required', 'false'); + } + } + // Modify the form based on Edit Abbreviation access controls. + if ($id != 0 && (!$user->authorise('verse.edit.abbreviation', 'com_getbible.verse.' . (int) $id)) + || ($id == 0 && !$user->authorise('verse.edit.abbreviation', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('abbreviation', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('abbreviation', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('abbreviation')) + { + // Disable fields while saving. + $form->setFieldAttribute('abbreviation', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('abbreviation', 'required', 'false'); + } + } + // Modify the form based on Edit Text access controls. + if ($id != 0 && (!$user->authorise('verse.edit.text', 'com_getbible.verse.' . (int) $id)) + || ($id == 0 && !$user->authorise('verse.edit.text', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('text', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('text', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('text')) + { + // Disable fields while saving. + $form->setFieldAttribute('text', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('text', 'required', 'false'); + } + } + // Modify the form based on Edit Name access controls. + if ($id != 0 && (!$user->authorise('verse.edit.name', 'com_getbible.verse.' . (int) $id)) + || ($id == 0 && !$user->authorise('verse.edit.name', 'com_getbible'))) + { + // Disable fields for display. + $form->setFieldAttribute('name', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('name', 'readonly', 'true'); + // If there is no value continue. + if (!$form->getValue('name')) + { + // Disable fields while saving. + $form->setFieldAttribute('name', 'filter', 'unset'); + // Disable fields while saving. + $form->setFieldAttribute('name', 'required', 'false'); + } + } + // Only load these values if no id is found + if (0 == $id) + { + // Set redirected view name + $redirectedView = $jinput->get('ref', null, 'STRING'); + // Set field name (or fall back to view name) + $redirectedField = $jinput->get('field', $redirectedView, 'STRING'); + // Set redirected view id + $redirectedId = $jinput->get('refid', 0, 'INT'); + // Set field id (or fall back to redirected view id) + $redirectedValue = $jinput->get('field_id', $redirectedId, 'INT'); + if (0 != $redirectedValue && $redirectedField) + { + // Now set the local-redirected field default value + $form->setValue($redirectedField, null, $redirectedValue); + } + } + return $form; + } + + /** + * Method to get the script that have to be included on the form + * + * @return string script files + */ + public function getScript() + { + return 'media/com_getbible/js/verse.js'; + } + + /** + * Method to test whether a record can be deleted. + * + * @param object $record A record object. + * + * @return boolean True if allowed to delete the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canDelete($record) + { + if (!empty($record->id)) + { + if ($record->published != -2) + { + return; + } + + $user = JFactory::getUser(); + // The record has been set. Check the record permissions. + return $user->authorise('verse.delete', 'com_getbible.verse.' . (int) $record->id); + } + return false; + } + + /** + * Method to test whether a record can have its state edited. + * + * @param object $record A record object. + * + * @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canEditState($record) + { + $user = JFactory::getUser(); + $recordId = (!empty($record->id)) ? $record->id : 0; + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('verse.edit.state', 'com_getbible.verse.' . (int) $recordId); + if (!$permission && !is_null($permission)) + { + return false; + } + } + // In the absense of better information, revert to the component permissions. + return $user->authorise('verse.edit.state', 'com_getbible'); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * @since 2.5 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // Check specific edit permission then general edit permission. + $user = JFactory::getUser(); + + return $user->authorise('verse.edit', 'com_getbible.verse.'. ((int) isset($data[$key]) ? $data[$key] : 0)) or $user->authorise('verse.edit', 'com_getbible'); + } + + /** + * Prepare and sanitise the table data prior to saving. + * + * @param JTable $table A JTable object. + * + * @return void + * + * @since 1.6 + */ + protected function prepareTable($table) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if (isset($table->name)) + { + $table->name = htmlspecialchars_decode($table->name, ENT_QUOTES); + } + + if (isset($table->alias) && empty($table->alias)) + { + $table->generateAlias(); + } + + if (empty($table->id)) + { + $table->created = $date->toSql(); + // set the user + if ($table->created_by == 0 || empty($table->created_by)) + { + $table->created_by = $user->id; + } + // Set ordering to the last item if not set + if (empty($table->ordering)) + { + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select('MAX(ordering)') + ->from($db->quoteName('#__getbible_verse')); + $db->setQuery($query); + $max = $db->loadResult(); + + $table->ordering = $max + 1; + } + } + else + { + $table->modified = $date->toSql(); + $table->modified_by = $user->id; + } + + if (!empty($table->id)) + { + // Increment the items version number. + $table->version++; + } + } + + /** + * Method to get the data that should be injected in the form. + * + * @return mixed The data for the form. + * + * @since 1.6 + */ + protected function loadFormData() + { + // Check the session for previously entered form data. + $data = JFactory::getApplication()->getUserState('com_getbible.edit.verse.data', array()); + + if (empty($data)) + { + $data = $this->getItem(); + // run the perprocess of the data + $this->preprocessData('com_getbible.verse', $data); + } + + return $data; + } + + /** + * Method to get the unique fields of this table. + * + * @return mixed An array of field names, boolean false if none is set. + * + * @since 3.0 + */ + protected function getUniqueFields() + { + return false; + } + + /** + * Method to delete one or more records. + * + * @param array &$pks An array of record primary keys. + * + * @return boolean True if successful, false if an error occurs. + * + * @since 12.2 + */ + public function delete(&$pks) + { + if (!parent::delete($pks)) + { + return false; + } + + return true; + } + + /** + * Method to change the published state of one or more records. + * + * @param array &$pks A list of the primary keys to change. + * @param integer $value The value of the published state. + * + * @return boolean True on success. + * + * @since 12.2 + */ + public function publish(&$pks, $value = 1) + { + if (!parent::publish($pks, $value)) + { + return false; + } + + return true; + } + + /** + * Method to perform batch operations on an item or a set of items. + * + * @param array $commands An array of commands to perform. + * @param array $pks An array of item ids. + * @param array $contexts An array of item contexts. + * + * @return boolean Returns true on success, false on failure. + * + * @since 12.2 + */ + public function batch($commands, $pks, $contexts) + { + // Sanitize ids. + $pks = array_unique($pks); + ArrayHelper::toInteger($pks); + + // Remove any values of zero. + if (array_search(0, $pks, true)) + { + unset($pks[array_search(0, $pks, true)]); + } + + if (empty($pks)) + { + $this->setError(JText::_('JGLOBAL_NO_ITEM_SELECTED')); + return false; + } + + $done = false; + + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->contentType = new JUcmType; + $this->type = $this->contentType->getTypeByTable($this->tableClassName); + $this->canDo = GetbibleHelper::getActions('verse'); + $this->batchSet = true; + + if (!$this->canDo->get('core.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + return false; + } + + if ($this->type == false) + { + $type = new JUcmType; + $this->type = $type->getTypeByAlias($this->typeAlias); + } + + $this->tagsObserver = $this->table->getObserverOfClass('JTableObserverTags'); + + if (!empty($commands['move_copy'])) + { + $cmd = ArrayHelper::getValue($commands, 'move_copy', 'c'); + + if ($cmd == 'c') + { + $result = $this->batchCopy($commands, $pks, $contexts); + + if (is_array($result)) + { + foreach ($result as $old => $new) + { + $contexts[$new] = $contexts[$old]; + } + $pks = array_values($result); + } + else + { + return false; + } + } + elseif ($cmd == 'm' && !$this->batchMove($commands, $pks, $contexts)) + { + return false; + } + + $done = true; + } + + if (!$done) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + + return false; + } + + // Clear the cache + $this->cleanCache(); + + return true; + } + + /** + * Batch copy items to a new category or current. + * + * @param integer $values The new values. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return mixed An array of new IDs on success, boolean false on failure. + * + * @since 12.2 + */ + protected function batchCopy($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('verse'); + } + + if (!$this->canDo->get('verse.create') && !$this->canDo->get('verse.batch')) + { + return false; + } + + // get list of unique fields + $uniqueFields = $this->getUniqueFields(); + // remove move_copy from array + unset($values['move_copy']); + + // make sure published is set + if (!isset($values['published'])) + { + $values['published'] = 0; + } + elseif (isset($values['published']) && !$this->canDo->get('verse.edit.state')) + { + $values['published'] = 0; + } + + $newIds = array(); + // Parent exists so let's proceed + while (!empty($pks)) + { + // Pop the first ID off the stack + $pk = array_shift($pks); + + $this->table->reset(); + + // only allow copy if user may edit this item. + if (!$this->user->authorise('verse.edit', $contexts[$pk])) + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // Only for strings + if (GetbibleHelper::checkString($this->table->book_nr) && !is_numeric($this->table->book_nr)) + { + $this->table->book_nr = $this->generateUnique('book_nr',$this->table->book_nr); + } + + // insert all set values + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + if (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + // update all unique fields + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $this->table->$uniqueField = $this->generateUnique($uniqueField,$this->table->$uniqueField); + } + } + + // Reset the ID because we are making a copy + $this->table->id = 0; + + // TODO: Deal with ordering? + // $this->table->ordering = 1; + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + + // Get the new item ID + $newId = $this->table->get('id'); + + // Add the new ID to the array + $newIds[$pk] = $newId; + } + + // Clean the cache + $this->cleanCache(); + + return $newIds; + } + + /** + * Batch move items to a new category + * + * @param integer $value The new category ID. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 12.2 + */ + protected function batchMove($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = GetbibleHelper::getActions('verse'); + } + + if (!$this->canDo->get('verse.edit') && !$this->canDo->get('verse.batch')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // make sure published only updates if user has the permission. + if (isset($values['published']) && !$this->canDo->get('verse.edit.state')) + { + unset($values['published']); + } + // remove move_copy from array + unset($values['move_copy']); + + // Parent exists so we proceed + foreach ($pks as $pk) + { + if (!$this->user->authorise('verse.edit', $contexts[$pk])) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // insert all set values. + if (GetbibleHelper::checkArray($values)) + { + foreach ($values as $key => $value) + { + // Do special action for access. + if ('access' === $key && strlen($value) > 0) + { + $this->table->$key = $value; + } + elseif (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + } + + // Clean the cache + $this->cleanCache(); + + return true; + } + + /** + * Method to save the form data. + * + * @param array $data The form data. + * + * @return boolean True on success. + * + * @since 1.6 + */ + public function save($data) + { + $input = JFactory::getApplication()->input; + $filter = JFilterInput::getInstance(); + + // set the metadata to the Item Data + if (isset($data['metadata']) && isset($data['metadata']['author'])) + { + $data['metadata']['author'] = $filter->clean($data['metadata']['author'], 'TRIM'); + + $metadata = new JRegistry; + $metadata->loadArray($data['metadata']); + $data['metadata'] = (string) $metadata; + } + + // Set the Params Items to data + if (isset($data['params']) && is_array($data['params'])) + { + $params = new JRegistry; + $params->loadArray($data['params']); + $data['params'] = (string) $params; + } + + // Alter the unique field for save as copy + if ($input->get('task') === 'save2copy') + { + // Automatic handling of other unique fields + $uniqueFields = $this->getUniqueFields(); + if (GetbibleHelper::checkArray($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $data[$uniqueField] = $this->generateUnique($uniqueField,$data[$uniqueField]); + } + } + } + + if (parent::save($data)) + { + return true; + } + return false; + } + + /** + * Method to generate a unique value. + * + * @param string $field name. + * @param string $value data. + * + * @return string New value. + * + * @since 3.0 + */ + protected function generateUnique($field,$value) + { + + // set field value unique + $table = $this->getTable(); + + while ($table->load(array($field => $value))) + { + $value = StringHelper::increment($value); + } + + return $value; + } + + /** + * Method to change the title + * + * @param string $title The title. + * + * @return array Contains the modified title and alias. + * + */ + protected function _generateNewTitle($title) + { + + // Alter the title + $table = $this->getTable(); + + while ($table->load(array('title' => $title))) + { + $title = StringHelper::increment($title); + } + + return $title; + } +} diff --git a/admin/models/verses.php b/admin/models/verses.php new file mode 100644 index 0000000..6572849 --- /dev/null +++ b/admin/models/verses.php @@ -0,0 +1,406 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\ListModel; +use Joomla\Utilities\ArrayHelper; + +/** + * Verses List Model + */ +class GetbibleModelVerses extends ListModel +{ + public function __construct($config = array()) + { + if (empty($config['filter_fields'])) + { + $config['filter_fields'] = array( + 'a.id','id', + 'a.published','published', + 'a.access','access', + 'a.ordering','ordering', + 'a.created_by','created_by', + 'a.modified_by','modified_by', + 'a.book_nr','book_nr', + 'a.chapter','chapter', + 'a.verse','verse', + 'g.translation','abbreviation' + ); + } + + parent::__construct($config); + } + + /** + * Method to auto-populate the model state. + * + * Note. Calling getState in this method will result in recursion. + * + * @param string $ordering An optional ordering field. + * @param string $direction An optional direction (asc|desc). + * + * @return void + * + */ + protected function populateState($ordering = null, $direction = null) + { + $app = JFactory::getApplication(); + + // Adjust the context to support modal layouts. + if ($layout = $app->input->get('layout')) + { + $this->context .= '.' . $layout; + } + + // Check if the form was submitted + $formSubmited = $app->input->post->get('form_submited'); + + $access = $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', 0, 'int'); + if ($formSubmited) + { + $access = $app->input->post->get('access'); + $this->setState('filter.access', $access); + } + + $published = $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', ''); + $this->setState('filter.published', $published); + + $created_by = $this->getUserStateFromRequest($this->context . '.filter.created_by', 'filter_created_by', ''); + $this->setState('filter.created_by', $created_by); + + $created = $this->getUserStateFromRequest($this->context . '.filter.created', 'filter_created'); + $this->setState('filter.created', $created); + + $sorting = $this->getUserStateFromRequest($this->context . '.filter.sorting', 'filter_sorting', 0, 'int'); + $this->setState('filter.sorting', $sorting); + + $search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search'); + $this->setState('filter.search', $search); + + $book_nr = $this->getUserStateFromRequest($this->context . '.filter.book_nr', 'filter_book_nr'); + if ($formSubmited) + { + $book_nr = $app->input->post->get('book_nr'); + $this->setState('filter.book_nr', $book_nr); + } + + $chapter = $this->getUserStateFromRequest($this->context . '.filter.chapter', 'filter_chapter'); + if ($formSubmited) + { + $chapter = $app->input->post->get('chapter'); + $this->setState('filter.chapter', $chapter); + } + + $verse = $this->getUserStateFromRequest($this->context . '.filter.verse', 'filter_verse'); + if ($formSubmited) + { + $verse = $app->input->post->get('verse'); + $this->setState('filter.verse', $verse); + } + + $abbreviation = $this->getUserStateFromRequest($this->context . '.filter.abbreviation', 'filter_abbreviation'); + if ($formSubmited) + { + $abbreviation = $app->input->post->get('abbreviation'); + $this->setState('filter.abbreviation', $abbreviation); + } + + // List state information. + parent::populateState($ordering, $direction); + } + + /** + * Method to get an array of data items. + * + * @return mixed An array of data items on success, false on failure. + */ + public function getItems() + { + // Check in items + $this->checkInNow(); + + // load parent items + $items = parent::getItems(); + + // Set values to display correctly. + if (GetbibleHelper::checkArray($items)) + { + // Get the user object if not set. + if (!isset($user) || !GetbibleHelper::checkObject($user)) + { + $user = JFactory::getUser(); + } + foreach ($items as $nr => &$item) + { + // Remove items the user can't access. + $access = ($user->authorise('verse.access', 'com_getbible.verse.' . (int) $item->id) && $user->authorise('verse.access', 'com_getbible')); + if (!$access) + { + unset($items[$nr]); + continue; + } + + } + } + + // return items + return $items; + } + + /** + * Method to build an SQL query to load the list data. + * + * @return string An SQL query + */ + protected function getListQuery() + { + // Get the user object. + $user = JFactory::getUser(); + // Create a new query object. + $db = JFactory::getDBO(); + $query = $db->getQuery(true); + + // Select some fields + $query->select('a.*'); + + // From the getbible_item table + $query->from($db->quoteName('#__getbible_verse', 'a')); + + // From the getbible_translation table. + $query->select($db->quoteName(['g.translation','g.id'],['abbreviation_translation','abbreviation_id'])); + $query->join('LEFT', $db->quoteName('#__getbible_translation', 'g') . ' ON (' . $db->quoteName('a.abbreviation') . ' = ' . $db->quoteName('g.abbreviation') . ')'); + + // Filter by published state + $published = $this->getState('filter.published'); + if (is_numeric($published)) + { + $query->where('a.published = ' . (int) $published); + } + elseif ($published === '') + { + $query->where('(a.published = 0 OR a.published = 1)'); + } + + // Join over the asset groups. + $query->select('ag.title AS access_level'); + $query->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access'); + // Filter by access level. + $_access = $this->getState('filter.access'); + if ($_access && is_numeric($_access)) + { + $query->where('a.access = ' . (int) $_access); + } + elseif (GetbibleHelper::checkArray($_access)) + { + // Secure the array for the query + $_access = ArrayHelper::toInteger($_access); + // Filter by the Access Array. + $query->where('a.access IN (' . implode(',', $_access) . ')'); + } + // Implement View Level Access + if (!$user->authorise('core.options', 'com_getbible')) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + // Filter by search. + $search = $this->getState('filter.search'); + if (!empty($search)) + { + if (stripos($search, 'id:') === 0) + { + $query->where('a.id = ' . (int) substr($search, 3)); + } + else + { + $search = $db->quote('%' . $db->escape($search) . '%'); + $query->where('(a.book_nr LIKE '.$search.' OR a.chapter LIKE '.$search.' OR a.verse LIKE '.$search.' OR a.abbreviation LIKE '.$search.' OR g.translation LIKE '.$search.' OR a.name LIKE '.$search.')'); + } + } + + // Filter by Book_nr. + $_book_nr = $this->getState('filter.book_nr'); + if (is_numeric($_book_nr)) + { + if (is_float($_book_nr)) + { + $query->where('a.book_nr = ' . (float) $_book_nr); + } + else + { + $query->where('a.book_nr = ' . (int) $_book_nr); + } + } + elseif (GetbibleHelper::checkString($_book_nr)) + { + $query->where('a.book_nr = ' . $db->quote($db->escape($_book_nr))); + } + // Filter by Chapter. + $_chapter = $this->getState('filter.chapter'); + if (is_numeric($_chapter)) + { + if (is_float($_chapter)) + { + $query->where('a.chapter = ' . (float) $_chapter); + } + else + { + $query->where('a.chapter = ' . (int) $_chapter); + } + } + elseif (GetbibleHelper::checkString($_chapter)) + { + $query->where('a.chapter = ' . $db->quote($db->escape($_chapter))); + } + // Filter by Verse. + $_verse = $this->getState('filter.verse'); + if (is_numeric($_verse)) + { + if (is_float($_verse)) + { + $query->where('a.verse = ' . (float) $_verse); + } + else + { + $query->where('a.verse = ' . (int) $_verse); + } + } + elseif (GetbibleHelper::checkString($_verse)) + { + $query->where('a.verse = ' . $db->quote($db->escape($_verse))); + } + // Filter by Abbreviation. + $_abbreviation = $this->getState('filter.abbreviation'); + if (is_numeric($_abbreviation)) + { + if (is_float($_abbreviation)) + { + $query->where('a.abbreviation = ' . (float) $_abbreviation); + } + else + { + $query->where('a.abbreviation = ' . (int) $_abbreviation); + } + } + elseif (GetbibleHelper::checkString($_abbreviation)) + { + $query->where('a.abbreviation = ' . $db->quote($db->escape($_abbreviation))); + } + + // Add the list ordering clause. + $orderCol = $this->state->get('list.ordering', 'a.id'); + $orderDirn = $this->state->get('list.direction', 'desc'); + if ($orderCol != '') + { + $query->order($db->escape($orderCol . ' ' . $orderDirn)); + } + + return $query; + } + + /** + * Method to get a store id based on model configuration state. + * + * @return string A store id. + * + */ + protected function getStoreId($id = '') + { + // Compile the store id. + $id .= ':' . $this->getState('filter.id'); + $id .= ':' . $this->getState('filter.search'); + $id .= ':' . $this->getState('filter.published'); + // Check if the value is an array + $_access = $this->getState('filter.access'); + if (GetbibleHelper::checkArray($_access)) + { + $id .= ':' . implode(':', $_access); + } + // Check if this is only an number or string + elseif (is_numeric($_access) + || GetbibleHelper::checkString($_access)) + { + $id .= ':' . $_access; + } + $id .= ':' . $this->getState('filter.ordering'); + $id .= ':' . $this->getState('filter.created_by'); + $id .= ':' . $this->getState('filter.modified_by'); + $id .= ':' . $this->getState('filter.book_nr'); + $id .= ':' . $this->getState('filter.chapter'); + $id .= ':' . $this->getState('filter.verse'); + $id .= ':' . $this->getState('filter.abbreviation'); + + return parent::getStoreId($id); + } + + /** + * Build an SQL query to checkin all items left checked out longer then a set time. + * + * @return a bool + * + */ + protected function checkInNow() + { + // Get set check in time + $time = JComponentHelper::getParams('com_getbible')->get('check_in'); + + if ($time) + { + + // Get a db connection. + $db = JFactory::getDbo(); + // Reset query. + $query = $db->getQuery(true); + $query->select('*'); + $query->from($db->quoteName('#__getbible_verse')); + // Only select items that are checked out. + $query->where($db->quoteName('checked_out') . '!=0'); + $db->setQuery($query, 0, 1); + $db->execute(); + if ($db->getNumRows()) + { + // Get Yesterdays date. + $date = JFactory::getDate()->modify($time)->toSql(); + // Reset query. + $query = $db->getQuery(true); + + // Fields to update. + $fields = array( + $db->quoteName('checked_out_time') . '=\'0000-00-00 00:00:00\'', + $db->quoteName('checked_out') . '=0' + ); + + // Conditions for which records should be updated. + $conditions = array( + $db->quoteName('checked_out') . '!=0', + $db->quoteName('checked_out_time') . '<\''.$date.'\'' + ); + + // Check table. + $query->update($db->quoteName('#__getbible_verse'))->set($fields)->where($conditions); + + $db->setQuery($query); + + $db->execute(); + } + } + + return false; + } +} diff --git a/admin/sql/index.html b/admin/sql/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/sql/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/sql/install.mysql.utf8.sql b/admin/sql/install.mysql.utf8.sql new file mode 100644 index 0000000..95b0986 --- /dev/null +++ b/admin/sql/install.mysql.utf8.sql @@ -0,0 +1,446 @@ +CREATE TABLE IF NOT EXISTS `#__getbible_linker` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `asset_id` INT(10) unsigned NOT NULL DEFAULT 0 COMMENT 'FK to the #__assets table.', + `guid` VARCHAR(36) NOT NULL DEFAULT '', + `name` VARCHAR(255) NOT NULL DEFAULT '', + `params` text NULL, + `published` TINYINT(3) NOT NULL DEFAULT 1, + `created_by` INT(10) unsigned NOT NULL DEFAULT 0, + `modified_by` INT(10) unsigned NOT NULL DEFAULT 0, + `created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `modified` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `checked_out` int(11) unsigned NOT NULL DEFAULT 0, + `checked_out_time` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `version` INT(10) unsigned NOT NULL DEFAULT 1, + `hits` INT(10) unsigned NOT NULL DEFAULT 0, + `access` INT(10) unsigned NOT NULL DEFAULT 0, + `ordering` INT(11) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_name` (`name`), + KEY `idx_guid` (`guid`), + KEY `idx_access` (`access`), + KEY `idx_checkout` (`checked_out`), + KEY `idx_createdby` (`created_by`), + KEY `idx_modifiedby` (`modified_by`), + KEY `idx_state` (`published`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `#__getbible_note` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `asset_id` INT(10) unsigned NOT NULL DEFAULT 0 COMMENT 'FK to the #__assets table.', + `access` TINYINT(1) NOT NULL DEFAULT 0, + `book_nr` INT(7) NOT NULL DEFAULT 0, + `chapter` INT(7) NOT NULL DEFAULT 0, + `guid` VARCHAR(36) NOT NULL DEFAULT '', + `linker` VARCHAR(36) NOT NULL DEFAULT '', + `note` TEXT NOT NULL, + `verse` INT(7) NOT NULL DEFAULT 0, + `params` text NULL, + `published` TINYINT(3) NOT NULL DEFAULT 1, + `created_by` INT(10) unsigned NOT NULL DEFAULT 0, + `modified_by` INT(10) unsigned NOT NULL DEFAULT 0, + `created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `modified` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `checked_out` int(11) unsigned NOT NULL DEFAULT 0, + `checked_out_time` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `version` INT(10) unsigned NOT NULL DEFAULT 1, + `hits` INT(10) unsigned NOT NULL DEFAULT 0, + `ordering` INT(11) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_book_nr` (`book_nr`), + KEY `idx_linker` (`linker`), + KEY `idx_guid` (`guid`), + KEY `idx_verse` (`verse`), + KEY `idx_chapter` (`chapter`), + KEY `idx_access` (`access`), + KEY `idx_checkout` (`checked_out`), + KEY `idx_createdby` (`created_by`), + KEY `idx_modifiedby` (`modified_by`), + KEY `idx_state` (`published`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `#__getbible_tagged_verse` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `asset_id` INT(10) unsigned NOT NULL DEFAULT 0 COMMENT 'FK to the #__assets table.', + `abbreviation` VARCHAR(100) NOT NULL DEFAULT '', + `access` TINYINT(1) NOT NULL DEFAULT 0, + `book_nr` INT(7) NOT NULL DEFAULT 0, + `chapter` INT(7) NOT NULL DEFAULT 0, + `guid` VARCHAR(36) NOT NULL DEFAULT '', + `linker` VARCHAR(36) NOT NULL DEFAULT '', + `tag` VARCHAR(36) NOT NULL DEFAULT '', + `verse` INT(7) NOT NULL DEFAULT 0, + `params` text NULL, + `published` TINYINT(3) NOT NULL DEFAULT 1, + `created_by` INT(10) unsigned NOT NULL DEFAULT 0, + `modified_by` INT(10) unsigned NOT NULL DEFAULT 0, + `created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `modified` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `checked_out` int(11) unsigned NOT NULL DEFAULT 0, + `checked_out_time` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `version` INT(10) unsigned NOT NULL DEFAULT 1, + `hits` INT(10) unsigned NOT NULL DEFAULT 0, + `ordering` INT(11) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_book_nr` (`book_nr`), + KEY `idx_abbreviation` (`abbreviation`), + KEY `idx_linker` (`linker`), + KEY `idx_tag` (`tag`), + KEY `idx_guid` (`guid`), + KEY `idx_verse` (`verse`), + KEY `idx_chapter` (`chapter`), + KEY `idx_access` (`access`), + KEY `idx_checkout` (`checked_out`), + KEY `idx_createdby` (`created_by`), + KEY `idx_modifiedby` (`modified_by`), + KEY `idx_state` (`published`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `#__getbible_prompt` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `asset_id` INT(10) unsigned NOT NULL DEFAULT 0 COMMENT 'FK to the #__assets table.', + `abbreviation` VARCHAR(100) NOT NULL DEFAULT '', + `ai_org_token_override` TINYINT(1) NOT NULL DEFAULT 0, + `cache_behaviour` TINYINT(1) NOT NULL DEFAULT 0, + `cache_capacity` INT(11) NOT NULL DEFAULT 0, + `frequency_penalty` FLOAT(11) NOT NULL DEFAULT 0, + `frequency_penalty_override` TINYINT(1) NOT NULL DEFAULT 0, + `guid` VARCHAR(36) NOT NULL DEFAULT '', + `integration` TINYINT(1) NOT NULL DEFAULT 1, + `max_tokens` INT(11) NOT NULL DEFAULT 0, + `max_tokens_override` TINYINT(1) NOT NULL DEFAULT 0, + `messages` TEXT NOT NULL, + `model` VARCHAR(50) NOT NULL DEFAULT '', + `n` INT(7) NOT NULL DEFAULT 0, + `n_override` TINYINT(1) NOT NULL DEFAULT 0, + `name` VARCHAR(255) NOT NULL DEFAULT '', + `org_token` VARCHAR(100) NOT NULL DEFAULT '', + `presence_penalty` FLOAT(11) NOT NULL DEFAULT 0, + `presence_penalty_override` TINYINT(1) NOT NULL DEFAULT 0, + `response_retrieval` TINYINT(1) NOT NULL DEFAULT 0, + `temperature` FLOAT(11) NOT NULL DEFAULT 0, + `temperature_override` TINYINT(1) NOT NULL DEFAULT 0, + `token` VARCHAR(100) NOT NULL DEFAULT '', + `token_override` TINYINT(1) NOT NULL DEFAULT 0, + `top_p` FLOAT(11) NOT NULL DEFAULT 0, + `top_p_override` TINYINT(1) NOT NULL DEFAULT 0, + `params` text NULL, + `published` TINYINT(3) NOT NULL DEFAULT 1, + `created_by` INT(10) unsigned NOT NULL DEFAULT 0, + `modified_by` INT(10) unsigned NOT NULL DEFAULT 0, + `created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `modified` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `checked_out` int(11) unsigned NOT NULL DEFAULT 0, + `checked_out_time` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `version` INT(10) unsigned NOT NULL DEFAULT 1, + `hits` INT(10) unsigned NOT NULL DEFAULT 0, + `access` INT(10) unsigned NOT NULL DEFAULT 0, + `ordering` INT(11) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_name` (`name`), + KEY `idx_integration` (`integration`), + KEY `idx_cache_behaviour` (`cache_behaviour`), + KEY `idx_abbreviation` (`abbreviation`), + KEY `idx_guid` (`guid`), + KEY `idx_model` (`model`), + KEY `idx_access` (`access`), + KEY `idx_checkout` (`checked_out`), + KEY `idx_createdby` (`created_by`), + KEY `idx_modifiedby` (`modified_by`), + KEY `idx_state` (`published`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `#__getbible_open_ai_response` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `asset_id` INT(10) unsigned NOT NULL DEFAULT 0 COMMENT 'FK to the #__assets table.', + `abbreviation` VARCHAR(100) NOT NULL DEFAULT '', + `book` INT(11) NOT NULL DEFAULT 0, + `chapter` INT(11) NOT NULL DEFAULT 0, + `completion_tokens` INT(11) NOT NULL DEFAULT 0, + `frequency_penalty` FLOAT(11) NOT NULL DEFAULT 0, + `language` VARCHAR(255) NOT NULL DEFAULT '', + `lcsh` VARCHAR(255) NOT NULL DEFAULT '', + `max_tokens` INT(11) NOT NULL DEFAULT 0, + `model` VARCHAR(50) NOT NULL DEFAULT '', + `n` INT(7) NOT NULL DEFAULT 0, + `presence_penalty` FLOAT(11) NOT NULL DEFAULT 0, + `prompt` VARCHAR(36) NOT NULL DEFAULT '', + `prompt_tokens` INT(11) NOT NULL DEFAULT 0, + `response_created` VARCHAR(255) NOT NULL DEFAULT '', + `response_id` VARCHAR(255) NOT NULL DEFAULT '', + `response_model` VARCHAR(255) NOT NULL DEFAULT '', + `response_object` VARCHAR(255) NOT NULL DEFAULT '', + `selected_word` TEXT NOT NULL, + `temperature` FLOAT(11) NOT NULL DEFAULT 0, + `top_p` FLOAT(11) NOT NULL DEFAULT 0, + `total_tokens` INT(11) NOT NULL DEFAULT 0, + `verse` VARCHAR(255) NOT NULL DEFAULT '', + `word` VARCHAR(255) NOT NULL DEFAULT '', + `params` text NULL, + `published` TINYINT(3) NOT NULL DEFAULT 1, + `created_by` INT(10) unsigned NOT NULL DEFAULT 0, + `modified_by` INT(10) unsigned NOT NULL DEFAULT 0, + `created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `modified` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `checked_out` int(11) unsigned NOT NULL DEFAULT 0, + `checked_out_time` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `version` INT(10) unsigned NOT NULL DEFAULT 1, + `hits` INT(10) unsigned NOT NULL DEFAULT 0, + `access` INT(10) unsigned NOT NULL DEFAULT 0, + `ordering` INT(11) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_response_id` (`response_id`), + KEY `idx_prompt` (`prompt`), + KEY `idx_response_object` (`response_object`), + KEY `idx_response_model` (`response_model`), + KEY `idx_total_tokens` (`total_tokens`), + KEY `idx_word` (`word`), + KEY `idx_chapter` (`chapter`), + KEY `idx_lcsh` (`lcsh`), + KEY `idx_completion_tokens` (`completion_tokens`), + KEY `idx_prompt_tokens` (`prompt_tokens`), + KEY `idx_response_created` (`response_created`), + KEY `idx_abbreviation` (`abbreviation`), + KEY `idx_language` (`language`), + KEY `idx_book` (`book`), + KEY `idx_verse` (`verse`), + KEY `idx_model` (`model`), + KEY `idx_access` (`access`), + KEY `idx_checkout` (`checked_out`), + KEY `idx_createdby` (`created_by`), + KEY `idx_modifiedby` (`modified_by`), + KEY `idx_state` (`published`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `#__getbible_open_ai_message` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `asset_id` INT(10) unsigned NOT NULL DEFAULT 0 COMMENT 'FK to the #__assets table.', + `content` TEXT NOT NULL, + `index` INT(11) NOT NULL DEFAULT 0, + `name` VARCHAR(255) NOT NULL DEFAULT '', + `open_ai_response` VARCHAR(255) NOT NULL DEFAULT '', + `prompt` VARCHAR(36) NOT NULL DEFAULT '', + `role` VARCHAR(255) NOT NULL DEFAULT '', + `source` TINYINT(1) NOT NULL DEFAULT 0, + `params` text NULL, + `published` TINYINT(3) NOT NULL DEFAULT 1, + `created_by` INT(10) unsigned NOT NULL DEFAULT 0, + `modified_by` INT(10) unsigned NOT NULL DEFAULT 0, + `created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `modified` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `checked_out` int(11) unsigned NOT NULL DEFAULT 0, + `checked_out_time` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `version` INT(10) unsigned NOT NULL DEFAULT 1, + `hits` INT(10) unsigned NOT NULL DEFAULT 0, + `access` INT(10) unsigned NOT NULL DEFAULT 0, + `ordering` INT(11) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_role` (`role`), + KEY `idx_open_ai_response` (`open_ai_response`), + KEY `idx_prompt` (`prompt`), + KEY `idx_source` (`source`), + KEY `idx_access` (`access`), + KEY `idx_checkout` (`checked_out`), + KEY `idx_createdby` (`created_by`), + KEY `idx_modifiedby` (`modified_by`), + KEY `idx_state` (`published`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `#__getbible_password` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `asset_id` INT(10) unsigned NOT NULL DEFAULT 0 COMMENT 'FK to the #__assets table.', + `guid` VARCHAR(36) NOT NULL DEFAULT '', + `linker` VARCHAR(36) NOT NULL DEFAULT '', + `name` VARCHAR(255) NOT NULL DEFAULT '', + `password` VARCHAR(100) NOT NULL DEFAULT '', + `params` text NULL, + `published` TINYINT(3) NOT NULL DEFAULT 1, + `created_by` INT(10) unsigned NOT NULL DEFAULT 0, + `modified_by` INT(10) unsigned NOT NULL DEFAULT 0, + `created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `modified` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `checked_out` int(11) unsigned NOT NULL DEFAULT 0, + `checked_out_time` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `version` INT(10) unsigned NOT NULL DEFAULT 1, + `hits` INT(10) unsigned NOT NULL DEFAULT 0, + `access` INT(10) unsigned NOT NULL DEFAULT 0, + `ordering` INT(11) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_name` (`name`), + KEY `idx_linker` (`linker`), + KEY `idx_guid` (`guid`), + KEY `idx_access` (`access`), + KEY `idx_checkout` (`checked_out`), + KEY `idx_createdby` (`created_by`), + KEY `idx_modifiedby` (`modified_by`), + KEY `idx_state` (`published`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `#__getbible_tag` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `asset_id` INT(10) unsigned NOT NULL DEFAULT 0 COMMENT 'FK to the #__assets table.', + `access` TINYINT(1) NOT NULL DEFAULT 0, + `description` TEXT NOT NULL, + `guid` VARCHAR(36) NOT NULL DEFAULT '', + `linker` VARCHAR(36) NOT NULL DEFAULT '', + `name` VARCHAR(255) NOT NULL DEFAULT '', + `params` text NULL, + `published` TINYINT(3) NOT NULL DEFAULT 1, + `created_by` INT(10) unsigned NOT NULL DEFAULT 0, + `modified_by` INT(10) unsigned NOT NULL DEFAULT 0, + `created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `modified` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `checked_out` int(11) unsigned NOT NULL DEFAULT 0, + `checked_out_time` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `version` INT(10) unsigned NOT NULL DEFAULT 1, + `hits` INT(10) unsigned NOT NULL DEFAULT 0, + `ordering` INT(11) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_name` (`name`), + KEY `idx_linker` (`linker`), + KEY `idx_guid` (`guid`), + KEY `idx_access` (`access`), + KEY `idx_checkout` (`checked_out`), + KEY `idx_createdby` (`created_by`), + KEY `idx_modifiedby` (`modified_by`), + KEY `idx_state` (`published`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `#__getbible_translation` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `asset_id` INT(10) unsigned NOT NULL DEFAULT 0 COMMENT 'FK to the #__assets table.', + `abbreviation` VARCHAR(64) NOT NULL DEFAULT '', + `direction` VARCHAR(64) NOT NULL DEFAULT '', + `distribution_abbreviation` VARCHAR(64) NOT NULL DEFAULT '', + `distribution_about` TEXT NOT NULL, + `distribution_history` TEXT NOT NULL, + `distribution_lcsh` VARCHAR(64) NOT NULL DEFAULT '', + `distribution_license` TEXT NOT NULL, + `distribution_source` VARCHAR(255) NOT NULL DEFAULT '', + `distribution_sourcetype` VARCHAR(64) NOT NULL DEFAULT '', + `distribution_versification` VARCHAR(64) NOT NULL DEFAULT '', + `distribution_version` VARCHAR(64) NOT NULL DEFAULT '', + `distribution_version_date` VARCHAR(64) NOT NULL DEFAULT '', + `encoding` VARCHAR(64) NOT NULL DEFAULT '', + `lang` VARCHAR(255) NOT NULL DEFAULT '', + `language` VARCHAR(100) NOT NULL DEFAULT '', + `sha` VARCHAR(64) NOT NULL DEFAULT '', + `translation` VARCHAR(255) NOT NULL DEFAULT '', + `params` text NULL, + `published` TINYINT(3) NOT NULL DEFAULT 1, + `created_by` INT(10) unsigned NOT NULL DEFAULT 0, + `modified_by` INT(10) unsigned NOT NULL DEFAULT 0, + `created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `modified` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `checked_out` int(11) unsigned NOT NULL DEFAULT 0, + `checked_out_time` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `version` INT(10) unsigned NOT NULL DEFAULT 1, + `hits` INT(10) unsigned NOT NULL DEFAULT 0, + `access` INT(10) unsigned NOT NULL DEFAULT 0, + `ordering` INT(11) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_translation` (`translation`), + KEY `idx_access` (`access`), + KEY `idx_checkout` (`checked_out`), + KEY `idx_createdby` (`created_by`), + KEY `idx_modifiedby` (`modified_by`), + KEY `idx_state` (`published`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `#__getbible_book` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `asset_id` INT(10) unsigned NOT NULL DEFAULT 0 COMMENT 'FK to the #__assets table.', + `abbreviation` VARCHAR(100) NOT NULL DEFAULT '', + `name` VARCHAR(255) NOT NULL DEFAULT '', + `nr` INT(7) NOT NULL DEFAULT 0, + `sha` VARCHAR(64) NOT NULL DEFAULT '', + `params` text NULL, + `published` TINYINT(3) NOT NULL DEFAULT 1, + `created_by` INT(10) unsigned NOT NULL DEFAULT 0, + `modified_by` INT(10) unsigned NOT NULL DEFAULT 0, + `created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `modified` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `checked_out` int(11) unsigned NOT NULL DEFAULT 0, + `checked_out_time` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `version` INT(10) unsigned NOT NULL DEFAULT 1, + `hits` INT(10) unsigned NOT NULL DEFAULT 0, + `access` INT(10) unsigned NOT NULL DEFAULT 0, + `ordering` INT(11) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_name` (`name`), + KEY `idx_abbreviation` (`abbreviation`), + KEY `idx_nr` (`nr`), + KEY `idx_access` (`access`), + KEY `idx_checkout` (`checked_out`), + KEY `idx_createdby` (`created_by`), + KEY `idx_modifiedby` (`modified_by`), + KEY `idx_state` (`published`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `#__getbible_chapter` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `asset_id` INT(10) unsigned NOT NULL DEFAULT 0 COMMENT 'FK to the #__assets table.', + `abbreviation` VARCHAR(100) NOT NULL DEFAULT '', + `book_nr` INT(7) NOT NULL DEFAULT 0, + `chapter` INT(7) NOT NULL DEFAULT 0, + `name` VARCHAR(255) NOT NULL DEFAULT '', + `sha` VARCHAR(64) NOT NULL DEFAULT '', + `params` text NULL, + `published` TINYINT(3) NOT NULL DEFAULT 1, + `created_by` INT(10) unsigned NOT NULL DEFAULT 0, + `modified_by` INT(10) unsigned NOT NULL DEFAULT 0, + `created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `modified` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `checked_out` int(11) unsigned NOT NULL DEFAULT 0, + `checked_out_time` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `version` INT(10) unsigned NOT NULL DEFAULT 1, + `hits` INT(10) unsigned NOT NULL DEFAULT 0, + `access` INT(10) unsigned NOT NULL DEFAULT 0, + `ordering` INT(11) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_name` (`name`), + KEY `idx_chapter` (`chapter`), + KEY `idx_book_nr` (`book_nr`), + KEY `idx_abbreviation` (`abbreviation`), + KEY `idx_access` (`access`), + KEY `idx_checkout` (`checked_out`), + KEY `idx_createdby` (`created_by`), + KEY `idx_modifiedby` (`modified_by`), + KEY `idx_state` (`published`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `#__getbible_verse` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `asset_id` INT(10) unsigned NOT NULL DEFAULT 0 COMMENT 'FK to the #__assets table.', + `abbreviation` VARCHAR(100) NOT NULL DEFAULT '', + `book_nr` INT(7) NOT NULL DEFAULT 0, + `chapter` INT(7) NOT NULL DEFAULT 0, + `name` VARCHAR(255) NOT NULL DEFAULT '', + `text` TEXT NOT NULL, + `verse` INT(7) NOT NULL DEFAULT 0, + `params` text NULL, + `published` TINYINT(3) NOT NULL DEFAULT 1, + `created_by` INT(10) unsigned NOT NULL DEFAULT 0, + `modified_by` INT(10) unsigned NOT NULL DEFAULT 0, + `created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `modified` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `checked_out` int(11) unsigned NOT NULL DEFAULT 0, + `checked_out_time` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `version` INT(10) unsigned NOT NULL DEFAULT 1, + `hits` INT(10) unsigned NOT NULL DEFAULT 0, + `access` INT(10) unsigned NOT NULL DEFAULT 0, + `ordering` INT(11) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_book_nr` (`book_nr`), + KEY `idx_chapter` (`chapter`), + KEY `idx_verse` (`verse`), + KEY `idx_abbreviation` (`abbreviation`), + KEY `idx_name` (`name`), + KEY `idx_access` (`access`), + KEY `idx_checkout` (`checked_out`), + KEY `idx_createdby` (`created_by`), + KEY `idx_modifiedby` (`modified_by`), + KEY `idx_state` (`published`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci; + + diff --git a/admin/sql/uninstall.mysql.utf8.sql b/admin/sql/uninstall.mysql.utf8.sql new file mode 100644 index 0000000..898f828 --- /dev/null +++ b/admin/sql/uninstall.mysql.utf8.sql @@ -0,0 +1,13 @@ +DROP TABLE IF EXISTS `#__getbible_linker`; +DROP TABLE IF EXISTS `#__getbible_note`; +DROP TABLE IF EXISTS `#__getbible_tagged_verse`; +DROP TABLE IF EXISTS `#__getbible_prompt`; +DROP TABLE IF EXISTS `#__getbible_open_ai_response`; +DROP TABLE IF EXISTS `#__getbible_open_ai_message`; +DROP TABLE IF EXISTS `#__getbible_password`; +DROP TABLE IF EXISTS `#__getbible_tag`; +DROP TABLE IF EXISTS `#__getbible_translation`; +DROP TABLE IF EXISTS `#__getbible_book`; +DROP TABLE IF EXISTS `#__getbible_chapter`; +DROP TABLE IF EXISTS `#__getbible_verse`; + diff --git a/admin/sql/updates/index.html b/admin/sql/updates/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/sql/updates/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/sql/updates/mysql/index.html b/admin/sql/updates/mysql/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/sql/updates/mysql/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/tables/book.php b/admin/tables/book.php new file mode 100644 index 0000000..6a2e1f9 --- /dev/null +++ b/admin/tables/book.php @@ -0,0 +1,327 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Table\Table; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; + +/** + * Books Table class + */ +class GetbibleTableBook extends Table +{ + /** + * Ensure the params and metadata in json encoded in the bind method + * + * @var array + * @since 3.3 + */ + protected $_jsonEncode = array('params', 'metadata'); + + /** + * Constructor + * + * @param object Database connector object + */ + function __construct(&$db) + { + parent::__construct('#__getbible_book', 'id', $db); + } + + public function bind($array, $ignore = '') + { + + if (isset($array['params']) && is_array($array['params'])) + { + $registry = new JRegistry; + $registry->loadArray($array['params']); + $array['params'] = (string) $registry; + } + + if (isset($array['metadata']) && is_array($array['metadata'])) + { + $registry = new JRegistry; + $registry->loadArray($array['metadata']); + $array['metadata'] = (string) $registry; + } + + // Bind the rules. + if (isset($array['rules']) && is_array($array['rules'])) + { + $rules = new JAccessRules($array['rules']); + $this->setRules($rules); + } + return parent::bind($array, $ignore); + } + + /** + * Overload the store method for the Book table. + * + * @param boolean Toggle whether null values should be updated. + * @return boolean True on success, false on failure. + * @since 1.6 + */ + public function store($updateNulls = false) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if ($this->id) + { + // Existing item + $this->modified = $date->toSql(); + $this->modified_by = $user->get('id'); + } + else + { + // New book. A book created and created_by field can be set by the user, + // so we don't touch either of these if they are set. + if (!(int) $this->created) + { + $this->created = $date->toSql(); + } + if (empty($this->created_by)) + { + $this->created_by = $user->get('id'); + } + } + + if (isset($this->alias)) + { + // Verify that the alias is unique + $table = JTable::getInstance('book', 'GetbibleTable'); + + if ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->setError(JText::_('COM_GETBIBLE_BOOK_ERROR_UNIQUE_ALIAS')); + return false; + } + } + + if (isset($this->url)) + { + // Convert IDN urls to punycode + $this->url = JStringPunycode::urlToPunycode($this->url); + } + if (isset($this->website)) + { + // Convert IDN urls to punycode + $this->website = JStringPunycode::urlToPunycode($this->website); + } + + return parent::store($updateNulls); + } + + /** + * Overloaded check method to ensure data integrity. + * + * @return boolean True on success. + */ + public function check() + { + if (isset($this->alias)) + { + // Generate a valid alias + $this->generateAlias(); + + $table = JTable::getInstance('book', 'getbibleTable'); + + while ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->alias = StringHelper::increment($this->alias, 'dash'); + } + } + + /* + * Clean up keywords -- eliminate extra spaces between phrases + * and cr (\r) and lf (\n) characters from string. + * Only process if not empty. + */ + if (!empty($this->metakey)) + { + // Array of characters to remove. + $bad_characters = array("\n", "\r", "\"", "<", ">"); + + // Remove bad characters. + $after_clean = StringHelper::str_ireplace($bad_characters, "", $this->metakey); + + // Create array using commas as delimiter. + $keys = explode(',', $after_clean); + $clean_keys = array(); + + foreach ($keys as $key) + { + // Ignore blank keywords. + if (trim($key)) + { + $clean_keys[] = trim($key); + } + } + + // Put array back together delimited by ", " + $this->metakey = implode(", ", $clean_keys); + } + + // Clean up description -- eliminate quotes and <> brackets + if (!empty($this->metadesc)) + { + // Only process if not empty + $bad_characters = array("\"", "<", ">"); + $this->metadesc = StringHelper::str_ireplace($bad_characters, "", $this->metadesc); + } + + // If we don't have any access rules set at this point just use an empty JAccessRules class + if (!$this->getRules()) + { + $rules = $this->getDefaultAssetValues('com_getbible.book.'.$this->id); + $this->setRules($rules); + } + + // Set ordering + if ($this->published < 0) + { + // Set ordering to 0 if state is archived or trashed + $this->ordering = 0; + } + + return true; + } + + /** + * Gets the default asset values for a component. + * + * @param $string $component The component asset name to search for + * + * @return JAccessRules The JAccessRules object for the asset + */ + protected function getDefaultAssetValues($component, $try = true) + { + // Need to find the asset id by the name of the component. + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select($db->quoteName('id')) + ->from($db->quoteName('#__assets')) + ->where($db->quoteName('name') . ' = ' . $db->quote($component)); + $db->setQuery($query); + $db->execute(); + if ($db->loadRowList()) + { + // asset already set so use saved rules + $assetId = (int) $db->loadResult(); + return JAccess::getAssetRules($assetId); // (TODO) instead of keeping inherited Allowed it becomes Allowed. + } + // try again + elseif ($try) + { + $try = explode('.',$component); + $result = $this->getDefaultAssetValues($try[0], false); + if ($result instanceof JAccessRules) + { + if (isset($try[1])) + { + $_result = (string) $result; + $_result = json_decode($_result); + foreach ($_result as $name => &$rule) + { + $v = explode('.', $name); + if ($try[1] !== $v[0]) + { + // remove since it is not part of this view + unset($_result->$name); + } + else + { + // clear the value since we inherit + $rule = array(); + } + } + // check if there are any view values remaining + if (count( (array) $_result)) + { + $_result = json_encode($_result); + $_result = array($_result); + // Instantiate and return the JAccessRules object for the asset rules. + $rules = new JAccessRules; + $rules->mergeCollection($_result); + + return $rules; + } + } + return $result; + } + } + return JAccess::getAssetRules(0); + } + + /** + * Method to compute the default name of the asset. + * The default name is in the form 'table_name.id' + * where id is the value of the primary key of the table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetName() + { + $k = $this->_tbl_key; + return 'com_getbible.book.'.(int) $this->$k; + } + + /** + * Method to return the title to use for the asset table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetTitle() + { + if (isset($this->title)) + { + return $this->title; + } + return ''; + } + + /** + * Get the parent asset id for the record + * + * @return int + * @since 2.5 + */ + protected function _getAssetParentId(JTable $table = NULL, $id = NULL) + { + $asset = JTable::getInstance('Asset'); + $asset->loadByName('com_getbible'); + + return $asset->id; + } + + /** + * This view does not actually have an alias + * + * @return bool + */ + public function generateAlias() + { + return false; + } + +} diff --git a/admin/tables/chapter.php b/admin/tables/chapter.php new file mode 100644 index 0000000..41a17bd --- /dev/null +++ b/admin/tables/chapter.php @@ -0,0 +1,327 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Table\Table; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; + +/** + * Chapters Table class + */ +class GetbibleTableChapter extends Table +{ + /** + * Ensure the params and metadata in json encoded in the bind method + * + * @var array + * @since 3.3 + */ + protected $_jsonEncode = array('params', 'metadata'); + + /** + * Constructor + * + * @param object Database connector object + */ + function __construct(&$db) + { + parent::__construct('#__getbible_chapter', 'id', $db); + } + + public function bind($array, $ignore = '') + { + + if (isset($array['params']) && is_array($array['params'])) + { + $registry = new JRegistry; + $registry->loadArray($array['params']); + $array['params'] = (string) $registry; + } + + if (isset($array['metadata']) && is_array($array['metadata'])) + { + $registry = new JRegistry; + $registry->loadArray($array['metadata']); + $array['metadata'] = (string) $registry; + } + + // Bind the rules. + if (isset($array['rules']) && is_array($array['rules'])) + { + $rules = new JAccessRules($array['rules']); + $this->setRules($rules); + } + return parent::bind($array, $ignore); + } + + /** + * Overload the store method for the Chapter table. + * + * @param boolean Toggle whether null values should be updated. + * @return boolean True on success, false on failure. + * @since 1.6 + */ + public function store($updateNulls = false) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if ($this->id) + { + // Existing item + $this->modified = $date->toSql(); + $this->modified_by = $user->get('id'); + } + else + { + // New chapter. A chapter created and created_by field can be set by the user, + // so we don't touch either of these if they are set. + if (!(int) $this->created) + { + $this->created = $date->toSql(); + } + if (empty($this->created_by)) + { + $this->created_by = $user->get('id'); + } + } + + if (isset($this->alias)) + { + // Verify that the alias is unique + $table = JTable::getInstance('chapter', 'GetbibleTable'); + + if ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->setError(JText::_('COM_GETBIBLE_CHAPTER_ERROR_UNIQUE_ALIAS')); + return false; + } + } + + if (isset($this->url)) + { + // Convert IDN urls to punycode + $this->url = JStringPunycode::urlToPunycode($this->url); + } + if (isset($this->website)) + { + // Convert IDN urls to punycode + $this->website = JStringPunycode::urlToPunycode($this->website); + } + + return parent::store($updateNulls); + } + + /** + * Overloaded check method to ensure data integrity. + * + * @return boolean True on success. + */ + public function check() + { + if (isset($this->alias)) + { + // Generate a valid alias + $this->generateAlias(); + + $table = JTable::getInstance('chapter', 'getbibleTable'); + + while ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->alias = StringHelper::increment($this->alias, 'dash'); + } + } + + /* + * Clean up keywords -- eliminate extra spaces between phrases + * and cr (\r) and lf (\n) characters from string. + * Only process if not empty. + */ + if (!empty($this->metakey)) + { + // Array of characters to remove. + $bad_characters = array("\n", "\r", "\"", "<", ">"); + + // Remove bad characters. + $after_clean = StringHelper::str_ireplace($bad_characters, "", $this->metakey); + + // Create array using commas as delimiter. + $keys = explode(',', $after_clean); + $clean_keys = array(); + + foreach ($keys as $key) + { + // Ignore blank keywords. + if (trim($key)) + { + $clean_keys[] = trim($key); + } + } + + // Put array back together delimited by ", " + $this->metakey = implode(", ", $clean_keys); + } + + // Clean up description -- eliminate quotes and <> brackets + if (!empty($this->metadesc)) + { + // Only process if not empty + $bad_characters = array("\"", "<", ">"); + $this->metadesc = StringHelper::str_ireplace($bad_characters, "", $this->metadesc); + } + + // If we don't have any access rules set at this point just use an empty JAccessRules class + if (!$this->getRules()) + { + $rules = $this->getDefaultAssetValues('com_getbible.chapter.'.$this->id); + $this->setRules($rules); + } + + // Set ordering + if ($this->published < 0) + { + // Set ordering to 0 if state is archived or trashed + $this->ordering = 0; + } + + return true; + } + + /** + * Gets the default asset values for a component. + * + * @param $string $component The component asset name to search for + * + * @return JAccessRules The JAccessRules object for the asset + */ + protected function getDefaultAssetValues($component, $try = true) + { + // Need to find the asset id by the name of the component. + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select($db->quoteName('id')) + ->from($db->quoteName('#__assets')) + ->where($db->quoteName('name') . ' = ' . $db->quote($component)); + $db->setQuery($query); + $db->execute(); + if ($db->loadRowList()) + { + // asset already set so use saved rules + $assetId = (int) $db->loadResult(); + return JAccess::getAssetRules($assetId); // (TODO) instead of keeping inherited Allowed it becomes Allowed. + } + // try again + elseif ($try) + { + $try = explode('.',$component); + $result = $this->getDefaultAssetValues($try[0], false); + if ($result instanceof JAccessRules) + { + if (isset($try[1])) + { + $_result = (string) $result; + $_result = json_decode($_result); + foreach ($_result as $name => &$rule) + { + $v = explode('.', $name); + if ($try[1] !== $v[0]) + { + // remove since it is not part of this view + unset($_result->$name); + } + else + { + // clear the value since we inherit + $rule = array(); + } + } + // check if there are any view values remaining + if (count( (array) $_result)) + { + $_result = json_encode($_result); + $_result = array($_result); + // Instantiate and return the JAccessRules object for the asset rules. + $rules = new JAccessRules; + $rules->mergeCollection($_result); + + return $rules; + } + } + return $result; + } + } + return JAccess::getAssetRules(0); + } + + /** + * Method to compute the default name of the asset. + * The default name is in the form 'table_name.id' + * where id is the value of the primary key of the table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetName() + { + $k = $this->_tbl_key; + return 'com_getbible.chapter.'.(int) $this->$k; + } + + /** + * Method to return the title to use for the asset table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetTitle() + { + if (isset($this->title)) + { + return $this->title; + } + return ''; + } + + /** + * Get the parent asset id for the record + * + * @return int + * @since 2.5 + */ + protected function _getAssetParentId(JTable $table = NULL, $id = NULL) + { + $asset = JTable::getInstance('Asset'); + $asset->loadByName('com_getbible'); + + return $asset->id; + } + + /** + * This view does not actually have an alias + * + * @return bool + */ + public function generateAlias() + { + return false; + } + +} diff --git a/admin/tables/index.html b/admin/tables/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/tables/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/tables/linker.php b/admin/tables/linker.php new file mode 100644 index 0000000..d9e9b66 --- /dev/null +++ b/admin/tables/linker.php @@ -0,0 +1,327 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Table\Table; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; + +/** + * Linkers Table class + */ +class GetbibleTableLinker extends Table +{ + /** + * Ensure the params and metadata in json encoded in the bind method + * + * @var array + * @since 3.3 + */ + protected $_jsonEncode = array('params', 'metadata'); + + /** + * Constructor + * + * @param object Database connector object + */ + function __construct(&$db) + { + parent::__construct('#__getbible_linker', 'id', $db); + } + + public function bind($array, $ignore = '') + { + + if (isset($array['params']) && is_array($array['params'])) + { + $registry = new JRegistry; + $registry->loadArray($array['params']); + $array['params'] = (string) $registry; + } + + if (isset($array['metadata']) && is_array($array['metadata'])) + { + $registry = new JRegistry; + $registry->loadArray($array['metadata']); + $array['metadata'] = (string) $registry; + } + + // Bind the rules. + if (isset($array['rules']) && is_array($array['rules'])) + { + $rules = new JAccessRules($array['rules']); + $this->setRules($rules); + } + return parent::bind($array, $ignore); + } + + /** + * Overload the store method for the Linker table. + * + * @param boolean Toggle whether null values should be updated. + * @return boolean True on success, false on failure. + * @since 1.6 + */ + public function store($updateNulls = false) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if ($this->id) + { + // Existing item + $this->modified = $date->toSql(); + $this->modified_by = $user->get('id'); + } + else + { + // New linker. A linker created and created_by field can be set by the user, + // so we don't touch either of these if they are set. + if (!(int) $this->created) + { + $this->created = $date->toSql(); + } + if (empty($this->created_by)) + { + $this->created_by = $user->get('id'); + } + } + + if (isset($this->alias)) + { + // Verify that the alias is unique + $table = JTable::getInstance('linker', 'GetbibleTable'); + + if ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->setError(JText::_('COM_GETBIBLE_LINKER_ERROR_UNIQUE_ALIAS')); + return false; + } + } + + if (isset($this->url)) + { + // Convert IDN urls to punycode + $this->url = JStringPunycode::urlToPunycode($this->url); + } + if (isset($this->website)) + { + // Convert IDN urls to punycode + $this->website = JStringPunycode::urlToPunycode($this->website); + } + + return parent::store($updateNulls); + } + + /** + * Overloaded check method to ensure data integrity. + * + * @return boolean True on success. + */ + public function check() + { + if (isset($this->alias)) + { + // Generate a valid alias + $this->generateAlias(); + + $table = JTable::getInstance('linker', 'getbibleTable'); + + while ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->alias = StringHelper::increment($this->alias, 'dash'); + } + } + + /* + * Clean up keywords -- eliminate extra spaces between phrases + * and cr (\r) and lf (\n) characters from string. + * Only process if not empty. + */ + if (!empty($this->metakey)) + { + // Array of characters to remove. + $bad_characters = array("\n", "\r", "\"", "<", ">"); + + // Remove bad characters. + $after_clean = StringHelper::str_ireplace($bad_characters, "", $this->metakey); + + // Create array using commas as delimiter. + $keys = explode(',', $after_clean); + $clean_keys = array(); + + foreach ($keys as $key) + { + // Ignore blank keywords. + if (trim($key)) + { + $clean_keys[] = trim($key); + } + } + + // Put array back together delimited by ", " + $this->metakey = implode(", ", $clean_keys); + } + + // Clean up description -- eliminate quotes and <> brackets + if (!empty($this->metadesc)) + { + // Only process if not empty + $bad_characters = array("\"", "<", ">"); + $this->metadesc = StringHelper::str_ireplace($bad_characters, "", $this->metadesc); + } + + // If we don't have any access rules set at this point just use an empty JAccessRules class + if (!$this->getRules()) + { + $rules = $this->getDefaultAssetValues('com_getbible.linker.'.$this->id); + $this->setRules($rules); + } + + // Set ordering + if ($this->published < 0) + { + // Set ordering to 0 if state is archived or trashed + $this->ordering = 0; + } + + return true; + } + + /** + * Gets the default asset values for a component. + * + * @param $string $component The component asset name to search for + * + * @return JAccessRules The JAccessRules object for the asset + */ + protected function getDefaultAssetValues($component, $try = true) + { + // Need to find the asset id by the name of the component. + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select($db->quoteName('id')) + ->from($db->quoteName('#__assets')) + ->where($db->quoteName('name') . ' = ' . $db->quote($component)); + $db->setQuery($query); + $db->execute(); + if ($db->loadRowList()) + { + // asset already set so use saved rules + $assetId = (int) $db->loadResult(); + return JAccess::getAssetRules($assetId); // (TODO) instead of keeping inherited Allowed it becomes Allowed. + } + // try again + elseif ($try) + { + $try = explode('.',$component); + $result = $this->getDefaultAssetValues($try[0], false); + if ($result instanceof JAccessRules) + { + if (isset($try[1])) + { + $_result = (string) $result; + $_result = json_decode($_result); + foreach ($_result as $name => &$rule) + { + $v = explode('.', $name); + if ($try[1] !== $v[0]) + { + // remove since it is not part of this view + unset($_result->$name); + } + else + { + // clear the value since we inherit + $rule = array(); + } + } + // check if there are any view values remaining + if (count( (array) $_result)) + { + $_result = json_encode($_result); + $_result = array($_result); + // Instantiate and return the JAccessRules object for the asset rules. + $rules = new JAccessRules; + $rules->mergeCollection($_result); + + return $rules; + } + } + return $result; + } + } + return JAccess::getAssetRules(0); + } + + /** + * Method to compute the default name of the asset. + * The default name is in the form 'table_name.id' + * where id is the value of the primary key of the table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetName() + { + $k = $this->_tbl_key; + return 'com_getbible.linker.'.(int) $this->$k; + } + + /** + * Method to return the title to use for the asset table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetTitle() + { + if (isset($this->title)) + { + return $this->title; + } + return ''; + } + + /** + * Get the parent asset id for the record + * + * @return int + * @since 2.5 + */ + protected function _getAssetParentId(JTable $table = NULL, $id = NULL) + { + $asset = JTable::getInstance('Asset'); + $asset->loadByName('com_getbible'); + + return $asset->id; + } + + /** + * This view does not actually have an alias + * + * @return bool + */ + public function generateAlias() + { + return false; + } + +} diff --git a/admin/tables/note.php b/admin/tables/note.php new file mode 100644 index 0000000..45296be --- /dev/null +++ b/admin/tables/note.php @@ -0,0 +1,330 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Table\Table; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; + +/** + * Notes Table class + */ +class GetbibleTableNote extends Table +{ + /** + * Ensure the params and metadata in json encoded in the bind method + * + * @var array + * @since 3.3 + */ + protected $_jsonEncode = array('params', 'metadata'); + + /** + * Constructor + * + * @param object Database connector object + */ + function __construct(&$db) + { + parent::__construct('#__getbible_note', 'id', $db); + + // Adding History Options + JTableObserverContenthistory::createObserver($this, array('typeAlias' => 'com_getbible.note')); + } + + public function bind($array, $ignore = '') + { + + if (isset($array['params']) && is_array($array['params'])) + { + $registry = new JRegistry; + $registry->loadArray($array['params']); + $array['params'] = (string) $registry; + } + + if (isset($array['metadata']) && is_array($array['metadata'])) + { + $registry = new JRegistry; + $registry->loadArray($array['metadata']); + $array['metadata'] = (string) $registry; + } + + // Bind the rules. + if (isset($array['rules']) && is_array($array['rules'])) + { + $rules = new JAccessRules($array['rules']); + $this->setRules($rules); + } + return parent::bind($array, $ignore); + } + + /** + * Overload the store method for the Note table. + * + * @param boolean Toggle whether null values should be updated. + * @return boolean True on success, false on failure. + * @since 1.6 + */ + public function store($updateNulls = false) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if ($this->id) + { + // Existing item + $this->modified = $date->toSql(); + $this->modified_by = $user->get('id'); + } + else + { + // New note. A note created and created_by field can be set by the user, + // so we don't touch either of these if they are set. + if (!(int) $this->created) + { + $this->created = $date->toSql(); + } + if (empty($this->created_by)) + { + $this->created_by = $user->get('id'); + } + } + + if (isset($this->alias)) + { + // Verify that the alias is unique + $table = JTable::getInstance('note', 'GetbibleTable'); + + if ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->setError(JText::_('COM_GETBIBLE_NOTE_ERROR_UNIQUE_ALIAS')); + return false; + } + } + + if (isset($this->url)) + { + // Convert IDN urls to punycode + $this->url = JStringPunycode::urlToPunycode($this->url); + } + if (isset($this->website)) + { + // Convert IDN urls to punycode + $this->website = JStringPunycode::urlToPunycode($this->website); + } + + return parent::store($updateNulls); + } + + /** + * Overloaded check method to ensure data integrity. + * + * @return boolean True on success. + */ + public function check() + { + if (isset($this->alias)) + { + // Generate a valid alias + $this->generateAlias(); + + $table = JTable::getInstance('note', 'getbibleTable'); + + while ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->alias = StringHelper::increment($this->alias, 'dash'); + } + } + + /* + * Clean up keywords -- eliminate extra spaces between phrases + * and cr (\r) and lf (\n) characters from string. + * Only process if not empty. + */ + if (!empty($this->metakey)) + { + // Array of characters to remove. + $bad_characters = array("\n", "\r", "\"", "<", ">"); + + // Remove bad characters. + $after_clean = StringHelper::str_ireplace($bad_characters, "", $this->metakey); + + // Create array using commas as delimiter. + $keys = explode(',', $after_clean); + $clean_keys = array(); + + foreach ($keys as $key) + { + // Ignore blank keywords. + if (trim($key)) + { + $clean_keys[] = trim($key); + } + } + + // Put array back together delimited by ", " + $this->metakey = implode(", ", $clean_keys); + } + + // Clean up description -- eliminate quotes and <> brackets + if (!empty($this->metadesc)) + { + // Only process if not empty + $bad_characters = array("\"", "<", ">"); + $this->metadesc = StringHelper::str_ireplace($bad_characters, "", $this->metadesc); + } + + // If we don't have any access rules set at this point just use an empty JAccessRules class + if (!$this->getRules()) + { + $rules = $this->getDefaultAssetValues('com_getbible.note.'.$this->id); + $this->setRules($rules); + } + + // Set ordering + if ($this->published < 0) + { + // Set ordering to 0 if state is archived or trashed + $this->ordering = 0; + } + + return true; + } + + /** + * Gets the default asset values for a component. + * + * @param $string $component The component asset name to search for + * + * @return JAccessRules The JAccessRules object for the asset + */ + protected function getDefaultAssetValues($component, $try = true) + { + // Need to find the asset id by the name of the component. + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select($db->quoteName('id')) + ->from($db->quoteName('#__assets')) + ->where($db->quoteName('name') . ' = ' . $db->quote($component)); + $db->setQuery($query); + $db->execute(); + if ($db->loadRowList()) + { + // asset already set so use saved rules + $assetId = (int) $db->loadResult(); + return JAccess::getAssetRules($assetId); // (TODO) instead of keeping inherited Allowed it becomes Allowed. + } + // try again + elseif ($try) + { + $try = explode('.',$component); + $result = $this->getDefaultAssetValues($try[0], false); + if ($result instanceof JAccessRules) + { + if (isset($try[1])) + { + $_result = (string) $result; + $_result = json_decode($_result); + foreach ($_result as $name => &$rule) + { + $v = explode('.', $name); + if ($try[1] !== $v[0]) + { + // remove since it is not part of this view + unset($_result->$name); + } + else + { + // clear the value since we inherit + $rule = array(); + } + } + // check if there are any view values remaining + if (count( (array) $_result)) + { + $_result = json_encode($_result); + $_result = array($_result); + // Instantiate and return the JAccessRules object for the asset rules. + $rules = new JAccessRules; + $rules->mergeCollection($_result); + + return $rules; + } + } + return $result; + } + } + return JAccess::getAssetRules(0); + } + + /** + * Method to compute the default name of the asset. + * The default name is in the form 'table_name.id' + * where id is the value of the primary key of the table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetName() + { + $k = $this->_tbl_key; + return 'com_getbible.note.'.(int) $this->$k; + } + + /** + * Method to return the title to use for the asset table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetTitle() + { + if (isset($this->title)) + { + return $this->title; + } + return ''; + } + + /** + * Get the parent asset id for the record + * + * @return int + * @since 2.5 + */ + protected function _getAssetParentId(JTable $table = NULL, $id = NULL) + { + $asset = JTable::getInstance('Asset'); + $asset->loadByName('com_getbible'); + + return $asset->id; + } + + /** + * This view does not actually have an alias + * + * @return bool + */ + public function generateAlias() + { + return false; + } + +} diff --git a/admin/tables/open_ai_message.php b/admin/tables/open_ai_message.php new file mode 100644 index 0000000..bfde711 --- /dev/null +++ b/admin/tables/open_ai_message.php @@ -0,0 +1,330 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Table\Table; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; + +/** + * Open_ai_messages Table class + */ +class GetbibleTableOpen_ai_message extends Table +{ + /** + * Ensure the params and metadata in json encoded in the bind method + * + * @var array + * @since 3.3 + */ + protected $_jsonEncode = array('params', 'metadata'); + + /** + * Constructor + * + * @param object Database connector object + */ + function __construct(&$db) + { + parent::__construct('#__getbible_open_ai_message', 'id', $db); + + // Adding History Options + JTableObserverContenthistory::createObserver($this, array('typeAlias' => 'com_getbible.open_ai_message')); + } + + public function bind($array, $ignore = '') + { + + if (isset($array['params']) && is_array($array['params'])) + { + $registry = new JRegistry; + $registry->loadArray($array['params']); + $array['params'] = (string) $registry; + } + + if (isset($array['metadata']) && is_array($array['metadata'])) + { + $registry = new JRegistry; + $registry->loadArray($array['metadata']); + $array['metadata'] = (string) $registry; + } + + // Bind the rules. + if (isset($array['rules']) && is_array($array['rules'])) + { + $rules = new JAccessRules($array['rules']); + $this->setRules($rules); + } + return parent::bind($array, $ignore); + } + + /** + * Overload the store method for the Open_ai_message table. + * + * @param boolean Toggle whether null values should be updated. + * @return boolean True on success, false on failure. + * @since 1.6 + */ + public function store($updateNulls = false) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if ($this->id) + { + // Existing item + $this->modified = $date->toSql(); + $this->modified_by = $user->get('id'); + } + else + { + // New open_ai_message. A open_ai_message created and created_by field can be set by the user, + // so we don't touch either of these if they are set. + if (!(int) $this->created) + { + $this->created = $date->toSql(); + } + if (empty($this->created_by)) + { + $this->created_by = $user->get('id'); + } + } + + if (isset($this->alias)) + { + // Verify that the alias is unique + $table = JTable::getInstance('open_ai_message', 'GetbibleTable'); + + if ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->setError(JText::_('COM_GETBIBLE_OPEN_AI_MESSAGE_ERROR_UNIQUE_ALIAS')); + return false; + } + } + + if (isset($this->url)) + { + // Convert IDN urls to punycode + $this->url = JStringPunycode::urlToPunycode($this->url); + } + if (isset($this->website)) + { + // Convert IDN urls to punycode + $this->website = JStringPunycode::urlToPunycode($this->website); + } + + return parent::store($updateNulls); + } + + /** + * Overloaded check method to ensure data integrity. + * + * @return boolean True on success. + */ + public function check() + { + if (isset($this->alias)) + { + // Generate a valid alias + $this->generateAlias(); + + $table = JTable::getInstance('open_ai_message', 'getbibleTable'); + + while ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->alias = StringHelper::increment($this->alias, 'dash'); + } + } + + /* + * Clean up keywords -- eliminate extra spaces between phrases + * and cr (\r) and lf (\n) characters from string. + * Only process if not empty. + */ + if (!empty($this->metakey)) + { + // Array of characters to remove. + $bad_characters = array("\n", "\r", "\"", "<", ">"); + + // Remove bad characters. + $after_clean = StringHelper::str_ireplace($bad_characters, "", $this->metakey); + + // Create array using commas as delimiter. + $keys = explode(',', $after_clean); + $clean_keys = array(); + + foreach ($keys as $key) + { + // Ignore blank keywords. + if (trim($key)) + { + $clean_keys[] = trim($key); + } + } + + // Put array back together delimited by ", " + $this->metakey = implode(", ", $clean_keys); + } + + // Clean up description -- eliminate quotes and <> brackets + if (!empty($this->metadesc)) + { + // Only process if not empty + $bad_characters = array("\"", "<", ">"); + $this->metadesc = StringHelper::str_ireplace($bad_characters, "", $this->metadesc); + } + + // If we don't have any access rules set at this point just use an empty JAccessRules class + if (!$this->getRules()) + { + $rules = $this->getDefaultAssetValues('com_getbible.open_ai_message.'.$this->id); + $this->setRules($rules); + } + + // Set ordering + if ($this->published < 0) + { + // Set ordering to 0 if state is archived or trashed + $this->ordering = 0; + } + + return true; + } + + /** + * Gets the default asset values for a component. + * + * @param $string $component The component asset name to search for + * + * @return JAccessRules The JAccessRules object for the asset + */ + protected function getDefaultAssetValues($component, $try = true) + { + // Need to find the asset id by the name of the component. + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select($db->quoteName('id')) + ->from($db->quoteName('#__assets')) + ->where($db->quoteName('name') . ' = ' . $db->quote($component)); + $db->setQuery($query); + $db->execute(); + if ($db->loadRowList()) + { + // asset already set so use saved rules + $assetId = (int) $db->loadResult(); + return JAccess::getAssetRules($assetId); // (TODO) instead of keeping inherited Allowed it becomes Allowed. + } + // try again + elseif ($try) + { + $try = explode('.',$component); + $result = $this->getDefaultAssetValues($try[0], false); + if ($result instanceof JAccessRules) + { + if (isset($try[1])) + { + $_result = (string) $result; + $_result = json_decode($_result); + foreach ($_result as $name => &$rule) + { + $v = explode('.', $name); + if ($try[1] !== $v[0]) + { + // remove since it is not part of this view + unset($_result->$name); + } + else + { + // clear the value since we inherit + $rule = array(); + } + } + // check if there are any view values remaining + if (count( (array) $_result)) + { + $_result = json_encode($_result); + $_result = array($_result); + // Instantiate and return the JAccessRules object for the asset rules. + $rules = new JAccessRules; + $rules->mergeCollection($_result); + + return $rules; + } + } + return $result; + } + } + return JAccess::getAssetRules(0); + } + + /** + * Method to compute the default name of the asset. + * The default name is in the form 'table_name.id' + * where id is the value of the primary key of the table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetName() + { + $k = $this->_tbl_key; + return 'com_getbible.open_ai_message.'.(int) $this->$k; + } + + /** + * Method to return the title to use for the asset table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetTitle() + { + if (isset($this->title)) + { + return $this->title; + } + return ''; + } + + /** + * Get the parent asset id for the record + * + * @return int + * @since 2.5 + */ + protected function _getAssetParentId(JTable $table = NULL, $id = NULL) + { + $asset = JTable::getInstance('Asset'); + $asset->loadByName('com_getbible'); + + return $asset->id; + } + + /** + * This view does not actually have an alias + * + * @return bool + */ + public function generateAlias() + { + return false; + } + +} diff --git a/admin/tables/open_ai_response.php b/admin/tables/open_ai_response.php new file mode 100644 index 0000000..f4ec262 --- /dev/null +++ b/admin/tables/open_ai_response.php @@ -0,0 +1,330 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Table\Table; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; + +/** + * Open_ai_responses Table class + */ +class GetbibleTableOpen_ai_response extends Table +{ + /** + * Ensure the params and metadata in json encoded in the bind method + * + * @var array + * @since 3.3 + */ + protected $_jsonEncode = array('params', 'metadata'); + + /** + * Constructor + * + * @param object Database connector object + */ + function __construct(&$db) + { + parent::__construct('#__getbible_open_ai_response', 'id', $db); + + // Adding History Options + JTableObserverContenthistory::createObserver($this, array('typeAlias' => 'com_getbible.open_ai_response')); + } + + public function bind($array, $ignore = '') + { + + if (isset($array['params']) && is_array($array['params'])) + { + $registry = new JRegistry; + $registry->loadArray($array['params']); + $array['params'] = (string) $registry; + } + + if (isset($array['metadata']) && is_array($array['metadata'])) + { + $registry = new JRegistry; + $registry->loadArray($array['metadata']); + $array['metadata'] = (string) $registry; + } + + // Bind the rules. + if (isset($array['rules']) && is_array($array['rules'])) + { + $rules = new JAccessRules($array['rules']); + $this->setRules($rules); + } + return parent::bind($array, $ignore); + } + + /** + * Overload the store method for the Open_ai_response table. + * + * @param boolean Toggle whether null values should be updated. + * @return boolean True on success, false on failure. + * @since 1.6 + */ + public function store($updateNulls = false) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if ($this->id) + { + // Existing item + $this->modified = $date->toSql(); + $this->modified_by = $user->get('id'); + } + else + { + // New open_ai_response. A open_ai_response created and created_by field can be set by the user, + // so we don't touch either of these if they are set. + if (!(int) $this->created) + { + $this->created = $date->toSql(); + } + if (empty($this->created_by)) + { + $this->created_by = $user->get('id'); + } + } + + if (isset($this->alias)) + { + // Verify that the alias is unique + $table = JTable::getInstance('open_ai_response', 'GetbibleTable'); + + if ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->setError(JText::_('COM_GETBIBLE_OPEN_AI_RESPONSE_ERROR_UNIQUE_ALIAS')); + return false; + } + } + + if (isset($this->url)) + { + // Convert IDN urls to punycode + $this->url = JStringPunycode::urlToPunycode($this->url); + } + if (isset($this->website)) + { + // Convert IDN urls to punycode + $this->website = JStringPunycode::urlToPunycode($this->website); + } + + return parent::store($updateNulls); + } + + /** + * Overloaded check method to ensure data integrity. + * + * @return boolean True on success. + */ + public function check() + { + if (isset($this->alias)) + { + // Generate a valid alias + $this->generateAlias(); + + $table = JTable::getInstance('open_ai_response', 'getbibleTable'); + + while ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->alias = StringHelper::increment($this->alias, 'dash'); + } + } + + /* + * Clean up keywords -- eliminate extra spaces between phrases + * and cr (\r) and lf (\n) characters from string. + * Only process if not empty. + */ + if (!empty($this->metakey)) + { + // Array of characters to remove. + $bad_characters = array("\n", "\r", "\"", "<", ">"); + + // Remove bad characters. + $after_clean = StringHelper::str_ireplace($bad_characters, "", $this->metakey); + + // Create array using commas as delimiter. + $keys = explode(',', $after_clean); + $clean_keys = array(); + + foreach ($keys as $key) + { + // Ignore blank keywords. + if (trim($key)) + { + $clean_keys[] = trim($key); + } + } + + // Put array back together delimited by ", " + $this->metakey = implode(", ", $clean_keys); + } + + // Clean up description -- eliminate quotes and <> brackets + if (!empty($this->metadesc)) + { + // Only process if not empty + $bad_characters = array("\"", "<", ">"); + $this->metadesc = StringHelper::str_ireplace($bad_characters, "", $this->metadesc); + } + + // If we don't have any access rules set at this point just use an empty JAccessRules class + if (!$this->getRules()) + { + $rules = $this->getDefaultAssetValues('com_getbible.open_ai_response.'.$this->id); + $this->setRules($rules); + } + + // Set ordering + if ($this->published < 0) + { + // Set ordering to 0 if state is archived or trashed + $this->ordering = 0; + } + + return true; + } + + /** + * Gets the default asset values for a component. + * + * @param $string $component The component asset name to search for + * + * @return JAccessRules The JAccessRules object for the asset + */ + protected function getDefaultAssetValues($component, $try = true) + { + // Need to find the asset id by the name of the component. + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select($db->quoteName('id')) + ->from($db->quoteName('#__assets')) + ->where($db->quoteName('name') . ' = ' . $db->quote($component)); + $db->setQuery($query); + $db->execute(); + if ($db->loadRowList()) + { + // asset already set so use saved rules + $assetId = (int) $db->loadResult(); + return JAccess::getAssetRules($assetId); // (TODO) instead of keeping inherited Allowed it becomes Allowed. + } + // try again + elseif ($try) + { + $try = explode('.',$component); + $result = $this->getDefaultAssetValues($try[0], false); + if ($result instanceof JAccessRules) + { + if (isset($try[1])) + { + $_result = (string) $result; + $_result = json_decode($_result); + foreach ($_result as $name => &$rule) + { + $v = explode('.', $name); + if ($try[1] !== $v[0]) + { + // remove since it is not part of this view + unset($_result->$name); + } + else + { + // clear the value since we inherit + $rule = array(); + } + } + // check if there are any view values remaining + if (count( (array) $_result)) + { + $_result = json_encode($_result); + $_result = array($_result); + // Instantiate and return the JAccessRules object for the asset rules. + $rules = new JAccessRules; + $rules->mergeCollection($_result); + + return $rules; + } + } + return $result; + } + } + return JAccess::getAssetRules(0); + } + + /** + * Method to compute the default name of the asset. + * The default name is in the form 'table_name.id' + * where id is the value of the primary key of the table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetName() + { + $k = $this->_tbl_key; + return 'com_getbible.open_ai_response.'.(int) $this->$k; + } + + /** + * Method to return the title to use for the asset table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetTitle() + { + if (isset($this->title)) + { + return $this->title; + } + return ''; + } + + /** + * Get the parent asset id for the record + * + * @return int + * @since 2.5 + */ + protected function _getAssetParentId(JTable $table = NULL, $id = NULL) + { + $asset = JTable::getInstance('Asset'); + $asset->loadByName('com_getbible'); + + return $asset->id; + } + + /** + * This view does not actually have an alias + * + * @return bool + */ + public function generateAlias() + { + return false; + } + +} diff --git a/admin/tables/password.php b/admin/tables/password.php new file mode 100644 index 0000000..1fe8aed --- /dev/null +++ b/admin/tables/password.php @@ -0,0 +1,327 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Table\Table; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; + +/** + * Passwords Table class + */ +class GetbibleTablePassword extends Table +{ + /** + * Ensure the params and metadata in json encoded in the bind method + * + * @var array + * @since 3.3 + */ + protected $_jsonEncode = array('params', 'metadata'); + + /** + * Constructor + * + * @param object Database connector object + */ + function __construct(&$db) + { + parent::__construct('#__getbible_password', 'id', $db); + } + + public function bind($array, $ignore = '') + { + + if (isset($array['params']) && is_array($array['params'])) + { + $registry = new JRegistry; + $registry->loadArray($array['params']); + $array['params'] = (string) $registry; + } + + if (isset($array['metadata']) && is_array($array['metadata'])) + { + $registry = new JRegistry; + $registry->loadArray($array['metadata']); + $array['metadata'] = (string) $registry; + } + + // Bind the rules. + if (isset($array['rules']) && is_array($array['rules'])) + { + $rules = new JAccessRules($array['rules']); + $this->setRules($rules); + } + return parent::bind($array, $ignore); + } + + /** + * Overload the store method for the Password table. + * + * @param boolean Toggle whether null values should be updated. + * @return boolean True on success, false on failure. + * @since 1.6 + */ + public function store($updateNulls = false) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if ($this->id) + { + // Existing item + $this->modified = $date->toSql(); + $this->modified_by = $user->get('id'); + } + else + { + // New password. A password created and created_by field can be set by the user, + // so we don't touch either of these if they are set. + if (!(int) $this->created) + { + $this->created = $date->toSql(); + } + if (empty($this->created_by)) + { + $this->created_by = $user->get('id'); + } + } + + if (isset($this->alias)) + { + // Verify that the alias is unique + $table = JTable::getInstance('password', 'GetbibleTable'); + + if ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->setError(JText::_('COM_GETBIBLE_PASSWORD_ERROR_UNIQUE_ALIAS')); + return false; + } + } + + if (isset($this->url)) + { + // Convert IDN urls to punycode + $this->url = JStringPunycode::urlToPunycode($this->url); + } + if (isset($this->website)) + { + // Convert IDN urls to punycode + $this->website = JStringPunycode::urlToPunycode($this->website); + } + + return parent::store($updateNulls); + } + + /** + * Overloaded check method to ensure data integrity. + * + * @return boolean True on success. + */ + public function check() + { + if (isset($this->alias)) + { + // Generate a valid alias + $this->generateAlias(); + + $table = JTable::getInstance('password', 'getbibleTable'); + + while ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->alias = StringHelper::increment($this->alias, 'dash'); + } + } + + /* + * Clean up keywords -- eliminate extra spaces between phrases + * and cr (\r) and lf (\n) characters from string. + * Only process if not empty. + */ + if (!empty($this->metakey)) + { + // Array of characters to remove. + $bad_characters = array("\n", "\r", "\"", "<", ">"); + + // Remove bad characters. + $after_clean = StringHelper::str_ireplace($bad_characters, "", $this->metakey); + + // Create array using commas as delimiter. + $keys = explode(',', $after_clean); + $clean_keys = array(); + + foreach ($keys as $key) + { + // Ignore blank keywords. + if (trim($key)) + { + $clean_keys[] = trim($key); + } + } + + // Put array back together delimited by ", " + $this->metakey = implode(", ", $clean_keys); + } + + // Clean up description -- eliminate quotes and <> brackets + if (!empty($this->metadesc)) + { + // Only process if not empty + $bad_characters = array("\"", "<", ">"); + $this->metadesc = StringHelper::str_ireplace($bad_characters, "", $this->metadesc); + } + + // If we don't have any access rules set at this point just use an empty JAccessRules class + if (!$this->getRules()) + { + $rules = $this->getDefaultAssetValues('com_getbible.password.'.$this->id); + $this->setRules($rules); + } + + // Set ordering + if ($this->published < 0) + { + // Set ordering to 0 if state is archived or trashed + $this->ordering = 0; + } + + return true; + } + + /** + * Gets the default asset values for a component. + * + * @param $string $component The component asset name to search for + * + * @return JAccessRules The JAccessRules object for the asset + */ + protected function getDefaultAssetValues($component, $try = true) + { + // Need to find the asset id by the name of the component. + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select($db->quoteName('id')) + ->from($db->quoteName('#__assets')) + ->where($db->quoteName('name') . ' = ' . $db->quote($component)); + $db->setQuery($query); + $db->execute(); + if ($db->loadRowList()) + { + // asset already set so use saved rules + $assetId = (int) $db->loadResult(); + return JAccess::getAssetRules($assetId); // (TODO) instead of keeping inherited Allowed it becomes Allowed. + } + // try again + elseif ($try) + { + $try = explode('.',$component); + $result = $this->getDefaultAssetValues($try[0], false); + if ($result instanceof JAccessRules) + { + if (isset($try[1])) + { + $_result = (string) $result; + $_result = json_decode($_result); + foreach ($_result as $name => &$rule) + { + $v = explode('.', $name); + if ($try[1] !== $v[0]) + { + // remove since it is not part of this view + unset($_result->$name); + } + else + { + // clear the value since we inherit + $rule = array(); + } + } + // check if there are any view values remaining + if (count( (array) $_result)) + { + $_result = json_encode($_result); + $_result = array($_result); + // Instantiate and return the JAccessRules object for the asset rules. + $rules = new JAccessRules; + $rules->mergeCollection($_result); + + return $rules; + } + } + return $result; + } + } + return JAccess::getAssetRules(0); + } + + /** + * Method to compute the default name of the asset. + * The default name is in the form 'table_name.id' + * where id is the value of the primary key of the table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetName() + { + $k = $this->_tbl_key; + return 'com_getbible.password.'.(int) $this->$k; + } + + /** + * Method to return the title to use for the asset table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetTitle() + { + if (isset($this->title)) + { + return $this->title; + } + return ''; + } + + /** + * Get the parent asset id for the record + * + * @return int + * @since 2.5 + */ + protected function _getAssetParentId(JTable $table = NULL, $id = NULL) + { + $asset = JTable::getInstance('Asset'); + $asset->loadByName('com_getbible'); + + return $asset->id; + } + + /** + * This view does not actually have an alias + * + * @return bool + */ + public function generateAlias() + { + return false; + } + +} diff --git a/admin/tables/prompt.php b/admin/tables/prompt.php new file mode 100644 index 0000000..c1ee6ed --- /dev/null +++ b/admin/tables/prompt.php @@ -0,0 +1,330 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Table\Table; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; + +/** + * Prompts Table class + */ +class GetbibleTablePrompt extends Table +{ + /** + * Ensure the params and metadata in json encoded in the bind method + * + * @var array + * @since 3.3 + */ + protected $_jsonEncode = array('params', 'metadata'); + + /** + * Constructor + * + * @param object Database connector object + */ + function __construct(&$db) + { + parent::__construct('#__getbible_prompt', 'id', $db); + + // Adding History Options + JTableObserverContenthistory::createObserver($this, array('typeAlias' => 'com_getbible.prompt')); + } + + public function bind($array, $ignore = '') + { + + if (isset($array['params']) && is_array($array['params'])) + { + $registry = new JRegistry; + $registry->loadArray($array['params']); + $array['params'] = (string) $registry; + } + + if (isset($array['metadata']) && is_array($array['metadata'])) + { + $registry = new JRegistry; + $registry->loadArray($array['metadata']); + $array['metadata'] = (string) $registry; + } + + // Bind the rules. + if (isset($array['rules']) && is_array($array['rules'])) + { + $rules = new JAccessRules($array['rules']); + $this->setRules($rules); + } + return parent::bind($array, $ignore); + } + + /** + * Overload the store method for the Prompt table. + * + * @param boolean Toggle whether null values should be updated. + * @return boolean True on success, false on failure. + * @since 1.6 + */ + public function store($updateNulls = false) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if ($this->id) + { + // Existing item + $this->modified = $date->toSql(); + $this->modified_by = $user->get('id'); + } + else + { + // New prompt. A prompt created and created_by field can be set by the user, + // so we don't touch either of these if they are set. + if (!(int) $this->created) + { + $this->created = $date->toSql(); + } + if (empty($this->created_by)) + { + $this->created_by = $user->get('id'); + } + } + + if (isset($this->alias)) + { + // Verify that the alias is unique + $table = JTable::getInstance('prompt', 'GetbibleTable'); + + if ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->setError(JText::_('COM_GETBIBLE_PROMPT_ERROR_UNIQUE_ALIAS')); + return false; + } + } + + if (isset($this->url)) + { + // Convert IDN urls to punycode + $this->url = JStringPunycode::urlToPunycode($this->url); + } + if (isset($this->website)) + { + // Convert IDN urls to punycode + $this->website = JStringPunycode::urlToPunycode($this->website); + } + + return parent::store($updateNulls); + } + + /** + * Overloaded check method to ensure data integrity. + * + * @return boolean True on success. + */ + public function check() + { + if (isset($this->alias)) + { + // Generate a valid alias + $this->generateAlias(); + + $table = JTable::getInstance('prompt', 'getbibleTable'); + + while ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->alias = StringHelper::increment($this->alias, 'dash'); + } + } + + /* + * Clean up keywords -- eliminate extra spaces between phrases + * and cr (\r) and lf (\n) characters from string. + * Only process if not empty. + */ + if (!empty($this->metakey)) + { + // Array of characters to remove. + $bad_characters = array("\n", "\r", "\"", "<", ">"); + + // Remove bad characters. + $after_clean = StringHelper::str_ireplace($bad_characters, "", $this->metakey); + + // Create array using commas as delimiter. + $keys = explode(',', $after_clean); + $clean_keys = array(); + + foreach ($keys as $key) + { + // Ignore blank keywords. + if (trim($key)) + { + $clean_keys[] = trim($key); + } + } + + // Put array back together delimited by ", " + $this->metakey = implode(", ", $clean_keys); + } + + // Clean up description -- eliminate quotes and <> brackets + if (!empty($this->metadesc)) + { + // Only process if not empty + $bad_characters = array("\"", "<", ">"); + $this->metadesc = StringHelper::str_ireplace($bad_characters, "", $this->metadesc); + } + + // If we don't have any access rules set at this point just use an empty JAccessRules class + if (!$this->getRules()) + { + $rules = $this->getDefaultAssetValues('com_getbible.prompt.'.$this->id); + $this->setRules($rules); + } + + // Set ordering + if ($this->published < 0) + { + // Set ordering to 0 if state is archived or trashed + $this->ordering = 0; + } + + return true; + } + + /** + * Gets the default asset values for a component. + * + * @param $string $component The component asset name to search for + * + * @return JAccessRules The JAccessRules object for the asset + */ + protected function getDefaultAssetValues($component, $try = true) + { + // Need to find the asset id by the name of the component. + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select($db->quoteName('id')) + ->from($db->quoteName('#__assets')) + ->where($db->quoteName('name') . ' = ' . $db->quote($component)); + $db->setQuery($query); + $db->execute(); + if ($db->loadRowList()) + { + // asset already set so use saved rules + $assetId = (int) $db->loadResult(); + return JAccess::getAssetRules($assetId); // (TODO) instead of keeping inherited Allowed it becomes Allowed. + } + // try again + elseif ($try) + { + $try = explode('.',$component); + $result = $this->getDefaultAssetValues($try[0], false); + if ($result instanceof JAccessRules) + { + if (isset($try[1])) + { + $_result = (string) $result; + $_result = json_decode($_result); + foreach ($_result as $name => &$rule) + { + $v = explode('.', $name); + if ($try[1] !== $v[0]) + { + // remove since it is not part of this view + unset($_result->$name); + } + else + { + // clear the value since we inherit + $rule = array(); + } + } + // check if there are any view values remaining + if (count( (array) $_result)) + { + $_result = json_encode($_result); + $_result = array($_result); + // Instantiate and return the JAccessRules object for the asset rules. + $rules = new JAccessRules; + $rules->mergeCollection($_result); + + return $rules; + } + } + return $result; + } + } + return JAccess::getAssetRules(0); + } + + /** + * Method to compute the default name of the asset. + * The default name is in the form 'table_name.id' + * where id is the value of the primary key of the table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetName() + { + $k = $this->_tbl_key; + return 'com_getbible.prompt.'.(int) $this->$k; + } + + /** + * Method to return the title to use for the asset table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetTitle() + { + if (isset($this->title)) + { + return $this->title; + } + return ''; + } + + /** + * Get the parent asset id for the record + * + * @return int + * @since 2.5 + */ + protected function _getAssetParentId(JTable $table = NULL, $id = NULL) + { + $asset = JTable::getInstance('Asset'); + $asset->loadByName('com_getbible'); + + return $asset->id; + } + + /** + * This view does not actually have an alias + * + * @return bool + */ + public function generateAlias() + { + return false; + } + +} diff --git a/admin/tables/tag.php b/admin/tables/tag.php new file mode 100644 index 0000000..65617a0 --- /dev/null +++ b/admin/tables/tag.php @@ -0,0 +1,330 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Table\Table; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; + +/** + * Tags Table class + */ +class GetbibleTableTag extends Table +{ + /** + * Ensure the params and metadata in json encoded in the bind method + * + * @var array + * @since 3.3 + */ + protected $_jsonEncode = array('params', 'metadata'); + + /** + * Constructor + * + * @param object Database connector object + */ + function __construct(&$db) + { + parent::__construct('#__getbible_tag', 'id', $db); + + // Adding History Options + JTableObserverContenthistory::createObserver($this, array('typeAlias' => 'com_getbible.tag')); + } + + public function bind($array, $ignore = '') + { + + if (isset($array['params']) && is_array($array['params'])) + { + $registry = new JRegistry; + $registry->loadArray($array['params']); + $array['params'] = (string) $registry; + } + + if (isset($array['metadata']) && is_array($array['metadata'])) + { + $registry = new JRegistry; + $registry->loadArray($array['metadata']); + $array['metadata'] = (string) $registry; + } + + // Bind the rules. + if (isset($array['rules']) && is_array($array['rules'])) + { + $rules = new JAccessRules($array['rules']); + $this->setRules($rules); + } + return parent::bind($array, $ignore); + } + + /** + * Overload the store method for the Tag table. + * + * @param boolean Toggle whether null values should be updated. + * @return boolean True on success, false on failure. + * @since 1.6 + */ + public function store($updateNulls = false) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if ($this->id) + { + // Existing item + $this->modified = $date->toSql(); + $this->modified_by = $user->get('id'); + } + else + { + // New tag. A tag created and created_by field can be set by the user, + // so we don't touch either of these if they are set. + if (!(int) $this->created) + { + $this->created = $date->toSql(); + } + if (empty($this->created_by)) + { + $this->created_by = $user->get('id'); + } + } + + if (isset($this->alias)) + { + // Verify that the alias is unique + $table = JTable::getInstance('tag', 'GetbibleTable'); + + if ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->setError(JText::_('COM_GETBIBLE_TAG_ERROR_UNIQUE_ALIAS')); + return false; + } + } + + if (isset($this->url)) + { + // Convert IDN urls to punycode + $this->url = JStringPunycode::urlToPunycode($this->url); + } + if (isset($this->website)) + { + // Convert IDN urls to punycode + $this->website = JStringPunycode::urlToPunycode($this->website); + } + + return parent::store($updateNulls); + } + + /** + * Overloaded check method to ensure data integrity. + * + * @return boolean True on success. + */ + public function check() + { + if (isset($this->alias)) + { + // Generate a valid alias + $this->generateAlias(); + + $table = JTable::getInstance('tag', 'getbibleTable'); + + while ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->alias = StringHelper::increment($this->alias, 'dash'); + } + } + + /* + * Clean up keywords -- eliminate extra spaces between phrases + * and cr (\r) and lf (\n) characters from string. + * Only process if not empty. + */ + if (!empty($this->metakey)) + { + // Array of characters to remove. + $bad_characters = array("\n", "\r", "\"", "<", ">"); + + // Remove bad characters. + $after_clean = StringHelper::str_ireplace($bad_characters, "", $this->metakey); + + // Create array using commas as delimiter. + $keys = explode(',', $after_clean); + $clean_keys = array(); + + foreach ($keys as $key) + { + // Ignore blank keywords. + if (trim($key)) + { + $clean_keys[] = trim($key); + } + } + + // Put array back together delimited by ", " + $this->metakey = implode(", ", $clean_keys); + } + + // Clean up description -- eliminate quotes and <> brackets + if (!empty($this->metadesc)) + { + // Only process if not empty + $bad_characters = array("\"", "<", ">"); + $this->metadesc = StringHelper::str_ireplace($bad_characters, "", $this->metadesc); + } + + // If we don't have any access rules set at this point just use an empty JAccessRules class + if (!$this->getRules()) + { + $rules = $this->getDefaultAssetValues('com_getbible.tag.'.$this->id); + $this->setRules($rules); + } + + // Set ordering + if ($this->published < 0) + { + // Set ordering to 0 if state is archived or trashed + $this->ordering = 0; + } + + return true; + } + + /** + * Gets the default asset values for a component. + * + * @param $string $component The component asset name to search for + * + * @return JAccessRules The JAccessRules object for the asset + */ + protected function getDefaultAssetValues($component, $try = true) + { + // Need to find the asset id by the name of the component. + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select($db->quoteName('id')) + ->from($db->quoteName('#__assets')) + ->where($db->quoteName('name') . ' = ' . $db->quote($component)); + $db->setQuery($query); + $db->execute(); + if ($db->loadRowList()) + { + // asset already set so use saved rules + $assetId = (int) $db->loadResult(); + return JAccess::getAssetRules($assetId); // (TODO) instead of keeping inherited Allowed it becomes Allowed. + } + // try again + elseif ($try) + { + $try = explode('.',$component); + $result = $this->getDefaultAssetValues($try[0], false); + if ($result instanceof JAccessRules) + { + if (isset($try[1])) + { + $_result = (string) $result; + $_result = json_decode($_result); + foreach ($_result as $name => &$rule) + { + $v = explode('.', $name); + if ($try[1] !== $v[0]) + { + // remove since it is not part of this view + unset($_result->$name); + } + else + { + // clear the value since we inherit + $rule = array(); + } + } + // check if there are any view values remaining + if (count( (array) $_result)) + { + $_result = json_encode($_result); + $_result = array($_result); + // Instantiate and return the JAccessRules object for the asset rules. + $rules = new JAccessRules; + $rules->mergeCollection($_result); + + return $rules; + } + } + return $result; + } + } + return JAccess::getAssetRules(0); + } + + /** + * Method to compute the default name of the asset. + * The default name is in the form 'table_name.id' + * where id is the value of the primary key of the table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetName() + { + $k = $this->_tbl_key; + return 'com_getbible.tag.'.(int) $this->$k; + } + + /** + * Method to return the title to use for the asset table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetTitle() + { + if (isset($this->title)) + { + return $this->title; + } + return ''; + } + + /** + * Get the parent asset id for the record + * + * @return int + * @since 2.5 + */ + protected function _getAssetParentId(JTable $table = NULL, $id = NULL) + { + $asset = JTable::getInstance('Asset'); + $asset->loadByName('com_getbible'); + + return $asset->id; + } + + /** + * This view does not actually have an alias + * + * @return bool + */ + public function generateAlias() + { + return false; + } + +} diff --git a/admin/tables/tagged_verse.php b/admin/tables/tagged_verse.php new file mode 100644 index 0000000..5208774 --- /dev/null +++ b/admin/tables/tagged_verse.php @@ -0,0 +1,330 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Table\Table; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; + +/** + * Tagged_verses Table class + */ +class GetbibleTableTagged_verse extends Table +{ + /** + * Ensure the params and metadata in json encoded in the bind method + * + * @var array + * @since 3.3 + */ + protected $_jsonEncode = array('params', 'metadata'); + + /** + * Constructor + * + * @param object Database connector object + */ + function __construct(&$db) + { + parent::__construct('#__getbible_tagged_verse', 'id', $db); + + // Adding History Options + JTableObserverContenthistory::createObserver($this, array('typeAlias' => 'com_getbible.tagged_verse')); + } + + public function bind($array, $ignore = '') + { + + if (isset($array['params']) && is_array($array['params'])) + { + $registry = new JRegistry; + $registry->loadArray($array['params']); + $array['params'] = (string) $registry; + } + + if (isset($array['metadata']) && is_array($array['metadata'])) + { + $registry = new JRegistry; + $registry->loadArray($array['metadata']); + $array['metadata'] = (string) $registry; + } + + // Bind the rules. + if (isset($array['rules']) && is_array($array['rules'])) + { + $rules = new JAccessRules($array['rules']); + $this->setRules($rules); + } + return parent::bind($array, $ignore); + } + + /** + * Overload the store method for the Tagged_verse table. + * + * @param boolean Toggle whether null values should be updated. + * @return boolean True on success, false on failure. + * @since 1.6 + */ + public function store($updateNulls = false) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if ($this->id) + { + // Existing item + $this->modified = $date->toSql(); + $this->modified_by = $user->get('id'); + } + else + { + // New tagged_verse. A tagged_verse created and created_by field can be set by the user, + // so we don't touch either of these if they are set. + if (!(int) $this->created) + { + $this->created = $date->toSql(); + } + if (empty($this->created_by)) + { + $this->created_by = $user->get('id'); + } + } + + if (isset($this->alias)) + { + // Verify that the alias is unique + $table = JTable::getInstance('tagged_verse', 'GetbibleTable'); + + if ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->setError(JText::_('COM_GETBIBLE_TAGGED_VERSE_ERROR_UNIQUE_ALIAS')); + return false; + } + } + + if (isset($this->url)) + { + // Convert IDN urls to punycode + $this->url = JStringPunycode::urlToPunycode($this->url); + } + if (isset($this->website)) + { + // Convert IDN urls to punycode + $this->website = JStringPunycode::urlToPunycode($this->website); + } + + return parent::store($updateNulls); + } + + /** + * Overloaded check method to ensure data integrity. + * + * @return boolean True on success. + */ + public function check() + { + if (isset($this->alias)) + { + // Generate a valid alias + $this->generateAlias(); + + $table = JTable::getInstance('tagged_verse', 'getbibleTable'); + + while ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->alias = StringHelper::increment($this->alias, 'dash'); + } + } + + /* + * Clean up keywords -- eliminate extra spaces between phrases + * and cr (\r) and lf (\n) characters from string. + * Only process if not empty. + */ + if (!empty($this->metakey)) + { + // Array of characters to remove. + $bad_characters = array("\n", "\r", "\"", "<", ">"); + + // Remove bad characters. + $after_clean = StringHelper::str_ireplace($bad_characters, "", $this->metakey); + + // Create array using commas as delimiter. + $keys = explode(',', $after_clean); + $clean_keys = array(); + + foreach ($keys as $key) + { + // Ignore blank keywords. + if (trim($key)) + { + $clean_keys[] = trim($key); + } + } + + // Put array back together delimited by ", " + $this->metakey = implode(", ", $clean_keys); + } + + // Clean up description -- eliminate quotes and <> brackets + if (!empty($this->metadesc)) + { + // Only process if not empty + $bad_characters = array("\"", "<", ">"); + $this->metadesc = StringHelper::str_ireplace($bad_characters, "", $this->metadesc); + } + + // If we don't have any access rules set at this point just use an empty JAccessRules class + if (!$this->getRules()) + { + $rules = $this->getDefaultAssetValues('com_getbible.tagged_verse.'.$this->id); + $this->setRules($rules); + } + + // Set ordering + if ($this->published < 0) + { + // Set ordering to 0 if state is archived or trashed + $this->ordering = 0; + } + + return true; + } + + /** + * Gets the default asset values for a component. + * + * @param $string $component The component asset name to search for + * + * @return JAccessRules The JAccessRules object for the asset + */ + protected function getDefaultAssetValues($component, $try = true) + { + // Need to find the asset id by the name of the component. + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select($db->quoteName('id')) + ->from($db->quoteName('#__assets')) + ->where($db->quoteName('name') . ' = ' . $db->quote($component)); + $db->setQuery($query); + $db->execute(); + if ($db->loadRowList()) + { + // asset already set so use saved rules + $assetId = (int) $db->loadResult(); + return JAccess::getAssetRules($assetId); // (TODO) instead of keeping inherited Allowed it becomes Allowed. + } + // try again + elseif ($try) + { + $try = explode('.',$component); + $result = $this->getDefaultAssetValues($try[0], false); + if ($result instanceof JAccessRules) + { + if (isset($try[1])) + { + $_result = (string) $result; + $_result = json_decode($_result); + foreach ($_result as $name => &$rule) + { + $v = explode('.', $name); + if ($try[1] !== $v[0]) + { + // remove since it is not part of this view + unset($_result->$name); + } + else + { + // clear the value since we inherit + $rule = array(); + } + } + // check if there are any view values remaining + if (count( (array) $_result)) + { + $_result = json_encode($_result); + $_result = array($_result); + // Instantiate and return the JAccessRules object for the asset rules. + $rules = new JAccessRules; + $rules->mergeCollection($_result); + + return $rules; + } + } + return $result; + } + } + return JAccess::getAssetRules(0); + } + + /** + * Method to compute the default name of the asset. + * The default name is in the form 'table_name.id' + * where id is the value of the primary key of the table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetName() + { + $k = $this->_tbl_key; + return 'com_getbible.tagged_verse.'.(int) $this->$k; + } + + /** + * Method to return the title to use for the asset table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetTitle() + { + if (isset($this->title)) + { + return $this->title; + } + return ''; + } + + /** + * Get the parent asset id for the record + * + * @return int + * @since 2.5 + */ + protected function _getAssetParentId(JTable $table = NULL, $id = NULL) + { + $asset = JTable::getInstance('Asset'); + $asset->loadByName('com_getbible'); + + return $asset->id; + } + + /** + * This view does not actually have an alias + * + * @return bool + */ + public function generateAlias() + { + return false; + } + +} diff --git a/admin/tables/translation.php b/admin/tables/translation.php new file mode 100644 index 0000000..6113407 --- /dev/null +++ b/admin/tables/translation.php @@ -0,0 +1,327 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Table\Table; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; + +/** + * Translations Table class + */ +class GetbibleTableTranslation extends Table +{ + /** + * Ensure the params and metadata in json encoded in the bind method + * + * @var array + * @since 3.3 + */ + protected $_jsonEncode = array('params', 'metadata'); + + /** + * Constructor + * + * @param object Database connector object + */ + function __construct(&$db) + { + parent::__construct('#__getbible_translation', 'id', $db); + } + + public function bind($array, $ignore = '') + { + + if (isset($array['params']) && is_array($array['params'])) + { + $registry = new JRegistry; + $registry->loadArray($array['params']); + $array['params'] = (string) $registry; + } + + if (isset($array['metadata']) && is_array($array['metadata'])) + { + $registry = new JRegistry; + $registry->loadArray($array['metadata']); + $array['metadata'] = (string) $registry; + } + + // Bind the rules. + if (isset($array['rules']) && is_array($array['rules'])) + { + $rules = new JAccessRules($array['rules']); + $this->setRules($rules); + } + return parent::bind($array, $ignore); + } + + /** + * Overload the store method for the Translation table. + * + * @param boolean Toggle whether null values should be updated. + * @return boolean True on success, false on failure. + * @since 1.6 + */ + public function store($updateNulls = false) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if ($this->id) + { + // Existing item + $this->modified = $date->toSql(); + $this->modified_by = $user->get('id'); + } + else + { + // New translation. A translation created and created_by field can be set by the user, + // so we don't touch either of these if they are set. + if (!(int) $this->created) + { + $this->created = $date->toSql(); + } + if (empty($this->created_by)) + { + $this->created_by = $user->get('id'); + } + } + + if (isset($this->alias)) + { + // Verify that the alias is unique + $table = JTable::getInstance('translation', 'GetbibleTable'); + + if ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->setError(JText::_('COM_GETBIBLE_TRANSLATION_ERROR_UNIQUE_ALIAS')); + return false; + } + } + + if (isset($this->url)) + { + // Convert IDN urls to punycode + $this->url = JStringPunycode::urlToPunycode($this->url); + } + if (isset($this->website)) + { + // Convert IDN urls to punycode + $this->website = JStringPunycode::urlToPunycode($this->website); + } + + return parent::store($updateNulls); + } + + /** + * Overloaded check method to ensure data integrity. + * + * @return boolean True on success. + */ + public function check() + { + if (isset($this->alias)) + { + // Generate a valid alias + $this->generateAlias(); + + $table = JTable::getInstance('translation', 'getbibleTable'); + + while ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->alias = StringHelper::increment($this->alias, 'dash'); + } + } + + /* + * Clean up keywords -- eliminate extra spaces between phrases + * and cr (\r) and lf (\n) characters from string. + * Only process if not empty. + */ + if (!empty($this->metakey)) + { + // Array of characters to remove. + $bad_characters = array("\n", "\r", "\"", "<", ">"); + + // Remove bad characters. + $after_clean = StringHelper::str_ireplace($bad_characters, "", $this->metakey); + + // Create array using commas as delimiter. + $keys = explode(',', $after_clean); + $clean_keys = array(); + + foreach ($keys as $key) + { + // Ignore blank keywords. + if (trim($key)) + { + $clean_keys[] = trim($key); + } + } + + // Put array back together delimited by ", " + $this->metakey = implode(", ", $clean_keys); + } + + // Clean up description -- eliminate quotes and <> brackets + if (!empty($this->metadesc)) + { + // Only process if not empty + $bad_characters = array("\"", "<", ">"); + $this->metadesc = StringHelper::str_ireplace($bad_characters, "", $this->metadesc); + } + + // If we don't have any access rules set at this point just use an empty JAccessRules class + if (!$this->getRules()) + { + $rules = $this->getDefaultAssetValues('com_getbible.translation.'.$this->id); + $this->setRules($rules); + } + + // Set ordering + if ($this->published < 0) + { + // Set ordering to 0 if state is archived or trashed + $this->ordering = 0; + } + + return true; + } + + /** + * Gets the default asset values for a component. + * + * @param $string $component The component asset name to search for + * + * @return JAccessRules The JAccessRules object for the asset + */ + protected function getDefaultAssetValues($component, $try = true) + { + // Need to find the asset id by the name of the component. + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select($db->quoteName('id')) + ->from($db->quoteName('#__assets')) + ->where($db->quoteName('name') . ' = ' . $db->quote($component)); + $db->setQuery($query); + $db->execute(); + if ($db->loadRowList()) + { + // asset already set so use saved rules + $assetId = (int) $db->loadResult(); + return JAccess::getAssetRules($assetId); // (TODO) instead of keeping inherited Allowed it becomes Allowed. + } + // try again + elseif ($try) + { + $try = explode('.',$component); + $result = $this->getDefaultAssetValues($try[0], false); + if ($result instanceof JAccessRules) + { + if (isset($try[1])) + { + $_result = (string) $result; + $_result = json_decode($_result); + foreach ($_result as $name => &$rule) + { + $v = explode('.', $name); + if ($try[1] !== $v[0]) + { + // remove since it is not part of this view + unset($_result->$name); + } + else + { + // clear the value since we inherit + $rule = array(); + } + } + // check if there are any view values remaining + if (count( (array) $_result)) + { + $_result = json_encode($_result); + $_result = array($_result); + // Instantiate and return the JAccessRules object for the asset rules. + $rules = new JAccessRules; + $rules->mergeCollection($_result); + + return $rules; + } + } + return $result; + } + } + return JAccess::getAssetRules(0); + } + + /** + * Method to compute the default name of the asset. + * The default name is in the form 'table_name.id' + * where id is the value of the primary key of the table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetName() + { + $k = $this->_tbl_key; + return 'com_getbible.translation.'.(int) $this->$k; + } + + /** + * Method to return the title to use for the asset table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetTitle() + { + if (isset($this->title)) + { + return $this->title; + } + return ''; + } + + /** + * Get the parent asset id for the record + * + * @return int + * @since 2.5 + */ + protected function _getAssetParentId(JTable $table = NULL, $id = NULL) + { + $asset = JTable::getInstance('Asset'); + $asset->loadByName('com_getbible'); + + return $asset->id; + } + + /** + * This view does not actually have an alias + * + * @return bool + */ + public function generateAlias() + { + return false; + } + +} diff --git a/admin/tables/verse.php b/admin/tables/verse.php new file mode 100644 index 0000000..5ca405b --- /dev/null +++ b/admin/tables/verse.php @@ -0,0 +1,327 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Table\Table; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; + +/** + * Verses Table class + */ +class GetbibleTableVerse extends Table +{ + /** + * Ensure the params and metadata in json encoded in the bind method + * + * @var array + * @since 3.3 + */ + protected $_jsonEncode = array('params', 'metadata'); + + /** + * Constructor + * + * @param object Database connector object + */ + function __construct(&$db) + { + parent::__construct('#__getbible_verse', 'id', $db); + } + + public function bind($array, $ignore = '') + { + + if (isset($array['params']) && is_array($array['params'])) + { + $registry = new JRegistry; + $registry->loadArray($array['params']); + $array['params'] = (string) $registry; + } + + if (isset($array['metadata']) && is_array($array['metadata'])) + { + $registry = new JRegistry; + $registry->loadArray($array['metadata']); + $array['metadata'] = (string) $registry; + } + + // Bind the rules. + if (isset($array['rules']) && is_array($array['rules'])) + { + $rules = new JAccessRules($array['rules']); + $this->setRules($rules); + } + return parent::bind($array, $ignore); + } + + /** + * Overload the store method for the Verse table. + * + * @param boolean Toggle whether null values should be updated. + * @return boolean True on success, false on failure. + * @since 1.6 + */ + public function store($updateNulls = false) + { + $date = JFactory::getDate(); + $user = JFactory::getUser(); + + if ($this->id) + { + // Existing item + $this->modified = $date->toSql(); + $this->modified_by = $user->get('id'); + } + else + { + // New verse. A verse created and created_by field can be set by the user, + // so we don't touch either of these if they are set. + if (!(int) $this->created) + { + $this->created = $date->toSql(); + } + if (empty($this->created_by)) + { + $this->created_by = $user->get('id'); + } + } + + if (isset($this->alias)) + { + // Verify that the alias is unique + $table = JTable::getInstance('verse', 'GetbibleTable'); + + if ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->setError(JText::_('COM_GETBIBLE_VERSE_ERROR_UNIQUE_ALIAS')); + return false; + } + } + + if (isset($this->url)) + { + // Convert IDN urls to punycode + $this->url = JStringPunycode::urlToPunycode($this->url); + } + if (isset($this->website)) + { + // Convert IDN urls to punycode + $this->website = JStringPunycode::urlToPunycode($this->website); + } + + return parent::store($updateNulls); + } + + /** + * Overloaded check method to ensure data integrity. + * + * @return boolean True on success. + */ + public function check() + { + if (isset($this->alias)) + { + // Generate a valid alias + $this->generateAlias(); + + $table = JTable::getInstance('verse', 'getbibleTable'); + + while ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->alias = StringHelper::increment($this->alias, 'dash'); + } + } + + /* + * Clean up keywords -- eliminate extra spaces between phrases + * and cr (\r) and lf (\n) characters from string. + * Only process if not empty. + */ + if (!empty($this->metakey)) + { + // Array of characters to remove. + $bad_characters = array("\n", "\r", "\"", "<", ">"); + + // Remove bad characters. + $after_clean = StringHelper::str_ireplace($bad_characters, "", $this->metakey); + + // Create array using commas as delimiter. + $keys = explode(',', $after_clean); + $clean_keys = array(); + + foreach ($keys as $key) + { + // Ignore blank keywords. + if (trim($key)) + { + $clean_keys[] = trim($key); + } + } + + // Put array back together delimited by ", " + $this->metakey = implode(", ", $clean_keys); + } + + // Clean up description -- eliminate quotes and <> brackets + if (!empty($this->metadesc)) + { + // Only process if not empty + $bad_characters = array("\"", "<", ">"); + $this->metadesc = StringHelper::str_ireplace($bad_characters, "", $this->metadesc); + } + + // If we don't have any access rules set at this point just use an empty JAccessRules class + if (!$this->getRules()) + { + $rules = $this->getDefaultAssetValues('com_getbible.verse.'.$this->id); + $this->setRules($rules); + } + + // Set ordering + if ($this->published < 0) + { + // Set ordering to 0 if state is archived or trashed + $this->ordering = 0; + } + + return true; + } + + /** + * Gets the default asset values for a component. + * + * @param $string $component The component asset name to search for + * + * @return JAccessRules The JAccessRules object for the asset + */ + protected function getDefaultAssetValues($component, $try = true) + { + // Need to find the asset id by the name of the component. + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select($db->quoteName('id')) + ->from($db->quoteName('#__assets')) + ->where($db->quoteName('name') . ' = ' . $db->quote($component)); + $db->setQuery($query); + $db->execute(); + if ($db->loadRowList()) + { + // asset already set so use saved rules + $assetId = (int) $db->loadResult(); + return JAccess::getAssetRules($assetId); // (TODO) instead of keeping inherited Allowed it becomes Allowed. + } + // try again + elseif ($try) + { + $try = explode('.',$component); + $result = $this->getDefaultAssetValues($try[0], false); + if ($result instanceof JAccessRules) + { + if (isset($try[1])) + { + $_result = (string) $result; + $_result = json_decode($_result); + foreach ($_result as $name => &$rule) + { + $v = explode('.', $name); + if ($try[1] !== $v[0]) + { + // remove since it is not part of this view + unset($_result->$name); + } + else + { + // clear the value since we inherit + $rule = array(); + } + } + // check if there are any view values remaining + if (count( (array) $_result)) + { + $_result = json_encode($_result); + $_result = array($_result); + // Instantiate and return the JAccessRules object for the asset rules. + $rules = new JAccessRules; + $rules->mergeCollection($_result); + + return $rules; + } + } + return $result; + } + } + return JAccess::getAssetRules(0); + } + + /** + * Method to compute the default name of the asset. + * The default name is in the form 'table_name.id' + * where id is the value of the primary key of the table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetName() + { + $k = $this->_tbl_key; + return 'com_getbible.verse.'.(int) $this->$k; + } + + /** + * Method to return the title to use for the asset table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetTitle() + { + if (isset($this->title)) + { + return $this->title; + } + return ''; + } + + /** + * Get the parent asset id for the record + * + * @return int + * @since 2.5 + */ + protected function _getAssetParentId(JTable $table = NULL, $id = NULL) + { + $asset = JTable::getInstance('Asset'); + $asset->loadByName('com_getbible'); + + return $asset->id; + } + + /** + * This view does not actually have an alias + * + * @return bool + */ + public function generateAlias() + { + return false; + } + +} diff --git a/admin/views/book/submitbutton.js b/admin/views/book/submitbutton.js new file mode 100644 index 0000000..e9bf89d --- /dev/null +++ b/admin/views/book/submitbutton.js @@ -0,0 +1,31 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +Joomla.submitbutton = function(task) +{ + if (task == ''){ + return false; + } else { + var action = task.split('.'); + if (action[1] == 'cancel' || action[1] == 'close' || document.formvalidator.isValid(document.getElementById("adminForm"))){ + Joomla.submitform(task, document.getElementById("adminForm")); + return true; + } else { + alert(Joomla.JText._('book, some values are not acceptable.','Some values are unacceptable')); + return false; + } + } +} \ No newline at end of file diff --git a/admin/views/book/tmpl/edit.php b/admin/views/book/tmpl/edit.php new file mode 100644 index 0000000..96da247 --- /dev/null +++ b/admin/views/book/tmpl/edit.php @@ -0,0 +1,112 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/html'); +JHtml::_('behavior.formvalidator'); +JHtml::_('formbehavior.chosen', 'select'); +JHtml::_('behavior.keepalive'); +$componentParams = $this->params; // will be removed just use $this->params instead +?> + + diff --git a/admin/views/book/tmpl/index.html b/admin/views/book/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/book/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/book/view.html.php b/admin/views/book/view.html.php new file mode 100644 index 0000000..7e5552e --- /dev/null +++ b/admin/views/book/view.html.php @@ -0,0 +1,130 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Book Html View class + */ +class GetbibleViewBook extends HtmlView +{ + /** + * display method of View + * @return void + */ + public function display($tpl = null) + { + // set params + $this->params = JComponentHelper::getParams('com_getbible'); + // Assign the variables + $this->form = $this->get('Form'); + $this->item = $this->get('Item'); + $this->script = $this->get('Script'); + $this->state = $this->get('State'); + // get action permissions + $this->canDo = GetbibleHelper::getActions('book', $this->item); + // get input + $jinput = JFactory::getApplication()->input; + $this->ref = $jinput->get('ref', 0, 'word'); + $this->refid = $jinput->get('refid', 0, 'int'); + $return = $jinput->get('return', null, 'base64'); + // set the referral string + $this->referral = ''; + if ($this->refid && $this->ref) + { + // return to the item that referred to this item + $this->referral = '&ref=' . (string)$this->ref . '&refid=' . (int)$this->refid; + } + elseif($this->ref) + { + // return to the list view that referred to this item + $this->referral = '&ref=' . (string)$this->ref; + } + // check return value + if (!is_null($return)) + { + // add the return value + $this->referral .= '&return=' . (string)$return; + } + + // Set the toolbar + $this->addToolBar(); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JFactory::getApplication()->input->set('hidemainmenu', true); + JToolBarHelper::title(JText::_('COM_GETBIBLE_BOOK_READONLY'), 'book'); + JToolBarHelper::cancel('book.cancel', 'JTOOLBAR_CLOSE'); + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 30) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true, 30); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + $isNew = ($this->item->id < 1); + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_($isNew ? 'COM_GETBIBLE_BOOK_NEW' : 'COM_GETBIBLE_BOOK_EDIT')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/book.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + $this->document->addScript(JURI::root() . $this->script, (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + $this->document->addScript(JURI::root() . "administrator/components/com_getbible/views/book/submitbutton.js", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + JText::script('view not acceptable. Error'); + } +} diff --git a/admin/views/books/index.html b/admin/views/books/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/books/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/books/tmpl/default.php b/admin/views/books/tmpl/default.php new file mode 100644 index 0000000..f52c2a0 --- /dev/null +++ b/admin/views/books/tmpl/default.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::_('behavior.multiselect'); +JHtml::_('dropdown.init'); +JHtml::_('formbehavior.chosen', '.multipleAccessLevels', null, array('placeholder_text_multiple' => '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_ACCESS') . ' -')); +JHtml::_('formbehavior.chosen', 'select'); +if ($this->saveOrder) +{ + $saveOrderingUrl = 'index.php?option=com_getbible&task=books.saveOrderAjax&tmpl=component'; + JHtml::_('sortablelist.sortable', 'bookList', 'adminForm', strtolower($this->listDirn), $saveOrderingUrl); +} +?> +
+sidebar)): ?> +
+ sidebar; ?> +
+
+ +
+ + $this)); +?> +items)): ?> +
+ +
+ + + loadTemplate('head');?> + loadTemplate('foot');?> + loadTemplate('body');?> +
+ + canCreate && $this->canEdit) : ?> + JText::_('COM_GETBIBLE_BOOKS_BATCH_OPTIONS'), + 'footer' => $this->loadTemplate('batch_footer') + ), + $this->loadTemplate('batch_body') + ); ?> + + +
+ + + + diff --git a/admin/views/books/tmpl/default_batch_body.php b/admin/views/books/tmpl/default_batch_body.php new file mode 100644 index 0000000..d6441cd --- /dev/null +++ b/admin/views/books/tmpl/default_batch_body.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + +

+batchDisplay; ?> \ No newline at end of file diff --git a/admin/views/books/tmpl/default_batch_footer.php b/admin/views/books/tmpl/default_batch_footer.php new file mode 100644 index 0000000..09516d7 --- /dev/null +++ b/admin/views/books/tmpl/default_batch_footer.php @@ -0,0 +1,29 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + + + \ No newline at end of file diff --git a/admin/views/books/tmpl/default_body.php b/admin/views/books/tmpl/default_body.php new file mode 100644 index 0000000..a74aa3d --- /dev/null +++ b/admin/views/books/tmpl/default_body.php @@ -0,0 +1,109 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +$edit = "index.php?option=com_getbible&view=books&task=book.edit"; + +?> +items as $i => $item): ?> + user->authorise('core.manage', 'com_checkin') || $item->checked_out == $this->user->id || $item->checked_out == 0; + $userChkOut = JFactory::getUser($item->checked_out); + $canDo = GetbibleHelper::getActions('book',$item,'books'); + ?> + + + get('book.edit.state')): ?> + saveOrder) + { + $iconClass = ' inactive tip-top" hasTooltip" title="' . JHtml::tooltipText('JORDERINGDISABLED'); + } + ?> + + + + saveOrder) : ?> + + + + ⋮ + + + + get('book.edit')): ?> + checked_out) : ?> + + id); ?> + + □ + + + id); ?> + + + □ + + + +
+ get('book.edit')): ?> + escape($item->name); ?> + checked_out): ?> + name, $item->checked_out_time, 'books.', $canCheckin); ?> + + + escape($item->name); ?> + +
+ + +
+ user->authorise('translation.edit', 'com_getbible.translation.' . (int) $item->abbreviation_id)): ?> + escape($item->abbreviation_translation); ?> + + escape($item->abbreviation_translation); ?> + +
+ + + escape($item->nr); ?> + + + get('book.edit.state')) : ?> + checked_out) : ?> + + published, $i, 'books.', true, 'cb'); ?> + + published, $i, 'books.', false, 'cb'); ?> + + + published, $i, 'books.', true, 'cb'); ?> + + + published, $i, 'books.', false, 'cb'); ?> + + + + id; ?> + + + \ No newline at end of file diff --git a/admin/views/books/tmpl/default_foot.php b/admin/views/books/tmpl/default_foot.php new file mode 100644 index 0000000..38a928f --- /dev/null +++ b/admin/views/books/tmpl/default_foot.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + pagination->getListFooter(); ?> + \ No newline at end of file diff --git a/admin/views/books/tmpl/default_head.php b/admin/views/books/tmpl/default_head.php new file mode 100644 index 0000000..c1309ee --- /dev/null +++ b/admin/views/books/tmpl/default_head.php @@ -0,0 +1,59 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + canEdit&& $this->canState): ?> + + listDirn, $this->listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?> + + + + + + + ▾ + + + ■ + + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + canState): ?> + + listDirn, $this->listOrder); ?> + + + + + + + + listDirn, $this->listOrder); ?> + + \ No newline at end of file diff --git a/admin/views/books/tmpl/default_toolbar.php b/admin/views/books/tmpl/default_toolbar.php new file mode 100644 index 0000000..7aa3e61 --- /dev/null +++ b/admin/views/books/tmpl/default_toolbar.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
+ +
+ + +
+
+ + pagination->getLimitBox(); ?> +
+
+ + +
+
+ + +
+
+
\ No newline at end of file diff --git a/admin/views/books/tmpl/index.html b/admin/views/books/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/books/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/books/view.html.php b/admin/views/books/view.html.php new file mode 100644 index 0000000..3e030cd --- /dev/null +++ b/admin/views/books/view.html.php @@ -0,0 +1,289 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Getbible Html View class for the Books + */ +class GetbibleViewBooks extends HtmlView +{ + /** + * Books view display method + * @return void + */ + function display($tpl = null) + { + if ($this->getLayout() !== 'modal') + { + // Include helper submenu + GetbibleHelper::addSubmenu('books'); + } + + // Assign data to the view + $this->items = $this->get('Items'); + $this->pagination = $this->get('Pagination'); + $this->state = $this->get('State'); + $this->user = JFactory::getUser(); + // Load the filter form from xml. + $this->filterForm = $this->get('FilterForm'); + // Load the active filters. + $this->activeFilters = $this->get('ActiveFilters'); + // Add the list ordering clause. + $this->listOrder = $this->escape($this->state->get('list.ordering', 'a.id')); + $this->listDirn = $this->escape($this->state->get('list.direction', 'DESC')); + $this->saveOrder = $this->listOrder == 'a.ordering'; + // set the return here value + $this->return_here = urlencode(base64_encode((string) JUri::getInstance())); + // get global action permissions + $this->canDo = GetbibleHelper::getActions('book'); + $this->canEdit = $this->canDo->get('book.edit'); + $this->canState = $this->canDo->get('book.edit.state'); + $this->canCreate = $this->canDo->get('book.create'); + $this->canDelete = $this->canDo->get('book.delete'); + $this->canBatch = $this->canDo->get('core.batch'); + + // We don't need toolbar in the modal window. + if ($this->getLayout() !== 'modal') + { + $this->addToolbar(); + $this->sidebar = JHtmlSidebar::render(); + // load the batch html + if ($this->canCreate && $this->canEdit && $this->canState) + { + $this->batchDisplay = JHtmlBatch_::render(); + } + } + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JToolBarHelper::title(JText::_('COM_GETBIBLE_BOOKS'), 'generic'); + JHtmlSidebar::setAction('index.php?option=com_getbible&view=books'); + JFormHelper::addFieldPath(JPATH_COMPONENT . '/models/fields'); + + if ($this->canCreate) + { + JToolBarHelper::addNew('book.add'); + } + + // Only load if there are items + if (GetbibleHelper::checkArray($this->items)) + { + if ($this->canEdit) + { + JToolBarHelper::editList('book.edit'); + } + + if ($this->canState) + { + JToolBarHelper::publishList('books.publish'); + JToolBarHelper::unpublishList('books.unpublish'); + JToolBarHelper::archiveList('books.archive'); + + if ($this->canDo->get('core.admin')) + { + JToolBarHelper::checkin('books.checkin'); + } + } + + // Add a batch button + if ($this->canBatch && $this->canCreate && $this->canEdit && $this->canState) + { + // Get the toolbar object instance + $bar = JToolBar::getInstance('toolbar'); + // set the batch button name + $title = JText::_('JTOOLBAR_BATCH'); + // Instantiate a new JLayoutFile instance and render the batch button + $layout = new JLayoutFile('joomla.toolbar.batch'); + // add the button to the page + $dhtml = $layout->render(array('title' => $title)); + $bar->appendButton('Custom', $dhtml, 'batch'); + } + + if ($this->state->get('filter.published') == -2 && ($this->canState && $this->canDelete)) + { + JToolbarHelper::deleteList('', 'books.delete', 'JTOOLBAR_EMPTY_TRASH'); + } + elseif ($this->canState && $this->canDelete) + { + JToolbarHelper::trash('books.trash'); + } + } + + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('books'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + + // add the options comp button + if ($this->canDo->get('core.admin') || $this->canDo->get('core.options')) + { + JToolBarHelper::preferences('com_getbible'); + } + + // Only load published batch if state and batch is allowed + if ($this->canState && $this->canBatch) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_STATE'), + 'batch[published]', + JHtml::_('select.options', JHtml::_('jgrid.publishedOptions', array('all' => false)), 'value', 'text', '', true) + ); + } + + // Only load access batch if create, edit and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_ACCESS'), + 'batch[access]', + JHtml::_('select.options', JHtml::_('access.assetgroups'), 'value', 'text') + ); + } + + // Only load Name batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Name Selection + $this->nameOptions = JFormHelper::loadFieldType('booksfiltername')->options; + // We do some sanitation for Name filter + if (GetbibleHelper::checkArray($this->nameOptions) && + isset($this->nameOptions[0]->value) && + !GetbibleHelper::checkString($this->nameOptions[0]->value)) + { + unset($this->nameOptions[0]); + } + // Name Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_BOOK_NAME_LABEL').' -', + 'batch[name]', + JHtml::_('select.options', $this->nameOptions, 'value', 'text') + ); + } + + // Only load Abbreviation Translation batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Abbreviation Translation Selection + $this->abbreviationTranslationOptions = JFormHelper::loadFieldType('Translations')->options; + // We do some sanitation for Abbreviation Translation filter + if (GetbibleHelper::checkArray($this->abbreviationTranslationOptions) && + isset($this->abbreviationTranslationOptions[0]->value) && + !GetbibleHelper::checkString($this->abbreviationTranslationOptions[0]->value)) + { + unset($this->abbreviationTranslationOptions[0]); + } + // Abbreviation Translation Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_BOOK_ABBREVIATION_LABEL').' -', + 'batch[abbreviation]', + JHtml::_('select.options', $this->abbreviationTranslationOptions, 'value', 'text') + ); + } + + // Only load Nr batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Nr Selection + $this->nrOptions = JFormHelper::loadFieldType('booksfilternr')->options; + // We do some sanitation for Nr filter + if (GetbibleHelper::checkArray($this->nrOptions) && + isset($this->nrOptions[0]->value) && + !GetbibleHelper::checkString($this->nrOptions[0]->value)) + { + unset($this->nrOptions[0]); + } + // Nr Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_BOOK_NR_LABEL').' -', + 'batch[nr]', + JHtml::_('select.options', $this->nrOptions, 'value', 'text') + ); + } + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_('COM_GETBIBLE_BOOKS')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/books.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 50) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Returns an array of fields the table can be sorted by + * + * @return array Array containing the field name to sort by as the key and display text as value + */ + protected function getSortFields() + { + return array( + 'a.ordering' => JText::_('JGRID_HEADING_ORDERING'), + 'a.published' => JText::_('JSTATUS'), + 'a.name' => JText::_('COM_GETBIBLE_BOOK_NAME_LABEL'), + 'g.translation' => JText::_('COM_GETBIBLE_BOOK_ABBREVIATION_LABEL'), + 'a.nr' => JText::_('COM_GETBIBLE_BOOK_NR_LABEL'), + 'a.id' => JText::_('JGRID_HEADING_ID') + ); + } +} diff --git a/admin/views/chapter/submitbutton.js b/admin/views/chapter/submitbutton.js new file mode 100644 index 0000000..cc7923e --- /dev/null +++ b/admin/views/chapter/submitbutton.js @@ -0,0 +1,31 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +Joomla.submitbutton = function(task) +{ + if (task == ''){ + return false; + } else { + var action = task.split('.'); + if (action[1] == 'cancel' || action[1] == 'close' || document.formvalidator.isValid(document.getElementById("adminForm"))){ + Joomla.submitform(task, document.getElementById("adminForm")); + return true; + } else { + alert(Joomla.JText._('chapter, some values are not acceptable.','Some values are unacceptable')); + return false; + } + } +} \ No newline at end of file diff --git a/admin/views/chapter/tmpl/edit.php b/admin/views/chapter/tmpl/edit.php new file mode 100644 index 0000000..fd17978 --- /dev/null +++ b/admin/views/chapter/tmpl/edit.php @@ -0,0 +1,112 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/html'); +JHtml::_('behavior.formvalidator'); +JHtml::_('formbehavior.chosen', 'select'); +JHtml::_('behavior.keepalive'); +$componentParams = $this->params; // will be removed just use $this->params instead +?> + + diff --git a/admin/views/chapter/tmpl/index.html b/admin/views/chapter/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/chapter/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/chapter/view.html.php b/admin/views/chapter/view.html.php new file mode 100644 index 0000000..e8f90b9 --- /dev/null +++ b/admin/views/chapter/view.html.php @@ -0,0 +1,130 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Chapter Html View class + */ +class GetbibleViewChapter extends HtmlView +{ + /** + * display method of View + * @return void + */ + public function display($tpl = null) + { + // set params + $this->params = JComponentHelper::getParams('com_getbible'); + // Assign the variables + $this->form = $this->get('Form'); + $this->item = $this->get('Item'); + $this->script = $this->get('Script'); + $this->state = $this->get('State'); + // get action permissions + $this->canDo = GetbibleHelper::getActions('chapter', $this->item); + // get input + $jinput = JFactory::getApplication()->input; + $this->ref = $jinput->get('ref', 0, 'word'); + $this->refid = $jinput->get('refid', 0, 'int'); + $return = $jinput->get('return', null, 'base64'); + // set the referral string + $this->referral = ''; + if ($this->refid && $this->ref) + { + // return to the item that referred to this item + $this->referral = '&ref=' . (string)$this->ref . '&refid=' . (int)$this->refid; + } + elseif($this->ref) + { + // return to the list view that referred to this item + $this->referral = '&ref=' . (string)$this->ref; + } + // check return value + if (!is_null($return)) + { + // add the return value + $this->referral .= '&return=' . (string)$return; + } + + // Set the toolbar + $this->addToolBar(); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JFactory::getApplication()->input->set('hidemainmenu', true); + JToolBarHelper::title(JText::_('COM_GETBIBLE_CHAPTER_READONLY'), 'chapter'); + JToolBarHelper::cancel('chapter.cancel', 'JTOOLBAR_CLOSE'); + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 30) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true, 30); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + $isNew = ($this->item->id < 1); + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_($isNew ? 'COM_GETBIBLE_CHAPTER_NEW' : 'COM_GETBIBLE_CHAPTER_EDIT')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/chapter.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + $this->document->addScript(JURI::root() . $this->script, (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + $this->document->addScript(JURI::root() . "administrator/components/com_getbible/views/chapter/submitbutton.js", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + JText::script('view not acceptable. Error'); + } +} diff --git a/admin/views/chapters/index.html b/admin/views/chapters/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/chapters/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/chapters/tmpl/default.php b/admin/views/chapters/tmpl/default.php new file mode 100644 index 0000000..ca05c5c --- /dev/null +++ b/admin/views/chapters/tmpl/default.php @@ -0,0 +1,75 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::_('behavior.multiselect'); +JHtml::_('dropdown.init'); +JHtml::_('formbehavior.chosen', '.multipleChaptersfilterchapter', null, array('placeholder_text_multiple' => '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_CHAPTER') . ' -')); +JHtml::_('formbehavior.chosen', '.multipleChaptersfilterbooknr', null, array('placeholder_text_multiple' => '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_BOOK_NUMBER') . ' -')); +JHtml::_('formbehavior.chosen', '.multipleAccessLevels', null, array('placeholder_text_multiple' => '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_ACCESS') . ' -')); +JHtml::_('formbehavior.chosen', 'select'); +if ($this->saveOrder) +{ + $saveOrderingUrl = 'index.php?option=com_getbible&task=chapters.saveOrderAjax&tmpl=component'; + JHtml::_('sortablelist.sortable', 'chapterList', 'adminForm', strtolower($this->listDirn), $saveOrderingUrl); +} +?> +
+sidebar)): ?> +
+ sidebar; ?> +
+
+ +
+ + $this)); +?> +items)): ?> +
+ +
+ + + loadTemplate('head');?> + loadTemplate('foot');?> + loadTemplate('body');?> +
+ + canCreate && $this->canEdit) : ?> + JText::_('COM_GETBIBLE_CHAPTERS_BATCH_OPTIONS'), + 'footer' => $this->loadTemplate('batch_footer') + ), + $this->loadTemplate('batch_body') + ); ?> + + +
+ + + + diff --git a/admin/views/chapters/tmpl/default_batch_body.php b/admin/views/chapters/tmpl/default_batch_body.php new file mode 100644 index 0000000..bfa6966 --- /dev/null +++ b/admin/views/chapters/tmpl/default_batch_body.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + +

+batchDisplay; ?> \ No newline at end of file diff --git a/admin/views/chapters/tmpl/default_batch_footer.php b/admin/views/chapters/tmpl/default_batch_footer.php new file mode 100644 index 0000000..fc887a4 --- /dev/null +++ b/admin/views/chapters/tmpl/default_batch_footer.php @@ -0,0 +1,29 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + + + \ No newline at end of file diff --git a/admin/views/chapters/tmpl/default_body.php b/admin/views/chapters/tmpl/default_body.php new file mode 100644 index 0000000..d08e1aa --- /dev/null +++ b/admin/views/chapters/tmpl/default_body.php @@ -0,0 +1,112 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +$edit = "index.php?option=com_getbible&view=chapters&task=chapter.edit"; + +?> +items as $i => $item): ?> + user->authorise('core.manage', 'com_checkin') || $item->checked_out == $this->user->id || $item->checked_out == 0; + $userChkOut = JFactory::getUser($item->checked_out); + $canDo = GetbibleHelper::getActions('chapter',$item,'chapters'); + ?> + + + get('chapter.edit.state')): ?> + saveOrder) + { + $iconClass = ' inactive tip-top" hasTooltip" title="' . JHtml::tooltipText('JORDERINGDISABLED'); + } + ?> + + + + saveOrder) : ?> + + + + ⋮ + + + + get('chapter.edit')): ?> + checked_out) : ?> + + id); ?> + + □ + + + id); ?> + + + □ + + + +
+ get('chapter.edit')): ?> + escape($item->name); ?> + checked_out): ?> + name, $item->checked_out_time, 'chapters.', $canCheckin); ?> + + + escape($item->name); ?> + +
+ + + escape($item->chapter); ?> + + + escape($item->book_nr); ?> + + +
+ user->authorise('translation.edit', 'com_getbible.translation.' . (int) $item->abbreviation_id)): ?> + escape($item->abbreviation_translation); ?> + + escape($item->abbreviation_translation); ?> + +
+ + + get('chapter.edit.state')) : ?> + checked_out) : ?> + + published, $i, 'chapters.', true, 'cb'); ?> + + published, $i, 'chapters.', false, 'cb'); ?> + + + published, $i, 'chapters.', true, 'cb'); ?> + + + published, $i, 'chapters.', false, 'cb'); ?> + + + + id; ?> + + + \ No newline at end of file diff --git a/admin/views/chapters/tmpl/default_foot.php b/admin/views/chapters/tmpl/default_foot.php new file mode 100644 index 0000000..290760a --- /dev/null +++ b/admin/views/chapters/tmpl/default_foot.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + pagination->getListFooter(); ?> + \ No newline at end of file diff --git a/admin/views/chapters/tmpl/default_head.php b/admin/views/chapters/tmpl/default_head.php new file mode 100644 index 0000000..6b1fbd2 --- /dev/null +++ b/admin/views/chapters/tmpl/default_head.php @@ -0,0 +1,62 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + canEdit&& $this->canState): ?> + + listDirn, $this->listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?> + + + + + + + ▾ + + + ■ + + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + canState): ?> + + listDirn, $this->listOrder); ?> + + + + + + + + listDirn, $this->listOrder); ?> + + \ No newline at end of file diff --git a/admin/views/chapters/tmpl/default_toolbar.php b/admin/views/chapters/tmpl/default_toolbar.php new file mode 100644 index 0000000..a8c1773 --- /dev/null +++ b/admin/views/chapters/tmpl/default_toolbar.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
+ +
+ + +
+
+ + pagination->getLimitBox(); ?> +
+
+ + +
+
+ + +
+
+
\ No newline at end of file diff --git a/admin/views/chapters/tmpl/index.html b/admin/views/chapters/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/chapters/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/chapters/view.html.php b/admin/views/chapters/view.html.php new file mode 100644 index 0000000..e079e1d --- /dev/null +++ b/admin/views/chapters/view.html.php @@ -0,0 +1,290 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Getbible Html View class for the Chapters + */ +class GetbibleViewChapters extends HtmlView +{ + /** + * Chapters view display method + * @return void + */ + function display($tpl = null) + { + if ($this->getLayout() !== 'modal') + { + // Include helper submenu + GetbibleHelper::addSubmenu('chapters'); + } + + // Assign data to the view + $this->items = $this->get('Items'); + $this->pagination = $this->get('Pagination'); + $this->state = $this->get('State'); + $this->user = JFactory::getUser(); + // Load the filter form from xml. + $this->filterForm = $this->get('FilterForm'); + // Load the active filters. + $this->activeFilters = $this->get('ActiveFilters'); + // Add the list ordering clause. + $this->listOrder = $this->escape($this->state->get('list.ordering', 'a.id')); + $this->listDirn = $this->escape($this->state->get('list.direction', 'DESC')); + $this->saveOrder = $this->listOrder == 'a.ordering'; + // set the return here value + $this->return_here = urlencode(base64_encode((string) JUri::getInstance())); + // get global action permissions + $this->canDo = GetbibleHelper::getActions('chapter'); + $this->canEdit = $this->canDo->get('chapter.edit'); + $this->canState = $this->canDo->get('chapter.edit.state'); + $this->canCreate = $this->canDo->get('chapter.create'); + $this->canDelete = $this->canDo->get('chapter.delete'); + $this->canBatch = $this->canDo->get('core.batch'); + + // We don't need toolbar in the modal window. + if ($this->getLayout() !== 'modal') + { + $this->addToolbar(); + $this->sidebar = JHtmlSidebar::render(); + // load the batch html + if ($this->canCreate && $this->canEdit && $this->canState) + { + $this->batchDisplay = JHtmlBatch_::render(); + } + } + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JToolBarHelper::title(JText::_('COM_GETBIBLE_CHAPTERS'), 'generic'); + JHtmlSidebar::setAction('index.php?option=com_getbible&view=chapters'); + JFormHelper::addFieldPath(JPATH_COMPONENT . '/models/fields'); + + if ($this->canCreate) + { + JToolBarHelper::addNew('chapter.add'); + } + + // Only load if there are items + if (GetbibleHelper::checkArray($this->items)) + { + if ($this->canEdit) + { + JToolBarHelper::editList('chapter.edit'); + } + + if ($this->canState) + { + JToolBarHelper::publishList('chapters.publish'); + JToolBarHelper::unpublishList('chapters.unpublish'); + JToolBarHelper::archiveList('chapters.archive'); + + if ($this->canDo->get('core.admin')) + { + JToolBarHelper::checkin('chapters.checkin'); + } + } + + // Add a batch button + if ($this->canBatch && $this->canCreate && $this->canEdit && $this->canState) + { + // Get the toolbar object instance + $bar = JToolBar::getInstance('toolbar'); + // set the batch button name + $title = JText::_('JTOOLBAR_BATCH'); + // Instantiate a new JLayoutFile instance and render the batch button + $layout = new JLayoutFile('joomla.toolbar.batch'); + // add the button to the page + $dhtml = $layout->render(array('title' => $title)); + $bar->appendButton('Custom', $dhtml, 'batch'); + } + + if ($this->state->get('filter.published') == -2 && ($this->canState && $this->canDelete)) + { + JToolbarHelper::deleteList('', 'chapters.delete', 'JTOOLBAR_EMPTY_TRASH'); + } + elseif ($this->canState && $this->canDelete) + { + JToolbarHelper::trash('chapters.trash'); + } + } + + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('chapters'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + + // add the options comp button + if ($this->canDo->get('core.admin') || $this->canDo->get('core.options')) + { + JToolBarHelper::preferences('com_getbible'); + } + + // Only load published batch if state and batch is allowed + if ($this->canState && $this->canBatch) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_STATE'), + 'batch[published]', + JHtml::_('select.options', JHtml::_('jgrid.publishedOptions', array('all' => false)), 'value', 'text', '', true) + ); + } + + // Only load access batch if create, edit and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_ACCESS'), + 'batch[access]', + JHtml::_('select.options', JHtml::_('access.assetgroups'), 'value', 'text') + ); + } + + // Only load Chapter batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Chapter Selection + $this->chapterOptions = JFormHelper::loadFieldType('chaptersfilterchapter')->options; + // We do some sanitation for Chapter filter + if (GetbibleHelper::checkArray($this->chapterOptions) && + isset($this->chapterOptions[0]->value) && + !GetbibleHelper::checkString($this->chapterOptions[0]->value)) + { + unset($this->chapterOptions[0]); + } + // Chapter Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_CHAPTER_CHAPTER_LABEL').' -', + 'batch[chapter]', + JHtml::_('select.options', $this->chapterOptions, 'value', 'text') + ); + } + + // Only load Book Nr batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Book Nr Selection + $this->book_nrOptions = JFormHelper::loadFieldType('chaptersfilterbooknr')->options; + // We do some sanitation for Book Nr filter + if (GetbibleHelper::checkArray($this->book_nrOptions) && + isset($this->book_nrOptions[0]->value) && + !GetbibleHelper::checkString($this->book_nrOptions[0]->value)) + { + unset($this->book_nrOptions[0]); + } + // Book Nr Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_CHAPTER_BOOK_NR_LABEL').' -', + 'batch[book_nr]', + JHtml::_('select.options', $this->book_nrOptions, 'value', 'text') + ); + } + + // Only load Abbreviation Translation batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Abbreviation Translation Selection + $this->abbreviationTranslationOptions = JFormHelper::loadFieldType('Translations')->options; + // We do some sanitation for Abbreviation Translation filter + if (GetbibleHelper::checkArray($this->abbreviationTranslationOptions) && + isset($this->abbreviationTranslationOptions[0]->value) && + !GetbibleHelper::checkString($this->abbreviationTranslationOptions[0]->value)) + { + unset($this->abbreviationTranslationOptions[0]); + } + // Abbreviation Translation Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_CHAPTER_ABBREVIATION_LABEL').' -', + 'batch[abbreviation]', + JHtml::_('select.options', $this->abbreviationTranslationOptions, 'value', 'text') + ); + } + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_('COM_GETBIBLE_CHAPTERS')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/chapters.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 50) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Returns an array of fields the table can be sorted by + * + * @return array Array containing the field name to sort by as the key and display text as value + */ + protected function getSortFields() + { + return array( + 'a.ordering' => JText::_('JGRID_HEADING_ORDERING'), + 'a.published' => JText::_('JSTATUS'), + 'a.name' => JText::_('COM_GETBIBLE_CHAPTER_NAME_LABEL'), + 'a.chapter' => JText::_('COM_GETBIBLE_CHAPTER_CHAPTER_LABEL'), + 'a.book_nr' => JText::_('COM_GETBIBLE_CHAPTER_BOOK_NR_LABEL'), + 'g.translation' => JText::_('COM_GETBIBLE_CHAPTER_ABBREVIATION_LABEL'), + 'a.id' => JText::_('JGRID_HEADING_ID') + ); + } +} diff --git a/admin/views/getbible/index.html b/admin/views/getbible/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/getbible/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/getbible/tmpl/default.php b/admin/views/getbible/tmpl/default.php new file mode 100644 index 0000000..946509a --- /dev/null +++ b/admin/views/getbible/tmpl/default.php @@ -0,0 +1,85 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + + + +?> +
+
+ 'cpanel')); ?> + + +
+
+ 'main')); ?> + + loadTemplate('main');?> + + +
+
+ 'vdm')); ?> + + loadTemplate('vdm');?> + + +
+
+ + + +
+
+ 'wiki_one')); ?> + + loadTemplate('wiki_tutorials');?> + + +
+
+ + + +
+
+ 'notice_board_one')); ?> + + loadTemplate('notice_board_vast_development_method');?> + + +
+
+ + + +
+
+ 'readme_one')); ?> + + loadTemplate('readme_information');?> + + +
+
+ + + +
+
\ No newline at end of file diff --git a/admin/views/getbible/tmpl/default_main.php b/admin/views/getbible/tmpl/default_main.php new file mode 100644 index 0000000..4da9e6d --- /dev/null +++ b/admin/views/getbible/tmpl/default_main.php @@ -0,0 +1,36 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +icons['main']) && is_array($this->icons['main'])) :?> + icons['main'] as $icon): ?> + + +
+ +

+ \ No newline at end of file diff --git a/admin/views/getbible/tmpl/default_notice_board_vast_development_method.php b/admin/views/getbible/tmpl/default_notice_board_vast_development_method.php new file mode 100644 index 0000000..2a0e483 --- /dev/null +++ b/admin/views/getbible/tmpl/default_notice_board_vast_development_method.php @@ -0,0 +1,22 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +noticeboard; ?> diff --git a/admin/views/getbible/tmpl/default_readme_information.php b/admin/views/getbible/tmpl/default_readme_information.php new file mode 100644 index 0000000..18f25d2 --- /dev/null +++ b/admin/views/getbible/tmpl/default_readme_information.php @@ -0,0 +1,22 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +readme; ?> diff --git a/admin/views/getbible/tmpl/default_vdm.php b/admin/views/getbible/tmpl/default_vdm.php new file mode 100644 index 0000000..cf8cd6d --- /dev/null +++ b/admin/views/getbible/tmpl/default_vdm.php @@ -0,0 +1,44 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +<?php echo JText::_('COM_GETBIBLE'); ?> + +
+contributors)): ?> + contributors) > 1): ?> +

+ +

+ +
    + contributors as $contributor): ?> +
  • :
  • + +
+
+ \ No newline at end of file diff --git a/admin/views/getbible/tmpl/default_wiki_tutorials.php b/admin/views/getbible/tmpl/default_wiki_tutorials.php new file mode 100644 index 0000000..c531eb9 --- /dev/null +++ b/admin/views/getbible/tmpl/default_wiki_tutorials.php @@ -0,0 +1,22 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +wiki; ?> diff --git a/admin/views/getbible/tmpl/index.html b/admin/views/getbible/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/getbible/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/getbible/view.html.php b/admin/views/getbible/view.html.php new file mode 100644 index 0000000..3be7666 --- /dev/null +++ b/admin/views/getbible/view.html.php @@ -0,0 +1,100 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + + + +/** + * Getbible View class + */ +class GetbibleViewGetbible extends JViewLegacy +{ + /** + * View display method + * @return void + */ + function display($tpl = null) + { + // Assign data to the view + $this->icons = $this->get('Icons'); + $this->contributors = GetbibleHelper::getContributors(); + $this->wiki = $this->get('Wiki'); + $this->noticeboard = $this->get('Noticeboard'); + $this->readme = $this->get('Readme'); + $this->version = $this->get('Version'); + + // get the manifest details of the component + $this->manifest = GetbibleHelper::manifest(); + + // Set the toolbar + $this->addToolBar(); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + $canDo = GetbibleHelper::getActions('getbible'); + JToolBarHelper::title(JText::_('COM_GETBIBLE_DASHBOARD'), 'grid-2'); + + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('getbible'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + + if ($canDo->get('core.admin') || $canDo->get('core.options')) + { + JToolBarHelper::preferences('com_getbible'); + } + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + $document = JFactory::getDocument(); + + // add dashboard style sheets + $document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/dashboard.css"); + + // set page title + $document->setTitle(JText::_('COM_GETBIBLE_DASHBOARD')); + + // add manifest to page JavaScript + $document->addScriptDeclaration("var manifest = jQuery.parseJSON('" . json_encode($this->manifest) . "');", "text/javascript"); + } +} diff --git a/admin/views/index.html b/admin/views/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/linker/submitbutton.js b/admin/views/linker/submitbutton.js new file mode 100644 index 0000000..173acd2 --- /dev/null +++ b/admin/views/linker/submitbutton.js @@ -0,0 +1,31 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +Joomla.submitbutton = function(task) +{ + if (task == ''){ + return false; + } else { + var action = task.split('.'); + if (action[1] == 'cancel' || action[1] == 'close' || document.formvalidator.isValid(document.getElementById("adminForm"))){ + Joomla.submitform(task, document.getElementById("adminForm")); + return true; + } else { + alert(Joomla.JText._('linker, some values are not acceptable.','Some values are unacceptable')); + return false; + } + } +} \ No newline at end of file diff --git a/admin/views/linker/tmpl/edit.php b/admin/views/linker/tmpl/edit.php new file mode 100644 index 0000000..793cf77 --- /dev/null +++ b/admin/views/linker/tmpl/edit.php @@ -0,0 +1,144 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/html'); +JHtml::_('behavior.formvalidator'); +JHtml::_('formbehavior.chosen', 'select'); +JHtml::_('behavior.keepalive'); +$componentParams = $this->params; // will be removed just use $this->params instead +?> + + diff --git a/admin/views/linker/tmpl/index.html b/admin/views/linker/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/linker/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/linker/view.html.php b/admin/views/linker/view.html.php new file mode 100644 index 0000000..4b16b25 --- /dev/null +++ b/admin/views/linker/view.html.php @@ -0,0 +1,231 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Linker Html View class + */ +class GetbibleViewLinker extends HtmlView +{ + /** + * display method of View + * @return void + */ + public function display($tpl = null) + { + // set params + $this->params = JComponentHelper::getParams('com_getbible'); + // Assign the variables + $this->form = $this->get('Form'); + $this->item = $this->get('Item'); + $this->script = $this->get('Script'); + $this->state = $this->get('State'); + // get action permissions + $this->canDo = GetbibleHelper::getActions('linker', $this->item); + // get input + $jinput = JFactory::getApplication()->input; + $this->ref = $jinput->get('ref', 0, 'word'); + $this->refid = $jinput->get('refid', 0, 'int'); + $return = $jinput->get('return', null, 'base64'); + // set the referral string + $this->referral = ''; + if ($this->refid && $this->ref) + { + // return to the item that referred to this item + $this->referral = '&ref=' . (string)$this->ref . '&refid=' . (int)$this->refid; + } + elseif($this->ref) + { + // return to the list view that referred to this item + $this->referral = '&ref=' . (string)$this->ref; + } + // check return value + if (!is_null($return)) + { + // add the return value + $this->referral .= '&return=' . (string)$return; + } + + // Get Linked view data + $this->vvvtags = $this->get('Vvvtags'); + + // Get Linked view data + $this->vvwnotes = $this->get('Vvwnotes'); + + // Get Linked view data + $this->vvxpasswords = $this->get('Vvxpasswords'); + + // Set the toolbar + $this->addToolBar(); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JFactory::getApplication()->input->set('hidemainmenu', true); + $user = JFactory::getUser(); + $userId = $user->id; + $isNew = $this->item->id == 0; + + JToolbarHelper::title( JText::_($isNew ? 'COM_GETBIBLE_LINKER_NEW' : 'COM_GETBIBLE_LINKER_EDIT'), 'pencil-2 article-add'); + // Built the actions for new and existing records. + if (GetbibleHelper::checkString($this->referral)) + { + if ($this->canDo->get('linker.create') && $isNew) + { + // We can create the record. + JToolBarHelper::save('linker.save', 'JTOOLBAR_SAVE'); + } + elseif ($this->canDo->get('linker.edit')) + { + // We can save the record. + JToolBarHelper::save('linker.save', 'JTOOLBAR_SAVE'); + } + if ($isNew) + { + // Do not creat but cancel. + JToolBarHelper::cancel('linker.cancel', 'JTOOLBAR_CANCEL'); + } + else + { + // We can close it. + JToolBarHelper::cancel('linker.cancel', 'JTOOLBAR_CLOSE'); + } + } + else + { + if ($isNew) + { + // For new records, check the create permission. + if ($this->canDo->get('linker.create')) + { + JToolBarHelper::apply('linker.apply', 'JTOOLBAR_APPLY'); + JToolBarHelper::save('linker.save', 'JTOOLBAR_SAVE'); + JToolBarHelper::custom('linker.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false); + }; + JToolBarHelper::cancel('linker.cancel', 'JTOOLBAR_CANCEL'); + } + else + { + if ($this->canDo->get('linker.edit')) + { + // We can save the new record + JToolBarHelper::apply('linker.apply', 'JTOOLBAR_APPLY'); + JToolBarHelper::save('linker.save', 'JTOOLBAR_SAVE'); + // We can save this record, but check the create permission to see + // if we can return to make a new one. + if ($this->canDo->get('linker.create')) + { + JToolBarHelper::custom('linker.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false); + } + } + if ($this->canDo->get('linker.create')) + { + JToolBarHelper::custom('linker.save2copy', 'save-copy.png', 'save-copy_f2.png', 'JTOOLBAR_SAVE_AS_COPY', false); + } + JToolBarHelper::cancel('linker.cancel', 'JTOOLBAR_CLOSE'); + } + } + JToolbarHelper::divider(); + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('linker'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 30) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true, 30); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + $isNew = ($this->item->id < 1); + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_($isNew ? 'COM_GETBIBLE_LINKER_NEW' : 'COM_GETBIBLE_LINKER_EDIT')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/linker.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + + // Add the CSS for Footable. + JHtml::_('stylesheet', 'media/com_getbible/footable-v2/css/footable.core.min.css', ['version' => 'auto']); + + // Use the Metro Style + if (!isset($this->fooTableStyle) || 0 == $this->fooTableStyle) + { + JHtml::_('stylesheet', 'media/com_getbible/footable-v2/css/footable.metro.min.css', ['version' => 'auto']); + } + // Use the Legacy Style. + elseif (isset($this->fooTableStyle) && 1 == $this->fooTableStyle) + { + JHtml::_('stylesheet', 'media/com_getbible/footable-v2/css/footable.standalone.min.css', ['version' => 'auto']); + } + + // Add the JavaScript for Footable + JHtml::_('script', 'media/com_getbible/footable-v2/js/footable.js', ['version' => 'auto']); + JHtml::_('script', 'media/com_getbible/footable-v2/js/footable.sort.js', ['version' => 'auto']); + JHtml::_('script', 'media/com_getbible/footable-v2/js/footable.filter.js', ['version' => 'auto']); + JHtml::_('script', 'media/com_getbible/footable-v2/js/footable.paginate.js', ['version' => 'auto']); + + $footable = "jQuery(document).ready(function() { jQuery(function () { jQuery('.footable').footable(); }); jQuery('.nav-tabs').on('click', 'li', function() { setTimeout(tableFix, 10); }); }); function tableFix() { jQuery('.footable').trigger('footable_resize'); }"; + $this->document->addScriptDeclaration($footable); + + $this->document->addScript(JURI::root() . $this->script, (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + $this->document->addScript(JURI::root() . "administrator/components/com_getbible/views/linker/submitbutton.js", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + JText::script('view not acceptable. Error'); + } +} diff --git a/admin/views/linkers/index.html b/admin/views/linkers/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/linkers/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/linkers/tmpl/default.php b/admin/views/linkers/tmpl/default.php new file mode 100644 index 0000000..4f1523b --- /dev/null +++ b/admin/views/linkers/tmpl/default.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::_('behavior.multiselect'); +JHtml::_('dropdown.init'); +JHtml::_('formbehavior.chosen', '.multipleAccessLevels', null, array('placeholder_text_multiple' => '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_ACCESS') . ' -')); +JHtml::_('formbehavior.chosen', 'select'); +if ($this->saveOrder) +{ + $saveOrderingUrl = 'index.php?option=com_getbible&task=linkers.saveOrderAjax&tmpl=component'; + JHtml::_('sortablelist.sortable', 'linkerList', 'adminForm', strtolower($this->listDirn), $saveOrderingUrl); +} +?> +
+sidebar)): ?> +
+ sidebar; ?> +
+
+ +
+ + $this)); +?> +items)): ?> +
+ +
+ + + loadTemplate('head');?> + loadTemplate('foot');?> + loadTemplate('body');?> +
+ + canCreate && $this->canEdit) : ?> + JText::_('COM_GETBIBLE_LINKERS_BATCH_OPTIONS'), + 'footer' => $this->loadTemplate('batch_footer') + ), + $this->loadTemplate('batch_body') + ); ?> + + +
+ + + + diff --git a/admin/views/linkers/tmpl/default_batch_body.php b/admin/views/linkers/tmpl/default_batch_body.php new file mode 100644 index 0000000..ae7ef3b --- /dev/null +++ b/admin/views/linkers/tmpl/default_batch_body.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + +

+batchDisplay; ?> \ No newline at end of file diff --git a/admin/views/linkers/tmpl/default_batch_footer.php b/admin/views/linkers/tmpl/default_batch_footer.php new file mode 100644 index 0000000..2880c91 --- /dev/null +++ b/admin/views/linkers/tmpl/default_batch_footer.php @@ -0,0 +1,29 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + + + \ No newline at end of file diff --git a/admin/views/linkers/tmpl/default_body.php b/admin/views/linkers/tmpl/default_body.php new file mode 100644 index 0000000..068e927 --- /dev/null +++ b/admin/views/linkers/tmpl/default_body.php @@ -0,0 +1,100 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +$edit = "index.php?option=com_getbible&view=linkers&task=linker.edit"; + +?> +items as $i => $item): ?> + user->authorise('core.manage', 'com_checkin') || $item->checked_out == $this->user->id || $item->checked_out == 0; + $userChkOut = JFactory::getUser($item->checked_out); + $canDo = GetbibleHelper::getActions('linker',$item,'linkers'); + ?> + + + get('linker.edit.state')): ?> + saveOrder) + { + $iconClass = ' inactive tip-top" hasTooltip" title="' . JHtml::tooltipText('JORDERINGDISABLED'); + } + ?> + + + + saveOrder) : ?> + + + + ⋮ + + + + get('linker.edit')): ?> + checked_out) : ?> + + id); ?> + + □ + + + id); ?> + + + □ + + + +
+ get('linker.edit')): ?> + escape($item->name); ?> + checked_out): ?> + name, $item->checked_out_time, 'linkers.', $canCheckin); ?> + + + escape($item->name); ?> + +
+ + + escape($item->guid); ?> + + + get('linker.edit.state')) : ?> + checked_out) : ?> + + published, $i, 'linkers.', true, 'cb'); ?> + + published, $i, 'linkers.', false, 'cb'); ?> + + + published, $i, 'linkers.', true, 'cb'); ?> + + + published, $i, 'linkers.', false, 'cb'); ?> + + + + id; ?> + + + \ No newline at end of file diff --git a/admin/views/linkers/tmpl/default_foot.php b/admin/views/linkers/tmpl/default_foot.php new file mode 100644 index 0000000..a0cf75a --- /dev/null +++ b/admin/views/linkers/tmpl/default_foot.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + pagination->getListFooter(); ?> + \ No newline at end of file diff --git a/admin/views/linkers/tmpl/default_head.php b/admin/views/linkers/tmpl/default_head.php new file mode 100644 index 0000000..563b382 --- /dev/null +++ b/admin/views/linkers/tmpl/default_head.php @@ -0,0 +1,56 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + canEdit&& $this->canState): ?> + + listDirn, $this->listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?> + + + + + + + ▾ + + + ■ + + + + listDirn, $this->listOrder); ?> + + + + + canState): ?> + + listDirn, $this->listOrder); ?> + + + + + + + + listDirn, $this->listOrder); ?> + + \ No newline at end of file diff --git a/admin/views/linkers/tmpl/default_toolbar.php b/admin/views/linkers/tmpl/default_toolbar.php new file mode 100644 index 0000000..ca55191 --- /dev/null +++ b/admin/views/linkers/tmpl/default_toolbar.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
+ +
+ + +
+
+ + pagination->getLimitBox(); ?> +
+
+ + +
+
+ + +
+
+
\ No newline at end of file diff --git a/admin/views/linkers/tmpl/index.html b/admin/views/linkers/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/linkers/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/linkers/view.html.php b/admin/views/linkers/view.html.php new file mode 100644 index 0000000..5e5d7c2 --- /dev/null +++ b/admin/views/linkers/view.html.php @@ -0,0 +1,247 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Getbible Html View class for the Linkers + */ +class GetbibleViewLinkers extends HtmlView +{ + /** + * Linkers view display method + * @return void + */ + function display($tpl = null) + { + if ($this->getLayout() !== 'modal') + { + // Include helper submenu + GetbibleHelper::addSubmenu('linkers'); + } + + // Assign data to the view + $this->items = $this->get('Items'); + $this->pagination = $this->get('Pagination'); + $this->state = $this->get('State'); + $this->user = JFactory::getUser(); + // Load the filter form from xml. + $this->filterForm = $this->get('FilterForm'); + // Load the active filters. + $this->activeFilters = $this->get('ActiveFilters'); + // Add the list ordering clause. + $this->listOrder = $this->escape($this->state->get('list.ordering', 'a.id')); + $this->listDirn = $this->escape($this->state->get('list.direction', 'DESC')); + $this->saveOrder = $this->listOrder == 'a.ordering'; + // set the return here value + $this->return_here = urlencode(base64_encode((string) JUri::getInstance())); + // get global action permissions + $this->canDo = GetbibleHelper::getActions('linker'); + $this->canEdit = $this->canDo->get('linker.edit'); + $this->canState = $this->canDo->get('linker.edit.state'); + $this->canCreate = $this->canDo->get('linker.create'); + $this->canDelete = $this->canDo->get('linker.delete'); + $this->canBatch = $this->canDo->get('core.batch'); + + // We don't need toolbar in the modal window. + if ($this->getLayout() !== 'modal') + { + $this->addToolbar(); + $this->sidebar = JHtmlSidebar::render(); + // load the batch html + if ($this->canCreate && $this->canEdit && $this->canState) + { + $this->batchDisplay = JHtmlBatch_::render(); + } + } + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JToolBarHelper::title(JText::_('COM_GETBIBLE_LINKERS'), 'joomla'); + JHtmlSidebar::setAction('index.php?option=com_getbible&view=linkers'); + JFormHelper::addFieldPath(JPATH_COMPONENT . '/models/fields'); + + if ($this->canCreate) + { + JToolBarHelper::addNew('linker.add'); + } + + // Only load if there are items + if (GetbibleHelper::checkArray($this->items)) + { + if ($this->canEdit) + { + JToolBarHelper::editList('linker.edit'); + } + + if ($this->canState) + { + JToolBarHelper::publishList('linkers.publish'); + JToolBarHelper::unpublishList('linkers.unpublish'); + JToolBarHelper::archiveList('linkers.archive'); + + if ($this->canDo->get('core.admin')) + { + JToolBarHelper::checkin('linkers.checkin'); + } + } + + // Add a batch button + if ($this->canBatch && $this->canCreate && $this->canEdit && $this->canState) + { + // Get the toolbar object instance + $bar = JToolBar::getInstance('toolbar'); + // set the batch button name + $title = JText::_('JTOOLBAR_BATCH'); + // Instantiate a new JLayoutFile instance and render the batch button + $layout = new JLayoutFile('joomla.toolbar.batch'); + // add the button to the page + $dhtml = $layout->render(array('title' => $title)); + $bar->appendButton('Custom', $dhtml, 'batch'); + } + + if ($this->state->get('filter.published') == -2 && ($this->canState && $this->canDelete)) + { + JToolbarHelper::deleteList('', 'linkers.delete', 'JTOOLBAR_EMPTY_TRASH'); + } + elseif ($this->canState && $this->canDelete) + { + JToolbarHelper::trash('linkers.trash'); + } + } + + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('linkers'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + + // add the options comp button + if ($this->canDo->get('core.admin') || $this->canDo->get('core.options')) + { + JToolBarHelper::preferences('com_getbible'); + } + + // Only load published batch if state and batch is allowed + if ($this->canState && $this->canBatch) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_STATE'), + 'batch[published]', + JHtml::_('select.options', JHtml::_('jgrid.publishedOptions', array('all' => false)), 'value', 'text', '', true) + ); + } + + // Only load access batch if create, edit and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_ACCESS'), + 'batch[access]', + JHtml::_('select.options', JHtml::_('access.assetgroups'), 'value', 'text') + ); + } + + // Only load Name batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Name Selection + $this->nameOptions = JFormHelper::loadFieldType('linkersfiltername')->options; + // We do some sanitation for Name filter + if (GetbibleHelper::checkArray($this->nameOptions) && + isset($this->nameOptions[0]->value) && + !GetbibleHelper::checkString($this->nameOptions[0]->value)) + { + unset($this->nameOptions[0]); + } + // Name Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_LINKER_NAME_LABEL').' -', + 'batch[name]', + JHtml::_('select.options', $this->nameOptions, 'value', 'text') + ); + } + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_('COM_GETBIBLE_LINKERS')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/linkers.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 50) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Returns an array of fields the table can be sorted by + * + * @return array Array containing the field name to sort by as the key and display text as value + */ + protected function getSortFields() + { + return array( + 'a.ordering' => JText::_('JGRID_HEADING_ORDERING'), + 'a.published' => JText::_('JSTATUS'), + 'a.name' => JText::_('COM_GETBIBLE_LINKER_NAME_LABEL'), + 'a.id' => JText::_('JGRID_HEADING_ID') + ); + } +} diff --git a/admin/views/note/submitbutton.js b/admin/views/note/submitbutton.js new file mode 100644 index 0000000..8136d65 --- /dev/null +++ b/admin/views/note/submitbutton.js @@ -0,0 +1,31 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +Joomla.submitbutton = function(task) +{ + if (task == ''){ + return false; + } else { + var action = task.split('.'); + if (action[1] == 'cancel' || action[1] == 'close' || document.formvalidator.isValid(document.getElementById("adminForm"))){ + Joomla.submitform(task, document.getElementById("adminForm")); + return true; + } else { + alert(Joomla.JText._('note, some values are not acceptable.','Some values are unacceptable')); + return false; + } + } +} \ No newline at end of file diff --git a/admin/views/note/tmpl/edit.php b/admin/views/note/tmpl/edit.php new file mode 100644 index 0000000..cb7166b --- /dev/null +++ b/admin/views/note/tmpl/edit.php @@ -0,0 +1,112 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/html'); +JHtml::_('behavior.formvalidator'); +JHtml::_('formbehavior.chosen', 'select'); +JHtml::_('behavior.keepalive'); +$componentParams = $this->params; // will be removed just use $this->params instead +?> + + diff --git a/admin/views/note/tmpl/index.html b/admin/views/note/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/note/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/note/view.html.php b/admin/views/note/view.html.php new file mode 100644 index 0000000..9ade78a --- /dev/null +++ b/admin/views/note/view.html.php @@ -0,0 +1,203 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Note Html View class + */ +class GetbibleViewNote extends HtmlView +{ + /** + * display method of View + * @return void + */ + public function display($tpl = null) + { + // set params + $this->params = JComponentHelper::getParams('com_getbible'); + // Assign the variables + $this->form = $this->get('Form'); + $this->item = $this->get('Item'); + $this->script = $this->get('Script'); + $this->state = $this->get('State'); + // get action permissions + $this->canDo = GetbibleHelper::getActions('note', $this->item); + // get input + $jinput = JFactory::getApplication()->input; + $this->ref = $jinput->get('ref', 0, 'word'); + $this->refid = $jinput->get('refid', 0, 'int'); + $return = $jinput->get('return', null, 'base64'); + // set the referral string + $this->referral = ''; + if ($this->refid && $this->ref) + { + // return to the item that referred to this item + $this->referral = '&ref=' . (string)$this->ref . '&refid=' . (int)$this->refid; + } + elseif($this->ref) + { + // return to the list view that referred to this item + $this->referral = '&ref=' . (string)$this->ref; + } + // check return value + if (!is_null($return)) + { + // add the return value + $this->referral .= '&return=' . (string)$return; + } + + // Set the toolbar + $this->addToolBar(); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JFactory::getApplication()->input->set('hidemainmenu', true); + $user = JFactory::getUser(); + $userId = $user->id; + $isNew = $this->item->id == 0; + + JToolbarHelper::title( JText::_($isNew ? 'COM_GETBIBLE_NOTE_NEW' : 'COM_GETBIBLE_NOTE_EDIT'), 'pencil-2 article-add'); + // Built the actions for new and existing records. + if (GetbibleHelper::checkString($this->referral)) + { + if ($this->canDo->get('note.create') && $isNew) + { + // We can create the record. + JToolBarHelper::save('note.save', 'JTOOLBAR_SAVE'); + } + elseif ($this->canDo->get('note.edit')) + { + // We can save the record. + JToolBarHelper::save('note.save', 'JTOOLBAR_SAVE'); + } + if ($isNew) + { + // Do not creat but cancel. + JToolBarHelper::cancel('note.cancel', 'JTOOLBAR_CANCEL'); + } + else + { + // We can close it. + JToolBarHelper::cancel('note.cancel', 'JTOOLBAR_CLOSE'); + } + } + else + { + if ($isNew) + { + // For new records, check the create permission. + if ($this->canDo->get('note.create')) + { + JToolBarHelper::apply('note.apply', 'JTOOLBAR_APPLY'); + JToolBarHelper::save('note.save', 'JTOOLBAR_SAVE'); + JToolBarHelper::custom('note.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false); + }; + JToolBarHelper::cancel('note.cancel', 'JTOOLBAR_CANCEL'); + } + else + { + if ($this->canDo->get('note.edit')) + { + // We can save the new record + JToolBarHelper::apply('note.apply', 'JTOOLBAR_APPLY'); + JToolBarHelper::save('note.save', 'JTOOLBAR_SAVE'); + // We can save this record, but check the create permission to see + // if we can return to make a new one. + if ($this->canDo->get('note.create')) + { + JToolBarHelper::custom('note.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false); + } + } + $canVersion = ($this->canDo->get('core.version') && $this->canDo->get('note.version')); + if ($this->state->params->get('save_history', 1) && $this->canDo->get('note.edit') && $canVersion) + { + JToolbarHelper::versions('com_getbible.note', $this->item->id); + } + if ($this->canDo->get('note.create')) + { + JToolBarHelper::custom('note.save2copy', 'save-copy.png', 'save-copy_f2.png', 'JTOOLBAR_SAVE_AS_COPY', false); + } + JToolBarHelper::cancel('note.cancel', 'JTOOLBAR_CLOSE'); + } + } + JToolbarHelper::divider(); + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('note'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 30) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true, 30); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + $isNew = ($this->item->id < 1); + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_($isNew ? 'COM_GETBIBLE_NOTE_NEW' : 'COM_GETBIBLE_NOTE_EDIT')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/note.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + $this->document->addScript(JURI::root() . $this->script, (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + $this->document->addScript(JURI::root() . "administrator/components/com_getbible/views/note/submitbutton.js", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + JText::script('view not acceptable. Error'); + } +} diff --git a/admin/views/notes/index.html b/admin/views/notes/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/notes/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/notes/tmpl/default.php b/admin/views/notes/tmpl/default.php new file mode 100644 index 0000000..f7936a4 --- /dev/null +++ b/admin/views/notes/tmpl/default.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::_('behavior.multiselect'); +JHtml::_('dropdown.init'); +JHtml::_('formbehavior.chosen', '.multipleAccessLevels', null, array('placeholder_text_multiple' => '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_ACCESS') . ' -')); +JHtml::_('formbehavior.chosen', 'select'); +if ($this->saveOrder) +{ + $saveOrderingUrl = 'index.php?option=com_getbible&task=notes.saveOrderAjax&tmpl=component'; + JHtml::_('sortablelist.sortable', 'noteList', 'adminForm', strtolower($this->listDirn), $saveOrderingUrl); +} +?> +
+sidebar)): ?> +
+ sidebar; ?> +
+
+ +
+ + $this)); +?> +items)): ?> +
+ +
+ + + loadTemplate('head');?> + loadTemplate('foot');?> + loadTemplate('body');?> +
+ + canCreate && $this->canEdit) : ?> + JText::_('COM_GETBIBLE_NOTES_BATCH_OPTIONS'), + 'footer' => $this->loadTemplate('batch_footer') + ), + $this->loadTemplate('batch_body') + ); ?> + + +
+ + + + diff --git a/admin/views/notes/tmpl/default_batch_body.php b/admin/views/notes/tmpl/default_batch_body.php new file mode 100644 index 0000000..be0c120 --- /dev/null +++ b/admin/views/notes/tmpl/default_batch_body.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + +

+batchDisplay; ?> \ No newline at end of file diff --git a/admin/views/notes/tmpl/default_batch_footer.php b/admin/views/notes/tmpl/default_batch_footer.php new file mode 100644 index 0000000..df4b4d9 --- /dev/null +++ b/admin/views/notes/tmpl/default_batch_footer.php @@ -0,0 +1,29 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + + + \ No newline at end of file diff --git a/admin/views/notes/tmpl/default_body.php b/admin/views/notes/tmpl/default_body.php new file mode 100644 index 0000000..3e25be6 --- /dev/null +++ b/admin/views/notes/tmpl/default_body.php @@ -0,0 +1,109 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +$edit = "index.php?option=com_getbible&view=notes&task=note.edit"; + +?> +items as $i => $item): ?> + user->authorise('core.manage', 'com_checkin') || $item->checked_out == $this->user->id || $item->checked_out == 0; + $userChkOut = JFactory::getUser($item->checked_out); + $canDo = GetbibleHelper::getActions('note',$item,'notes'); + ?> + + + get('note.edit.state')): ?> + saveOrder) + { + $iconClass = ' inactive tip-top" hasTooltip" title="' . JHtml::tooltipText('JORDERINGDISABLED'); + } + ?> + + + + saveOrder) : ?> + + + + ⋮ + + + + get('note.edit')): ?> + checked_out) : ?> + + id); ?> + + □ + + + id); ?> + + + □ + + + +
+ get('note.edit')): ?> + escape($item->book_nr); ?> + checked_out): ?> + name, $item->checked_out_time, 'notes.', $canCheckin); ?> + + + escape($item->book_nr); ?> + +
+ + +
+ user->authorise('linker.edit', 'com_getbible.linker.' . (int) $item->linker_id)): ?> + escape($item->linker_name); ?> + + escape($item->linker_name); ?> + +
+ + + access); ?> + + + get('note.edit.state')) : ?> + checked_out) : ?> + + published, $i, 'notes.', true, 'cb'); ?> + + published, $i, 'notes.', false, 'cb'); ?> + + + published, $i, 'notes.', true, 'cb'); ?> + + + published, $i, 'notes.', false, 'cb'); ?> + + + + id; ?> + + + \ No newline at end of file diff --git a/admin/views/notes/tmpl/default_foot.php b/admin/views/notes/tmpl/default_foot.php new file mode 100644 index 0000000..38a928f --- /dev/null +++ b/admin/views/notes/tmpl/default_foot.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + pagination->getListFooter(); ?> + \ No newline at end of file diff --git a/admin/views/notes/tmpl/default_head.php b/admin/views/notes/tmpl/default_head.php new file mode 100644 index 0000000..45dae8a --- /dev/null +++ b/admin/views/notes/tmpl/default_head.php @@ -0,0 +1,59 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + canEdit&& $this->canState): ?> + + listDirn, $this->listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?> + + + + + + + ▾ + + + ■ + + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + canState): ?> + + listDirn, $this->listOrder); ?> + + + + + + + + listDirn, $this->listOrder); ?> + + \ No newline at end of file diff --git a/admin/views/notes/tmpl/default_toolbar.php b/admin/views/notes/tmpl/default_toolbar.php new file mode 100644 index 0000000..77747da --- /dev/null +++ b/admin/views/notes/tmpl/default_toolbar.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
+ +
+ + +
+
+ + pagination->getLimitBox(); ?> +
+
+ + +
+
+ + +
+
+
\ No newline at end of file diff --git a/admin/views/notes/tmpl/index.html b/admin/views/notes/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/notes/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/notes/view.html.php b/admin/views/notes/view.html.php new file mode 100644 index 0000000..db500b9 --- /dev/null +++ b/admin/views/notes/view.html.php @@ -0,0 +1,319 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Getbible Html View class for the Notes + */ +class GetbibleViewNotes extends HtmlView +{ + /** + * Notes view display method + * @return void + */ + function display($tpl = null) + { + if ($this->getLayout() !== 'modal') + { + // Include helper submenu + GetbibleHelper::addSubmenu('notes'); + } + + // Assign data to the view + $this->items = $this->get('Items'); + $this->pagination = $this->get('Pagination'); + $this->state = $this->get('State'); + $this->user = JFactory::getUser(); + // Load the filter form from xml. + $this->filterForm = $this->get('FilterForm'); + // Load the active filters. + $this->activeFilters = $this->get('ActiveFilters'); + // Add the list ordering clause. + $this->listOrder = $this->escape($this->state->get('list.ordering', 'a.id')); + $this->listDirn = $this->escape($this->state->get('list.direction', 'DESC')); + $this->saveOrder = $this->listOrder == 'a.ordering'; + // set the return here value + $this->return_here = urlencode(base64_encode((string) JUri::getInstance())); + // get global action permissions + $this->canDo = GetbibleHelper::getActions('note'); + $this->canEdit = $this->canDo->get('note.edit'); + $this->canState = $this->canDo->get('note.edit.state'); + $this->canCreate = $this->canDo->get('note.create'); + $this->canDelete = $this->canDo->get('note.delete'); + $this->canBatch = $this->canDo->get('core.batch'); + + // We don't need toolbar in the modal window. + if ($this->getLayout() !== 'modal') + { + $this->addToolbar(); + $this->sidebar = JHtmlSidebar::render(); + // load the batch html + if ($this->canCreate && $this->canEdit && $this->canState) + { + $this->batchDisplay = JHtmlBatch_::render(); + } + } + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JToolBarHelper::title(JText::_('COM_GETBIBLE_NOTES'), 'file'); + JHtmlSidebar::setAction('index.php?option=com_getbible&view=notes'); + JFormHelper::addFieldPath(JPATH_COMPONENT . '/models/fields'); + + if ($this->canCreate) + { + JToolBarHelper::addNew('note.add'); + } + + // Only load if there are items + if (GetbibleHelper::checkArray($this->items)) + { + if ($this->canEdit) + { + JToolBarHelper::editList('note.edit'); + } + + if ($this->canState) + { + JToolBarHelper::publishList('notes.publish'); + JToolBarHelper::unpublishList('notes.unpublish'); + JToolBarHelper::archiveList('notes.archive'); + + if ($this->canDo->get('core.admin')) + { + JToolBarHelper::checkin('notes.checkin'); + } + } + + // Add a batch button + if ($this->canBatch && $this->canCreate && $this->canEdit && $this->canState) + { + // Get the toolbar object instance + $bar = JToolBar::getInstance('toolbar'); + // set the batch button name + $title = JText::_('JTOOLBAR_BATCH'); + // Instantiate a new JLayoutFile instance and render the batch button + $layout = new JLayoutFile('joomla.toolbar.batch'); + // add the button to the page + $dhtml = $layout->render(array('title' => $title)); + $bar->appendButton('Custom', $dhtml, 'batch'); + } + + if ($this->state->get('filter.published') == -2 && ($this->canState && $this->canDelete)) + { + JToolbarHelper::deleteList('', 'notes.delete', 'JTOOLBAR_EMPTY_TRASH'); + } + elseif ($this->canState && $this->canDelete) + { + JToolbarHelper::trash('notes.trash'); + } + } + + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('notes'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + + // add the options comp button + if ($this->canDo->get('core.admin') || $this->canDo->get('core.options')) + { + JToolBarHelper::preferences('com_getbible'); + } + + // Only load published batch if state and batch is allowed + if ($this->canState && $this->canBatch) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_STATE'), + 'batch[published]', + JHtml::_('select.options', JHtml::_('jgrid.publishedOptions', array('all' => false)), 'value', 'text', '', true) + ); + } + + // Only load Book Nr batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Book Nr Selection + $this->book_nrOptions = JFormHelper::loadFieldType('notesfilterbooknr')->options; + // We do some sanitation for Book Nr filter + if (GetbibleHelper::checkArray($this->book_nrOptions) && + isset($this->book_nrOptions[0]->value) && + !GetbibleHelper::checkString($this->book_nrOptions[0]->value)) + { + unset($this->book_nrOptions[0]); + } + // Book Nr Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_NOTE_BOOK_NR_LABEL').' -', + 'batch[book_nr]', + JHtml::_('select.options', $this->book_nrOptions, 'value', 'text') + ); + } + + // Only load Linker Name batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Linker Name Selection + $this->linkerNameOptions = JFormHelper::loadFieldType('Linkers')->options; + // We do some sanitation for Linker Name filter + if (GetbibleHelper::checkArray($this->linkerNameOptions) && + isset($this->linkerNameOptions[0]->value) && + !GetbibleHelper::checkString($this->linkerNameOptions[0]->value)) + { + unset($this->linkerNameOptions[0]); + } + // Linker Name Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_NOTE_LINKER_LABEL').' -', + 'batch[linker]', + JHtml::_('select.options', $this->linkerNameOptions, 'value', 'text') + ); + } + + // Only load Access batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Access Selection + $this->accessOptions = JFormHelper::loadFieldType('notesfilteraccess')->options; + // We do some sanitation for Access filter + if (GetbibleHelper::checkArray($this->accessOptions) && + isset($this->accessOptions[0]->value) && + !GetbibleHelper::checkString($this->accessOptions[0]->value)) + { + unset($this->accessOptions[0]); + } + // Access Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_NOTE_ACCESS_LABEL').' -', + 'batch[access]', + JHtml::_('select.options', $this->accessOptions, 'value', 'text') + ); + } + + // Only load Verse batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Verse Selection + $this->verseOptions = JFormHelper::loadFieldType('notesfilterverse')->options; + // We do some sanitation for Verse filter + if (GetbibleHelper::checkArray($this->verseOptions) && + isset($this->verseOptions[0]->value) && + !GetbibleHelper::checkString($this->verseOptions[0]->value)) + { + unset($this->verseOptions[0]); + } + // Verse Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_NOTE_VERSE_LABEL').' -', + 'batch[verse]', + JHtml::_('select.options', $this->verseOptions, 'value', 'text') + ); + } + + // Only load Chapter batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Chapter Selection + $this->chapterOptions = JFormHelper::loadFieldType('notesfilterchapter')->options; + // We do some sanitation for Chapter filter + if (GetbibleHelper::checkArray($this->chapterOptions) && + isset($this->chapterOptions[0]->value) && + !GetbibleHelper::checkString($this->chapterOptions[0]->value)) + { + unset($this->chapterOptions[0]); + } + // Chapter Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_NOTE_CHAPTER_LABEL').' -', + 'batch[chapter]', + JHtml::_('select.options', $this->chapterOptions, 'value', 'text') + ); + } + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_('COM_GETBIBLE_NOTES')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/notes.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 50) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Returns an array of fields the table can be sorted by + * + * @return array Array containing the field name to sort by as the key and display text as value + */ + protected function getSortFields() + { + return array( + 'a.ordering' => JText::_('JGRID_HEADING_ORDERING'), + 'a.published' => JText::_('JSTATUS'), + 'a.book_nr' => JText::_('COM_GETBIBLE_NOTE_BOOK_NR_LABEL'), + 'g.name' => JText::_('COM_GETBIBLE_NOTE_LINKER_LABEL'), + 'a.access' => JText::_('COM_GETBIBLE_NOTE_ACCESS_LABEL'), + 'a.id' => JText::_('JGRID_HEADING_ID') + ); + } +} diff --git a/admin/views/open_ai_message/submitbutton.js b/admin/views/open_ai_message/submitbutton.js new file mode 100644 index 0000000..3c988c5 --- /dev/null +++ b/admin/views/open_ai_message/submitbutton.js @@ -0,0 +1,31 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +Joomla.submitbutton = function(task) +{ + if (task == ''){ + return false; + } else { + var action = task.split('.'); + if (action[1] == 'cancel' || action[1] == 'close' || document.formvalidator.isValid(document.getElementById("adminForm"))){ + Joomla.submitform(task, document.getElementById("adminForm")); + return true; + } else { + alert(Joomla.JText._('open_ai_message, some values are not acceptable.','Some values are unacceptable')); + return false; + } + } +} \ No newline at end of file diff --git a/admin/views/open_ai_message/tmpl/edit.php b/admin/views/open_ai_message/tmpl/edit.php new file mode 100644 index 0000000..f6227cb --- /dev/null +++ b/admin/views/open_ai_message/tmpl/edit.php @@ -0,0 +1,117 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/html'); +JHtml::_('behavior.formvalidator'); +JHtml::_('formbehavior.chosen', 'select'); +JHtml::_('behavior.keepalive'); +$componentParams = $this->params; // will be removed just use $this->params instead +?> + + diff --git a/admin/views/open_ai_message/tmpl/index.html b/admin/views/open_ai_message/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/open_ai_message/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/open_ai_message/view.html.php b/admin/views/open_ai_message/view.html.php new file mode 100644 index 0000000..2cf015d --- /dev/null +++ b/admin/views/open_ai_message/view.html.php @@ -0,0 +1,203 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Open_ai_message Html View class + */ +class GetbibleViewOpen_ai_message extends HtmlView +{ + /** + * display method of View + * @return void + */ + public function display($tpl = null) + { + // set params + $this->params = JComponentHelper::getParams('com_getbible'); + // Assign the variables + $this->form = $this->get('Form'); + $this->item = $this->get('Item'); + $this->script = $this->get('Script'); + $this->state = $this->get('State'); + // get action permissions + $this->canDo = GetbibleHelper::getActions('open_ai_message', $this->item); + // get input + $jinput = JFactory::getApplication()->input; + $this->ref = $jinput->get('ref', 0, 'word'); + $this->refid = $jinput->get('refid', 0, 'int'); + $return = $jinput->get('return', null, 'base64'); + // set the referral string + $this->referral = ''; + if ($this->refid && $this->ref) + { + // return to the item that referred to this item + $this->referral = '&ref=' . (string)$this->ref . '&refid=' . (int)$this->refid; + } + elseif($this->ref) + { + // return to the list view that referred to this item + $this->referral = '&ref=' . (string)$this->ref; + } + // check return value + if (!is_null($return)) + { + // add the return value + $this->referral .= '&return=' . (string)$return; + } + + // Set the toolbar + $this->addToolBar(); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JFactory::getApplication()->input->set('hidemainmenu', true); + $user = JFactory::getUser(); + $userId = $user->id; + $isNew = $this->item->id == 0; + + JToolbarHelper::title( JText::_($isNew ? 'COM_GETBIBLE_OPEN_AI_MESSAGE_NEW' : 'COM_GETBIBLE_OPEN_AI_MESSAGE_EDIT'), 'pencil-2 article-add'); + // Built the actions for new and existing records. + if (GetbibleHelper::checkString($this->referral)) + { + if ($this->canDo->get('open_ai_message.create') && $isNew) + { + // We can create the record. + JToolBarHelper::save('open_ai_message.save', 'JTOOLBAR_SAVE'); + } + elseif ($this->canDo->get('open_ai_message.edit')) + { + // We can save the record. + JToolBarHelper::save('open_ai_message.save', 'JTOOLBAR_SAVE'); + } + if ($isNew) + { + // Do not creat but cancel. + JToolBarHelper::cancel('open_ai_message.cancel', 'JTOOLBAR_CANCEL'); + } + else + { + // We can close it. + JToolBarHelper::cancel('open_ai_message.cancel', 'JTOOLBAR_CLOSE'); + } + } + else + { + if ($isNew) + { + // For new records, check the create permission. + if ($this->canDo->get('open_ai_message.create')) + { + JToolBarHelper::apply('open_ai_message.apply', 'JTOOLBAR_APPLY'); + JToolBarHelper::save('open_ai_message.save', 'JTOOLBAR_SAVE'); + JToolBarHelper::custom('open_ai_message.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false); + }; + JToolBarHelper::cancel('open_ai_message.cancel', 'JTOOLBAR_CANCEL'); + } + else + { + if ($this->canDo->get('open_ai_message.edit')) + { + // We can save the new record + JToolBarHelper::apply('open_ai_message.apply', 'JTOOLBAR_APPLY'); + JToolBarHelper::save('open_ai_message.save', 'JTOOLBAR_SAVE'); + // We can save this record, but check the create permission to see + // if we can return to make a new one. + if ($this->canDo->get('open_ai_message.create')) + { + JToolBarHelper::custom('open_ai_message.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false); + } + } + $canVersion = ($this->canDo->get('core.version') && $this->canDo->get('open_ai_message.version')); + if ($this->state->params->get('save_history', 1) && $this->canDo->get('open_ai_message.edit') && $canVersion) + { + JToolbarHelper::versions('com_getbible.open_ai_message', $this->item->id); + } + if ($this->canDo->get('open_ai_message.create')) + { + JToolBarHelper::custom('open_ai_message.save2copy', 'save-copy.png', 'save-copy_f2.png', 'JTOOLBAR_SAVE_AS_COPY', false); + } + JToolBarHelper::cancel('open_ai_message.cancel', 'JTOOLBAR_CLOSE'); + } + } + JToolbarHelper::divider(); + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('open_ai_message'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 30) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true, 30); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + $isNew = ($this->item->id < 1); + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_($isNew ? 'COM_GETBIBLE_OPEN_AI_MESSAGE_NEW' : 'COM_GETBIBLE_OPEN_AI_MESSAGE_EDIT')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/open_ai_message.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + $this->document->addScript(JURI::root() . $this->script, (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + $this->document->addScript(JURI::root() . "administrator/components/com_getbible/views/open_ai_message/submitbutton.js", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + JText::script('view not acceptable. Error'); + } +} diff --git a/admin/views/open_ai_messages/index.html b/admin/views/open_ai_messages/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/open_ai_messages/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/open_ai_messages/tmpl/default.php b/admin/views/open_ai_messages/tmpl/default.php new file mode 100644 index 0000000..644446d --- /dev/null +++ b/admin/views/open_ai_messages/tmpl/default.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::_('behavior.multiselect'); +JHtml::_('dropdown.init'); +JHtml::_('formbehavior.chosen', '.multipleAccessLevels', null, array('placeholder_text_multiple' => '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_ACCESS') . ' -')); +JHtml::_('formbehavior.chosen', 'select'); +if ($this->saveOrder) +{ + $saveOrderingUrl = 'index.php?option=com_getbible&task=open_ai_messages.saveOrderAjax&tmpl=component'; + JHtml::_('sortablelist.sortable', 'open_ai_messageList', 'adminForm', strtolower($this->listDirn), $saveOrderingUrl); +} +?> +
+sidebar)): ?> +
+ sidebar; ?> +
+
+ +
+ + $this)); +?> +items)): ?> +
+ +
+ + + loadTemplate('head');?> + loadTemplate('foot');?> + loadTemplate('body');?> +
+ + canCreate && $this->canEdit) : ?> + JText::_('COM_GETBIBLE_OPEN_AI_MESSAGES_BATCH_OPTIONS'), + 'footer' => $this->loadTemplate('batch_footer') + ), + $this->loadTemplate('batch_body') + ); ?> + + +
+ + + + diff --git a/admin/views/open_ai_messages/tmpl/default_batch_body.php b/admin/views/open_ai_messages/tmpl/default_batch_body.php new file mode 100644 index 0000000..2214298 --- /dev/null +++ b/admin/views/open_ai_messages/tmpl/default_batch_body.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + +

+batchDisplay; ?> \ No newline at end of file diff --git a/admin/views/open_ai_messages/tmpl/default_batch_footer.php b/admin/views/open_ai_messages/tmpl/default_batch_footer.php new file mode 100644 index 0000000..14602de --- /dev/null +++ b/admin/views/open_ai_messages/tmpl/default_batch_footer.php @@ -0,0 +1,29 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + + + \ No newline at end of file diff --git a/admin/views/open_ai_messages/tmpl/default_body.php b/admin/views/open_ai_messages/tmpl/default_body.php new file mode 100644 index 0000000..d7311d0 --- /dev/null +++ b/admin/views/open_ai_messages/tmpl/default_body.php @@ -0,0 +1,118 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +$edit = "index.php?option=com_getbible&view=open_ai_messages&task=open_ai_message.edit"; + +?> +items as $i => $item): ?> + user->authorise('core.manage', 'com_checkin') || $item->checked_out == $this->user->id || $item->checked_out == 0; + $userChkOut = JFactory::getUser($item->checked_out); + $canDo = GetbibleHelper::getActions('open_ai_message',$item,'open_ai_messages'); + ?> + + + get('open_ai_message.edit.state')): ?> + saveOrder) + { + $iconClass = ' inactive tip-top" hasTooltip" title="' . JHtml::tooltipText('JORDERINGDISABLED'); + } + ?> + + + + saveOrder) : ?> + + + + ⋮ + + + + get('open_ai_message.edit')): ?> + checked_out) : ?> + + id); ?> + + □ + + + id); ?> + + + □ + + + +
+ get('open_ai_message.edit')): ?> + role); ?> + checked_out): ?> + name, $item->checked_out_time, 'open_ai_messages.', $canCheckin); ?> + + + role); ?> + +
+ + +
+ user->authorise('open_ai_response.edit', 'com_getbible.open_ai_response.' . (int) $item->open_ai_response_id)): ?> + escape($item->open_ai_response_response_id); ?> + + escape($item->open_ai_response_response_id); ?> + +
+ + +
+ user->authorise('prompt.edit', 'com_getbible.prompt.' . (int) $item->prompt_id)): ?> + escape($item->prompt_name); ?> + + escape($item->prompt_name); ?> + +
+ + + source); ?> + + + get('open_ai_message.edit.state')) : ?> + checked_out) : ?> + + published, $i, 'open_ai_messages.', true, 'cb'); ?> + + published, $i, 'open_ai_messages.', false, 'cb'); ?> + + + published, $i, 'open_ai_messages.', true, 'cb'); ?> + + + published, $i, 'open_ai_messages.', false, 'cb'); ?> + + + + id; ?> + + + \ No newline at end of file diff --git a/admin/views/open_ai_messages/tmpl/default_foot.php b/admin/views/open_ai_messages/tmpl/default_foot.php new file mode 100644 index 0000000..290760a --- /dev/null +++ b/admin/views/open_ai_messages/tmpl/default_foot.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + pagination->getListFooter(); ?> + \ No newline at end of file diff --git a/admin/views/open_ai_messages/tmpl/default_head.php b/admin/views/open_ai_messages/tmpl/default_head.php new file mode 100644 index 0000000..2f4f6d4 --- /dev/null +++ b/admin/views/open_ai_messages/tmpl/default_head.php @@ -0,0 +1,62 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + canEdit&& $this->canState): ?> + + listDirn, $this->listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?> + + + + + + + ▾ + + + ■ + + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + canState): ?> + + listDirn, $this->listOrder); ?> + + + + + + + + listDirn, $this->listOrder); ?> + + \ No newline at end of file diff --git a/admin/views/open_ai_messages/tmpl/default_toolbar.php b/admin/views/open_ai_messages/tmpl/default_toolbar.php new file mode 100644 index 0000000..665453b --- /dev/null +++ b/admin/views/open_ai_messages/tmpl/default_toolbar.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
+ +
+ + +
+
+ + pagination->getLimitBox(); ?> +
+
+ + +
+
+ + +
+
+
\ No newline at end of file diff --git a/admin/views/open_ai_messages/tmpl/index.html b/admin/views/open_ai_messages/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/open_ai_messages/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/open_ai_messages/view.html.php b/admin/views/open_ai_messages/view.html.php new file mode 100644 index 0000000..51522f9 --- /dev/null +++ b/admin/views/open_ai_messages/view.html.php @@ -0,0 +1,310 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Getbible Html View class for the Open_ai_messages + */ +class GetbibleViewOpen_ai_messages extends HtmlView +{ + /** + * Open_ai_messages view display method + * @return void + */ + function display($tpl = null) + { + if ($this->getLayout() !== 'modal') + { + // Include helper submenu + GetbibleHelper::addSubmenu('open_ai_messages'); + } + + // Assign data to the view + $this->items = $this->get('Items'); + $this->pagination = $this->get('Pagination'); + $this->state = $this->get('State'); + $this->user = JFactory::getUser(); + // Load the filter form from xml. + $this->filterForm = $this->get('FilterForm'); + // Load the active filters. + $this->activeFilters = $this->get('ActiveFilters'); + // Add the list ordering clause. + $this->listOrder = $this->escape($this->state->get('list.ordering', 'a.id')); + $this->listDirn = $this->escape($this->state->get('list.direction', 'desc')); + $this->saveOrder = $this->listOrder == 'a.ordering'; + // set the return here value + $this->return_here = urlencode(base64_encode((string) JUri::getInstance())); + // get global action permissions + $this->canDo = GetbibleHelper::getActions('open_ai_message'); + $this->canEdit = $this->canDo->get('open_ai_message.edit'); + $this->canState = $this->canDo->get('open_ai_message.edit.state'); + $this->canCreate = $this->canDo->get('open_ai_message.create'); + $this->canDelete = $this->canDo->get('open_ai_message.delete'); + $this->canBatch = $this->canDo->get('core.batch'); + + // We don't need toolbar in the modal window. + if ($this->getLayout() !== 'modal') + { + $this->addToolbar(); + $this->sidebar = JHtmlSidebar::render(); + // load the batch html + if ($this->canCreate && $this->canEdit && $this->canState) + { + $this->batchDisplay = JHtmlBatch_::render(); + } + } + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JToolBarHelper::title(JText::_('COM_GETBIBLE_OPEN_AI_MESSAGES'), 'comment'); + JHtmlSidebar::setAction('index.php?option=com_getbible&view=open_ai_messages'); + JFormHelper::addFieldPath(JPATH_COMPONENT . '/models/fields'); + + if ($this->canCreate) + { + JToolBarHelper::addNew('open_ai_message.add'); + } + + // Only load if there are items + if (GetbibleHelper::checkArray($this->items)) + { + if ($this->canEdit) + { + JToolBarHelper::editList('open_ai_message.edit'); + } + + if ($this->canState) + { + JToolBarHelper::publishList('open_ai_messages.publish'); + JToolBarHelper::unpublishList('open_ai_messages.unpublish'); + JToolBarHelper::archiveList('open_ai_messages.archive'); + + if ($this->canDo->get('core.admin')) + { + JToolBarHelper::checkin('open_ai_messages.checkin'); + } + } + + // Add a batch button + if ($this->canBatch && $this->canCreate && $this->canEdit && $this->canState) + { + // Get the toolbar object instance + $bar = JToolBar::getInstance('toolbar'); + // set the batch button name + $title = JText::_('JTOOLBAR_BATCH'); + // Instantiate a new JLayoutFile instance and render the batch button + $layout = new JLayoutFile('joomla.toolbar.batch'); + // add the button to the page + $dhtml = $layout->render(array('title' => $title)); + $bar->appendButton('Custom', $dhtml, 'batch'); + } + + if ($this->state->get('filter.published') == -2 && ($this->canState && $this->canDelete)) + { + JToolbarHelper::deleteList('', 'open_ai_messages.delete', 'JTOOLBAR_EMPTY_TRASH'); + } + elseif ($this->canState && $this->canDelete) + { + JToolbarHelper::trash('open_ai_messages.trash'); + } + } + + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('open_ai_messages'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + + // add the options comp button + if ($this->canDo->get('core.admin') || $this->canDo->get('core.options')) + { + JToolBarHelper::preferences('com_getbible'); + } + + // Only load published batch if state and batch is allowed + if ($this->canState && $this->canBatch) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_STATE'), + 'batch[published]', + JHtml::_('select.options', JHtml::_('jgrid.publishedOptions', array('all' => false)), 'value', 'text', '', true) + ); + } + + // Only load access batch if create, edit and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_ACCESS'), + 'batch[access]', + JHtml::_('select.options', JHtml::_('access.assetgroups'), 'value', 'text') + ); + } + + // Only load Role batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Role Selection + $this->roleOptions = JFormHelper::loadFieldType('openaimessagesfilterrole')->options; + // We do some sanitation for Role filter + if (GetbibleHelper::checkArray($this->roleOptions) && + isset($this->roleOptions[0]->value) && + !GetbibleHelper::checkString($this->roleOptions[0]->value)) + { + unset($this->roleOptions[0]); + } + // Role Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_OPEN_AI_MESSAGE_ROLE_LABEL').' -', + 'batch[role]', + JHtml::_('select.options', $this->roleOptions, 'value', 'text') + ); + } + + // Only load Open Ai Response Response Id batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Open Ai Response Response Id Selection + $this->open_ai_responseResponse_idOptions = JFormHelper::loadFieldType('Openairesponses')->options; + // We do some sanitation for Open Ai Response Response Id filter + if (GetbibleHelper::checkArray($this->open_ai_responseResponse_idOptions) && + isset($this->open_ai_responseResponse_idOptions[0]->value) && + !GetbibleHelper::checkString($this->open_ai_responseResponse_idOptions[0]->value)) + { + unset($this->open_ai_responseResponse_idOptions[0]); + } + // Open Ai Response Response Id Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_OPEN_AI_MESSAGE_OPEN_AI_RESPONSE_LABEL').' -', + 'batch[open_ai_response]', + JHtml::_('select.options', $this->open_ai_responseResponse_idOptions, 'value', 'text') + ); + } + + // Only load Prompt Name batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Prompt Name Selection + $this->promptNameOptions = JFormHelper::loadFieldType('Prompts')->options; + // We do some sanitation for Prompt Name filter + if (GetbibleHelper::checkArray($this->promptNameOptions) && + isset($this->promptNameOptions[0]->value) && + !GetbibleHelper::checkString($this->promptNameOptions[0]->value)) + { + unset($this->promptNameOptions[0]); + } + // Prompt Name Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_OPEN_AI_MESSAGE_PROMPT_LABEL').' -', + 'batch[prompt]', + JHtml::_('select.options', $this->promptNameOptions, 'value', 'text') + ); + } + + // Only load Source batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Source Selection + $this->sourceOptions = JFormHelper::loadFieldType('openaimessagesfiltersource')->options; + // We do some sanitation for Source filter + if (GetbibleHelper::checkArray($this->sourceOptions) && + isset($this->sourceOptions[0]->value) && + !GetbibleHelper::checkString($this->sourceOptions[0]->value)) + { + unset($this->sourceOptions[0]); + } + // Source Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_OPEN_AI_MESSAGE_SOURCE_LABEL').' -', + 'batch[source]', + JHtml::_('select.options', $this->sourceOptions, 'value', 'text') + ); + } + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_('COM_GETBIBLE_OPEN_AI_MESSAGES')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/open_ai_messages.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 50) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Returns an array of fields the table can be sorted by + * + * @return array Array containing the field name to sort by as the key and display text as value + */ + protected function getSortFields() + { + return array( + 'a.ordering' => JText::_('JGRID_HEADING_ORDERING'), + 'a.published' => JText::_('JSTATUS'), + 'a.role' => JText::_('COM_GETBIBLE_OPEN_AI_MESSAGE_ROLE_LABEL'), + 'g.response_id' => JText::_('COM_GETBIBLE_OPEN_AI_MESSAGE_OPEN_AI_RESPONSE_LABEL'), + 'h.name' => JText::_('COM_GETBIBLE_OPEN_AI_MESSAGE_PROMPT_LABEL'), + 'a.source' => JText::_('COM_GETBIBLE_OPEN_AI_MESSAGE_SOURCE_LABEL'), + 'a.id' => JText::_('JGRID_HEADING_ID') + ); + } +} diff --git a/admin/views/open_ai_response/submitbutton.js b/admin/views/open_ai_response/submitbutton.js new file mode 100644 index 0000000..975edef --- /dev/null +++ b/admin/views/open_ai_response/submitbutton.js @@ -0,0 +1,31 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +Joomla.submitbutton = function(task) +{ + if (task == ''){ + return false; + } else { + var action = task.split('.'); + if (action[1] == 'cancel' || action[1] == 'close' || document.formvalidator.isValid(document.getElementById("adminForm"))){ + Joomla.submitform(task, document.getElementById("adminForm")); + return true; + } else { + alert(Joomla.JText._('open_ai_response, some values are not acceptable.','Some values are unacceptable')); + return false; + } + } +} \ No newline at end of file diff --git a/admin/views/open_ai_response/tmpl/edit.php b/admin/views/open_ai_response/tmpl/edit.php new file mode 100644 index 0000000..012a0b8 --- /dev/null +++ b/admin/views/open_ai_response/tmpl/edit.php @@ -0,0 +1,146 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/html'); +JHtml::_('behavior.formvalidator'); +JHtml::_('formbehavior.chosen', 'select'); +JHtml::_('behavior.keepalive'); +$componentParams = $this->params; // will be removed just use $this->params instead +?> + + diff --git a/admin/views/open_ai_response/tmpl/index.html b/admin/views/open_ai_response/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/open_ai_response/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/open_ai_response/view.html.php b/admin/views/open_ai_response/view.html.php new file mode 100644 index 0000000..3b6db38 --- /dev/null +++ b/admin/views/open_ai_response/view.html.php @@ -0,0 +1,230 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Open_ai_response Html View class + */ +class GetbibleViewOpen_ai_response extends HtmlView +{ + /** + * display method of View + * @return void + */ + public function display($tpl = null) + { + // set params + $this->params = JComponentHelper::getParams('com_getbible'); + // Assign the variables + $this->form = $this->get('Form'); + $this->item = $this->get('Item'); + $this->script = $this->get('Script'); + $this->state = $this->get('State'); + // get action permissions + $this->canDo = GetbibleHelper::getActions('open_ai_response', $this->item); + // get input + $jinput = JFactory::getApplication()->input; + $this->ref = $jinput->get('ref', 0, 'word'); + $this->refid = $jinput->get('refid', 0, 'int'); + $return = $jinput->get('return', null, 'base64'); + // set the referral string + $this->referral = ''; + if ($this->refid && $this->ref) + { + // return to the item that referred to this item + $this->referral = '&ref=' . (string)$this->ref . '&refid=' . (int)$this->refid; + } + elseif($this->ref) + { + // return to the list view that referred to this item + $this->referral = '&ref=' . (string)$this->ref; + } + // check return value + if (!is_null($return)) + { + // add the return value + $this->referral .= '&return=' . (string)$return; + } + + // Get Linked view data + $this->vvymessage = $this->get('Vvymessage'); + + // Set the toolbar + $this->addToolBar(); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JFactory::getApplication()->input->set('hidemainmenu', true); + $user = JFactory::getUser(); + $userId = $user->id; + $isNew = $this->item->id == 0; + + JToolbarHelper::title( JText::_($isNew ? 'COM_GETBIBLE_OPEN_AI_RESPONSE_NEW' : 'COM_GETBIBLE_OPEN_AI_RESPONSE_EDIT'), 'pencil-2 article-add'); + // Built the actions for new and existing records. + if (GetbibleHelper::checkString($this->referral)) + { + if ($this->canDo->get('open_ai_response.create') && $isNew) + { + // We can create the record. + JToolBarHelper::save('open_ai_response.save', 'JTOOLBAR_SAVE'); + } + elseif ($this->canDo->get('open_ai_response.edit')) + { + // We can save the record. + JToolBarHelper::save('open_ai_response.save', 'JTOOLBAR_SAVE'); + } + if ($isNew) + { + // Do not creat but cancel. + JToolBarHelper::cancel('open_ai_response.cancel', 'JTOOLBAR_CANCEL'); + } + else + { + // We can close it. + JToolBarHelper::cancel('open_ai_response.cancel', 'JTOOLBAR_CLOSE'); + } + } + else + { + if ($isNew) + { + // For new records, check the create permission. + if ($this->canDo->get('open_ai_response.create')) + { + JToolBarHelper::apply('open_ai_response.apply', 'JTOOLBAR_APPLY'); + JToolBarHelper::save('open_ai_response.save', 'JTOOLBAR_SAVE'); + JToolBarHelper::custom('open_ai_response.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false); + }; + JToolBarHelper::cancel('open_ai_response.cancel', 'JTOOLBAR_CANCEL'); + } + else + { + if ($this->canDo->get('open_ai_response.edit')) + { + // We can save the new record + JToolBarHelper::apply('open_ai_response.apply', 'JTOOLBAR_APPLY'); + JToolBarHelper::save('open_ai_response.save', 'JTOOLBAR_SAVE'); + // We can save this record, but check the create permission to see + // if we can return to make a new one. + if ($this->canDo->get('open_ai_response.create')) + { + JToolBarHelper::custom('open_ai_response.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false); + } + } + $canVersion = ($this->canDo->get('core.version') && $this->canDo->get('open_ai_response.version')); + if ($this->state->params->get('save_history', 1) && $this->canDo->get('open_ai_response.edit') && $canVersion) + { + JToolbarHelper::versions('com_getbible.open_ai_response', $this->item->id); + } + if ($this->canDo->get('open_ai_response.create')) + { + JToolBarHelper::custom('open_ai_response.save2copy', 'save-copy.png', 'save-copy_f2.png', 'JTOOLBAR_SAVE_AS_COPY', false); + } + JToolBarHelper::cancel('open_ai_response.cancel', 'JTOOLBAR_CLOSE'); + } + } + JToolbarHelper::divider(); + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('open_ai_response'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 30) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true, 30); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + $isNew = ($this->item->id < 1); + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_($isNew ? 'COM_GETBIBLE_OPEN_AI_RESPONSE_NEW' : 'COM_GETBIBLE_OPEN_AI_RESPONSE_EDIT')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/open_ai_response.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + + // Add the CSS for Footable. + JHtml::_('stylesheet', 'media/com_getbible/footable-v2/css/footable.core.min.css', ['version' => 'auto']); + + // Use the Metro Style + if (!isset($this->fooTableStyle) || 0 == $this->fooTableStyle) + { + JHtml::_('stylesheet', 'media/com_getbible/footable-v2/css/footable.metro.min.css', ['version' => 'auto']); + } + // Use the Legacy Style. + elseif (isset($this->fooTableStyle) && 1 == $this->fooTableStyle) + { + JHtml::_('stylesheet', 'media/com_getbible/footable-v2/css/footable.standalone.min.css', ['version' => 'auto']); + } + + // Add the JavaScript for Footable + JHtml::_('script', 'media/com_getbible/footable-v2/js/footable.js', ['version' => 'auto']); + JHtml::_('script', 'media/com_getbible/footable-v2/js/footable.sort.js', ['version' => 'auto']); + JHtml::_('script', 'media/com_getbible/footable-v2/js/footable.filter.js', ['version' => 'auto']); + JHtml::_('script', 'media/com_getbible/footable-v2/js/footable.paginate.js', ['version' => 'auto']); + + $footable = "jQuery(document).ready(function() { jQuery(function () { jQuery('.footable').footable(); }); jQuery('.nav-tabs').on('click', 'li', function() { setTimeout(tableFix, 10); }); }); function tableFix() { jQuery('.footable').trigger('footable_resize'); }"; + $this->document->addScriptDeclaration($footable); + + $this->document->addScript(JURI::root() . $this->script, (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + $this->document->addScript(JURI::root() . "administrator/components/com_getbible/views/open_ai_response/submitbutton.js", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + JText::script('view not acceptable. Error'); + } +} diff --git a/admin/views/open_ai_responses/index.html b/admin/views/open_ai_responses/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/open_ai_responses/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/open_ai_responses/tmpl/default.php b/admin/views/open_ai_responses/tmpl/default.php new file mode 100644 index 0000000..8430029 --- /dev/null +++ b/admin/views/open_ai_responses/tmpl/default.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::_('behavior.multiselect'); +JHtml::_('dropdown.init'); +JHtml::_('formbehavior.chosen', '.multipleAccessLevels', null, array('placeholder_text_multiple' => '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_ACCESS') . ' -')); +JHtml::_('formbehavior.chosen', 'select'); +if ($this->saveOrder) +{ + $saveOrderingUrl = 'index.php?option=com_getbible&task=open_ai_responses.saveOrderAjax&tmpl=component'; + JHtml::_('sortablelist.sortable', 'open_ai_responseList', 'adminForm', strtolower($this->listDirn), $saveOrderingUrl); +} +?> +
+sidebar)): ?> +
+ sidebar; ?> +
+
+ +
+ + $this)); +?> +items)): ?> +
+ +
+ + + loadTemplate('head');?> + loadTemplate('foot');?> + loadTemplate('body');?> +
+ + canCreate && $this->canEdit) : ?> + JText::_('COM_GETBIBLE_OPEN_AI_RESPONSES_BATCH_OPTIONS'), + 'footer' => $this->loadTemplate('batch_footer') + ), + $this->loadTemplate('batch_body') + ); ?> + + +
+ + + + diff --git a/admin/views/open_ai_responses/tmpl/default_batch_body.php b/admin/views/open_ai_responses/tmpl/default_batch_body.php new file mode 100644 index 0000000..ee5919d --- /dev/null +++ b/admin/views/open_ai_responses/tmpl/default_batch_body.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + +

+batchDisplay; ?> \ No newline at end of file diff --git a/admin/views/open_ai_responses/tmpl/default_batch_footer.php b/admin/views/open_ai_responses/tmpl/default_batch_footer.php new file mode 100644 index 0000000..0cb25d3 --- /dev/null +++ b/admin/views/open_ai_responses/tmpl/default_batch_footer.php @@ -0,0 +1,29 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + + + \ No newline at end of file diff --git a/admin/views/open_ai_responses/tmpl/default_body.php b/admin/views/open_ai_responses/tmpl/default_body.php new file mode 100644 index 0000000..7af3ea5 --- /dev/null +++ b/admin/views/open_ai_responses/tmpl/default_body.php @@ -0,0 +1,115 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +$edit = "index.php?option=com_getbible&view=open_ai_responses&task=open_ai_response.edit"; + +?> +items as $i => $item): ?> + user->authorise('core.manage', 'com_checkin') || $item->checked_out == $this->user->id || $item->checked_out == 0; + $userChkOut = JFactory::getUser($item->checked_out); + $canDo = GetbibleHelper::getActions('open_ai_response',$item,'open_ai_responses'); + ?> + + + get('open_ai_response.edit.state')): ?> + saveOrder) + { + $iconClass = ' inactive tip-top" hasTooltip" title="' . JHtml::tooltipText('JORDERINGDISABLED'); + } + ?> + + + + saveOrder) : ?> + + + + ⋮ + + + + get('open_ai_response.edit')): ?> + checked_out) : ?> + + id); ?> + + □ + + + id); ?> + + + □ + + + +
+ get('open_ai_response.edit')): ?> + escape($item->response_id); ?> + checked_out): ?> + name, $item->checked_out_time, 'open_ai_responses.', $canCheckin); ?> + + + escape($item->response_id); ?> + +
+ + +
+ user->authorise('prompt.edit', 'com_getbible.prompt.' . (int) $item->prompt_id)): ?> + escape($item->prompt_name); ?> + + escape($item->prompt_name); ?> + +
+ + + escape($item->response_object); ?> + + + escape($item->response_model); ?> + + + escape($item->total_tokens); ?> + + + get('open_ai_response.edit.state')) : ?> + checked_out) : ?> + + published, $i, 'open_ai_responses.', true, 'cb'); ?> + + published, $i, 'open_ai_responses.', false, 'cb'); ?> + + + published, $i, 'open_ai_responses.', true, 'cb'); ?> + + + published, $i, 'open_ai_responses.', false, 'cb'); ?> + + + + id; ?> + + + \ No newline at end of file diff --git a/admin/views/open_ai_responses/tmpl/default_foot.php b/admin/views/open_ai_responses/tmpl/default_foot.php new file mode 100644 index 0000000..6df0a9f --- /dev/null +++ b/admin/views/open_ai_responses/tmpl/default_foot.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + pagination->getListFooter(); ?> + \ No newline at end of file diff --git a/admin/views/open_ai_responses/tmpl/default_head.php b/admin/views/open_ai_responses/tmpl/default_head.php new file mode 100644 index 0000000..ca3f75d --- /dev/null +++ b/admin/views/open_ai_responses/tmpl/default_head.php @@ -0,0 +1,65 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + canEdit&& $this->canState): ?> + + listDirn, $this->listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?> + + + + + + + ▾ + + + ■ + + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + canState): ?> + + listDirn, $this->listOrder); ?> + + + + + + + + listDirn, $this->listOrder); ?> + + \ No newline at end of file diff --git a/admin/views/open_ai_responses/tmpl/default_toolbar.php b/admin/views/open_ai_responses/tmpl/default_toolbar.php new file mode 100644 index 0000000..ef1197e --- /dev/null +++ b/admin/views/open_ai_responses/tmpl/default_toolbar.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
+ +
+ + +
+
+ + pagination->getLimitBox(); ?> +
+
+ + +
+
+ + +
+
+
\ No newline at end of file diff --git a/admin/views/open_ai_responses/tmpl/index.html b/admin/views/open_ai_responses/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/open_ai_responses/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/open_ai_responses/view.html.php b/admin/views/open_ai_responses/view.html.php new file mode 100644 index 0000000..4d27453 --- /dev/null +++ b/admin/views/open_ai_responses/view.html.php @@ -0,0 +1,291 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Getbible Html View class for the Open_ai_responses + */ +class GetbibleViewOpen_ai_responses extends HtmlView +{ + /** + * Open_ai_responses view display method + * @return void + */ + function display($tpl = null) + { + if ($this->getLayout() !== 'modal') + { + // Include helper submenu + GetbibleHelper::addSubmenu('open_ai_responses'); + } + + // Assign data to the view + $this->items = $this->get('Items'); + $this->pagination = $this->get('Pagination'); + $this->state = $this->get('State'); + $this->user = JFactory::getUser(); + // Load the filter form from xml. + $this->filterForm = $this->get('FilterForm'); + // Load the active filters. + $this->activeFilters = $this->get('ActiveFilters'); + // Add the list ordering clause. + $this->listOrder = $this->escape($this->state->get('list.ordering', 'a.id')); + $this->listDirn = $this->escape($this->state->get('list.direction', 'desc')); + $this->saveOrder = $this->listOrder == 'a.ordering'; + // set the return here value + $this->return_here = urlencode(base64_encode((string) JUri::getInstance())); + // get global action permissions + $this->canDo = GetbibleHelper::getActions('open_ai_response'); + $this->canEdit = $this->canDo->get('open_ai_response.edit'); + $this->canState = $this->canDo->get('open_ai_response.edit.state'); + $this->canCreate = $this->canDo->get('open_ai_response.create'); + $this->canDelete = $this->canDo->get('open_ai_response.delete'); + $this->canBatch = $this->canDo->get('core.batch'); + + // We don't need toolbar in the modal window. + if ($this->getLayout() !== 'modal') + { + $this->addToolbar(); + $this->sidebar = JHtmlSidebar::render(); + // load the batch html + if ($this->canCreate && $this->canEdit && $this->canState) + { + $this->batchDisplay = JHtmlBatch_::render(); + } + } + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JToolBarHelper::title(JText::_('COM_GETBIBLE_OPEN_AI_RESPONSES'), 'reply'); + JHtmlSidebar::setAction('index.php?option=com_getbible&view=open_ai_responses'); + JFormHelper::addFieldPath(JPATH_COMPONENT . '/models/fields'); + + if ($this->canCreate) + { + JToolBarHelper::addNew('open_ai_response.add'); + } + + // Only load if there are items + if (GetbibleHelper::checkArray($this->items)) + { + if ($this->canEdit) + { + JToolBarHelper::editList('open_ai_response.edit'); + } + + if ($this->canState) + { + JToolBarHelper::publishList('open_ai_responses.publish'); + JToolBarHelper::unpublishList('open_ai_responses.unpublish'); + JToolBarHelper::archiveList('open_ai_responses.archive'); + + if ($this->canDo->get('core.admin')) + { + JToolBarHelper::checkin('open_ai_responses.checkin'); + } + } + + // Add a batch button + if ($this->canBatch && $this->canCreate && $this->canEdit && $this->canState) + { + // Get the toolbar object instance + $bar = JToolBar::getInstance('toolbar'); + // set the batch button name + $title = JText::_('JTOOLBAR_BATCH'); + // Instantiate a new JLayoutFile instance and render the batch button + $layout = new JLayoutFile('joomla.toolbar.batch'); + // add the button to the page + $dhtml = $layout->render(array('title' => $title)); + $bar->appendButton('Custom', $dhtml, 'batch'); + } + + if ($this->state->get('filter.published') == -2 && ($this->canState && $this->canDelete)) + { + JToolbarHelper::deleteList('', 'open_ai_responses.delete', 'JTOOLBAR_EMPTY_TRASH'); + } + elseif ($this->canState && $this->canDelete) + { + JToolbarHelper::trash('open_ai_responses.trash'); + } + } + + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('open_ai_responses'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + + // add the options comp button + if ($this->canDo->get('core.admin') || $this->canDo->get('core.options')) + { + JToolBarHelper::preferences('com_getbible'); + } + + // Only load published batch if state and batch is allowed + if ($this->canState && $this->canBatch) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_STATE'), + 'batch[published]', + JHtml::_('select.options', JHtml::_('jgrid.publishedOptions', array('all' => false)), 'value', 'text', '', true) + ); + } + + // Only load access batch if create, edit and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_ACCESS'), + 'batch[access]', + JHtml::_('select.options', JHtml::_('access.assetgroups'), 'value', 'text') + ); + } + + // Only load Response Id batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Response Id Selection + $this->response_idOptions = JFormHelper::loadFieldType('openairesponsesfilterresponseid')->options; + // We do some sanitation for Response Id filter + if (GetbibleHelper::checkArray($this->response_idOptions) && + isset($this->response_idOptions[0]->value) && + !GetbibleHelper::checkString($this->response_idOptions[0]->value)) + { + unset($this->response_idOptions[0]); + } + // Response Id Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_ID_LABEL').' -', + 'batch[response_id]', + JHtml::_('select.options', $this->response_idOptions, 'value', 'text') + ); + } + + // Only load Prompt Name batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Prompt Name Selection + $this->promptNameOptions = JFormHelper::loadFieldType('Prompts')->options; + // We do some sanitation for Prompt Name filter + if (GetbibleHelper::checkArray($this->promptNameOptions) && + isset($this->promptNameOptions[0]->value) && + !GetbibleHelper::checkString($this->promptNameOptions[0]->value)) + { + unset($this->promptNameOptions[0]); + } + // Prompt Name Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_OPEN_AI_RESPONSE_PROMPT_LABEL').' -', + 'batch[prompt]', + JHtml::_('select.options', $this->promptNameOptions, 'value', 'text') + ); + } + + // Only load Response Model batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Response Model Selection + $this->response_modelOptions = JFormHelper::loadFieldType('openairesponsesfilterresponsemodel')->options; + // We do some sanitation for Response Model filter + if (GetbibleHelper::checkArray($this->response_modelOptions) && + isset($this->response_modelOptions[0]->value) && + !GetbibleHelper::checkString($this->response_modelOptions[0]->value)) + { + unset($this->response_modelOptions[0]); + } + // Response Model Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_MODEL_LABEL').' -', + 'batch[response_model]', + JHtml::_('select.options', $this->response_modelOptions, 'value', 'text') + ); + } + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_('COM_GETBIBLE_OPEN_AI_RESPONSES')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/open_ai_responses.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 50) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Returns an array of fields the table can be sorted by + * + * @return array Array containing the field name to sort by as the key and display text as value + */ + protected function getSortFields() + { + return array( + 'a.ordering' => JText::_('JGRID_HEADING_ORDERING'), + 'a.published' => JText::_('JSTATUS'), + 'a.response_id' => JText::_('COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_ID_LABEL'), + 'g.name' => JText::_('COM_GETBIBLE_OPEN_AI_RESPONSE_PROMPT_LABEL'), + 'a.response_object' => JText::_('COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_OBJECT_LABEL'), + 'a.response_model' => JText::_('COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_MODEL_LABEL'), + 'a.total_tokens' => JText::_('COM_GETBIBLE_OPEN_AI_RESPONSE_TOTAL_TOKENS_LABEL'), + 'a.id' => JText::_('JGRID_HEADING_ID') + ); + } +} diff --git a/admin/views/password/submitbutton.js b/admin/views/password/submitbutton.js new file mode 100644 index 0000000..91edb6e --- /dev/null +++ b/admin/views/password/submitbutton.js @@ -0,0 +1,31 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +Joomla.submitbutton = function(task) +{ + if (task == ''){ + return false; + } else { + var action = task.split('.'); + if (action[1] == 'cancel' || action[1] == 'close' || document.formvalidator.isValid(document.getElementById("adminForm"))){ + Joomla.submitform(task, document.getElementById("adminForm")); + return true; + } else { + alert(Joomla.JText._('password, some values are not acceptable.','Some values are unacceptable')); + return false; + } + } +} \ No newline at end of file diff --git a/admin/views/password/tmpl/edit.php b/admin/views/password/tmpl/edit.php new file mode 100644 index 0000000..9cb982d --- /dev/null +++ b/admin/views/password/tmpl/edit.php @@ -0,0 +1,112 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/html'); +JHtml::_('behavior.formvalidator'); +JHtml::_('formbehavior.chosen', 'select'); +JHtml::_('behavior.keepalive'); +$componentParams = $this->params; // will be removed just use $this->params instead +?> + + diff --git a/admin/views/password/tmpl/index.html b/admin/views/password/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/password/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/password/view.html.php b/admin/views/password/view.html.php new file mode 100644 index 0000000..7f7bcc3 --- /dev/null +++ b/admin/views/password/view.html.php @@ -0,0 +1,198 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Password Html View class + */ +class GetbibleViewPassword extends HtmlView +{ + /** + * display method of View + * @return void + */ + public function display($tpl = null) + { + // set params + $this->params = JComponentHelper::getParams('com_getbible'); + // Assign the variables + $this->form = $this->get('Form'); + $this->item = $this->get('Item'); + $this->script = $this->get('Script'); + $this->state = $this->get('State'); + // get action permissions + $this->canDo = GetbibleHelper::getActions('password', $this->item); + // get input + $jinput = JFactory::getApplication()->input; + $this->ref = $jinput->get('ref', 0, 'word'); + $this->refid = $jinput->get('refid', 0, 'int'); + $return = $jinput->get('return', null, 'base64'); + // set the referral string + $this->referral = ''; + if ($this->refid && $this->ref) + { + // return to the item that referred to this item + $this->referral = '&ref=' . (string)$this->ref . '&refid=' . (int)$this->refid; + } + elseif($this->ref) + { + // return to the list view that referred to this item + $this->referral = '&ref=' . (string)$this->ref; + } + // check return value + if (!is_null($return)) + { + // add the return value + $this->referral .= '&return=' . (string)$return; + } + + // Set the toolbar + $this->addToolBar(); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JFactory::getApplication()->input->set('hidemainmenu', true); + $user = JFactory::getUser(); + $userId = $user->id; + $isNew = $this->item->id == 0; + + JToolbarHelper::title( JText::_($isNew ? 'COM_GETBIBLE_PASSWORD_NEW' : 'COM_GETBIBLE_PASSWORD_EDIT'), 'pencil-2 article-add'); + // Built the actions for new and existing records. + if (GetbibleHelper::checkString($this->referral)) + { + if ($this->canDo->get('password.create') && $isNew) + { + // We can create the record. + JToolBarHelper::save('password.save', 'JTOOLBAR_SAVE'); + } + elseif ($this->canDo->get('password.edit')) + { + // We can save the record. + JToolBarHelper::save('password.save', 'JTOOLBAR_SAVE'); + } + if ($isNew) + { + // Do not creat but cancel. + JToolBarHelper::cancel('password.cancel', 'JTOOLBAR_CANCEL'); + } + else + { + // We can close it. + JToolBarHelper::cancel('password.cancel', 'JTOOLBAR_CLOSE'); + } + } + else + { + if ($isNew) + { + // For new records, check the create permission. + if ($this->canDo->get('password.create')) + { + JToolBarHelper::apply('password.apply', 'JTOOLBAR_APPLY'); + JToolBarHelper::save('password.save', 'JTOOLBAR_SAVE'); + JToolBarHelper::custom('password.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false); + }; + JToolBarHelper::cancel('password.cancel', 'JTOOLBAR_CANCEL'); + } + else + { + if ($this->canDo->get('password.edit')) + { + // We can save the new record + JToolBarHelper::apply('password.apply', 'JTOOLBAR_APPLY'); + JToolBarHelper::save('password.save', 'JTOOLBAR_SAVE'); + // We can save this record, but check the create permission to see + // if we can return to make a new one. + if ($this->canDo->get('password.create')) + { + JToolBarHelper::custom('password.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false); + } + } + if ($this->canDo->get('password.create')) + { + JToolBarHelper::custom('password.save2copy', 'save-copy.png', 'save-copy_f2.png', 'JTOOLBAR_SAVE_AS_COPY', false); + } + JToolBarHelper::cancel('password.cancel', 'JTOOLBAR_CLOSE'); + } + } + JToolbarHelper::divider(); + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('password'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 30) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true, 30); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + $isNew = ($this->item->id < 1); + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_($isNew ? 'COM_GETBIBLE_PASSWORD_NEW' : 'COM_GETBIBLE_PASSWORD_EDIT')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/password.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + $this->document->addScript(JURI::root() . $this->script, (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + $this->document->addScript(JURI::root() . "administrator/components/com_getbible/views/password/submitbutton.js", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + JText::script('view not acceptable. Error'); + } +} diff --git a/admin/views/passwords/index.html b/admin/views/passwords/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/passwords/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/passwords/tmpl/default.php b/admin/views/passwords/tmpl/default.php new file mode 100644 index 0000000..b1d8fbf --- /dev/null +++ b/admin/views/passwords/tmpl/default.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::_('behavior.multiselect'); +JHtml::_('dropdown.init'); +JHtml::_('formbehavior.chosen', '.multipleAccessLevels', null, array('placeholder_text_multiple' => '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_ACCESS') . ' -')); +JHtml::_('formbehavior.chosen', 'select'); +if ($this->saveOrder) +{ + $saveOrderingUrl = 'index.php?option=com_getbible&task=passwords.saveOrderAjax&tmpl=component'; + JHtml::_('sortablelist.sortable', 'passwordList', 'adminForm', strtolower($this->listDirn), $saveOrderingUrl); +} +?> +
+sidebar)): ?> +
+ sidebar; ?> +
+
+ +
+ + $this)); +?> +items)): ?> +
+ +
+ + + loadTemplate('head');?> + loadTemplate('foot');?> + loadTemplate('body');?> +
+ + canCreate && $this->canEdit) : ?> + JText::_('COM_GETBIBLE_PASSWORDS_BATCH_OPTIONS'), + 'footer' => $this->loadTemplate('batch_footer') + ), + $this->loadTemplate('batch_body') + ); ?> + + +
+ + + + diff --git a/admin/views/passwords/tmpl/default_batch_body.php b/admin/views/passwords/tmpl/default_batch_body.php new file mode 100644 index 0000000..663a506 --- /dev/null +++ b/admin/views/passwords/tmpl/default_batch_body.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + +

+batchDisplay; ?> \ No newline at end of file diff --git a/admin/views/passwords/tmpl/default_batch_footer.php b/admin/views/passwords/tmpl/default_batch_footer.php new file mode 100644 index 0000000..4a2e171 --- /dev/null +++ b/admin/views/passwords/tmpl/default_batch_footer.php @@ -0,0 +1,29 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + + + \ No newline at end of file diff --git a/admin/views/passwords/tmpl/default_body.php b/admin/views/passwords/tmpl/default_body.php new file mode 100644 index 0000000..10b389e --- /dev/null +++ b/admin/views/passwords/tmpl/default_body.php @@ -0,0 +1,109 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +$edit = "index.php?option=com_getbible&view=passwords&task=password.edit"; + +?> +items as $i => $item): ?> + user->authorise('core.manage', 'com_checkin') || $item->checked_out == $this->user->id || $item->checked_out == 0; + $userChkOut = JFactory::getUser($item->checked_out); + $canDo = GetbibleHelper::getActions('password',$item,'passwords'); + ?> + + + get('password.edit.state')): ?> + saveOrder) + { + $iconClass = ' inactive tip-top" hasTooltip" title="' . JHtml::tooltipText('JORDERINGDISABLED'); + } + ?> + + + + saveOrder) : ?> + + + + ⋮ + + + + get('password.edit')): ?> + checked_out) : ?> + + id); ?> + + □ + + + id); ?> + + + □ + + + +
+ get('password.edit')): ?> + escape($item->name); ?> + checked_out): ?> + name, $item->checked_out_time, 'passwords.', $canCheckin); ?> + + + escape($item->name); ?> + +
+ + +
+ user->authorise('linker.edit', 'com_getbible.linker.' . (int) $item->linker_id)): ?> + escape($item->linker_name); ?> + + escape($item->linker_name); ?> + +
+ + + escape($item->guid); ?> + + + get('password.edit.state')) : ?> + checked_out) : ?> + + published, $i, 'passwords.', true, 'cb'); ?> + + published, $i, 'passwords.', false, 'cb'); ?> + + + published, $i, 'passwords.', true, 'cb'); ?> + + + published, $i, 'passwords.', false, 'cb'); ?> + + + + id; ?> + + + \ No newline at end of file diff --git a/admin/views/passwords/tmpl/default_foot.php b/admin/views/passwords/tmpl/default_foot.php new file mode 100644 index 0000000..38a928f --- /dev/null +++ b/admin/views/passwords/tmpl/default_foot.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + pagination->getListFooter(); ?> + \ No newline at end of file diff --git a/admin/views/passwords/tmpl/default_head.php b/admin/views/passwords/tmpl/default_head.php new file mode 100644 index 0000000..bcb6663 --- /dev/null +++ b/admin/views/passwords/tmpl/default_head.php @@ -0,0 +1,59 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + canEdit&& $this->canState): ?> + + listDirn, $this->listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?> + + + + + + + ▾ + + + ■ + + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + + + + canState): ?> + + listDirn, $this->listOrder); ?> + + + + + + + + listDirn, $this->listOrder); ?> + + \ No newline at end of file diff --git a/admin/views/passwords/tmpl/default_toolbar.php b/admin/views/passwords/tmpl/default_toolbar.php new file mode 100644 index 0000000..19b66e6 --- /dev/null +++ b/admin/views/passwords/tmpl/default_toolbar.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
+ +
+ + +
+
+ + pagination->getLimitBox(); ?> +
+
+ + +
+
+ + +
+
+
\ No newline at end of file diff --git a/admin/views/passwords/tmpl/index.html b/admin/views/passwords/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/passwords/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/passwords/view.html.php b/admin/views/passwords/view.html.php new file mode 100644 index 0000000..acaf415 --- /dev/null +++ b/admin/views/passwords/view.html.php @@ -0,0 +1,268 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Getbible Html View class for the Passwords + */ +class GetbibleViewPasswords extends HtmlView +{ + /** + * Passwords view display method + * @return void + */ + function display($tpl = null) + { + if ($this->getLayout() !== 'modal') + { + // Include helper submenu + GetbibleHelper::addSubmenu('passwords'); + } + + // Assign data to the view + $this->items = $this->get('Items'); + $this->pagination = $this->get('Pagination'); + $this->state = $this->get('State'); + $this->user = JFactory::getUser(); + // Load the filter form from xml. + $this->filterForm = $this->get('FilterForm'); + // Load the active filters. + $this->activeFilters = $this->get('ActiveFilters'); + // Add the list ordering clause. + $this->listOrder = $this->escape($this->state->get('list.ordering', 'a.id')); + $this->listDirn = $this->escape($this->state->get('list.direction', 'DESC')); + $this->saveOrder = $this->listOrder == 'a.ordering'; + // set the return here value + $this->return_here = urlencode(base64_encode((string) JUri::getInstance())); + // get global action permissions + $this->canDo = GetbibleHelper::getActions('password'); + $this->canEdit = $this->canDo->get('password.edit'); + $this->canState = $this->canDo->get('password.edit.state'); + $this->canCreate = $this->canDo->get('password.create'); + $this->canDelete = $this->canDo->get('password.delete'); + $this->canBatch = $this->canDo->get('core.batch'); + + // We don't need toolbar in the modal window. + if ($this->getLayout() !== 'modal') + { + $this->addToolbar(); + $this->sidebar = JHtmlSidebar::render(); + // load the batch html + if ($this->canCreate && $this->canEdit && $this->canState) + { + $this->batchDisplay = JHtmlBatch_::render(); + } + } + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JToolBarHelper::title(JText::_('COM_GETBIBLE_PASSWORDS'), 'lock'); + JHtmlSidebar::setAction('index.php?option=com_getbible&view=passwords'); + JFormHelper::addFieldPath(JPATH_COMPONENT . '/models/fields'); + + if ($this->canCreate) + { + JToolBarHelper::addNew('password.add'); + } + + // Only load if there are items + if (GetbibleHelper::checkArray($this->items)) + { + if ($this->canEdit) + { + JToolBarHelper::editList('password.edit'); + } + + if ($this->canState) + { + JToolBarHelper::publishList('passwords.publish'); + JToolBarHelper::unpublishList('passwords.unpublish'); + JToolBarHelper::archiveList('passwords.archive'); + + if ($this->canDo->get('core.admin')) + { + JToolBarHelper::checkin('passwords.checkin'); + } + } + + // Add a batch button + if ($this->canBatch && $this->canCreate && $this->canEdit && $this->canState) + { + // Get the toolbar object instance + $bar = JToolBar::getInstance('toolbar'); + // set the batch button name + $title = JText::_('JTOOLBAR_BATCH'); + // Instantiate a new JLayoutFile instance and render the batch button + $layout = new JLayoutFile('joomla.toolbar.batch'); + // add the button to the page + $dhtml = $layout->render(array('title' => $title)); + $bar->appendButton('Custom', $dhtml, 'batch'); + } + + if ($this->state->get('filter.published') == -2 && ($this->canState && $this->canDelete)) + { + JToolbarHelper::deleteList('', 'passwords.delete', 'JTOOLBAR_EMPTY_TRASH'); + } + elseif ($this->canState && $this->canDelete) + { + JToolbarHelper::trash('passwords.trash'); + } + } + + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('passwords'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + + // add the options comp button + if ($this->canDo->get('core.admin') || $this->canDo->get('core.options')) + { + JToolBarHelper::preferences('com_getbible'); + } + + // Only load published batch if state and batch is allowed + if ($this->canState && $this->canBatch) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_STATE'), + 'batch[published]', + JHtml::_('select.options', JHtml::_('jgrid.publishedOptions', array('all' => false)), 'value', 'text', '', true) + ); + } + + // Only load access batch if create, edit and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_ACCESS'), + 'batch[access]', + JHtml::_('select.options', JHtml::_('access.assetgroups'), 'value', 'text') + ); + } + + // Only load Name batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Name Selection + $this->nameOptions = JFormHelper::loadFieldType('passwordsfiltername')->options; + // We do some sanitation for Name filter + if (GetbibleHelper::checkArray($this->nameOptions) && + isset($this->nameOptions[0]->value) && + !GetbibleHelper::checkString($this->nameOptions[0]->value)) + { + unset($this->nameOptions[0]); + } + // Name Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_PASSWORD_NAME_LABEL').' -', + 'batch[name]', + JHtml::_('select.options', $this->nameOptions, 'value', 'text') + ); + } + + // Only load Linker Name batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Linker Name Selection + $this->linkerNameOptions = JFormHelper::loadFieldType('Linkers')->options; + // We do some sanitation for Linker Name filter + if (GetbibleHelper::checkArray($this->linkerNameOptions) && + isset($this->linkerNameOptions[0]->value) && + !GetbibleHelper::checkString($this->linkerNameOptions[0]->value)) + { + unset($this->linkerNameOptions[0]); + } + // Linker Name Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_PASSWORD_LINKER_LABEL').' -', + 'batch[linker]', + JHtml::_('select.options', $this->linkerNameOptions, 'value', 'text') + ); + } + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_('COM_GETBIBLE_PASSWORDS')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/passwords.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 50) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Returns an array of fields the table can be sorted by + * + * @return array Array containing the field name to sort by as the key and display text as value + */ + protected function getSortFields() + { + return array( + 'a.ordering' => JText::_('JGRID_HEADING_ORDERING'), + 'a.published' => JText::_('JSTATUS'), + 'a.name' => JText::_('COM_GETBIBLE_PASSWORD_NAME_LABEL'), + 'g.name' => JText::_('COM_GETBIBLE_PASSWORD_LINKER_LABEL'), + 'a.id' => JText::_('JGRID_HEADING_ID') + ); + } +} diff --git a/admin/views/prompt/submitbutton.js b/admin/views/prompt/submitbutton.js new file mode 100644 index 0000000..1a18fec --- /dev/null +++ b/admin/views/prompt/submitbutton.js @@ -0,0 +1,31 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +Joomla.submitbutton = function(task) +{ + if (task == ''){ + return false; + } else { + var action = task.split('.'); + if (action[1] == 'cancel' || action[1] == 'close' || document.formvalidator.isValid(document.getElementById("adminForm"))){ + Joomla.submitform(task, document.getElementById("adminForm")); + return true; + } else { + alert(Joomla.JText._('prompt, some values are not acceptable.','Some values are unacceptable')); + return false; + } + } +} \ No newline at end of file diff --git a/admin/views/prompt/tmpl/edit.php b/admin/views/prompt/tmpl/edit.php new file mode 100644 index 0000000..bbd2658 --- /dev/null +++ b/admin/views/prompt/tmpl/edit.php @@ -0,0 +1,138 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/html'); +JHtml::_('behavior.formvalidator'); +JHtml::_('formbehavior.chosen', 'select'); +JHtml::_('behavior.keepalive'); +$componentParams = $this->params; // will be removed just use $this->params instead +?> + + + + diff --git a/admin/views/prompt/tmpl/index.html b/admin/views/prompt/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/prompt/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/prompt/view.html.php b/admin/views/prompt/view.html.php new file mode 100644 index 0000000..c49ac31 --- /dev/null +++ b/admin/views/prompt/view.html.php @@ -0,0 +1,203 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Prompt Html View class + */ +class GetbibleViewPrompt extends HtmlView +{ + /** + * display method of View + * @return void + */ + public function display($tpl = null) + { + // set params + $this->params = JComponentHelper::getParams('com_getbible'); + // Assign the variables + $this->form = $this->get('Form'); + $this->item = $this->get('Item'); + $this->script = $this->get('Script'); + $this->state = $this->get('State'); + // get action permissions + $this->canDo = GetbibleHelper::getActions('prompt', $this->item); + // get input + $jinput = JFactory::getApplication()->input; + $this->ref = $jinput->get('ref', 0, 'word'); + $this->refid = $jinput->get('refid', 0, 'int'); + $return = $jinput->get('return', null, 'base64'); + // set the referral string + $this->referral = ''; + if ($this->refid && $this->ref) + { + // return to the item that referred to this item + $this->referral = '&ref=' . (string)$this->ref . '&refid=' . (int)$this->refid; + } + elseif($this->ref) + { + // return to the list view that referred to this item + $this->referral = '&ref=' . (string)$this->ref; + } + // check return value + if (!is_null($return)) + { + // add the return value + $this->referral .= '&return=' . (string)$return; + } + + // Set the toolbar + $this->addToolBar(); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JFactory::getApplication()->input->set('hidemainmenu', true); + $user = JFactory::getUser(); + $userId = $user->id; + $isNew = $this->item->id == 0; + + JToolbarHelper::title( JText::_($isNew ? 'COM_GETBIBLE_PROMPT_NEW' : 'COM_GETBIBLE_PROMPT_EDIT'), 'pencil-2 article-add'); + // Built the actions for new and existing records. + if (GetbibleHelper::checkString($this->referral)) + { + if ($this->canDo->get('prompt.create') && $isNew) + { + // We can create the record. + JToolBarHelper::save('prompt.save', 'JTOOLBAR_SAVE'); + } + elseif ($this->canDo->get('prompt.edit')) + { + // We can save the record. + JToolBarHelper::save('prompt.save', 'JTOOLBAR_SAVE'); + } + if ($isNew) + { + // Do not creat but cancel. + JToolBarHelper::cancel('prompt.cancel', 'JTOOLBAR_CANCEL'); + } + else + { + // We can close it. + JToolBarHelper::cancel('prompt.cancel', 'JTOOLBAR_CLOSE'); + } + } + else + { + if ($isNew) + { + // For new records, check the create permission. + if ($this->canDo->get('prompt.create')) + { + JToolBarHelper::apply('prompt.apply', 'JTOOLBAR_APPLY'); + JToolBarHelper::save('prompt.save', 'JTOOLBAR_SAVE'); + JToolBarHelper::custom('prompt.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false); + }; + JToolBarHelper::cancel('prompt.cancel', 'JTOOLBAR_CANCEL'); + } + else + { + if ($this->canDo->get('prompt.edit')) + { + // We can save the new record + JToolBarHelper::apply('prompt.apply', 'JTOOLBAR_APPLY'); + JToolBarHelper::save('prompt.save', 'JTOOLBAR_SAVE'); + // We can save this record, but check the create permission to see + // if we can return to make a new one. + if ($this->canDo->get('prompt.create')) + { + JToolBarHelper::custom('prompt.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false); + } + } + $canVersion = ($this->canDo->get('core.version') && $this->canDo->get('prompt.version')); + if ($this->state->params->get('save_history', 1) && $this->canDo->get('prompt.edit') && $canVersion) + { + JToolbarHelper::versions('com_getbible.prompt', $this->item->id); + } + if ($this->canDo->get('prompt.create')) + { + JToolBarHelper::custom('prompt.save2copy', 'save-copy.png', 'save-copy_f2.png', 'JTOOLBAR_SAVE_AS_COPY', false); + } + JToolBarHelper::cancel('prompt.cancel', 'JTOOLBAR_CLOSE'); + } + } + JToolbarHelper::divider(); + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('prompt'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 30) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true, 30); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + $isNew = ($this->item->id < 1); + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_($isNew ? 'COM_GETBIBLE_PROMPT_NEW' : 'COM_GETBIBLE_PROMPT_EDIT')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/prompt.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + $this->document->addScript(JURI::root() . $this->script, (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + $this->document->addScript(JURI::root() . "administrator/components/com_getbible/views/prompt/submitbutton.js", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + JText::script('view not acceptable. Error'); + } +} diff --git a/admin/views/prompts/index.html b/admin/views/prompts/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/prompts/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/prompts/tmpl/default.php b/admin/views/prompts/tmpl/default.php new file mode 100644 index 0000000..7e39a33 --- /dev/null +++ b/admin/views/prompts/tmpl/default.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::_('behavior.multiselect'); +JHtml::_('dropdown.init'); +JHtml::_('formbehavior.chosen', '.multipleAccessLevels', null, array('placeholder_text_multiple' => '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_ACCESS') . ' -')); +JHtml::_('formbehavior.chosen', 'select'); +if ($this->saveOrder) +{ + $saveOrderingUrl = 'index.php?option=com_getbible&task=prompts.saveOrderAjax&tmpl=component'; + JHtml::_('sortablelist.sortable', 'promptList', 'adminForm', strtolower($this->listDirn), $saveOrderingUrl); +} +?> +
+sidebar)): ?> +
+ sidebar; ?> +
+
+ +
+ + $this)); +?> +items)): ?> +
+ +
+ + + loadTemplate('head');?> + loadTemplate('foot');?> + loadTemplate('body');?> +
+ + canCreate && $this->canEdit) : ?> + JText::_('COM_GETBIBLE_PROMPTS_BATCH_OPTIONS'), + 'footer' => $this->loadTemplate('batch_footer') + ), + $this->loadTemplate('batch_body') + ); ?> + + +
+ + + + diff --git a/admin/views/prompts/tmpl/default_batch_body.php b/admin/views/prompts/tmpl/default_batch_body.php new file mode 100644 index 0000000..4500a22 --- /dev/null +++ b/admin/views/prompts/tmpl/default_batch_body.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + +

+batchDisplay; ?> \ No newline at end of file diff --git a/admin/views/prompts/tmpl/default_batch_footer.php b/admin/views/prompts/tmpl/default_batch_footer.php new file mode 100644 index 0000000..8147c5a --- /dev/null +++ b/admin/views/prompts/tmpl/default_batch_footer.php @@ -0,0 +1,29 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + + + \ No newline at end of file diff --git a/admin/views/prompts/tmpl/default_body.php b/admin/views/prompts/tmpl/default_body.php new file mode 100644 index 0000000..8b99045 --- /dev/null +++ b/admin/views/prompts/tmpl/default_body.php @@ -0,0 +1,112 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +$edit = "index.php?option=com_getbible&view=prompts&task=prompt.edit"; + +?> +items as $i => $item): ?> + user->authorise('core.manage', 'com_checkin') || $item->checked_out == $this->user->id || $item->checked_out == 0; + $userChkOut = JFactory::getUser($item->checked_out); + $canDo = GetbibleHelper::getActions('prompt',$item,'prompts'); + ?> + + + get('prompt.edit.state')): ?> + saveOrder) + { + $iconClass = ' inactive tip-top" hasTooltip" title="' . JHtml::tooltipText('JORDERINGDISABLED'); + } + ?> + + + + saveOrder) : ?> + + + + ⋮ + + + + get('prompt.edit')): ?> + checked_out) : ?> + + id); ?> + + □ + + + id); ?> + + + □ + + + +
+ get('prompt.edit')): ?> + escape($item->name); ?> + checked_out): ?> + name, $item->checked_out_time, 'prompts.', $canCheckin); ?> + + + escape($item->name); ?> + +
+ + + integration); ?> + + + cache_behaviour); ?> + + + escape($item->abbreviation_translation); ?> + + + escape($item->guid); ?> + + + model); ?> + + + get('prompt.edit.state')) : ?> + checked_out) : ?> + + published, $i, 'prompts.', true, 'cb'); ?> + + published, $i, 'prompts.', false, 'cb'); ?> + + + published, $i, 'prompts.', true, 'cb'); ?> + + + published, $i, 'prompts.', false, 'cb'); ?> + + + + id; ?> + + + \ No newline at end of file diff --git a/admin/views/prompts/tmpl/default_foot.php b/admin/views/prompts/tmpl/default_foot.php new file mode 100644 index 0000000..085e186 --- /dev/null +++ b/admin/views/prompts/tmpl/default_foot.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + pagination->getListFooter(); ?> + \ No newline at end of file diff --git a/admin/views/prompts/tmpl/default_head.php b/admin/views/prompts/tmpl/default_head.php new file mode 100644 index 0000000..e10490e --- /dev/null +++ b/admin/views/prompts/tmpl/default_head.php @@ -0,0 +1,68 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + canEdit&& $this->canState): ?> + + listDirn, $this->listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?> + + + + + + + ▾ + + + ■ + + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + + + + + + + + listDirn, $this->listOrder); ?> + + canState): ?> + + listDirn, $this->listOrder); ?> + + + + + + + + listDirn, $this->listOrder); ?> + + \ No newline at end of file diff --git a/admin/views/prompts/tmpl/default_toolbar.php b/admin/views/prompts/tmpl/default_toolbar.php new file mode 100644 index 0000000..8bf8855 --- /dev/null +++ b/admin/views/prompts/tmpl/default_toolbar.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
+ +
+ + +
+
+ + pagination->getLimitBox(); ?> +
+
+ + +
+
+ + +
+
+
\ No newline at end of file diff --git a/admin/views/prompts/tmpl/index.html b/admin/views/prompts/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/prompts/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/prompts/view.html.php b/admin/views/prompts/view.html.php new file mode 100644 index 0000000..7b36b74 --- /dev/null +++ b/admin/views/prompts/view.html.php @@ -0,0 +1,310 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Getbible Html View class for the Prompts + */ +class GetbibleViewPrompts extends HtmlView +{ + /** + * Prompts view display method + * @return void + */ + function display($tpl = null) + { + if ($this->getLayout() !== 'modal') + { + // Include helper submenu + GetbibleHelper::addSubmenu('prompts'); + } + + // Assign data to the view + $this->items = $this->get('Items'); + $this->pagination = $this->get('Pagination'); + $this->state = $this->get('State'); + $this->user = JFactory::getUser(); + // Load the filter form from xml. + $this->filterForm = $this->get('FilterForm'); + // Load the active filters. + $this->activeFilters = $this->get('ActiveFilters'); + // Add the list ordering clause. + $this->listOrder = $this->escape($this->state->get('list.ordering', 'a.id')); + $this->listDirn = $this->escape($this->state->get('list.direction', 'desc')); + $this->saveOrder = $this->listOrder == 'a.ordering'; + // set the return here value + $this->return_here = urlencode(base64_encode((string) JUri::getInstance())); + // get global action permissions + $this->canDo = GetbibleHelper::getActions('prompt'); + $this->canEdit = $this->canDo->get('prompt.edit'); + $this->canState = $this->canDo->get('prompt.edit.state'); + $this->canCreate = $this->canDo->get('prompt.create'); + $this->canDelete = $this->canDo->get('prompt.delete'); + $this->canBatch = $this->canDo->get('core.batch'); + + // We don't need toolbar in the modal window. + if ($this->getLayout() !== 'modal') + { + $this->addToolbar(); + $this->sidebar = JHtmlSidebar::render(); + // load the batch html + if ($this->canCreate && $this->canEdit && $this->canState) + { + $this->batchDisplay = JHtmlBatch_::render(); + } + } + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JToolBarHelper::title(JText::_('COM_GETBIBLE_PROMPTS'), 'featured'); + JHtmlSidebar::setAction('index.php?option=com_getbible&view=prompts'); + JFormHelper::addFieldPath(JPATH_COMPONENT . '/models/fields'); + + if ($this->canCreate) + { + JToolBarHelper::addNew('prompt.add'); + } + + // Only load if there are items + if (GetbibleHelper::checkArray($this->items)) + { + if ($this->canEdit) + { + JToolBarHelper::editList('prompt.edit'); + } + + if ($this->canState) + { + JToolBarHelper::publishList('prompts.publish'); + JToolBarHelper::unpublishList('prompts.unpublish'); + JToolBarHelper::archiveList('prompts.archive'); + + if ($this->canDo->get('core.admin')) + { + JToolBarHelper::checkin('prompts.checkin'); + } + } + + // Add a batch button + if ($this->canBatch && $this->canCreate && $this->canEdit && $this->canState) + { + // Get the toolbar object instance + $bar = JToolBar::getInstance('toolbar'); + // set the batch button name + $title = JText::_('JTOOLBAR_BATCH'); + // Instantiate a new JLayoutFile instance and render the batch button + $layout = new JLayoutFile('joomla.toolbar.batch'); + // add the button to the page + $dhtml = $layout->render(array('title' => $title)); + $bar->appendButton('Custom', $dhtml, 'batch'); + } + + if ($this->state->get('filter.published') == -2 && ($this->canState && $this->canDelete)) + { + JToolbarHelper::deleteList('', 'prompts.delete', 'JTOOLBAR_EMPTY_TRASH'); + } + elseif ($this->canState && $this->canDelete) + { + JToolbarHelper::trash('prompts.trash'); + } + } + + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('prompts'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + + // add the options comp button + if ($this->canDo->get('core.admin') || $this->canDo->get('core.options')) + { + JToolBarHelper::preferences('com_getbible'); + } + + // Only load published batch if state and batch is allowed + if ($this->canState && $this->canBatch) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_STATE'), + 'batch[published]', + JHtml::_('select.options', JHtml::_('jgrid.publishedOptions', array('all' => false)), 'value', 'text', '', true) + ); + } + + // Only load access batch if create, edit and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_ACCESS'), + 'batch[access]', + JHtml::_('select.options', JHtml::_('access.assetgroups'), 'value', 'text') + ); + } + + // Only load Name batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Name Selection + $this->nameOptions = JFormHelper::loadFieldType('promptsfiltername')->options; + // We do some sanitation for Name filter + if (GetbibleHelper::checkArray($this->nameOptions) && + isset($this->nameOptions[0]->value) && + !GetbibleHelper::checkString($this->nameOptions[0]->value)) + { + unset($this->nameOptions[0]); + } + // Name Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_PROMPT_NAME_LABEL').' -', + 'batch[name]', + JHtml::_('select.options', $this->nameOptions, 'value', 'text') + ); + } + + // Only load Cache Behaviour batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Cache Behaviour Selection + $this->cache_behaviourOptions = JFormHelper::loadFieldType('promptsfiltercachebehaviour')->options; + // We do some sanitation for Cache Behaviour filter + if (GetbibleHelper::checkArray($this->cache_behaviourOptions) && + isset($this->cache_behaviourOptions[0]->value) && + !GetbibleHelper::checkString($this->cache_behaviourOptions[0]->value)) + { + unset($this->cache_behaviourOptions[0]); + } + // Cache Behaviour Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_PROMPT_CACHE_BEHAVIOUR_LABEL').' -', + 'batch[cache_behaviour]', + JHtml::_('select.options', $this->cache_behaviourOptions, 'value', 'text') + ); + } + + // Only load Abbreviation Translation batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Abbreviation Translation Selection + $this->abbreviationTranslationOptions = JFormHelper::loadFieldType('Targettranslations')->options; + // We do some sanitation for Abbreviation Translation filter + if (GetbibleHelper::checkArray($this->abbreviationTranslationOptions) && + isset($this->abbreviationTranslationOptions[0]->value) && + !GetbibleHelper::checkString($this->abbreviationTranslationOptions[0]->value)) + { + unset($this->abbreviationTranslationOptions[0]); + } + // Abbreviation Translation Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_PROMPT_ABBREVIATION_LABEL').' -', + 'batch[abbreviation]', + JHtml::_('select.options', $this->abbreviationTranslationOptions, 'value', 'text') + ); + } + + // Only load Model batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Model Selection + $this->modelOptions = JFormHelper::loadFieldType('promptsfiltermodel')->options; + // We do some sanitation for Model filter + if (GetbibleHelper::checkArray($this->modelOptions) && + isset($this->modelOptions[0]->value) && + !GetbibleHelper::checkString($this->modelOptions[0]->value)) + { + unset($this->modelOptions[0]); + } + // Model Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_PROMPT_MODEL_LABEL').' -', + 'batch[model]', + JHtml::_('select.options', $this->modelOptions, 'value', 'text') + ); + } + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_('COM_GETBIBLE_PROMPTS')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/prompts.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 50) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Returns an array of fields the table can be sorted by + * + * @return array Array containing the field name to sort by as the key and display text as value + */ + protected function getSortFields() + { + return array( + 'a.ordering' => JText::_('JGRID_HEADING_ORDERING'), + 'a.published' => JText::_('JSTATUS'), + 'a.name' => JText::_('COM_GETBIBLE_PROMPT_NAME_LABEL'), + 'a.integration' => JText::_('COM_GETBIBLE_PROMPT_INTEGRATION_LABEL'), + 'a.cache_behaviour' => JText::_('COM_GETBIBLE_PROMPT_CACHE_BEHAVIOUR_LABEL'), + 'a.model' => JText::_('COM_GETBIBLE_PROMPT_MODEL_LABEL'), + 'a.id' => JText::_('JGRID_HEADING_ID') + ); + } +} diff --git a/admin/views/tag/submitbutton.js b/admin/views/tag/submitbutton.js new file mode 100644 index 0000000..a9ad492 --- /dev/null +++ b/admin/views/tag/submitbutton.js @@ -0,0 +1,31 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +Joomla.submitbutton = function(task) +{ + if (task == ''){ + return false; + } else { + var action = task.split('.'); + if (action[1] == 'cancel' || action[1] == 'close' || document.formvalidator.isValid(document.getElementById("adminForm"))){ + Joomla.submitform(task, document.getElementById("adminForm")); + return true; + } else { + alert(Joomla.JText._('tag, some values are not acceptable.','Some values are unacceptable')); + return false; + } + } +} \ No newline at end of file diff --git a/admin/views/tag/tmpl/edit.php b/admin/views/tag/tmpl/edit.php new file mode 100644 index 0000000..fa4b3c6 --- /dev/null +++ b/admin/views/tag/tmpl/edit.php @@ -0,0 +1,114 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/html'); +JHtml::_('behavior.formvalidator'); +JHtml::_('formbehavior.chosen', 'select'); +JHtml::_('behavior.keepalive'); +$componentParams = $this->params; // will be removed just use $this->params instead +?> + + diff --git a/admin/views/tag/tmpl/index.html b/admin/views/tag/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/tag/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/tag/view.html.php b/admin/views/tag/view.html.php new file mode 100644 index 0000000..89aea34 --- /dev/null +++ b/admin/views/tag/view.html.php @@ -0,0 +1,203 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Tag Html View class + */ +class GetbibleViewTag extends HtmlView +{ + /** + * display method of View + * @return void + */ + public function display($tpl = null) + { + // set params + $this->params = JComponentHelper::getParams('com_getbible'); + // Assign the variables + $this->form = $this->get('Form'); + $this->item = $this->get('Item'); + $this->script = $this->get('Script'); + $this->state = $this->get('State'); + // get action permissions + $this->canDo = GetbibleHelper::getActions('tag', $this->item); + // get input + $jinput = JFactory::getApplication()->input; + $this->ref = $jinput->get('ref', 0, 'word'); + $this->refid = $jinput->get('refid', 0, 'int'); + $return = $jinput->get('return', null, 'base64'); + // set the referral string + $this->referral = ''; + if ($this->refid && $this->ref) + { + // return to the item that referred to this item + $this->referral = '&ref=' . (string)$this->ref . '&refid=' . (int)$this->refid; + } + elseif($this->ref) + { + // return to the list view that referred to this item + $this->referral = '&ref=' . (string)$this->ref; + } + // check return value + if (!is_null($return)) + { + // add the return value + $this->referral .= '&return=' . (string)$return; + } + + // Set the toolbar + $this->addToolBar(); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JFactory::getApplication()->input->set('hidemainmenu', true); + $user = JFactory::getUser(); + $userId = $user->id; + $isNew = $this->item->id == 0; + + JToolbarHelper::title( JText::_($isNew ? 'COM_GETBIBLE_TAG_NEW' : 'COM_GETBIBLE_TAG_EDIT'), 'pencil-2 article-add'); + // Built the actions for new and existing records. + if (GetbibleHelper::checkString($this->referral)) + { + if ($this->canDo->get('tag.create') && $isNew) + { + // We can create the record. + JToolBarHelper::save('tag.save', 'JTOOLBAR_SAVE'); + } + elseif ($this->canDo->get('tag.edit')) + { + // We can save the record. + JToolBarHelper::save('tag.save', 'JTOOLBAR_SAVE'); + } + if ($isNew) + { + // Do not creat but cancel. + JToolBarHelper::cancel('tag.cancel', 'JTOOLBAR_CANCEL'); + } + else + { + // We can close it. + JToolBarHelper::cancel('tag.cancel', 'JTOOLBAR_CLOSE'); + } + } + else + { + if ($isNew) + { + // For new records, check the create permission. + if ($this->canDo->get('tag.create')) + { + JToolBarHelper::apply('tag.apply', 'JTOOLBAR_APPLY'); + JToolBarHelper::save('tag.save', 'JTOOLBAR_SAVE'); + JToolBarHelper::custom('tag.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false); + }; + JToolBarHelper::cancel('tag.cancel', 'JTOOLBAR_CANCEL'); + } + else + { + if ($this->canDo->get('tag.edit')) + { + // We can save the new record + JToolBarHelper::apply('tag.apply', 'JTOOLBAR_APPLY'); + JToolBarHelper::save('tag.save', 'JTOOLBAR_SAVE'); + // We can save this record, but check the create permission to see + // if we can return to make a new one. + if ($this->canDo->get('tag.create')) + { + JToolBarHelper::custom('tag.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false); + } + } + $canVersion = ($this->canDo->get('core.version') && $this->canDo->get('tag.version')); + if ($this->state->params->get('save_history', 1) && $this->canDo->get('tag.edit') && $canVersion) + { + JToolbarHelper::versions('com_getbible.tag', $this->item->id); + } + if ($this->canDo->get('tag.create')) + { + JToolBarHelper::custom('tag.save2copy', 'save-copy.png', 'save-copy_f2.png', 'JTOOLBAR_SAVE_AS_COPY', false); + } + JToolBarHelper::cancel('tag.cancel', 'JTOOLBAR_CLOSE'); + } + } + JToolbarHelper::divider(); + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('tag'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 30) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true, 30); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + $isNew = ($this->item->id < 1); + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_($isNew ? 'COM_GETBIBLE_TAG_NEW' : 'COM_GETBIBLE_TAG_EDIT')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/tag.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + $this->document->addScript(JURI::root() . $this->script, (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + $this->document->addScript(JURI::root() . "administrator/components/com_getbible/views/tag/submitbutton.js", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + JText::script('view not acceptable. Error'); + } +} diff --git a/admin/views/tagged_verse/submitbutton.js b/admin/views/tagged_verse/submitbutton.js new file mode 100644 index 0000000..2c6c846 --- /dev/null +++ b/admin/views/tagged_verse/submitbutton.js @@ -0,0 +1,31 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +Joomla.submitbutton = function(task) +{ + if (task == ''){ + return false; + } else { + var action = task.split('.'); + if (action[1] == 'cancel' || action[1] == 'close' || document.formvalidator.isValid(document.getElementById("adminForm"))){ + Joomla.submitform(task, document.getElementById("adminForm")); + return true; + } else { + alert(Joomla.JText._('tagged_verse, some values are not acceptable.','Some values are unacceptable')); + return false; + } + } +} \ No newline at end of file diff --git a/admin/views/tagged_verse/tmpl/edit.php b/admin/views/tagged_verse/tmpl/edit.php new file mode 100644 index 0000000..6b28f81 --- /dev/null +++ b/admin/views/tagged_verse/tmpl/edit.php @@ -0,0 +1,112 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/html'); +JHtml::_('behavior.formvalidator'); +JHtml::_('formbehavior.chosen', 'select'); +JHtml::_('behavior.keepalive'); +$componentParams = $this->params; // will be removed just use $this->params instead +?> + + diff --git a/admin/views/tagged_verse/tmpl/index.html b/admin/views/tagged_verse/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/tagged_verse/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/tagged_verse/view.html.php b/admin/views/tagged_verse/view.html.php new file mode 100644 index 0000000..fd4f1f1 --- /dev/null +++ b/admin/views/tagged_verse/view.html.php @@ -0,0 +1,203 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Tagged_verse Html View class + */ +class GetbibleViewTagged_verse extends HtmlView +{ + /** + * display method of View + * @return void + */ + public function display($tpl = null) + { + // set params + $this->params = JComponentHelper::getParams('com_getbible'); + // Assign the variables + $this->form = $this->get('Form'); + $this->item = $this->get('Item'); + $this->script = $this->get('Script'); + $this->state = $this->get('State'); + // get action permissions + $this->canDo = GetbibleHelper::getActions('tagged_verse', $this->item); + // get input + $jinput = JFactory::getApplication()->input; + $this->ref = $jinput->get('ref', 0, 'word'); + $this->refid = $jinput->get('refid', 0, 'int'); + $return = $jinput->get('return', null, 'base64'); + // set the referral string + $this->referral = ''; + if ($this->refid && $this->ref) + { + // return to the item that referred to this item + $this->referral = '&ref=' . (string)$this->ref . '&refid=' . (int)$this->refid; + } + elseif($this->ref) + { + // return to the list view that referred to this item + $this->referral = '&ref=' . (string)$this->ref; + } + // check return value + if (!is_null($return)) + { + // add the return value + $this->referral .= '&return=' . (string)$return; + } + + // Set the toolbar + $this->addToolBar(); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JFactory::getApplication()->input->set('hidemainmenu', true); + $user = JFactory::getUser(); + $userId = $user->id; + $isNew = $this->item->id == 0; + + JToolbarHelper::title( JText::_($isNew ? 'COM_GETBIBLE_TAGGED_VERSE_NEW' : 'COM_GETBIBLE_TAGGED_VERSE_EDIT'), 'pencil-2 article-add'); + // Built the actions for new and existing records. + if (GetbibleHelper::checkString($this->referral)) + { + if ($this->canDo->get('tagged_verse.create') && $isNew) + { + // We can create the record. + JToolBarHelper::save('tagged_verse.save', 'JTOOLBAR_SAVE'); + } + elseif ($this->canDo->get('tagged_verse.edit')) + { + // We can save the record. + JToolBarHelper::save('tagged_verse.save', 'JTOOLBAR_SAVE'); + } + if ($isNew) + { + // Do not creat but cancel. + JToolBarHelper::cancel('tagged_verse.cancel', 'JTOOLBAR_CANCEL'); + } + else + { + // We can close it. + JToolBarHelper::cancel('tagged_verse.cancel', 'JTOOLBAR_CLOSE'); + } + } + else + { + if ($isNew) + { + // For new records, check the create permission. + if ($this->canDo->get('tagged_verse.create')) + { + JToolBarHelper::apply('tagged_verse.apply', 'JTOOLBAR_APPLY'); + JToolBarHelper::save('tagged_verse.save', 'JTOOLBAR_SAVE'); + JToolBarHelper::custom('tagged_verse.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false); + }; + JToolBarHelper::cancel('tagged_verse.cancel', 'JTOOLBAR_CANCEL'); + } + else + { + if ($this->canDo->get('tagged_verse.edit')) + { + // We can save the new record + JToolBarHelper::apply('tagged_verse.apply', 'JTOOLBAR_APPLY'); + JToolBarHelper::save('tagged_verse.save', 'JTOOLBAR_SAVE'); + // We can save this record, but check the create permission to see + // if we can return to make a new one. + if ($this->canDo->get('tagged_verse.create')) + { + JToolBarHelper::custom('tagged_verse.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false); + } + } + $canVersion = ($this->canDo->get('core.version') && $this->canDo->get('tagged_verse.version')); + if ($this->state->params->get('save_history', 1) && $this->canDo->get('tagged_verse.edit') && $canVersion) + { + JToolbarHelper::versions('com_getbible.tagged_verse', $this->item->id); + } + if ($this->canDo->get('tagged_verse.create')) + { + JToolBarHelper::custom('tagged_verse.save2copy', 'save-copy.png', 'save-copy_f2.png', 'JTOOLBAR_SAVE_AS_COPY', false); + } + JToolBarHelper::cancel('tagged_verse.cancel', 'JTOOLBAR_CLOSE'); + } + } + JToolbarHelper::divider(); + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('tagged_verse'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 30) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true, 30); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + $isNew = ($this->item->id < 1); + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_($isNew ? 'COM_GETBIBLE_TAGGED_VERSE_NEW' : 'COM_GETBIBLE_TAGGED_VERSE_EDIT')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/tagged_verse.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + $this->document->addScript(JURI::root() . $this->script, (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + $this->document->addScript(JURI::root() . "administrator/components/com_getbible/views/tagged_verse/submitbutton.js", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + JText::script('view not acceptable. Error'); + } +} diff --git a/admin/views/tagged_verses/index.html b/admin/views/tagged_verses/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/tagged_verses/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/tagged_verses/tmpl/default.php b/admin/views/tagged_verses/tmpl/default.php new file mode 100644 index 0000000..8eced20 --- /dev/null +++ b/admin/views/tagged_verses/tmpl/default.php @@ -0,0 +1,77 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::_('behavior.multiselect'); +JHtml::_('dropdown.init'); +JHtml::_('formbehavior.chosen', '.multipleTaggedversesfilterbooknr', null, array('placeholder_text_multiple' => '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_BOOK_NUMBER') . ' -')); +JHtml::_('formbehavior.chosen', '.multipleTranslations', null, array('placeholder_text_multiple' => '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_TRANSLATION') . ' -')); +JHtml::_('formbehavior.chosen', '.multipleTaggedversesfilterverse', null, array('placeholder_text_multiple' => '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_VERSE') . ' -')); +JHtml::_('formbehavior.chosen', '.multipleTaggedversesfilterchapter', null, array('placeholder_text_multiple' => '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_CHAPTER') . ' -')); +JHtml::_('formbehavior.chosen', '.multipleAccessLevels', null, array('placeholder_text_multiple' => '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_ACCESS') . ' -')); +JHtml::_('formbehavior.chosen', 'select'); +if ($this->saveOrder) +{ + $saveOrderingUrl = 'index.php?option=com_getbible&task=tagged_verses.saveOrderAjax&tmpl=component'; + JHtml::_('sortablelist.sortable', 'tagged_verseList', 'adminForm', strtolower($this->listDirn), $saveOrderingUrl); +} +?> +
+sidebar)): ?> +
+ sidebar; ?> +
+
+ +
+ + $this)); +?> +items)): ?> +
+ +
+ + + loadTemplate('head');?> + loadTemplate('foot');?> + loadTemplate('body');?> +
+ + canCreate && $this->canEdit) : ?> + JText::_('COM_GETBIBLE_TAGGED_VERSES_BATCH_OPTIONS'), + 'footer' => $this->loadTemplate('batch_footer') + ), + $this->loadTemplate('batch_body') + ); ?> + + +
+ + + + diff --git a/admin/views/tagged_verses/tmpl/default_batch_body.php b/admin/views/tagged_verses/tmpl/default_batch_body.php new file mode 100644 index 0000000..3a1f5dd --- /dev/null +++ b/admin/views/tagged_verses/tmpl/default_batch_body.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + +

+batchDisplay; ?> \ No newline at end of file diff --git a/admin/views/tagged_verses/tmpl/default_batch_footer.php b/admin/views/tagged_verses/tmpl/default_batch_footer.php new file mode 100644 index 0000000..3623df3 --- /dev/null +++ b/admin/views/tagged_verses/tmpl/default_batch_footer.php @@ -0,0 +1,29 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + + + \ No newline at end of file diff --git a/admin/views/tagged_verses/tmpl/default_body.php b/admin/views/tagged_verses/tmpl/default_body.php new file mode 100644 index 0000000..406a8c1 --- /dev/null +++ b/admin/views/tagged_verses/tmpl/default_body.php @@ -0,0 +1,127 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +$edit = "index.php?option=com_getbible&view=tagged_verses&task=tagged_verse.edit"; + +?> +items as $i => $item): ?> + user->authorise('core.manage', 'com_checkin') || $item->checked_out == $this->user->id || $item->checked_out == 0; + $userChkOut = JFactory::getUser($item->checked_out); + $canDo = GetbibleHelper::getActions('tagged_verse',$item,'tagged_verses'); + ?> + + + get('tagged_verse.edit.state')): ?> + saveOrder) + { + $iconClass = ' inactive tip-top" hasTooltip" title="' . JHtml::tooltipText('JORDERINGDISABLED'); + } + ?> + + + + saveOrder) : ?> + + + + ⋮ + + + + get('tagged_verse.edit')): ?> + checked_out) : ?> + + id); ?> + + □ + + + id); ?> + + + □ + + + +
+ get('tagged_verse.edit')): ?> + escape($item->book_nr); ?> + checked_out): ?> + name, $item->checked_out_time, 'tagged_verses.', $canCheckin); ?> + + + escape($item->book_nr); ?> + +
+ + +
+ user->authorise('translation.edit', 'com_getbible.translation.' . (int) $item->abbreviation_id)): ?> + escape($item->abbreviation_translation); ?> + + escape($item->abbreviation_translation); ?> + +
+ + + access); ?> + + +
+ user->authorise('linker.edit', 'com_getbible.linker.' . (int) $item->linker_id)): ?> + escape($item->linker_name); ?> + + escape($item->linker_name); ?> + +
+ + +
+ user->authorise('tag.edit', 'com_getbible.tag.' . (int) $item->tag_id)): ?> + escape($item->tag_name); ?> + + escape($item->tag_name); ?> + +
+ + + get('tagged_verse.edit.state')) : ?> + checked_out) : ?> + + published, $i, 'tagged_verses.', true, 'cb'); ?> + + published, $i, 'tagged_verses.', false, 'cb'); ?> + + + published, $i, 'tagged_verses.', true, 'cb'); ?> + + + published, $i, 'tagged_verses.', false, 'cb'); ?> + + + + id; ?> + + + \ No newline at end of file diff --git a/admin/views/tagged_verses/tmpl/default_foot.php b/admin/views/tagged_verses/tmpl/default_foot.php new file mode 100644 index 0000000..6df0a9f --- /dev/null +++ b/admin/views/tagged_verses/tmpl/default_foot.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + pagination->getListFooter(); ?> + \ No newline at end of file diff --git a/admin/views/tagged_verses/tmpl/default_head.php b/admin/views/tagged_verses/tmpl/default_head.php new file mode 100644 index 0000000..b103017 --- /dev/null +++ b/admin/views/tagged_verses/tmpl/default_head.php @@ -0,0 +1,65 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + canEdit&& $this->canState): ?> + + listDirn, $this->listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?> + + + + + + + ▾ + + + ■ + + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + canState): ?> + + listDirn, $this->listOrder); ?> + + + + + + + + listDirn, $this->listOrder); ?> + + \ No newline at end of file diff --git a/admin/views/tagged_verses/tmpl/default_toolbar.php b/admin/views/tagged_verses/tmpl/default_toolbar.php new file mode 100644 index 0000000..8c2066c --- /dev/null +++ b/admin/views/tagged_verses/tmpl/default_toolbar.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
+ +
+ + +
+
+ + pagination->getLimitBox(); ?> +
+
+ + +
+
+ + +
+
+
\ No newline at end of file diff --git a/admin/views/tagged_verses/tmpl/index.html b/admin/views/tagged_verses/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/tagged_verses/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/tagged_verses/view.html.php b/admin/views/tagged_verses/view.html.php new file mode 100644 index 0000000..995bf5b --- /dev/null +++ b/admin/views/tagged_verses/view.html.php @@ -0,0 +1,361 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Getbible Html View class for the Tagged_verses + */ +class GetbibleViewTagged_verses extends HtmlView +{ + /** + * Tagged_verses view display method + * @return void + */ + function display($tpl = null) + { + if ($this->getLayout() !== 'modal') + { + // Include helper submenu + GetbibleHelper::addSubmenu('tagged_verses'); + } + + // Assign data to the view + $this->items = $this->get('Items'); + $this->pagination = $this->get('Pagination'); + $this->state = $this->get('State'); + $this->user = JFactory::getUser(); + // Load the filter form from xml. + $this->filterForm = $this->get('FilterForm'); + // Load the active filters. + $this->activeFilters = $this->get('ActiveFilters'); + // Add the list ordering clause. + $this->listOrder = $this->escape($this->state->get('list.ordering', 'a.id')); + $this->listDirn = $this->escape($this->state->get('list.direction', 'DESC')); + $this->saveOrder = $this->listOrder == 'a.ordering'; + // set the return here value + $this->return_here = urlencode(base64_encode((string) JUri::getInstance())); + // get global action permissions + $this->canDo = GetbibleHelper::getActions('tagged_verse'); + $this->canEdit = $this->canDo->get('tagged_verse.edit'); + $this->canState = $this->canDo->get('tagged_verse.edit.state'); + $this->canCreate = $this->canDo->get('tagged_verse.create'); + $this->canDelete = $this->canDo->get('tagged_verse.delete'); + $this->canBatch = $this->canDo->get('core.batch'); + + // We don't need toolbar in the modal window. + if ($this->getLayout() !== 'modal') + { + $this->addToolbar(); + $this->sidebar = JHtmlSidebar::render(); + // load the batch html + if ($this->canCreate && $this->canEdit && $this->canState) + { + $this->batchDisplay = JHtmlBatch_::render(); + } + } + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JToolBarHelper::title(JText::_('COM_GETBIBLE_TAGGED_VERSES'), 'tags-2'); + JHtmlSidebar::setAction('index.php?option=com_getbible&view=tagged_verses'); + JFormHelper::addFieldPath(JPATH_COMPONENT . '/models/fields'); + + if ($this->canCreate) + { + JToolBarHelper::addNew('tagged_verse.add'); + } + + // Only load if there are items + if (GetbibleHelper::checkArray($this->items)) + { + if ($this->canEdit) + { + JToolBarHelper::editList('tagged_verse.edit'); + } + + if ($this->canState) + { + JToolBarHelper::publishList('tagged_verses.publish'); + JToolBarHelper::unpublishList('tagged_verses.unpublish'); + JToolBarHelper::archiveList('tagged_verses.archive'); + + if ($this->canDo->get('core.admin')) + { + JToolBarHelper::checkin('tagged_verses.checkin'); + } + } + + // Add a batch button + if ($this->canBatch && $this->canCreate && $this->canEdit && $this->canState) + { + // Get the toolbar object instance + $bar = JToolBar::getInstance('toolbar'); + // set the batch button name + $title = JText::_('JTOOLBAR_BATCH'); + // Instantiate a new JLayoutFile instance and render the batch button + $layout = new JLayoutFile('joomla.toolbar.batch'); + // add the button to the page + $dhtml = $layout->render(array('title' => $title)); + $bar->appendButton('Custom', $dhtml, 'batch'); + } + + if ($this->state->get('filter.published') == -2 && ($this->canState && $this->canDelete)) + { + JToolbarHelper::deleteList('', 'tagged_verses.delete', 'JTOOLBAR_EMPTY_TRASH'); + } + elseif ($this->canState && $this->canDelete) + { + JToolbarHelper::trash('tagged_verses.trash'); + } + } + + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('tagged_verses'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + + // add the options comp button + if ($this->canDo->get('core.admin') || $this->canDo->get('core.options')) + { + JToolBarHelper::preferences('com_getbible'); + } + + // Only load published batch if state and batch is allowed + if ($this->canState && $this->canBatch) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_STATE'), + 'batch[published]', + JHtml::_('select.options', JHtml::_('jgrid.publishedOptions', array('all' => false)), 'value', 'text', '', true) + ); + } + + // Only load Book Nr batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Book Nr Selection + $this->book_nrOptions = JFormHelper::loadFieldType('taggedversesfilterbooknr')->options; + // We do some sanitation for Book Nr filter + if (GetbibleHelper::checkArray($this->book_nrOptions) && + isset($this->book_nrOptions[0]->value) && + !GetbibleHelper::checkString($this->book_nrOptions[0]->value)) + { + unset($this->book_nrOptions[0]); + } + // Book Nr Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_TAGGED_VERSE_BOOK_NR_LABEL').' -', + 'batch[book_nr]', + JHtml::_('select.options', $this->book_nrOptions, 'value', 'text') + ); + } + + // Only load Abbreviation Translation batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Abbreviation Translation Selection + $this->abbreviationTranslationOptions = JFormHelper::loadFieldType('Translations')->options; + // We do some sanitation for Abbreviation Translation filter + if (GetbibleHelper::checkArray($this->abbreviationTranslationOptions) && + isset($this->abbreviationTranslationOptions[0]->value) && + !GetbibleHelper::checkString($this->abbreviationTranslationOptions[0]->value)) + { + unset($this->abbreviationTranslationOptions[0]); + } + // Abbreviation Translation Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_TAGGED_VERSE_ABBREVIATION_LABEL').' -', + 'batch[abbreviation]', + JHtml::_('select.options', $this->abbreviationTranslationOptions, 'value', 'text') + ); + } + + // Only load Access batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Access Selection + $this->accessOptions = JFormHelper::loadFieldType('taggedversesfilteraccess')->options; + // We do some sanitation for Access filter + if (GetbibleHelper::checkArray($this->accessOptions) && + isset($this->accessOptions[0]->value) && + !GetbibleHelper::checkString($this->accessOptions[0]->value)) + { + unset($this->accessOptions[0]); + } + // Access Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_TAGGED_VERSE_ACCESS_LABEL').' -', + 'batch[access]', + JHtml::_('select.options', $this->accessOptions, 'value', 'text') + ); + } + + // Only load Linker Name batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Linker Name Selection + $this->linkerNameOptions = JFormHelper::loadFieldType('Linkers')->options; + // We do some sanitation for Linker Name filter + if (GetbibleHelper::checkArray($this->linkerNameOptions) && + isset($this->linkerNameOptions[0]->value) && + !GetbibleHelper::checkString($this->linkerNameOptions[0]->value)) + { + unset($this->linkerNameOptions[0]); + } + // Linker Name Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_TAGGED_VERSE_LINKER_LABEL').' -', + 'batch[linker]', + JHtml::_('select.options', $this->linkerNameOptions, 'value', 'text') + ); + } + + // Only load Tag Name batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Tag Name Selection + $this->tagNameOptions = JFormHelper::loadFieldType('Tagers')->options; + // We do some sanitation for Tag Name filter + if (GetbibleHelper::checkArray($this->tagNameOptions) && + isset($this->tagNameOptions[0]->value) && + !GetbibleHelper::checkString($this->tagNameOptions[0]->value)) + { + unset($this->tagNameOptions[0]); + } + // Tag Name Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_TAGGED_VERSE_TAG_LABEL').' -', + 'batch[tag]', + JHtml::_('select.options', $this->tagNameOptions, 'value', 'text') + ); + } + + // Only load Verse batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Verse Selection + $this->verseOptions = JFormHelper::loadFieldType('taggedversesfilterverse')->options; + // We do some sanitation for Verse filter + if (GetbibleHelper::checkArray($this->verseOptions) && + isset($this->verseOptions[0]->value) && + !GetbibleHelper::checkString($this->verseOptions[0]->value)) + { + unset($this->verseOptions[0]); + } + // Verse Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_TAGGED_VERSE_VERSE_LABEL').' -', + 'batch[verse]', + JHtml::_('select.options', $this->verseOptions, 'value', 'text') + ); + } + + // Only load Chapter batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Chapter Selection + $this->chapterOptions = JFormHelper::loadFieldType('taggedversesfilterchapter')->options; + // We do some sanitation for Chapter filter + if (GetbibleHelper::checkArray($this->chapterOptions) && + isset($this->chapterOptions[0]->value) && + !GetbibleHelper::checkString($this->chapterOptions[0]->value)) + { + unset($this->chapterOptions[0]); + } + // Chapter Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_TAGGED_VERSE_CHAPTER_LABEL').' -', + 'batch[chapter]', + JHtml::_('select.options', $this->chapterOptions, 'value', 'text') + ); + } + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_('COM_GETBIBLE_TAGGED_VERSES')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/tagged_verses.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 50) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Returns an array of fields the table can be sorted by + * + * @return array Array containing the field name to sort by as the key and display text as value + */ + protected function getSortFields() + { + return array( + 'a.ordering' => JText::_('JGRID_HEADING_ORDERING'), + 'a.published' => JText::_('JSTATUS'), + 'a.book_nr' => JText::_('COM_GETBIBLE_TAGGED_VERSE_BOOK_NR_LABEL'), + 'g.translation' => JText::_('COM_GETBIBLE_TAGGED_VERSE_ABBREVIATION_LABEL'), + 'a.access' => JText::_('COM_GETBIBLE_TAGGED_VERSE_ACCESS_LABEL'), + 'h.name' => JText::_('COM_GETBIBLE_TAGGED_VERSE_LINKER_LABEL'), + 'i.name' => JText::_('COM_GETBIBLE_TAGGED_VERSE_TAG_LABEL'), + 'a.id' => JText::_('JGRID_HEADING_ID') + ); + } +} diff --git a/admin/views/tags/index.html b/admin/views/tags/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/tags/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/tags/tmpl/default.php b/admin/views/tags/tmpl/default.php new file mode 100644 index 0000000..3a30519 --- /dev/null +++ b/admin/views/tags/tmpl/default.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::_('behavior.multiselect'); +JHtml::_('dropdown.init'); +JHtml::_('formbehavior.chosen', '.multipleAccessLevels', null, array('placeholder_text_multiple' => '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_ACCESS') . ' -')); +JHtml::_('formbehavior.chosen', 'select'); +if ($this->saveOrder) +{ + $saveOrderingUrl = 'index.php?option=com_getbible&task=tags.saveOrderAjax&tmpl=component'; + JHtml::_('sortablelist.sortable', 'tagList', 'adminForm', strtolower($this->listDirn), $saveOrderingUrl); +} +?> +
+sidebar)): ?> +
+ sidebar; ?> +
+
+ +
+ + $this)); +?> +items)): ?> +
+ +
+ + + loadTemplate('head');?> + loadTemplate('foot');?> + loadTemplate('body');?> +
+ + canCreate && $this->canEdit) : ?> + JText::_('COM_GETBIBLE_TAGS_BATCH_OPTIONS'), + 'footer' => $this->loadTemplate('batch_footer') + ), + $this->loadTemplate('batch_body') + ); ?> + + +
+ + + + diff --git a/admin/views/tags/tmpl/default_batch_body.php b/admin/views/tags/tmpl/default_batch_body.php new file mode 100644 index 0000000..54607fe --- /dev/null +++ b/admin/views/tags/tmpl/default_batch_body.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + +

+batchDisplay; ?> \ No newline at end of file diff --git a/admin/views/tags/tmpl/default_batch_footer.php b/admin/views/tags/tmpl/default_batch_footer.php new file mode 100644 index 0000000..7457dae --- /dev/null +++ b/admin/views/tags/tmpl/default_batch_footer.php @@ -0,0 +1,29 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + + + \ No newline at end of file diff --git a/admin/views/tags/tmpl/default_body.php b/admin/views/tags/tmpl/default_body.php new file mode 100644 index 0000000..0561b2f --- /dev/null +++ b/admin/views/tags/tmpl/default_body.php @@ -0,0 +1,103 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +$edit = "index.php?option=com_getbible&view=tags&task=tag.edit"; + +?> +items as $i => $item): ?> + user->authorise('core.manage', 'com_checkin') || $item->checked_out == $this->user->id || $item->checked_out == 0; + $userChkOut = JFactory::getUser($item->checked_out); + $canDo = GetbibleHelper::getActions('tag',$item,'tags'); + ?> + + + get('tag.edit.state')): ?> + saveOrder) + { + $iconClass = ' inactive tip-top" hasTooltip" title="' . JHtml::tooltipText('JORDERINGDISABLED'); + } + ?> + + + + saveOrder) : ?> + + + + ⋮ + + + + get('tag.edit')): ?> + checked_out) : ?> + + id); ?> + + □ + + + id); ?> + + + □ + + + +
+ get('tag.edit')): ?> + escape($item->name); ?> + checked_out): ?> + name, $item->checked_out_time, 'tags.', $canCheckin); ?> + + + escape($item->name); ?> + +
+ + + escape($item->linker_name); ?> + + + access); ?> + + + get('tag.edit.state')) : ?> + checked_out) : ?> + + published, $i, 'tags.', true, 'cb'); ?> + + published, $i, 'tags.', false, 'cb'); ?> + + + published, $i, 'tags.', true, 'cb'); ?> + + + published, $i, 'tags.', false, 'cb'); ?> + + + + id; ?> + + + \ No newline at end of file diff --git a/admin/views/tags/tmpl/default_foot.php b/admin/views/tags/tmpl/default_foot.php new file mode 100644 index 0000000..38a928f --- /dev/null +++ b/admin/views/tags/tmpl/default_foot.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + pagination->getListFooter(); ?> + \ No newline at end of file diff --git a/admin/views/tags/tmpl/default_head.php b/admin/views/tags/tmpl/default_head.php new file mode 100644 index 0000000..e7da840 --- /dev/null +++ b/admin/views/tags/tmpl/default_head.php @@ -0,0 +1,59 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + canEdit&& $this->canState): ?> + + listDirn, $this->listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?> + + + + + + + ▾ + + + ■ + + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + canState): ?> + + listDirn, $this->listOrder); ?> + + + + + + + + listDirn, $this->listOrder); ?> + + \ No newline at end of file diff --git a/admin/views/tags/tmpl/default_toolbar.php b/admin/views/tags/tmpl/default_toolbar.php new file mode 100644 index 0000000..09fdafc --- /dev/null +++ b/admin/views/tags/tmpl/default_toolbar.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
+ +
+ + +
+
+ + pagination->getLimitBox(); ?> +
+
+ + +
+
+ + +
+
+
\ No newline at end of file diff --git a/admin/views/tags/tmpl/index.html b/admin/views/tags/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/tags/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/tags/view.html.php b/admin/views/tags/view.html.php new file mode 100644 index 0000000..1903692 --- /dev/null +++ b/admin/views/tags/view.html.php @@ -0,0 +1,259 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Getbible Html View class for the Tags + */ +class GetbibleViewTags extends HtmlView +{ + /** + * Tags view display method + * @return void + */ + function display($tpl = null) + { + if ($this->getLayout() !== 'modal') + { + // Include helper submenu + GetbibleHelper::addSubmenu('tags'); + } + + // Assign data to the view + $this->items = $this->get('Items'); + $this->pagination = $this->get('Pagination'); + $this->state = $this->get('State'); + $this->user = JFactory::getUser(); + // Load the filter form from xml. + $this->filterForm = $this->get('FilterForm'); + // Load the active filters. + $this->activeFilters = $this->get('ActiveFilters'); + // Add the list ordering clause. + $this->listOrder = $this->escape($this->state->get('list.ordering', 'a.id')); + $this->listDirn = $this->escape($this->state->get('list.direction', 'DESC')); + $this->saveOrder = $this->listOrder == 'a.ordering'; + // set the return here value + $this->return_here = urlencode(base64_encode((string) JUri::getInstance())); + // get global action permissions + $this->canDo = GetbibleHelper::getActions('tag'); + $this->canEdit = $this->canDo->get('tag.edit'); + $this->canState = $this->canDo->get('tag.edit.state'); + $this->canCreate = $this->canDo->get('tag.create'); + $this->canDelete = $this->canDo->get('tag.delete'); + $this->canBatch = $this->canDo->get('core.batch'); + + // We don't need toolbar in the modal window. + if ($this->getLayout() !== 'modal') + { + $this->addToolbar(); + $this->sidebar = JHtmlSidebar::render(); + // load the batch html + if ($this->canCreate && $this->canEdit && $this->canState) + { + $this->batchDisplay = JHtmlBatch_::render(); + } + } + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JToolBarHelper::title(JText::_('COM_GETBIBLE_TAGS'), 'tags'); + JHtmlSidebar::setAction('index.php?option=com_getbible&view=tags'); + JFormHelper::addFieldPath(JPATH_COMPONENT . '/models/fields'); + + if ($this->canCreate) + { + JToolBarHelper::addNew('tag.add'); + } + + // Only load if there are items + if (GetbibleHelper::checkArray($this->items)) + { + if ($this->canEdit) + { + JToolBarHelper::editList('tag.edit'); + } + + if ($this->canState) + { + JToolBarHelper::publishList('tags.publish'); + JToolBarHelper::unpublishList('tags.unpublish'); + JToolBarHelper::archiveList('tags.archive'); + + if ($this->canDo->get('core.admin')) + { + JToolBarHelper::checkin('tags.checkin'); + } + } + + // Add a batch button + if ($this->canBatch && $this->canCreate && $this->canEdit && $this->canState) + { + // Get the toolbar object instance + $bar = JToolBar::getInstance('toolbar'); + // set the batch button name + $title = JText::_('JTOOLBAR_BATCH'); + // Instantiate a new JLayoutFile instance and render the batch button + $layout = new JLayoutFile('joomla.toolbar.batch'); + // add the button to the page + $dhtml = $layout->render(array('title' => $title)); + $bar->appendButton('Custom', $dhtml, 'batch'); + } + + if ($this->state->get('filter.published') == -2 && ($this->canState && $this->canDelete)) + { + JToolbarHelper::deleteList('', 'tags.delete', 'JTOOLBAR_EMPTY_TRASH'); + } + elseif ($this->canState && $this->canDelete) + { + JToolbarHelper::trash('tags.trash'); + } + } + + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('tags'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + + // add the options comp button + if ($this->canDo->get('core.admin') || $this->canDo->get('core.options')) + { + JToolBarHelper::preferences('com_getbible'); + } + + // Only load published batch if state and batch is allowed + if ($this->canState && $this->canBatch) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_STATE'), + 'batch[published]', + JHtml::_('select.options', JHtml::_('jgrid.publishedOptions', array('all' => false)), 'value', 'text', '', true) + ); + } + + // Only load Linker Name batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Linker Name Selection + $this->linkerNameOptions = JFormHelper::loadFieldType('Linkers')->options; + // We do some sanitation for Linker Name filter + if (GetbibleHelper::checkArray($this->linkerNameOptions) && + isset($this->linkerNameOptions[0]->value) && + !GetbibleHelper::checkString($this->linkerNameOptions[0]->value)) + { + unset($this->linkerNameOptions[0]); + } + // Linker Name Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_TAG_LINKER_LABEL').' -', + 'batch[linker]', + JHtml::_('select.options', $this->linkerNameOptions, 'value', 'text') + ); + } + + // Only load Access batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Access Selection + $this->accessOptions = JFormHelper::loadFieldType('tagsfilteraccess')->options; + // We do some sanitation for Access filter + if (GetbibleHelper::checkArray($this->accessOptions) && + isset($this->accessOptions[0]->value) && + !GetbibleHelper::checkString($this->accessOptions[0]->value)) + { + unset($this->accessOptions[0]); + } + // Access Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_TAG_ACCESS_LABEL').' -', + 'batch[access]', + JHtml::_('select.options', $this->accessOptions, 'value', 'text') + ); + } + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_('COM_GETBIBLE_TAGS')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/tags.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 50) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Returns an array of fields the table can be sorted by + * + * @return array Array containing the field name to sort by as the key and display text as value + */ + protected function getSortFields() + { + return array( + 'a.ordering' => JText::_('JGRID_HEADING_ORDERING'), + 'a.published' => JText::_('JSTATUS'), + 'a.name' => JText::_('COM_GETBIBLE_TAG_NAME_LABEL'), + 'g.name' => JText::_('COM_GETBIBLE_TAG_LINKER_LABEL'), + 'a.access' => JText::_('COM_GETBIBLE_TAG_ACCESS_LABEL'), + 'a.id' => JText::_('JGRID_HEADING_ID') + ); + } +} diff --git a/admin/views/translation/submitbutton.js b/admin/views/translation/submitbutton.js new file mode 100644 index 0000000..2db2bd4 --- /dev/null +++ b/admin/views/translation/submitbutton.js @@ -0,0 +1,31 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +Joomla.submitbutton = function(task) +{ + if (task == ''){ + return false; + } else { + var action = task.split('.'); + if (action[1] == 'cancel' || action[1] == 'close' || document.formvalidator.isValid(document.getElementById("adminForm"))){ + Joomla.submitform(task, document.getElementById("adminForm")); + return true; + } else { + alert(Joomla.JText._('translation, some values are not acceptable.','Some values are unacceptable')); + return false; + } + } +} \ No newline at end of file diff --git a/admin/views/translation/tmpl/edit.php b/admin/views/translation/tmpl/edit.php new file mode 100644 index 0000000..e3eaf7b --- /dev/null +++ b/admin/views/translation/tmpl/edit.php @@ -0,0 +1,117 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/html'); +JHtml::_('behavior.formvalidator'); +JHtml::_('formbehavior.chosen', 'select'); +JHtml::_('behavior.keepalive'); +$componentParams = $this->params; // will be removed just use $this->params instead +?> + + diff --git a/admin/views/translation/tmpl/index.html b/admin/views/translation/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/translation/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/translation/view.html.php b/admin/views/translation/view.html.php new file mode 100644 index 0000000..2e1ac67 --- /dev/null +++ b/admin/views/translation/view.html.php @@ -0,0 +1,132 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Translation Html View class + */ +class GetbibleViewTranslation extends HtmlView +{ + /** + * display method of View + * @return void + */ + public function display($tpl = null) + { + // set params + $this->params = JComponentHelper::getParams('com_getbible'); + // Assign the variables + $this->form = $this->get('Form'); + $this->item = $this->get('Item'); + $this->script = $this->get('Script'); + $this->state = $this->get('State'); + // get action permissions + $this->canDo = GetbibleHelper::getActions('translation', $this->item); + // get input + $jinput = JFactory::getApplication()->input; + $this->ref = $jinput->get('ref', 0, 'word'); + $this->refid = $jinput->get('refid', 0, 'int'); + $return = $jinput->get('return', null, 'base64'); + // set the referral string + $this->referral = ''; + if ($this->refid && $this->ref) + { + // return to the item that referred to this item + $this->referral = '&ref=' . (string)$this->ref . '&refid=' . (int)$this->refid; + } + elseif($this->ref) + { + // return to the list view that referred to this item + $this->referral = '&ref=' . (string)$this->ref; + } + // check return value + if (!is_null($return)) + { + // add the return value + $this->referral .= '&return=' . (string)$return; + } + + // Set the toolbar + $this->addToolBar(); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JFactory::getApplication()->input->set('hidemainmenu', true); + JToolBarHelper::title(JText::_('COM_GETBIBLE_TRANSLATION_READONLY'), 'translation'); + JToolBarHelper::cancel('translation.cancel', 'JTOOLBAR_CLOSE'); + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 30) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true, 30); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + $isNew = ($this->item->id < 1); + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_($isNew ? 'COM_GETBIBLE_TRANSLATION_NEW' : 'COM_GETBIBLE_TRANSLATION_EDIT')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/translation.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + // Add Ajax Token + $this->document->addScriptDeclaration("var token = '".JSession::getFormToken()."';"); + $this->document->addScript(JURI::root() . $this->script, (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + $this->document->addScript(JURI::root() . "administrator/components/com_getbible/views/translation/submitbutton.js", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + JText::script('view not acceptable. Error'); + } +} diff --git a/admin/views/translations/index.html b/admin/views/translations/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/translations/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/translations/tmpl/default.php b/admin/views/translations/tmpl/default.php new file mode 100644 index 0000000..2739932 --- /dev/null +++ b/admin/views/translations/tmpl/default.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::_('behavior.multiselect'); +JHtml::_('dropdown.init'); +JHtml::_('formbehavior.chosen', '.multipleAccessLevels', null, array('placeholder_text_multiple' => '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_ACCESS') . ' -')); +JHtml::_('formbehavior.chosen', 'select'); +if ($this->saveOrder) +{ + $saveOrderingUrl = 'index.php?option=com_getbible&task=translations.saveOrderAjax&tmpl=component'; + JHtml::_('sortablelist.sortable', 'translationList', 'adminForm', strtolower($this->listDirn), $saveOrderingUrl); +} +?> +
+sidebar)): ?> +
+ sidebar; ?> +
+
+ +
+ + $this)); +?> +items)): ?> +
+ +
+ + + loadTemplate('head');?> + loadTemplate('foot');?> + loadTemplate('body');?> +
+ + canCreate && $this->canEdit) : ?> + JText::_('COM_GETBIBLE_TRANSLATIONS_BATCH_OPTIONS'), + 'footer' => $this->loadTemplate('batch_footer') + ), + $this->loadTemplate('batch_body') + ); ?> + + +
+ + + + diff --git a/admin/views/translations/tmpl/default_batch_body.php b/admin/views/translations/tmpl/default_batch_body.php new file mode 100644 index 0000000..4bc956e --- /dev/null +++ b/admin/views/translations/tmpl/default_batch_body.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + +

+batchDisplay; ?> \ No newline at end of file diff --git a/admin/views/translations/tmpl/default_batch_footer.php b/admin/views/translations/tmpl/default_batch_footer.php new file mode 100644 index 0000000..53b2349 --- /dev/null +++ b/admin/views/translations/tmpl/default_batch_footer.php @@ -0,0 +1,29 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + + + \ No newline at end of file diff --git a/admin/views/translations/tmpl/default_body.php b/admin/views/translations/tmpl/default_body.php new file mode 100644 index 0000000..c04ab83 --- /dev/null +++ b/admin/views/translations/tmpl/default_body.php @@ -0,0 +1,106 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +$edit = "index.php?option=com_getbible&view=translations&task=translation.edit"; + +?> +items as $i => $item): ?> + user->authorise('core.manage', 'com_checkin') || $item->checked_out == $this->user->id || $item->checked_out == 0; + $userChkOut = JFactory::getUser($item->checked_out); + $canDo = GetbibleHelper::getActions('translation',$item,'translations'); + ?> + + + get('translation.edit.state')): ?> + saveOrder) + { + $iconClass = ' inactive tip-top" hasTooltip" title="' . JHtml::tooltipText('JORDERINGDISABLED'); + } + ?> + + + + saveOrder) : ?> + + + + ⋮ + + + + get('translation.edit')): ?> + checked_out) : ?> + + id); ?> + + □ + + + id); ?> + + + □ + + + +
+ get('translation.edit')): ?> + escape($item->translation); ?> + checked_out): ?> + name, $item->checked_out_time, 'translations.', $canCheckin); ?> + + + escape($item->translation); ?> + +
+ + + escape($item->abbreviation); ?> + + + escape($item->language); ?> + + + direction); ?> + + + get('translation.edit.state')) : ?> + checked_out) : ?> + + published, $i, 'translations.', true, 'cb'); ?> + + published, $i, 'translations.', false, 'cb'); ?> + + + published, $i, 'translations.', true, 'cb'); ?> + + + published, $i, 'translations.', false, 'cb'); ?> + + + + id; ?> + + + \ No newline at end of file diff --git a/admin/views/translations/tmpl/default_foot.php b/admin/views/translations/tmpl/default_foot.php new file mode 100644 index 0000000..290760a --- /dev/null +++ b/admin/views/translations/tmpl/default_foot.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + pagination->getListFooter(); ?> + \ No newline at end of file diff --git a/admin/views/translations/tmpl/default_head.php b/admin/views/translations/tmpl/default_head.php new file mode 100644 index 0000000..003c884 --- /dev/null +++ b/admin/views/translations/tmpl/default_head.php @@ -0,0 +1,62 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + canEdit&& $this->canState): ?> + + listDirn, $this->listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?> + + + + + + + ▾ + + + ■ + + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + canState): ?> + + listDirn, $this->listOrder); ?> + + + + + + + + listDirn, $this->listOrder); ?> + + \ No newline at end of file diff --git a/admin/views/translations/tmpl/default_toolbar.php b/admin/views/translations/tmpl/default_toolbar.php new file mode 100644 index 0000000..50bd491 --- /dev/null +++ b/admin/views/translations/tmpl/default_toolbar.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
+ +
+ + +
+
+ + pagination->getLimitBox(); ?> +
+
+ + +
+
+ + +
+
+
\ No newline at end of file diff --git a/admin/views/translations/tmpl/index.html b/admin/views/translations/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/translations/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/translations/view.html.php b/admin/views/translations/view.html.php new file mode 100644 index 0000000..f937f6d --- /dev/null +++ b/admin/views/translations/view.html.php @@ -0,0 +1,250 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Getbible Html View class for the Translations + */ +class GetbibleViewTranslations extends HtmlView +{ + /** + * Translations view display method + * @return void + */ + function display($tpl = null) + { + if ($this->getLayout() !== 'modal') + { + // Include helper submenu + GetbibleHelper::addSubmenu('translations'); + } + + // Assign data to the view + $this->items = $this->get('Items'); + $this->pagination = $this->get('Pagination'); + $this->state = $this->get('State'); + $this->user = JFactory::getUser(); + // Load the filter form from xml. + $this->filterForm = $this->get('FilterForm'); + // Load the active filters. + $this->activeFilters = $this->get('ActiveFilters'); + // Add the list ordering clause. + $this->listOrder = $this->escape($this->state->get('list.ordering', 'a.id')); + $this->listDirn = $this->escape($this->state->get('list.direction', 'DESC')); + $this->saveOrder = $this->listOrder == 'a.ordering'; + // set the return here value + $this->return_here = urlencode(base64_encode((string) JUri::getInstance())); + // get global action permissions + $this->canDo = GetbibleHelper::getActions('translation'); + $this->canEdit = $this->canDo->get('translation.edit'); + $this->canState = $this->canDo->get('translation.edit.state'); + $this->canCreate = $this->canDo->get('translation.create'); + $this->canDelete = $this->canDo->get('translation.delete'); + $this->canBatch = $this->canDo->get('core.batch'); + + // We don't need toolbar in the modal window. + if ($this->getLayout() !== 'modal') + { + $this->addToolbar(); + $this->sidebar = JHtmlSidebar::render(); + // load the batch html + if ($this->canCreate && $this->canEdit && $this->canState) + { + $this->batchDisplay = JHtmlBatch_::render(); + } + } + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JToolBarHelper::title(JText::_('COM_GETBIBLE_TRANSLATIONS'), 'book'); + JHtmlSidebar::setAction('index.php?option=com_getbible&view=translations'); + JFormHelper::addFieldPath(JPATH_COMPONENT . '/models/fields'); + + if ($this->canCreate) + { + JToolBarHelper::addNew('translation.add'); + } + + // Only load if there are items + if (GetbibleHelper::checkArray($this->items)) + { + if ($this->canEdit) + { + JToolBarHelper::editList('translation.edit'); + } + + if ($this->canState) + { + JToolBarHelper::publishList('translations.publish'); + JToolBarHelper::unpublishList('translations.unpublish'); + JToolBarHelper::archiveList('translations.archive'); + + if ($this->canDo->get('core.admin')) + { + JToolBarHelper::checkin('translations.checkin'); + } + } + + // Add a batch button + if ($this->canBatch && $this->canCreate && $this->canEdit && $this->canState) + { + // Get the toolbar object instance + $bar = JToolBar::getInstance('toolbar'); + // set the batch button name + $title = JText::_('JTOOLBAR_BATCH'); + // Instantiate a new JLayoutFile instance and render the batch button + $layout = new JLayoutFile('joomla.toolbar.batch'); + // add the button to the page + $dhtml = $layout->render(array('title' => $title)); + $bar->appendButton('Custom', $dhtml, 'batch'); + } + + if ($this->state->get('filter.published') == -2 && ($this->canState && $this->canDelete)) + { + JToolbarHelper::deleteList('', 'translations.delete', 'JTOOLBAR_EMPTY_TRASH'); + } + elseif ($this->canState && $this->canDelete) + { + JToolbarHelper::trash('translations.trash'); + } + } + + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('translations'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + + // add the options comp button + if ($this->canDo->get('core.admin') || $this->canDo->get('core.options')) + { + JToolBarHelper::preferences('com_getbible'); + } + + // Only load published batch if state and batch is allowed + if ($this->canState && $this->canBatch) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_STATE'), + 'batch[published]', + JHtml::_('select.options', JHtml::_('jgrid.publishedOptions', array('all' => false)), 'value', 'text', '', true) + ); + } + + // Only load access batch if create, edit and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_ACCESS'), + 'batch[access]', + JHtml::_('select.options', JHtml::_('access.assetgroups'), 'value', 'text') + ); + } + + // Only load Direction batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Direction Selection + $this->directionOptions = JFormHelper::loadFieldType('translationsfilterdirection')->options; + // We do some sanitation for Direction filter + if (GetbibleHelper::checkArray($this->directionOptions) && + isset($this->directionOptions[0]->value) && + !GetbibleHelper::checkString($this->directionOptions[0]->value)) + { + unset($this->directionOptions[0]); + } + // Direction Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_TRANSLATION_DIRECTION_LABEL').' -', + 'batch[direction]', + JHtml::_('select.options', $this->directionOptions, 'value', 'text') + ); + } + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_('COM_GETBIBLE_TRANSLATIONS')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/translations.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 50) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Returns an array of fields the table can be sorted by + * + * @return array Array containing the field name to sort by as the key and display text as value + */ + protected function getSortFields() + { + return array( + 'a.ordering' => JText::_('JGRID_HEADING_ORDERING'), + 'a.published' => JText::_('JSTATUS'), + 'a.translation' => JText::_('COM_GETBIBLE_TRANSLATION_TRANSLATION_LABEL'), + 'a.abbreviation' => JText::_('COM_GETBIBLE_TRANSLATION_ABBREVIATION_LABEL'), + 'a.language' => JText::_('COM_GETBIBLE_TRANSLATION_LANGUAGE_LABEL'), + 'a.direction' => JText::_('COM_GETBIBLE_TRANSLATION_DIRECTION_LABEL'), + 'a.id' => JText::_('JGRID_HEADING_ID') + ); + } +} diff --git a/admin/views/verse/submitbutton.js b/admin/views/verse/submitbutton.js new file mode 100644 index 0000000..82b9203 --- /dev/null +++ b/admin/views/verse/submitbutton.js @@ -0,0 +1,31 @@ +/*----------------------------------------------------------------------------------| io.vdm.dev |----/ + Vast Development Method +/-------------------------------------------------------------------------------------------------------/ + + @package getBible.net + + @created 3rd December, 2015 + @author Llewellyn van der Merwe + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +Joomla.submitbutton = function(task) +{ + if (task == ''){ + return false; + } else { + var action = task.split('.'); + if (action[1] == 'cancel' || action[1] == 'close' || document.formvalidator.isValid(document.getElementById("adminForm"))){ + Joomla.submitform(task, document.getElementById("adminForm")); + return true; + } else { + alert(Joomla.JText._('verse, some values are not acceptable.','Some values are unacceptable')); + return false; + } + } +} \ No newline at end of file diff --git a/admin/views/verse/tmpl/edit.php b/admin/views/verse/tmpl/edit.php new file mode 100644 index 0000000..9600416 --- /dev/null +++ b/admin/views/verse/tmpl/edit.php @@ -0,0 +1,117 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/html'); +JHtml::_('behavior.formvalidator'); +JHtml::_('formbehavior.chosen', 'select'); +JHtml::_('behavior.keepalive'); +$componentParams = $this->params; // will be removed just use $this->params instead +?> + + diff --git a/admin/views/verse/tmpl/index.html b/admin/views/verse/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/verse/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/verse/view.html.php b/admin/views/verse/view.html.php new file mode 100644 index 0000000..09a6322 --- /dev/null +++ b/admin/views/verse/view.html.php @@ -0,0 +1,130 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Verse Html View class + */ +class GetbibleViewVerse extends HtmlView +{ + /** + * display method of View + * @return void + */ + public function display($tpl = null) + { + // set params + $this->params = JComponentHelper::getParams('com_getbible'); + // Assign the variables + $this->form = $this->get('Form'); + $this->item = $this->get('Item'); + $this->script = $this->get('Script'); + $this->state = $this->get('State'); + // get action permissions + $this->canDo = GetbibleHelper::getActions('verse', $this->item); + // get input + $jinput = JFactory::getApplication()->input; + $this->ref = $jinput->get('ref', 0, 'word'); + $this->refid = $jinput->get('refid', 0, 'int'); + $return = $jinput->get('return', null, 'base64'); + // set the referral string + $this->referral = ''; + if ($this->refid && $this->ref) + { + // return to the item that referred to this item + $this->referral = '&ref=' . (string)$this->ref . '&refid=' . (int)$this->refid; + } + elseif($this->ref) + { + // return to the list view that referred to this item + $this->referral = '&ref=' . (string)$this->ref; + } + // check return value + if (!is_null($return)) + { + // add the return value + $this->referral .= '&return=' . (string)$return; + } + + // Set the toolbar + $this->addToolBar(); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JFactory::getApplication()->input->set('hidemainmenu', true); + JToolBarHelper::title(JText::_('COM_GETBIBLE_VERSE_READONLY'), 'verse'); + JToolBarHelper::cancel('verse.cancel', 'JTOOLBAR_CLOSE'); + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 30) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true, 30); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + $isNew = ($this->item->id < 1); + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_($isNew ? 'COM_GETBIBLE_VERSE_NEW' : 'COM_GETBIBLE_VERSE_EDIT')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/verse.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + $this->document->addScript(JURI::root() . $this->script, (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + $this->document->addScript(JURI::root() . "administrator/components/com_getbible/views/verse/submitbutton.js", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/javascript'); + JText::script('view not acceptable. Error'); + } +} diff --git a/admin/views/verses/index.html b/admin/views/verses/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/verses/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/verses/tmpl/default.php b/admin/views/verses/tmpl/default.php new file mode 100644 index 0000000..bb29d6c --- /dev/null +++ b/admin/views/verses/tmpl/default.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JHtml::_('behavior.multiselect'); +JHtml::_('dropdown.init'); +JHtml::_('formbehavior.chosen', '.multipleAccessLevels', null, array('placeholder_text_multiple' => '- ' . JText::_('COM_GETBIBLE_FILTER_SELECT_ACCESS') . ' -')); +JHtml::_('formbehavior.chosen', 'select'); +if ($this->saveOrder) +{ + $saveOrderingUrl = 'index.php?option=com_getbible&task=verses.saveOrderAjax&tmpl=component'; + JHtml::_('sortablelist.sortable', 'verseList', 'adminForm', strtolower($this->listDirn), $saveOrderingUrl); +} +?> +
+sidebar)): ?> +
+ sidebar; ?> +
+
+ +
+ + $this)); +?> +items)): ?> +
+ +
+ + + loadTemplate('head');?> + loadTemplate('foot');?> + loadTemplate('body');?> +
+ + canCreate && $this->canEdit) : ?> + JText::_('COM_GETBIBLE_VERSES_BATCH_OPTIONS'), + 'footer' => $this->loadTemplate('batch_footer') + ), + $this->loadTemplate('batch_body') + ); ?> + + +
+ + + + diff --git a/admin/views/verses/tmpl/default_batch_body.php b/admin/views/verses/tmpl/default_batch_body.php new file mode 100644 index 0000000..7cc9e9e --- /dev/null +++ b/admin/views/verses/tmpl/default_batch_body.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + +

+batchDisplay; ?> \ No newline at end of file diff --git a/admin/views/verses/tmpl/default_batch_footer.php b/admin/views/verses/tmpl/default_batch_footer.php new file mode 100644 index 0000000..aa9022b --- /dev/null +++ b/admin/views/verses/tmpl/default_batch_footer.php @@ -0,0 +1,29 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + + + \ No newline at end of file diff --git a/admin/views/verses/tmpl/default_body.php b/admin/views/verses/tmpl/default_body.php new file mode 100644 index 0000000..7574671 --- /dev/null +++ b/admin/views/verses/tmpl/default_body.php @@ -0,0 +1,112 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +$edit = "index.php?option=com_getbible&view=verses&task=verse.edit"; + +?> +items as $i => $item): ?> + user->authorise('core.manage', 'com_checkin') || $item->checked_out == $this->user->id || $item->checked_out == 0; + $userChkOut = JFactory::getUser($item->checked_out); + $canDo = GetbibleHelper::getActions('verse',$item,'verses'); + ?> + + + get('verse.edit.state')): ?> + saveOrder) + { + $iconClass = ' inactive tip-top" hasTooltip" title="' . JHtml::tooltipText('JORDERINGDISABLED'); + } + ?> + + + + saveOrder) : ?> + + + + ⋮ + + + + get('verse.edit')): ?> + checked_out) : ?> + + id); ?> + + □ + + + id); ?> + + + □ + + + +
+ get('verse.edit')): ?> + escape($item->book_nr); ?> + checked_out): ?> + name, $item->checked_out_time, 'verses.', $canCheckin); ?> + + + escape($item->book_nr); ?> + +
+ + + escape($item->chapter); ?> + + + escape($item->verse); ?> + + +
+ user->authorise('translation.edit', 'com_getbible.translation.' . (int) $item->abbreviation_id)): ?> + escape($item->abbreviation_translation); ?> + + escape($item->abbreviation_translation); ?> + +
+ + + get('verse.edit.state')) : ?> + checked_out) : ?> + + published, $i, 'verses.', true, 'cb'); ?> + + published, $i, 'verses.', false, 'cb'); ?> + + + published, $i, 'verses.', true, 'cb'); ?> + + + published, $i, 'verses.', false, 'cb'); ?> + + + + id; ?> + + + \ No newline at end of file diff --git a/admin/views/verses/tmpl/default_foot.php b/admin/views/verses/tmpl/default_foot.php new file mode 100644 index 0000000..290760a --- /dev/null +++ b/admin/views/verses/tmpl/default_foot.php @@ -0,0 +1,24 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + pagination->getListFooter(); ?> + \ No newline at end of file diff --git a/admin/views/verses/tmpl/default_head.php b/admin/views/verses/tmpl/default_head.php new file mode 100644 index 0000000..fe2a643 --- /dev/null +++ b/admin/views/verses/tmpl/default_head.php @@ -0,0 +1,62 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + canEdit&& $this->canState): ?> + + listDirn, $this->listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?> + + + + + + + ▾ + + + ■ + + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + + listDirn, $this->listOrder); ?> + + canState): ?> + + listDirn, $this->listOrder); ?> + + + + + + + + listDirn, $this->listOrder); ?> + + \ No newline at end of file diff --git a/admin/views/verses/tmpl/default_toolbar.php b/admin/views/verses/tmpl/default_toolbar.php new file mode 100644 index 0000000..cc28bb4 --- /dev/null +++ b/admin/views/verses/tmpl/default_toolbar.php @@ -0,0 +1,51 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
+ +
+ + +
+
+ + pagination->getLimitBox(); ?> +
+
+ + +
+
+ + +
+
+
\ No newline at end of file diff --git a/admin/views/verses/tmpl/index.html b/admin/views/verses/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/admin/views/verses/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/verses/view.html.php b/admin/views/verses/view.html.php new file mode 100644 index 0000000..c55b187 --- /dev/null +++ b/admin/views/verses/view.html.php @@ -0,0 +1,310 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Getbible Html View class for the Verses + */ +class GetbibleViewVerses extends HtmlView +{ + /** + * Verses view display method + * @return void + */ + function display($tpl = null) + { + if ($this->getLayout() !== 'modal') + { + // Include helper submenu + GetbibleHelper::addSubmenu('verses'); + } + + // Assign data to the view + $this->items = $this->get('Items'); + $this->pagination = $this->get('Pagination'); + $this->state = $this->get('State'); + $this->user = JFactory::getUser(); + // Load the filter form from xml. + $this->filterForm = $this->get('FilterForm'); + // Load the active filters. + $this->activeFilters = $this->get('ActiveFilters'); + // Add the list ordering clause. + $this->listOrder = $this->escape($this->state->get('list.ordering', 'a.id')); + $this->listDirn = $this->escape($this->state->get('list.direction', 'DESC')); + $this->saveOrder = $this->listOrder == 'a.ordering'; + // set the return here value + $this->return_here = urlencode(base64_encode((string) JUri::getInstance())); + // get global action permissions + $this->canDo = GetbibleHelper::getActions('verse'); + $this->canEdit = $this->canDo->get('verse.edit'); + $this->canState = $this->canDo->get('verse.edit.state'); + $this->canCreate = $this->canDo->get('verse.create'); + $this->canDelete = $this->canDo->get('verse.delete'); + $this->canBatch = $this->canDo->get('core.batch'); + + // We don't need toolbar in the modal window. + if ($this->getLayout() !== 'modal') + { + $this->addToolbar(); + $this->sidebar = JHtmlSidebar::render(); + // load the batch html + if ($this->canCreate && $this->canEdit && $this->canState) + { + $this->batchDisplay = JHtmlBatch_::render(); + } + } + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JToolBarHelper::title(JText::_('COM_GETBIBLE_VERSES'), 'generic'); + JHtmlSidebar::setAction('index.php?option=com_getbible&view=verses'); + JFormHelper::addFieldPath(JPATH_COMPONENT . '/models/fields'); + + if ($this->canCreate) + { + JToolBarHelper::addNew('verse.add'); + } + + // Only load if there are items + if (GetbibleHelper::checkArray($this->items)) + { + if ($this->canEdit) + { + JToolBarHelper::editList('verse.edit'); + } + + if ($this->canState) + { + JToolBarHelper::publishList('verses.publish'); + JToolBarHelper::unpublishList('verses.unpublish'); + JToolBarHelper::archiveList('verses.archive'); + + if ($this->canDo->get('core.admin')) + { + JToolBarHelper::checkin('verses.checkin'); + } + } + + // Add a batch button + if ($this->canBatch && $this->canCreate && $this->canEdit && $this->canState) + { + // Get the toolbar object instance + $bar = JToolBar::getInstance('toolbar'); + // set the batch button name + $title = JText::_('JTOOLBAR_BATCH'); + // Instantiate a new JLayoutFile instance and render the batch button + $layout = new JLayoutFile('joomla.toolbar.batch'); + // add the button to the page + $dhtml = $layout->render(array('title' => $title)); + $bar->appendButton('Custom', $dhtml, 'batch'); + } + + if ($this->state->get('filter.published') == -2 && ($this->canState && $this->canDelete)) + { + JToolbarHelper::deleteList('', 'verses.delete', 'JTOOLBAR_EMPTY_TRASH'); + } + elseif ($this->canState && $this->canDelete) + { + JToolbarHelper::trash('verses.trash'); + } + } + + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('verses'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + + // add the options comp button + if ($this->canDo->get('core.admin') || $this->canDo->get('core.options')) + { + JToolBarHelper::preferences('com_getbible'); + } + + // Only load published batch if state and batch is allowed + if ($this->canState && $this->canBatch) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_STATE'), + 'batch[published]', + JHtml::_('select.options', JHtml::_('jgrid.publishedOptions', array('all' => false)), 'value', 'text', '', true) + ); + } + + // Only load access batch if create, edit and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + JHtmlBatch_::addListSelection( + JText::_('COM_GETBIBLE_KEEP_ORIGINAL_ACCESS'), + 'batch[access]', + JHtml::_('select.options', JHtml::_('access.assetgroups'), 'value', 'text') + ); + } + + // Only load Book Nr batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Book Nr Selection + $this->book_nrOptions = JFormHelper::loadFieldType('versesfilterbooknr')->options; + // We do some sanitation for Book Nr filter + if (GetbibleHelper::checkArray($this->book_nrOptions) && + isset($this->book_nrOptions[0]->value) && + !GetbibleHelper::checkString($this->book_nrOptions[0]->value)) + { + unset($this->book_nrOptions[0]); + } + // Book Nr Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_VERSE_BOOK_NR_LABEL').' -', + 'batch[book_nr]', + JHtml::_('select.options', $this->book_nrOptions, 'value', 'text') + ); + } + + // Only load Chapter batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Chapter Selection + $this->chapterOptions = JFormHelper::loadFieldType('versesfilterchapter')->options; + // We do some sanitation for Chapter filter + if (GetbibleHelper::checkArray($this->chapterOptions) && + isset($this->chapterOptions[0]->value) && + !GetbibleHelper::checkString($this->chapterOptions[0]->value)) + { + unset($this->chapterOptions[0]); + } + // Chapter Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_VERSE_CHAPTER_LABEL').' -', + 'batch[chapter]', + JHtml::_('select.options', $this->chapterOptions, 'value', 'text') + ); + } + + // Only load Verse batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Verse Selection + $this->verseOptions = JFormHelper::loadFieldType('versesfilterverse')->options; + // We do some sanitation for Verse filter + if (GetbibleHelper::checkArray($this->verseOptions) && + isset($this->verseOptions[0]->value) && + !GetbibleHelper::checkString($this->verseOptions[0]->value)) + { + unset($this->verseOptions[0]); + } + // Verse Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_VERSE_VERSE_LABEL').' -', + 'batch[verse]', + JHtml::_('select.options', $this->verseOptions, 'value', 'text') + ); + } + + // Only load Abbreviation Translation batch if create, edit, and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + // Set Abbreviation Translation Selection + $this->abbreviationTranslationOptions = JFormHelper::loadFieldType('Translations')->options; + // We do some sanitation for Abbreviation Translation filter + if (GetbibleHelper::checkArray($this->abbreviationTranslationOptions) && + isset($this->abbreviationTranslationOptions[0]->value) && + !GetbibleHelper::checkString($this->abbreviationTranslationOptions[0]->value)) + { + unset($this->abbreviationTranslationOptions[0]); + } + // Abbreviation Translation Batch Selection + JHtmlBatch_::addListSelection( + '- Keep Original '.JText::_('COM_GETBIBLE_VERSE_ABBREVIATION_LABEL').' -', + 'batch[abbreviation]', + JHtml::_('select.options', $this->abbreviationTranslationOptions, 'value', 'text') + ); + } + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + if (!isset($this->document)) + { + $this->document = JFactory::getDocument(); + } + $this->document->setTitle(JText::_('COM_GETBIBLE_VERSES')); + $this->document->addStyleSheet(JURI::root() . "administrator/components/com_getbible/assets/css/verses.css", (GetbibleHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css'); + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 50) + { + // use the helper htmlEscape method instead and shorten the string + return GetbibleHelper::htmlEscape($var, $this->_charset, true); + } + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset); + } + + /** + * Returns an array of fields the table can be sorted by + * + * @return array Array containing the field name to sort by as the key and display text as value + */ + protected function getSortFields() + { + return array( + 'a.ordering' => JText::_('JGRID_HEADING_ORDERING'), + 'a.published' => JText::_('JSTATUS'), + 'a.book_nr' => JText::_('COM_GETBIBLE_VERSE_BOOK_NR_LABEL'), + 'a.chapter' => JText::_('COM_GETBIBLE_VERSE_CHAPTER_LABEL'), + 'a.verse' => JText::_('COM_GETBIBLE_VERSE_VERSE_LABEL'), + 'g.translation' => JText::_('COM_GETBIBLE_VERSE_ABBREVIATION_LABEL'), + 'a.id' => JText::_('JGRID_HEADING_ID') + ); + } +} diff --git a/getbible.xml b/getbible.xml new file mode 100644 index 0000000..bec23c9 --- /dev/null +++ b/getbible.xml @@ -0,0 +1,120 @@ + + + COM_GETBIBLE + 26th July, 2023 + Llewellyn van der Merwe + joomla@vdm.io + https://getbible.net + Copyright (C) 2015. All Rights Reserved + GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + 2.0.1 + Get Bible (v.2.0.1) +
+

Welcome to the next level of scripture engagement - The Bible for Joomla! Our purpose is to bring the Word of God to every person, in their native language, entirely free. This isn't just a typical extension; it's a groundbreaking tool developed to span language divides and deliver a rich, customizable Bible study experience to users worldwide. + +With an impressive array of 80 translations, our Joomla extension allows people from all corners of the globe to read, comprehend, and meditate on the Holy Scriptures in their preferred language. Moreover, we offer the unique opportunity for individuals to host the Bible on their own website, further extending the reach of the Word. + +We've integrated robust features such as note-taking, tagging, and a search function, to enhance your interaction with the Scriptures. This allows users to immerse themselves in the text, crafting a personal journey through the Bible that can be revisited in future sessions. Furthermore, our innovative linker system assigns each visitor a unique identifier (GUID) - no login required. This means you can create notes, select favorite verses, and even share sessions, while maintaining control over your personalized content. + +A distinctive feature of our application is the integration with OpenAI. This advanced capability allows website owners to create custom prompts to interact with OpenAI using text from any translation. This function allows you to ask questions, gain clarity, and deepen your understanding of the Scriptures in an engaging and user-friendly manner. + +In essence, The Bible for Joomla is designed to transform how the Word of God is shared, studied, and comprehended. Its comprehensive features, combined with a user-friendly interface, make it an essential tool for individuals, churches, and website owners alike. Join us on this journey of faith as we make the wisdom and guidance of the Scriptures accessible to all, one verse, one language, and one website at a time.

+

Created by Llewellyn van der Merwe
Development started 3rd December, 2015

+ ]]>
+ + + + + sql/install.mysql.utf8.sql + + + + + + + sql/uninstall.mysql.utf8.sql + + + + + script.php + + + index.html + js + css + images + nouislider + datatable + uikit-v3 + + + + + + sql/updates/mysql/ + + + + + controller.php + index.html + router.php + getbible.php + router.php + assets + helpers + controllers + models + views + layouts + + + + language/en-GB/en-GB.com_getbible.ini + language/en-GB/en-GB.com_getbible.sys.ini + + + + COM_GETBIBLE_MENU + + + COM_GETBIBLE_MENU_LINKERS + COM_GETBIBLE_MENU_NOTES + COM_GETBIBLE_MENU_TAGGED_VERSES + COM_GETBIBLE_MENU_PROMPTS + COM_GETBIBLE_MENU_OPEN_AI_RESPONSES + COM_GETBIBLE_MENU_TAGS + COM_GETBIBLE_MENU_TRANSLATIONS + COM_GETBIBLE_MENU_BOOKS + COM_GETBIBLE_MENU_CHAPTERS + COM_GETBIBLE_MENU_VERSES + + + access.xml + config.xml + controller.php + index.html + getbible.php + README.txt + assets + controllers + helpers + models + sql + tables + views + layouts + + + + language/en-GB/en-GB.com_getbible.ini + language/en-GB/en-GB.com_getbible.sys.ini + + + + + https://git.vdm.dev/getBible/joomla-component/raw/branch/master/update_server.xml + +
\ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/.htaccess b/libraries/jcb_powers/.htaccess new file mode 100644 index 0000000..9afb1a1 --- /dev/null +++ b/libraries/jcb_powers/.htaccess @@ -0,0 +1,9 @@ +# Apache 2.4+ + + Require all denied + + +# Apache 2.0-2.2 + + Deny from all + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/index.html b/libraries/jcb_powers/VDM.Joomla.GetBible/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/AI.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/AI.php new file mode 100644 index 0000000..927d809 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/AI.php @@ -0,0 +1,104 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible; + + +use VDM\Joomla\GetBible\Openai\Config; +use VDM\Joomla\GetBible\Data\Response; +use VDM\Joomla\GetBible\AI\Engineer; + + +/** + * The GetBible AI + * + * @since 2.0.1 + */ +final class AI +{ + /** + * The Config class + * + * @var Config + * @since 2.0.1 + */ + protected Config $config; + + /** + * The Response class + * + * @var Response + * @since 2.0.1 + */ + protected Response $response; + + /** + * The Engineer class + * + * @var Engineer + * @since 2.0.1 + */ + protected Engineer $engineer; + + /** + * Constructor + * + * @param Config $config The response object. + * @param Response $response The response object. + * @param Engineer $engineer The engineer object. + * + * @since 2.0.1 + */ + public function __construct(Config $config, Response $response, Engineer $engineer) + { + $this->config = $config; + $this->response = $response; + $this->engineer = $engineer; + } + + /** + * Get the Open AI response + * + * @return array|null Array of response messages + * @since 2.0.1 + */ + public function get(): ?array + { + // If Open AI isn't enabled in the config, we return null right away. + if (!$this->config->get('enable_open_ai')) + { + return null; + } + + // If we have enough responses already, return them. + $response = $this->response->get(); + if ($this->response->isEnough()) + { + return $response; + } + + // If there is no existing response and engineer has any response, return it. + if (empty($response)) + { + return $this->engineer->get(); + } + + // If there are existing responses, we append the first response from the engineer (if any). + $_response = $this->engineer->get(); + if (!empty($_response)) + { + $response[] = $_response[0]; + } + + return $response; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/AI/Engineer.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/AI/Engineer.php new file mode 100644 index 0000000..4aa4dbb --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/AI/Engineer.php @@ -0,0 +1,308 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\AI; + + +use VDM\Joomla\GetBible\Data\Scripture; +use VDM\Joomla\GetBible\Data\Prompt; +use VDM\Joomla\GetBible\Data\Placeholders; +use VDM\Joomla\Openai\Chat; +use VDM\Joomla\GetBible\Database\Insert; + + +/** + * The GetBible AI Engineer + * + * @since 2.0.1 + */ +final class Engineer +{ + /** + * The Scripture class + * + * @var Scripture + * @since 2.0.1 + */ + protected Scripture $scripture; + + /** + * The Prompt class + * + * @var Prompt + * @since 2.0.1 + */ + protected Prompt $prompt; + + /** + * The Placeholders class + * + * @var Placeholders + * @since 2.0.1 + */ + protected Placeholders $placeholders; + + /** + * The Chat class + * + * @var Chat + * @since 2.0.1 + */ + protected Chat $chat; + + /** + * The Insert class + * + * @var Insert + * @since 2.0.1 + */ + protected Insert $insert; + + /** + * The request messages + * + * @var array|null + * @since 2.0.1 + */ + protected ?array $messages = null; + + /** + * The response object + * + * @var object|null + * @since 2.0.1 + */ + protected ?object $response = null; + + /** + * Constructor + * + * @param Scripture $scripture The scripture object. + * @param Prompt $prompt The prompt object. + * @param Placeholders $placeholders The placeholders object. + * @param Chat $chat The chat object. + * @param Insert $insert The insert object. + * + * @since 2.0.1 + */ + public function __construct( + Scripture $scripture, + Prompt $prompt, + Placeholders $placeholders, + Chat $chat, + Insert $insert) + { + $this->scripture = $scripture; + $this->prompt = $prompt; + $this->placeholders = $placeholders; + $this->chat = $chat; + $this->insert = $insert; + } + + /** + * Return the current data state + * + * @return array|null True on success + * @since 2.0.1 + */ + public function get(): ?array + { + if ($this->getResponse() && $this->modelMessages() && $this->modelResponse() + && $this->saveResponse() && $this->saveMessages()) + { + // add this response's messages + $this->response->messages = $this->messages ?? ''; + + return [ + $this->response + ]; + } + + return null; + } + + /** + * Save the messages + * + * @return bool True on success + * @since 2.0.1 + */ + private function saveMessages(): bool + { + return $this->insert->items($this->messages, 'open_ai_message'); + } + + /** + * Save the response + * + * @return bool True on success + * @since 2.0.1 + */ + private function saveResponse(): bool + { + return $this->insert->item($this->response, 'open_ai_response'); + } + + /** + * Prep the response data + * + * @return bool True on success + * @since 2.0.1 + */ + private function modelResponse(): bool + { + if ($this->response) + { + $data = new \stdClass(); + // Bible link + $data->abbreviation = $this->scripture->get('translation_abbreviation', ''); + $data->language = $this->scripture->get('translation_language', ''); + $data->lcsh = $this->scripture->get('translation_lcsh', ''); + $data->book = $this->scripture->get('book_number', ''); + $data->chapter = $this->scripture->get('chapter_number', ''); + $data->verse = $this->scripture->get('verse_number', ''); + $data->word = $this->scripture->get('selected_word_number', ''); + $data->selected_word = $this->scripture->get('selected_word_text', ''); + // Prompt data + $data->prompt = $this->prompt->getGuid(); + $data->model = $this->prompt->getModel(); + $data->max_tokens = $this->prompt->getMaxTokens(); + $data->temperature = $this->prompt->getTemperature(); + $data->top_p = $this->prompt->getTopP(); + $data->presence_penalty = $this->prompt->getPresencePenalty(); + $data->frequency_penalty = $this->prompt->getFrequencyPenalty(); + $data->n = ''; + // Response data + $data->response_id = $this->response->id ?? ''; + $data->response_object = $this->response->object ?? ''; + $data->response_model = $this->response->model ?? ''; + $data->response_created = $this->response->created ?? ''; + $data->prompt_tokens = $this->response->usage->prompt_tokens ?? ''; + $data->completion_tokens = $this->response->usage->completion_tokens ?? ''; + $data->total_tokens = $this->response->usage->total_tokens ?? ''; + + $this->response = $data; + + return true; + } + + return false; + } + + /** + * Prep the messages + * + * @return bool True on success + * @since 2.0.1 + */ + private function modelMessages(): bool + { + if (isset($this->response->choices) && + is_array($this->response->choices) && + $this->response->choices !== []) + { + // set some global keys + $open_ai_response = $this->response->id ?? ''; + $prompt = $this->prompt->getGuid(); + // if Persistently we archive this response + $cache_type = $this->prompt->getCacheBehaviour(); + $state = ($cache_type == 0) ? 2 : 1; + + // update the system messages + $index = (int) 0 - count($this->messages); + foreach ($this->messages as $n => &$message) + { + $message->prompt = $prompt; + $message->open_ai_response = $open_ai_response; + $message->source = 1; // prompt as source + $message->index = $index; + $message->published = $state; + + $index++; + } + + // now add the response messages + foreach ($this->response->choices as $choice) + { + $choice->message->prompt = $prompt; + $choice->message->open_ai_response = $open_ai_response; + $choice->message->source = 2; // open AI as source + $choice->message->index = $choice->index; + $choice->message->name = 'getBible-Open-AI'; + $choice->message->published = $state; + + $this->messages[] = $choice->message; + } + + // we remove it from the response object + unset($this->response->choices); + + return true; + } + + return false; + } + + /** + * Get the Open AI response + * + * @return bool True on success + * @since 2.0.1 + */ + private function getResponse(): bool + { + if (($this->messages = $this->getMessages()) !== null) + { + $this->response = $this->chat->create( + $this->prompt->getModel(), + $this->messages, + $this->prompt->getMaxTokens(), + $this->prompt->getTemperature(), + $this->prompt->getTopP(), + $this->prompt->getN(), + null, + null, + $this->prompt->getPresencePenalty(), + $this->prompt->getFrequencyPenalty(), + null + ); + + return true; + } + + return false; + } + + /** + * Get the ready to use prompt messages + * + * @return array|null Array of prompt messages + * @since 2.0.1 + */ + private function getMessages(): ?array + { + if (($placeholders = $this->placeholders->get()) !== null && + ($messages = $this->prompt->getMessages()) !== null) + { + return array_map(function ($message) use($placeholders) { + $message->content = str_replace( + array_keys($placeholders), + array_values($placeholders), + $message->content + ); + return $message; + }, $messages); + } + + return null; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/AI/index.html b/libraries/jcb_powers/VDM.Joomla.GetBible/src/AI/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/AI/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Abstraction/Api.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Abstraction/Api.php new file mode 100644 index 0000000..c2b23ca --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Abstraction/Api.php @@ -0,0 +1,67 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Abstraction; + + +use VDM\Joomla\GetBible\Utilities\Http; +use VDM\Joomla\GetBible\Utilities\Uri; +use VDM\Joomla\GetBible\Utilities\Response; + + +/** + * The GetBible Api + * + * @since 2.0.1 + */ +abstract class Api +{ + /** + * The Http class + * + * @var Http + * @since 2.0.1 + */ + protected Http $http; + + /** + * The Uri class + * + * @var Uri + * @since 2.0.1 + */ + protected Uri $uri; + + /** + * The Response class + * + * @var Response + * @since 2.0.1 + */ + protected Response $response; + + /** + * Constructor. + * + * @param Http $http The http class. + * @param Uri $uri The uri class. + * @param Response $response The response class. + * + * @since 2.0.1 + **/ + public function __construct(Http $http, Uri $uri, Response $response) + { + $this->http = $http; + $this->uri = $uri; + $this->response = $response; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Abstraction/index.html b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Abstraction/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Abstraction/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Api/Books.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Api/Books.php new file mode 100644 index 0000000..12a36ca --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Api/Books.php @@ -0,0 +1,96 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Api; + + +use VDM\Joomla\GetBible\Abstraction\Api; + + +/** + * The GetBible Books + * + * @since 2.0.1 + */ +final class Books extends Api +{ + /** + * Get the books in a translation + * + * @param string $translation The translation. + * + * @return object|null The response object or null if an error occurs. + * @since 2.0.1 + */ + public function get(string $translation = 'kjv'): ?object + { + return $this->response->get( + $this->http->get( + $this->uri->get($translation . '.json') + ) + ); + } + + /** + * List the books in a translation + * + * @param string $translation The translation. + * + * @return object|null The response object or null if an error occurs. + * @since 2.0.1 + */ + public function list(string $translation = 'kjv'): ?object + { + return $this->response->get( + $this->http->get( + $this->uri->get($translation . '/books.json') + ) + ); + } + + /** + * List the books checksums in a translation + * + * @param string $translation The translation. + * + * @return object|null The response object or null if an error occurs. + * @since 2.0.1 + */ + public function checksum(string $translation = 'kjv'): ?object + { + return $this->response->get( + $this->http->get( + $this->uri->get($translation . '/checksum.json') + ) + ); + } + + /** + * Get the book's checksums in a translation + * + * @param string $translation The translation. + * @param int $book The book number. + * + * @return string|null The response checksums or null if an error occurs. + * @since 2.0.1 + */ + public function sha(string $translation, int $book): ?string + { + return trim( + $this->response->get( + $this->http->get( + $this->uri->get($translation . '/' . $book . '.sha') + ) + ) + ); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Api/Chapters.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Api/Chapters.php new file mode 100644 index 0000000..0e9d06e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Api/Chapters.php @@ -0,0 +1,100 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Api; + + +use VDM\Joomla\GetBible\Abstraction\Api; + + +/** + * The GetBible Book Chapters + * + * @since 2.0.1 + */ +final class Chapters extends Api +{ + /** + * Get the chapters in a book in a translation + * + * @param string $translation The translation. + * @param int $book The book number. + * + * @return object|null The response object or null if an error occurs. + * @since 2.0.1 + */ + public function get(string $translation, int $book): ?object + { + return $this->response->get( + $this->http->get( + $this->uri->get($translation . '/' . $book . '.json') + ) + ); + } + + /** + * List the chapters of a book in a translation + * + * @param string $translation The translation. + * @param int $book The book number. + * + * @return object|null The response object or null if an error occurs. + * @since 2.0.1 + */ + public function list( string $translation, int $book): ?object + { + return $this->response->get( + $this->http->get( + $this->uri->get($translation . '/' . $book . '/chapters.json') + ) + ); + } + + /** + * List the chapters checksums of a book in a translation + * + * @param string $translation The translation. + * @param int $book The book number. + * + * @return object|null The response object or null if an error occurs. + * @since 2.0.1 + */ + public function checksum(string $translation, int $book): ?object + { + return $this->response->get( + $this->http->get( + $this->uri->get($translation . '/' . $book . '/checksum.json') + ) + ); + } + + /** + * Get the chapter's checksums of a book in a translation + * + * @param string $translation The translation. + * @param int $book The book number. + * @param int $chapter The chapter number. + * + * @return string|null The response checksum or null if an error occurs. + * @since 2.0.1 + */ + public function sha(string $translation, int $book, int $chapter): ?string + { + return trim( + $this->response->get( + $this->http->get( + $this->uri->get($translation . '/' . $book . '/' . $chapter . '.sha') + ) + ) + ); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Api/Translations.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Api/Translations.php new file mode 100644 index 0000000..4ff0648 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Api/Translations.php @@ -0,0 +1,74 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Api; + + +use VDM\Joomla\GetBible\Abstraction\Api; + + +/** + * The GetBible Translations + * + * @since 2.0.1 + */ +final class Translations extends Api +{ + /** + * List the translations + * + * @return object|null The response object or null if an error occurs. + * @since 2.0.1 + */ + public function list(): ?object + { + return $this->response->get( + $this->http->get( + $this->uri->get('translations.json') + ) + ); + } + + /** + * List the translations checksums + * + * @return object|null The response object or null if an error occurs. + * @since 2.0.1 + */ + public function checksum(): ?object + { + return $this->response->get( + $this->http->get( + $this->uri->get('checksum.json') + ) + ); + } + + /** + * Get the translation's checksums + * + * @param string $translation The translation. + * + * @return string|null The response checksum or null if an error occurs. + * @since 2.0.1 + */ + public function sha(string $translation = 'kjv'): ?string + { + return trim( + $this->response->get( + $this->http->get( + $this->uri->get($translation . '.sha') + ) + ) + ); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Api/Verses.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Api/Verses.php new file mode 100644 index 0000000..8110f72 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Api/Verses.php @@ -0,0 +1,44 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Api; + + +use VDM\Joomla\GetBible\Abstraction\Api; + + +/** + * The GetBible Book Chapter Verses + * + * @since 2.0.1 + */ +final class Verses extends Api +{ + /** + * Get the verses of chapter in a book in a translation + * + * @param string $translation The translation. + * @param int $book The book number. + * @param int $chapter The chapter number. + * + * @return object|null The response object or null if an error occurs. + * @since 2.0.1 + */ + public function get(string $translation, int $book, int $chapter): ?object + { + return $this->response->get( + $this->http->get( + $this->uri->get($translation . '/' . $book . '/' . $chapter . '.json') + ) + ); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Api/index.html b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Api/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Api/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Config.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Config.php new file mode 100644 index 0000000..1221c33 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Config.php @@ -0,0 +1,81 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible; + + +use VDM\Joomla\Utilities\Component\Helper; +use VDM\Joomla\Abstraction\BaseConfig; + + +/** + * GetBible Configurations + * + * @since 2.0.1 + */ +class Config extends BaseConfig +{ + /** + * get Bible API url + * + * @return string The API Endpoint + * @since 2.0.1 + */ + protected function getEndpoint(): ?string + { + return $this->schema . '://' . $this->domain . '/' . $this->version . '/'; + } + + /** + * get Bible API Schema + * + * @return string The Get Bible Schema + * @since 2.0.1 + */ + protected function getSchema(): ?string + { + return 'https'; + } + + /** + * get Bible API domain + * + * @return string The Get Bible Domain + * @since 2.0.1 + */ + protected function getDomain(): ?string + { + return 'api.getbible.net'; + } + + /** + * get Bible version + * + * @return string The Get Bible Version + * @since 2.0.1 + */ + protected function getVersion(): ?string + { + return 'v2'; + } + + /** + * get Daily Scripture URL + * + * @return string The Get Daily Scripture URL + * @since 2.0.1 + */ + protected function getDailyscriptureurl(): ?string + { + return 'https://raw.githubusercontent.com/trueChristian/daily-scripture/master/README.today'; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/DailyScripture.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/DailyScripture.php new file mode 100644 index 0000000..46cf947 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/DailyScripture.php @@ -0,0 +1,244 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible; + + +use VDM\Joomla\GetBible\Config; +use VDM\Joomla\GetBible\Utilities\Http; +use VDM\Joomla\GetBible\Database\Load; + + +/** + * The GetBible Daily Scripture + * + * @since 2.0.1 + */ +final class DailyScripture +{ + /** + * The book number + * + * @var string|null + * @since 2.0.1 + */ + protected ?int $book = null; + + /** + * The chapter number + * + * @var int|null + * @since 2.0.1 + */ + protected ?int $chapter = null; + + /** + * The verses string + * + * @var string|null + * @since 2.0.1 + */ + protected ?string $verses = null; + + /** + * The reference string + * + * @var string|null + * @since 2.0.1 + */ + protected ?string $reference = null; + + /** + * The load object + * + * @var Load + * @since 2.0.1 + */ + protected Load $load; + + /** + * The active verse + * + * @var string + * @since 2.0.1 + */ + protected string $active = ''; + + /** + * Constructor + * + * @param Config $config The config object. + * @param Http $http The http object. + * @param Load $load The load object. + * + * @since 2.0.1 + */ + public function __construct(Config $config, Http $http, Load $load) + { + $response = $http->get($config->daily_scripture_url); + + // make sure we got the correct response + if ($response->code == 200 && isset($response->body) && is_string($response->body)) + { + $this->reference = $response->body; + + $this->parse($this->reference); + } + + $this->load = $load; + } + + /** + * method to validate if this is still the daily verse + * + * @return bool true if it is daily + * @since 2.0.1 + */ + public function isDaily(): bool + { + return (strcasecmp($this->active, $this->reference) == 0); + } + + /** + * An option to load another reference + * + * @param string $reference The scriptural reference. + * + * @since 2.0.1 + */ + public function load(string $reference) + { + // convert book name to book number + if (($name = $this->extract($reference)) !== null) + { + if (($number = $this->load->value( + ['name' => $name], 'nr', 'book')) === null) + { + // the book number could not be found + return; + } + + $reference = $this->replace($reference, $name, $number); + } + + $this->parse($reference); + + if ($this->book === null) + { + $this->parse($this->reference); + } + } + + /** + * Get the book number from the reference + * + * @return int|null Book number + * @since 2.0.1 + */ + public function book(): ?int + { + return $this->book; + } + + /** + * Get the chapter from the reference + * + * @return int|null Chapter number + * @since 2.0.1 + */ + public function chapter(): ?int + { + return $this->chapter; + } + + /** + * Get the verses from the reference + * + * @return string|null Verses + * @since 2.0.1 + */ + public function verses(): ?string + { + return $this->verses; + } + + /** + * Parse the scriptural reference + * + * @param string $reference The scriptural reference. + * + * @since 2.0.1 + */ + private function parse(string $reference) + { + $this->active = $reference; + $parts = explode(' ', $reference); + + $this->book = (isset($parts[0]) && is_numeric($parts[0])) ? intval($parts[0]) : null; + $chapterVerses = isset($parts[1]) ? explode(':', $parts[1]) : [null, null]; + + $this->chapter = (isset($chapterVerses[0]) && is_numeric($chapterVerses[0])) ? intval($chapterVerses[0]) : null; + $this->verses = isset($chapterVerses[1]) ? trim($chapterVerses[1]) : null; + } + + /** + * Extract the book name from the reference + * + * @return string|null Book name + * @since 2.0.1 + */ + private function extract(string $reference): ?string + { + // Use regex to match and remove chapter:verse and their variations (if they exist) from the end of the string + // This new regex considers Unicode word boundaries + $bookName = preg_replace('/\b\d+(:(\d+([,-]\d+)*)?\b)*$/u', '', $reference); + + // If there's no match or the remaining string is empty or numeric, return null + // The is_numeric check has been adjusted to work for Unicode strings + if (mb_strlen(trim($bookName)) === 0 || preg_match('/^\d+$/u', $bookName)) + { + return null; + } + + return trim($bookName); + } + + /** + * Replace the book name with a number in the reference + * + * @param string $reference Original reference + * @param string $name Book name + * @param int $number Book number + * + * @return string New reference with the book number instead of the name + * @since 2.0.1 + */ + private function replace(string $reference, string $name, int $number): string + { + return $this->mb_str_replace($name, "$number", $reference); + } + + /** + * Build in str_replace that will work with all languages + * + * @param string $search The search phrase/word + * @param string $replace The replace phrase/word + * @param string $subject The string to update + * + * @return string New updated string + * @since 2.0.1 + */ + private function mb_str_replace(string $search, string $replace, string $subject): string + { + return mb_ereg_replace(preg_quote($search), $replace, $subject); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Book.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Book.php new file mode 100644 index 0000000..da5d4f8 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Book.php @@ -0,0 +1,156 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Data; + + +use VDM\Joomla\GetBible\Database\Load; +use VDM\Joomla\GetBible\Openai\Config; + + +/** + * The GetBible Book Data + * + * @since 2.0.1 + */ +final class Book +{ + /** + * The Load class + * + * @var Load + * @since 2.0.1 + */ + protected Load $load; + + /** + * The Config class + * + * @var Config + * @since 2.0.1 + */ + protected Config $config; + + /** + * The books + * + * @var array + * @since 2.0.1 + */ + protected array $books = []; + + /** + * Constructor + * + * @param Load $load The load object. + * @param Config $config The config object. + * + * @since 2.0.1 + */ + public function __construct(Load $load, Config $config) + { + $this->load = $load; + $this->config = $config; + } + + /** + * Get the book number + * + * @return string The book number + * @since 2.0.1 + */ + public function getNumber(): string + { + $book = $this->get(); + return $book ? $book->nr ?? '' : ''; + } + + /** + * Get the book name + * + * @return string The book name + * @since 2.0.1 + */ + public function getName(): string + { + $book = $this->get(); + return $book ? $book->name ?? '' : ''; + } + + /** + * Get the book + * + * @return object|null True on success + * @since 2.0.1 + */ + private function get(): ?object + { + $abbreviation = $this->config->get('translation'); + $book = $this->config->get('book'); + + if (empty($abbreviation) || empty($book)) + { + return null; + } + + $cacheKey = $this->generateCacheKey($abbreviation, $book); + + if (isset($this->books[$cacheKey])) + { + return $this->books[$cacheKey]; + } + + return $this->loadBookData($abbreviation, $book); + } + + /** + * Loads the book data from the database and updates the cache + * + * @param string $abbreviation The translation abbreviation. + * @param int $book The book number. + * + * @return object|null The loaded book data, or null if not found or an error occurred. + * @since 2.0.1 + */ + private function loadBookData(string $abbreviation, int $book): ?object + { + $data = $this->load->item( + ['abbreviation' => $abbreviation, 'nr' => $book], + 'book' + ); + + if (!is_object($data)) + { + return null; + } + + $cacheKey = $this->generateCacheKey($abbreviation, $book); + + $this->books[$cacheKey] = $data; + + return $this->books[$cacheKey]; + } + + /** + * Generates a cache key based on the abbreviation, and book + * + * @param string $abbreviation The translation abbreviation. + * @param int $book The book number. + * + * @return string The generated cache key. + * @since 2.0.1 + */ + private function generateCacheKey(string $abbreviation, int $book): string + { + return $abbreviation . $book; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Chapter.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Chapter.php new file mode 100644 index 0000000..04e899a --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Chapter.php @@ -0,0 +1,214 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Data; + + +use VDM\Joomla\GetBible\Database\Load; +use VDM\Joomla\GetBible\Openai\Config; + + +/** + * The GetBible Chapter Data + * + * @since 2.0.1 + */ +final class Chapter +{ + /** + * The Load class + * + * @var Load + * @since 2.0.1 + */ + protected Load $load; + + /** + * The Config class + * + * @var Config + * @since 2.0.1 + */ + protected Config $config; + + /** + * The chapters + * + * @var array + * @since 2.0.1 + */ + protected array $chapters = []; + + /** + * Constructor + * + * @param Load $load The load object. + * @param Config $config The config object. + * + * @since 2.0.1 + */ + public function __construct(Load $load, Config $config) + { + $this->load = $load; + $this->config = $config; + } + + /** + * Get the chapter number + * + * @return string The chapter number + * @since 2.0.1 + */ + public function getNumber(): string + { + $chapter = $this->get(); + return $chapter ? $chapter->chapter ?? '' : ''; + } + + /** + * Get the chapter name + * + * @return string The chapter name + * @since 2.0.1 + */ + public function getName(): string + { + $chapter = $this->get(); + return $chapter ? $chapter->name ?? '' : ''; + } + + /** + * Get the chapter text + * + * @return string The chapter text + * @since 2.0.1 + */ + public function getText(): string + { + $chapter = $this->get(); + return $chapter ? $chapter->text ?? '' : ''; + } + + /** + * Get the chapter verses + * + * @return array|null The chapter verses + * @since 2.0.1 + */ + public function getVerses(): ?array + { + $chapter = $this->get(); + return $chapter ? $chapter->verses ?? null : null; + } + + /** + * Get the chapter + * + * @return object|null True on success + * @since 2.0.1 + */ + private function get(): ?object + { + $abbreviation = $this->config->get('translation'); + $book = $this->config->get('book'); + $chapter = $this->config->get('chapter'); + + if (empty($abbreviation) || empty($book) || empty($chapter)) + { + return null; + } + + $cacheKey = $this->generateCacheKey($abbreviation, $book, $chapter); + + if (isset($this->chapters[$cacheKey])) + { + return $this->chapters[$cacheKey]; + } + + return $this->loadChapterData($abbreviation, (int) $book, (int) $chapter); + } + + /** + * Loads the chapter data from the database and updates the cache + * + * @param string $abbreviation The translation abbreviation. + * @param int $book The book number. + * @param int $chapter The chapter number. + * + * @return object|null The loaded chapter data, or null if not found or an error occurred. + * @since 2.0.1 + */ + private function loadChapterData(string $abbreviation, int $book, int $chapter): ?object + { + $data = $this->load->item( + ['abbreviation' => $abbreviation, 'book_nr' => $book, 'chapter' => $chapter, 'published' => 1], + 'chapter' + ); + + if (!is_object($data)) + { + return null; + } + + $data->verses = $this->load->items( + ['abbreviation' => $abbreviation, 'book_nr' => $book, 'chapter' => $chapter, 'published' => 1], + 'verse' + ); + + if ($data->verses === null || !is_array($data->verses) || $data->verses === []) + { + return null; + } + + $cacheKey = $this->generateCacheKey($abbreviation, $book, $chapter); + + $data->text = $this->convertVersesToText($data->verses); + + $this->chapters[$cacheKey] = $data; + + return $this->chapters[$cacheKey]; + } + + /** + * Convert verses to text + * + * @param array $verses The chapter verses. + * + * @return string The verses in text. + * @since 2.0.1 + */ + private function convertVersesToText(array $verses): string + { + $text = []; + foreach ($verses as $verse) + { + $text[] = trim($verse->verse) . ' ' . trim($verse->text); + } + + return implode(' ', $text); + } + + /** + * Generates a cache key based on the abbreviation, book, and chapter + * + * @param string $abbreviation The translation abbreviation. + * @param int $book The book number. + * @param int $chapter The chapter number. + * + * @return string The generated cache key. + * @since 2.0.1 + */ + private function generateCacheKey(string $abbreviation, int $book, int $chapter): string + { + return $abbreviation . '_' . $book . '_' . $chapter; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Placeholders.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Placeholders.php new file mode 100644 index 0000000..fdc0e91 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Placeholders.php @@ -0,0 +1,151 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Data; + + +use VDM\Joomla\GetBible\Data\Scripture; +use VDM\Joomla\GetBible\Data\Prompt; + + +/** + * The GetBible Prompt Placeholders + * + * @since 2.0.1 + */ +final class Placeholders +{ + /** + * The Scripture class + * + * @var Scripture + * @since 2.0.1 + */ + protected Scripture $scripture; + + /** + * The Prompt class + * + * @var Prompt + * @since 2.0.1 + */ + protected Prompt $prompt; + + /** + * Constructor + * + * @param Scripture $scripture The scripture object. + * @param Prompt $prompt The prompt object. + * + * @since 2.0.1 + */ + public function __construct( + Scripture $scripture, + Prompt $prompt) + { + $this->scripture = $scripture; + $this->prompt = $prompt; + } + + /** + * Get the Open AI response + * + * @return array Array of response messages + * @since 2.0.1 + */ + public function get(): array + { + $integration = $this->prompt->getIntegration(); + $cache_behaviour = $this->prompt->getCacheBehaviour(); + + if ($integration === null || $cache_behaviour === null) + { + return []; + } + + if (($integration == 1 || $integration == 3) && ($cache_behaviour == 0 || $cache_behaviour == 2)) + { + return $this->all(); + } + elseif ($integration == 2 && ($cache_behaviour == 0 || $cache_behaviour == 2)) + { + return $this->without(); + } + + return $this->words(); + } + + /** + * Get All Placeholders + * + * @return array Array of Placeholders + * @since 2.0.1 + */ + private function all(): array + { + return [ + '[translation_name]' => $this->scripture->get('translation_name', ''), + '[translation_language]' => $this->scripture->get('translation_language', ''), + '[translation_lcsh]' => $this->scripture->get('translation_lcsh', ''), + '[translation_abbreviation]' => $this->scripture->get('translation_abbreviation', ''), + '[book_number]' => $this->scripture->get('book_number', ''), + '[book_name]' => $this->scripture->get('book_name', ''), + '[chapter_number]' => $this->scripture->get('chapter_number', ''), + '[chapter_name]' => $this->scripture->get('chapter_name', ''), + '[chapter_text]' => $this->scripture->get('chapter_text', ''), + '[verse_number]' => $this->scripture->get('verse_number', ''), + '[verse_name]' => $this->scripture->get('verse_name', ''), + '[verse_text]' => $this->scripture->get('verse_text', ''), + '[selected_word_number]' => $this->scripture->get('selected_word_number', ''), + '[selected_word_text]' => $this->scripture->get('selected_word_text', '') + ]; + } + + /** + * Get All Placeholders without words + * + * @return array Array of Placeholders + * @since 2.0.1 + */ + private function without(): array + { + return [ + '[translation_name]' => $this->scripture->get('translation_name', ''), + '[translation_language]' => $this->scripture->get('translation_language', ''), + '[translation_lcsh]' => $this->scripture->get('translation_lcsh', ''), + '[translation_abbreviation]' => $this->scripture->get('translation_abbreviation', ''), + '[book_number]' => $this->scripture->get('book_number', ''), + '[book_name]' => $this->scripture->get('book_name', ''), + '[chapter_number]' => $this->scripture->get('chapter_number', ''), + '[chapter_name]' => $this->scripture->get('chapter_name', ''), + '[chapter_text]' => $this->scripture->get('chapter_text', ''), + '[verse_number]' => $this->scripture->get('verse_number', ''), + '[verse_name]' => $this->scripture->get('verse_name', ''), + '[verse_text]' => $this->scripture->get('verse_text', '') + ]; + } + + /** + * Get Words Placeholders + * + * @return array Array of Placeholders + * @since 2.0.1 + */ + private function words(): array + { + return [ + '[translation_language]' => $this->scripture->get('translation_language', ''), + '[translation_lcsh]' => $this->scripture->get('translation_lcsh', ''), + '[selected_word_text]' => $this->scripture->get('selected_word_text', '') + ]; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Prompt.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Prompt.php new file mode 100644 index 0000000..cde1a2b --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Prompt.php @@ -0,0 +1,327 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Data; + + +use VDM\Joomla\GetBible\Database\Load; +use VDM\Joomla\GetBible\Openai\Config; + + +/** + * The GetBible Prompt Data + * + * @since 2.0.1 + */ +final class Prompt +{ + /** + * The Load class + * + * @var Load + * @since 2.0.1 + */ + protected Load $load; + + /** + * The Config class + * + * @var Config + * @since 2.0.1 + */ + protected Config $config; + + /** + * The prompts + * + * @var array + * @since 2.0.1 + */ + protected array $prompts = []; + + /** + * Constructor + * + * @param Load $load The load object. + * @param Config $config The config object. + * + * @since 2.0.1 + */ + public function __construct(Load $load, Config $config) + { + $this->load = $load; + $this->config = $config; + } + + /** + * Get prompt guid + * + * @return string The global unique id + * @since 2.0.1 + */ + public function getGuid(): string + { + $prompt = $this->get(); + return $prompt ? $prompt->guid ?? '' : ''; + } + + /** + * Get open ai token + * + * @return string|null The token + * @since 2.0.1 + */ + public function getToken(): ?string + { + $default = $this->config->get('token'); + $prompt = $this->get(); + + if (!$prompt || !isset($prompt->token_override) || + $prompt->token_override != 1) + { + return $default; + } + + return $prompt->token ?? $default; + } + + /** + * Get open ai organisation token + * + * @return string|null The token + * @since 2.0.1 + */ + public function getOrgToken(): ?string + { + $default = $this->config->get('org_token'); + $prompt = $this->get(); + + if (!$prompt || !isset($prompt->ai_org_token_override) || + $prompt->ai_org_token_override != 1) + { + return $default; + } + + return $prompt->org_token ?? $default; + } + + /** + * Get open ai model name + * + * @return string|null The model name + * @since 2.0.1 + */ + public function getModel(): ?string + { + $default = $this->config->get('model'); + $prompt = $this->get(); + + return $prompt ? $prompt->model ?? $default : $default; + } + + /** + * Get the max tokens + * + * @return int|null The max tokens + * @since 2.0.1 + */ + public function getMaxTokens(): ?int + { + $default = $this->config->get('max_tokens'); + $prompt = $this->get(); + + if (!$prompt || !isset($prompt->max_tokens_override) || + $prompt->max_tokens_override != 1) + { + return $default; + } + + return $prompt->max_tokens ?? $default; + } + + /** + * Get the temperature + * + * @return float|null The temperature + * @since 2.0.1 + */ + public function getTemperature(): ?float + { + $default = $this->config->get('temperature'); + $prompt = $this->get(); + + if (!$prompt || !isset($prompt->temperature_override) || + $prompt->temperature_override != 1) + { + return $default; + } + + return $prompt->temperature ?? $default; + } + + /** + * Get the top p + * + * @return float|null The top p + * @since 2.0.1 + */ + public function getTopP(): ?float + { + $default = $this->config->get('top_p'); + $prompt = $this->get(); + + if (!$prompt || !isset($prompt->top_p_override) || + $prompt->top_p_override != 1) + { + return $default; + } + + return $prompt->top_p ?? $default; + } + + /** + * Get the number of results + * + * @return int|null The number of results + * @since 2.0.1 + */ + public function getN(): ?int + { + $default = $this->config->get('n'); + $prompt = $this->get(); + + if (!$prompt || !isset($prompt->n_override) || + $prompt->n_override != 1) + { + return $default; + } + + return $prompt->n ?? $default; + } + + /** + * Get presence penalty + * + * @return float|null The presence penalty + * @since 2.0.1 + */ + public function getPresencePenalty(): ?float + { + $default = $this->config->get('presence_penalty'); + $prompt = $this->get(); + + if (!$prompt || !isset($prompt->presence_penalty_override) || + $prompt->presence_penalty_override != 1) + { + return $default; + } + + return $prompt->presence_penalty ?? $default; + } + + /** + * Get frequency penalty + * + * @return float|null The frequency penalty + * @since 2.0.1 + */ + public function getFrequencyPenalty(): ?float + { + $default = $this->config->get('frequency_penalty'); + $prompt = $this->get(); + + if (!$prompt || !isset($prompt->frequency_penalty_override) || + $prompt->frequency_penalty_override != 1) + { + return $default; + } + + return $prompt->frequency_penalty ?? $default; + } + + /** + * Get the integration + * + * @return int|null 1 = Word-Based, 2 = Verse-Based, 3 = Selection-Based + * @since 2.0.1 + */ + public function getIntegration(): ?int + { + $prompt = $this->get(); + return $prompt ? $prompt->integration ?? null : null; + } + + /** + * Get the cache behaviour + * + * @return int|null 0 = Persistently, 2 = Basic, 3 = Advanced + * @since 2.0.1 + */ + public function getCacheBehaviour(): ?int + { + $prompt = $this->get(); + return $prompt ? $prompt->cache_behaviour ?? null : null; + } + + /** + * Get the cache capacity + * + * @return int The number to cache + * @since 2.0.1 + */ + public function getCacheCapacity(): int + { + $prompt = $this->get(); + return $prompt ? $prompt->cache_capacity ?? 1 : 1; + } + + /** + * Get the prompt messages + * + * @return array|null The array of massage + * @since 2.0.1 + */ + public function getMessages(): ?array + { + $prompt = $this->get(); + return $prompt ? $prompt->messages ?? null : null; + } + + /** + * Get the prompt + * + * @return object|null True on success + * @since 2.0.1 + */ + protected function get(): ?object + { + // get from cache if not found + $guid = $this->config->get('prompt'); + + if (empty($guid)) + { + return null; + } + + if (!isset($this->prompts[$guid])) + { + $this->prompts[$guid] = $this->load->item(['guid' => $guid, 'published' => 1], 'prompt'); + + if ($this->prompts[$guid] && isset($this->prompts[$guid]->messages) && is_object($this->prompts[$guid]->messages)) + { + $this->prompts[$guid]->messages = array_values((array) $this->prompts[$guid]->messages); + } + } + + return $this->prompts[$guid]; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Response.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Response.php new file mode 100644 index 0000000..eacc4d5 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Response.php @@ -0,0 +1,200 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Data; + + +use VDM\Joomla\GetBible\Data\Scripture; +use VDM\Joomla\GetBible\Data\Prompt; +use VDM\Joomla\GetBible\Database\Load; +use VDM\Joomla\GetBible\Openai\Config; + + +/** + * The GetBible Response Data + * + * @since 2.0.1 + */ +final class Response +{ + /** + * The Scripture class + * + * @var Scripture + * @since 2.0.1 + */ + protected Scripture $scripture; + + /** + * The Prompt class + * + * @var Prompt + * @since 2.0.1 + */ + protected Prompt $prompt; + + /** + * The Load class + * + * @var Load + * @since 2.0.1 + */ + protected Load $load; + + /** + * The Config class + * + * @var Config + * @since 2.0.1 + */ + protected Config $config; + + /** + * The responses + * + * @var array + * @since 2.0.1 + */ + protected array $responses = []; + + /** + * The total responses + * + * @var int + * @since 2.0.1 + */ + protected int $total = 0; + + /** + * Constructor + * + * @param Scripture $scripture The scripture object. + * @param Prompt $prompt The prompt object. + * @param Load $load The load object. + * @param Config $config The config object. + * + * @since 2.0.1 + */ + public function __construct( + Scripture $scripture, + Prompt $prompt, + Load $load, + Config $config) + { + $this->scripture = $scripture; + $this->prompt = $prompt; + $this->load = $load; + $this->config = $config; + } + + /** + * Get the responses + * + * @return array|null True on success + * @since 2.0.1 + */ + public function get(): ?array + { + // get the cache behaviour + $cache = $this->prompt->getCacheBehaviour(); + + if (empty($cache) || ($cache != 1 && $cache != 2)) + { + return null; + } + + // load the prompt GUID + $guid = $this->config->get('prompt'); + + if ($guid === null) + { + return null; + } + + if (!isset($this->responses[$guid])) + { + $this->responses[$guid] = null; + + $query = ['prompt' => $guid, 'published' => 1]; + + // Basic Caching - Words/Language + if ($cache == 1) + { + // any empty string so cause no value to be returned + $query['language'] = $this->scripture->get('translation_language', 'none__found'); + $query['selected_word'] = $this->scripture->get('selected_word_text', 'none__found'); + } + // Advanced Caching - Verse/Contex + else + { + // any empty string so cause no value to be returned + $query['abbreviation'] = $this->scripture->get('translation_abbreviation', 'none__found'); + $query['book'] = $this->scripture->get('book_number', 'none__found'); + $query['chapter'] = $this->scripture->get('chapter_number', 'none__found'); + $query['verse'] = $this->scripture->get('verse_number', 'none__found'); + + // get the integration + $integration = $this->prompt->getIntegration(); + if ($integration == 1 || $integration == 3) + { + $query['word'] = $this->scripture->get('selected_word_number', 'none__found'); + } + } + $bucket = $this->load->items($query, 'open_ai_response'); + + if (is_array($bucket) && $bucket !== []) + { + foreach($bucket as $nr => &$response) + { + $response->messages = $this->load->items([ + 'prompt' => $guid, + 'open_ai_response' => $response->response_id, + 'published' => 1 + ], 'open_ai_message'); + } + + $this->responses[$guid] = $bucket; + } + } + + return $this->responses[$guid]; + } + + /** + * is there enough response messages + * + * @return bool true if there is enough messages + * @since 2.0.1 + */ + public function isEnough(): bool + { + return ($this->getTotal() >= $this->prompt->getCacheCapacity()); + } + + /** + * Get the total responses in cache + * + * @return int Number responses from OpenAI + * @since 2.0.1 + */ + public function getTotal(): int + { + if ($this->total > 0 || ($responses = $this->get()) === null) + { + return $this->total; + } + + $this->total = count((array) $responses); + + return $this->total; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Scripture.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Scripture.php new file mode 100644 index 0000000..904363c --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Scripture.php @@ -0,0 +1,154 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Data; + + +use VDM\Joomla\GetBible\Data\Translation; +use VDM\Joomla\GetBible\Data\Book; +use VDM\Joomla\GetBible\Data\Chapter; +use VDM\Joomla\GetBible\Data\Verse; +use VDM\Joomla\GetBible\Data\Word; + + +/** + * The GetBible Scripture + * + * @since 2.0.1 + */ +final class Scripture +{ + /** + * The Translation class + * + * @var Translation + * @since 2.0.1 + */ + protected Translation $translation; + + /** + * The Book class + * + * @var Book + * @since 2.0.1 + */ + protected Book $book; + + /** + * The Chapter class + * + * @var Chapter + * @since 2.0.1 + */ + protected Chapter $chapter; + + /** + * The Verse class + * + * @var Verse + * @since 2.0.1 + */ + protected Verse $verse; + + /** + * The Word class + * + * @var Word + * @since 2.0.1 + */ + protected Word $word; + + /** + * The Scripture object + * + * @var object + * @since 2.0.1 + */ + protected ?object $scripture; + + /** + * Constructor + * + * @param Translation $translation The translation object. + * @param Book $book The book object. + * @param Chapter $chapter The chapter object. + * @param Verse $verse The verse object. + * @param Word $word The word object. + * + * @since 2.0.1 + */ + public function __construct( + Translation $translation, + Book $book, + Chapter $chapter, + Verse $verse, + Word $word) + { + $this->translation = $translation; + $this->book = $book; + $this->chapter = $chapter; + $this->verse = $verse; + $this->word = $word; + } + + /** + * Get the Open AI response + * + * @param string $key The value key. + * @param mixed $default The default value. + * + * @return mixed Scripture Values + * @since 2.0.1 + */ + public function get(string $key, $default = null) + { + if (empty($this->scripture)) + { + $this->scripture = $this->getScripture(); + } + + return $this->scripture->{$key} ?? $default; + } + + /** + * Get all related scripture values + * + * @return object Object of Scripture Values + * @since 2.0.1 + */ + private function getScripture(): object + { + /** + * do not change these keys !!! + * this is an easy mapping + * so called bad practice + * that we use to simplify + * access to these values + */ + return (object) [ + 'translation_name' => $this->translation->getName(), + 'translation_language' => $this->translation->getLanguage(), + 'translation_lcsh' => $this->translation->getLcsh(), + 'translation_abbreviation' => $this->translation->getAbbreviation(), + 'book_number' => $this->book->getNumber(), + 'book_name' => $this->book->getName(), + 'chapter_number' => $this->chapter->getNumber(), + 'chapter_name' => $this->chapter->getName(), + 'chapter_text' => $this->chapter->getText(), + 'verse_number' => $this->verse->getNumber(), + 'verse_name' => $this->verse->getName(), + 'verse_text' => $this->verse->getText(), + 'selected_word_number' => $this->word->getNumber(), + 'selected_word_text' => $this->word->getText() + ]; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Translation.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Translation.php new file mode 100644 index 0000000..193a72b --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Translation.php @@ -0,0 +1,140 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Data; + + +use VDM\Joomla\GetBible\Database\Load; +use VDM\Joomla\GetBible\Openai\Config; + + +/** + * The GetBible Translation Data + * + * @since 2.0.1 + */ +final class Translation +{ + /** + * The Load class + * + * @var Load + * @since 2.0.1 + */ + protected Load $load; + + /** + * The Config class + * + * @var Config + * @since 2.0.1 + */ + protected Config $config; + + /** + * The translations + * + * @var array + * @since 2.0.1 + */ + protected array $translations = []; + + /** + * Constructor + * + * @param Load $load The load object. + * @param Config $config The config object. + * + * @since 2.0.1 + */ + public function __construct(Load $load, Config $config) + { + $this->load = $load; + $this->config = $config; + } + + /** + * Get the translation name + * + * @return string The translation name + * @since 2.0.1 + */ + public function getName(): string + { + $translation = $this->get(); + return $translation ? $translation->translation ?? '' : ''; + } + + /** + * Get the translation language + * + * @return string The translation language + * @since 2.0.1 + */ + public function getLanguage(): string + { + $translation = $this->get(); + $lang = trim(preg_replace('/Bible\.?/', '', $this->getLcsh())); + return $translation ? $translation->language ?? $lang : ''; + } + + /** + * Get the translation distribution lcsh + * + * @return string The translation lcsh + * @since 2.0.1 + */ + public function getLcsh(): string + { + $translation = $this->get(); + return $translation ? $translation->distribution_lcsh ?? '' : ''; + } + + /** + * Get the translation abbreviation + * + * @return string The translation abbreviation + * @since 2.0.1 + */ + public function getAbbreviation(): string + { + $translation = $this->get(); + return $translation ? $translation->abbreviation ?? '' : ''; + } + + /** + * Get the translation + * + * @return object|null True on success + * @since 2.0.1 + */ + public function get(): ?object + { + // get selected translation abbreviation + $abbreviation = $this->config->get('translation'); + + if (empty($abbreviation)) + { + return null; + } + + if (!isset($this->translations[$abbreviation])) + { + $this->translations[$abbreviation] = $this->load->item( + ['abbreviation' => $abbreviation, 'published' => 1], + 'translation' + ); + } + + return $this->translations[$abbreviation]; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Verse.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Verse.php new file mode 100644 index 0000000..4ef1905 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Verse.php @@ -0,0 +1,453 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Data; + + +use VDM\Joomla\GetBible\Data\Chapter; +use VDM\Joomla\GetBible\Openai\Config; +use VDM\Joomla\GetBible\Data\Prompt; +use VDM\Joomla\GetBible\Utilities\StringHelper; + + +/** + * The GetBible Verse Data + * + * @since 2.0.1 + */ +final class Verse +{ + /** + * The Chapter class + * + * @var Chapter + * @since 2.0.1 + */ + protected Chapter $chapter; + + /** + * The Config class + * + * @var Config + * @since 2.0.1 + */ + protected Config $config; + + /** + * The Prompt class + * + * @var Prompt + * @since 2.0.1 + */ + protected Prompt $prompt; + + /** + * The StringHelper class + * + * @var StringHelper + * @since 2.0.1 + */ + protected StringHelper $stringHelper; + + /** + * The verses + * + * @var array + * @since 2.0.1 + */ + protected array $verses = []; + + /** + * Constructor + * + * @param Chapter $chapter The chapter object. + * @param Config $config The config object. + * @param Prompt $prompt The prompt object. + * @param StringHelper $stringHelper The string helper object. + * + * @since 2.0.1 + */ + public function __construct(Chapter $chapter, Config $config, Prompt $prompt, StringHelper $stringHelper) + { + $this->chapter = $chapter; + $this->config = $config; + $this->prompt = $prompt; + $this->stringHelper = $stringHelper; + } + + /** + * Get the verse number/s + * + * @return string The verse number/s + * @since 2.0.1 + */ + public function getNumber(): string + { + $verse = $this->get(); + return $verse ? $verse->number ?? '' : ''; + } + + /** + * Get the verse name + * + * @return string The verse name + * @since 2.0.1 + */ + public function getName(): string + { + $verse = $this->get(); + return $verse ? $verse->name ?? '' : ''; + } + + /** + * Get the verse text + * + * @return string The verse text + * @since 2.0.1 + */ + public function getText(): string + { + $verse = $this->get(); + return $verse ? $verse->text ?? '' : ''; + } + + /** + * Get the verse array + * + * @return array|null The verse array + * @since 2.0.1 + */ + public function getVerse(): ?array + { + $verse = $this->get(); + return $verse ? $verse->verse ?? null : null; + } + + /** + * Get the valid verse numbers + * + * @return array|null The verse number array + * @since 2.0.1 + */ + public function getValid(): ?array + { + $verse = $this->get(); + return $verse ? $verse->valid ?? null : null; + } + + /** + * Get the verse + * + * @return object|null True on success + * @since 2.0.1 + */ + private function get(): ?object + { + $abbreviation = $this->config->get('translation'); + $book = $this->config->get('book'); + $chapter = $this->config->get('chapter'); + $verse = $this->config->get('verse'); + + if (empty($abbreviation) || empty($book) || empty($chapter) || empty($verse)) + { + return null; + } + + $cacheKey = $this->generateCacheKey($abbreviation, $book, $chapter, $verse); + + if (isset($this->verses[$cacheKey])) + { + return $this->verses[$cacheKey]; + } + + return $this->loadVerseData($cacheKey, $verse); + } + + /** + * Loads the verse data + * + * @param string $cacheKey The cache key. + * @param string $verses The selected verses. + * + * @return object|null The loaded verse data, or null if not found or an error occurred. + * @since 2.0.1 + */ + private function loadVerseData(string $cacheKey, string $verses): ?object + { + $chapter = $this->chapter->getVerses(); + + if (empty($chapter)) + { + $this->verses[$cacheKey] = null; + + return null; + } + + $data = new \stdClass(); + + $data->range = $this->selectedVersesRange($verses); + + $data->number = $this->validateSelectedVersesNumbers($data->range, $chapter); + + $chapter_name = $this->chapter->getName(); + + if (empty($data->number) || empty($chapter_name)) + { + $this->verses[$cacheKey] = null; + + return null; + } + + $data->name = $chapter_name . ':' . $data->number; + + $data->text = $this->getVersesString($data->range, $chapter); + + $data->verse = $this->getVersesArray($data->range, $chapter); + + if (empty($data->text) || empty($data->verse)) + { + $this->verses[$cacheKey] = null; + + return null; + } + + $data->valid = $this->validVerseNumbers($data->range); + + $this->verses[$cacheKey] = $data; + + return $this->verses[$cacheKey]; + } + + /** + * Get the range of verses selected + * + * @param string $verses The selected verses + * + * @return array The the raw selected verses + * @since 2.0.1 + */ + private function selectedVersesRange(string $verses): array + { + $bucket = []; + + if (strpos($verses, '-') !== false) + { + $_verses = $this->splitAndTrim($verses); + + $min_verse = min($_verses); + $max_verse = max($_verses); + + $bucket[] = $min_verse; + if ($min_verse != $max_verse && $this->prompt->getIntegration() == 2) + { + $bucket[] = $max_verse; + } + } + else + { + $bucket[] = trim($verses); + } + + return $bucket; + } + + /** + * Split string by '-' and trim each element. + * + * @param string $str The string to be split. + * + * @return array The splitted and trimmed array. + * @since 2.0.1 + */ + private function splitAndTrim(string $str): array + { + if (strpos($str, '-') !== false) + { + $array = array_map('trim', explode('-', $str)); + + sort($array); + + return $array; + } + + return [trim($str)]; + } + + /** + * Validate that these verse numbers exist in chapter + * + * @param array $verses The selected verse numbers + * @param array $chapter The chapter verses + * + * @return string|null The the valid verse numbers or empty string + * @since 2.0.1 + */ + private function validateSelectedVersesNumbers(array &$verses, array $chapter): ?string + { + $valid = []; + + foreach ($chapter as $verse) + { + if (isset($verses[0]) && $verse->verse == $verses[0]) + { + $valid[0] = $verses[0]; + } + elseif (isset($verses[1]) && $verse->verse == $verses[1]) + { + $valid[1] = $verses[1]; + } + } + + if ($valid !== []) + { + // update the verse array to its valid state + $verses = $valid; + + return implode('-', $valid); + } + + $verses = []; + + return null; + } + + /** + * Get the verses selected as text string + * + * @param array $verses The valid selected verse numbers + * @param array $chapter The chapter verses + * + * @return string|null The selected verses as a string + * @since 2.0.1 + */ + private function getVersesString(array $verses, array $chapter): ?string + { + $text = []; + + $add = false; + + foreach ($chapter as $verse) + { + if ($verse->verse == $verses[0]) + { + $add = true; + } + elseif (!isset($verses[1])) + { + $add = false; + } + + if ($add) + { + $text[] = trim($verse->verse) . ' ' . trim($verse->text); + } + + if (isset($verses[1]) && $verse->verse == $verses[1]) + { + $add = false; + } + } + + if (empty($text)) + { + return null; + } + + return implode(' ', $text); + } + + /** + * Get the verses selected as multidimensional array + * + * @param array $verses The valid selected verse numbers + * @param array $chapter The chapter verses + * + * @return array|null The selected verses as an array + * @since 2.0.1 + */ + private function getVersesArray(array $verses, array $chapter): ?array + { + $text = []; + + $add = false; + + foreach ($chapter as $verse) + { + if ($verse->verse == $verses[0]) + { + $add = true; + } + elseif (!isset($verses[1])) + { + $add = false; + } + + if ($add) + { + $text[$verse->verse] = $this->stringHelper->splitToWords(trim($verse->text), false); + } + + if (isset($verses[1]) && $verse->verse == $verses[1]) + { + $add = false; + } + } + + if (empty($text)) + { + return null; + } + + return $text; + } + + /** + * Get all valid verse numbers + * + * @param array $verses The verse range + * + * @return array|null The the valid verses + * @since 2.0.1 + */ + private function validVerseNumbers(array $range): ?array + { + if(count($range) == 1) + { + return $range; + } + elseif(count($range) == 2) + { + // sort the array in ascending order to make sure the range goes from lower to higher + sort($range); + + return range($range[0], $range[1]); + } + + return null; + } + + /** + * Generates a cache key based on the abbreviation, book, chapter, and verses + * + * @param string $abbreviation The translation abbreviation. + * @param int $book The book number. + * @param int $chapter The chapter number. + * @param string $verses The selected verses. + * + * @return string The generated cache key. + * @since 2.0.1 + */ + private function generateCacheKey($abbreviation, $book, int $chapter, string $verses): string + { + return $abbreviation . '_' . $book . '_' . $chapter . '_' . $verses; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Word.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Word.php new file mode 100644 index 0000000..0c80681 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/Word.php @@ -0,0 +1,391 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Data; + + +use VDM\Joomla\GetBible\Data\Verse; +use VDM\Joomla\GetBible\Openai\Config; +use VDM\Joomla\GetBible\Data\Prompt; + + +/** + * The GetBible Word Data + * + * @since 2.0.1 + */ +final class Word +{ + /** + * The Verse class + * + * @var Verse + * @since 2.0.1 + */ + protected Verse $verse; + + /** + * The Config class + * + * @var Config + * @since 2.0.1 + */ + protected Config $config; + + /** + * The Prompt class + * + * @var Prompt + * @since 2.0.1 + */ + protected Prompt $prompt; + + /** + * The words + * + * @var array + * @since 2.0.1 + */ + protected array $words = []; + + /** + * The check if words are sequential + * + * @var array + * @since 2.0.1 + */ + protected array $sequential = []; + + /** + * The active verses + * + * @var array|null + * @since 2.0.1 + */ + protected ?array $verses = null; + + /** + * The valid verse numbers + * + * @var array|null + * @since 2.0.1 + */ + protected ?array $valid = null; + + /** + * Constructor + * + * @param Verse $verse The verse object. + * @param Config $config The config object. + * @param Prompt $prompt The prompt object. + * + * @since 2.0.1 + */ + public function __construct(Verse $verse, Config $config, Prompt $prompt) + { + $this->verse = $verse; + $this->config = $config; + $this->prompt = $prompt; + } + + /** + * Get the word number/s + * + * @return string The word number/s + * @since 2.0.1 + */ + public function getNumber(): string + { + $word = $this->get(); + return $word ? $word->number ?? '' : ''; + } + + /** + * Get the word text + * + * @return string The verse text + * @since 2.0.1 + */ + public function getText(): string + { + $word = $this->get(); + return $word ? $word->text ?? '' : ''; + } + + /** + * Get the words + * + * @return object|null True on success + * @since 2.0.1 + */ + private function get(): ?object + { + $abbreviation = $this->config->get('translation'); + $book = $this->config->get('book'); + $chapter = $this->config->get('chapter'); + $verse = $this->config->get('verse'); + $words = $this->config->get('words'); + + if (empty($abbreviation) || empty($book) || empty($chapter) || empty($verse) || empty($words)) + { + return null; + } + + $cacheKey = $this->generateCacheKey($abbreviation, $book, $chapter, $verse, $words); + + if (isset($this->words[$cacheKey])) + { + return $this->words[$cacheKey]; + } + + return $this->loadWordData($cacheKey, $verse, $words); + } + + /** + * Loads the word data + * + * @param string $cacheKey The cache key. + * @param string $verses The selected verses. + * @param string $words The selected words. + * + * @return object|null The loaded word data, or null if not found or an error occurred. + * @since 2.0.1 + */ + private function loadWordData(string $cacheKey, string $verses, string $words): ?object + { + $this->valid = $this->verse->getValid(); + $this->verses = $this->verse->getVerse(); + + if (empty($this->verses) || empty($this->valid)) + { + $this->words[$cacheKey] = null; + + return null; + } + + $data = new \stdClass(); + + $data->number_array = $this->selectedWordNumbers($verses, $words); + + if (empty($data->number_array)) + { + $this->words[$cacheKey] = null; + + return null; + } + + $data->number = $this->selectedWordNumbersToString($data->number_array); + + $data->text_array = $this->selectedWord($data->number_array); + + if (empty($data->text_array)) + { + $this->words[$cacheKey] = null; + + return null; + } + + $data->text = $this->selectedWordToString($data->text_array); + + $this->words[$cacheKey] = $data; + + return $this->words[$cacheKey]; + } + + /** + * Build word number array from verse and words. + * + * @param string $verse The verse selected. + * @param string $words The words words. + * + * @return array The word number array. + * @since 2.0.1 + */ + private function selectedWordNumbers(string $verse, string $words): array + { + $verse = $this->splitAndTrim($verse); + $words = $this->splitAndTrim($words); + + $array = []; + $integration = $this->prompt->getIntegration(); + $this->sequential = []; + + foreach ($verse as $key => $verse) + { + if (isset($words[$key]) && in_array($verse, $this->valid) && + $this->isValidWordNumber($verse, $words[$key])) + { + $array[$verse][] = $words[$key]; + if ($integration == 1) + { + break; + } + } + } + + return $array; + } + + /** + * Converts word number array to string. + * + * @param array $wordNumberArray The word number array. + * + * @return string The word number string. + * @since 2.0.1 + */ + private function selectedWordNumbersToString(array $wordNumberArray): string + { + $word_number = []; + + if (count($wordNumberArray) == 1) + { + $word_number[] = implode(',', array_values($wordNumberArray)[0]); + } + else + { + foreach ($wordNumberArray as $verse => $words) + { + $word_number[] = $verse . ':' . implode(',', $words); + } + } + + return implode(';', $word_number); + } + + /** + * Build word array from verse and words. + * + * @param array $words The words array. + * + * @return array The word array. + * @since 2.0.1 + */ + private function selectedWord(array $words): array + { + $word_array = []; + foreach ($words as $verse => $word_numbers) + { + foreach ($word_numbers as $word) + { + if (isset($this->verses[$verse][$word])) + { + $word_array[$verse][] = $this->verses[$verse][$word]; + } + } + } + + return $word_array; + } + + /** + * Converts word array to string. + * + * @param array $wordArray The word array. + * + * @return string The word string. + * @since 2.0.1 + */ + private function selectedWordToString(array $wordArray): string + { + $word_number = []; + + foreach ($wordArray as $verse => $words) + { + $word_number[] = implode(' ', $words); + } + + return implode(' ', $word_number); + } + + /** + * Split string by '-' and trim each element. + * + * @param string $str The string to be split. + * + * @return array The splitted and trimmed array. + * @since 2.0.1 + */ + private function splitAndTrim(string $str): array + { + if (strpos($str, '-') !== false) + { + $array = array_map('trim', explode('-', $str)); + + sort($array); + + return $array; + } + + return [trim($str)]; + } + + /** + * Check if a word exist in a verse + * + * @param int $verseNumber The verse number. + * @param int $wordNumber The word number. + * + * @return bool True on success + * @since 2.0.1 + */ + private function isValidWordNumber(int $verseNumber, int $wordNumber): bool + { + // we add the next word number to check sequential selection of words + $this->sequential[$verseNumber][$wordNumber] = $wordNumber; + if (count($this->sequential[$verseNumber]) > 1 && !$this->isSequential($this->sequential[$verseNumber])) + { + return false; + } + + return isset($this->verses[$verseNumber][$wordNumber]); + } + + /** + * Check if an array values is sequential. + * + * @param array $arr The number array. + * + * @return bool true if sequential + * @since 2.0.1 + */ + private function isSequential(array $arr): bool + { + $arr = array_values($arr); // Reset keys + for ($i = 0, $len = count($arr) - 1; $i < $len; $i++) + { + if ($arr[$i] + 1 !== $arr[$i + 1]) + { + return false; + } + } + + return true; + } + + /** + * Generates a cache key based on the abbreviation, book, chapter, verses, and words + * + * @param string $abbreviation The translation abbreviation. + * @param int $book The book number. + * @param int $chapter The chapter number. + * @param string $verses The selected verses. + * @param string $words The selected words. + * + * @return string The generated cache key. + * @since 2.0.1 + */ + private function generateCacheKey($abbreviation, $book, int $chapter, string $verses, string $words): string + { + return $abbreviation . '_' . $book . '_' . $chapter . '_' . $verses . '_' . $words; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/index.html b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Data/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Database/Insert.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Database/Insert.php new file mode 100644 index 0000000..010bac0 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Database/Insert.php @@ -0,0 +1,161 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Database; + + +use VDM\Joomla\GetBible\Model\Upsert as Model; +use VDM\Joomla\Database\Insert as Database; + + +/** + * GetBible Database Insert + * + * @since 2.0.1 + */ +final class Insert +{ + /** + * Model + * + * @var Model + * @since 2.0.1 + */ + protected Model $model; + + /** + * Database + * + * @var Database + * @since 2.0.1 + */ + protected Database $database; + + /** + * Constructor + * + * @param Model $model The set model object. + * @param Database $database The insert database object. + * + * @since 2.0.1 + */ + public function __construct(Model $model, Database $database) + { + $this->model = $model; + $this->database = $database; + } + + /** + * Insert a value to a given table + * Example: $this->value(Value, 'value_key', 'table_name'); + * + * @param mixed $value The field value + * @param string $field The field key + * @param string $table Target table + * + * @return bool + * @since 2.0.1 + */ + public function value($value, string $field, string $table): bool + { + // build the array + $item = []; + $item[$field] = $value; + + // Insert the column of this table + return $this->row($item, $table); + } + + /** + * Insert single row with multiple values to a given table + * Example: $this->item(Array, 'table_name'); + * + * @param array $item The item to save + * @param string $table Target table + * + * @return bool + * @since 2.0.1 + */ + public function row(array $item, string $table): bool + { + // check if array could be modelled + if (($item = $this->model->row($item, $table)) !== null) + { + // Insert the column of this table + return $this->database->row($item, $table); + } + return false; + } + + /** + * Insert multiple rows to a given table + * Example: $this->items(Array, 'table_name'); + * + * @param array|null $items The items updated in database (array of arrays) + * @param string $table Target table + * + * @return bool + * @since 2.0.1 + */ + public function rows(?array $items, string $table): bool + { + // check if arrays could be modelled + if (($items = $this->model->rows($items, $table)) !== null) + { + // Insert the column of this table + return $this->database->rows($items, $table); + } + return false; + } + + /** + * Insert single item with multiple values to a given table + * Example: $this->item(Object, 'table_name'); + * + * @param object $item The item to save + * @param string $table Target table + * + * @return bool + * @since 2.0.1 + */ + public function item(object $item, string $table): bool + { + // check if object could be modelled + if (($item = $this->model->item($item, $table)) !== null) + { + // Insert the column of this table. + return $this->database->item($item, $table); + } + return false; + } + + /** + * Insert multiple items to a given table + * Example: $this->items(Array, 'table_name'); + * + * @param array|null $items The items updated in database (array of objects) + * @param string $table Target table + * + * @return bool + * @since 2.0.1 + */ + public function items(?array $items, string $table): bool + { + // check if object could be modelled + if (($items = $this->model->items($items, $table)) !== null) + { + // Insert the column of this table. + return $this->database->items($items, $table); + } + return false; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Database/Load.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Database/Load.php new file mode 100644 index 0000000..86ba1ee --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Database/Load.php @@ -0,0 +1,262 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Database; + + +use VDM\Joomla\GetBible\Table; +use VDM\Joomla\GetBible\Model\Load as Model; +use VDM\Joomla\Database\Load as Database; + + +/** + * GetBible Database Load + * + * @since 2.0.1 + */ +final class Load +{ + /** + * Search Table + * + * @var Table + * @since 2.0.1 + */ + protected Table $table; + + /** + * Model Load + * + * @var Model + * @since 2.0.1 + */ + protected Model $model; + + /** + * Database Load + * + * @var Database + * @since 2.0.1 + */ + protected Database $load; + + /** + * Constructor + * + * @param Table $table The core table object. + * @param Model $model The model object. + * @param Database $load The database object. + * + * @since 2.0.1 + */ + public function __construct(Table $table, Model $model, Database $load) + { + $this->table = $table; + $this->model = $model; + $this->load = $load; + } + + /** + * Get a value from a given table + * Example: $this->value( + * [ + * 'abbreviation' => 'kjv', + * 'book_nr' => 62, + * 'chapter' => 3, + * 'verse' => 16 + * ], 'value_key', 'table_name' + * ); + * + * @param array $keys The item keys + * @param string $field The field key + * @param string $table The table + * + * @return mixed + * @since 2.0.1 + */ + public function value(array $keys, string $field, string $table) + { + // check if this is a valid table + if ($this->table->exist($table, $field)) + { + return $this->model->value( + $this->load->value( + ["a.${field}" => $field], + ['a' => $table], + $this->prefix($keys) + ), + $field, + $table + ); + } + + return null; + } + + /** + * Get the max value based on a filtered result from a given table + * Example: $this->max( + * [ + * 'abbreviation' => 'kjv', + * 'book_nr' => 62, + * 'chapter' => 3, + * 'verse' => 16 + * ], 'value_key', 'table_name' + * ); + * + * @param array $filter The filter keys + * @param string $field The field key + * @param string $table The table + * + * @return int|null + * @since 2.0.1 + */ + public function max(array $filter, string $field, string $table): ?int + { + // check if this is a valid table + if ($this->table->exist($table, $field)) + { + return $this->load->max( + $field, + ['a' => $table], + $this->prefix($filter) + ); + } + + return null; + } + + /** + * Count the number of items based on filter result from a given table + * Example: $this->count( + * [ + * 'abbreviation' => 'kjv', + * 'book_nr' => 62, + * 'chapter' => 3, + * 'verse' => 16 + * ], 'table_name' + * ); + * + * @param array $filter The filter keys + * @param string $table The table + * + * @return int|null + * @since 2.0.1 + */ + public function count(array $filter, string $table): ?int + { + // check if this is a valid table + if ($this->table->exist($table)) + { + return $this->load->count( + ['a' => $table], + $this->prefix($filter) + ); + } + + return null; + } + + /** + * Get values from a given table + * Example: $this->item( + * [ + * 'abbriviation' => 'kjv', + * 'book_nr' => 62, + * 'chapter' => 3, + * 'verse' => 16 + * ], 'table_name' + * ); + * + * @param array $keys The item keys + * @param string $table The table + * + * @return object|null + * @since 2.0.1 + */ + public function item(array $keys, string $table): ?object + { + // check if this is a valid table + if ($this->table->exist($table)) + { + return $this->model->item( + $this->load->item( + ['all' => 'a.*'], + ['a' => $table], + $this->prefix($keys) + ), + $table + ); + } + + return null; + } + + /** + * Get values from a given table + * Example: $this->items( + * [ + * 'abbriviation' => [ + * 'operator' => 'IN', + * 'value' => ['kjv', 'aov'] + * ], + * 'book_nr' => 62, + * 'chapter' => 3, + * 'verse' => [ + * 'operator' => 'IN', + * 'value' => [16, 17, 18] + * ] + * ], 'table_name' + * ); + * Example: $this->items($ids, 'table_name'); + * + * @param array $keys The item keys + * @param string $table The table + * + * @return array|null + * @since 2.0.1 + */ + public function items(array $keys, string $table): ?array + { + // check if this is a valid table + if ($this->table->exist($table)) + { + return $this->model->items( + $this->load->items( + ['all' => 'a.*'], ['a' => $table], $this->prefix($keys) + ), + $table + ); + } + + return null; + } + + /** + * Add prefix to the keys + * + * @param array $keys The query keys + * + * @return array + * @since 2.0.1 + */ + private function prefix(array &$keys): array + { + // update the key values + $bucket = []; + foreach ($keys as $k => $v) + { + $bucket['a.' . $k] = $v; + } + return $bucket; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Database/Update.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Database/Update.php new file mode 100644 index 0000000..dfa4101 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Database/Update.php @@ -0,0 +1,168 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Database; + + +use VDM\Joomla\GetBible\Model\Upsert as Model; +use VDM\Joomla\Database\Update as Database; + + +/** + * The GetBible Database Update + * + * @since 2.0.1 + */ +final class Update +{ + /** + * Model + * + * @var Model + * @since 2.0.1 + */ + protected Model $model; + + /** + * Database + * + * @var Database + * @since 2.0.1 + */ + protected Database $database; + + /** + * Constructor + * + * @param Model $model The set model object. + * @param Database $database The update database object. + * + * @since 2.0.1 + */ + public function __construct(Model $model, Database $database) + { + $this->model = $model; + $this->database = $database; + } + + /** + * Update a value to a given table + * Example: $this->value(Value, 'value_key', 'id', 'table_name'); + * + * @param mixed $value The field value + * @param string $field The field key + * @param string $keyValue The key value + * @param string $key The key name + * @param string $table Target table + * + * @return bool + * @since 2.0.1 + */ + public function value($value, string $field, string $keyValue, string $key, string $table): bool + { + // build the array + $item = []; + $item[$key] = $keyValue; + $item[$field] = $value; + + // Update the column of this table using guid as the primary key. + return $this->row($item, $key, $table); + } + + /** + * Update single row with multiple values to a given table + * Example: $this->item(Array, 'id', 'table_name'); + * + * @param array $item The item to save + * @param string $key The key name + * @param string $table Target table + * + * @return bool + * @since 2.0.1 + */ + public function row(array $item, string $key, string $table): bool + { + // check if object could be modelled + if (($item = $this->model->row($item, $table)) !== null) + { + // Update the column of this table using $key as the primary key. + return $this->database->row($item, $key, $table); + } + return false; + } + + /** + * Update multiple rows to a given table + * Example: $this->items(Array, 'id', 'table_name'); + * + * @param array|null $items The items updated in database (array of arrays) + * @param string $key The key name + * @param string $table Target table + * + * @return bool + * @since 2.0.1 + */ + public function rows(?array $items, string $key, string $table): bool + { + // check if object could be modelled + if (($items = $this->model->rows($items, $table)) !== null) + { + // Update the column of this table using $key as the primary key. + return $this->database->rows($items, $key, $table); + } + return false; + } + + /** + * Update single item with multiple values to a given table + * Example: $this->item(Object, 'id', 'table_name'); + * + * @param object $item The item to save + * @param string $key The key name + * @param string $table Target table + * + * @return bool + * @since 2.0.1 + */ + public function item(object $item, string $key, string $table): bool + { + // check if object could be modelled + if (($item = $this->model->item($item, $table)) !== null) + { + // Update the column of this table using $key as the primary key. + return $this->database->item($item, $key, $table); + } + return false; + } + + /** + * Update multiple items to a given table + * Example: $this->items(Array, 'id', 'table_name'); + * + * @param array|null $items The items updated in database (array of objects) + * @param string $key The key name + * @param string $table Target table + * + * @return bool + * @since 2.0.1 + */ + public function items(?array $items, string $key, string $table): bool + { + // check if object could be modelled + if (($items = $this->model->items($items, $table)) !== null) + { + // Update the column of this table using $key as the primary key. + return $this->database->items($items, $key, $table); + } + return false; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Database/index.html b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Database/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Database/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Factory.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Factory.php new file mode 100644 index 0000000..4bdbfb9 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Factory.php @@ -0,0 +1,84 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible; + + +use Joomla\DI\Container; +use VDM\Joomla\GetBible\Service\Api; +use VDM\Joomla\GetBible\Service\Utilities; +use VDM\Joomla\GetBible\Service\App; +use VDM\Joomla\GetBible\Service\Model; +use VDM\Joomla\GetBible\Service\Database; +use VDM\Joomla\Interfaces\FactoryInterface; + + +/** + * GetBible Factory + * + * @since 2.0.1 + */ +abstract class Factory implements FactoryInterface +{ + /** + * Global Package Container + * + * @var Container + * @since 2.0.1 + **/ + protected static $container = null; + + /** + * Get any class from the package container + * + * @param string $key The container class key + * + * @return Mixed + * @since 2.0.1 + */ + public static function _($key) + { + return self::getContainer()->get($key); + } + + /** + * Get the global package container + * + * @return Container + * @since 2.0.1 + */ + public static function getContainer(): Container + { + if (!self::$container) + { + self::$container = self::createContainer(); + } + + return self::$container; + } + + /** + * Create a container object + * + * @return Container + * @since 2.0.1 + */ + protected static function createContainer(): Container + { + return (new Container()) + ->registerServiceProvider(new Utilities()) + ->registerServiceProvider(new Api()) + ->registerServiceProvider(new App()) + ->registerServiceProvider(new Model()) + ->registerServiceProvider(new Database()); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Linker.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Linker.php new file mode 100644 index 0000000..ec68777 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Linker.php @@ -0,0 +1,424 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible; + + +use Joomla\CMS\User\UserHelper; +use Joomla\CMS\Language\Text; +use VDM\Joomla\GetBible\Database\Load; +use VDM\Joomla\GetBible\Database\Insert; +use VDM\Joomla\GetBible\Database\Update; +use VDM\Joomla\GetBible\Utilities\SessionHelper as Session; +use VDM\Joomla\Utilities\GuidHelper; + + +/** + * The GetBible Linker + * + * @since 2.0.1 + */ +final class Linker +{ + /** + * The Load class + * + * @var Load + * @since 2.0.1 + */ + protected Load $load; + + /** + * The Insert class + * + * @var Insert + * @since 2.0.1 + */ + protected Insert $insert; + + /** + * The Update class + * + * @var Update + * @since 2.0.1 + */ + protected Update $update; + + /** + * The Session class + * + * @var Session + * @since 2.0.1 + */ + protected Session $session; + + /** + * The Share His Word Trigger + * + * @var bool + * @since 2.0.1 + */ + protected bool $trigger = false; + + /** + * Constructor + * + * @param Load $load The load object. + * @param Insert $insert The insert object. + * @param Update $update The update object. + * @param Session $session The session object. + * + * @since 2.0.1 + */ + public function __construct( + Load $load, + Insert $insert, + Update $update, + Session $session) + { + $this->load = $load; + $this->insert = $insert; + $this->update = $update; + $this->session = $session; + } + + /** + * The Share His Word Trigger + * + * @return bool True on success + * @since 2.0.1 + **/ + public function share(): bool + { + return $this->trigger; + } + + /** + * Get Linker that has Access + * + * @return string|null Linker GUID that has access + * @since 2.0.1 + **/ + public function get(): ?string + { + if (($linker = $this->session->get('getbible_active_linker_guid', null)) === null) + { + return null; + } + + if (($access = $this->session->get("getbible_active_{$linker}", null)) === null + || $access !== 'valid_access') + { + return null; + } + + return $linker; + } + + /** + * Get active Linker + * + * @param bool $setup The setup switch + * + * @return string|null Linker GUID that has access + * @since 2.0.1 + **/ + public function active(bool $setup = true): ?string + { + if (($linker = $this->session->get('getbible_active_linker_guid', null)) !== null) + { + return $linker; + } + + if ($setup) + { + $guid = (string) GuidHelper::get(); + $this->session->set('getbible_active_linker_guid', $guid); + + return $guid; + } + + return null; + } + + /** + * Check if a Linker is valid active linker + * + * @param string $linker The linker GUID value + * + * @return bool True if active valid linker + * @since 2.0.1 + **/ + public function valid(string $linker): bool + { + // is only valid if this linker has an active password + if (GuidHelper::valid($linker) && ($password_name = $this->load->value( + ['linker' => $linker, 'published' => 1], + 'name', 'password' + )) !== null) + { + return true; + } + + return false; + } + + /** + * The Share His Word Trigger + * + * @param string $linker The linker GUID value + * + * @return bool True on success + * @since 2.0.1 + **/ + public function trigger(string $linker): bool + { + if (!$this->set($linker)) + { + return false; + } + + $this->trigger = true; + + return true; + } + + /** + * Set Active Linker + * + * @param string $linker The linker GUID value + * + * @return bool True on success + * @since 2.0.1 + **/ + public function set(string $linker): bool + { + if (!GuidHelper::valid($linker)) + { + return false; + } + + $this->session->set('getbible_active_linker_guid', $linker); + + return true; + } + + /** + * Set Access + * + * @param string $linker The linker GUID value + * @param string $pass The linker pass value + * @param string|null $oldPass The linker old pass value + * + * @return array|null The success or error details + * @since 2.0.1 + **/ + public function access(string $linker, string $pass, ?string $oldPass): ?array + { + // trim all empty space + $pass = trim($pass); + + // password to short + if (strlen($pass) <= 3) + { + return [ + 'error' => Text::_('COM_GETBIBLE_PASSWORD_TO_SHORT_USE_A_LONGER_PASSWORD') + ]; + } + // linker not valid GUID + elseif (!GuidHelper::valid($linker)) + { + return [ + 'error' => Text::_('COM_GETBIBLE_INVALID_SESSION_KEY_VALUE') + ]; + } + + // get linker + if (($_linker = $this->load->item(['guid' => $linker],'linker')) !== null) + { + // publish the linker if needed + if ($_linker->published != 1 && $this->update->value(1, 'published', $_linker->id, 'id', 'linker')) + { + return [ + 'error' => Text::_('COM_GETBIBLE_ACCESS_ALREADY_EXIST_BUT_COULD_NOT_BE_REACTIVATED') + ]; + } + + if (!empty($oldPass)) + { + + $oldPass = trim($oldPass); + + if (($guid = $this->getPassGuid($linker, $oldPass)) === null) + { + return [ + 'error' => Text::_('COM_GETBIBLE_INCORRECT_FAVOURITE_VERSE_SELECTED') + ]; + } + + if (!$this->setPassword($linker, $pass)) + { + return [ + 'error' => Text::_('COM_GETBIBLE_FAVOURITE_VERSE_COULD_NOT_BE_CHANGED') + ]; + } + + // unpublished the old pass word only if new password was set + $this->update->value(-2, 'published', $guid, 'guid', 'password'); + } + elseif (!$this->hasAccess($linker, $pass)) + { + return [ + 'error' => Text::_('COM_GETBIBLE_INCORRECT_FAVOURITE_VERSE_SELECTED') + ]; + } + } + elseif (!$this->setLinker($linker)) + { + return [ + 'error' => Text::_('COM_GETBIBLE_SESSION_KEY_COULD_NOT_BE_STORED') + ]; + } + elseif (!$this->setPassword($linker, $pass)) + { + return [ + 'error' => Text::_('COM_GETBIBLE_FAVOURITE_VERSE_COULD_NOT_BE_STORED') + ]; + } + elseif (($_linker = $this->load->item(['guid' => $linker],'linker')) === null) + { + return null; + } + + $_linker->published = 1; + $_linker->success = Text::_('COM_GETBIBLE_FAVOURITE_VERSE_SUCCESSFULLY_SET'); + + // add to session + $this->session->set('getbible_active_linker_guid', $linker); + $this->session->set("getbible_active_{$linker}", 'valid_access'); + + return (array) $_linker; + } + + /** + * Has Access + * + * @param string $linker The linker GUID value + * @param string $pass The linker pass value + * + * @return bool True on success + * @since 2.0.1 + **/ + private function hasAccess(string $linker, string $pass): bool + { + if (($password = $this->getPassword($linker, $pass)) !== null) + { + return true; + } + + return false; + } + + /** + * Get Password GUID + * + * @param string $linker The linker GUID value + * @param string $pass The linker pass value + * + * @return string|null The GUID on success + * @since 2.0.1 + **/ + private function getPassGuid(string $linker, string $pass): ?string + { + if (($password = $this->getPassword($linker, $pass)) !== null) + { + return $password->guid; + } + + return null; + } + + /** + * Get Password + * + * @param string $linker The linker GUID value + * @param string $pass The linker pass value + * + * @return object|null The GUID on success + * @since 2.0.1 + **/ + private function getPassword(string $linker, string $pass): ?object + { + if (strlen($pass) > 3 && ($passwords = $this->load->items( + ['linker' => $linker, 'published' => 1], + 'password' + )) !== null) + { + foreach ($passwords as $password) + { + if (UserHelper::verifyPassword($pass, $password->password)) + { + return $password; + } + } + } + + return null; + } + + /** + * Set Linker + * + * @param string $linker The linker GUID value + * + * @return bool True on success + * @since 2.0.1 + **/ + private function setLinker(string $linker): bool + { + return $this->insert->row([ + 'name' => 'Default-Name', + 'guid' => $linker + ], 'linker'); + } + + /** + * Set Password + * + * @param string $linker The linker GUID value + * @param string $pass The linker pass value + * + * @return bool True on success + * @since 2.0.1 + **/ + private function setPassword(string $linker, string $pass): bool + { + if (strlen($pass) <= 3) + { + return false; + } + + $guid = (string) GuidHelper::get(); + while (!GuidHelper::valid($guid, 'password', 0, 'getbible')) + { + // must always be set + $guid = (string) GuidHelper::get(); + } + + return $this->insert->row([ + 'name' => 'Favourite-Verse', + 'linker' => $linker, + 'password' => UserHelper::hashPassword($pass), + 'guid' => $guid + ], 'password'); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Loader.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Loader.php new file mode 100644 index 0000000..1598913 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Loader.php @@ -0,0 +1,83 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible; + + +use Joomla\Registry\Registry; +use VDM\Joomla\GetBible\Database\Load; +use VDM\Joomla\GetBible\Watcher; + + +/** + * The GetBible Loader of Scripture in Content + * + * @since 2.0.1 + */ +final class Loader +{ + /** + * The Load class + * + * @var Load + * @since 2.0.1 + */ + protected Load $load; + + /** + * The Watcher class + * + * @var Watcher + * @since 2.0.1 + */ + protected Watcher $watcher; + + /** + * The Plugin Params class + * + * @var Registry + * @since 2.0.1 + */ + protected Registry $plugin; + + /** + * Constructor + * + * @param Load $load The load object. + * @param Watcher $watcher The watcher object. + * + * @since 2.0.1 + */ + public function __construct( + Load $load, + Watcher $watcher) + { + $this->load = $load; + $this->watcher = $watcher; + } + + /** + * The setting of Scripture into Content starts here + * + * @param object &$row The article object. Note $article->text is also available + * @param Registry $plugin The plugin params + * + * @return void + * @since 2.0.1 + */ + public function set(&$row, Registry $plugin): bool + { + $this->plugin = $plugin; + + return; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Model/Load.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Model/Load.php new file mode 100644 index 0000000..802f489 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Model/Load.php @@ -0,0 +1,160 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Model; + + +use VDM\Joomla\Abstraction\BaseConfig as Config; +use VDM\Joomla\GetBible\Table; +use VDM\Joomla\Utilities\StringHelper; +use VDM\Joomla\Utilities\ArrayHelper; +use VDM\Joomla\Utilities\ObjectHelper; +use VDM\Joomla\Interfaces\ModelInterface; +use VDM\Joomla\Abstraction\Model; + + +/** + * The GetBible Model to Load + * + * @since 2.0.1 + */ +final class Load extends Model implements ModelInterface +{ + /** + * GetBible Config + * + * @var Config + * @since 2.0.1 + */ + protected Config $config; + + /** + * Constructor + * + * @param Config $config The getBible config object. + * @param Table $table The getBible table object. + * + * @since 2.0.1 + */ + public function __construct(Config $config, Table $table) + { + parent::__construct($table); + + $this->config = $config; + } + + /** + * Model the value + * Example: $this->value(value, 'field_key', 'table_name'); + * + * @param mixed $value The value to model + * @param string $field The field key + * @param string|null $table The table + * + * @return mixed + * @since 2.0.1 + */ + public function value($value, string $field, ?string $table = null) + { + // set the table name + if (empty($table)) + { + $table = $this->getTable(); + } + + // check if this is a valid table + if (($store = $this->table->get($table, $field, 'store')) !== null) + { + // open the value based on the store method + switch($store) + { + case 'json': + $value = json_decode($value); + break; + } + + // Model Distribution History + if ($table === 'translation' && $field === 'distribution_history') + { + $value = $this->modelDistributionHistory($value); + } + } + + return $value; + } + + /** + * Validate before the value is modelled + * + * @param mixed $value The field value + * @param string|null $field The field key + * @param string|null $table The table + * + * @return bool + * @since 2.0.1 + */ + protected function validateBefore(&$value, ?string $field = null, ?string $table = null): bool + { + // only strings or numbers allowed + if (StringHelper::check($value) || is_numeric($value)) + { + return true; + } + // remove empty values + return false; + } + + /** + * Validate after the value is modelled + * + * @param mixed $value The field value + * @param string|null $field The field key + * @param string|null $table The table + * + * @return bool + * @since 2.0.1 + */ + protected function validateAfter(&$value, ?string $field = null, ?string $table = null): bool + { + // check values + if (StringHelper::check($value) || ArrayHelper::check($value, true) || ObjectHelper::check($value) || is_numeric($value)) + { + return true; + } + // remove empty values + return false; + } + + /** + * Get the current active table + * + * @return string + * @since 2.0.1 + */ + protected function getTable(): string + { + return $this->config->table_name; + } + + /** + * Model Distribution History + * + * @param mixed $value The value to model + * + * @return mixed + * @since 2.0.1 + */ + public function modelDistributionHistory($value) + { + return $value; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Model/Upsert.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Model/Upsert.php new file mode 100644 index 0000000..5c53ea3 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Model/Upsert.php @@ -0,0 +1,159 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Model; + + +use VDM\Joomla\Abstraction\BaseConfig as Config; +use VDM\Joomla\GetBible\Table; +use VDM\Joomla\Utilities\ObjectHelper; +use VDM\Joomla\Interfaces\ModelInterface; +use VDM\Joomla\Abstraction\Model; + + +/** + * The GetBible Model for both Update and Insert + * + * @since 2.0.1 + */ +final class Upsert extends Model implements ModelInterface +{ + /** + * GetBible Config + * + * @var Config + * @since 2.0.1 + */ + protected Config $config; + + /** + * Constructor + * + * @param Config $config The getBible config object. + * @param Table $table The getBible table object. + * + * @since 2.0.1 + */ + public function __construct(Config $config, Table $table) + { + parent::__construct($table); + + $this->config = $config; + } + + /** + * Model the value + * Example: $this->value(value, 'field_key', 'table_name'); + * + * @param mixed $value The value to model + * @param string $field The field key + * @param string|null $table The table + * + * @return mixed + * @since 2.0.1 + */ + public function value($value, string $field, ?string $table = null) + { + // set the table name + if (empty($table)) + { + $table = $this->getTable(); + } + + // check if this is a valid table + if (($store = $this->table->get($table, $field, 'store')) !== null) + { + // Model Distribution History + if ($table === 'translation' && $field === 'distribution_history') + { + $value = $this->modelDistributionHistory($value); + } + + // open the value based on the store method + switch($store) + { + case 'json': + $value = json_encode($value, JSON_FORCE_OBJECT); + break; + } + } + + return $value; + } + + /** + * Validate before the value is modelled + * + * @param mixed $value The field value + * @param string|null $field The field key + * @param string|null $table The table + * + * @return bool + * @since 2.0.1 + */ + protected function validateBefore(&$value, ?string $field = null, ?string $table = null): bool + { + // add all values + return true; + } + + /** + * Validate after the value is modelled + * + * @param mixed $value The field value + * @param string|null $field The field key + * @param string|null $table The table + * + * @return bool + * @since 2.0.1 + */ + protected function validateAfter(&$value, ?string $field = null, ?string $table = null): bool + { + // add all values + return true; + } + + /** + * Get the current active table + * + * @return string + * @since 2.0.1 + */ + protected function getTable(): string + { + return $this->config->table_name; + } + + /** + * Model Distribution History + * + * @param mixed $value The value to model + * + * @return mixed + * @since 2.0.1 + */ + public function modelDistributionHistory($value) + { + if (ObjectHelper::check($value)) + { + $n = 0; + $bucket = []; + foreach ($value as $version => $description) + { + $bucket["distribution_history$n"] = ['version' => $version, 'description' => $description]; + $n++; + } + return $bucket; + } + return ''; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Model/index.html b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Model/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Model/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Note.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Note.php new file mode 100644 index 0000000..b51a050 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Note.php @@ -0,0 +1,241 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible; + + +use Joomla\CMS\Language\Text; +use VDM\Joomla\GetBible\Database\Load; +use VDM\Joomla\GetBible\Database\Insert; +use VDM\Joomla\GetBible\Database\Update; +use VDM\Joomla\GetBible\Linker; +use VDM\Joomla\Utilities\GuidHelper; + + +/** + * The GetBible Note + * + * @since 2.0.1 + */ +final class Note +{ + /** + * The Load class + * + * @var Load + * @since 2.0.1 + */ + protected Load $load; + + /** + * The Insert class + * + * @var Insert + * @since 2.0.1 + */ + protected Insert $insert; + + /** + * The Update class + * + * @var Update + * @since 2.0.1 + */ + protected Update $update; + + /** + * The Linker class + * + * @var Linker + * @since 2.0.1 + */ + protected Linker $linker; + + /** + * Constructor + * + * @param Load $load The load object. + * @param Insert $insert The insert object. + * @param Update $update The update object. + * @param Linker $linker The linker object. + * + * @since 2.0.1 + */ + public function __construct( + Load $load, + Insert $insert, + Update $update, + Linker $linker) + { + $this->load = $load; + $this->insert = $insert; + $this->update = $update; + $this->linker = $linker; + } + + /** + * Set a note + * + * @param int $book The book in which the note is made + * @param int $chapter The chapter in which the note is made + * @param int $verse The verse where the note is made + * @param string|null $note The note being made + * + * @return array|null Array of the note values on success + * @since 2.0.1 + **/ + public function set( + int $book, + int $chapter, + int $verse, + ?string $note + ): ?array + { + // make sure the linker has access + if (($linker = $this->linker->get()) === null) + { + return [ + 'error' => Text::_("COM_GETBIBLE_WITHOUT_SELECTING_THE_CORRECT_FAVOURITE_VERSE_YOU_CANT_PERFORM_THE_INITIAL_ACTION"), + 'access_required' => true + ]; + } + + // get note if it exists + if (($_note = $this->get($linker, $book, $chapter, $verse)) !== null) + { + // publish if not published + if ($_note->published != 1 && !$this->update->value(1, 'published', $_note->id, 'id', 'note')) + { + return [ + 'error' => Text::_('COM_GETBIBLE_NOTE_ALREADY_EXIST_BUT_COULD_NOT_BE_REACTIVATED') + ]; + } + + // update the note if needed + if ((!isset($_note->note) || $_note->note !== $note) && !$this->update->value($note, 'note', $_note->id, 'id', 'note')) + { + return [ + 'error' => Text::_('COM_GETBIBLE_NOTE_ALREADY_EXIST_BUT_COULD_NOT_UPDATE_THE_NOTE_TEXT') + ]; + } + + $_note->published = 1; + $_note->note = $note; + $_note->success = Text::_('COM_GETBIBLE_THE_NOTE_WAS_SUCCESSFULLY_UPDATED'); + return (array) $_note; + } + // create a new tag + elseif ($this->create($linker, $book, $chapter, $verse, $note) + && ($_note = $this->get($linker, $book, $chapter, $verse)) !== null) + { + $_note->success = Text::_('COM_GETBIBLE_THE_NOTE_WAS_SUCCESSFULLY_CREATED'); + return (array) $_note; + } + + return null; + } + + /** + * Delete a note + * + * @param string $note The note GUID value + * + * @return bool True on success + * @since 2.0.1 + **/ + public function delete(string $note): bool + { + // make sure the linker has access + if (($linker = $this->linker->get()) === null) + { + return false; + } + + // make sure the linker has access to delete this tag + if (($id = $this->load->value(['guid' => $note, 'linker' => $linker], 'id', 'note')) !== null && $id > 0) + { + return $this->update->value(-2, 'published', $id, 'id', 'note'); + } + + return false; + } + + /** + * Get a note + * + * @param string $linker The linker GUID value + * @param int $book The book in which the note is made + * @param int $chapter The chapter in which the note is made + * @param int $verse The verse where the note is made + * + * @return object|null Object of the note values on success + * @since 2.0.1 + **/ + private function get( + string $linker, + int $book, + int $chapter, + int $verse + ): ?object + { + // get note if it exist + if (($note = $this->load->item([ + 'linker' => $linker, + 'book_nr' => $book, + 'chapter' => $chapter, + 'verse' => $verse + ], 'note')) !== null) + { + return $note; + } + + return null; + } + + /** + * Create a note + * + * @param string $linker The linker GUID value + * @param int $book The book in which the note is made + * @param int $chapter The chapter in which the note is made + * @param int $verse The verse where the note is made + * @param string|null $note The note being created (allow empty notes) + * + * @return bool True on success + * @since 2.0.1 + **/ + private function create( + string $linker, + int $book, + int $chapter, + int $verse, + ?string $note + ): bool + { + $guid = (string) GuidHelper::get(); + while (!GuidHelper::valid($guid, 'note', 0, 'getbible')) + { + // must always be set + $guid = (string) GuidHelper::get(); + } + + return $this->insert->row([ + 'note' => $note ?? '', + 'access' => 0, + 'linker' => $linker, + 'book_nr' => $book, + 'chapter' => $chapter, + 'verse' => $verse, + 'guid' => $guid + ], 'note'); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Openai.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Openai.php new file mode 100644 index 0000000..8cc9fe9 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Openai.php @@ -0,0 +1,86 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible; + + +use Joomla\DI\Container; +use VDM\Joomla\GetBible\Service\Openai as Api; +use VDM\Joomla\Openai\Service\Utilities; +use VDM\Joomla\GetBible\Service\Data; +use VDM\Joomla\GetBible\Service\AI; +use VDM\Joomla\GetBible\Service\Model; +use VDM\Joomla\GetBible\Service\Database; +use VDM\Joomla\Interfaces\FactoryInterface; + + +/** + * Openai Factory + * + * @since 3.2.0 + */ +abstract class Openai implements FactoryInterface +{ + /** + * Global Package Container + * + * @var Container + * @since 3.2.0 + **/ + protected static $container = null; + + /** + * Get any class from the package container + * + * @param string $key The container class key + * + * @return Mixed + * @since 3.2.0 + */ + public static function _($key) + { + return self::getContainer()->get($key); + } + + /** + * Get the global package container + * + * @return Container + * @since 3.2.0 + */ + public static function getContainer(): Container + { + if (!self::$container) + { + self::$container = self::createContainer(); + } + + return self::$container; + } + + /** + * Create a container object + * + * @return Container + * @since 3.2.0 + */ + protected static function createContainer(): Container + { + return (new Container()) + ->registerServiceProvider(new Api()) + ->registerServiceProvider(new Utilities()) + ->registerServiceProvider(new Data()) + ->registerServiceProvider(new AI()) + ->registerServiceProvider(new Model()) + ->registerServiceProvider(new Database()); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Openai/Config.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Openai/Config.php new file mode 100644 index 0000000..1c95a39 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Openai/Config.php @@ -0,0 +1,305 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Openai; + + +use Joomla\CMS\Factory as JoomlaFactory; +use Joomla\Registry\Registry as JoomlaRegistry; +use Joomla\Input\Input; +use VDM\Joomla\Utilities\Component\Helper; +use VDM\Joomla\Abstraction\BaseConfig; + + +/** + * GetBible Openai Configurations + * + * @since 2.0.1 + */ +class Config extends BaseConfig +{ + /** + * Hold a JInput object for easier access to the input variables. + * + * @var Input + * @since 3.2.0 + */ + protected Input $input; + + /** + * The Params + * + * @var JoomlaRegistry + * @since 3.2.0 + */ + protected JoomlaRegistry $params; + + /** + * Constructor + * + * @param Input|null $input Input + * @param JoomlaRegistry|null $params The component parameters + * + * @throws \Exception + * @since 3.2.0 + */ + public function __construct(?Input $input = null, ?JoomlaRegistry $params = null) + { + $this->input = $input ?: JoomlaFactory::getApplication()->input; + $this->params = $params ?: Helper::getParams('com_getbible'); + + // run parent constructor + parent::__construct(); + } + + /** + * get Prompt GUID + * + * @return string|null The translation abbreviation + * @since 2.0.1 + */ + protected function getPrompt(): ?string + { + return $this->input->getString('guid'); + } + + /** + * get Translation Abbreviation + * + * @return string|null The translation abbreviation + * @since 2.0.1 + */ + protected function getTranslation(): ?string + { + return $this->input->getString('t') ?? $this->input->getString('version') ?? $this->input->getString('translation'); + } + + /** + * get Book Number + * + * @return int|null The book number + * @since 2.0.1 + */ + protected function getBook(): ?int + { + return $this->input->getInt('book'); + } + + /** + * get Chapter Number + * + * @return int|null The chapter number + * @since 2.0.1 + */ + protected function getChapter(): ?int + { + return $this->input->getInt('chapter'); + } + + /** + * get Verse Number/s + * + * @return string|null The verse number/s + * @since 2.0.1 + */ + protected function getVerse(): ?string + { + return $this->input->getString('verse'); + } + + /** + * get Words Number/s + * + * @return string|null The word number/s + * @since 2.0.1 + */ + protected function getWords(): ?string + { + return $this->input->getString('words'); + } + + /** + * get Enable Open AI + * + * @return bool The switch to enable open AI + * @since 2.0.1 + */ + protected function getEnableopenai(): bool + { + if ($this->params->get('enable_open_ai', 0) == 1) + { + return true; + } + + return false; + } + + /** + * get Enable Open AI Organisation + * + * @return bool The switch to enable open AI Organisation + * @since 2.0.1 + */ + protected function getEnableopenaiorg(): bool + { + if ($this->params->get('enable_open_ai_org', 0) == 1) + { + return true; + } + + return false; + } + + /** + * get User Token + * + * @return string|null The token + * @since 2.0.1 + */ + protected function getToken(): ?string + { + if (!$this->enable_open_ai) + { + return null; + } + + return $this->params->get('openai_token'); + } + + /** + * get Org Token + * + * @return string|null The org token + * @since 2.0.1 + */ + protected function getOrgToken(): ?string + { + if (!$this->enable_open_ai || !$this->enable_open_ai_org) + { + return null; + } + + return $this->params->get('openai_org_token'); + } + + /** + * get Open AI Model name + * + * @return string|null The model name + * @since 2.0.1 + */ + protected function getModel(): ?string + { + if (!$this->enable_open_ai) + {die; + return null; + } + + return $this->params->get('openai_model'); + } + + /** + * get Max Tokens + * + * @return int|null The max tokens + * @since 2.0.1 + */ + protected function getMaxtokens(): ?int + { + if (!$this->enable_open_ai) + { + return null; + } + + return (int) $this->params->get('openai_max_tokens', 300); + } + + /** + * get Temperature + * + * @return float|null The temperature + * @since 2.0.1 + */ + protected function getTemperature(): ?float + { + if (!$this->enable_open_ai) + { + return null; + } + + return (float) $this->params->get('openai_temperature', 1); + } + + /** + * get Top P + * + * @return float|null The top p + * @since 2.0.1 + */ + protected function getTopp(): ?float + { + if (!$this->enable_open_ai) + { + return null; + } + + return (float) $this->params->get('openai_top_p', 1); + } + + /** + * get N (number of results) + * + * @return int|null The number of results + * @since 2.0.1 + */ + protected function getN(): ?int + { + if (!$this->enable_open_ai) + { + return null; + } + + return (int) $this->params->get('openai_n', 1); + } + + /** + * get Presence Penalty + * + * @return float|null The presence penalty + * @since 2.0.1 + */ + protected function getPresencepenalty(): ?float + { + if (!$this->enable_open_ai) + { + return null; + } + + return (float) $this->params->get('openai_presence_penalty', 0); + } + + /** + * get Frequency Penalty + * + * @return float|null The frequency penalty + * @since 2.0.1 + */ + protected function getFrequencypenalty(): ?float + { + if (!$this->enable_open_ai) + { + return null; + } + + return (float) $this->params->get('openai_frequency_penalty', 0); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Openai/index.html b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Openai/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Openai/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Search.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Search.php new file mode 100644 index 0000000..7483592 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Search.php @@ -0,0 +1,23 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible; + + +/** + * The GetBible Search + * + * @since 2.0.1 + */ +final class Search +{ +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/AI.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/AI.php new file mode 100644 index 0000000..c53cb08 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/AI.php @@ -0,0 +1,81 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VDM\Joomla\GetBible\AI as GetBible; +use VDM\Joomla\GetBible\AI\Engineer; + + +/** + * The GetBible AI Service + * + * @since 3.2.0 + */ +class AI implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 3.2.0 + */ + public function register(Container $container) + { + $container->alias(GetBible::class, 'GetBible.AI') + ->share('GetBible.AI', [$this, 'getAI'], true); + + $container->alias(Engineer::class, 'GetBible.AI.Engineer') + ->share('GetBible.AI.Engineer', [$this, 'getEngineer'], true); + } + + /** + * Get the GetBible AI class + * + * @param Container $container The DI container. + * + * @return GetBible + * @since 3.2.0 + */ + public function getAI(Container $container): GetBible + { + return new GetBible( + $container->get('GetBible.Config'), + $container->get('GetBible.Response'), + $container->get('GetBible.AI.Engineer') + ); + } + + /** + * Get the Engineer AI class + * + * @param Container $container The DI container. + * + * @return Engineer + * @since 3.2.0 + */ + public function getEngineer(Container $container): Engineer + { + return new Engineer( + $container->get('GetBible.Scripture'), + $container->get('GetBible.Prompt'), + $container->get('GetBible.Placeholders'), + $container->get('Openai.Chat'), + $container->get('GetBible.Insert') + ); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Api.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Api.php new file mode 100644 index 0000000..b08eb75 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Api.php @@ -0,0 +1,121 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VDM\Joomla\GetBible\Api\Translations; +use VDM\Joomla\GetBible\Api\Books; +use VDM\Joomla\GetBible\Api\Chapters; +use VDM\Joomla\GetBible\Api\Verses; + + +/** + * The GetBible Api Service + * + * @since 2.0.1 + */ +class Api implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 2.0.1 + */ + public function register(Container $container) + { + $container->alias(Translations::class, 'GetBible.Api.Translations') + ->share('GetBible.Api.Translations', [$this, 'getTranslations'], true); + + $container->alias(Books::class, 'GetBible.Api.Books') + ->share('GetBible.Api.Books', [$this, 'getBooks'], true); + + $container->alias(Chapters::class, 'GetBible.Api.Chapters') + ->share('GetBible.Api.Chapters', [$this, 'getChapters'], true); + + $container->alias(Verses::class, 'GetBible.Api.Verses') + ->share('GetBible.Api.Verses', [$this, 'getVerses'], true); + } + + /** + * Get the Translations class + * + * @param Container $container The DI container. + * + * @return Translations + * @since 3.2.0 + */ + public function getTranslations(Container $container): Translations + { + return new Translations( + $container->get('GetBible.Utilities.Http'), + $container->get('GetBible.Utilities.Uri'), + $container->get('GetBible.Utilities.Response') + ); + } + + /** + * Get the Books class + * + * @param Container $container The DI container. + * + * @return Books + * @since 3.2.0 + */ + public function getBooks(Container $container): Books + { + return new Books( + $container->get('GetBible.Utilities.Http'), + $container->get('GetBible.Utilities.Uri'), + $container->get('GetBible.Utilities.Response') + ); + } + + /** + * Get the Chapters class + * + * @param Container $container The DI container. + * + * @return Chapters + * @since 3.2.0 + */ + public function getChapters(Container $container): Chapters + { + return new Chapters( + $container->get('GetBible.Utilities.Http'), + $container->get('GetBible.Utilities.Uri'), + $container->get('GetBible.Utilities.Response') + ); + } + + /** + * Get the Verses class + * + * @param Container $container The DI container. + * + * @return Verses + * @since 3.2.0 + */ + public function getVerses(Container $container): Verses + { + return new Verses( + $container->get('GetBible.Utilities.Http'), + $container->get('GetBible.Utilities.Uri'), + $container->get('GetBible.Utilities.Response') + ); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/App.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/App.php new file mode 100644 index 0000000..012f390 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/App.php @@ -0,0 +1,259 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VDM\Joomla\GetBible\Config; +use VDM\Joomla\GetBible\Table; +use VDM\Joomla\GetBible\DailyScripture; +use VDM\Joomla\GetBible\Search; +use VDM\Joomla\GetBible\Watcher; +use VDM\Joomla\GetBible\Loader; +use VDM\Joomla\GetBible\Linker; +use VDM\Joomla\GetBible\Note; +use VDM\Joomla\GetBible\Tag; +use VDM\Joomla\GetBible\Tagged; +use VDM\Joomla\GetBible\Tagged\Paragraphs; + + +/** + * The GetBible App Service + * + * @since 2.0.1 + */ +class App implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 2.0.1 + */ + public function register(Container $container) + { + $container->alias(Config::class, 'GetBible.Config') + ->share('GetBible.Config', [$this, 'getConfig'], true); + + $container->alias(Table::class, 'GetBible.Table') + ->share('GetBible.Table', [$this, 'getTable'], true); + + $container->alias(DailyScripture::class, 'DailyScripture') + ->share('DailyScripture', [$this, 'getDailyScripture'], true); + + $container->alias(Search::class, 'GetBible.Search') + ->share('GetBible.Search', [$this, 'getSearch'], true); + + $container->alias(Watcher::class, 'GetBible.Watcher') + ->share('GetBible.Watcher', [$this, 'getWatcher'], true); + + $container->alias(Loader::class, 'GetBible.Loader') + ->share('GetBible.Loader', [$this, 'getLoader'], true); + + $container->alias(Linker::class, 'GetBible.Linker') + ->share('GetBible.Linker', [$this, 'getLinker'], true); + + $container->alias(Note::class, 'GetBible.Note') + ->share('GetBible.Note', [$this, 'getNote'], true); + + $container->alias(Tag::class, 'GetBible.Tag') + ->share('GetBible.Tag', [$this, 'getTag'], true); + + $container->alias(Tagged::class, 'GetBible.Tagged') + ->share('GetBible.Tagged', [$this, 'getTagged'], true); + + $container->alias(Paragraphs::class, 'GetBible.Tagged.Paragraphs') + ->share('GetBible.Tagged.Paragraphs', [$this, 'getTaggedParagraphs'], true); + } + + /** + * Get the Config class + * + * @param Container $container The DI container. + * + * @return Config + * @since 2.0.1 + */ + public function getConfig(Container $container): Config + { + return new Config(); + } + + /** + * Get the Table class + * + * @param Container $container The DI container. + * + * @return Table + * @since 2.0.1 + */ + public function getTable(Container $container): Table + { + return new Table(); + } + + /** + * Get the Daily Scripture class + * + * @param Container $container The DI container. + * + * @return DailyScripture + * @since 2.0.1 + */ + public function getDailyScripture(Container $container): DailyScripture + { + return new DailyScripture( + $container->get('GetBible.Config'), + $container->get('GetBible.Utilities.Http'), + $container->get('GetBible.Load') + ); + } + + /** + * Get the Search class + * + * @param Container $container The DI container. + * + * @return Search + * @since 2.0.1 + */ + public function getSearch(Container $container): Search + { + return new Search(); + } + + /** + * Get the Watcher class + * + * @param Container $container The DI container. + * + * @return Watcher + * @since 2.0.1 + */ + public function getWatcher(Container $container): Watcher + { + return new Watcher( + $container->get('GetBible.Load'), + $container->get('GetBible.Insert'), + $container->get('GetBible.Update'), + $container->get('GetBible.Api.Translations'), + $container->get('GetBible.Api.Books'), + $container->get('GetBible.Api.Chapters'), + $container->get('GetBible.Api.Verses') + ); + } + + /** + * Get the Loader class + * + * @param Container $container The DI container. + * + * @return Loader + * @since 2.0.1 + */ + public function getLoader(Container $container): Loader + { + return new Loader( + $container->get('GetBible.Load'), + $container->get('GetBible.Watcher') + ); + } + + /** + * Get the Linker class + * + * @param Container $container The DI container. + * + * @return Linker + * @since 2.0.1 + */ + public function getLinker(Container $container): Linker + { + return new Linker( + $container->get('GetBible.Load'), + $container->get('GetBible.Insert'), + $container->get('GetBible.Update'), + $container->get('GetBible.Utilities.Session') + ); + } + + /** + * Get the Note class + * + * @param Container $container The DI container. + * + * @return Note + * @since 2.0.1 + */ + public function getNote(Container $container): Note + { + return new Note( + $container->get('GetBible.Load'), + $container->get('GetBible.Insert'), + $container->get('GetBible.Update'), + $container->get('GetBible.Linker') + ); + } + + /** + * Get the Tag class + * + * @param Container $container The DI container. + * + * @return Tag + * @since 2.0.1 + */ + public function getTag(Container $container): Tag + { + return new Tag( + $container->get('GetBible.Load'), + $container->get('GetBible.Insert'), + $container->get('GetBible.Update'), + $container->get('GetBible.Linker') + ); + } + + /** + * Get the Tagged class + * + * @param Container $container The DI container. + * + * @return Tagged + * @since 2.0.1 + */ + public function getTagged(Container $container): Tagged + { + return new Tagged( + $container->get('GetBible.Load'), + $container->get('GetBible.Insert'), + $container->get('GetBible.Update'), + $container->get('GetBible.Linker') + ); + } + + /** + * Get the Paragraphs class + * + * @param Container $container The DI container. + * + * @return Paragraphs + * @since 2.0.1 + */ + public function getTaggedParagraphs(Container $container): Paragraphs + { + return new Paragraphs(); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Data.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Data.php new file mode 100644 index 0000000..20eca16 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Data.php @@ -0,0 +1,276 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VDM\Joomla\GetBible\Openai\Config; +use VDM\Joomla\GetBible\Table; +use VDM\Joomla\GetBible\Utilities\StringHelper; +use VDM\Joomla\GetBible\Data\Scripture; +use VDM\Joomla\GetBible\Data\Translation; +use VDM\Joomla\GetBible\Data\Book; +use VDM\Joomla\GetBible\Data\Chapter; +use VDM\Joomla\GetBible\Data\Verse; +use VDM\Joomla\GetBible\Data\Word; +use VDM\Joomla\GetBible\Data\Prompt; +use VDM\Joomla\GetBible\Data\Placeholders; +use VDM\Joomla\GetBible\Data\Response; + + +/** + * The GetBible Data Service + * + * @since 3.2.0 + */ +class Data implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 3.2.0 + */ + public function register(Container $container) + { + $container->alias(Config::class, 'GetBible.Config') + ->share('GetBible.Config', [$this, 'getConfig'], true); + + $container->alias(Table::class, 'GetBible.Table') + ->share('GetBible.Table', [$this, 'getTable'], true); + + $container->alias(StringHelper::class, 'GetBible.Utilities.String') + ->share('GetBible.Utilities.String', [$this, 'getString'], true); + + $container->alias(Prompt::class, 'GetBible.Prompt') + ->share('GetBible.Prompt', [$this, 'getPrompt'], true); + + $container->alias(Scripture::class, 'GetBible.Scripture') + ->share('GetBible.Scripture', [$this, 'getScripture'], true); + + $container->alias(Translation::class, 'GetBible.Translation') + ->share('GetBible.Translation', [$this, 'getTranslation'], true); + + $container->alias(Book::class, 'GetBible.Book') + ->share('GetBible.Book', [$this, 'getBook'], true); + + $container->alias(Chapter::class, 'GetBible.Chapter') + ->share('GetBible.Chapter', [$this, 'getChapter'], true); + + $container->alias(Verse::class, 'GetBible.Verse') + ->share('GetBible.Verse', [$this, 'getVerse'], true); + + $container->alias(Word::class, 'GetBible.Word') + ->share('GetBible.Word', [$this, 'getWord'], true); + + $container->alias(Placeholders::class, 'GetBible.Placeholders') + ->share('GetBible.Placeholders', [$this, 'getPlaceholders'], true); + + $container->alias(Response::class, 'GetBible.Response') + ->share('GetBible.Response', [$this, 'getResponse'], true); + } + + /** + * Get the Config class + * + * @param Container $container The DI container. + * + * @return Config + * @since 2.0.1 + */ + public function getConfig(Container $container): Config + { + return new Config(); + } + + /** + * Get the Table class + * + * @param Container $container The DI container. + * + * @return Table + * @since 2.0.1 + */ + public function getTable(Container $container): Table + { + return new Table(); + } + + /** + * Get the String Helper class + * + * @param Container $container The DI container. + * + * @return StringHelper + * @since 3.2.0 + */ + public function getString(Container $container): StringHelper + { + return new StringHelper(); + } + + /** + * Get the Prompt class + * + * @param Container $container The DI container. + * + * @return Prompt + * @since 3.2.0 + */ + public function getPrompt(Container $container): Prompt + { + return new Prompt( + $container->get('GetBible.Load'), + $container->get('GetBible.Config') + ); + } + + /** + * Get the Scripture class + * + * @param Container $container The DI container. + * + * @return Scripture + * @since 3.2.0 + */ + public function getScripture(Container $container): Scripture + { + return new Scripture( + $container->get('GetBible.Translation'), + $container->get('GetBible.Book'), + $container->get('GetBible.Chapter'), + $container->get('GetBible.Verse'), + $container->get('GetBible.Word'), + ); + } + + /** + * Get the Translation class + * + * @param Container $container The DI container. + * + * @return Translation + * @since 3.2.0 + */ + public function getTranslation(Container $container): Translation + { + return new Translation( + $container->get('GetBible.Load'), + $container->get('GetBible.Config') + ); + } + + /** + * Get the Book class + * + * @param Container $container The DI container. + * + * @return Book + * @since 3.2.0 + */ + public function getBook(Container $container): Book + { + return new Book( + $container->get('GetBible.Load'), + $container->get('GetBible.Config') + ); + } + + /** + * Get the Chapter class + * + * @param Container $container The DI container. + * + * @return Chapter + * @since 3.2.0 + */ + public function getChapter(Container $container): Chapter + { + return new Chapter( + $container->get('GetBible.Load'), + $container->get('GetBible.Config') + ); + } + + /** + * Get the Verse class + * + * @param Container $container The DI container. + * + * @return Verse + * @since 3.2.0 + */ + public function getVerse(Container $container): Verse + { + return new Verse( + $container->get('GetBible.Chapter'), + $container->get('GetBible.Config'), + $container->get('GetBible.Prompt'), + $container->get('GetBible.Utilities.String') + ); + } + + /** + * Get the Word class + * + * @param Container $container The DI container. + * + * @return Word + * @since 3.2.0 + */ + public function getWord(Container $container): Word + { + return new Word( + $container->get('GetBible.Verse'), + $container->get('GetBible.Config'), + $container->get('GetBible.Prompt') + ); + } + + /** + * Get the Placeholders class + * + * @param Container $container The DI container. + * + * @return Placeholders + * @since 3.2.0 + */ + public function getPlaceholders(Container $container): Placeholders + { + return new Placeholders( + $container->get('GetBible.Scripture'), + $container->get('GetBible.Prompt') + ); + } + + /** + * Get the Response class + * + * @param Container $container The DI container. + * + * @return Response + * @since 3.2.0 + */ + public function getResponse(Container $container): Response + { + return new Response( + $container->get('GetBible.Scripture'), + $container->get('GetBible.Prompt'), + $container->get('GetBible.Load'), + $container->get('GetBible.Config') + ); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Database.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Database.php new file mode 100644 index 0000000..b1a7039 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Database.php @@ -0,0 +1,149 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VDM\Joomla\Database\Insert as BaseInsert; +use VDM\Joomla\Database\Update as BaseUpdate; +use VDM\Joomla\Database\Load as BaseLoad; +use VDM\Joomla\GetBible\Database\Insert; +use VDM\Joomla\GetBible\Database\Load; +use VDM\Joomla\GetBible\Database\Update; + + +/** + * The GetBible Database Service + * + * @since 2.0.1 + */ +class Database implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 2.0.1 + */ + public function register(Container $container) + { + $container->alias(BaseInsert::class, 'DB.Insert') + ->share('DB.Insert', [$this, 'getBaseInsert'], true); + + $container->alias(BaseUpdate::class, 'DB.Update') + ->share('DB.Update', [$this, 'getBaseUpdate'], true); + + $container->alias(BaseLoad::class, 'DB.Load') + ->share('DB.Load', [$this, 'getBaseLoad'], true); + + $container->alias(Insert::class, 'GetBible.Insert') + ->share('GetBible.Insert', [$this, 'getInsert'], true); + + $container->alias(Update::class, 'GetBible.Update') + ->share('GetBible.Update', [$this, 'getUpdate'], true); + + $container->alias(Load::class, 'GetBible.Load') + ->share('GetBible.Load', [$this, 'getLoad'], true); + } + + /** + * Get the BaseUpdate class + * + * @param Container $container The DI container. + * + * @return BaseUpdate + * @since 2.0.1 + */ + public function getBaseUpdate(Container $container): BaseUpdate + { + return new BaseUpdate(); + } + + /** + * Get the BaseInsert class + * + * @param Container $container The DI container. + * + * @return BaseInsert + * @since 2.0.1 + */ + public function getBaseInsert(Container $container): BaseInsert + { + return new BaseInsert(); + } + + /** + * Get the BaseLoad class + * + * @param Container $container The DI container. + * + * @return BaseLoad + * @since 2.0.1 + */ + public function getBaseLoad(Container $container): BaseLoad + { + return new BaseLoad(); + } + + /** + * Get the Insert class + * + * @param Container $container The DI container. + * + * @return Insert + * @since 2.0.1 + */ + public function getInsert(Container $container): Insert + { + return new Insert( + $container->get('GetBible.Model.Upsert'), + $container->get('DB.Insert') + ); + } + + /** + * Get the Update class + * + * @param Container $container The DI container. + * + * @return Update + * @since 2.0.1 + */ + public function getUpdate(Container $container): Update + { + return new Update( + $container->get('GetBible.Model.Upsert'), + $container->get('DB.Update') + ); + } + + /** + * Get the Table class + * + * @param Container $container The DI container. + * + * @return Load + * @since 2.0.1 + */ + public function getLoad(Container $container): Load + { + return new Load( + $container->get('GetBible.Table'), + $container->get('GetBible.Model.Load'), + $container->get('DB.Load') + ); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Model.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Model.php new file mode 100644 index 0000000..2fd9db7 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Model.php @@ -0,0 +1,77 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VDM\Joomla\GetBible\Model\Upsert; +use VDM\Joomla\GetBible\Model\Load; + + +/** + * The GetBible Model Service + * + * @since 2.0.1 + */ +class Model implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 2.0.1 + */ + public function register(Container $container) + { + $container->alias(Upsert::class, 'GetBible.Model.Upsert') + ->share('GetBible.Model.Upsert', [$this, 'getUpsert'], true); + + $container->alias(Load::class, 'GetBible.Model.Load') + ->share('GetBible.Model.Load', [$this, 'getLoad'], true); + } + + /** + * Get the Upsert class + * + * @param Container $container The DI container. + * + * @return Upsert + * @since 2.0.1 + */ + public function getUpsert(Container $container): Upsert + { + return new Upsert( + $container->get('GetBible.Config'), + $container->get('GetBible.Table') + ); + } + + /** + * Get the Load class + * + * @param Container $container The DI container. + * + * @return Load + * @since 2.0.1 + */ + public function getLoad(Container $container): Load + { + return new Load( + $container->get('GetBible.Config'), + $container->get('GetBible.Table') + ); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Openai.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Openai.php new file mode 100644 index 0000000..e33a1b5 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Openai.php @@ -0,0 +1,121 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VDM\Joomla\Openai\Chat; +use VDM\Joomla\Openai\Completions; +use VDM\Joomla\Openai\Models; +use VDM\Joomla\Openai\Moderate; + + +/** + * The Openai Api Service + * + * @since 3.2.0 + */ +class Openai implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 3.2.0 + */ + public function register(Container $container) + { + $container->alias(Chat::class, 'Openai.Chat') + ->share('Openai.Chat', [$this, 'getChat'], true); + + $container->alias(Completions::class, 'Openai.Completions') + ->share('Openai.Completions', [$this, 'getCompletions'], true); + + $container->alias(Models::class, 'Openai.Models') + ->share('Openai.Models', [$this, 'getModels'], true); + + $container->alias(Moderate::class, 'Openai.Moderate') + ->share('Openai.Moderate', [$this, 'getModerate'], true); + } + + /** + * Get the Chat class + * + * @param Container $container The DI container. + * + * @return Chat + * @since 3.2.0 + */ + public function getChat(Container $container): Chat + { + return new Chat( + $container->get('Openai.Utilities.Http'), + $container->get('Openai.Utilities.Uri'), + $container->get('Openai.Utilities.Response') + ); + } + + /** + * Get the Completions class + * + * @param Container $container The DI container. + * + * @return Completions + * @since 3.2.0 + */ + public function getCompletions(Container $container): Completions + { + return new Completions( + $container->get('Openai.Utilities.Http'), + $container->get('Openai.Utilities.Uri'), + $container->get('Openai.Utilities.Response') + ); + } + + /** + * Get the Models class + * + * @param Container $container The DI container. + * + * @return Models + * @since 3.2.0 + */ + public function getModels(Container $container): Models + { + return new Models( + $container->get('Openai.Utilities.Http'), + $container->get('Openai.Utilities.Uri'), + $container->get('Openai.Utilities.Response') + ); + } + + /** + * Get the Moderate class + * + * @param Container $container The DI container. + * + * @return Moderate + * @since 3.2.0 + */ + public function getModerate(Container $container): Moderate + { + return new Moderate( + $container->get('Openai.Utilities.Http'), + $container->get('Openai.Utilities.Uri'), + $container->get('Openai.Utilities.Response') + ); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Utilities.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Utilities.php new file mode 100644 index 0000000..74a87e2 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/Utilities.php @@ -0,0 +1,124 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VDM\Joomla\GetBible\Utilities\Uri; +use VDM\Joomla\GetBible\Utilities\Response; +use VDM\Joomla\GetBible\Utilities\Http; +use VDM\Joomla\GetBible\Utilities\StringHelper; +use VDM\Joomla\GetBible\Utilities\SessionHelper; + + +/** + * The GetBible Utilities Service + * + * @since 3.2.0 + */ +class Utilities implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 3.2.0 + */ + public function register(Container $container) + { + $container->alias(Uri::class, 'GetBible.Utilities.Uri') + ->share('GetBible.Utilities.Uri', [$this, 'getUri'], true); + + $container->alias(Response::class, 'GetBible.Utilities.Response') + ->share('GetBible.Utilities.Response', [$this, 'getResponse'], true); + + $container->alias(Http::class, 'GetBible.Utilities.Http') + ->share('GetBible.Utilities.Http', [$this, 'getHttp'], true); + + $container->alias(StringHelper::class, 'GetBible.Utilities.String') + ->share('GetBible.Utilities.String', [$this, 'getString'], true); + + $container->alias(SessionHelper::class, 'GetBible.Utilities.Session') + ->share('GetBible.Utilities.Session', [$this, 'getSession'], true); + } + + /** + * Get the Uri class + * + * @param Container $container The DI container. + * + * @return Uri + * @since 3.2.0 + */ + public function getUri(Container $container): Uri + { + return new Uri( + $container->get('GetBible.Config') + ); + } + + /** + * Get the Response class + * + * @param Container $container The DI container. + * + * @return Response + * @since 3.2.0 + */ + public function getResponse(Container $container): Response + { + return new Response(); + } + + /** + * Get the Http class + * + * @param Container $container The DI container. + * + * @return Http + * @since 3.2.0 + */ + public function getHttp(Container $container): Http + { + return new Http(); + } + + /** + * Get the String Helper class + * + * @param Container $container The DI container. + * + * @return StringHelper + * @since 3.2.0 + */ + public function getString(Container $container): StringHelper + { + return new StringHelper(); + } + + /** + * Get the Session Helper class + * + * @param Container $container The DI container. + * + * @return SessionHelper + * @since 3.2.0 + */ + public function getSession(Container $container): SessionHelper + { + return new SessionHelper(); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/index.html b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Service/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Table.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Table.php new file mode 100644 index 0000000..7184cc5 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Table.php @@ -0,0 +1,1076 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible; + + +use VDM\Joomla\Interfaces\Tableinterface; +use VDM\Joomla\Abstraction\BaseTable; + + +/** + * GetBible Tables + * + * @since 2.0.1 + */ +class Table extends BaseTable implements Tableinterface +{ + /** + * All areas/views/tables with their field details + * + * @var array + * @since 2.0.1 + **/ + protected array $tables = [ + 'linker' => [ + 'name' => [ + 'name' => 'name', + 'label' => 'COM_GETBIBLE_LINKER_NAME_LABEL', + 'type' => 'text', + 'title' => true, + 'list' => 'linkers', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'guid' => [ + 'name' => 'guid', + 'label' => 'COM_GETBIBLE_LINKER_GUID_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'linkers', + 'store' => NULL, + 'tab_name' => 'publishing', + ], + ], + 'note' => [ + 'book_nr' => [ + 'name' => 'book_nr', + 'label' => 'COM_GETBIBLE_NOTE_BOOK_NR_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'notes', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'linker' => [ + 'name' => 'linker', + 'label' => 'COM_GETBIBLE_NOTE_LINKER_LABEL', + 'type' => 'linkers', + 'title' => false, + 'list' => 'notes', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'access' => [ + 'name' => 'access', + 'label' => 'COM_GETBIBLE_NOTE_ACCESS_LABEL', + 'type' => 'radio', + 'title' => false, + 'list' => 'notes', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'guid' => [ + 'name' => 'guid', + 'label' => 'COM_GETBIBLE_NOTE_GUID_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'notes', + 'store' => NULL, + 'tab_name' => 'publishing', + ], + 'note' => [ + 'name' => 'note', + 'label' => 'COM_GETBIBLE_NOTE_NOTE_LABEL', + 'type' => 'textarea', + 'title' => false, + 'list' => 'notes', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'verse' => [ + 'name' => 'verse', + 'label' => 'COM_GETBIBLE_NOTE_VERSE_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'notes', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'chapter' => [ + 'name' => 'chapter', + 'label' => 'COM_GETBIBLE_NOTE_CHAPTER_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'notes', + 'store' => NULL, + 'tab_name' => 'Details', + ], + ], + 'tagged_verse' => [ + 'book_nr' => [ + 'name' => 'book_nr', + 'label' => 'COM_GETBIBLE_TAGGED_VERSE_BOOK_NR_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'tagged_verses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'abbreviation' => [ + 'name' => 'abbreviation', + 'label' => 'COM_GETBIBLE_TAGGED_VERSE_ABBREVIATION_LABEL', + 'type' => 'translations', + 'title' => false, + 'list' => 'tagged_verses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'access' => [ + 'name' => 'access', + 'label' => 'COM_GETBIBLE_TAGGED_VERSE_ACCESS_LABEL', + 'type' => 'radio', + 'title' => false, + 'list' => 'tagged_verses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'linker' => [ + 'name' => 'linker', + 'label' => 'COM_GETBIBLE_TAGGED_VERSE_LINKER_LABEL', + 'type' => 'linkers', + 'title' => false, + 'list' => 'tagged_verses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'tag' => [ + 'name' => 'tag', + 'label' => 'COM_GETBIBLE_TAGGED_VERSE_TAG_LABEL', + 'type' => 'tagers', + 'title' => false, + 'list' => 'tagged_verses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'guid' => [ + 'name' => 'guid', + 'label' => 'COM_GETBIBLE_TAGGED_VERSE_GUID_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'tagged_verses', + 'store' => NULL, + 'tab_name' => 'publishing', + ], + 'verse' => [ + 'name' => 'verse', + 'label' => 'COM_GETBIBLE_TAGGED_VERSE_VERSE_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'tagged_verses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'chapter' => [ + 'name' => 'chapter', + 'label' => 'COM_GETBIBLE_TAGGED_VERSE_CHAPTER_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'tagged_verses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + ], + 'prompt' => [ + 'name' => [ + 'name' => 'name', + 'label' => 'COM_GETBIBLE_PROMPT_NAME_LABEL', + 'type' => 'text', + 'title' => true, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Prompt', + ], + 'integration' => [ + 'name' => 'integration', + 'label' => 'COM_GETBIBLE_PROMPT_INTEGRATION_LABEL', + 'type' => 'list', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Prompt', + ], + 'cache_behaviour' => [ + 'name' => 'cache_behaviour', + 'label' => 'COM_GETBIBLE_PROMPT_CACHE_BEHAVIOUR_LABEL', + 'type' => 'list', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Prompt', + ], + 'abbreviation' => [ + 'name' => 'abbreviation', + 'label' => 'COM_GETBIBLE_PROMPT_ABBREVIATION_LABEL', + 'type' => 'targettranslations', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Prompt', + ], + 'guid' => [ + 'name' => 'guid', + 'label' => 'COM_GETBIBLE_PROMPT_GUID_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'publishing', + ], + 'model' => [ + 'name' => 'model', + 'label' => 'COM_GETBIBLE_PROMPT_MODEL_LABEL', + 'type' => 'list', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Open AI', + ], + 'presence_penalty' => [ + 'name' => 'presence_penalty', + 'label' => 'COM_GETBIBLE_PROMPT_PRESENCE_PENALTY_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Open AI', + ], + 'org_token' => [ + 'name' => 'org_token', + 'label' => 'COM_GETBIBLE_PROMPT_ORG_TOKEN_LABEL', + 'type' => 'password', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Open AI', + ], + 'token' => [ + 'name' => 'token', + 'label' => 'COM_GETBIBLE_PROMPT_TOKEN_LABEL', + 'type' => 'password', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Open AI', + ], + 'n_override' => [ + 'name' => 'n_override', + 'label' => 'COM_GETBIBLE_PROMPT_N_OVERRIDE_LABEL', + 'type' => 'radio', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Open AI', + ], + 'cache_capacity' => [ + 'name' => 'cache_capacity', + 'label' => 'COM_GETBIBLE_PROMPT_CACHE_CAPACITY_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Prompt', + ], + 'messages' => [ + 'name' => 'messages', + 'label' => 'COM_GETBIBLE_PROMPT_MESSAGES_LABEL', + 'type' => 'subform', + 'title' => false, + 'list' => 'prompts', + 'store' => 'json', + 'tab_name' => 'Prompt', + ], + 'response_retrieval' => [ + 'name' => 'response_retrieval', + 'label' => 'COM_GETBIBLE_PROMPT_RESPONSE_RETRIEVAL_LABEL', + 'type' => 'radio', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Prompt', + ], + 'frequency_penalty_override' => [ + 'name' => 'frequency_penalty_override', + 'label' => 'COM_GETBIBLE_PROMPT_FREQUENCY_PENALTY_OVERRIDE_LABEL', + 'type' => 'radio', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Open AI', + ], + 'n' => [ + 'name' => 'n', + 'label' => 'COM_GETBIBLE_PROMPT_N_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Open AI', + ], + 'max_tokens_override' => [ + 'name' => 'max_tokens_override', + 'label' => 'COM_GETBIBLE_PROMPT_MAX_TOKENS_OVERRIDE_LABEL', + 'type' => 'radio', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Open AI', + ], + 'token_override' => [ + 'name' => 'token_override', + 'label' => 'COM_GETBIBLE_PROMPT_TOKEN_OVERRIDE_LABEL', + 'type' => 'radio', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Open AI', + ], + 'max_tokens' => [ + 'name' => 'max_tokens', + 'label' => 'COM_GETBIBLE_PROMPT_MAX_TOKENS_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Open AI', + ], + 'ai_org_token_override' => [ + 'name' => 'ai_org_token_override', + 'label' => 'COM_GETBIBLE_PROMPT_AI_ORG_TOKEN_OVERRIDE_LABEL', + 'type' => 'radio', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Open AI', + ], + 'temperature_override' => [ + 'name' => 'temperature_override', + 'label' => 'COM_GETBIBLE_PROMPT_TEMPERATURE_OVERRIDE_LABEL', + 'type' => 'radio', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Open AI', + ], + 'presence_penalty_override' => [ + 'name' => 'presence_penalty_override', + 'label' => 'COM_GETBIBLE_PROMPT_PRESENCE_PENALTY_OVERRIDE_LABEL', + 'type' => 'radio', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Open AI', + ], + 'top_p_override' => [ + 'name' => 'top_p_override', + 'label' => 'COM_GETBIBLE_PROMPT_TOP_P_OVERRIDE_LABEL', + 'type' => 'radio', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Open AI', + ], + 'frequency_penalty' => [ + 'name' => 'frequency_penalty', + 'label' => 'COM_GETBIBLE_PROMPT_FREQUENCY_PENALTY_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Open AI', + ], + 'top_p' => [ + 'name' => 'top_p', + 'label' => 'COM_GETBIBLE_PROMPT_TOP_P_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Open AI', + ], + 'temperature' => [ + 'name' => 'temperature', + 'label' => 'COM_GETBIBLE_PROMPT_TEMPERATURE_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'prompts', + 'store' => NULL, + 'tab_name' => 'Open AI', + ], + ], + 'open_ai_response' => [ + 'response_id' => [ + 'name' => 'response_id', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_ID_LABEL', + 'type' => 'text', + 'title' => true, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'prompt' => [ + 'name' => 'prompt', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_PROMPT_LABEL', + 'type' => 'prompts', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'response_object' => [ + 'name' => 'response_object', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_OBJECT_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'response_model' => [ + 'name' => 'response_model', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_MODEL_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'total_tokens' => [ + 'name' => 'total_tokens', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_TOTAL_TOKENS_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'n' => [ + 'name' => 'n', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_N_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Prompt', + ], + 'frequency_penalty' => [ + 'name' => 'frequency_penalty', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_FREQUENCY_PENALTY_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Prompt', + ], + 'presence_penalty' => [ + 'name' => 'presence_penalty', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_PRESENCE_PENALTY_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Prompt', + ], + 'word' => [ + 'name' => 'word', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_WORD_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Bible', + ], + 'chapter' => [ + 'name' => 'chapter', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_CHAPTER_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Bible', + ], + 'lcsh' => [ + 'name' => 'lcsh', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_LCSH_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Bible', + ], + 'completion_tokens' => [ + 'name' => 'completion_tokens', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_COMPLETION_TOKENS_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'prompt_tokens' => [ + 'name' => 'prompt_tokens', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_PROMPT_TOKENS_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'response_created' => [ + 'name' => 'response_created', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_RESPONSE_CREATED_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'abbreviation' => [ + 'name' => 'abbreviation', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_ABBREVIATION_LABEL', + 'type' => 'targettranslations', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Bible', + ], + 'language' => [ + 'name' => 'language', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_LANGUAGE_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Bible', + ], + 'max_tokens' => [ + 'name' => 'max_tokens', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_MAX_TOKENS_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Prompt', + ], + 'book' => [ + 'name' => 'book', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_BOOK_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Bible', + ], + 'temperature' => [ + 'name' => 'temperature', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_TEMPERATURE_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Prompt', + ], + 'verse' => [ + 'name' => 'verse', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_VERSE_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Bible', + ], + 'top_p' => [ + 'name' => 'top_p', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_TOP_P_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Prompt', + ], + 'selected_word' => [ + 'name' => 'selected_word', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_SELECTED_WORD_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Bible', + ], + 'model' => [ + 'name' => 'model', + 'label' => 'COM_GETBIBLE_OPEN_AI_RESPONSE_MODEL_LABEL', + 'type' => 'list', + 'title' => false, + 'list' => 'open_ai_responses', + 'store' => NULL, + 'tab_name' => 'Prompt', + ], + ], + 'open_ai_message' => [ + 'role' => [ + 'name' => 'role', + 'label' => 'COM_GETBIBLE_OPEN_AI_MESSAGE_ROLE_LABEL', + 'type' => 'list', + 'title' => true, + 'list' => 'open_ai_messages', + 'store' => NULL, + 'tab_name' => 'Message', + ], + 'open_ai_response' => [ + 'name' => 'open_ai_response', + 'label' => 'COM_GETBIBLE_OPEN_AI_MESSAGE_OPEN_AI_RESPONSE_LABEL', + 'type' => 'openairesponses', + 'title' => false, + 'list' => 'open_ai_messages', + 'store' => NULL, + 'tab_name' => 'Message', + ], + 'prompt' => [ + 'name' => 'prompt', + 'label' => 'COM_GETBIBLE_OPEN_AI_MESSAGE_PROMPT_LABEL', + 'type' => 'prompts', + 'title' => false, + 'list' => 'open_ai_messages', + 'store' => NULL, + 'tab_name' => 'Message', + ], + 'source' => [ + 'name' => 'source', + 'label' => 'COM_GETBIBLE_OPEN_AI_MESSAGE_SOURCE_LABEL', + 'type' => 'radio', + 'title' => false, + 'list' => 'open_ai_messages', + 'store' => NULL, + 'tab_name' => 'Message', + ], + 'content' => [ + 'name' => 'content', + 'label' => 'COM_GETBIBLE_OPEN_AI_MESSAGE_CONTENT_LABEL', + 'type' => 'textarea', + 'title' => false, + 'list' => 'open_ai_messages', + 'store' => NULL, + 'tab_name' => 'Message', + ], + 'name' => [ + 'name' => 'name', + 'label' => 'COM_GETBIBLE_OPEN_AI_MESSAGE_NAME_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'open_ai_messages', + 'store' => NULL, + 'tab_name' => 'Message', + ], + 'index' => [ + 'name' => 'index', + 'label' => 'COM_GETBIBLE_OPEN_AI_MESSAGE_INDEX_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'open_ai_messages', + 'store' => NULL, + 'tab_name' => 'Message', + ], + ], + 'password' => [ + 'name' => [ + 'name' => 'name', + 'label' => 'COM_GETBIBLE_PASSWORD_NAME_LABEL', + 'type' => 'text', + 'title' => true, + 'list' => 'passwords', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'linker' => [ + 'name' => 'linker', + 'label' => 'COM_GETBIBLE_PASSWORD_LINKER_LABEL', + 'type' => 'linkers', + 'title' => false, + 'list' => 'passwords', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'guid' => [ + 'name' => 'guid', + 'label' => 'COM_GETBIBLE_PASSWORD_GUID_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'passwords', + 'store' => NULL, + 'tab_name' => 'publishing', + ], + 'password' => [ + 'name' => 'password', + 'label' => 'COM_GETBIBLE_PASSWORD_PASSWORD_LABEL', + 'type' => 'password', + 'title' => false, + 'list' => 'passwords', + 'store' => NULL, + 'tab_name' => 'Details', + ], + ], + 'tag' => [ + 'name' => [ + 'name' => 'name', + 'label' => 'COM_GETBIBLE_TAG_NAME_LABEL', + 'type' => 'text', + 'title' => true, + 'list' => 'tags', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'linker' => [ + 'name' => 'linker', + 'label' => 'COM_GETBIBLE_TAG_LINKER_LABEL', + 'type' => 'linkers', + 'title' => false, + 'list' => 'tags', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'access' => [ + 'name' => 'access', + 'label' => 'COM_GETBIBLE_TAG_ACCESS_LABEL', + 'type' => 'radio', + 'title' => false, + 'list' => 'tags', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'guid' => [ + 'name' => 'guid', + 'label' => 'COM_GETBIBLE_TAG_GUID_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'tags', + 'store' => NULL, + 'tab_name' => 'publishing', + ], + 'description' => [ + 'name' => 'description', + 'label' => 'COM_GETBIBLE_TAG_DESCRIPTION_LABEL', + 'type' => 'textarea', + 'title' => false, + 'list' => 'tags', + 'store' => NULL, + 'tab_name' => 'Details', + ], + ], + 'translation' => [ + 'translation' => [ + 'name' => 'translation', + 'label' => 'COM_GETBIBLE_TRANSLATION_TRANSLATION_LABEL', + 'type' => 'text', + 'title' => true, + 'list' => 'translations', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'abbreviation' => [ + 'name' => 'abbreviation', + 'label' => 'COM_GETBIBLE_TRANSLATION_ABBREVIATION_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'translations', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'language' => [ + 'name' => 'language', + 'label' => 'COM_GETBIBLE_TRANSLATION_LANGUAGE_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'translations', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'direction' => [ + 'name' => 'direction', + 'label' => 'COM_GETBIBLE_TRANSLATION_DIRECTION_LABEL', + 'type' => 'radio', + 'title' => false, + 'list' => 'translations', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'distribution_history' => [ + 'name' => 'distribution_history', + 'label' => 'COM_GETBIBLE_TRANSLATION_DISTRIBUTION_HISTORY_LABEL', + 'type' => 'subform', + 'title' => false, + 'list' => 'translations', + 'store' => 'json', + 'tab_name' => 'Details', + ], + 'distribution_about' => [ + 'name' => 'distribution_about', + 'label' => 'COM_GETBIBLE_TRANSLATION_DISTRIBUTION_ABOUT_LABEL', + 'type' => 'textarea', + 'title' => false, + 'list' => 'translations', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'distribution_license' => [ + 'name' => 'distribution_license', + 'label' => 'COM_GETBIBLE_TRANSLATION_DISTRIBUTION_LICENSE_LABEL', + 'type' => 'textarea', + 'title' => false, + 'list' => 'translations', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'distribution_source' => [ + 'name' => 'distribution_source', + 'label' => 'COM_GETBIBLE_TRANSLATION_DISTRIBUTION_SOURCE_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'translations', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'distribution_sourcetype' => [ + 'name' => 'distribution_sourcetype', + 'label' => 'COM_GETBIBLE_TRANSLATION_DISTRIBUTION_SOURCETYPE_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'translations', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'distribution_versification' => [ + 'name' => 'distribution_versification', + 'label' => 'COM_GETBIBLE_TRANSLATION_DISTRIBUTION_VERSIFICATION_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'translations', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'sha' => [ + 'name' => 'sha', + 'label' => 'COM_GETBIBLE_TRANSLATION_SHA_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'translations', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'encoding' => [ + 'name' => 'encoding', + 'label' => 'COM_GETBIBLE_TRANSLATION_ENCODING_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'translations', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'distribution_lcsh' => [ + 'name' => 'distribution_lcsh', + 'label' => 'COM_GETBIBLE_TRANSLATION_DISTRIBUTION_LCSH_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'translations', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'distribution_version_date' => [ + 'name' => 'distribution_version_date', + 'label' => 'COM_GETBIBLE_TRANSLATION_DISTRIBUTION_VERSION_DATE_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'translations', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'distribution_version' => [ + 'name' => 'distribution_version', + 'label' => 'COM_GETBIBLE_TRANSLATION_DISTRIBUTION_VERSION_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'translations', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'lang' => [ + 'name' => 'lang', + 'label' => 'COM_GETBIBLE_TRANSLATION_LANG_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'translations', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'distribution_abbreviation' => [ + 'name' => 'distribution_abbreviation', + 'label' => 'COM_GETBIBLE_TRANSLATION_DISTRIBUTION_ABBREVIATION_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'translations', + 'store' => NULL, + 'tab_name' => 'Details', + ], + ], + 'book' => [ + 'name' => [ + 'name' => 'name', + 'label' => 'COM_GETBIBLE_BOOK_NAME_LABEL', + 'type' => 'text', + 'title' => true, + 'list' => 'books', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'abbreviation' => [ + 'name' => 'abbreviation', + 'label' => 'COM_GETBIBLE_BOOK_ABBREVIATION_LABEL', + 'type' => 'translations', + 'title' => false, + 'list' => 'books', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'nr' => [ + 'name' => 'nr', + 'label' => 'COM_GETBIBLE_BOOK_NR_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'books', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'sha' => [ + 'name' => 'sha', + 'label' => 'COM_GETBIBLE_BOOK_SHA_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'books', + 'store' => NULL, + 'tab_name' => 'Details', + ], + ], + 'chapter' => [ + 'name' => [ + 'name' => 'name', + 'label' => 'COM_GETBIBLE_CHAPTER_NAME_LABEL', + 'type' => 'text', + 'title' => true, + 'list' => 'chapters', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'chapter' => [ + 'name' => 'chapter', + 'label' => 'COM_GETBIBLE_CHAPTER_CHAPTER_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'chapters', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'book_nr' => [ + 'name' => 'book_nr', + 'label' => 'COM_GETBIBLE_CHAPTER_BOOK_NR_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'chapters', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'abbreviation' => [ + 'name' => 'abbreviation', + 'label' => 'COM_GETBIBLE_CHAPTER_ABBREVIATION_LABEL', + 'type' => 'translations', + 'title' => false, + 'list' => 'chapters', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'sha' => [ + 'name' => 'sha', + 'label' => 'COM_GETBIBLE_CHAPTER_SHA_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'chapters', + 'store' => NULL, + 'tab_name' => 'Details', + ], + ], + 'verse' => [ + 'book_nr' => [ + 'name' => 'book_nr', + 'label' => 'COM_GETBIBLE_VERSE_BOOK_NR_LABEL', + 'type' => 'number', + 'title' => true, + 'list' => 'verses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'chapter' => [ + 'name' => 'chapter', + 'label' => 'COM_GETBIBLE_VERSE_CHAPTER_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'verses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'verse' => [ + 'name' => 'verse', + 'label' => 'COM_GETBIBLE_VERSE_VERSE_LABEL', + 'type' => 'number', + 'title' => false, + 'list' => 'verses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'abbreviation' => [ + 'name' => 'abbreviation', + 'label' => 'COM_GETBIBLE_VERSE_ABBREVIATION_LABEL', + 'type' => 'translations', + 'title' => false, + 'list' => 'verses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'text' => [ + 'name' => 'text', + 'label' => 'COM_GETBIBLE_VERSE_TEXT_LABEL', + 'type' => 'textarea', + 'title' => false, + 'list' => 'verses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + 'name' => [ + 'name' => 'name', + 'label' => 'COM_GETBIBLE_VERSE_NAME_LABEL', + 'type' => 'text', + 'title' => false, + 'list' => 'verses', + 'store' => NULL, + 'tab_name' => 'Details', + ], + ], + ]; +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Tag.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Tag.php new file mode 100644 index 0000000..b2fb49a --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Tag.php @@ -0,0 +1,209 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible; + + +use Joomla\CMS\Language\Text; +use VDM\Joomla\GetBible\Database\Load; +use VDM\Joomla\GetBible\Database\Insert; +use VDM\Joomla\GetBible\Database\Update; +use VDM\Joomla\GetBible\Linker; +use VDM\Joomla\Utilities\GuidHelper; + + +/** + * The GetBible Tag + * + * @since 2.0.1 + */ +final class Tag +{ + /** + * The Load class + * + * @var Load + * @since 2.0.1 + */ + protected Load $load; + + /** + * The Insert class + * + * @var Insert + * @since 2.0.1 + */ + protected Insert $insert; + + /** + * The Update class + * + * @var Update + * @since 2.0.1 + */ + protected Update $update; + + /** + * The Linker class + * + * @var Linker + * @since 2.0.1 + */ + protected Linker $linker; + + /** + * Constructor + * + * @param Load $load The load object. + * @param Insert $insert The insert object. + * @param Update $update The update object. + * @param Linker $linker The linker object. + * + * @since 2.0.1 + */ + public function __construct( + Load $load, + Insert $insert, + Update $update, + Linker $linker) + { + $this->load = $load; + $this->insert = $insert; + $this->update = $update; + $this->linker = $linker; + } + + /** + * Set a tag + * + * @param string $name The tag name being created + * + * @return array|null Array of the tag values on success + * @since 2.0.1 + **/ + public function set(string $name): ?array + { + // make sure the linker has access + if (($linker = $this->linker->get()) === null) + { + return [ + 'error' => Text::_("COM_GETBIBLE_WITHOUT_SELECTING_THE_CORRECT_FAVOURITE_VERSE_YOU_CANT_PERFORM_THE_INITIAL_ACTION"), + 'access_required' => true + ]; + } + + // get tag if it exist + if (($tag = $this->get($linker, $name)) !== null) + { + // publish if not published + if ($tag->published != 1 && !$this->update->value(1, 'published', $tag->id, 'id', 'tag')) + { + return [ + 'error' => Text::_('COM_GETBIBLE_TAG_ALREADY_EXIST_BUT_COULD_NOT_BE_REACTIVATED') + ]; + } + + $tag->published = 1; + $tag->success = Text::_('COM_GETBIBLE_THE_TAG_WAS_SUCCESSFULLY_SET'); + return (array) $tag; + } + // create a new tag + elseif ($this->create($linker, $name) + && ($tag = $this->get($linker, $name)) !== null) + { + $tag->success = Text::_('COM_GETBIBLE_THE_TAG_WAS_SUCCESSFULLY_SET'); + return (array) $tag; + } + + return null; + } + + /** + * Delete a tag + * + * @param string $tag The tagged verse GUID value + * + * @return bool True on success + * @since 2.0.1 + **/ + public function delete(string $tag): bool + { + // make sure the linker has access + if (($linker = $this->linker->get()) === null) + { + return false; + } + + // make sure the linker has access to delete this tag + if (($id = $this->load->value(['guid' => $tag, 'linker' => $linker], 'id', 'tag')) !== null && $id > 0) + { + return $this->update->value(-2, 'published', $id, 'id', 'tag'); + } + + return false; + } + + /** + * Get a tag + * + * @param string $linker The linker GUID value + * @param string $name The tag name + * + * @return array|null Array of the tagged verse values on success + * @since 2.0.1 + **/ + private function get( + string $linker, + string $name + ): ?array + { + // get tag if it exist + if (($tag = $this->load->item([ + 'linker' => $linker, + 'name' => $name + ], 'tag')) !== null) + { + return $tag; + } + + return null; + } + + /** + * Create a Tag + * + * @param string $linker The linker GUID value + * @param string $name The tag name + * + * @return bool True on success + * @since 2.0.1 + **/ + private function create( + string $linker, + string $name + ): bool + { + $guid = (string) GuidHelper::get(); + while (!GuidHelper::valid($guid, 'tag', 0, 'getbible')) + { + // must always be set + $guid = (string) GuidHelper::get(); + } + + return $this->insert->row([ + 'access' => 0, + 'linker' => $linker, + 'name' => $name, + 'guid' => $guid + ], 'tag'); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Tagged.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Tagged.php new file mode 100644 index 0000000..41f9deb --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Tagged.php @@ -0,0 +1,364 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible; + + +use Joomla\Registry\Registry; +use Joomla\CMS\Language\Text; +use Joomla\CMS\Application\CMSApplication; +use Joomla\CMS\Factory; +use VDM\Joomla\GetBible\Database\Load; +use VDM\Joomla\GetBible\Database\Insert; +use VDM\Joomla\GetBible\Database\Update; +use VDM\Joomla\GetBible\Linker; +use VDM\Joomla\Utilities\GuidHelper; +use VDM\Joomla\Utilities\Component\Helper; + + +/** + * The GetBible Tagged + * + * @since 2.0.1 + */ +final class Tagged +{ + /** + * The Load class + * + * @var Load + * @since 2.0.1 + */ + protected Load $load; + + /** + * The Insert class + * + * @var Insert + * @since 2.0.1 + */ + protected Insert $insert; + + /** + * The Update class + * + * @var Update + * @since 2.0.1 + */ + protected Update $update; + + /** + * The Linker class + * + * @var Linker + * @since 2.0.1 + */ + protected Linker $linker; + + /** + * The Registry class + * + * @var Registry + * @since 2.0.1 + */ + protected Registry $params; + + /** + * Application object. + * + * @var CMSApplication + * @since 3.2.0 + **/ + protected CMSApplication $app; + + /** + * Constructor + * + * @param Load $load The load object. + * @param Insert $insert The insert object. + * @param Update $update The update object. + * @param Linker $linker The linker object. + * @param Registry|null $params The params object. + * @param CMSApplication|null $app The app object. + * + * @since 2.0.1 + */ + public function __construct( + Load $load, + Insert $insert, + Update $update, + Linker $linker, + ?Registry $params = null, + ?CMSApplication $app = null) + { + $this->load = $load; + $this->insert = $insert; + $this->update = $update; + $this->linker = $linker; + $this->params = $params ?: Helper::getParams('com_getbible'); + $this->app = $app ?: Factory::getApplication(); + } + + /** + * Set a tagged verse + * + * @param string $translation The translation in which the note is made + * @param int $book The book in which the note is made + * @param int $chapter The chapter in which the note is made + * @param int $verse The verse where the note is made + * @param string $tag The tag being added + * + * @return array|null Array of the tagged values on success + * @since 2.0.1 + **/ + public function set( + string $translation, + int $book, + int $chapter, + int $verse, + string $tag + ): ?array + { + // make sure the linker has access + if (($linker = $this->linker->get()) === null) + { + return [ + 'error' => Text::_("COM_GETBIBLE_WITHOUT_SELECTING_THE_CORRECT_FAVOURITE_VERSE_YOU_CANT_PERFORM_THE_INITIAL_ACTION"), + 'access_required' => true + ]; + } + + // make sure the tag is active + if (($published = GuidHelper::item($tag, 'tag', 'a.published', 'getbible')) === null + || $published != 1) + { + return [ + 'error' => Text::_('COM_GETBIBLE_THE_TAG_SELECTED_IS_NOT_ACTIVE_PLEASE_SELECT_AN_ACTIVE_TAG') + ]; + } + + // get tagged verse if it exist + if (($tagged = $this->get($linker, $book, $chapter, $verse, $tag)) !== null) + { + // publish if not published + if ($tagged->published != 1 && !$this->update->value(1, 'published', $tagged->id, 'id', 'tagged_verse')) + { + return [ + 'error' => Text::_('COM_GETBIBLE_TAGGED_VERSE_ALREADY_EXIST_BUT_COULD_NOT_BE_REACTIVATED') + ]; + } + + $tagged->published = 1; + $tagged->success = Text::_('COM_GETBIBLE_THE_VERSE_WAS_SUCCESSFULLY_TAGGED'); + return (array) $tagged; + } + // create a new tagged verse + elseif ($this->create($linker, $translation, $book, $chapter, $verse, $tag) + && ($tagged = $this->get($linker, $book, $chapter, $verse, $tag)) !== null) + { + $tagged->success = Text::_('COM_GETBIBLE_THE_VERSE_WAS_SUCCESSFULLY_TAGGED'); + return (array) $tagged; + } + + return null; + } + + /** + * Delete a tagged verse + * + * @param string $tagged The tagged verse GUID value + * + * @return array|null True on success + * @since 2.0.1 + **/ + public function delete( + string $tagged + ): ?array + { + // make sure the linker has access + if (($linker = $this->linker->get()) === null) + { + return [ + 'error' => Text::_("COM_GETBIBLE_WITHOUT_SELECTING_THE_CORRECT_FAVOURITE_VERSE_YOU_CANT_PERFORM_THE_INITIAL_ACTION"), + 'access_required' => true + ]; + } + + // make sure the linker has access to delete this tag + if (($id = $this->load->value(['linker' => $linker, 'guid' => $tagged], 'id', 'tagged_verse')) !== null && $id > 0 + && $this->update->value(-2, 'published', $id, 'id', 'tagged_verse')) + { + return [ + 'success' => Text::_('COM_GETBIBLE_THE_TAG_WAS_SUCCESSFULLY_REMOVED_FROM_THE_VERSE') + ]; + } + + // lets check if this is a systems tag + if (($_tagged = $this->getByGuid($tagged)) !== null && $_tagged->access == 1) + { + if ($this->params->get('allow_untagging') == 1 + && $this->createForLinker($linker, $_tagged, -2)) + { + return [ + 'success' => Text::_('COM_GETBIBLE_THE_TAG_WAS_SUCCESSFULLY_REMOVED_FROM_THE_VERSE') + ]; + } + + return [ + 'notice' => Text::sprintf("COM_GETBIBLE_THIS_IS_A_GLOBAL_TAG_SET_BY_US_AT_BSB_FOR_YOUR_CONVENIENCE_WE_HOLD_THE_PRIVILEGE_TO_MODIFY_THESE_TAGS_IF_YOU_BELIEVE_ITS_SET_IN_ERROR_KINDLY_INFORM_US", $this->app->get('sitename')) + ]; + } + + return [ + 'error' => Text::_('COM_GETBIBLE_THIS_TAG_COULD_NOT_BE_REMOVED') + ]; + } + + /** + * Get a tagged verse + * + * @param string $guid The tagged verse GUID value + * + * @return object|null Object of the tagged verse values on success + * @since 2.0.1 + **/ + private function getByGuid(string $guid): ?object + { + // get tagged verse if it exist + if (($tagged = $this->load->item(['guid' => $guid], 'tagged_verse')) !== null) + { + return $tagged; + } + + return null; + } + + /** + * Get a tagged verse + * + * @param string $linker The linker GUID value + * @param int $book The book in which the note is made + * @param int $chapter The chapter in which the note is made + * @param int $verse The verse where the note is made + * @param string $tag The tag being added + * + * @return object|null Object of the tagged verse values on success + * @since 2.0.1 + **/ + private function get( + string $linker, + int $book, + int $chapter, + int $verse, + string $tag + ): ?object + { + // get tagged verse if it exist + if (($tagged = $this->load->item([ + 'linker' => $linker, + 'book_nr' => $book, + 'chapter' => $chapter, + 'verse' => $verse, + 'tag' => $tag + ], 'tagged_verse')) !== null) + { + $tagged->name = $this->load->value([ + 'guid' => $tag + ], 'name', 'tag'); + + $tagged->description = $this->load->value([ + 'guid' => $tag + ], 'description', 'tag'); + + return $tagged; + } + + return null; + } + + /** + * Create a Tagged verse + * + * @param string $linker The linker GUID value + * @param string $translation The translation in which the note is made + * @param int $book The book in which the note is made + * @param int $chapter The chapter in which the note is made + * @param int $verse The verse where the note is made + * @param string $tag The tag being added + * + * @return bool True on success + * @since 2.0.1 + **/ + private function create( + string $linker, + string $translation, + int $book, + int $chapter, + int $verse, + string $tag + ): bool + { + $guid = (string) GuidHelper::get(); + while (!GuidHelper::valid($guid, 'tagged_verse', 0, 'getbible')) + { + // must always be set + $guid = (string) GuidHelper::get(); + } + + return $this->insert->row([ + 'tag' => $tag, + 'access' => 0, + 'linker' => $linker, + 'abbreviation' => $translation, + 'book_nr' => $book, + 'chapter' => $chapter, + 'verse' => $verse, + 'guid' => $guid + ], 'tagged_verse'); + } + + /** + * Create a Tagged verse for a linker using a system tagged verse + * + * @param string $linker The linker GUID value + * @param object $tagged The system tagged verse + * @param int $published The new tagged verse state [default trashed = -2] + * + * @return bool True on success + * @since 2.0.1 + **/ + private function createForLinker( + string $linker, + object $tagged, + int $published = -2 + ): bool + { + $guid = (string) GuidHelper::get(); + while (!GuidHelper::valid($guid, 'tagged_verse', 0, 'getbible')) + { + // must always be set + $guid = (string) GuidHelper::get(); + } + + return $this->insert->row([ + 'tag' => $tagged->tag, + 'access' => 0, + 'linker' => $linker, + 'abbreviation' => $tagged->abbreviation, + 'book_nr' => $tagged->book_nr, + 'chapter' => $tagged->chapter, + 'verse' => $tagged->verse, + 'guid' => $guid, + 'published' => $published + ], 'tagged_verse'); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Tagged/Paragraphs.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Tagged/Paragraphs.php new file mode 100644 index 0000000..9b46749 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Tagged/Paragraphs.php @@ -0,0 +1,275 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Tagged; + + +use Joomla\CMS\Router\Route; + + +/** + * The GetBible Tagged Paragraphs + * + * @since 2.0.1 + */ +final class Paragraphs +{ + /** + * The Previous Book number + * + * @var int + * @since 2.0.1 + */ + private int $previousBook = 0; + + /** + * The Previous Chapter number + * + * @var int + * @since 2.0.1 + */ + private int $previousChapter = 0; + + /** + * The Previous Verse number + * + * @var int + * @since 2.0.1 + */ + private int $previousVerse = 0; + + /** + * The Current Group number + * + * @var int + * @since 2.0.1 + */ + private int $group = 0; + + /** + * The paragraphs being build + * + * @var array + * @since 2.0.1 + */ + private array $paragraphs = []; + + /** + * Main function to get sorted paragraphs. + * + * @param array $items The items to be sorted into paragraphs. + * @param string $translation The translation to be used. + * + * @return array The sorted paragraphs. + * @since 2.0.1 + */ + public function get(array $items, string $translation = 'kjv'): array + { + $this->resetProperties(); + + // sort the items by book, chapter, and verse + usort($items, function ($a, $b) { + if ($a->book_nr != $b->book_nr) { + return $a->book_nr - $b->book_nr; + } + if ($a->chapter != $b->chapter) { + return $a->chapter - $b->chapter; + } + return $a->verse - $b->verse; + }); + + $this->sortIntoParagraphs($items); + $this->setUrls($translation); + + return $this->paragraphs; + } + + /** + * Reset properties before getting paragraphs + * + * @return void + * @since 2.0.1 + */ + private function resetProperties(): void + { + $this->previousBook = 0; + $this->previousChapter = 0; + $this->previousVerse = 0; + $this->group = 0; + $this->paragraphs = []; + } + + /** + * Sort items into paragraphs. + * + * @param array $items The items to be sorted into paragraphs. + * + * @return void + * @since 2.0.1 + */ + private function sortIntoParagraphs($items): void + { + foreach ($items as $item) + { + if ($this->isNotSequential($item)) + { + $this->group++; + } + + $key = $this->getKey($item); + + if (empty($this->paragraphs[$key])) + { + $this->setDetails($item, $key); + } + + $this->addVerse($item, $key); + + $this->updatePrevious($item); + } + } + + /** + * Check if a verse is not sequential. + * + * @param object $item The verse to be checked. + * + * @return bool Whether the verse is not sequential. + * @since 2.0.1 + */ + private function isNotSequential(object $item): bool + { + return $this->previousVerse > 0 + && ((int) $item->book_nr > $this->previousBook + || (int) $item->chapter > $this->previousChapter + || (int) $item->verse > $this->previousVerse + 1); + } + + /** + * Generate a key based on the verse item. + * + * @param object $item The verse item. + * + * @return string The generated key. + * @since 2.0.1 + */ + private function getKey(object $item): string + { + return $item->book_nr . '_' . $item->chapter . '_' . $this->group; + } + + /** + * Set details for a verse. + * + * @param object $item The verse item. + * @param string $key The key for the paragraph. + * + * @return void + * @since 2.0.1 + */ + private function setDetails(object $item, string $key): void + { + $this->paragraphs[$key]['name'] = $item->name . ' ' . $item->chapter; + $this->paragraphs[$key]['book'] = $item->name; + $this->paragraphs[$key]['data_book'] = preg_replace('/[^\p{L}\p{N}\s]/u', '', $item->name); + $this->paragraphs[$key]['chapter'] = $item->chapter; + } + + /** + * Add a verse to the paragraphs. + * + * @param object $item The verse item. + * @param string $key The key for the paragraph. + * + * @return void + * @since 2.0.1 + */ + private function addVerse(object $item, string $key): void + { + $this->paragraphs[$key]['verses'][$item->verse] = ['number' => $item->verse, 'text' => $item->text]; + } + + /** + * Update the previous verse, book, and chapter to the current one. + * + * @param object $item The current verse item. + * + * @return void + * @since 2.0.1 + */ + private function updatePrevious(object $item): void + { + $this->previousVerse = (int) $item->verse; + $this->previousBook = (int) $item->book_nr; + $this->previousChapter = (int) $item->chapter; + } + + /** + * Set URLs for the paragraphs. + * + * @param string $translation The translation to be used. + * + * @return void + * @since 2.0.1 + */ + private function setUrls(string $translation): void + { + if ($this->paragraphs !== []) + { + foreach ($this->paragraphs as $chapter => &$paragraph) + { + $this->setVerseAndName($paragraph); + $this->setUrl($paragraph, $translation); + } + } + } + + /** + * Set verse and name for a paragraph. + * + * @param array $paragraph The paragraph to be updated. + * + * @return void + * @since 2.0.1 + */ + private function setVerseAndName(array &$paragraph): void + { + $verse = array_keys($paragraph['verses']); + $first = reset($verse); + $last = end($verse); + + if ($first == $last) + { + $paragraph['name'] .= ':' . $first; + $paragraph['verse'] = $first; + } + else + { + $paragraph['name'] .= ':' . $first . '-' . $last; + $paragraph['verse'] = $first . '-' . $last; + } + } + + /** + * Set URL for a paragraph. + * + * @param array $paragraph The paragraph to be updated. + * @param string $translation The translation to be used. + * + * @return void + * @since 2.0.1 + */ + private function setUrl(array &$paragraph, string $translation): void + { + $paragraph['url'] = Route::_('index.php?option=com_getbible&view=app&t=' . $translation . '&ref=' . $paragraph['book'] . '&chapter=' . $paragraph['chapter'] . '&verse=' . $paragraph['verse']); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Tagged/index.html b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Tagged/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Tagged/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/Http.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/Http.php new file mode 100644 index 0000000..52c3cd4 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/Http.php @@ -0,0 +1,48 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Utilities; + + +use Joomla\CMS\Http\Http as JoomlaHttp; +use Joomla\Registry\Registry; + + +/** + * The GetBible Http + * + * @since 2.0.1 + */ +final class Http extends JoomlaHttp +{ + /** + * Constructor. + * + * @since 2.0.1 + * @throws \InvalidArgumentException + **/ + public function __construct() + { + // setup config + $config = [ + 'userAgent' => 'JoomlaGetBible/2.0', + 'headers' => [ + 'Content-Type' => 'application/json' + ] + ]; + + $options = new Registry($config); + + // run parent constructor + parent::__construct($options); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/Response.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/Response.php new file mode 100644 index 0000000..4264c8a --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/Response.php @@ -0,0 +1,123 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Utilities; + + +use Joomla\CMS\Http\Response as JoomlaResponse; +use VDM\Joomla\Utilities\JsonHelper; +use VDM\Joomla\Utilities\StringHelper; + + +/** + * The GetBible Response + * + * @since 2.0.1 + */ +final class Response +{ + /** + * Process the response and decode it. + * + * @param JoomlaResponse $response The response. + * @param integer $expectedCode The expected "good" code. + * @param mixed $default The default if body not have length + * + * @return mixed + * + * @since 2.0.1 + * @throws \DomainException + **/ + public function get(JoomlaResponse $response, int $expectedCode = 200, $default = null) + { + // Validate the response code. + if ($response->code != $expectedCode) + { + // Decode the error response and throw an exception. + $message = $this->error($response); + + // Throw an exception with the GetBible error message and code. + throw new \DomainException($message, $response->code); + } + + return $this->getBody($response, $default); + } + + /** + * Return the body from the response + * + * @param JoomlaResponse $response The response. + * @param mixed $default The default if body not have length + * + * @return mixed + * @since 2.0.1 + **/ + protected function getBody(JoomlaResponse $response, $default = null) + { + // check that we have a body + if (isset($response->body) && StringHelper::check($response->body)) + { + // if it's JSON, decode it + if (JsonHelper::check($response->body)) + { + return json_decode((string) $response->body); + } + + // if it's XML, convert it to an object + libxml_use_internal_errors(true); + $xml = simplexml_load_string($response->body); + if ($xml !== false) + { + return $xml; + } + + // if it's neither JSON nor XML, return as is + return $response->body; + } + + return $default; + } + + /** + * Get the error message from the GetBible API response + * + * @param JoomlaResponse $response The response. + * + * @return string + * @since 2.0.1 + **/ + protected function error(JoomlaResponse $response): string + { + // do we have a json string + if (isset($response->body) && JsonHelper::check($response->body)) + { + $error = json_decode($response->body); + } + else + { + return 'Invalid or empty response body.'; + } + + // check if GetBible returned an error object + if (isset($error->Error)) + { + // error object found, extract message and code + $errorMessage = isset($error->Error->Message) ? $error->Error->Message : 'Unknown error.'; + $errorCode = isset($error->Error->Code) ? $error->Error->Code : 'Unknown error code.'; + + // return formatted error message + return 'Wasabi Error: ' . $errorMessage . ' Code: ' . $errorCode; + } + + return 'No error information found in response.'; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/SessionHelper.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/SessionHelper.php new file mode 100644 index 0000000..cf010ee --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/SessionHelper.php @@ -0,0 +1,76 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Utilities; + + +use Joomla\CMS\Factory as JoomlaFactory; +use Joomla\CMS\Session\Session; +use VDM\Joomla\Utilities\GuidHelper; + + +/** + * The GetBible Session Helper + * - Just for easy set and get + * + * @since 2.0.1 + */ +final class SessionHelper +{ + /** + * The Session + * + * @var Session + * @since 3.2.0 + */ + protected Session $session; + + /** + * Constructor + * + * @param Session|null $session The Joomla session. + * + * @since 3.2.0 + */ + public function __construct(?Session $session = null) + { + $this->session = $session ?: JoomlaFactory::getSession(); + } + + /** + * Get data from the session store + * + * @param string $name Name of a variable + * @param mixed $default Default value of a variable if not set + * + * @return mixed Value of a variable + * @since 2.1.0 + */ + public function get(string $name, $default = null) + { + return $this->session->get($name, $default); + } + + /** + * Set data into the session store. + * + * @param string $name Name of a variable. + * @param mixed $value Value of a variable. + * + * @return mixed Old value of a variable. + * @since 2.1.0 + */ + public function set($name, $value = null) + { + return $this->session->set($name, $value); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/StringHelper.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/StringHelper.php new file mode 100644 index 0000000..faad516 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/StringHelper.php @@ -0,0 +1,120 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Utilities; + + +/** + * The GetBible String Helper + * + * @since 2.0.1 + */ +final class StringHelper +{ + /** + * Return an array of words + * + * @param string $text The actual sentence + * + * @return array An array of words + */ + public function split(string $text): array + { + if ($this->isCJK($text)) + { + // Split by characters for languages that don't use spaces + $words = (array) preg_split('//u', $text, -1, PREG_SPLIT_NO_EMPTY); + } + elseif (strpos($text, ' ') !== false) + { + // Split by spaces for languages that use them + $words = (array) preg_split('/(\s+)/u', $text, -1, PREG_SPLIT_DELIM_CAPTURE); + } + else + { + $words = [$text]; + } + + return $words; + } + + /** + * Return an array of only words + * + * @param string $text The actual sentence + * @param bool $punctuation Switch to keep or remove punctuation + * + * @return array An array of words + */ + public function splitToWords(string $text, bool $punctuation = true): array + { + $words = array_filter($this->split($text), function($word) { + $plain_word = preg_replace('/[^\p{L}\p{N}\s]/u', '', $word); + if ($this->hasLength($plain_word)) { + return true; + } return false; + }); + + if ($words === []) + { + return $words; + } + + // remove punctuation + if (!$punctuation) + { + $words = array_map(function($word) { + return preg_replace('/[^\p{L}\p{N}\s]/u', '', $word); + }, $words); + } + + // make the array 1 based + // so that the key 1 is the first word + array_unshift($words, null); + unset($words[0]); + + return $words; + } + + /** + * Checks if a string contains characters typically used in East Asian languages (Chinese, Japanese, Korean) + * These languages do not typically use word boundaries in the same way as languages written in Latin script + * + * @param string $text The string to be checked for CJK characters + * + * @return bool True if the string contains at least one CJK character, false otherwise + */ + public function isCJK(string $text): bool + { + if (preg_match('/[\x{4E00}-\x{9FFF}\x{3040}-\x{309F}\x{30A0}-\x{30FF}\x{AC00}-\x{D7AF}]/u', $text)) + { + return true; + } + return false; + } + + /** + * Make sure a string has a length + * + * @param string $word The actual string to check + * + * @return bool True if its a string with characters. + */ + public function hasLength(string $word): bool + { + // Trim the string + $trimmed = trim($word); + + // Return true if the trimmed string is not empty, false otherwise + return !empty($trimmed); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/Uri.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/Uri.php new file mode 100644 index 0000000..094555e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/Uri.php @@ -0,0 +1,63 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible\Utilities; + + +use Joomla\Uri\Uri as JoomlaUri; +use VDM\Joomla\GetBible\Config; + + +/** + * The GetBible Uri + * + * @since 2.0.1 + */ +final class Uri +{ + /** + * The Config class + * + * @var Config + * @since 2.0.1 + */ + protected Config $config; + + /** + * Constructor + * + * @param Config $config The config class. + * + * @since 2.0.1 + **/ + public function __construct(Config $config) + { + // set the API config + $this->config = $config; + } + + /** + * Method to build and return a full request URL for the request. + * + * @param string $path URL to inflect + * + * @return JoomlaUri + * @since 2.0.1 + **/ + public function get(string $path): JoomlaUri + { + // Get a new Uri object focusing the api url and given path. + $uri = new JoomlaUri($this->config->endpoint . $path); + + return $uri; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/index.html b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Utilities/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/Watcher.php b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Watcher.php new file mode 100644 index 0000000..4c65a1b --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/Watcher.php @@ -0,0 +1,693 @@ + + * @git GetBible + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\GetBible; + + +use Joomla\CMS\Date\Date; +use VDM\Joomla\GetBible\Database\Load; +use VDM\Joomla\GetBible\Database\Insert; +use VDM\Joomla\GetBible\Database\Update; +use VDM\Joomla\GetBible\Api\Translations; +use VDM\Joomla\GetBible\Api\Books; +use VDM\Joomla\GetBible\Api\Chapters; +use VDM\Joomla\GetBible\Api\Verses; + + +/** + * The GetBible Watcher + * + * @since 2.0.1 + */ +final class Watcher +{ + /** + * The Load class + * + * @var Load + * @since 2.0.1 + */ + protected Load $load; + + /** + * The Insert class + * + * @var Insert + * @since 2.0.1 + */ + protected Insert $insert; + + /** + * The Update class + * + * @var Update + * @since 2.0.1 + */ + protected Update $update; + + /** + * The Translations class + * + * @var Translations + * @since 2.0.1 + */ + protected Translations $translations; + + /** + * The Books class + * + * @var Books + * @since 2.0.1 + */ + protected Books $books; + + /** + * The Chapters class + * + * @var Chapters + * @since 2.0.1 + */ + protected Chapters $chapters; + + /** + * The Verses class + * + * @var Verses + * @since 2.0.1 + */ + protected Verses $verses; + + /** + * The fresh load switch + * + * @var bool + * @since 2.0.1 + */ + protected bool $fresh = false; + + /** + * The sql date of today + * + * @var string + * @since 2.0.1 + */ + protected string $today; + + /** + * The target verse + * + * @var object|null + * @since 2.0.1 + */ + protected ?object $verse; + + /** + * Constructor + * + * @param Load $load The load object. + * @param Insert $insert The insert object. + * @param Update $update The update object. + * @param Translations $translations The translations API object. + * @param Books $books The books API object. + * @param Chapters $chapters The chapters API object. + * @param Verses $verses The verses API object. + * + * @since 2.0.1 + */ + public function __construct( + Load $load, + Insert $insert, + Update $update, + Translations $translations, + Books $books, + Chapters $chapters, + Verses $verses) + { + $this->load = $load; + $this->insert = $insert; + $this->update = $update; + $this->translations = $translations; + $this->books = $books; + $this->chapters = $chapters; + $this->verses = $verses; + + // just in-case we set a date + $this->today = (new Date())->toSql(); + } + + /** + * The see if new chapters was installed, and therefore new + * + * @return bool true if is new + * @since 2.0.1 + */ + public function isNew(): bool + { + return $this->fresh; + } + + /** + * Check if a translation has enough verses + * + * @param string $translation The translation. + * + * @return bool + * @since 2.0.1 + */ + public function enoughVerses(string $translation = 'kjv'): bool + { + $total = $this->totalVerses($translation); + + if ($total < 10000) + { + return false; + } + + return true; + } + + /** + * Get the total number of verses in the database of a given translation + * + * @param string $translation The translation. + * + * @return int|null + * @since 2.0.1 + */ + public function totalVerses(string $translation = 'kjv'): ?int + { + return $this->load->count( + ['abbreviation' => $translation], 'verse' + ); + } + + /** + * Watching that the local Database and API is in sync + * + * @param string $translation The translation. + * @param int $book The book number. + * @param int $chapter The chapter number. + * + * @return bool True on success + * @since 2.0.1 + */ + public function api(string $translation, int $book, int $chapter): bool + { + // does the translation exist + if ($this->translation($translation) === null) + { + return false; + } + + // does the book exist + if ($this->book($translation, $book) === null) + { + return false; + } + + // does the chapter exist, and get hash value + if (($hash = $this->chapter($translation, $book, $chapter)) === null) + { + return false; + } + + // load the verses if not found + if ($this->verses($translation, $book, $chapter)) + { + if ($this->isNew() || $this->hold()) + { + return true; + } + + // get API chapter hash value + $api_hash = $this->chapters->sha($translation, $book, $chapter); + + // confirm chapter hash has not changed + if (hash_equals($hash, $api_hash)) + { + return $this->bump(); + } + + if ($this->update($translation, $book, $chapter)) + { + // now update the hash of this chapter + return $this->updateHash($translation, $book, $chapter, $api_hash); + } + } + + return false; + } + + /** + * Get the next chapter + * + * @param string $translation The translation. + * @param int $book The book number. + * @param int $chapter The chapter number. + * @param bool $force The switch to force the getting. + * + * @return int|null Number if there is a next, else null + * @since 2.0.1 + */ + public function getNextChapter(string $translation, int $book, int $chapter, bool $force = false): ?int + { + // we load the next chapter + $next = $chapter + 1; + // check if this books has this next chapter + if (($force || !$this->isNew()) && $this->load->value( + ['abbreviation' => $translation, 'book_nr' => $book, 'chapter' => $next], + 'sha', 'chapter' + )) + { + return $next; + } + + return null; + } + + /** + * Get the previous chapter + * + * @param int $chapter The chapter number. + * @param bool $force The switch to force the getting. + * + * @return int|null Number if there is a previous, else null + * @since 2.0.1 + */ + public function getPreviousChapter(int $chapter, bool $force = false): ?int + { + // we load the previous chapter + $previous = $chapter - 1; + if (($force || !$this->isNew()) && $previous > 0) + { + return $previous; + } + + return null; + } + + /** + * Get the last chapter of a book + * + * @param string $translation The translation. + * @param int $book The book number. + * + * @return int|null Number if there is a previous, else null + * @since 2.0.1 + */ + public function getLastChapter(string $translation, int $book): ?int + { + // we load the last chapter + return $this->load->max( + ['abbreviation' => $translation, 'book_nr' => $book], + 'chapter', 'chapter' + ); + } + + /** + * Get the next book + * + * @param string $translation The translation. + * @param int $book The book number. + * @param int $try The number of tries + * + * @return int|null Number if there is a next, else null + * @since 2.0.1 + */ + public function getNextBook(string $translation, int $book, int $try = 0): ?int + { + // we load the next chapter + $next = $book + 1; + + // if we already looked over 90 + if ($next >= 90) + { + $next = 1; + } + + // check if this book exist + if ($this->load->value( + ['abbreviation' => $translation, 'nr' => $next], + 'sha', 'book' + )) + { + return $next; + } + + $try++; + + // could not be found :( + if ($try >= 180) + { + return null; + } + + return $this->getNextBook($translation, $next, $try); + } + + /** + * Get the previous book + * + * @param string $translation The translation. + * @param int $book The book number. + * @param int $try The number of tries + * + * @return int|null Number if there is a previous, else null + * @since 2.0.1 + */ + public function getPreviousBook(string $translation, int $book, int $try = 0): ?int + { + // we load the previous book + $previous = $book - 1; + + // if we already looked over 90 + if ($previous <= 0) + { + $previous = 90; + } + + // check if this book exist + if ($this->load->value( + ['abbreviation' => $translation, 'nr' => $previous], + 'sha', 'book' + )) + { + return $previous; + } + + $try++; + + // could not be found :( + if ($try >= 180) + { + return null; + } + + return $this->getPreviousBook($translation, $previous, $try); + } + + /** + * Get Translation Hash Value + * + * @param string $translation The translation. + * + * @return string|null The sha of the translation + * @since 2.0.1 + */ + private function translation(string $translation): ?string + { + // check local value + if (($translation_sha = $this->load->value(['abbreviation' => $translation], 'sha', 'translation')) !== null) + { + return $translation_sha; + } + + // get all the translations + $translations = $this->translations->list(); + + // check return data + if (!isset($translations->{$translation}) || !isset($translations->{$translation}->sha)) + { + return null; + } + + // add them to the database + $this->insert->items((array) $translations, 'translation'); + + return $translations->{$translation}->sha; + } + + /** + * Get Book Hash Value + * + * @param string $translation The translation. + * @param int $book The book number. + * + * @return string|null The sha of the book + * @since 2.0.1 + */ + private function book(string $translation, int $book): ?string + { + // check local value + if (($book_sha = $this->load->value(['abbreviation' => $translation, 'nr' => $book], 'sha', 'book')) !== null) + { + return $book_sha; + } + + // get all the books + $books = $this->books->list($translation); + + // check return data + if (!isset($books->{$book}) || !isset($books->{$book}->sha)) + { + return null; + } + + // add them to the database + $this->insert->items((array) $books, 'book'); + + return $books->{$book}->sha; + } + + /** + * Get Chapter Hash Value + * + * @param string $translation The translation. + * @param int $book The book number. + * @param int $chapter The chapter number. + * + * @return string|null The sha of the chapter + * @since 2.0.1 + */ + private function chapter(string $translation, int $book, int $chapter): ?string + { + // check local value + if (($chapter_sha = $this->load->value( + ['abbreviation' => $translation, 'book_nr' => $book, 'chapter' => $chapter], + 'sha', 'chapter' + )) !== null) + { + return $chapter_sha; + } + + // get all the books + $chapters = $this->chapters->list($translation, $book); + + // check return data + if (!isset($chapters->{$chapter}) || !isset($chapters->{$chapter}->sha)) + { + return null; + } + + // add them to the database + $this->insert->items((array) $chapters, 'chapter'); + + return $chapters->{$chapter}->sha; + } + + /** + * Load verses if not in local database + * + * @param string $translation The translation. + * @param int $book The book number. + * @param int $chapter The chapter number. + * + * @return bool True if in local database + * @since 2.0.1 + */ + private function verses(string $translation, int $book, int $chapter): bool + { + // check local value + if (($this->verse = $this->load->item( + ['abbreviation' => $translation, 'book_nr' => $book, 'chapter' => $chapter, 'verse' => 1], + 'verse' + )) !== null) + { + return true; + } + + // get all the verses + if (($verses = $this->verses->get($translation, $book, $chapter)) === null) + { + return false; + } + + // dynamic update all verse objects + $insert = ['book_nr' => $book, 'abbreviation' => $translation]; + array_walk($verses->verses, function ($item, $key) use ($insert) { + foreach ($insert as $k => $v) { $item->$k = $v; } + }); + + $this->fresh = true; + + // add them to the database + return $this->insert->items((array) $verses->verses, 'verse'); + } + + /** + * Trigger the update of the verses of a translation-book-chapter + * + * @param string $translation The translation. + * @param int $book The book number. + * @param int $chapter The chapter number. + * + * @return bool True if update was a success + * @since 2.0.1 + */ + private function update(string $translation, int $book, int $chapter): bool + { + // load all the verses from the local database + if (($verses = $this->load->items( + ['abbreviation' => $translation, 'book_nr' => $book, 'chapter' => $chapter], + 'verse' + )) !== null) + { + // get verses from the API + if (($api = $this->verses->get($translation, $book, $chapter)) === null) + { + return false; + } + + $update = []; + $insert = []; + + // dynamic update all verse objects + foreach ($api->verses as $verse) + { + // check if the verse exist + if (($object = $this->getVerse((int) $verse->verse, $verses)) !== null) + { + $verse->id = $object->id; + $verse->created = $this->today; + $update[] = $verse; + } + else + { + $insert[] = $verse; + } + } + + // check if we have values to insert + if ($insert !== []) + { + $this->insert->items($insert, 'verse'); + } + + // update the local verses + if ($update !== [] && $this->update->items($update, 'id', 'verse')) + { + return true; + } + } + + return false; + } + + /** + * Get a verse text from the API array of verses + * + * @param int $number The verse number. + * @param array $verses The api verses + * + * @return object|null The verse string + * @since 2.0.1 + */ + private function getVerse(int $number, array &$verses): ?object + { + foreach ($verses as $verse) + { + if ($verse->verse === $number) + { + return $verse; + } + } + + return null; + } + + /** + * Trigger the update of a chapter hash value + * + * @param string $translation The translation. + * @param int $book The book number. + * @param int $chapter The chapter number. + * @param string $hash The API chapter hash value. + * + * @return bool True if update was a success + * @since 2.0.1 + */ + private function updateHash(string $translation, int $book, int $chapter, string $hash): bool + { + // load the chapter + if (($item = $this->load->item( + ['abbreviation' => $translation, 'book_nr' => $book, 'chapter' => $chapter], + 'chapter' + )) !== null) + { + $update = []; + $update['id'] = $item->id; + $update['sha'] = $hash; + $update['created'] = $this->today; + + // update the local chapter + return $this->update->row($update, 'id', 'chapter'); + } + + return false; + } + + /** + * Check if its time to match the API hash + * + * @return bool false if its time to check for an update + * @since 2.0.1 + */ + private function hold(): bool + { + // Create DateTime objects from the strings + try { + $today = new \DateTime($this->today); + $created = new \DateTime($this->verse->created); + } catch (\Exception $e) { + return false; + } + + // Calculate the difference + $interval = $today->diff($created); + + // Check if the interval is more than 1 month + if ($interval->m >= 1 || $interval->y >= 1) + { + return false; // More than a month, it's time to check for an update + } + else + { + return true; // Within the last month, hold off on the update check + } + } + + /** + * Bump the checking time + * + * @return bool true when the update was a success + * @since 2.0.1 + */ + private function bump(): bool + { + $update = []; + $update['id'] = $this->verse->id; + $update['created'] = $this->today; + + // update the local verse + return $this->update->row($update, 'id', 'verse'); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.GetBible/src/index.html b/libraries/jcb_powers/VDM.Joomla.GetBible/src/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.GetBible/src/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/index.html b/libraries/jcb_powers/VDM.Joomla.Gitea/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Abstraction/Api.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Abstraction/Api.php new file mode 100644 index 0000000..7f76657 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Abstraction/Api.php @@ -0,0 +1,83 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Abstraction; + + +use VDM\Joomla\Gitea\Utilities\Http; +use VDM\Joomla\Gitea\Utilities\Uri; +use VDM\Joomla\Gitea\Utilities\Response; + + +/** + * The Gitea Api + * + * @since 3.2.0 + */ +abstract class Api +{ + /** + * The Http class + * + * @var Http + * @since 3.2.0 + */ + protected Http $http; + + /** + * The Uri class + * + * @var Uri + * @since 3.2.0 + */ + protected Uri $uri; + + /** + * The Response class + * + * @var Response + * @since 3.2.0 + */ + protected Response $response; + + /** + * Constructor. + * + * @param Http $http The http class. + * @param Uri $uri The uri class. + * @param Response $response The response class. + * + * @since 3.2.0 + **/ + public function __construct(Http $http, Uri $uri, Response $response) + { + $this->http = $http; + $this->uri = $uri; + $this->response = $response; + } + + /** + * Load/Reload API. + * + * @param string $url The url. + * @param token $token The token. + * + * @return void + * @since 3.2.0 + **/ + public function load_(string $url, string $token) + { + $this->uri->setUrl($url); + $this->http->setToken($token); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Abstraction/index.html b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Abstraction/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Abstraction/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Cron.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Cron.php new file mode 100644 index 0000000..04031c2 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Cron.php @@ -0,0 +1,72 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Admin; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Admin Cron + * + * @since 3.2.0 + */ +class Cron extends Api +{ + /** + * List cron tasks. + * + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list(int $page = 1, int $limit = 10): ?array + { + // Build the request path. + $path = "/admin/cron"; + + // Set the query parameters. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Run cron task. + * + * @param string $task The cron task to run. + * + * @return string + * @since 3.2.0 + **/ + public function run(string $task): string + { + // Build the request path. + $path = "/admin/cron/{$task}"; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Organizations.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Organizations.php new file mode 100644 index 0000000..df1e6b4 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Organizations.php @@ -0,0 +1,51 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Admin; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Admin Organizations + * + * @since 3.2.0 + */ +class Organizations extends Api +{ + /** + * List all organizations. + * + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list(int $page = 1, int $limit = 10): ?array + { + // Build the request path. + $path = "/admin/orgs"; + + // Set the query parameters. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Unadopted.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Unadopted.php new file mode 100644 index 0000000..c73cf3e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Unadopted.php @@ -0,0 +1,101 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Admin; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Admin Unadopted + * + * @since 3.2.0 + */ +class Unadopted extends Api +{ + /** + * List unadopted repositories. + * + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * @param string $pattern Pattern of repositories to search for. + * + * @return array|null + * @since 3.2.0 + **/ + public function list(int $page = 1, int $limit = 10, string $pattern = ''): ?array + { + // Build the request path. + $path = "/admin/unadopted"; + + // Set the query parameters. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + if (!empty($pattern)) + { + $uri->setVar('pattern', $pattern); + } + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Adopt unadopted files as a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * + * @return string + * @since 3.2.0 + **/ + public function adopt(string $owner, string $repo): string + { + // Build the request path. + $path = "/admin/unadopted/{$owner}/{$repo}"; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), '' + ), 204, 'success' + ); + } + + /** + * Delete unadopted files. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * + * @return string + * @since 3.2.0 + **/ + public function delete(string $owner, string $repo): string + { + // Build the request path. + $path = "/admin/unadopted/{$owner}/{$repo}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Users.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Users.php new file mode 100644 index 0000000..47ec3e5 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Users.php @@ -0,0 +1,207 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Admin; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Admin Users + * + * @since 3.2.0 + */ +class Users extends Api +{ + /** + * List all users. + * + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list(int $page = 1, int $limit = 10): ?array + { + // Build the request path. + $path = "/admin/users"; + + // build the URL + $url = $this->uri->get($path); + $url->setVar('page', $page); + $url->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($url) + ); + } + + /** + * Create a user with extended options. + * + * @param string $loginName The user's login name. + * @param string $email The user's email address. + * @param string $password The user's password. + * @param string|null $username The username. + * @param string|null $fullName The user's full name (optional). + * @param bool|null $mustChangePassword User must change password on next login (optional). + * @param bool|null $restricted Restrict the user (optional). + * @param bool|null $sendNotify Send a notification email to the user (optional). + * @param int|null $sourceId Source ID (optional). + * @param string|null $visibility The user's visibility (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $loginName, + string $email, + string $password, + string $username, + ?string $fullName = null, + ?bool $mustChangePassword = null, + ?bool $restricted = null, + ?bool $sendNotify = null, + ?int $sourceId = null, + ?string $visibility = null + ): ?object + { + // Build the request path. + $path = "/admin/users"; + + // Set the user data. + $data = new \stdClass(); + $data->login_name = $loginName; + $data->email = $email; + $data->password = $password; + $data->username = $username; + $data->full_name = $fullName; + $data->must_change_password = $mustChangePassword; + $data->restricted = $restricted; + $data->send_notify = $sendNotify; + $data->source_id = $sourceId; + $data->visibility = $visibility; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ), 201 + ); + } + + /** + * Delete a user. + * + * @param string $username The user's display name. + * + * @return string + * @since 3.2.0 + **/ + public function delete(string $username): string + { + // Build the request path. + $path = "/admin/users/{$username}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * Edit an existing user. + * + * @param string $username The user's display name. + * @param string $loginName The user's login name. + * @param int $sourceId The user's source ID. + * @param bool $active Optional. Is the user active? Default: false. + * @param bool $admin Optional. Is the user an admin? Default: false. + * @param bool $allowCreateOrganization Optional. Can the user create an organization? Default: false. + * @param bool $allowGitHook Optional. Can the user create Git hooks? Default: false. + * @param bool $allowImportLocal Optional. Can the user import local repositories? Default: false. + * @param string $description Optional. The user's description. Default: ''. + * @param string $email Optional. The user's email address. Default: ''. + * @param string $fullName Optional. The user's full name. Default: ''. + * @param string $location Optional. The user's location. Default: ''. + * @param int $maxRepoCreation Optional. Maximum repositories the user can create. Default: 0. + * @param bool $mustChangePassword Optional. Must the user change their password? Default: false. + * @param string $password Optional. The user's password. Default: ''. + * @param bool $prohibitLogin Optional. Is the user's login prohibited? Default: false. + * @param bool $restricted Optional. Is the user restricted? Default: false. + * @param string $visibility Optional. The user's visibility setting. Default: ''. + * @param string $website Optional. The user's website. Default: ''. + * + * @return object|null + * @since 3.2.0 + **/ + public function edit( + string $username, + string $loginName, + int $sourceId, + bool $active = false, + bool $admin = false, + bool $allowCreateOrganization = false, + bool $allowGitHook = false, + bool $allowImportLocal = false, + string $description = '', + string $email = '', + string $fullName = '', + string $location = '', + int $maxRepoCreation = 0, + bool $mustChangePassword = false, + string $password = '', + bool $prohibitLogin = false, + bool $restricted = false, + string $visibility = '', + string $website = '' + ): ?object + { + // Build the request path. + $path = "/admin/users/{$username}"; + + // Set the data. + $data = [ + 'login_name' => $loginName, + 'source_id' => $sourceId, + 'active' => $active, + 'admin' => $admin, + 'allow_create_organization' => $allowCreateOrganization, + 'allow_git_hook' => $allowGitHook, + 'allow_import_local' => $allowImportLocal, + 'description' => $description, + 'email' => $email, + 'full_name' => $fullName, + 'location' => $location, + 'max_repo_creation' => $maxRepoCreation, + 'must_change_password' => $mustChangePassword, + 'password' => $password, + 'prohibit_login' => $prohibitLogin, + 'restricted' => $restricted, + 'visibility' => $visibility, + 'website' => $website + ]; + + // Send the patch request. + return $this->response->get( + $this->http->patch( + $this->uri->get($path), json_encode($data) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Users/Keys.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Users/Keys.php new file mode 100644 index 0000000..bea01de --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Users/Keys.php @@ -0,0 +1,86 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Admin\Users; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Admin Users Keys + * + * @since 3.2.0 + */ +class Keys extends Api +{ + /** + * Add a public key on behalf of a user. + * + * @param string $userName The user's display name. + * @param string $publicKey The public key to add. + * @param string $keyTitle Title of the key to add. + * @param bool $readOnly Whether the key has only read access or read/write (optional). + * @param string|null $description Description of the key (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function add( + string $userName, + string $publicKey, + string $keyTitle, + bool $readOnly = false, + ?string $description = null + ): ?object + { + // Build the request path. + $path = "/admin/users/{$userName}/keys"; + + // Set the key data. + $data = new \stdClass(); + $data->key = $publicKey; + $data->title = $keyTitle; + $data->read_only = $readOnly; + $data->description = $description; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ), 201 + ); + } + + /** + * Delete a user's public key. + * + * @param string $username The user's display name. + * @param int $id The public key ID. + * + * @return string + * @since 3.2.0 + **/ + public function delete(string $username, int $id): string + { + // Build the request path. + $path = "/admin/users/{$username}/keys/{$id}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Users/Organization.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Users/Organization.php new file mode 100644 index 0000000..ec1843f --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Users/Organization.php @@ -0,0 +1,70 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Admin\Users; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Admin Users Organization + * + * @since 3.2.0 + */ +class Organization extends Api +{ + /** + * Create an organization on behalf of a user. + * + * @param string $username The user's display name. + * @param string $fullName The organization full name. + * @param string|null $description The organization description (optional). + * @param string|null $location The organization location (optional). + * @param bool $repoAdminChangeTeamAccess Whether repo admin can change team access (optional). + * @param string $visibility The organization visibility (optional). + * @param string|null $website The organization website (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $username, + string $fullName, + ?string $description = null, + ?string $location = null, + bool $repoAdminChangeTeamAccess = false, + string $visibility = 'public', + ?string $website = null + ): ?object + { + // Build the request path. + $path = "/admin/users/{$username}/orgs"; + + // Set the organization data. + $data = new \stdClass(); + $data->full_name = $fullName; + $data->description = $description; + $data->location = $location; + $data->repo_admin_change_team_access = $repoAdminChangeTeamAccess; + $data->visibility = $visibility; + $data->website = $website; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ), 201 + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Users/Repository.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Users/Repository.php new file mode 100644 index 0000000..bfade26 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Users/Repository.php @@ -0,0 +1,85 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Admin\Users; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Admin Users Repository + * + * @since 3.2.0 + */ +class Repository extends Api +{ + /** + * Create a repository on behalf of a user. + * + * @param string $username The user's display name. + * @param string $repoName The repository name. + * @param string|null $description The repository description (optional). + * @param bool $auto_init Whether the repository should be auto-initialized? (optional). + * @param string|null $default_branch Default branch of the repository (optional). + * @param string|null $gitignores Gitignores to use (optional). + * @param string|null $issue_labels Label-Set to use (optional). + * @param string|null $license License to use (optional). + * @param bool $private Whether the repository is private (optional). + * @param string|null $readme Readme of the repository to create (optional). + * @param bool $template Whether the repository is template (optional). + * @param string|null $trust_model TrustModel of the repository (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $username, + string $repoName, + ?string $description = null, + bool $auto_init = false, + ?string $default_branch = null, + ?string $gitignores = null, + ?string $issue_labels = null, + ?string $license = null, + bool $private = false, + ?string $readme = null, + bool $template = false, + ?string $trust_model = null + ): ?object + { + // Build the request path. + $path = "/admin/users/{$username}/repos"; + + // Set the repository data. + $data = new \stdClass(); + $data->name = $repoName; + $data->description = $description; + $data->auto_init = $auto_init; + $data->default_branch = $default_branch; + $data->gitignores = $gitignores; + $data->issue_labels = $issue_labels; + $data->license = $license; + $data->private = $private; + $data->readme = $readme; + $data->template = $template; + $data->trust_model = $trust_model; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ), 201 + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Users/index.html b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Users/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/Users/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/index.html b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Admin/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Factory.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Factory.php new file mode 100644 index 0000000..78918e8 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Factory.php @@ -0,0 +1,97 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea; + + +use Joomla\DI\Container; +use VDM\Joomla\Gitea\Service\Utilities; +use VDM\Joomla\Gitea\Service\Jcb; +use VDM\Joomla\Gitea\Service\Settings; +use VDM\Joomla\Gitea\Service\Organization; +use VDM\Joomla\Gitea\Service\User; +use VDM\Joomla\Gitea\Service\Repository; +use VDM\Joomla\Gitea\Service\Package; +use VDM\Joomla\Gitea\Service\Issue; +use VDM\Joomla\Gitea\Service\Notifications; +use VDM\Joomla\Gitea\Service\Miscellaneous; +use VDM\Joomla\Gitea\Service\Admin; +use VDM\Joomla\Interfaces\FactoryInterface; + + +/** + * Gitea Factory + * + * @since 3.2.0 + */ +abstract class Factory implements FactoryInterface +{ + /** + * Global Package Container + * + * @var Container + * @since 3.2.0 + **/ + protected static $container = null; + + /** + * Get any class from the package container + * + * @param string $key The container class key + * + * @return Mixed + * @since 3.2.0 + */ + public static function _($key) + { + return self::getContainer()->get($key); + } + + /** + * Get the global package container + * + * @return Container + * @since 3.2.0 + */ + public static function getContainer(): Container + { + if (!self::$container) + { + self::$container = self::createContainer(); + } + + return self::$container; + } + + /** + * Create a container object + * + * @return Container + * @since 3.2.0 + */ + protected static function createContainer(): Container + { + return (new Container()) + ->registerServiceProvider(new Utilities()) + ->registerServiceProvider(new Jcb()) + ->registerServiceProvider(new Settings()) + ->registerServiceProvider(new Organization()) + ->registerServiceProvider(new User()) + ->registerServiceProvider(new Repository()) + ->registerServiceProvider(new Package()) + ->registerServiceProvider(new Issue()) + ->registerServiceProvider(new Notifications()) + ->registerServiceProvider(new Miscellaneous()) + ->registerServiceProvider(new Admin()); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue.php new file mode 100644 index 0000000..bfeb418 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue.php @@ -0,0 +1,406 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Issue + * + * @since 3.2.0 + */ +class Issue extends Api +{ + /** + * List a repository's issues. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param string $state The state of the issues to get, defaults to 'open'. + * @param int $page The page to get, defaults to null. + * @param int $limit The number of issues per page, defaults to null. + * @param string|null $labels Comma-separated list of labels, defaults to null. + * @param string|null $q The search string, defaults to null. + * @param string|null $type The type to filter by (issues/pulls), defaults to null. + * @param string|null $milestones Comma-separated list of milestone names or IDs, defaults to null. + * @param string|null $since Only show items updated after the given time, defaults to null. + * @param string|null $before Only show items updated before the given time, defaults to null. + * @param string|null $createdBy Only show items created by the given user, defaults to null. + * @param string|null $assignedBy Only show items assigned to the given user, defaults to null. + * @param string|null $mentionedBy Only show items where the given user is mentioned, defaults to null. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + string $owner, + string $repo, + string $state = 'open', + int $page = 1, + int $limit = 10, + ?string $labels = null, + ?string $q = null, + ?string $type = null, + ?string $milestones = null, + ?string $since = null, + ?string $before = null, + ?string $createdBy = null, + ?string $assignedBy = null, + ?string $mentionedBy = null + ): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues"; + + // Build the URI. + $uri = $this->uri->get($path); + + // Set the query parameters + $uri->setVar('state', $state); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + $uri->setVar('labels', $labels); + $uri->setVar('q', $q); + $uri->setVar('type', $type); + $uri->setVar('milestones', $milestones); + $uri->setVar('since', $since); + $uri->setVar('before', $before); + $uri->setVar('created_by', $createdBy); + $uri->setVar('assigned_by', $assignedBy); + $uri->setVar('mentioned_by', $mentionedBy); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get an issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(string $owner, string $repo, int $index): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Create an issue. If using deadline only the date will be taken into account, and time of day ignored. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param string $issueTitle The issue title. + * @param array|null $assignees The array of assignees, defaults to null. + * @param string|null $issueBody The issue body, defaults to null. + * @param bool|null $closed If the issue is closed, defaults to null. + * @param string|null $dueDate The deadline for the issue, format: "YYYY-MM-DD", defaults to null. + * @param array|null $labelIds The array of label IDs to attach to the issue, defaults to null. + * @param int|null $milestoneId The milestone ID, defaults to null. + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $owner, + string $repo, + string $issueTitle, + ?array $assignees = null, + ?string $issueBody = null, + ?bool $closed = null, + ?string $dueDate = null, + ?array $labelIds = null, + ?int $milestoneId = null + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues"; + + // Build the request data. + $data = new \stdClass(); + $data->title = $issueTitle; + $data->body = $issueBody; + $data->assignees = $assignees; + $data->closed = $closed; + $data->due_date = $dueDate; + $data->labels = $labelIds; + $data->milestone = $milestoneId; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } + + /** + * Search for issues across the repositories that the user has access to. + * + * @param string $q Search query. + * @param int $page Page number (default 1). + * @param int $limit Page size (default 10, max 50). + * @param string|null $state Issue state (default open). + * @param string|null $labels Label filter, comma-separated. + * @param string|null $milestones Milestone filter, comma-separated. + * @param int|null $priorityRepoId Repository to prioritize in the results. + * @param string|null $type Filter by type (issues/pulls). + * @param string|null $since Only show notifications updated after the given time (RFC 3339 format). + * @param string|null $before Only show notifications updated before the given time (RFC 3339 format). + * @param bool|null $assigned Filter assigned to you (default false). + * @param bool|null $created Filter created by you (default false). + * @param bool|null $mentioned Filter mentioning you (default false). + * @param bool|null $reviewRequested Filter pulls requesting your review (default false). + * @param string|null $owner Filter by owner. + * @param string|null $team Filter by team (requires organization owner parameter). + * + * @return array|null + * @since 3.2.0 + **/ + public function search( + string $q, + int $page = 1, + int $limit = 10, + ?string $state = 'open', + ?string $labels = null, + ?string $milestones = null, + ?int $priorityRepoId = null, + ?string $type = null, + ?string $since = null, + ?string $before = null, + ?bool $assigned = null, + ?bool $created = null, + ?bool $mentioned = null, + ?bool $reviewRequested = null, + ?string $owner = null, + ?string $team = null + ): ?array + { + // Build the request path. + $path = "/repos/issues/search"; + + // Set the URL parameters. + $uri = $this->uri->get($path); + $uri->setVar('q', $q); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + $uri->setVar('state', $state); + + if ($labels !== null) + { + $uri->setVar('labels', $labels); + } + + if ($milestones !== null) + { + $uri->setVar('milestones', $milestones); + } + + if ($priorityRepoId !== null) + { + $uri->setVar('priority_repo_id', $priorityRepoId); + } + + if ($type !== null) + { + $uri->setVar('type', $type); + } + + if ($since !== null) + { + $uri->setVar('since', $since); + } + + if ($before !== null) + { + $uri->setVar('before', $before); + } + + if ($assigned !== null) + { + $uri->setVar('assigned', $assigned); + } + + if ($created !== null) + { + $uri->setVar('created', $created); + } + + if ($mentioned !== null) + { + $uri->setVar('mentioned', $mentioned); + } + + if ($reviewRequested !== null) + { + $uri->setVar('review_requested', $reviewRequested); + } + + if ($owner !== null) + { + $uri->setVar('owner', $owner); + } + + if ($team !== null) + { + $uri->setVar('team', $team); + } + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Edit an issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * @param string|null $assignee The assignee, defaults to null. + * @param array|null $assignees The assignees, defaults to null. + * @param string|null $body The issue body, defaults to null. + * @param string|null $dueDate The due date, defaults to null. + * @param int|null $milestone The milestone, defaults to null. + * @param string|null $ref The reference, defaults to null. + * @param string|null $state The issue state, defaults to null. + * @param string|null $title The issue title, defaults to null. + * @param bool|null $unsetDueDate The flag to unset due date, defaults to null. + * + * @return object|null + * @since 3.2.0 + **/ + public function edit( + string $owner, + string $repo, + int $index, + ?string $assignee = null, + ?array $assignees = null, + ?string $body = null, + ?string $dueDate = null, + ?int $milestone = null, + ?string $ref = null, + ?string $state = null, + ?string $title = null, + ?bool $unsetDueDate = null + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}"; + + // Prepare the issue data. + $editIssueData = new \stdClass(); + + if ($assignee !== null || $assignees !== null) + { + $editIssueData->assignee = new \stdClass(); + + if ($assignee !== null) + { + $editIssueData->assignee->name = $assignee; + } + + if ($assignees !== null) + { + $editIssueData->assignee->names = $assignees; + } + } + + if ($body !== null) + { + $editIssueData->body = $body; + } + + if ($dueDate !== null || $unsetDueDate !== null) + { + $editIssueData->dueDate = new \stdClass(); + + if ($dueDate !== null) + { + $editIssueData->dueDate->date = $dueDate; + } + + if ($unsetDueDate !== null) + { + $editIssueData->dueDate->unset = $unsetDueDate; + } + } + + if ($milestone !== null) + { + $editIssueData->milestone = $milestone; + } + + if ($ref !== null) + { + $editIssueData->ref = $ref; + } + + if ($state !== null) + { + $editIssueData->state = $state; + } + + if ($title !== null) + { + $editIssueData->title = $title; + } + + // Send the patch request. + return $this->response->get( + $this->http->patch( + $this->uri->get($path), json_encode($editIssueData) + ) + ); + } + + /** + * Delete an issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * + * @return string + * @since 3.2.0 + **/ + public function delete(string $owner, string $repo, int $index): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Comments.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Comments.php new file mode 100644 index 0000000..c244035 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Comments.php @@ -0,0 +1,176 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Issue; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Issue Comments + * + * @since 3.2.0 + */ +class Comments extends Api +{ + /** + * List all comments on an issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * @param int $page The page number to get, defaults to 1. + * @param int $limit The number of comments per page, defaults to 10. + * @param string|null $since The date-time since when to get comments, defaults to null. + * @param string|null $before The date-time before when to get comments, defaults to null. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + string $owner, + string $repo, + int $index, + int $page = 1, + int $limit = 10, + ?string $since = null, + ?string $before = null + ): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/comments"; + + // Build the URI. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Set the 'since' and 'before' parameters if not null. + if ($since !== null) + { + $uri->setVar('since', $since); + } + if ($before !== null) + { + $uri->setVar('before', $before); + } + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get a comment. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $commentId The comment ID. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(string $owner, string $repo, int $commentId): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/comments/{$commentId}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Delete a comment. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $commentId The comment ID. + * + * @return string + * @since 3.2.0 + **/ + public function delete(string $owner, string $repo, int $commentId): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/comments/{$commentId}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * Edit a comment. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $commentId The comment ID. + * @param string $commentBody The new comment body. + * + * @return object|null + * @since 3.2.0 + **/ + public function edit(string $owner, string $repo, int $commentId, string $commentBody): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/comments/{$commentId}"; + + // Build the request data. + $data = new \stdClass(); + $data->body = $commentBody; + + // Send the patch request. + return $this->response->get( + $this->http->patch( + $this->uri->get($path), json_encode($data) + ) + ); + } + + /** + * Add a comment to an issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $issueIndex The issue index. + * @param string $commentBody The comment body. + * + * @return object|null + * @since 3.2.0 + **/ + public function add(string $owner, string $repo, int $issueIndex, string $commentBody): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$issueIndex}/comments"; + + // Build the request data. + $data = new \stdClass(); + $data->body = $commentBody; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ), 201 + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Deadline.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Deadline.php new file mode 100644 index 0000000..6c13d07 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Deadline.php @@ -0,0 +1,54 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Issue; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Issue Deadline + * + * @since 3.2.0 + */ +class Deadline extends Api +{ + /** + * Set an issue deadline. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * @param string|null $dueDate The deadline date string in the format YYYY-MM-DD or null to delete the deadline. + * + * @return object + * @since 3.2.0 + **/ + public function set(string $owner, string $repo, int $index, ?string $dueDate): object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/deadline"; + + // Build the request data. + $data = new \stdClass(); + $data->due_date = $dueDate; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Labels.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Labels.php new file mode 100644 index 0000000..fda80dc --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Labels.php @@ -0,0 +1,181 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Issue; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Issue Labels + * + * @since 3.2.0 + */ +class Labels extends Api +{ + /** + * Get all of a repository's labels. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $page The page number of results to return (1-based). + * @param int $limit The page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list(string $owner, string $repo, int $page = 1, int $limit = 10): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/labels"; + + // Get the URI object with the request path. + $uri = $this->uri->get($path); + + // Add the page and limit query parameters if provided. + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get an issue's labels. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * + * @return array|null + * @since 3.2.0 + **/ + public function get(string $owner, string $repo, int $index): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/labels"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Replace an issue's labels. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * @param array $labels An array of labels to replace the current issue labels. + * + * @return object + * @since 3.2.0 + **/ + public function replace(string $owner, string $repo, int $index, array $labels): object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/labels"; + + // Build the request data. + $data = new \stdClass(); + $data->labels = $labels; + + // Send the put request. + return $this->response->get( + $this->http->put( + $this->uri->get($path), json_encode($data) + ) + ); + } + + /** + * Add a label to an issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * @param array $labels An array of label IDs to add. + * + * @return array|null + * @since 3.2.0 + **/ + public function add(string $owner, string $repo, int $index, array $labels): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/labels"; + + // Build the request data. + $data = new \stdClass(); + $data->labels = $labels; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } + + /** + * Remove a label from an issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * @param int $labelId The ID of the label to remove. + * + * @return string + * @since 3.2.0 + **/ + public function remove(string $owner, string $repo, int $index, int $labelId): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/labels/{$labelId}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * Remove all labels from an issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * + * @return string + * @since 3.2.0 + **/ + public function clear(string $owner, string $repo, int $index): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/labels"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Milestones.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Milestones.php new file mode 100644 index 0000000..5178a73 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Milestones.php @@ -0,0 +1,230 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Issue; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Issue Milestones + * + * @since 3.2.0 + */ +class Milestones extends Api +{ + /** + * Create a milestone. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param string $title The title of the milestone. + * @param string|null $description Optional. The description of the milestone. + * @param string|null $dueOn Optional. The due date of the milestone. + * @param string|null $state Optional. The state of the milestone. Default is 'open'. + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $owner, + string $repo, + string $title, + ?string $description = null, + ?string $dueOn = null, + ?string $state = 'open' + ): ?object + { + // Set the lines data + $data = new \stdClass(); + + // Set all the required data. + $data->title = $title; + + // Set all the optional data that has been provided. + if ($description !== null) + { + $data->description = $description; + } + if ($dueOn !== null) + { + $data->due_on = $dueOn; + } + if ($state !== null) + { + $data->state = $state; + } + + // Build the request path. + $path = "/repos/{$owner}/{$repo}/milestones"; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + json_encode($data) + ), 201 + ); + } + + /** + * Get all of a repository's opened milestones. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param string|null $state Optional. Milestone state. Recognized values are open, closed, and all. Defaults to "open". + * @param string|null $name Optional. Filter by milestone name. + * @param int|null $page Optional. Page number of results to return (1-based). + * @param int|null $limit Optional. Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + string $owner, + string $repo, + ?string $state = 'open', + ?string $name = null, + ?int $page = null, + ?int $limit = null + ): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/milestones"; + + // Build the URI. + $uri = $this->uri->get($path); + $uri->setVar('state', $state); + if ($name !== null) + { + $uri->setVar('name', $name); + } + if ($page !== null) + { + $uri->setVar('page', $page); + } + if ($limit !== null) + { + $uri->setVar('limit', $limit); + } + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get a milestone. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param string $milestoneId The ID of the milestone. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(string $owner, string $repo, string $milestoneId): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/milestones/{$milestoneId}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Delete a milestone. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param string $milestoneId The ID of the milestone to delete. + * + * @return string + * @since 3.2.0 + **/ + public function delete(string $owner, string $repo, string $milestoneId): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/milestones/{$milestoneId}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * Update a milestone. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param string $milestoneId The ID of the milestone to update. + * @param string $title Optional. The new title of the milestone. + * @param string $description Optional. The new description of the milestone. + * @param string $dueOn Optional. The new due date of the milestone. + * @param string $state Optional. The new state of the milestone. + * + * @return object|null + * @since 3.2.0 + **/ + public function update( + string $owner, + string $repo, + string $milestoneId, + string $title = null, + string $description = null, + string $dueOn = null, + string $state = null + ): ?object + { + // Set the lines data + $data = new \stdClass(); + + // Set all the optional data that has been provided. + if ($title !== null) + { + $data->title = $title; + } + if ($description !== null) + { + $data->description = $description; + } + if ($dueOn !== null) + { + $data->due_on = $dueOn; + } + if ($state !== null) + { + $data->state = $state; + } + + // Build the request path. + $path = "/repos/{$owner}/{$repo}/milestones/{$milestoneId}"; + + // Send the patch request. + return $this->response->get( + $this->http->patch( + $this->uri->get($path), + json_encode($data) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Reactions.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Reactions.php new file mode 100644 index 0000000..7595295 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Reactions.php @@ -0,0 +1,110 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Issue; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Issue Reactions + * + * @since 3.2.0 + */ +class Reactions extends Api +{ + /** + * Get a list reactions of an issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * @param int $page The page to get, defaults to 1. + * @param int $limit The number of reactions per page, defaults to 10. + * + * @return array|null + * @since 3.2.0 + **/ + public function list(string $owner, string $repo, int $index, int $page = 1, int $limit = 10): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/reactions"; + + // Build the URI. + $uri = $this->uri->get($path); + + // Set the URI variables. + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Add a reaction to an issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * @param string $content The name of the reaction to add. + * + * @return object|null + * @since 3.2.0 + **/ + public function add(string $owner, string $repo, int $index, string $content): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/reactions"; + + // Build the request data. + $data = new \stdClass(); + $data->content = $content; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } + + /** + * Remove a reaction from an issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * @param string $content The name of the reaction to remove. + * + * @return string + * @since 3.2.0 + **/ + public function remove(string $owner, string $repo, int $index, string $content): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/reactions"; + + // Build the URI. + $uri = $this->uri->get($path); + $uri->setVar('content', $content); + + // Send the delete request. + return $this->response->get( + $this->http->delete($uri), 200, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Reactions/Comment.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Reactions/Comment.php new file mode 100644 index 0000000..0f2ca78 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Reactions/Comment.php @@ -0,0 +1,103 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Issue\Reactions; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Issue Reactions Comment + * + * @since 3.2.0 + */ +class Comment extends Api +{ + /** + * Get a list of reactions from a comment of an issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $commentId The comment ID. + * + * @return array|null + * @since 3.2.0 + **/ + public function list(string $owner, string $repo, int $commentId): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/comments/{$commentId}/reactions"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Add a reaction to a comment of an issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $commentId The comment ID. + * @param string $content The reaction to add, e.g. "+1". + * + * @return object|null + * @since 3.2.0 + **/ + public function add(string $owner, string $repo, int $commentId, string $content): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/comments/{$commentId}/reactions"; + + // Build the request data. + $data = new \stdClass(); + $data->content = $content; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } + + /** + * Remove a reaction from a comment of an issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $commentId The comment ID. + * @param string $content The reaction to remove, e.g. "+1". + * + * @return string + * @since 3.2.0 + **/ + public function remove(string $owner, string $repo, int $commentId, string $content): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/comments/{$commentId}/reactions"; + + // Build the URI. + $uri = $this->uri->get($path); + $uri->setVar('content', $content); + + // Send the delete request. + return $this->response->get( + $this->http->delete($uri), 200, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Reactions/index.html b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Reactions/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Reactions/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Repository/Comments.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Repository/Comments.php new file mode 100644 index 0000000..3ca83fc --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Repository/Comments.php @@ -0,0 +1,67 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Issue\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Issue Repository Comments + * + * @since 3.2.0 + */ +class Comments extends Api +{ + /** + * List all comments in a repository. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $page The page to get, defaults to 1. + * @param int $limit The number of comments per page, defaults to 10. + * @param string|null $since The date-time string to filter updated comments since, defaults to null. + * @param string|null $before The date-time string to filter updated comments before, defaults to null. + * + * @return array|null + * @since 3.2.0 + **/ + public function list(string $owner, string $repo, int $page = 1, int $limit = 10, ?string $since = null, ?string $before = null): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/comments"; + + // Build the URI. + $uri = $this->uri->get($path); + + // Set the URI variables. + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + if ($since !== null) + { + $uri->setVar('since', $since); + } + + if ($before !== null) + { + $uri->setVar('before', $before); + } + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Repository/index.html b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Repository/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Repository/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Stopwatch.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Stopwatch.php new file mode 100644 index 0000000..6745416 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Stopwatch.php @@ -0,0 +1,95 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Issue; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Issue Stopwatch + * + * @since 3.2.0 + */ +class Stopwatch extends Api +{ + /** + * Start stopwatch on an issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * + * @return string + * @since 3.2.0 + **/ + public function start(string $owner, string $repo, int $index): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/stopwatch/start"; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), '' + ), 201, 'success' + ); + } + + /** + * Stop an issue's existing stopwatch. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * + * @return string + * @since 3.2.0 + **/ + public function stop(string $owner, string $repo, int $index): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/stopwatch/stop"; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), '' + ), 201, 'success' + ); + } + + /** + * Delete an issue's existing stopwatch. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * + * @return string + * @since 3.2.0 + **/ + public function delete(string $owner, string $repo, int $index): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/stopwatch/delete"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Subscriptions.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Subscriptions.php new file mode 100644 index 0000000..c29bfb6 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Subscriptions.php @@ -0,0 +1,137 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Issue; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Issue Subscriptions + * + * @since 3.2.0 + */ +class Subscriptions extends Api +{ + /** + * Get users who subscribed on an issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * @param int|null $page Optional. Page number of results to return (1-based). + * @param int|null $limit Optional. Page size of results. + * + * @return object|null + * @since 3.2.0 + **/ + public function get( + string $owner, + string $repo, + int $index, + ?int $page = null, + ?int $limit = null + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/subscriptions"; + + // Set the query parameters. + $uri = $this->uri->get($path); + if ($page !== null) + { + $uri->setVar('page', $page); + } + if ($limit !== null) + { + $uri->setVar('limit', $limit); + } + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Check if user is subscribed to an issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * + * @return object|null + * @since 3.2.0 + **/ + public function check(string $owner, string $repo, int $index): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/subscriptions/check"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Subscribe user to issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * @param string $user The username to subscribe. + * + * @return string + * @since 3.2.0 + **/ + public function subscribe(string $owner, string $repo, int $index, string $user): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/subscriptions/{$user}"; + + // Send the put request. + return $this->response->get_( + $this->http->put( + $this->uri->get($path), '' + ), [200 => 'already subscribed', 201 => 'success'] + ); + } + + /** + * Unsubscribe user from issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * @param string $user The username to unsubscribe. + * + * @return string + * @since 3.2.0 + **/ + public function unsubscribe(string $owner, string $repo, int $index, string $user): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/subscriptions/{$user}"; + + // Send the delete request. + return $this->response->get_( + $this->http->delete( + $this->uri->get($path) + ), [200 => 'already unsubscribed', 201 => 'success'] + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Timeline.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Timeline.php new file mode 100644 index 0000000..4c54937 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Timeline.php @@ -0,0 +1,78 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Issue; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Issue Timeline + * + * @since 3.2.0 + */ +class Timeline extends Api +{ + /** + * List all comments and events on an issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * @param string|null $since Optional. If provided, only comments updated since the specified time are returned. + * @param int|null $page Optional. Page number of results to return (1-based). + * @param int|null $limit Optional. Page size of results. + * @param string|null $before Optional. If provided, only comments updated before the provided time are returned. + * + * @return array|null + * @since 3.2.0 + **/ + public function get( + string $owner, + string $repo, + int $index, + ?string $since = null, + ?int $page = null, + ?int $limit = null, + ?string $before = null + ): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/timeline"; + + // Set the query parameters. + $uri = $this->uri->get($path); + if ($since !== null) + { + $uri->setVar('since', $since); + } + if ($page !== null) + { + $uri->setVar('page', $page); + } + if ($limit !== null) + { + $uri->setVar('limit', $limit); + } + if ($before !== null) + { + $uri->setVar('before', $before); + } + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Times.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Times.php new file mode 100644 index 0000000..7c33c2a --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/Times.php @@ -0,0 +1,179 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Issue; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Issue Times + * + * @since 3.2.0 + */ +class Times extends Api +{ + /** + * List an issue's tracked times. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * @param string $user Optional. Filter by user. + * @param string $since Optional. Show times updated after the given time. + * @param string $before Optional. Show times updated before the given time. + * @param int $page Optional. Page number of results to return (1-based). + * @param int $limit Optional. Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + string $owner, + string $repo, + int $index, + string $user = null, + string $since = null, + string $before = null, + int $page = null, + int $limit = null + ): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/times"; + + // Prepare the query parameters. + $uri = $this->uri->get($path); + if ($user !== null) + { + $uri->setVar('user', $user); + } + if ($since !== null) + { + $uri->setVar('since', $since); + } + if ($before !== null) + { + $uri->setVar('before', $before); + } + if ($page !== null) + { + $uri->setVar('page', $page); + } + if ($limit !== null) + { + $uri->setVar('limit', $limit); + } + + // Send the get request with the query parameters. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Add tracked time to an issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * @param int $time The tracked time in seconds. + * @param string $created Optional. The date and time of the tracked time in RFC 3339 format. + * @param string $userName Optional. User who spent the time. + * + * @return object|null + * @since 3.2.0 + **/ + public function add( + string $owner, + string $repo, + int $index, + int $time, + string $created = null, + string $userName = null + ): ?object + { + // Set the lines data + $data = new \stdClass(); + + // Set all the needed data. + $data->time = $time; + if ($created !== null) + { + $data->created = $created; + } + if ($userName !== null) + { + $data->user_name = $userName; + } + + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/times"; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + json_encode($data) + ) + ); + } + + /** + * Reset a tracked time of an issue. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * + * @return string + * @since 3.2.0 + **/ + public function reset(string $owner, string $repo, int $index): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/times"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * Delete specific tracked time. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param int $index The issue index. + * @param int $id The ID of the tracked time to delete. + * + * @return string + * @since 3.2.0 + **/ + public function delete(string $owner, string $repo, int $index, int $id): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issues/{$index}/times/{$id}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/index.html b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Issue/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Labels.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Labels.php new file mode 100644 index 0000000..43f2c9f --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Labels.php @@ -0,0 +1,162 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Labels + * + * @since 3.2.0 + */ +class Labels extends Api +{ + /** + * Create a label. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param string $labelName The name of the label. + * @param string $labelColor The color of the label, in hexadecimal format with the leading '#'. + * @param string $labelDescription Optional. The description of the label. + * + * @return object|null + * @since 3.2.0 + **/ + public function create(string $owner, string $repo, string $labelName, string $labelColor, string $labelDescription = ''): ?object + { + // Set the lines data + $data = new \stdClass(); + + // Set all the needed data. + $data->name = $labelName; + $data->color = $labelColor; + if (!empty($labelDescription)) + { + $data->description = $labelDescription; + } + + // Build the request path. + $path = "/repos/{$owner}/{$repo}/labels"; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + json_encode($data) + ), 201 + ); + } + + /** + * Get a single label. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param string $id The ID of the label to retrieve. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(string $owner, string $repo, string $id): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/labels/{$id}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Delete a label. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param string $id The ID of the label to delete. + * + * @return string + * @since 3.2.0 + **/ + public function delete(string $owner, string $repo, string $id): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/labels/{$id}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * Update a label. + * + * @param string $owner The owner name. + * @param string $repo The repo name. + * @param string $id The ID of the label to update. + * @param string $labelName Optional. The new name of the label. + * @param string $labelColor Optional. The new color of the label, in hexadecimal format without the leading '#'. + * @param string $labelDescription Optional. The new description of the label. + * + * @return object|null + * @since 3.2.0 + **/ + public function update( + string $owner, + string $repo, + string $id, + string $labelName = '', + string $labelColor = '', + string $labelDescription = '' + ): ?object + { + // Set the lines data + $data = new \stdClass(); + + // Set all the optional data that has been provided. + if (!empty($labelName)) + { + $data->name = $labelName; + } + + if (!empty($labelColor)) + { + $data->color = $labelColor; + } + + if (!empty($labelDescription)) + { + $data->description = $labelDescription; + } + + // Build the request path. + $path = "/repos/{$owner}/{$repo}/labels/{$id}"; + + // Send the patch request. + return $this->response->get( + $this->http->patch( + $this->uri->get($path), + json_encode($data) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/Activitypub.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/Activitypub.php new file mode 100644 index 0000000..78c6d27 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/Activitypub.php @@ -0,0 +1,69 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Miscellaneous; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Miscellaneous Activitypub + * + * @since 3.2.0 + */ +class Activitypub extends Api +{ + /** + * Returns the Person actor for a user. + * + * @param string $username The user's username. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(string $username): ?object + { + // Build the request path. + $path = "/activitypub/user/{$username}"; + + // Send the GET request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Send to the user's inbox. + * + * @param string $username The user's username. + * @param object $postData The post data. + * + * @return string + * @since 3.2.0 + **/ + public function send(string $username, object $postData): string + { + // Build the request path. + $path = "/activitypub/user/{$username}/inbox"; + + // Send the POST request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($postData) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/Gpg.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/Gpg.php new file mode 100644 index 0000000..5a92c54 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/Gpg.php @@ -0,0 +1,45 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Miscellaneous; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Miscellaneous Gpg + * + * @since 3.2.0 + */ +class Gpg extends Api +{ + /** + * Get default signing-key.gpg. + * + * @return string|null + * @since 3.2.0 + **/ + public function get(): ?string + { + // Build the request path. + $path = "/signing-key.gpg"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/Markdown.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/Markdown.php new file mode 100644 index 0000000..f6f54e5 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/Markdown.php @@ -0,0 +1,87 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Miscellaneous; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Miscellaneous Markdown + * + * @since 3.2.0 + */ +class Markdown extends Api +{ + /** + * Render a markdown document as HTML. + * + * @param string $markdownText The markdown text to render. + * @param bool $isWikiPage Is it a wiki page? + * @param string $context Context to render. + * @param string $mode Mode to render. + * + * @return string|null + * @since 3.2.0 + **/ + public function render( + string $markdownText, + bool $isWikiPage = false, + string $context = 'string', + string $mode = 'string' + ): ?string + { + // Build the request path. + $path = "/markdown"; + + // Set the markdown data. + $data = new \stdClass(); + $data->Text = $markdownText; + $data->Wiki = $isWikiPage; + $data->Context = $context; + $data->Mode = $mode; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + json_encode($data), + ['accept' => 'text/html'] + ) + ); + } + + /** + * Render raw markdown as HTML. + * + * @param string $rawMarkdown The raw markdown text to render. + * + * @return string|null + * @since 3.2.0 + **/ + public function raw(string $rawMarkdown): ?string + { + // Build the request path. + $path = "/markdown/raw"; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + $rawMarkdown, + ['Content-Type' => 'text/plain', 'accept' => 'text/html'] + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/NodeInfo.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/NodeInfo.php new file mode 100644 index 0000000..fe714b2 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/NodeInfo.php @@ -0,0 +1,45 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Miscellaneous; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Miscellaneous NodeInfo + * + * @since 3.2.0 + */ +class NodeInfo extends Api +{ + /** + * Returns the nodeinfo of the Gitea application. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(): ?object + { + // Build the request path. + $path = "/nodeinfo"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/Version.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/Version.php new file mode 100644 index 0000000..696db50 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/Version.php @@ -0,0 +1,45 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Miscellaneous; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Miscellaneous Version + * + * @since 3.2.0 + */ +class Version extends Api +{ + /** + * Returns the version of the Gitea application. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(): ?object + { + // Build the request path. + $path = "/version"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/index.html b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Miscellaneous/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Notifications.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Notifications.php new file mode 100644 index 0000000..ffe33a8 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Notifications.php @@ -0,0 +1,149 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Notifications + * + * @since 3.2.0 + */ +class Notifications extends Api +{ + /** + * List user's notification threads. + * + * @param bool|null $all Show notifications marked as read (optional). + * @param array|null $statusTypes Show notifications with the provided status types (optional). + * @param array|null $subjectType Filter notifications by subject type (optional). + * @param string|null $since Show notifications updated after the given time (optional). + * @param string|null $before Show notifications updated before the given time (optional). + * @param int $page Page number of results to return (optional). + * @param int $limit Page size of results (optional). + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + ?bool $all = null, + ?array $statusTypes = null, + ?array $subjectType = null, + ?string $since = null, + ?string $before = null, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/notifications"; + + // Configure the URI with query parameters. + $uri = $this->uri->get($path); + if ($all !== null) + { + $uri->setVar('all', $all); + } + if ($statusTypes !== null) + { + $uri->setVar('status-types', implode(',', $statusTypes)); + } + if ($subjectType !== null) + { + $uri->setVar('subject-type', implode(',', $subjectType)); + } + if ($since !== null) + { + $uri->setVar('since', $since); + } + if ($before !== null) + { + $uri->setVar('before', $before); + } + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Mark notification threads as read, pinned, or unread. + * + * @param string|null $lastReadAt Describes the last point that notifications were checked (optional). + * @param bool|null $all If true, mark all notifications on this repo (optional). + * @param array|null $statusTypes Mark notifications with the provided status types (optional). + * @param string|null $toStatus Status to mark notifications as (optional). + * + * @return array|null + * @since 3.2.0 + **/ + public function update( + ?string $lastReadAt = null, + ?bool $all = null, + ?array $statusTypes = null, + ?string $toStatus = null + ): ?array + { + // Build the request path. + $path = "/notifications"; + + // Configure the URI with query parameters. + $uri = $this->uri->get($path); + if ($lastReadAt !== null) + { + $uri->setVar('last_read_at', $lastReadAt); + } + if ($all !== null) + { + $uri->setVar('all', $all); + } + if ($statusTypes !== null) + { + $uri->setVar('status-types', implode(',', $statusTypes)); + } + if ($toStatus !== null) + { + $uri->setVar('to-status', $toStatus); + } + + // Send the put request. + return $this->response->get( + $this->http->put($uri, ''), 205 + ); + } + + /** + * Check if unread notifications exist. + * + * @return object|null + * @since 3.2.0 + **/ + public function check(): ?object + { + // Build the request path. + $path = "/notifications/new"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Notifications/Repository.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Notifications/Repository.php new file mode 100644 index 0000000..4520391 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Notifications/Repository.php @@ -0,0 +1,144 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Notifications; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Notifications Repository + * + * @since 3.2.0 + */ +class Repository extends Api +{ + /** + * List user's notification threads on a specific repo. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param bool $all Show notifications marked as read. + * @param array $statusTypes Show notifications with the provided status types. + * @param array $subjectTypes Filter notifications by subject type. + * @param string $since Show notifications updated after the given time. + * @param string $before Show notifications updated before the given time. + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function get( + string $owner, + string $repo, + bool $all = false, + array $statusTypes = [], + array $subjectTypes = [], + string $since = '', + string $before = '', + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/notifications"; + + // Configure the URI with query parameters. + $uri = $this->uri->get($path); + + if ($all) + { + $uri->setVar('all', $all); + } + + if (!empty($statusTypes)) + { + $uri->setVar('status-types', implode(',', $statusTypes)); + } + + if (!empty($subjectTypes)) + { + $uri->setVar('subject-type', implode(',', $subjectTypes)); + } + + if (!empty($since)) + { + $uri->setVar('since', $since); + } + + if (!empty($before)) + { + $uri->setVar('before', $before); + } + + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Mark notification threads as read, pinned, or unread on a specific repo. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param bool|null $all Mark all notifications on this repo (optional). + * @param array|null $statusTypes Mark notifications with the provided status types (optional). + * @param string|null $toStatus Status to mark notifications as (optional). + * @param string|null $lastReadAt Last point that notifications were checked (optional). + * + * @return array|null + * @since 3.2.0 + **/ + public function update( + string $owner, + string $repo, + ?bool $all = null, + ?array $statusTypes = null, + ?string $toStatus = null, + ?string $lastReadAt = null + ): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/notifications"; + + // Configure the URI with query parameters. + $uri = $this->uri->get($path); + if ($all !== null) + { + $uri->setVar('all', $all); + } + if ($statusTypes !== null) + { + $uri->setVar('status-types', implode(',', $statusTypes)); + } + if ($toStatus !== null) + { + $uri->setVar('to-status', $toStatus); + } + if ($lastReadAt !== null) + { + $uri->setVar('last_read_at', $lastReadAt); + } + + // Send the put request. + return $this->response->get( + $this->http->put($uri, ''), 205 + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Notifications/Thread.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Notifications/Thread.php new file mode 100644 index 0000000..ae8daaa --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Notifications/Thread.php @@ -0,0 +1,96 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Notifications; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Notifications Thread + * + * @since 3.2.0 + */ +class Thread extends Api +{ + /** + * Get notification thread by ID. + * + * @param int $id The notification thread ID. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(int $id): ?object + { + // Build the request path. + $path = "/notifications/threads/{$id}"; + + // Get the URI with the path. + $uri = $this->uri->get($path); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Mark notification threads as read, pinned, or unread by ID. + * + * @param int $id The notification thread ID. + * @param string|null $lastReadAt Last point that notifications were checked (optional). + * @param bool|null $all Mark all notifications on this repo (optional). + * @param array|null $statusTypes Mark notifications with the provided status types (optional). + * @param string|null $toStatus Status to mark notifications as (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function mark( + int $id, + ?string $lastReadAt = null, + ?bool $all = null, + ?array $statusTypes = null, + ?string $toStatus = null + ): ?object + { + // Build the request path. + $path = "/notifications/threads/{$id}"; + + // Configure the URI with query parameters. + $uri = $this->uri->get($path); + if ($lastReadAt !== null) + { + $uri->setVar('last_read_at', $lastReadAt); + } + if ($all !== null) + { + $uri->setVar('all', $all); + } + if ($statusTypes !== null) + { + $uri->setVar('status-types', implode(',', $statusTypes)); + } + if ($toStatus !== null) + { + $uri->setVar('to-status', $toStatus); + } + + // Send the put request. + return $this->response->get( + $this->http->put($uri, ''), 205 + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Notifications/index.html b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Notifications/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Notifications/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization.php new file mode 100644 index 0000000..0e7255c --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization.php @@ -0,0 +1,209 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Organization + * + * @since 3.2.0 + */ +class Organization extends Api +{ + /** + * Create an organization. + * + * @param string $login Required. The organization's username. + * @param string $fullName Required. The full name of the organization. + * @param string $email Required. The email of the organization. + * @param string $description Optional. The description of the organization. + * @param bool $repoAdmin Optional. Whether the user has repository admin access. + * @param bool $teamAdmin Optional. Whether the user has team admin access. + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $login, + string $fullName, + string $email, + string $description = '', + bool $repoAdmin = false, + bool $teamAdmin = false + ): ?object + { + // Set the lines data + $data = new \stdClass(); + $data->username = $login; + $data->full_name = $fullName; + $data->email = $email; + $data->description = $description; + $data->repo_admin_change_team_access = $repoAdmin; + $data->team_admin_change_team_access = $teamAdmin; + + // Build the request path. + $path = '/orgs'; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + json_encode($data) + ), 201 + ); + } + + /** + * Get an organization. + * + * @param string $org The organization name. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(string $org): ?object + { + // Build the request path. + $path = "/orgs/{$org}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Get a list of organizations. + * + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = '/orgs'; + + // Get the URI and set query parameters. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Delete an organization. + * + * @param string $org The organization name. + * + * @return string + * @since 3.2.0 + **/ + public function delete(string $org): string + { + // Build the request path. + $path = "/orgs/{$org}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * Edit an organization. + * + * @param string $org The organization name. + * @param string $fullName Optional. The full name of the organization. + * @param string $location Optional. The location of the organization. + * @param string $description Optional. The description of the organization. + * @param bool $repoAdmin Optional. Whether the user has repository admin access. + * @param string $visibility Optional. The visibility of the organization (public, limited, or private). + * @param string $website Optional. The website of the organization. + * + * @return object|null + * @since 3.2.0 + **/ + public function edit( + string $org, + ?string $fullName = null, + ?string $email = null, + ?string $location = null, + ?string $description = null, + ?bool $repoAdmin = null, + ?string $visibility = null, + ?string $website = null + ): ?object + { + // Set the lines data + $data = new \stdClass(); + + if ($fullName !== null) + { + $data->full_name = $fullName; + } + + if ($location !== null) + { + $data->location = $location; + } + + if ($description !== null) + { + $data->description = $description; + } + + if ($repoAdmin !== null) + { + $data->repo_admin_change_team_access = $repoAdmin; + } + + if ($visibility !== null) + { + $data->visibility = $visibility; + } + + if ($website !== null) + { + $data->website = $website; + } + + // Build the request path. + $path = "/orgs/{$org}"; + + // Send the patch request. + return $this->response->get( + $this->http->patch( + $this->uri->get($path), + json_encode($data) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Hooks.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Hooks.php new file mode 100644 index 0000000..981c065 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Hooks.php @@ -0,0 +1,200 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Organization; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Organization Hooks + * + * @since 3.2.0 + */ +class Hooks extends Api +{ + /** + * List an organization's webhooks. + * + * @param string $orgName The organization name. + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + string $orgName, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/orgs/{$orgName}/hooks"; + + // Get the URI and set query parameters. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Create a hook for an organization. + * + * @param string $org The organization name. + * @param string $type The type of hook (e.g. "gitea", "slack", "discord", etc.). + * @param string $url The URL of the hook. + * @param string $secret Optional. The secret for the hook. + * @param bool $events Optional. The events that trigger the hook. + * @param bool $active Optional. Whether the hook is active. + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $org, + string $type, + string $url, + string $secret = '', + bool $events = true, + bool $active = true + ): ?object + { + // Set the lines data + $data = new \stdClass(); + $data->type = $type; + $data->config = new \stdClass(); + $data->config->url = $url; + $data->config->secret = $secret; + $data->events = []; + $data->active = $active; + + // Build the request path. + $path = "/orgs/{$org}/hooks"; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + json_encode($data) + ), 201 + ); + } + + /** + * Get a hook for an organization. + * + * @param string $org The organization name. + * @param int $id The ID of the hook. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(string $org, int $id): ?object + { + // Build the request path. + $path = "/orgs/{$org}/hooks/{$id}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Delete a hook for an organization. + * + * @param string $org The organization name. + * @param int $id The hook ID. + * + * @return string + * @since 3.2.0 + **/ + public function delete(string $org, int $id): string + { + // Build the request path. + $path = "/orgs/{$org}/hooks/{$id}"; + + // Send the DELETE request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * Update a hook for an organization. + * + * @param string $orgName The organization name. + * @param int $hookId The ID of the hook. + * @param bool|null $active Optional. Whether the hook is active. + * @param string|null $branchFilter Optional. Branch filter for the hook. + * @param array|null $config Optional. Configuration for the hook. + * @param array|null $events Optional. Events for the hook. + * + * @return object|null + * @since 3.2.0 + **/ + public function update( + string $orgName, + int $hookId, + ?bool $active = null, + ?string $branchFilter = null, + ?array $config = null, + ?array $events = null + ): ?object + { + // Set the lines data + $data = new \stdClass(); + + if ($active !== null) + { + $data->active = $active; + } + + if ($branchFilter !== null) + { + $data->branch_filter = $branchFilter; + } + + if ($config !== null) + { + $data->config = (object) $config; + } + + if ($events !== null) + { + $data->events = $events; + } + + // Build the request path. + $path = "/orgs/{$orgName}/hooks/{$hookId}"; + + // Send the patch request. + return $this->response->get( + $this->http->patch( + $this->uri->get($path), + json_encode($data) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Labels.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Labels.php new file mode 100644 index 0000000..0836501 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Labels.php @@ -0,0 +1,183 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Organization; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Organization Labels + * + * @since 3.2.0 + */ +class Labels extends Api +{ + /** + * List an organization's labels. + * + * @param string $orgName The organization name. + * @param int $pageNum Page number of results to return (1-based). + * @param int $pageSize Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + string $orgName, + int $pageNum = 1, + int $pageSize = 10 + ): ?array + { + // Build the request path. + $path = "/orgs/{$orgName}/labels"; + + // Build the URL + $url = $this->uri->get($path); + $url->setVar('page', $pageNum); + $url->setVar('limit', $pageSize); + + // Send the get request. + return $this->response->get( + $this->http->get($url) + ); + } + + /** + * Create a label for an organization. + * + * @param string $org The organization name. + * @param string $name The name of the label. + * @param string $color The color of the label. + * @param string $description Optional. The description of the label. + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $org, + string $name, + string $color, + string $description = '' + ): ?object + { + // Set the lines data + $data = new \stdClass(); + $data->name = $name; + $data->color = $color; + $data->description = $description; + + // Build the request path. + $path = "/orgs/{$org}/labels"; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + json_encode($data) + ), 201 + ); + } + + /** + * Get a single label for an organization. + * + * @param string $org The organization name. + * @param int $id The ID of the label. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(string $org, int $id): ?object + { + // Build the request path. + $path = "/orgs/{$org}/labels/{$id}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Delete a label for an organization. + * + * @param string $org The organization name. + * @param int $id The ID of the label. + * + * @return string + * @since 3.2.0 + **/ + public function delete(string $org, int $id): string + { + // Build the request path. + $path = "/orgs/{$org}/labels/{$id}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * Update a label for an organization. + * + * @param string $org The organization name. + * @param int $id The ID of the label. + * @param string $name Optional. The name of the label. + * @param string $color Optional. The color of the label. + * @param string $description Optional. The description of the label. + * + * @return object|null + * @since 3.2.0 + **/ + public function update( + string $org, + int $id, + string $name = '', + string $color = '', + string $description = '' + ): ?object + { + // Set the lines data + $data = new \stdClass(); + + if ($name) { + $data->name = $name; + } + + if ($color) { + $data->color = $color; + } + + if ($description) { + $data->description = $description; + } + + // Build the request path. + $path = "/orgs/{$org}/labels/{$id}"; + + // Send the patch request. + return $this->response->get( + $this->http->patch( + $this->uri->get($path), + json_encode($data) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Members.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Members.php new file mode 100644 index 0000000..97bf82b --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Members.php @@ -0,0 +1,100 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Organization; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Organization Members + * + * @since 3.2.0 + */ +class Members extends Api +{ + /** + * Get a list of members of an organization. + * + * @param string $orgName The organization name. + * @param int $page The page number. + * @param int $limit The number of members per page. + * + * @return array|null The organization members. + * @since 3.2.0 + */ + public function list( + string $orgName, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/orgs/{$orgName}/members"; + + // Get the URI and set query parameters. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Check if a user is a member of an organization. + * + * @param string $org The organization name. + * @param string $username The username. + * + * @return string Whether the user is a member of the organization. + * @since 3.2.0 + */ + public function check(string $org, string $username): string + { + // Build the request path. + $path = "/orgs/{$org}/members/{$username}"; + + // Send the request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * Remove a member from an organization. + * + * @param string $org The organization name. + * @param string $username The username of the user to remove. + * + * @return string Whether the user was successfully removed from the organization. + * @since 3.2.0 + */ + public function remove(string $org, string $username): string + { + // Build the request path. + $path = "/orgs/{$org}/members/{$username}"; + + // Send the request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/PublicMembers.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/PublicMembers.php new file mode 100644 index 0000000..c828532 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/PublicMembers.php @@ -0,0 +1,119 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Organization; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Organization Public Members + * + * @since 3.2.0 + */ +class PublicMembers extends Api +{ + /** + * List an organization's public members. + * + * @param string $orgName The organization name. + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list(string $orgName, int $page = 1, int $limit = 10): ?array + { + // Build the request path. + $path = "/orgs/{$orgName}/public_members"; + + // Configure the request URI. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + + /** + * Check if a user is a public member of an organization. + * + * @param string $org The organization name. + * @param string $username The user's username. + * + * @return string|null + * @since 3.2.0 + **/ + public function check(string $org, string $username): ?string + { + // Build the request path. + $path = "/orgs/{$org}/public_members/{$username}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ), 204 + ); + } + + /** + * Publicize a user's membership. + * + * @param string $org The organization name. + * @param string $username The user's username. + * + * @return string|null + * @since 3.2.0 + **/ + public function publicize(string $org, string $username): ?string + { + // Build the request path. + $path = "/orgs/{$org}/public_members/{$username}"; + + // Send the put request. + return $this->response->get( + $this->http->put( + $this->uri->get($path), '' + ), 204 + ); + } + + /** + * Conceal a user's membership. + * + * @param string $org The organization name. + * @param string $username The user's username. + * + * @return string + * @since 3.2.0 + **/ + public function conceal(string $org, string $username): string + { + // Build the request path. + $path = "/orgs/{$org}/public_members/{$username}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Repository.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Repository.php new file mode 100644 index 0000000..18c5384 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Repository.php @@ -0,0 +1,145 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Organization; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Organization Repository + * + * @since 3.2.0 + */ +class Repository extends Api +{ + /** + * List an organization's repos. + * + * @param string $org The organization name. + * @param int $pageNumber The page number. + * @param int $pageSize The page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + string $org, + int $pageNumber = 1, + int $pageSize = 10 + ): ?array + { + // Build the request path. + $path = "/orgs/{$org}/repos"; + + // Configure the request URI. + $uri = $this->uri->get($path); + $uri->setVar('page', $pageNumber); + $uri->setVar('limit', $pageSize); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Create a repository in an organization. + * + * @param string $org The organization name. + * @param string $repoName The name of the repository. + * @param string|null $description The description of the repository (optional). + * @param bool|null $autoInit Whether the repository should be auto-initialized (optional). + * @param string|null $defaultBranch Default branch of the repository (optional). + * @param string|null $gitignores Gitignores to use (optional). + * @param string|null $issueLabels Label-set to use (optional). + * @param string|null $license License to use (optional). + * @param bool|null $private Whether the repository is private (optional). + * @param string|null $readme Readme of the repository to create (optional). + * @param bool|null $template Whether the repository is a template (optional). + * @param string|null $trustModel Trust model of the repository (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $org, + string $repoName, + ?string $description = null, + ?bool $autoInit = null, + ?string $defaultBranch = null, + ?string $gitignores = null, + ?string $issueLabels = null, + ?string $license = null, + ?bool $private = null, + ?string $readme = null, + ?bool $template = null, + ?string $trustModel = null + ): ?object + { + // Build the request path. + $path = "/orgs/{$org}/repos"; + + // Set the repository data. + $data = new \stdClass(); + $data->name = $repoName; + if ($description !== null) + { + $data->description = $description; + } + if ($autoInit !== null) + { + $data->auto_init = $autoInit; + } + if ($defaultBranch !== null) + { + $data->default_branch = $defaultBranch; + } + if ($gitignores !== null) + { + $data->gitignores = $gitignores; + } + if ($issueLabels !== null) + { + $data->issue_labels = $issueLabels; + } + if ($license !== null) + { + $data->license = $license; + } + if ($private !== null) + { + $data->private = $private; + } + if ($readme !== null) + { + $data->readme = $readme; + } + if ($template !== null) + { + $data->template = $template; + } + if ($trustModel !== null) + { + $data->trust_model = $trustModel; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Teams.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Teams.php new file mode 100644 index 0000000..46a27b0 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Teams.php @@ -0,0 +1,274 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Organization; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Organization Teams + * + * @since 3.2.0 + */ +class Teams extends Api +{ + /** + * List an organization's teams. + * + * @param string $organization The organization name. + * @param int $pageNumber The page number of results to return (1-based). + * @param int $pageSize The page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + string $organization, + int $pageNumber = 1, + int $pageSize = 10 + ): ?array + { + // Build the request path. + $path = "/orgs/{$organization}/teams"; + + // Get the URI object. + $uri = $this->uri->get($path); + + // Add the query parameters for page number and page size. + $uri->setVar('page', $pageNumber); + $uri->setVar('limit', $pageSize); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get a team. + * + * @param int $id The team ID. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(int $id): ?object + { + // Build the request path. + $path = "/teams/{$id}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Create a team. + * + * @param string $organization The organization name. + * @param string $name The name of the team. + * @param string $description The description of the team. + * @param array $repoNames An array of repository names for the team (optional). + * @param string $permission The team's permission level (optional). + * @param array $units Units for the team (optional). + * @param array $unitsMap Units map for the team (optional). + * @param bool $canCreateOrgRepo Can create organization repository flag (optional). + * @param bool $includesAllRepositories Includes all repositories flag (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $organization, + string $name, + string $description, + array $repoNames = [], + string $permission = 'read', + array $units = [], + array $unitsMap = [], + bool $canCreateOrgRepo = null, + bool $includesAllRepositories = null + ): ?object + { + // Build the request path. + $path = "/orgs/{$organization}/teams"; + + // Set the team data. + $data = new \stdClass(); + $data->name = $name; + $data->description = $description; + $data->permission = $permission; + + if (!empty($repoNames)) + { + $data->repo_names = $repoNames; + } + + if (!empty($units)) + { + $data->units = $units; + } + + if (!empty($unitsMap)) + { + $data->units_map = (object)$unitsMap; + } + + if ($canCreateOrgRepo !== null) + { + $data->can_create_org_repo = $canCreateOrgRepo; + } + + if ($includesAllRepositories !== null) + { + $data->includes_all_repositories = $includesAllRepositories; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ), 201 + ); + } + + /** + * Search for teams within an organization. + * + * @param string $organization The organization name. + * @param string $keywords The search keywords. + * @param bool $includeDesc Include search within team description (defaults to true). + * @param int $page The page number. + * @param int $limit The number of results per page. + * + * @return object|null + * @since 3.2.0 + **/ + public function search( + string $organization, + string $keywords, + bool $includeDesc = true, + int $page = 1, + int $limit = 10 + ): ?object + { + // Build the request path. + $path = "/orgs/{$organization}/teams/search"; + + // Configure the request URI. + $uri = $this->uri->get($path); + $uri->setVar('q', $keywords); + $uri->setVar('include_desc', $includeDesc); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Delete a team. + * + * @param int $id The team ID. + * + * @return string + * @since 3.2.0 + **/ + public function delete(int $id): string + { + // Build the request path. + $path = "/teams/{$id}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * Edit a team. + * + * @param int $teamId The team ID. + * @param string|null $teamName The team name (optional). + * @param string|null $teamDescription The team description (optional). + * @param string|null $teamPermission The team's permission level (optional). + * @param bool|null $canCreateOrgRepo Can team create organization repositories (optional). + * @param bool|null $includesAllRepositories Include all repositories (optional). + * @param array|null $units List of units (optional). + * @param array|null $unitsMap Units map (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function edit( + int $teamId, + ?string $teamName = null, + ?string $teamDescription = null, + ?string $teamPermission = null, + ?bool $canCreateOrgRepo = null, + ?bool $includesAllRepositories = null, + ?array $units = null, + ?array $unitsMap = null + ): ?object + { + // Build the request path. + $path = "/teams/{$teamId}"; + + // Set the team data. + $data = new \stdClass(); + if ($teamName !== null) + { + $data->name = $teamName; + } + if ($teamDescription !== null) + { + $data->description = $teamDescription; + } + if ($teamPermission !== null) + { + $data->permission = $teamPermission; + } + if ($canCreateOrgRepo !== null) + { + $data->can_create_org_repo = $canCreateOrgRepo; + } + if ($includesAllRepositories !== null) + { + $data->includes_all_repositories = $includesAllRepositories; + } + if ($units !== null) + { + $data->units = $units; + } + if ($unitsMap !== null) + { + $data->units_map = $unitsMap; + } + + // Send the patch request. + return $this->response->get( + $this->http->patch( + $this->uri->get($path), json_encode($data) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Teams/Members.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Teams/Members.php new file mode 100644 index 0000000..89e9145 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Teams/Members.php @@ -0,0 +1,124 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Organization\Teams; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Organization Teams Members + * + * @since 3.2.0 + */ +class Members extends Api +{ + /** + * List a team's members. + * + * @param int $teamId The team ID. + * @param int $pageNumber The page number of results to return (1-based). + * @param int $pageSize The page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + int $teamId, + int $pageNumber = 1, + int $pageSize = 10 + ): ?array + { + // Build the request path. + $path = "/teams/{$teamId}/members"; + + // Get the URI object. + $uri = $this->uri->get($path); + + // Add the query parameters for page number and page size. + $uri->setVar('page', $pageNumber); + $uri->setVar('limit', $pageSize); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * List a particular member of the team. + * + * @param int $id The team ID. + * @param string $username The user's username. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(int $id, string $username): ?object + { + // Build the request path. + $path = "/teams/{$id}/members/{$username}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Add a team member. + * + * @param int $id The team ID. + * @param string $username The user's username. + * + * @return string + * @since 3.2.0 + **/ + public function add(int $id, string $username): string + { + // Build the request path. + $path = "/teams/{$id}/members/{$username}"; + + // Send the put request. + return $this->response->get( + $this->http->put( + $this->uri->get($path), '' + ), 204, 'success' + ); + } + + /** + * Remove a team member. + * + * @param int $id The team ID. + * @param string $username The user's username. + * + * @return string + * @since 3.2.0 + **/ + public function remove(int $id, string $username): string + { + // Build the request path. + $path = "/teams/{$id}/members/{$username}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Teams/Repository.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Teams/Repository.php new file mode 100644 index 0000000..f485c09 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Teams/Repository.php @@ -0,0 +1,135 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Organization\Teams; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Organization Teams Repository + * + * @since 3.2.0 + */ +class Repository extends Api +{ + /** + * List a team's repos. + * + * @param int $teamId The team ID. + * @param int $pageNumber The page number of results to return (1-based). + * @param int $pageSize The page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + int $teamId, + int $pageNumber = 1, + int $pageSize = 10 + ): ?array + { + // Build the request path. + $path = "/teams/{$teamId}/repos"; + + // Get the URI object. + $uri = $this->uri->get($path); + + // Add the query parameters for page number and page size. + $uri->setVar('page', $pageNumber); + $uri->setVar('limit', $pageSize); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * List a particular repo of the team. + * + * @param int $teamId The team ID. + * @param string $organization The organization name. + * @param string $repository The repository name. + * + * @return object|null + * @since 3.2.0 + **/ + public function get( + int $teamId, + string $organization, + string $repository + ): ?object + { + // Build the request path. + $path = "/teams/{$teamId}/repos/{$organization}/{$repository}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Add a repository to a team. + * + * @param int $id The team ID. + * @param string $org The organization name. + * @param string $repo The repository name. + * + * @return string + * @since 3.2.0 + **/ + public function add( + int $id, + string $org, + string $repo + ): string + { + // Build the request path. + $path = "/teams/{$id}/repos/{$org}/{$repo}"; + + // Send the put request. + return $this->response->get( + $this->http->put( + $this->uri->get($path), '' + ),204, 'success' + ); + } + + /** + * Remove a repository from a team. + * + * @param int $id The team ID. + * @param string $org The organization name. + * @param string $repo The repository name. + * + * @return string + * @since 3.2.0 + **/ + public function remove(int $id, string $org, string $repo): string + { + // Build the request path. + $path = "/teams/{$id}/repos/{$org}/{$repo}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Teams/index.html b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Teams/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/Teams/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/User.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/User.php new file mode 100644 index 0000000..b59fe9b --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/User.php @@ -0,0 +1,111 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Organization; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Organization User + * + * @since 3.2.0 + */ +class User extends Api +{ + /** + * List the current user's organizations. + * + * @param int $pageNumber The page number of results to return (1-based). + * @param int $pageSize The page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + int $pageNumber = 1, + int $pageSize = 10 + ): ?array + { + // Build the request path. + $path = "/user/orgs"; + + // Get the URI object. + $uri = $this->uri->get($path); + + // Add the query parameters for page number and page size. + $uri->setVar('page', $pageNumber); + $uri->setVar('limit', $pageSize); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * List a user's organizations. + * + * @param string $username The user's username. + * @param int $pageNumber The page number of results to return (1-based). + * @param int $pageSize The page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function get( + string $username, + int $pageNumber = 1, + int $pageSize = 10 + ): ?array + { + // Build the request path. + $path = "/users/{$username}/orgs"; + + // Get the URI object. + $uri = $this->uri->get($path); + + // Add the query parameters for page number and page size. + $uri->setVar('page', $pageNumber); + $uri->setVar('limit', $pageSize); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get user permissions in an organization. + * + * @param string $username The user's username. + * @param string $org The organization name. + * + * @return object|null + * @since 3.2.0 + **/ + public function permissions(string $username, string $org): ?object + { + // Build the request path. + $path = "/users/{$username}/orgs/{$org}/permissions"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/index.html b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Organization/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Package.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Package.php new file mode 100644 index 0000000..8fb1ac2 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Package.php @@ -0,0 +1,84 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Package + * + * @since 3.2.0 + */ +class Package extends Api +{ + /** + * Gets a package. + * + * @param string $owner The owner of the package. + * @param string $type The type of the package. + * @param string $name The name of the package. + * @param string $version The version of the package. + * + * @return object|null + * @since 3.2.0 + **/ + public function get( + string $owner, + string $type, + string $name, + string $version + ): ?object + { + // Build the request path. + $path = "/packages/{$owner}/{$type}/{$name}/{$version}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Delete a package. + * + * @param string $owner The owner of the package. + * @param string $type The type of the package. + * @param string $name The name of the package. + * @param string $version The version of the package. + * + * @return string + * @since 3.2.0 + **/ + public function delete( + string $owner, + string $type, + string $name, + string $version + ): string + { + // Build the request path. + $path = "/packages/{$owner}/{$type}/{$name}/{$version}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Package/Files.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Package/Files.php new file mode 100644 index 0000000..c3851c0 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Package/Files.php @@ -0,0 +1,55 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Package; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Package Files + * + * @since 3.2.0 + */ +class Files extends Api +{ + /** + * Gets all files of a package. + * + * @param string $owner The owner of the package. + * @param string $type The type of the package. + * @param string $name The name of the package. + * @param string $version The version of the package. + * + * @return object|null + * @since 3.2.0 + **/ + public function get( + string $owner, + string $type, + string $name, + string $version + ): ?object + { + // Build the request path. + $path = "/packages/{$owner}/{$type}/{$name}/{$version}/files"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Package/Owner.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Package/Owner.php new file mode 100644 index 0000000..93960d1 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Package/Owner.php @@ -0,0 +1,68 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Package; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Package Owner + * + * @since 3.2.0 + */ +class Owner extends Api +{ + /** + * Gets all packages of an owner. + * + * @param string $owner The owner of the packages. + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * @param string|null $type Package type filter (optional). + * @param string|null $name Filter Name filter (optional). + * + * @return array|null + * @since 3.2.0 + **/ + public function get( + string $owner, + int $page = 1, + int $limit = 10, + ?string $type = null, + ?string $nameFilter = null + ): ?array + { + // Build the request path. + $path = "/packages/{$owner}"; + + // Configure the URI with query parameters. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + if ($type !== null) + { + $uri->setVar('type', $type); + } + if ($nameFilter !== null) + { + $uri->setVar('q', $nameFilter); + } + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Package/index.html b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Package/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Package/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository.php new file mode 100644 index 0000000..c1e7126 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository.php @@ -0,0 +1,439 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository + * + * @since 3.2.0 + */ +class Repository extends Api +{ + /** + * Search for repositories. + * + * @param string $q The search query. + * @param array $options Additional search options (optional). + * @param int $page The page number (optional). + * @param int $limit The number of items per page (optional). + * @param string $sort The sort order (optional). + * @param string $order The order direction (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function search( + string $q, + array $options = [], + int $page = 1, + int $limit = 10, + string $sort = 'alpha', + string $order = 'asc' + ): ?object + { + // Build the request path. + $path = '/repos/search'; + + // Create the URI object and set URL values. + $uri = $this->uri->get($path); + $uri->setVar('q', $q); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + $uri->setVar('sort', $sort); + $uri->setVar('order', $order); + + foreach ($options as $key => $val) + { + $uri->setVar($key, $val); + } + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(string $owner, string $repo): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Get a repository by owner and repo name. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * + * @return object|null + * @since 3.2.0 + **/ + public function id(string $owner, string $repo): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Delete a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * + * @return string + * @since 3.2.0 + **/ + public function delete(string $owner, string $repo): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * Edit a repository's properties. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string|null $description The repository description (optional). + * @param string|null $website The repository website (optional). + * @param bool|null $private Set the repository to private (optional). + * @param bool|null $hasIssues Set the repository to have issues (optional). + * @param bool|null $hasWiki Set the repository to have a wiki (optional). + * @param bool|null $hasProjects Set the repository to have projects (optional). + * @param bool|null $allowManualMerge Allow manual merge of pull requests (optional). + * @param bool|null $allowMergeCommits Allow merge commits for pull requests (optional). + * @param bool|null $allowRebase Allow rebase-merging pull requests (optional). + * @param bool|null $allowRebaseExplicit Allow rebase with explicit merge commits (optional). + * @param bool|null $allowRebaseUpdate Allow updating pull request branch by rebase (optional). + * @param bool|null $allowSquashMerge Allow squash-merging pull requests (optional). + * @param bool|null $archived + * @param bool|null $archived Set to true to archive this repository (optional). + * @param bool|null $autodetectManualMerge Enable AutodetectManualMerge (optional). + * @param string|null $defaultBranch Sets the default branch for this repository (optional). + * @param bool|null $defaultDeleteBranchAfterMerge Set to true to delete pr branch after merge by default (optional). + * @param string|null $defaultMergeStyle Set to a merge style to be used by this repository (optional). + * @param bool|null $enablePrune Enable prune - remove obsolete remote-tracking references (optional). + * @param object|null $externalTracker External tracker settings (optional). + * @param object|null $externalWiki External wiki settings (optional). + * @param bool|null $hasPullRequests Set the repository to have pull requests (optional). + * @param bool|null $ignoreWhitespaceConflicts Ignore whitespace for conflicts (optional). + * @param object|null $internalTracker Internal tracker settings (optional). + * @param string|null $mirrorInterval Set the mirror interval time (optional). + * @param bool|null $template Set to true to make this repository a template (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function edit( + string $owner, + string $repo, + ?string $description = null, + ?string $website = null, + ?bool $private = null, + ?bool $hasIssues = null, + ?bool $hasWiki = null, + ?bool $hasProjects = null, + ?bool $allowManualMerge = null, + ?bool $allowMergeCommits = null, + ?bool $allowRebase = null, + ?bool $allowRebaseExplicit = null, + ?bool $allowRebaseUpdate = null, + ?bool $allowSquashMerge = null, + ?bool $archived = null, + ?bool $autodetectManualMerge = null, + ?string $defaultBranch = null, + ?bool $defaultDeleteBranchAfterMerge = null, + ?string $defaultMergeStyle = null, + ?bool $enablePrune = null, + ?object $externalTracker = null, + ?object $externalWiki = null, + ?bool $hasPullRequests = null, + ?bool $ignoreWhitespaceConflicts = null, + ?object $internalTracker = null, + ?string $mirrorInterval = null, + ?bool $template = null + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}"; + + // Set the repository properties to update. + $data = new \stdClass(); + + if ($description !== null) + { + $data->description = $description; + } + + if ($website !== null) + { + $data->website = $website; + } + + if ($private !== null) + { + $data->private = $private; + } + + if ($hasIssues !== null) + { + $data->has_issues = $hasIssues; + } + + if ($hasWiki !== null) + { + $data->has_wiki = $hasWiki; + } + + if ($hasProjects !== null) + { + $data->has_projects = $hasProjects; + } + + // Add the additional properties to update. + if ($allowManualMerge !== null) + { + $data->allow_manual_merge = $allowManualMerge; + } + + if ($allowMergeCommits !== null) + { + $data->allow_merge_commits = $allowMergeCommits; + } + + if ($allowRebase !== null) + { + $data->allow_rebase = $allowRebase; + } + + if ($allowRebaseExplicit !== null) + { + $data->allow_rebase_explicit = $allowRebaseExplicit; + } + + if ($allowRebaseUpdate !== null) + { + $data->allow_rebase_update = $allowRebaseUpdate; + } + + if ($allowSquashMerge !== null) + { + $data->allow_squash_merge = $allowSquashMerge; + } + + if ($archived !== null) + { + $data->archived = $archived; + } + + if ($autodetectManualMerge !== null) + { + $data->autodetect_manual_merge = $autodetectManualMerge; + } + + if ($defaultBranch !== null) + { + $data->default_branch = $defaultBranch; + } + + if ($defaultDeleteBranchAfterMerge !== null) + { + $data->default_delete_branch_after_merge = $defaultDeleteBranchAfterMerge; + } + + if ($defaultMergeStyle !== + null) + { + $data->default_merge_style = $defaultMergeStyle; + } + + if ($enablePrune !== null) + { + $data->enable_prune = $enablePrune; + } + + if ($externalTracker !== null) + { + $data->external_tracker = $externalTracker; + } + + if ($externalWiki !== null) + { + $data->external_wiki = $externalWiki; + } + + if ($hasPullRequests !== null) + { + $data->has_pull_requests = $hasPullRequests; + } + + if ($ignoreWhitespaceConflicts !== null) + { + $data->ignore_whitespace_conflicts = $ignoreWhitespaceConflicts; + } + + if ($internalTracker !== null) + { + $data->internal_tracker = $internalTracker; + } + + if ($mirrorInterval !== null) + { + $data->mirror_interval = $mirrorInterval; + } + + if ($template !== null) + { + $data->template = $template; + } + + // Send the patch request. + return $this->response->get( + $this->http->patch( + $this->uri->get($path), json_encode($data) + ) + ); + } + + /** + * Create a repository. + * + * @param string $name The name of the new repository. + * @param string|null $description Optional. The description of the new repository. + * @param bool|null $private Optional. Set to true if the new repository should be private. + * @param bool|null $autoInit Optional. Set to true to initialize the repository with a README. + * @param string|null $defaultBranch Optional. Default branch of the repository (used when initializes and in template). + * @param string|null $gitignores Optional. The desired .gitignore templates to apply. + * @param string|null $issueLabels Optional. Label-Set to use. + * @param string|null $license Optional. The desired license for the repository. + * @param string|null $readme Optional. Readme of the repository to create. + * @param bool|null $template Optional. Set to true if the repository is a template. + * @param string|null $trustModel Optional. TrustModel of the repository. + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $name, + ?string $description = null, + ?bool $private = null, + ?bool $autoInit = null, + ?string $defaultBranch = null, + ?string $gitignores = null, + ?string $issueLabels = null, + ?string $license = null, + ?string $readme = null, + ?bool $template = null, + ?string $trustModel = null + ): ?object { + // Build the request path. + $path = "/user/repos"; + + // Set the repo data. + $data = new \stdClass(); + $data->name = $name; + + if ($description !== null) + { + $data->description = $description; + } + + if ($private !== null) + { + $data->private = $private; + } + + if ($autoInit !== null) + { + $data->auto_init = $autoInit; + } + + if ($defaultBranch !== null) + { + $data->default_branch = $defaultBranch; + } + + if ($gitignores !== null) + { + $data->gitignores = $gitignores; + } + + if ($issueLabels !== null) + { + $data->issue_labels = $issueLabels; + } + + if ($license !== null) + { + $data->license = $license; + } + + if ($readme !== null) + { + $data->readme = $readme; + } + + if ($template !== null) + { + $data->template = $template; + } + + if ($trustModel !== null) + { + $data->trust_model = $trustModel; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + json_encode($data) + ), 201 + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Archive.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Archive.php new file mode 100644 index 0000000..8cc3499 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Archive.php @@ -0,0 +1,58 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Archive + * + * @since 3.2.0 + */ +class Archive extends Api +{ + /** + * Get an archive of a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $archive The archive format, e.g., "zip" or "tar.gz". + * + * @return string + * @since 3.2.0 + **/ + public function get( + string $owner, + string $repo, + string $archive + ): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/archive/{$archive}"; + + // Set the required variables to the URI. + $uri = $this->uri->get($path); + $uri->setVar('owner', $owner); + $uri->setVar('repo', $repo); + $uri->setVar('archive', $archive); + + // Send the get request. + return $this->response->get( + $this->http->get($uri), 200, 'success' + ); + } + + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Assignees.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Assignees.php new file mode 100644 index 0000000..f6c8c75 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Assignees.php @@ -0,0 +1,51 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Assignees + * + * @since 3.2.0 + */ +class Assignees extends Api +{ + /** + * Return all users that have write access and can be assigned to issues. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * + * @return array|null + * @since 3.2.0 + **/ + public function get(string $owner, string $repo): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/assignees"; + + // Set the required variables to the URI. + $uri = $this->uri->get($path); + $uri->setVar('owner', $owner); + $uri->setVar('repo', $repo); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Attachments.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Attachments.php new file mode 100644 index 0000000..121da5d --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Attachments.php @@ -0,0 +1,196 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Attachments + * + * @since 3.2.0 + */ +class Attachments extends Api +{ + /** + * List release's attachments. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param int $releaseId The release ID. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + string $ownerName, + string $repoName, + int $releaseId + ): ?array + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/releases/{$releaseId}/assets"; + + // Retrieve the URI object with the path. + $uri = $this->uri->get($path); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Create a release attachment. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param int $releaseId The release ID. + * @param string $attachmentFile The attachment file content. + * @param string $attachmentName The attachment file name. + * @param string $contentType The attachment content type. + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $ownerName, + string $repoName, + int $releaseId, + string $attachmentFile, + string $attachmentName, + string $contentType + ): ?object + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/releases/{$releaseId}/assets"; + + // Retrieve the URI object with the path. + $uri = $this->uri->get($path); + + // Add the attachment name as a query parameter. + $uri->setVar('name', $attachmentName); + + // Set the request headers. + $headers = [ + "Content-Type: {$contentType}", + "Content-Disposition: attachment; filename={$attachmentName}" + ]; + + // Send the post request. + return $this->response->get( + $this->http->post( + $uri, $attachmentFile, $headers + ), 201 + ); + } + + /** + * Get a release attachment. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $id The release ID. + * @param int $attachmentId The attachment ID. + * + * @return object|null + * @since 3.2.0 + **/ + public function get( + string $owner, + string $repo, + int $id, + int $attachmentId + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/releases/{$id}/assets/{$attachmentId}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Delete a release attachment. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $id The release ID. + * @param int $attachmentId The attachment ID. + * + * @return string + * @since 3.2.0 + **/ + public function delete( + string $owner, + string $repo, + int $id, + int $attachmentId + ): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/releases/{$id}/assets/{$attachmentId}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * Edit a release attachment. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $id The release ID. + * @param int $attachmentId The attachment ID. + * @param string|null $name The new name of the attachment (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function edit( + string $owner, + string $repo, + int $id, + int $attachmentId, + ?string $name = null + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/releases/{$id}/assets/{$attachmentId}"; + + // Set the attachment data + $data = new \stdClass(); + + if ($name !== null) + { + $data->name = $name; + } + + // Send the patch request. + return $this->response->get( + $this->http->patch( + $this->uri->get($path), json_encode($data) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Branch.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Branch.php new file mode 100644 index 0000000..0936bbe --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Branch.php @@ -0,0 +1,148 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Branch + * + * @since 3.2.0 + */ +class Branch extends Api +{ + /** + * List a repository's branches. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + string $owner, + string $repo, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/branches"; + + // Set the required variables to the URI. + $uri = $this->uri->get($path); + $uri->setVar('owner', $owner); + $uri->setVar('repo', $repo); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Create a branch. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $branch_name The name of the new branch. + * @param string $old_branch The name of the existing branch from which to create the new branch. + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $owner, + string $repo, + string $branch_name, + string $old_branch + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/branches"; + + // Set the branch data. + $data = new \stdClass(); + $data->branch_name = $branch_name; + $data->old_branch = $old_branch; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ), 201 + ); + } + + /** + * Retrieve a specific branch from a repository, including its effective branch protection. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $branch The branch name. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(string $owner, string $repo, string $branch): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/branches/{$branch}"; + + // Set the required variables to the URI. + $uri = $this->uri->get($path); + $uri->setVar('owner', $owner); + $uri->setVar('repo', $repo); + $uri->setVar('branch', $branch); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Delete a specific branch from a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $branch The branch name. + * + * @return string + * @since 3.2.0 + **/ + public function delete( + string $owner, + string $repo, + string $branch + ): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/branches/{$branch}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Branch/Protection.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Branch/Protection.php new file mode 100644 index 0000000..946bce2 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Branch/Protection.php @@ -0,0 +1,380 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository\Branch; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Branch Protection + * + * @since 3.2.0 + */ +class Protection extends Api +{ + /** + * List branch protections for a repository. + * + * @param string $ownerName The owner name. + * @param string $repositoryName The repository name. + * + * @return array|null + * @since 3.2.0 + **/ + public function list(string $ownerName, string $repositoryName): ?array + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repositoryName}/branch_protections"; + + // Get the URI with the path. + $uri = $this->uri->get($path); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Create a branch protection for a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $branchName The name of the branch to protect. + * @param array $approvalsWhitelistUsernames An array of usernames that can approve. + * @param array $approvalsWhitelistTeams An array of team names that can approve. + * @param bool $blockOnOfficialReviewRequests Enable/disable blocking on official review requests (optional, default false). + * @param bool $blockOnOutdatedBranch Enable/disable blocking on outdated branch (optional, default false). + * @param bool $blockOnRejectedReviews Enable/disable blocking on rejected reviews (optional, default false). + * @param bool $dismissStaleApprovals Enable/disable dismissing stale approvals (optional, default false). + * @param bool $enableApprovalsWhitelist Enable/disable approvals whitelist (optional, default false). + * @param bool $enableMergeWhitelist Enable/disable merge whitelist (optional, default false). + * @param bool $enablePush Enable/disable push (optional, default true). + * @param bool $enablePushWhitelist Enable/disable push whitelist (optional, default false). + * @param bool $enableStatusCheck Enable/disable status check (optional, default false). + * @param array $mergeWhitelistUsernames An array of usernames that can merge (optional). + * @param array $mergeWhitelistTeams An array of team names that can merge (optional). + * @param string $protectedFilePatterns Protected file patterns (optional). + * @param bool $pushWhitelistDeployKeys Enable/disable push whitelist deploy keys (optional, default false). + * @param array $pushWhitelistUsernames An array of usernames that can push (optional). + * @param array $pushWhitelistTeams An array of team names that can push (optional). + * @param bool $requireSignedCommits Enable/disable requiring signed commits (optional, default false). + * @param int $requiredApprovals Number of required approvals (optional, default 0). + * @param array $statusCheckContexts An array of status check contexts (optional). + * @param string $unprotectedFilePatterns Unprotected file patterns (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $owner, + string $repo, + string $branchName, + array $approvalsWhitelistUsernames, + array $approvalsWhitelistTeams, + bool $blockOnOfficialReviewRequests = false, + bool $blockOnOutdatedBranch = false, + bool $blockOnRejectedReviews = false, + bool $dismissStaleApprovals = false, + bool $enableApprovalsWhitelist = false, + bool $enableMergeWhitelist = false, + bool $enablePush = true, + bool $enablePushWhitelist = false, + bool $enableStatusCheck = false, + array $mergeWhitelistUsernames = [], + array $mergeWhitelistTeams = [], + string $protectedFilePatterns = '', + bool $pushWhitelistDeployKeys = false, + array $pushWhitelistUsernames = [], + array $pushWhitelistTeams = [], + bool $requireSignedCommits = false, + int $requiredApprovals = 0, + array $statusCheckContexts = [], + string $unprotectedFilePatterns = '' + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/branch_protections"; + + // Set the branch protection data. + $data = new \stdClass(); + $data->branch_name = $branchName; + $data->approvals_whitelist_usernames = $approvalsWhitelistUsernames; + $data->approvals_whitelist_teams = $approvalsWhitelistTeams; + $data->block_on_official_review_requests = $blockOnOfficialReviewRequests; + $data->block_on_outdated_branch = $blockOnOutdatedBranch; + $data->block_on_rejected_reviews = $blockOnRejectedReviews; + $data->dismiss_stale_approvals = $dismissStaleApprovals; + $data->enable_approvals_whitelist = $enableApprovalsWhitelist; + $data->enable_merge_whitelist = $enableMergeWhitelist; + $data->enable_push = $enablePush; + $data->enable_push_whitelist = $enablePushWhitelist; + $data->enable_status_check = $enableStatusCheck; + $data->merge_whitelist_usernames = $mergeWhitelistUsernames; + $data->merge_whitelist_teams = $mergeWhitelistTeams; + $data->protected_file_patterns = $protectedFilePatterns; + $data->push_whitelist_deploy_keys = $pushWhitelistDeployKeys; + $data->push_whitelist_usernames = $pushWhitelistUsernames; + $data->push_whitelist_teams = $pushWhitelistTeams; + $data->require_signed_commits = $requireSignedCommits; + $data->required_approvals = $requiredApprovals; + $data->status_check_contexts = $statusCheckContexts; + $data->unprotected_file_patterns = $unprotectedFilePatterns; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ), 201 + ); + } + + /** + * Get a specific branch protection for the repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $branchName The branch protection name. + * + * @return object|null + * @since 3.2.0 + **/ + public function get( + string $owner, + string $repo, + string $branchName + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/branch_protections/{$branchName}"; + + // Get the URI object with the given path. + $uri = $this->uri->get($path); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Delete a specific branch protection for the repository. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param string $branchName The branch protection name. + * + * @return string + * @since 3.2.0 + **/ + public function delete( + string $ownerName, + string $repoName, + string $branchName + ): string + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/branch_protections/{$branchName}"; + + // Set the required variables in the URI. + $this->uri->setVar('owner', $ownerName); + $this->uri->setVar('repo', $repoName); + $this->uri->setVar('name', $branchName); + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * Edit a branch protection for a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $name The branch protection name. + * @param array|null $approvalsWhitelistTeams An array of team names that are allowed to approve (optional). + * @param array|null $approvalsWhitelistUsernames An array of usernames that are allowed to approve (optional). + * @param bool|null $blockOnOfficialReviewRequests Block when official review requests are pending (optional). + * @param bool|null $blockOnOutdatedBranch Block when the branch is outdated (optional). + * @param bool|null $blockOnRejectedReviews Block when reviews are rejected (optional). + * @param bool|null $dismissStaleApprovals Dismiss stale approvals when new commits are pushed (optional). + * @param bool|null $enableApprovalsWhitelist Enable/disable approvals whitelist (optional). + * @param bool|null $enableMergeWhitelist Enable/disable merge whitelist (optional). + * @param bool|null $enablePush Enable/disable push (optional). + * @param bool|null $enablePushWhitelist Enable/disable push whitelist (optional). + * @param bool|null $enableStatusCheck Enable/disable status check (optional). + * @param array|null $mergeWhitelistTeams An array of team names that are allowed to merge (optional). + * @param array|null $mergeWhitelistUsernames An array of usernames that are allowed to merge (optional). + * @param string|null $protectedFilePatterns A string pattern for protected files (optional). + * @param bool|null $pushWhitelistDeployKeys Enable/disable push whitelist for deploy keys (optional). + * @param array|null $pushWhitelistTeams An array of team names that are allowed to push (optional). + * @param array|null $pushWhitelistUsernames An array of usernames that are allowed to push (optional). + * @param bool|null $requireSignedCommits Require signed commits (optional). + * @param int|null $requiredApprovals Number of required approvals (optional). + * @param array|null $statusCheckContexts An array of status check contexts (optional). + * @param string|null $unprotectedFilePatterns A string pattern for unprotected files (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function edit( + string $owner, + string $repo, + string $name, + ?array $approvalsWhitelistTeams = null, + ?array $approvalsWhitelistUsernames = null, + ?bool $blockOnOfficialReviewRequests = null, + ?bool $blockOnOutdatedBranch = null, + ?bool $blockOnRejectedReviews = null, + ?bool $dismissStaleApprovals = null, + ?bool $enableApprovalsWhitelist = null, + ?bool $enableMergeWhitelist = null, + ?bool $enablePush = null, + ?bool $enablePushWhitelist = null, + ?bool $enableStatusCheck = null, + ?array $mergeWhitelistTeams = null, + ?array $mergeWhitelistUsernames = null, + ?string $protectedFilePatterns = null, + ?bool $pushWhitelistDeployKeys = null, + ?array $pushWhitelistTeams = null, + ?array $pushWhitelistUsernames = null, + ?bool $requireSignedCommits = null, + ?int $requiredApprovals = null, + ?array $statusCheckContexts = null, + ?string $unprotectedFilePatterns = null + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/branch_protections/{$name}"; + + // Set the branch protection data. + $data = new \stdClass(); + + if ($approvalsWhitelistTeams !== null) + { + $data->approvals_whitelist_teams = $approvalsWhitelistTeams; + } + + if ($approvalsWhitelistUsernames !== null) + { + $data->approvals_whitelist_usernames = $approvalsWhitelistUsernames; + } + + if ($blockOnOfficialReviewRequests !== null) + { + $data->block_on_official_review_requests = $blockOnOfficialReviewRequests; + } + + if ($blockOnOutdatedBranch !== null) + { + $data->block_on_outdated_branch = $blockOnOutdatedBranch; + } + + if ($blockOnRejectedReviews !== null) + { + $data->block_on_rejected_reviews = $blockOnRejectedReviews; + } + + if ($dismissStaleApprovals !== null) + { + $data->dismiss_stale_approvals = $dismissStaleApprovals; + } + + if ($enableApprovalsWhitelist !== null) + { + $data->enable_approvals_whitelist = $enableApprovalsWhitelist; + } + + if ($enableMergeWhitelist !== null) + { + $data->enable_merge_whitelist = $enableMergeWhitelist; + } + + if ($enablePush !== null) + { + $data->enable_push = $enablePush; + } + + if ($enablePushWhitelist !== null) + { + $data->enable_push_whitelist = $enablePushWhitelist; + } + + if ($enableStatusCheck !== null) + { + $data->enable_status_check = $enableStatusCheck; + } + + if ($mergeWhitelistTeams !== null) + { + $data->merge_whitelist_teams = $mergeWhitelistTeams; + } + + if ($mergeWhitelistUsernames !== null) + { + $data->merge_whitelist_usernames = $mergeWhitelistUsernames; + } + + if ($protectedFilePatterns !== null) + { + $data->protected_file_patterns = $protectedFilePatterns; + } + + if ($pushWhitelistDeployKeys !== null) + { + $data->push_whitelist_deploy_keys = $pushWhitelistDeployKeys; + } + + if ($pushWhitelistTeams !== null) + { + $data->push_whitelist_teams = $pushWhitelistTeams; + } + + if ($pushWhitelistUsernames !== null) + { + $data->push_whitelist_usernames = $pushWhitelistUsernames; + } + + if ($requireSignedCommits !== null) + { + $data->require_signed_commits = $requireSignedCommits; + } + + if ($requiredApprovals !== null) + { + $data->required_approvals = $requiredApprovals; + } + + if ($statusCheckContexts !== null) + { + $data->status_check_contexts = $statusCheckContexts; + } + + if ($unprotectedFilePatterns !== null) + { + $data->unprotected_file_patterns = $unprotectedFilePatterns; + } + + // Send the patch request. + return $this->response->get( + $this->http->patch( + $this->uri->get($path), json_encode($data) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Branch/index.html b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Branch/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Branch/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Collaborator.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Collaborator.php new file mode 100644 index 0000000..38ee512 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Collaborator.php @@ -0,0 +1,175 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Collaborator + * + * @since 3.2.0 + */ +class Collaborator extends Api +{ + /** + * List a repository's collaborators. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $page The page number of results to return (1-based). + * @param int $limit The page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list(string $owner, string $repo, int $page = 1, int $limit = 10): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/collaborators"; + + // Get the URI object for the path. + $uri = $this->uri->get($path); + + // Set the page and limit variables. + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Check if a user is a collaborator of a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $collaborator The collaborator username. + * + * @return string + * @since 3.2.0 + **/ + public function check( + string $owner, + string $repo, + string $collaborator + ): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/collaborators/{$collaborator}"; + + // Get the URI object for the path. + $uri = $this->uri->get($path); + + // Send the get request. + return $this->response->get( + $this->http->get($uri), 204, 'success' + ); + } + + /** + * Add a collaborator to a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $collaborator The collaborator username. + * @param string $permission The permission level for the collaborator (optional). + * + * @return string + * @since 3.2.0 + **/ + public function add( + string $owner, + string $repo, + string $collaborator, + string $permission = null + ): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/collaborators/{$collaborator}"; + + // Get the URI object for the path. + $uri = $this->uri->get($path); + + // Prepare the request body. + $body = new stdClass(); + if ($permission !== null) { + $body->permission = $permission; + } + $bodyJson = json_encode($body); + + // Send the put request. + return $this->response->get( + $this->http->put($uri, $bodyJson), 204, 'success' + ); + } + + /** + * Delete a collaborator from a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $collaborator The collaborator username. + * + * @return string + * @since 3.2.0 + **/ + public function delete( + string $owner, + string $repo, + string $collaborator + ): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/collaborators/{$collaborator}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * Get repository permissions for a user. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $collaborator The collaborator username. + * + * @return object|null + * @since 3.2.0 + **/ + public function permission( + string $owner, + string $repo, + string $collaborator + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/collaborators/{$collaborator}/permission"; + + // Get the URI object for the path. + $uri = $this->uri->get($path); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Commits.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Commits.php new file mode 100644 index 0000000..d8142c2 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Commits.php @@ -0,0 +1,225 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Commit + * + * @since 3.2.0 + */ +class Commits extends Api +{ + /** + * Get a list of all commits from a repository. + * + * @param string $owner The owner of the repo. + * @param string $repo The name of the repo. + * @param string|null $sha SHA or branch to start listing commits from (usually 'master'). + * @param string|null $path Filepath of a file/dir. + * @param bool|null $stat Include diff stats for every commit (disable for speedup, default 'true'). + * @param int|null $page Page number of results to return (1-based). + * @param int|null $limit Page size of results (ignored if used with 'path'). + * + * @return array|null + * @since 3.2.0 + */ + public function getList( + string $owner, + string $repo, + ?string $sha = null, + ?string $path = null, + ?bool $stat = true, + ?int $page = 1, + ?int $limit = 10 + ): ?object + { + // Build the request path. + $uriPath = "/repos/{$owner}/{$repo}/commits"; + + // Set query parameters. + $uri = $this->uri->get($uriPath); + + if ($sha !== null) + { + $uri->setVar('sha', $sha); + } + + if ($path !== null) + { + $uri->setVar('path', $path); + } + + if ($stat !== null) + { + $uri->setVar('stat', $stat ? 'true' : 'false'); + } + + if ($page !== null) + { + $uri->setVar('page', $page); + } + + if ($limit !== null) + { + $uri->setVar('limit', $limit); + } + + // Send the GET request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get a single commit from a repository. + * + * @param string $owner The owner of the repo. + * @param string $repo The name of the repo. + * @param string $sha A git ref or commit sha. + * + * @return object|null + * @since 3.2.0 + */ + public function getCommit(string $owner, string $repo, string $sha): ?object + { + // Build the request path. + $uriPath = "/repos/{$owner}/{$repo}/git/commits/{$sha}"; + + // Send the GET request. + return $this->response->get( + $this->http->get( + $this->uri->get($uriPath) + ) + ); + } + + /** + * Get a commit's combined status, by branch/tag/commit reference. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $ref The branch, tag, or commit reference. + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return object|null + * @since 3.2.0 + **/ + public function status( + string $owner, + string $repo, + string $ref, + int $page = 1, + int $limit = 10 + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/commits/{$ref}/status"; + + // Set up the URI with the required parameters. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get a commit's statuses, by branch/tag/commit reference. + * + * @param string $owner The owner of the repository. + * @param string $repo The name of the repository. + * @param string $ref The branch, tag, or commit reference. + * @param string $sort The type of sort. Available values: oldest, recentupdate, leastupdate, leastindex, highestindex. + * @param string $state The type of state. Available values: pending, success, error, failure, warning. + * @param int $page The page number of results to return (1-based). Default value: 1. + * @param int $limit The page size of results. Default value: 10. + * + * @return array|null + * @since 3.2.0 + */ + public function statuses( + string $owner, + string $repo, + string $ref, + string $sort = null, + string $state = null, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/commits/{$ref}/statuses"; + + // Add query parameters to the URI. + $uri = $this->uri->get($path); + + if ($sort !== null) + { + $uri->setVar('sort', $sort); + } + + if ($state !== null) + { + $uri->setVar('state', $state); + } + + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the GET request. + $response = $this->http->get($uri); + return $this->response->get($response); + } + + /** + * Get a commit's diff or patch. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $sha The SHA hash of the commit. + * @param string $diffType The diff type, either 'diff' or 'patch'. + * + * @return string + * @since 3.2.0 + **/ + public function diff( + string $owner, + string $repo, + string $sha, + string $diffType + ): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/git/commits/{$sha}"; + + // Set the diffType as a variable in the URI. + $this->uri->setVar('diffType', $diffType); + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Contents.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Contents.php new file mode 100644 index 0000000..982403c --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Contents.php @@ -0,0 +1,509 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Contents + * + * @since 3.2.0 + */ +class Contents extends Api +{ + /** + * Get a file from a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $filepath The file path. + * @param string|null $ref Optional. The name of the commit/branch/tag. + * Default the repository's default branch (usually master). + * + * @return mixed + * @since 3.2.0 + **/ + public function get(string $owner, string $repo, string $filepath, ?string $ref = null) + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/raw/{$filepath}"; + + // Get the URI with the specified path. + $uri = $this->uri->get($path); + + // Add the ref parameter if provided. + if ($ref !== null) + { + $uri->setVar('ref', $ref); + } + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get the metadata and contents (if a file) of an entry in a repository, + * or a list of entries if a directory. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $filepath The file or directory path. + * @param string|null $ref Optional. The name of the commit/branch/tag. + * Default the repository's default branch (usually master). + * + * @return object|null + * @since 3.2.0 + **/ + public function metadata(string $owner, string $repo, string $filepath, ?string $ref = null): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/contents/{$filepath}"; + + // Get the URI with the specified path. + $uri = $this->uri->get($path); + + // Add the ref parameter if provided. + if ($ref !== null) + { + $uri->setVar('ref', $ref); + } + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Create a file in a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $filepath The file path. + * @param string $content The file content. + * @param string $message The commit message. + * @param string $branch The branch name. Defaults to the repository's default branch. + * @param string|null $authorName The author's name. + * @param string|null $authorEmail The author's email. + * @param string|null $committerName The committer's name. + * @param string|null $committerEmail The committer's email. + * @param bool|null $newBranch Whether to create a new branch. Defaults to false. + * @param string|null $authorDate The author's date. + * @param string|null $committerDate The committer's date. + * @param bool|null $signoff Add a Signed-off-by trailer. Defaults to null. + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $owner, + string $repo, + string $filepath, + string $content, + string $message, + string $branch = 'master', + ?string $authorName = null, + ?string $authorEmail = null, + ?string $committerName = null, + ?string $committerEmail = null, + ?bool $newBranch = false, + ?string $authorDate = null, + ?string $committerDate = null, + ?bool $signoff = null + ): ?object { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/contents/{$filepath}"; + + // Set the post data + $data = new \stdClass(); + $data->content = base64_encode($content); + $data->message = $message; + $data->branch = $branch; + + if ($authorName !== null || $authorEmail !== null) + { + $data->author = new \stdClass(); + if ($authorName !== null) + { + $data->author->name = $authorName; + } + if ($authorEmail !== null) + { + $data->author->email = $authorEmail; + } + } + + if ($committerName !== null || $committerEmail !== null) + { + $data->committer = new \stdClass(); + if ($committerName !== null) + { + $data->committer->name = $committerName; + } + if ($committerEmail !== null) + { + $data->committer->email = $committerEmail; + } + } + + if ($newBranch !== null) + { + $data->new_branch = $newBranch; + } + + if ($authorDate !== null || $committerDate !== null) + { + $data->dates = new \stdClass(); + if ($authorDate !== null) + { + $data->dates->author = $authorDate; + } + if ($committerDate !== null) + { + $data->dates->committer = $committerDate; + } + } + + if ($signoff !== null) + { + $data->signoff = $signoff; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ), 201 + ); + } + + /** + * Get the metadata of all the entries of the root directory. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string|null $ref The name of the commit/branch/tag. Default the repository's default branch (usually master). + * + * @return array|null + * @since 3.2.0 + **/ + public function root(string $owner, string $repo, ?string $ref = null): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/contents"; + + // Add the 'ref' parameter if it's provided. + if ($ref !== null) + { + $this->uri->setVar('ref', $ref); + } + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Update a file in a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $filepath The file path. + * @param string $content The file content. + * @param string $message The commit message. + * @param string $branch The branch name. Defaults to the repository's default branch. + * @param string $sha The blob SHA of the file. + * @param string|null $authorName The author name. Defaults to the authenticated user. + * @param string|null $authorEmail The author email. Defaults to the authenticated user. + * @param string|null $committerName The committer name. Defaults to the authenticated user. + * @param string|null $committerEmail The committer email. Defaults to the authenticated user. + * @param string|null $authorDate The author date. + * @param string|null $committerDate The committer date. + * @param string|null $fromPath The original file path to move/rename. + * @param string|null $newBranch The new branch to create from the specified branch. + * @param bool|null $signoff Add a Signed-off-by trailer. + * + * @return object|null + * @since 3.2.0 + **/ + public function update( + string $owner, + string $repo, + string $filepath, + string $content, + string $message, + string $branch = 'master', + string $sha, + ?string $authorName = null, + ?string $authorEmail = null, + ?string $committerName = null, + ?string $committerEmail = null, + ?string $authorDate = null, + ?string $committerDate = null, + ?string $fromPath = null, + ?string $newBranch = null, + ?bool $signoff = null + ): ?object { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/contents/{$filepath}"; + + // Set the file data. + $data = new \stdClass(); + $data->content = base64_encode($content); + $data->message = $message; + $data->branch = $branch; + $data->sha = $sha; + + if ($authorName !== null || $authorEmail !== null) + { + $data->author = new \stdClass(); + + if ($authorName !== null) + { + $data->author->name = $authorName; + } + + if ($authorEmail !== null) + { + $data->author->email = $authorEmail; + } + } + + if ($committerName !== null || $committerEmail !== null) + { + $data->committer = new \stdClass(); + + if ($committerName !== null) + { + $data->committer->name = $committerName; + } + + if ($committerEmail !== null) + { + $data->committer->email = $committerEmail; + } + } + + if ($authorDate !== null || $committerDate !== null) + { + $data->dates = new \stdClass(); + + if ($authorDate !== null) + { + $data->dates->author = $authorDate; + } + + if ($committerDate !== null) + { + $data->dates->committer = $committerDate; + } + } + + if ($fromPath !== null) + { + $data->from_path = $fromPath; + } + + if ($newBranch !== null) + { + $data->new_branch = $newBranch; + } + + if ($signoff !== null) + { + $data->signoff = $signoff; + } + + // Send the put request. + return $this->response->get( + $this->http->put( + $this->uri->get($path), + json_encode($data) + ) + ); + } + + /** + * Delete a file in a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $filepath The file path. + * @param string $message The commit message. + * @param string $branch The branch name (optional). + * @param string $sha The blob SHA of the file. + * @param string $authorName The author name (optional). + * @param string $authorEmail The author email (optional). + * @param string $committerName The committer name (optional). + * @param string $committerEmail The committer email (optional). + * @param string $authorDate The author date (optional). + * @param string $committerDate The committer date (optional). + * @param string $newBranch The new branch name (optional). + * @param bool $signoff Add a Signed-off-by trailer (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function delete( + string $owner, + string $repo, + string $filepath, + string $message, + string $sha, + ?string $branch = null, + ?string $authorName = null, + ?string $authorEmail = null, + ?string $committerName = null, + ?string $committerEmail = null, + ?string $authorDate = null, + ?string $committerDate = null, + ?string $newBranch = null, + ?bool $signoff = null + ): ?object { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/contents/{$filepath}"; + + // Set the file data. + $data = new \stdClass(); + $data->message = $message; + $data->sha = $sha; + + if ($branch !== null) { + $data->branch = $branch; + } + + if ($authorName !== null || $authorEmail !== null) + { + $data->author = new \stdClass(); + + if ($authorName !== null) + { + $data->author->name = $authorName; + } + + if ($authorEmail !== null) + { + $data->author->email = $authorEmail; + } + } + + if ($committerName !== null || $committerEmail !== null) + { + $data->committer = new \stdClass(); + + if ($committerName !== null) + { + $data->committer->name = $committerName; + } + + if ($committerEmail !== null) + { + $data->committer->email = $committerEmail; + } + } + + if ($authorDate !== null || $committerDate !== null) + { + $data->dates = new \stdClass(); + + if ($authorDate !== null) + { + $data->dates->author = $authorDate; + } + + if ($committerDate !== null) + { + $data->dates->committer = $committerDate; + } + } + + if ($newBranch !== null) + { + $data->new_branch = $newBranch; + } + + if ($signoff !== null) + { + $data->signoff = $signoff; + } + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path), + json_encode($data) + ) + ); + } + + /** + * Get the EditorConfig definitions of a file in a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $filepath The file path. + * @param string $ref The name of the commit/branch/tag. + * + * @return string|null + * @since 3.2.0 + **/ + public function editor(string $owner, string $repo, string $filepath, string $ref = null): ?string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/editorconfig/{$filepath}"; + + // Set the request parameters. + $uri = $this->uri->get($path); + + if ($ref !== null) + { + $uri->setVar('ref', $ref); + } + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get the blob of a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $sha The SHA hash of the blob. + * + * @return object|null + * @since 3.2.0 + **/ + public function blob(string $owner, string $repo, string $sha): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/git/blobs/{$sha}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Forks.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Forks.php new file mode 100644 index 0000000..224e286 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Forks.php @@ -0,0 +1,102 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Forks + * + * @since 3.2.0 + */ +class Forks extends Api +{ + /** + * List a repository's forks. + * + * @param string $owner The owner of the repo. + * @param string $repo The name of the repo. + * @param int $page The page number of results to return (1-based). + * @param int $limit The page size of results. + * + * @return array|null + * @since 3.2.0 + */ + public function listForks( + string $owner, + string $repo, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $uriPath = "/repos/{$owner}/{$repo}/forks"; + + // Set the query parameters. + $uri = $this->uri->get($uriPath); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Fork a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $forkName The name of the forked repository (optional). + * @param string $organization The organization name (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function repo( + string $owner, + string $repo, + string $forkName = '', + string $organization = '' + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/forks"; + + // Set the fork data. + $data = new \stdClass(); + + if (!empty($forkName)) + { + $data->name = $forkName; + } + + if (!empty($organization)) + { + $data->organization = $organization; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + json_encode($data) + ), 202 + ); + } + + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Gpg.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Gpg.php new file mode 100644 index 0000000..0a6c317 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Gpg.php @@ -0,0 +1,48 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Gpg + * + * @since 3.2.0 + */ +class Gpg extends Api +{ + /** + * Get signing-key.gpg for a given repository. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * + * @return string + * @since 3.2.0 + **/ + public function get(string $ownerName, string $repoName): string + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/signing-key.gpg"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Hooks.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Hooks.php new file mode 100644 index 0000000..eadb2e6 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Hooks.php @@ -0,0 +1,214 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Hooks + * + * @since 3.2.0 + */ +class Hooks extends Api +{ + /** + * List the hooks in a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $page The page number of results to return (1-based). + * @param int $limit The page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + string $owner, + string $repo, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/hooks"; + + // Set up the URI with query parameters. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Create a hook in a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $type The hook type. + * @param array $config The hook configuration. + * @param bool $active The hook's active status (optional, default: false). + * @param array|null $events The events for the hook (optional). + * @param string $branchFilter The branch filter (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $owner, + string $repo, + string $type, + array $config, + string $type, + array $config, + bool $active = false, + ?array $events = null, + string $branchFilter = '' + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/hooks"; + + // Set the hook data. + $data = new \stdClass(); + $data->type = $type; + $data->config = (object) $config; + $data->active = $active; + + if ($events !== null) + { + $data->events = $events; + } + + if (!empty($branchFilter)) + { + $data->branch_filter = $branchFilter; + } + + // Send the request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ), 201 + ); + } + + /** + * Get a hook. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $hookId The hook ID. + * + * @return object|null + * @since 3.2.0 + **/ + public function get( + string $owner, + string $repo, + int $hookId + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/hooks/{$hookId}"; + + // Get the URI for the request path. + $uri = $this->uri->get($path); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Edit a hook in a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $id The hook ID. + * @param array $config The hook configuration. + * @param array $events The events to trigger the hook. + * @param bool $active Whether the hook is active. + * + * @return object|null + * @since 3.2.0 + **/ + public function edit( + string $owner, + string $repo, + int $id, + array $config, + array $events, + bool $active + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/hooks/{$id}"; + + // Set the hook data. + $data = new \stdClass(); + $data->config = $config; + $data->events = $events; + $data->active = $active; + + // Send the PATCH request. + return $this->response->get( + $this->http->patch( + $this->uri->get($path), + json_encode($data) + ) + ); + } + + /** + * Test a push webhook. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $hookId The hook ID. + * @param string $ref The name of the commit/branch/tag (optional). + * + * @return string + * @since 3.2.0 + **/ + public function test( + string $owner, + string $repo, + int $hookId, + string $ref = '' + ): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/hooks/{$hookId}/tests"; + + // Get the URI for the request path. + $uri = $this->uri->get($path); + + if (!empty($ref)) + { + $uri->setVar('ref', $ref); + } + + // Send the POST request. + return $this->response->get( + $this->http->post($uri), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Hooks/Git.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Hooks/Git.php new file mode 100644 index 0000000..0b0a849 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Hooks/Git.php @@ -0,0 +1,137 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository\Hooks; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Hooks Git + * + * @since 3.2.0 + */ +class Git extends Api +{ + /** + * List the Git hooks in a repository. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * + * @return array|null + * @since 3.2.0 + **/ + public function list(string $ownerName, string $repoName): ?array + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/hooks/git"; + + // Get the URI object with the path. + $uri = $this->uri->get($path); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get a Git hook. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param int $hookId The Git hook ID. + * + * @return object|null + * @since 3.2.0 + **/ + public function get( + string $ownerName, + string $repoName, + int $hookId + ): ?object + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/hooks/git/{$hookId}"; + + // Get the URI object with the path. + $uri = $this->uri->get($path); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Delete a Git hook in a repository. + * + * @param string $ownerName The owner name. + * @param string $repositoryName The repository name. + * @param string $hookId The Git hook ID. + * + * @return string + * @since 3.2.0 + **/ + public function delete( + string $ownerName, + string $repositoryName, + string $hookId + ): string + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repositoryName}/hooks/git/{$hookId}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * Edit a Git hook in a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $hookId The Git hook ID. + * @param array $hookOptions The hook configuration. + * + * @return object|null + * @since 3.2.0 + **/ + public function edit( + string $owner, + string $repo, + string $hookId, + array $hookOptions + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/hooks/git/{$hookId}"; + + // Set the hook data. + $data = new \stdClass(); + $data->config = (object) $hookOptions; + + // Send the PATCH request. + return $this->response->get( + $this->http->patch( + $this->uri->get($path), json_encode($data) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Hooks/index.html b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Hooks/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Hooks/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Keys.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Keys.php new file mode 100644 index 0000000..5e7757f --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Keys.php @@ -0,0 +1,159 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Keys + * + * @since 3.2.0 + */ +class Keys extends Api +{ + /** + * List a repository's keys. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int|null $keyId The key_id to search for. (Optional) + * @param string|null $fingerprint The fingerprint of the key. (Optional) + * @param int $page The page number of results to return. (Default: 1) + * @param int $limit The page size of results. (Default: 10) + * + * @return array|null + * @since 3.2.0 + */ + public function list(string $owner, string $repo, ?int $keyId = null, ?string $fingerprint = null, int $page = 1, int $limit = 10): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/keys"; + + // Prepare the URI. + $uri = $this->uri->get($path); + + // Add the optional query parameters. + if ($keyId !== null) + { + $uri->setVar('key_id', $keyId); + } + + if ($fingerprint !== null) + { + $uri->setVar('fingerprint', $fingerprint); + } + + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the GET request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Add a key to a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $key The public key. + * @param string $title The title of the key. + * @param bool $readOnly Whether the key is read-only. + * + * @return object|null + * @since 3.2.0 + **/ + public function add( + string $owner, + string $repo, + string $key, + string $title, + bool $readOnly + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/keys"; + + // Set the key data. + $data = new \stdClass(); + $data->key = $key; + $data->title = $title; + $data->read_only = $readOnly; + + // Send the POST request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + json_encode($data) + ), 201 + ); + } + + /** + * Get a repository's key by id. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $id The key ID. + * + * @return object|null + * @since 3.2.0 + */ + public function id( + string $owner, + string $repo, + int $id + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/keys/{$id}"; + + // Send the GET request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Delete a key from a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $id The key ID. + * + * @return string + * @since 3.2.0 + **/ + public function delete( + string $owner, + string $repo, + int $id + ): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/keys/{$id}"; + + // Send the DELETE request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Languages.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Languages.php new file mode 100644 index 0000000..e4f4f0e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Languages.php @@ -0,0 +1,49 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Languages + * + * @since 3.2.0 + */ +class Languages extends Api +{ + /** + * Get languages and number of bytes of code written in a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * + * @return object|null + * @since 3.2.0 + **/ + public function getLanguages(string $owner, string $repo): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/languages"; + + // Build the URI. + $uri = $this->uri->get($path); + + // Send the GET request. + return $this->response->get( + $this->http->get($uri) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Media.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Media.php new file mode 100644 index 0000000..74ea839 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Media.php @@ -0,0 +1,63 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Media + * + * @since 3.2.0 + */ +class Media extends Api +{ + /** + * Get a file or its LFS object from a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $filepath The file path. + * @param string|null $ref The name of the commit/branch/tag. (Optional) + * + * @return string + * @since 3.2.0 + */ + public function get( + string $owner, + string $repo, + string $filepath, + ?string $ref = null + ): string + { + // Build the request path. + $encodedFilepath = rawurlencode($filepath); + $path = "/repos/{$owner}/{$repo}/media/{$encodedFilepath}"; + + // Prepare the URI. + $uri = $this->uri->get($path); + + // Add the 'ref' query parameter if provided. + if ($ref !== null) + { + $uri->setVar('ref', $ref); + } + + // Send the GET request. + return $this->response->get( + $this->http->get($uri), 200, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Merge.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Merge.php new file mode 100644 index 0000000..2b2cd2d --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Merge.php @@ -0,0 +1,167 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Merge + * + * @since 3.2.0 + */ +class Merge extends Api +{ + /** + * Check if a pull request has been merged. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $index The pull request index. + * + * @return string + * @since 3.2.0 + **/ + public function check( + string $owner, + string $repo, + int $index + ): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls/{$index}/merge"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * Merge a pull request. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $index The pull request index. + * @param string|null $mergeMethod Merge method to use (optional). + * @param string|null $mergeCommitId Merge commit ID (optional). + * @param string|null $mergeMessageField Merge message field (optional). + * @param string|null $mergeTitleField Merge title field (optional). + * @param bool|null $deleteBranchAfterMerge Delete branch after merge (optional). + * @param bool|null $forceMerge Force merge (optional). + * @param string|null $headCommitId Head commit ID (optional). + * @param bool|null $mergeWhenChecksSucceed Merge when checks succeed (optional). + * + * @return string + * @since 3.2.0 + **/ + public function pull( + string $owner, + string $repo, + int $index, + ?string $mergeMethod = null, + ?string $mergeCommitId = null, + ?string $mergeMessageField = null, + ?string $mergeTitleField = null, + ?bool $deleteBranchAfterMerge = null, + ?bool $forceMerge = null, + ?string $headCommitId = null, + ?bool $mergeWhenChecksSucceed = null + ): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls/{$index}/merge"; + + // Set the merge data. + $data = new \stdClass(); + + if ($mergeMethod !== null) + { + $data->do = $mergeMethod; + } + + if ($mergeCommitId !== null) + { + $data->merge_commit_id = $mergeCommitId; + } + + if ($mergeMessageField !== null) + { + $data->merge_message_field = $mergeMessageField; + } + + if ($mergeTitleField !== null) + { + $data->merge_title_field = $mergeTitleField; + } + + if ($deleteBranchAfterMerge !== null) + { + $data->delete_branch_after_merge = $deleteBranchAfterMerge; + } + + if ($forceMerge !== null) + { + $data->force_merge = $forceMerge; + } + + if ($headCommitId !== null) + { + $data->head_commit_id = $headCommitId; + } + + if ($mergeWhenChecksSucceed !== null) + { + $data->merge_when_checks_succeed = $mergeWhenChecksSucceed; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ), 200, 'success' + ); + } + + /** + * Cancel the scheduled auto merge for a pull request. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $index The pull request index. + * + * @return string + * @since 3.2.0 + **/ + public function cancel( + string $owner, + string $repo, + int $index + ): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls/{$index}/merge"; + + // Get the URI with the path. + $uri = $this->uri->get($path); + + // Send the delete request. + return $this->response->get( + $this->http->delete($uri), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Mirror.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Mirror.php new file mode 100644 index 0000000..37e3b57 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Mirror.php @@ -0,0 +1,48 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Mirror + * + * @since 3.2.0 + */ +class Mirror extends Api +{ + /** + * Sync a mirrored repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * + * @return string + * @since 3.2.0 + */ + public function sync(string $owner, string $repo): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/mirror-sync"; + + // Send the POST request. + return $this->response->get( + $this->http->post( + $this->uri->get($path) + ), 200, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Mirrors.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Mirrors.php new file mode 100644 index 0000000..2dd60ed --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Mirrors.php @@ -0,0 +1,190 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Mirrors + * + * @since 3.2.0 + */ +class Mirrors extends Api +{ + /** + * Get all push mirrors of the repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $page The page number of results to return (1-based). + * @param int $limit The page size of results. + * + * @return array|null + * @since 3.2.0 + */ + public function get( + string $owner, + string $repo, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/push_mirrors"; + + // Set query parameters. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Add a push mirror to the repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $remoteAddress The push mirror address. + * @param string|null $remoteUsername The push mirror user. (Optional) + * @param string|null $remotePassword The push mirror password. (Optional) + * @param string $interval The interval for the push mirror. + * @param bool $syncOnCommit Sync on commit option. + * + * @return object|null + * @since 3.2.0 + */ + public function add( + string $owner, + string $repo, + string $remoteAddress, + ?string $remoteUsername = null, + ?string $remotePassword = null, + string $interval, + bool $syncOnCommit + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/push_mirrors"; + + // Set the mirror data. + $data = new \stdClass(); + $data->remote_address = $remoteAddress; + $data->interval = $interval; + $data->sync_on_commit = $syncOnCommit; + + if ($remoteUsername !== null) + { + $data->remote_username = $remoteUsername; + } + + if ($remotePassword !== null) + { + $data->remote_password = $remotePassword; + } + + // Send the request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ), 201 + ); + } + + /** + * Sync all push mirrored repositories. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * + * @return string + * @since 3.2.0 + */ + public function sync( + string $owner, + string $repo + ): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/push_mirrors-sync"; + + // Send the request. + return $this->response->get( + $this->http->post( + $this->uri->get($path) + ), 200, 'success' + ); + } + + /** + * Get push mirror of the repository by remoteName. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $name The remote name. + * + * @return object|null + * @since 3.2.0 + */ + public function name( + string $owner, + string $repo, + string $name + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/push_mirrors/{$name}"; + + // Get the URI with the path. + $uri = $this->uri->get($path); + + // Send the request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Delete a push mirror from a repository by remoteName. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $name The remote name. + * + * @return string + * @since 3.2.0 + */ + public function delete( + string $owner, + string $repo, + string $name + ): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/push_mirrors/{$name}"; + + // Get the URI with the path. + $uri = $this->uri->get($path); + + // Send the request. + return $this->response->get( + $this->http->delete($uri), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Notes.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Notes.php new file mode 100644 index 0000000..823d613 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Notes.php @@ -0,0 +1,53 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Notes + * + * @since 3.2.0 + */ +class Notes extends Api +{ + /** + * Get a note corresponding to a single commit from a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $commitSha The SHA hash of the commit. + * + * @return object|null + * @since 3.2.0 + **/ + public function get( + string $owner, + string $repo, + string $commitSha + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/git/notes/{$commitSha}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Patch.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Patch.php new file mode 100644 index 0000000..d7d8007 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Patch.php @@ -0,0 +1,78 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Patch + * + * @since 3.2.0 + */ +class Patch extends Api +{ + /** + * Apply a diff patch to a repository. + * + * @param string $owner The owner of the repo. + * @param string $repo The name of the repo. + * @param array $options Options for updating files. + * $options = [ + * 'description' => 'UpdateFileOptions', + * 'body' => [ + * 'content' => 'string', // Content must be base64 encoded. + * 'sha' => 'string', // The SHA for the file that already exists. + * 'branch' => 'string', // Branch (optional) to base this file from. If not given, the default branch is used. + * 'new_branch' => 'string', // New branch (optional) will make a new branch from branch before creating the file. + * 'from_path' => 'string', // From_path (optional) is the path of the original file which will be moved/renamed to the path in the URL. + * 'message' => 'string', // Message (optional) for the commit of this file. If not supplied, a default message will be used. + * 'author' => [ // Identity for a person's identity like an author or committer. + * 'name' => 'string', + * 'email' => 'string($email)' + * ], + * 'committer' => [ // Identity for a person's identity like an author or committer. + * 'name' => 'string', + * 'email' => 'string($email)' + * ], + * 'dates' => [ // Store dates for GIT_AUTHOR_DATE and GIT_COMMITTER_DATE. + * 'author' => 'string($date-time)', + * 'committer' => 'string($date-time)' + * ], + * 'signoff' => 'boolean' // Add a Signed-off-by trailer by the committer at the end of the commit log message. + * ] + * ] + * + * @return object|null + * @since 3.2.0 + */ + public function applyDiffPatch( + string $owner, + string $repo, + array $option + ): ?object + { + // Build the request path. + $uriPath = "/repos/{$owner}/{$repo}/diffpatch"; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($uriPath), + json_encode($options) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Pulls.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Pulls.php new file mode 100644 index 0000000..a979e79 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Pulls.php @@ -0,0 +1,547 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Pulls + * + * @since 3.2.0 + */ +class Pulls extends Api +{ + /** + * List a repository's pull requests. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string|null $state State of pull request: open, closed, or all (optional). + * @param string|null $sort Type of sort (optional). + * @param int|null $milestone ID of the milestone (optional). + * @param array|null $labels Label IDs (optional). + * @param int $page Page number of results to return (1-based, default: 1). + * @param int $limit Page size of results (default: 10). + * + * @return array|null + * @since 3.2.0 + */ + public function list( + string $owner, + string $repo, + ?string $state = null, + ?string $sort = null, + ?int $milestone = null, + ?array $labels = null, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls"; + + // Set query parameters. + $this->uri->setVar('page', $page); + $this->uri->setVar('limit', $limit); + + if ($state !== null) + { + $this->uri->setVar('state', $state); + } + + if ($sort !== null) + { + $this->uri->setVar('sort', $sort); + } + + if ($milestone !== null) + { + $this->uri->setVar('milestone', $milestone); + } + + if ($labels !== null) + { + $this->uri->setVar('labels', implode(',', $labels)); + } + + // Send the GET request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Create a pull request. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $title The title of the pull request. + * @param string $head The head branch. + * @param string $base The base branch. + * @param string|null $body The description of the pull request (optional). + * @param string|null $assignee The assignee of the pull request (optional). + * @param array|null $assignees Additional assignees (optional). + * @param array|null $labels Label IDs (optional). + * @param int|null $milestone ID of the milestone (optional). + * @param string|null $dueDate Due date of the pull request (optional). + * + * @return object|null + * @since 3.2.0 + */ + public function create( + string $owner, + string $repo, + string $title, + string $head, + string $base, + ?string $body = null, + ?string $assignee = null, + ?array $assignees = null, + ?array $labels = null, + ?int $milestone = null, + ?string $dueDate = null + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls"; + + // Set the pull request data. + $data = new \stdClass(); + $data->title = $title; + $data->head = $head; + $data->base = $base; + + if ($body !== null) + { + $data->body = $body; + } + + if ($assignee !== null) + { + $data->assignee = $assignee; + } + + if ($assignees !== null) + { + $data->assignees = $assignees; + } + + if ($labels !== null) + { + $data->labels = $labels; + } + + if ($milestone !== null) + { + $data->milestone = $milestone; + } + + if ($dueDate !== null) + { + $data->due_date = $dueDate; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ), 201 + ); + } + + /** + * Get a pull request. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $index The pull request index. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(string $owner, string $repo, int $index): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls/{$index}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Update a pull request. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $index The pull request index. + * @param string|null $title The title of the pull request (optional). + * @param string|null $body The description of the pull request (optional). + * @param string|null $assignee The assignee of the pull request (optional). + * @param array|null $assignees Additional assignees (optional). + * @param string|null $base The base branch (optional). + * @param string|null $state The state of the pull request (optional). + * @param array|null $labels Label IDs (optional). + * @param int|null $milestone ID of the milestone (optional). + * @param string|null $dueDate Due date of the pull request (optional). + * @param bool|null $unsetDueDate Whether to unset the due date (optional). + * @param bool|null $allowMaintainerEdit Allow maintainer to edit the pull request (optional). + * + * @return object|null + * @since 3.2.0 + */ + public function update( + string $owner, + string $repo, + int $index, + ?string $title = null, + ?string $body = null, + ?string $assignee = null, + ?array $assignees = null, + ?string $base = null, + ?string $state = null, + ?array $labels = null, + ?int $milestone = null, + ?string $dueDate = null, + ?bool $unsetDueDate = null, + ?bool $allowMaintainerEdit = null + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls/{$index}"; + + // Set the pull request data. + $data = new \stdClass(); + + if ($title !== null) + { + $data->title = $title; + } + + if ($body !== null) + { + $data->body = $body; + } + + if ($assignee !== null) + { + $data->assignee = $assignee; + } + + if ($assignees !== null) + { + $data->assignees = $assignees; + } + + if ($base !== null) + { + $data->base = $base; + } + + if ($state !== null) + { + $data->state = $state; + } + + if ($labels !== null) + { + $data->labels = $labels; + } + + if ($milestone !== null) + { + $data->milestone = $milestone; + } + + if ($dueDate !== null) + { + $data->due_date = $dueDate; + } + + if ($unsetDueDate !== null) + { + $data->unset_due_date = $unsetDueDate; + } + + if ($allowMaintainerEdit !== null) + { + $data->allow_maintainer_edit = $allowMaintainerEdit; + } + + // Send the patch request. + return $this->response->get( + $this->http->patch( + $this->uri->get($path), json_encode($data) + ), 201 + ); + } + + /** + * Get a pull request diff or patch. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $index The pull request index. + * @param string $diffType The type of the requested data, either "diff" or "patch". + * @param bool $binary Whether to include binary file changes. If true, the diff is applicable with git apply. + * + * @return string + * @since 3.2.0 + **/ + public function diff( + string $owner, + string $repo, + int $index, + string $diffType, + bool $binary = false + ): string + { + // Validate the diff type. + if (!in_array($diffType, ['diff', 'patch'])) + { + throw new \InvalidArgumentException('Invalid diff type. Allowed types are "diff" and "patch".'); + } + + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls/{$index}.{$diffType}"; + + // Get the URI with the path. + $uri = $this->uri->get($path); + + // Set the binary query parameter if required. + if ($binary) + { + $uri->setVar('binary', 'true'); + } + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get commits for a pull request. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $index The pull request index. + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function commits( + string $owner, + string $repo, + int $index, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls/{$index}/commits"; + + // Get the URI with the path. + $uri = $this->uri->get($path); + + // Set the page and limit query parameters. + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get changed files for a pull request. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $index The pull request index. + * @param string $skipTo Skip to the given file. + * @param string $whitespace Whitespace behavior. + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function files( + string $owner, + string $repo, + int $index, + ?string $skipTo = null, + ?string $whitespace = null, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls/{$index}/files"; + + // Get the URI with the path. + $uri = $this->uri->get($path); + + // Set the skip-to, whitespace, page, and limit query parameters if needed. + if ($skipTo !== null) + { + $uri->setVar('skip-to', $skipTo); + } + if ($whitespace !== null) + { + $uri->setVar('whitespace', $whitespace); + } + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Merge a pull request. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $index The pull request index. + * @param string|null $do Merge method. + * @param string|null $mergeCommitId Merge commit ID. + * @param string|null $mergeMessageField Merge message field. + * @param string|null $mergeTitleField Merge title field. + * @param bool|null $deleteBranchAfterMerge Whether to delete the branch after merge. + * @param bool|null $forceMerge Whether to force merge. + * @param string|null $headCommitId Head commit ID. + * @param bool|null $mergeWhenChecksSucceed Whether to merge when checks succeed. + * + * @return string + * @since 3.2.0 + **/ + public function merge( + string $owner, + string $repo, + int $index, + ?string $do = null, + ?string $mergeCommitId = null, + ?string $mergeMessageField = null, + ?string $mergeTitleField = null, + ?bool $deleteBranchAfterMerge = null, + ?bool $forceMerge = null, + ?string $headCommitId = null, + ?bool $mergeWhenChecksSucceed = null + ): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls/{$index}/merge"; + + // Set the merge data. + $data = new \stdClass(); + + if ($do !== null) + { + $data->do = $do; + } + + if ($mergeCommitId !== null) + { + $data->merge_commit_id = $mergeCommitId; + } + + if ($mergeMessageField !== null) + { + $data->merge_message_field = $mergeMessageField; + } + + if ($mergeTitleField !== null) + { + $data->merge_title_field = $mergeTitleField; + } + + if ($deleteBranchAfterMerge !== null) + { + $data->delete_branch_after_merge = $deleteBranchAfterMerge; + } + + if ($forceMerge !== null) + { + $data->force_merge = $forceMerge; + } + + if ($headCommitId !== null) + { + $data->head_commit_id = $headCommitId; + } + + if ($mergeWhenChecksSucceed !== null) + { + $data->merge_when_checks_succeed = $mergeWhenChecksSucceed; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ), 200, 'success' + ); + } + + /** + * Merge PR's baseBranch into headBranch. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $index The pull request index. + * @param string|null $style How to update the pull request. (Optional) + * + * @return string + * @since 3.2.0 + */ + public function update( + string $owner, + string $repo, + int $index, + ?string $style = null + ): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls/{$index}/update"; + + // Set the merge data. + $data = new \stdClass(); + + if ($style !== null) + { + $data->style = $style; + } + + // Send the request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ), 200, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Refs.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Refs.php new file mode 100644 index 0000000..6abc591 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Refs.php @@ -0,0 +1,77 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Refs + * + * @since 3.2.0 + */ +class Refs extends Api +{ + /** + * Get specified ref or filtered repository's refs. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * + * @return array|null + * @since 3.2.0 + **/ + public function list(string $owner, string $repo): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/git/refs"; + + // Build the URI. + $uri = $this->uri->get($path); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get specified ref. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $ref The ref name. + * + * @return array|null + * @since 3.2.0 + **/ + public function get( + string $owner, + string $repo, + string $ref + ): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/git/refs/{$ref}"; + + // Build the URI. + $uri = $this->uri->get($path); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Releases.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Releases.php new file mode 100644 index 0000000..5723b56 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Releases.php @@ -0,0 +1,309 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Releases + * + * @since 3.2.0 + */ +class Releases extends Api +{ + /** + * List a repo's releases. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param bool|null $draft Filter (exclude/include) drafts (optional). + * @param bool|null $preRelease Filter (exclude/include) pre-releases (optional). + * @param int $page Page number of results to return (1-based, optional). + * @param int $limit Page size of results (optional). + * + * @return array|null + * @since 3.2.0 + */ + public function list( + string $ownerName, + string $repoName, + ?bool $draft = null, + ?bool $preRelease = null, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/releases"; + + // Set additional URI values. + $this->uri->setVar('page', $page); + $this->uri->setVar('limit', $limit); + + if ($draft !== null) + { + $this->uri->setVar('draft', $draft); + } + + if ($preRelease !== null) + { + $this->uri->setVar('pre-release', $preRelease); + } + + // Send the request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Create a release. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param string $tagName The tag name. + * @param string $targetCommitish The commitish value that determines where the Git tag is created from. + * @param string $releaseName The name of the release. + * @param string $releaseBody The description of the release. + * @param bool $isDraft Whether the release is a draft. + * @param bool $isPrerelease Whether the release is a pre-release. + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $ownerName, + string $repoName, + string $tagName, + string $targetCommitish, + string $releaseName, + string $releaseBody, + bool $isDraft = false, + bool $isPrerelease = false + ): ?object + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/releases"; + + // Set the release data + $data = new \stdClass(); + $data->tag_name = $tagName; + $data->target_commitish = $targetCommitish; + $data->name = $releaseName; + $data->body = $releaseBody; + $data->draft = $isDraft; + $data->prerelease = $isPrerelease; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ), 201 + ); + } + + /** + * Get a release by ID. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param int $releaseId The release ID. + * + * @return object|null + * @since 3.2.0 + **/ + public function get( + string $ownerName, + string $repoName, + int $releaseId + ): ?object + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/releases/{$releaseId}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Delete a release by ID. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param int $releaseId The release ID. + * + * @return string + * @since 3.2.0 + **/ + public function delete( + string $ownerName, + string $repoName, + int $releaseId + ): string + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/releases/{$releaseId}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * Update a release. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param int $releaseId The release ID. + * @param string|null $tagName The tag name (optional). + * @param string|null $targetCommitish The commitish value that determines where the Git tag is created from (optional). + * @param string|null $releaseName The name of the release (optional). + * @param string|null $description The description of the release (optional). + * @param bool|null $isDraft Whether the release is a draft (optional). + * @param bool|null $isPrerelease Whether the release is a pre-release (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function update( + string $ownerName, + string $repoName, + int $releaseId, + ?string $tagName = null, + ?string $targetCommitish = null, + ?string $releaseName = null, + ?string $description = null, + ?bool $isDraft = null, + ?bool $isPrerelease = null + ): ?object + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/releases/{$releaseId}"; + + // Set the release data + $data = new \stdClass(); + + if ($tagName !== null || $targetCommitish !== null || $releaseName !== null || $description !== null || $isDraft !== null || $isPrerelease !== null) + { + $data->editReleaseOption = new \stdClass(); + + if ($tagName !== null) + { + $data->editReleaseOption->tag_name = $tagName; + } + + if ($targetCommitish !== null) + { + $data->editReleaseOption->target_commitish = $targetCommitish; + } + + if ($releaseName !== null) + { + $data->editReleaseOption->name = $releaseName; + } + + if ($description !== null) + { + $data->editReleaseOption->body = $description; + } + + if ($isDraft !== null) + { + $data->editReleaseOption->draft = $isDraft; + } + + if ($isPrerelease !== null) + { + $data->editReleaseOption->prerelease = $isPrerelease; + } + } + + // Send the patch request. + return $this->response->get( + $this->http->patch( + $this->uri->get($path), json_encode($data) + ) + ); + } + + /** + * Get a release by tag name. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param string $tagName The tag name. + * + * @return object|null + * @since 3.2.0 + **/ + public function getByTag( + string $ownerName, + string $repoName, + string $tagName + ): ?object + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/releases/tags/{$tagName}"; + + // Configure the URI with the path. + $this->uri->setVar('owner', $ownerName); + $this->uri->setVar('repo', $repoName); + $this->uri->setVar('tag', $tagName); + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Delete a release by tag name. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param string $tagName The tag name. + * + * @return string + * @since 3.2.0 + **/ + public function deleteByTag( + string $ownerName, + string $repoName, + string $tagName + ): string + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/releases/tags/{$tagName}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Remote.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Remote.php new file mode 100644 index 0000000..f1bf114 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Remote.php @@ -0,0 +1,96 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Remote + * + * @since 3.2.0 + */ +class Remote extends Api +{ + /** + * Migrate a remote git repository. + * + * @param string $cloneAddr The URL to clone the repository from. + * @param string $repoName The desired name for the new repository. + * @param string $repoOwner The name of the user or organization who will own the repo after migration. + * @param string $uid The ID of the user that will own the new repository (deprecated). + * @param string $description The description for the new repository (optional). + * @param bool $private Set the repository to private (optional, default false). + * @param string|null $authToken Authentication token (optional). + * @param string|null $authUsername Authentication username (optional). + * @param string|null $authPassword Authentication password (optional). + * @param array $options Additional migration options (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function migrate( + string $cloneAddr, + string $repoName, + string $repoOwner, + string $uid, + string $description = '', + bool $private = false, + ?string $authToken = null, + ?string $authUsername = null, + ?string $authPassword = null, + array $options = [] + ): ?object + { + // Build the request path. + $path = "/repos/migrate"; + + // Set the repository migration data. + $data = new \stdClass(); + $data->cloneAddr = $cloneAddr; + $data->repoName = $repoName; + $data->repoOwner = $repoOwner; + $data->uid = $uid; + $data->description = $description; + $data->private = $private; + + if ($authToken !== null) + { + $data->authToken = $authToken; + } + + if ($authUsername !== null) + { + $data->authUsername = $authUsername; + } + + if ($authPassword !== null) + { + $data->authPassword = $authPassword; + } + + foreach ($options as $key => $val) + { + $data->{$key} = $val; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ), 201 + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Reviewers.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Reviewers.php new file mode 100644 index 0000000..ee0a4a0 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Reviewers.php @@ -0,0 +1,126 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Reviewers + * + * @since 3.2.0 + */ +class Reviewers extends Api +{ + /** + * Create review requests for a pull request. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $index The pull request index. + * @param array $reviewers Array of reviewers usernames. + * @param array|null $teamReviewers Array of team reviewers (optional). + * + * @return array|null + * @since 3.2.0 + **/ + public function request( + string $owner, + string $repo, + int $index, + array $reviewers, + ?array $teamReviewers = null + ): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls/{$index}/requested_reviewers"; + + // Set the review requests data. + $data = new \stdClass(); + $data->reviewers = $reviewers; + + if ($teamReviewers !== null) + { + $data->team_reviewers = $teamReviewers; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ), 201 + ); + } + + /** + * Cancel review requests for a pull request. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $index The pull request index. + * @param array $reviewers Array of reviewers usernames. + * @param array|null $teamReviewers Array of team reviewers (optional). + * + * @return string + * @since 3.2.0 + **/ + public function cancel( + string $owner, + string $repo, + int $index, + array $reviewers, + ?array $teamReviewers = null + ): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls/{$index}/requested_reviewers"; + + // Get the URI and set the required variables. + $uri = $this->uri->get($path); + $uri->setVar('reviewers', json_encode($reviewers)); + + if ($teamReviewers !== null) + { + $uri->setVar('teamReviewers', json_encode($teamReviewers)); + } + + // Send the delete request. + return $this->response->get( + $this->http->delete($uri), 204, 'success' + ); + } + + /** + * Return all users that can be requested to review in this repo. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * + * @return array|null + * @since 3.2.0 + **/ + public function get(string $owner, string $repo): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/reviewers"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Reviews.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Reviews.php new file mode 100644 index 0000000..17e3ac3 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Reviews.php @@ -0,0 +1,321 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Reviews + * + * @since 3.2.0 + */ +class Reviews extends Api +{ + /** + * List all reviews for a pull request. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $index The pull request index. + * @param int $page The page number of results to return (1-based). + * @param int $limit The page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + string $owner, + string $repo, + int $index, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls/{$index}/reviews"; + + // Get the URI. + $uri = $this->uri->get($path); + + // Set query parameters. + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Create a review for a pull request. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $index The pull request index. + * @param string $body The review body text. + * @param string $event The review event type (APPROVE, REQUEST_CHANGES, COMMENT). + * @param array|null $comments An array of CreatePullReviewComment objects. + * @param string|null $commitId The commit ID. + * + * @return object|null + * @since 3.2.0 + */ + public function create( + string $owner, + string $repo, + int $index, + string $body, + string $event, + ?array $comments = null, + ?string $commitId = null + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls/{$index}/reviews"; + + // Set the review data. + $data = new \stdClass(); + $data->body = $body; + $data->event = $event; + + // Add comments if available. + if ($comments !== null) + { + $data->comments = $comments; + } + + // Add commitId if available. + if ($commitId !== null) + { + $data->commit_id = $commitId; + } + + // Send the request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } + + /** + * Get a specific review for a pull request. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $index The pull request index. + * @param int $id The review ID. + * + * @return object|null + * @since 3.2.0 + */ + public function get( + string $owner, + string $repo, + int $index, + int $id + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls/{$index}/reviews/{$id}"; + + // Set the variables for the URI. + $uri = $this->uri->get($path); + $uri->setVar('owner', $owner); + $uri->setVar('repo', $repo); + $uri->setVar('index', $index); + $uri->setVar('id', $id); + + // Send the request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Submit a pending review to a pull request. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $index The pull request index. + * @param int $id The review ID. + * @param string $body The review body text. + * @param string $event The review event type (APPROVE, REQUEST_CHANGES, COMMENT). + * + * @return object|null + * @since 3.2.0 + */ + public function submit( + string $owner, + string $repo, + int $index, + int $id, + string $body, + string $event + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls/{$index}/reviews/{$id}"; + + // Set the review data. + $data = new \stdClass(); + $data->body = $body; + $data->event = $event; + + // Send the request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } + + /** + * Delete a specific review from a pull request. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $index The pull request index. + * @param int $id The review ID. + * + * @return string + * @since 3.2.0 + */ + public function delete( + string $owner, + string $repo, + int $index, + int $id + ): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls/{$index}/reviews/{$id}"; + + // Set the variables for the URI. + $uri = $this->uri->get($path); + $uri->setVar('owner', $owner); + $uri->setVar('repo', $repo); + $uri->setVar('index', $index); + $uri->setVar('id', $id); + + // Send the delete request. + return $this->response->get( + $this->http->delete($uri), 204, 'success' + ); + } + + /** + * Get the comments of a specific review for a pull request. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $index The pull request index. + * @param int $id The review ID. + * + * @return array|null + * @since 3.2.0 + */ + public function comments( + string $owner, + string $repo, + int $index, + int $id + ): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls/{$index}/reviews/{$id}/comments"; + + // Set the variables for the URI. + $uri = $this->uri->get($path); + $uri->setVar('owner', $owner); + $uri->setVar('repo', $repo); + $uri->setVar('index', $index); + $uri->setVar('id', $id); + + // Send the request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Dismiss a review for a pull request. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $index The pull request index. + * @param int $id The review ID. + * @param string $message The dismissal message. + * @param bool $priors The flag to dismiss prior reviews. + * + * @return object|null + * @since 3.2.0 + */ + public function dismiss( + string $owner, + string $repo, + int $index, + int $id, + string $message, + bool $priors = false + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls/{$index}/reviews/{$id}/dismissals"; + + // Set the dismissal data. + $data = new \stdClass(); + $data->message = $message; + $data->priors = $priors; + + // Send the request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } + + /** + * Cancel the dismissal of a review for a pull request. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $index The pull request index. + * @param int $id The review ID. + * + * @return object|null + * @since 3.2.0 + */ + public function undismiss( + string $owner, + string $repo, + int $index, + int $id + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/pulls/{$index}/reviews/{$id}/undismissals"; + + // Send the request. + return $this->response->get( + $this->http->post( + $this->uri->get($path) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Stargazers.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Stargazers.php new file mode 100644 index 0000000..0c72b6d --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Stargazers.php @@ -0,0 +1,59 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Stargazers + * + * @since 3.2.0 + */ +class Stargazers extends Api +{ + /** + * List a repo's stargazers. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param int $page The page number of results to return (1-based). + * @param int $limit The page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + string $ownerName, + string $repoName, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/stargazers"; + + // Set the page and limit values. + $this->uri->setVar('page', $page); + $this->uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Statuses.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Statuses.php new file mode 100644 index 0000000..ba6e3c1 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Statuses.php @@ -0,0 +1,122 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Statuses + * + * @since 3.2.0 + */ +class Statuses extends Api +{ + /** + * Get a commit's statuses. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param string $commitSha The commit SHA. + * @param string $sort The type of sort. + * @param string $state The type of state. + * @param int $page The page number of results to return (1-based). + * @param int $limit The page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function get( + string $ownerName, + string $repoName, + string $commitSha, + string $sort = 'recentupdate', + string $state = 'pending', + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/statuses/{$commitSha}"; + + // Prepare the URI with the path. + $uri = $this->uri->get($path); + + // Set the query parameters. + $uri->setVar('sort', $sort); + $uri->setVar('state', $state); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Create a commit status. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param string $commitSha The commit SHA. + * @param string $state The commit status state (error, failure, pending, success, or warning). + * @param string|null $context The context of the status (optional). + * @param string|null $statusDescription The status description (optional). + * @param string|null $targetUrl The URL of the associated build status (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $ownerName, + string $repoName, + string $commitSha, + string $state, + ?string $context = null, + ?string $statusDescription = null, + ?string $targetUrl = null + ): ?object + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/statuses/{$commitSha}"; + + // Set the commit status data + $data = new \stdClass(); + $data->state = $state; + + if ($context !== null) + { + $data->context = $context; + } + + if ($statusDescription !== null) + { + $data->description = $statusDescription; + } + + if ($targetUrl !== null) + { + $data->target_url = $targetUrl; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ), 201 + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Tags.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Tags.php new file mode 100644 index 0000000..600bfc2 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Tags.php @@ -0,0 +1,182 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Tags + * + * @since 3.2.0 + */ +class Tags extends Api +{ + /** + * List a repository's tags + * + * @param string $owner The owner of the repo. + * @param string $repo The name of the repo. + * @param int|null $page The page number of results to return (1-based). + * @param int|null $limit The page size of results, default maximum page size is 10. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + string $owner, + string $repo, + ?int $page = 1, + ?int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/tags"; + + // Get the URI with the path. + $uri = $this->uri->get($path); + + // Add query parameters if they are provided. + if ($page !== null) + { + $uri->setVar('page', $page); + } + + if ($limit !== null) + { + $uri->setVar('limit', $limit); + } + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get the tag of a repository by tag name. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $tag The tag name. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(string $owner, string $repo, string $tag): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/tags/{$tag}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Get the tag object of an annotated tag (not lightweight tags). + * + * @param string $owner The owner of the repo. + * @param string $repo The name of the repo. + * @param string $sha The sha of the tag. The Git tags API only supports annotated tag objects, not lightweight tags. + * + * @return object|null + * @since 3.2.0 + **/ + public function sha( + string $owner, + string $repo, + string $sha + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/git/tags/{$sha}"; + + // Get the URI with the path. + $uri = $this->uri->get($path); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Create a new git tag in a repository. + * + * @param string $owner The owner of the repo. + * @param string $repo The name of the repo. + * @param string $tagName The name of the tag. + * @param string $target The SHA of the git object this is tagging. + * @param string $message The tag message. + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $owner, + string $repo, + string $tagName, + string $target, + string $message + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/tags"; + + // Set the tag data + $data = new \stdClass(); + $data->tag_name = $tagName; + $data->target = $target; + $data->message = $message; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } + + /** + * Delete a repository's tag by name. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $tag The tag name. + * + * @return string + * @since 3.2.0 + **/ + public function delete( + string $owner, + string $repo, + string $tag + ): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/tags/{$tag}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'succes' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Teams.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Teams.php new file mode 100644 index 0000000..cb39f7c --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Teams.php @@ -0,0 +1,133 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Teams + * + * @since 3.2.0 + */ +class Teams extends Api +{ + /** + * List a repository's teams. + * + * @param string $ownerOfRepo The owner name. + * @param string $nameOfRepo The repository name. + * + * @return array|null + * @since 3.2.0 + **/ + public function list(string $ownerOfRepo, string $nameOfRepo): ?array + { + // Build the request path. + $path = "/repos/{$ownerOfRepo}/{$nameOfRepo}/teams"; + + // Get the URI with the path. + $uri = $this->uri->get($path); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Check if a team is assigned to a repository. + * + * @param string $ownerOfRepo The owner name. + * @param string $nameOfRepo The repository name. + * @param string $teamName The team name. + * + * @return object|null + * @since 3.2.0 + **/ + public function check( + string $ownerOfRepo, + string $nameOfRepo, + string $teamName + ): ?object + { + // Build the request path. + $path = "/repos/{$ownerOfRepo}/{$nameOfRepo}/teams/{$teamName}"; + + // Get the URI with the path. + $uri = $this->uri->get($path); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Add a team to a repository. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param string $teamName The team name. + * + * @return string + * @since 3.2.0 + **/ + public function add( + string $ownerName, + string $repoName, + string $teamName + ): string + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/teams/{$teamName}"; + + // Send the put request. + return $this->response->get( + $this->http->put( + $this->uri->get($path), '' + ), 204, 'success' + ); + } + + /** + * Delete a team from a repository. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param string $teamName The team name. + * + * @return string + * @since 3.2.0 + **/ + public function delete( + string $ownerName, + string $repoName, + string $teamName + ): string + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/teams/{$teamName}"; + + // Prepare the URI with the path. + $uri = $this->uri->get($path); + + // Send the delete request. + return $this->response->get( + $this->http->delete($uri), + 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Templates.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Templates.php new file mode 100644 index 0000000..40246fc --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Templates.php @@ -0,0 +1,91 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Templates + * + * @since 3.2.0 + */ +class Templates extends Api +{ + /** + * Get available issue templates for a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * + * @return array|null + * @since 3.2.0 + **/ + public function issue(string $owner, string $repo): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/issue_templates"; + + // Get the URI. + $uri = $this->uri->get($path); + + // Send the GET request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Create a repository using a template. + * + * @param string $templateOwner The template owner's name. + * @param string $templateRepo The template repository name. + * @param string $name The name of the new repository. + * @param array $options Optional. Additional options for the new repository. + * + * @return object|null + * @since 3.2.0 + **/ + public function repo( + string $templateOwner, + string $templateRepo, + string $name, + array $options = [] + ): ?object + { + // Build the request path. + $path = "/repos/{$templateOwner}/{$templateRepo}/generate"; + + // Set the repo data. + $data = new \stdClass(); + $data->name = $name; + + foreach ($options as $key => $value) + { + if ($value !== null) + { + $data->{$key} = $value; + } + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + json_encode($data) + ), 201 + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Times.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Times.php new file mode 100644 index 0000000..bae1416 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Times.php @@ -0,0 +1,80 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Times + * + * @since 3.2.0 + */ +class Times extends Api +{ + /** + * List a repo's tracked times. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param string $user Optional filter by user (available for issue managers). + * @param string $since Only show times updated after the given time. This is a timestamp in RFC 3339 format. + * @param string $before Only show times updated before the given time. This is a timestamp in RFC 3339 format. + * @param int $page The page number of results to return (1-based). + * @param int $limit The page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + string $ownerName, + string $repoName, + string $user = null, + string $since = null, + string $before = null, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/times"; + + // Set the query parameters. + $uri = $this->uri->get($path); + + if ($user !== null) + { + $uri->setVar('user', $user); + } + + if ($since !== null) + { + $uri->setVar('since', $since); + } + + if ($before !== null) + { + $uri->setVar('before', $before); + } + + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Topics.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Topics.php new file mode 100644 index 0000000..bbd24b8 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Topics.php @@ -0,0 +1,175 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Topics + * + * @since 3.2.0 + */ +class Topics extends Api +{ + /** + * Get the list of topics that a repository has. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $page The page number of results to return (1-based). + * @param int $limit The page size of results. + * + * @return object|null + * @since 3.2.0 + **/ + public function get( + string $owner, + string $repo, + int $page = 1, + int $limit = 10 + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/topics"; + + // Set query parameters for pagination. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Replace the list of topics for a repository. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param array $topicNames The new list of topics. + * + * @return string + * @since 3.2.0 + **/ + public function replace( + string $ownerName, + string $repoName, + array $topicNames + ): string + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/topics"; + + // Set the topics data. + $data = new \stdClass(); + $data->topics = $topicNames; + + // Send the put request. + return $this->response->get( + $this->http->put( + $this->uri->get($path), + json_encode($data) + ), 204, 'success' + ); + } + + /** + * Add a topic to a repository. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param string $topicName The topic to add. + * + * @return string + * @since 3.2.0 + **/ + public function add( + string $ownerName, + string $repoName, + string $topicName + ): string + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/topics/{$topicName}"; + + // Send the put request. + return $this->response->get( + $this->http->put( + $this->uri->get($path), '' + ), 204, 'success' + ); + } + + /** + * Delete a topic from a repository. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param string $topicName The topic to delete. + * + * @return string + * @since 3.2.0 + **/ + public function delete( + string $ownerName, + string $repoName, + string $topicName + ): string + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/topics/{$topicName}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * Search topics via keyword. + * + * @param string $searchKeyword The keyword to search for. + * @param int $page The page number of results to return (1-based). + * @param int $limit The page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function search( + string $searchKeyword, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/topics/search"; + + // Set the query parameters. + $uri = $this->uri->get($path); + $uri->setVar('q', $searchKeyword); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Transfer.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Transfer.php new file mode 100644 index 0000000..b2e80be --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Transfer.php @@ -0,0 +1,108 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Transfer + * + * @since 3.2.0 + */ +class Transfer extends Api +{ + /** + * Transfer a repo ownership. + * + * @param string $owner The current owner name. + * @param string $repo The repository name. + * @param string $newOwner The new owner's name. + * @param array|null $teamIDs Optional. The IDs of the teams that will be granted access. + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $owner, + string $repo, + string $newOwner, + ?array $teamIDs = null + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/transfer"; + + // Set the transfer data. + $data = new \stdClass(); + $data->new_owner = $newOwner; + if ($teamIDs !== null) + { + $data->team_ids = $teamIDs; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + json_encode($data) + ), 202 + ); + } + + /** + * Accept a repo transfer. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * + * @return object|null + * @since 3.2.0 + **/ + public function accept(string $owner, string $repo): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/transfer/accept"; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path) + ), 202 + ); + } + + /** + * Reject a repo transfer. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * + * @return object|null + * @since 3.2.0 + **/ + public function reject(string $owner, string $repo): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/transfer/reject"; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Trees.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Trees.php new file mode 100644 index 0000000..a9e1974 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Trees.php @@ -0,0 +1,63 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Trees + * + * @since 3.2.0 + */ +class Trees extends Api +{ + /** + * Get the tree of a repository. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $sha The commit SHA. + * @param bool $recursive Show all directories and files. + * @param int $page Page number. + * @param int $perPage Number of items per page. + * + * @return object|null + * @since 3.2.0 + **/ + public function get( + string $owner, + string $repo, + string $sha, + bool $recursive = false, + int $page = 1, + int $perPage = 30 + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/git/trees/{$sha}"; + + // Set URI variables. + $uri = $this->uri->get($path); + $uri->setVar('recursive', $recursive); + $uri->setVar('page', $page); + $uri->setVar('per_page', $perPage); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Watchers.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Watchers.php new file mode 100644 index 0000000..131482a --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Watchers.php @@ -0,0 +1,140 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Watchers + * + * @since 3.2.0 + */ +class Watchers extends Api +{ + /** + * List a repo's watchers. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + string $ownerName, + string $repoName, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/subscribers"; + + // Prepare the URI with the path. + $uri = $this->uri->get($path); + + // Set the page and limit query parameters. + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Check if the current user is watching a repo. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * + * @return object|null + * @since 3.2.0 + **/ + public function check(string $ownerName, string $repoName): ?object + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/subscription"; + + // Prepare the URI with the path. + $uri = $this->uri->get($path); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Watch a repo. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * @param bool $subscribed Determine if notifications should be received from this repository. + * @param bool $ignored Determine if all notifications should be blocked from this repository. + * + * @return object|null + * @since 3.2.0 + **/ + public function watch( + string $ownerName, + string $repoName, + bool $subscribed = true, + bool $ignored = false + ): ?object + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/subscription"; + + // Set the subscription data + $data = new \stdClass(); + $data->subscribed = $subscribed; + $data->ignored = $ignored; + + // Send the put request. + return $this->response->get( + $this->http->put( + $this->uri->get($path), json_encode($data) + ) + ); + } + + /** + * Unwatch a repo. + * + * @param string $ownerName The owner name. + * @param string $repoName The repository name. + * + * @return string + * @since 3.2.0 + **/ + public function unwatch(string $ownerName, string $repoName): string + { + // Build the request path. + $path = "/repos/{$ownerName}/{$repoName}/subscription"; + + // Prepare the URI with the path. + $uri = $this->uri->get($path); + + // Send the delete request. + return $this->response->get( + $this->http->delete($uri), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Wiki.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Wiki.php new file mode 100644 index 0000000..7488608 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/Wiki.php @@ -0,0 +1,232 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Repository; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Repository Wiki + * + * @since 3.2.0 + */ +class Wiki extends Api +{ + /** + * Create a wiki page. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $title The title of the wiki page. + * @param string $contentBase64 The base64 encoded content of the wiki page. + * @param string|null $message Optional commit message summarizing the change. + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $owner, + string $repo, + string $title, + string $contentBase64, + ?string $message = null + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/wiki/new"; + + // Set the wiki data. + $data = new \stdClass(); + $data->title = $title; + $data->content_base64 = $contentBase64; + + if ($message !== null) + { + $data->message = $message; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + json_encode($data) + ), 201 + ); + } + + /** + * Get a wiki page. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $pageName The name of the wiki page. + * + * @return object|null + * @since 3.2.0 + **/ + public function get( + string $owner, + string $repo, + string $pageName + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/wiki/page/{$pageName}"; + + // Set the URI. + $uri = $this->uri->get($path); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get all wiki pages. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function pages( + string $owner, + string $repo, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/wiki/pages"; + + // Set the URI. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Delete a wiki page. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $pageName The name of the wiki page. + * + * @return string + * @since 3.2.0 + **/ + public function delete( + string $owner, + string $repo, + string $pageName + ): string + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/wiki/page/{$pageName}"; + + // Get the URI. + $uri = $this->uri->get($path); + + // Send the delete request. + return $this->response->get( + $this->http->delete($uri), 204, 'success' + ); + } + + /** + * Edit a wiki page. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $pageName The name of the wiki page. + * @param string $title The new title of the wiki page. + * @param string $content The new content of the wiki page. + * @param string $message The optional commit message summarizing the change. + * + * @return object|null + * @since 3.2.0 + **/ + public function edit( + string $owner, + string $repo, + string $pageName, + string $title, + string $content, + string $message = null + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/wiki/page/{$pageName}"; + + // Set the wiki data. + $data = new \stdClass(); + $data->title = $title; + $data->content_base64 = base64_encode($content); + + if ($message !== null) + { + $data->message = $message; + } + + // Send the patch request. + return $this->response->get( + $this->http->patch( + $this->uri->get($path), + json_encode($data) + ) + ); + } + + /** + * Get revisions of a wiki page. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * @param string $pageName The name of the wiki page. + * @param int $page The page number of results to return (1-based). + * + * @return object|null + * @since 3.2.0 + **/ + public function revisions( + string $owner, + string $repo, + string $pageName, + int $page = 1 + ): ?object + { + // Build the request path. + $path = "/repos/{$owner}/{$repo}/wiki/revisions/{$pageName}"; + + // Set the page number. + $this->uri->setVar('page', $page); + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/index.html b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Repository/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Admin.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Admin.php new file mode 100644 index 0000000..be64aa1 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Admin.php @@ -0,0 +1,185 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VDM\Joomla\Gitea\Admin\Cron; +use VDM\Joomla\Gitea\Admin\Organizations; +use VDM\Joomla\Gitea\Admin\Unadopted; +use VDM\Joomla\Gitea\Admin\Users; +use VDM\Joomla\Gitea\Admin\Users\Keys; +use VDM\Joomla\Gitea\Admin\Users\Organization; +use VDM\Joomla\Gitea\Admin\Users\Repository; + + +/** + * The Gitea Admin Service + * + * @since 3.2.0 + */ +class Admin implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 3.2.0 + */ + public function register(Container $container) + { + $container->alias(Cron::class, 'Gitea.Admin.Cron') + ->share('Gitea.Admin.Cron', [$this, 'getCron'], true); + + $container->alias(Organizations::class, 'Gitea.Admin.Organizations') + ->share('Gitea.Admin.Organizations', [$this, 'getOrganizations'], true); + + $container->alias(Unadopted::class, 'Gitea.Admin.Unadopted') + ->share('Gitea.Admin.Unadopted', [$this, 'getUnadopted'], true); + + $container->alias(Users::class, 'Gitea.Admin.Users') + ->share('Gitea.Admin.Users', [$this, 'getUsers'], true); + + $container->alias(Keys::class, 'Gitea.Admin.Users.Keys') + ->share('Gitea.Admin.Users.Keys', [$this, 'getKeys'], true); + + $container->alias(Organization::class, 'Gitea.Admin.Users.Organization') + ->share('Gitea.Admin.Users.Organization', [$this, 'getOrganization'], true); + + $container->alias(Repository::class, 'Gitea.Admin.Users.Repository') + ->share('Gitea.Admin.Users.Repository', [$this, 'getRepository'], true); + } + + /** + * Get the Cron class + * + * @param Container $container The DI container. + * + * @return Cron + * @since 3.2.0 + */ + public function getCron(Container $container): Cron + { + return new Cron( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Organizations class + * + * @param Container $container The DI container. + * + * @return Organizations + * @since 3.2.0 + */ + public function getOrganizations(Container $container): Organizations + { + return new Organizations( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Unadopted class + * + * @param Container $container The DI container. + * + * @return Unadopted + * @since 3.2.0 + */ + public function getUnadopted(Container $container): Unadopted + { + return new Unadopted( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Users class + * + * @param Container $container The DI container. + * + * @return Users + * @since 3.2.0 + */ + public function getUsers(Container $container): Users + { + return new Users( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Keys class + * + * @param Container $container The DI container. + * + * @return Keys + * @since 3.2.0 + */ + public function getKeys(Container $container): Keys + { + return new Keys( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Organization class + * + * @param Container $container The DI container. + * + * @return Organization + * @since 3.2.0 + */ + public function getOrganization(Container $container): Organization + { + return new Organization( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Repository class + * + * @param Container $container The DI container. + * + * @return Repository + * @since 3.2.0 + */ + public function getRepository(Container $container): Repository + { + return new Repository( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Issue.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Issue.php new file mode 100644 index 0000000..9c49a5a --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Issue.php @@ -0,0 +1,294 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VDM\Joomla\Gitea\Issue as Issu; +use VDM\Joomla\Gitea\Issue\Comments; +use VDM\Joomla\Gitea\Issue\Repository\Comments as RepoComments; +use VDM\Joomla\Gitea\Issue\Deadline; +use VDM\Joomla\Gitea\Labels; +use VDM\Joomla\Gitea\Issue\Labels as IssueLabels; +use VDM\Joomla\Gitea\Issue\Milestones; +use VDM\Joomla\Gitea\Issue\Reactions; +use VDM\Joomla\Gitea\Issue\Reactions\Comment; +use VDM\Joomla\Gitea\Issue\Stopwatch; +use VDM\Joomla\Gitea\Issue\Subscriptions; +use VDM\Joomla\Gitea\Issue\Timeline; +use VDM\Joomla\Gitea\Issue\Times; + + +/** + * The Gitea Issue Service + * + * @since 3.2.0 + */ +class Issue implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 3.2.0 + */ + public function register(Container $container) + { + $container->alias(Issu::class, 'Gitea.Issue') + ->share('Gitea.Issue', [$this, 'getIssue'], true); + + $container->alias(Comments::class, 'Gitea.Issue.Comments') + ->share('Gitea.Issue.Comments', [$this, 'getComments'], true); + + $container->alias(RepoComments::class, 'Gitea.Issue.Repository.Comments') + ->share('Gitea.Issue.Repository.Comments', [$this, 'getRepoComments'], true); + + $container->alias(Deadline::class, 'Gitea.Issue.Deadline') + ->share('Gitea.Issue.Deadline', [$this, 'getDeadline'], true); + + $container->alias(Labels::class, 'Gitea.Labels') + ->share('Gitea.Labels', [$this, 'getLabels'], true); + + $container->alias(IssueLabels::class, 'Gitea.Issue.Labels') + ->share('Gitea.Issue.Labels', [$this, 'getIssueLabels'], true); + + $container->alias(Milestones::class, 'Gitea.Issue.Milestones') + ->share('Gitea.Issue.Milestones', [$this, 'getMilestones'], true); + + $container->alias(Reactions::class, 'Gitea.Issue.Reactions') + ->share('Gitea.Issue.Reactions', [$this, 'getReactions'], true); + + $container->alias(Comment::class, 'Gitea.Issue.Reactions.Comment') + ->share('Gitea.Issue.Reactions.Comment', [$this, 'getComment'], true); + + $container->alias(Stopwatch::class, 'Gitea.Issue.Stopwatch') + ->share('Gitea.Issue.Stopwatch', [$this, 'getStopwatch'], true); + + $container->alias(Subscriptions::class, 'Gitea.Issue.Subscriptions') + ->share('Gitea.Issue.Subscriptions', [$this, 'getSubscriptions'], true); + + $container->alias(Timeline::class, 'Gitea.Issue.Timeline') + ->share('Gitea.Issue.Timeline', [$this, 'getTimeline'], true); + + $container->alias(Times::class, 'Gitea.Issue.Times') + ->share('Gitea.Issue.Times', [$this, 'getTimes'], true); + } + + /** + * Get the Issue class + * + * @param Container $container The DI container. + * + * @return Issu + * @since 3.2.0 + */ + public function getIssue(Container $container): Issu + { + return new Issu( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Comments class + * + * @param Container $container The DI container. + * + * @return Comments + * @since 3.2.0 + */ + public function getComments(Container $container): Comments + { + return new Comments( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Repository Comments class + * + * @param Container $container The DI container. + * + * @return RepoComments + * @since 3.2.0 + */ + public function getRepoComments(Container $container): RepoComments + { + return new RepoComments( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Labels class + * + * @param Container $container The DI container. + * + * @return Labels + * @since 3.2.0 + */ + public function getLabels(Container $container): Labels + { + return new Labels( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Issue Labels class + * + * @param Container $container The DI container. + * + * @return IssueLabels + * @since 3.2.0 + */ + public function getIssueLabels(Container $container): IssueLabels + { + return new IssueLabels( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Milestones class + * + * @param Container $container The DI container. + * + * @return Milestones + * @since 3.2.0 + */ + public function getMilestones(Container $container): Milestones + { + return new Milestones( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Reactions class + * + * @param Container $container The DI container. + * + * @return Reactions + * @since 3.2.0 + */ + public function getReactions(Container $container): Reactions + { + return new Reactions( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Reactions Comment class + * + * @param Container $container The DI container. + * + * @return Comment + * @since 3.2.0 + */ + public function getComment(Container $container): Comment + { + return new Comment( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Stopwatch class + * + * @param Container $container The DI container. + * + * @return Stopwatch + * @since 3.2.0 + */ + public function getStopwatch(Container $container): Stopwatch + { + return new Stopwatch( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Subscriptions class + * + * @param Container $container The DI container. + * + * @return Subscriptions + * @since 3.2.0 + */ + public function getSubscriptions(Container $container): Subscriptions + { + return new Subscriptions( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Timeline class + * + * @param Container $container The DI container. + * + * @return Timeline + * @since 3.2.0 + */ + public function getTimeline(Container $container): Timeline + { + return new Timeline( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Times class + * + * @param Container $container The DI container. + * + * @return Times + * @since 3.2.0 + */ + public function getTimes(Container $container): Times + { + return new Times( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Jcb.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Jcb.php new file mode 100644 index 0000000..5e6a7a8 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Jcb.php @@ -0,0 +1,85 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VDM\Joomla\Gitea\Utilities\Uri; +use VDM\Joomla\Gitea\Utilities\Http; +use VDM\Joomla\Utilities\Component\Helper; + + +/** + * The Gitea Utilities Service + * + * @since 3.2.0 + */ +class Jcb implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 3.2.0 + */ + public function register(Container $container) + { + $container->alias(Uri::class, 'Gitea.Dynamic.Uri') + ->share('Gitea.Dynamic.Uri', [$this, 'getUri'], true); + + $container->alias(Http::class, 'Gitea.Utilities.Http') + ->share('Gitea.Utilities.Http', [$this, 'getHttp'], true); + } + + /** + * Get the Dynamic Uri class + * + * @param Container $container The DI container. + * + * @return Uri + * @since 3.2.0 + */ + public function getUri(Container $container): Uri + { + // get the global gitea URL + $add_gitea_url = Helper::getParams('com_componentbuilder')->get('add_custom_gitea_url', 1); + $gitea_url = Helper::getParams('com_componentbuilder')->get('custom_gitea_url'); + + // only load this if we have a custom URL set + if ($add_gitea_url == 2 && is_string($gitea_url) && strpos($gitea_url, 'http') !== false) + { + return new Uri($gitea_url); + } + + return $container->get('Gitea.Utilities.Uri'); + } + + /** + * Get the Http class + * + * @param Container $container The DI container. + * + * @return Http + * @since 3.2.0 + */ + public function getHttp(Container $container): Http + { + return new Http( + Helper::getParams('com_componentbuilder')->get('gitea_token') + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Miscellaneous.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Miscellaneous.php new file mode 100644 index 0000000..14abf45 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Miscellaneous.php @@ -0,0 +1,143 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VDM\Joomla\Gitea\Miscellaneous\Activitypub; +use VDM\Joomla\Gitea\Miscellaneous\Gpg; +use VDM\Joomla\Gitea\Miscellaneous\Markdown; +use VDM\Joomla\Gitea\Miscellaneous\NodeInfo; +use VDM\Joomla\Gitea\Miscellaneous\Version; + + +/** + * The Gitea Miscellaneous Service + * + * @since 3.2.0 + */ +class Miscellaneous implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 3.2.0 + */ + public function register(Container $container) + { + $container->alias(Activitypub::class, 'Gitea.Miscellaneous.Activitypub') + ->share('Gitea.Miscellaneous.Activitypub', [$this, 'getActivitypub'], true); + + $container->alias(Gpg::class, 'Gitea.Miscellaneous.Gpg') + ->share('Gitea.Miscellaneous.Gpg', [$this, 'getGpg'], true); + + $container->alias(Markdown::class, 'Gitea.Miscellaneous.Markdown') + ->share('Gitea.Miscellaneous.Markdown', [$this, 'getMarkdown'], true); + + $container->alias(NodeInfo::class, 'Gitea.Miscellaneous.NodeInfo') + ->share('Gitea.Miscellaneous.NodeInfo', [$this, 'getNodeInfo'], true); + + $container->alias(Version::class, 'Gitea.Miscellaneous.Version') + ->share('Gitea.Miscellaneous.Version', [$this, 'getVersion'], true); + } + + /** + * Get the Activitypub class + * + * @param Container $container The DI container. + * + * @return Activitypub + * @since 3.2.0 + */ + public function getActivitypub(Container $container): Activitypub + { + return new Activitypub( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Gpg class + * + * @param Container $container The DI container. + * + * @return Gpg + * @since 3.2.0 + */ + public function getGpg(Container $container): Gpg + { + return new Gpg( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Markdown class + * + * @param Container $container The DI container. + * + * @return Markdown + * @since 3.2.0 + */ + public function getMarkdown(Container $container): Markdown + { + return new Markdown( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the NodeInfo class + * + * @param Container $container The DI container. + * + * @return NodeInfo + * @since 3.2.0 + */ + public function getNodeInfo(Container $container): NodeInfo + { + return new NodeInfo( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Version class + * + * @param Container $container The DI container. + * + * @return Version + * @since 3.2.0 + */ + public function getVersion(Container $container): Version + { + return new Version( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Notifications.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Notifications.php new file mode 100644 index 0000000..b6b5a29 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Notifications.php @@ -0,0 +1,101 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VDM\Joomla\Gitea\Notifications as Notifi; +use VDM\Joomla\Gitea\Notifications\Repository; +use VDM\Joomla\Gitea\Notifications\Thread; + + +/** + * The Gitea Notifications Service + * + * @since 3.2.0 + */ +class Notifications implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 3.2.0 + */ + public function register(Container $container) + { + $container->alias(Notifi::class, 'Gitea.Notifications') + ->share('Gitea.Notifications', [$this, 'getNotifications'], true); + + $container->alias(Repository::class, 'Gitea.Notifications.Repository') + ->share('Gitea.Notifications.Repository', [$this, 'getRepository'], true); + + $container->alias(Thread::class, 'Gitea.Notifications.Thread') + ->share('Gitea.Notifications.Thread', [$this, 'getThread'], true); + } + + /** + * Get the Notifications class + * + * @param Container $container The DI container. + * + * @return Notifi + * @since 3.2.0 + */ + public function getNotifications(Container $container): Notifi + { + return new Notifi( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Repository class + * + * @param Container $container The DI container. + * + * @return Repository + * @since 3.2.0 + */ + public function getRepository(Container $container): Repository + { + return new Repository( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Thread class + * + * @param Container $container The DI container. + * + * @return Thread + * @since 3.2.0 + */ + public function getThread(Container $container): Thread + { + return new Thread( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Organization.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Organization.php new file mode 100644 index 0000000..dab899e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Organization.php @@ -0,0 +1,248 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VDM\Joomla\Gitea\Organization as Org; +use VDM\Joomla\Gitea\Organization\Hooks; +use VDM\Joomla\Gitea\Organization\Labels; +use VDM\Joomla\Gitea\Organization\Members; +use VDM\Joomla\Gitea\Organization\PublicMembers as PublicMembers; +use VDM\Joomla\Gitea\Organization\Repository; +use VDM\Joomla\Gitea\Organization\Teams; +use VDM\Joomla\Gitea\Organization\Teams\Members as TeamsMembers; +use VDM\Joomla\Gitea\Organization\Teams\Repository as TeamsRepository; +use VDM\Joomla\Gitea\Organization\User; + + +/** + * The Gitea Organization Service + * + * @since 3.2.0 + */ +class Organization implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 3.2.0 + */ + public function register(Container $container) + { + $container->alias(Org::class, 'Gitea.Organization') + ->share('Gitea.Organization', [$this, 'getOrganization'], true); + + $container->alias(Hooks::class, 'Gitea.Organization.Hooks') + ->share('Gitea.Organization.Hooks', [$this, 'getHooks'], true); + + $container->alias(Labels::class, 'Gitea.Organization.Labels') + ->share('Gitea.Organization.Labels', [$this, 'getLabels'], true); + + $container->alias(Members::class, 'Gitea.Organization.Members') + ->share('Gitea.Organization.Members', [$this, 'getMembers'], true); + + $container->alias(PublicMembers::class, 'Gitea.Organization.Public.Members') + ->share('Gitea.Organization.Public.Members', [$this, 'getPublicMembers'], true); + + $container->alias(Repository::class, 'Gitea.Organization.Repository') + ->share('Gitea.Organization.Repository', [$this, 'getRepository'], true); + + $container->alias(Teams::class, 'Gitea.Organization.Teams') + ->share('Gitea.Organization.Teams', [$this, 'getTeams'], true); + + $container->alias(TeamsMembers::class, 'Gitea.Organization.Teams.Members') + ->share('Gitea.Organization.Teams.Members', [$this, 'getTeamsMembers'], true); + + $container->alias(TeamsRepository::class, 'Gitea.Organization.Teams.Repository') + ->share('Gitea.Organization.Teams.Repository', [$this, 'getTeamsRepository'], true); + + $container->alias(User::class, 'Gitea.Organization.User') + ->share('Gitea.Organization.User', [$this, 'getUser'], true); + } + + /** + * Get the Organization class + * + * @param Container $container The DI container. + * + * @return Org + * @since 3.2.0 + */ + public function getOrganization(Container $container): Org + { + return new Org( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Hooks class + * + * @param Container $container The DI container. + * + * @return Hooks + * @since 3.2.0 + */ + public function getHooks(Container $container): Hooks + { + return new Hooks( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Labels class + * + * @param Container $container The DI container. + * + * @return Labels + * @since 3.2.0 + */ + public function getLabels(Container $container): Labels + { + return new Labels( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Members class + * + * @param Container $container The DI container. + * + * @return Members + * @since 3.2.0 + */ + public function getMembers(Container $container): Members + { + return new Members( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Public Members class + * + * @param Container $container The DI container. + * + * @return PublicMembers + * @since 3.2.0 + */ + public function getPublicMembers(Container $container): PublicMembers + { + return new PublicMembers( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Repository class + * + * @param Container $container The DI container. + * + * @return Repository + * @since 3.2.0 + */ + public function getRepository(Container $container): Repository + { + return new Repository( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Teams class + * + * @param Container $container The DI container. + * + * @return Teams + * @since 3.2.0 + */ + public function getTeams(Container $container): Teams + { + return new Teams( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Teams Members class + * + * @param Container $container The DI container. + * + * @return TeamsMembers + * @since 3.2.0 + */ + public function getTeamsMembers(Container $container): TeamsMembers + { + return new TeamsMembers( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Teams Repository class + * + * @param Container $container The DI container. + * + * @return TeamsRepository + * @since 3.2.0 + */ + public function getTeamsRepository(Container $container): TeamsRepository + { + return new TeamsRepository( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the User class + * + * @param Container $container The DI container. + * + * @return User + * @since 3.2.0 + */ + public function getUser(Container $container): User + { + return new User( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Package.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Package.php new file mode 100644 index 0000000..75d92cb --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Package.php @@ -0,0 +1,101 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VDM\Joomla\Gitea\Package as Pack; +use VDM\Joomla\Gitea\Package\Files; +use VDM\Joomla\Gitea\Package\Owner; + + +/** + * The Gitea Package Service + * + * @since 3.2.0 + */ +class Package implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 3.2.0 + */ + public function register(Container $container) + { + $container->alias(Pack::class, 'Gitea.Package') + ->share('Gitea.Package', [$this, 'getPackage'], true); + + $container->alias(Files::class, 'Gitea.Package.Files') + ->share('Gitea.Package.Files', [$this, 'getFiles'], true); + + $container->alias(Owner::class, 'Gitea.Package.Owner') + ->share('Gitea.Package.Owner', [$this, 'getOwner'], true); + } + + /** + * Get the Package class + * + * @param Container $container The DI container. + * + * @return Pack + * @since 3.2.0 + */ + public function getPackage(Container $container): Pack + { + return new Pack( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Files class + * + * @param Container $container The DI container. + * + * @return Files + * @since 3.2.0 + */ + public function getFiles(Container $container): Files + { + return new Files( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Owner class + * + * @param Container $container The DI container. + * + * @return Owner + * @since 3.2.0 + */ + public function getOwner(Container $container): Owner + { + return new Owner( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Repository.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Repository.php new file mode 100644 index 0000000..edfab0d --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Repository.php @@ -0,0 +1,836 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VDM\Joomla\Gitea\Repository as Repo; +use VDM\Joomla\Gitea\Repository\Archive; +use VDM\Joomla\Gitea\Repository\Assignees; +use VDM\Joomla\Gitea\Repository\Attachments; +use VDM\Joomla\Gitea\Repository\Branch; +use VDM\Joomla\Gitea\Repository\Branch\Protection; +use VDM\Joomla\Gitea\Repository\Collaborator; +use VDM\Joomla\Gitea\Repository\Commits; +use VDM\Joomla\Gitea\Repository\Contents; +use VDM\Joomla\Gitea\Repository\Forks; +use VDM\Joomla\Gitea\Repository\Gpg; +use VDM\Joomla\Gitea\Repository\Hooks; +use VDM\Joomla\Gitea\Repository\Hooks\Git; +use VDM\Joomla\Gitea\Repository\Keys; +use VDM\Joomla\Gitea\Repository\Languages; +use VDM\Joomla\Gitea\Repository\Media; +use VDM\Joomla\Gitea\Repository\Merge; +use VDM\Joomla\Gitea\Repository\Mirror; +use VDM\Joomla\Gitea\Repository\Mirrors; +use VDM\Joomla\Gitea\Repository\Notes; +use VDM\Joomla\Gitea\Repository\Patch; +use VDM\Joomla\Gitea\Repository\Pulls; +use VDM\Joomla\Gitea\Repository\Refs; +use VDM\Joomla\Gitea\Repository\Releases; +use VDM\Joomla\Gitea\Repository\Remote; +use VDM\Joomla\Gitea\Repository\Reviewers; +use VDM\Joomla\Gitea\Repository\Reviews; +use VDM\Joomla\Gitea\Repository\Stargazers; +use VDM\Joomla\Gitea\Repository\Statuses; +use VDM\Joomla\Gitea\Repository\Tags; +use VDM\Joomla\Gitea\Repository\Teams; +use VDM\Joomla\Gitea\Repository\Templates; +use VDM\Joomla\Gitea\Repository\Times; +use VDM\Joomla\Gitea\Repository\Topics; +use VDM\Joomla\Gitea\Repository\Transfer; +use VDM\Joomla\Gitea\Repository\Trees; +use VDM\Joomla\Gitea\Repository\Watchers; +use VDM\Joomla\Gitea\Repository\Wiki; + + +/** + * The Gitea Repository Service + * + * @since 3.2.0 + */ +class Repository implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 3.2.0 + */ + public function register(Container $container) + { + $container->alias(Repo::class, 'Gitea.Repository') + ->share('Gitea.Repository', [$this, 'getRepository'], true); + + $container->alias(Archive::class, 'Gitea.Repository.Archive') + ->share('Gitea.Repository.Archive', [$this, 'getArchive'], true); + + $container->alias(Assignees::class, 'Gitea.Repository.Assignees') + ->share('Gitea.Repository.Assignees', [$this, 'getAssignees'], true); + + $container->alias(Attachments::class, 'Gitea.Repository.Attachments') + ->share('Gitea.Repository.Attachments', [$this, 'getAttachments'], true); + + $container->alias(Branch::class, 'Gitea.Repository.Branch') + ->share('Gitea.Repository.Branch', [$this, 'getBranch'], true); + + $container->alias(Protection::class, 'Gitea.Repository.Branch.Protection') + ->share('Gitea.Repository.Branch.Protection', [$this, 'getProtection'], true); + + $container->alias(Collaborator::class, 'Gitea.Repository.Collaborator') + ->share('Gitea.Repository.Collaborator', [$this, 'getCollaborator'], true); + + $container->alias(Commits::class, 'Gitea.Repository.Commits') + ->share('Gitea.Repository.Commits', [$this, 'getCommits'], true); + + $container->alias(Contents::class, 'Gitea.Repository.Contents') + ->share('Gitea.Repository.Contents', [$this, 'getContents'], true); + + $container->alias(Forks::class, 'Gitea.Repository.Forks') + ->share('Gitea.Repository.Forks', [$this, 'getForks'], true); + + $container->alias(Gpg::class, 'Gitea.Repository.Gpg') + ->share('Gitea.Repository.Gpg', [$this, 'getGpg'], true); + + $container->alias(Hooks::class, 'Gitea.Repository.Hooks') + ->share('Gitea.Repository.Hooks', [$this, 'getHooks'], true); + + $container->alias(Git::class, 'Gitea.Repository.Hooks.Git') + ->share('Gitea.Repository.Hooks.Git', [$this, 'getGit'], true); + + $container->alias(Keys::class, 'Gitea.Repository.Keys') + ->share('Gitea.Repository.Keys', [$this, 'getKeys'], true); + + $container->alias(Languages::class, 'Gitea.Repository.Languages') + ->share('Gitea.Repository.Languages', [$this, 'getLanguages'], true); + + $container->alias(Media::class, 'Gitea.Repository.Media') + ->share('Gitea.Repository.Media', [$this, 'getMedia'], true); + + $container->alias(Merge::class, 'Gitea.Repository.Merge') + ->share('Gitea.Repository.Merge', [$this, 'getMerge'], true); + + $container->alias(Mirror::class, 'Gitea.Repository.Mirror') + ->share('Gitea.Repository.Mirror', [$this, 'getMirror'], true); + + $container->alias(Mirrors::class, 'Gitea.Repository.Mirrors') + ->share('Gitea.Repository.Mirrors', [$this, 'getMirrors'], true); + + $container->alias(Notes::class, 'Gitea.Repository.Notes') + ->share('Gitea.Repository.Notes', [$this, 'getNotes'], true); + + $container->alias(Patch::class, 'Gitea.Repository.Patch') + ->share('Gitea.Repository.Patch', [$this, 'getPatch'], true); + + $container->alias(Pulls::class, 'Gitea.Repository.Pulls') + ->share('Gitea.Repository.Pulls', [$this, 'getPulls'], true); + + $container->alias(Refs::class, 'Gitea.Repository.Refs') + ->share('Gitea.Repository.Refs', [$this, 'getRefs'], true); + + $container->alias(Releases::class, 'Gitea.Repository.Releases') + ->share('Gitea.Repository.Releases', [$this, 'getReleases'], true); + + $container->alias(Remote::class, 'Gitea.Repository.Remote') + ->share('Gitea.Repository.Remote', [$this, 'getRemote'], true); + + $container->alias(Reviewers::class, 'Gitea.Repository.Reviewers') + ->share('Gitea.Repository.Reviewers', [$this, 'getReviewers'], true); + + $container->alias(Reviews::class, 'Gitea.Repository.Reviews') + ->share('Gitea.Repository.Reviews', [$this, 'getReviews'], true); + + $container->alias(Stargazers::class, 'Gitea.Repository.Stargazers') + ->share('Gitea.Repository.Stargazers', [$this, 'getStargazers'], true); + + $container->alias(Statuses::class, 'Gitea.Repository.Statuses') + ->share('Gitea.Repository.Statuses', [$this, 'getStatuses'], true); + + $container->alias(Tags::class, 'Gitea.Repository.Tags') + ->share('Gitea.Repository.Tags', [$this, 'getTags'], true); + + $container->alias(Teams::class, 'Gitea.Repository.Teams') + ->share('Gitea.Repository.Teams', [$this, 'getTeams'], true); + + $container->alias(Templates::class, 'Gitea.Repository.Templates') + ->share('Gitea.Repository.Templates', [$this, 'getTemplates'], true); + + $container->alias(Times::class, 'Gitea.Repository.Times') + ->share('Gitea.Repository.Times', [$this, 'getTimes'], true); + + $container->alias(Topics::class, 'Gitea.Repository.Topics') + ->share('Gitea.Repository.Topics', [$this, 'getTopics'], true); + + $container->alias(Transfer::class, 'Gitea.Repository.Transfer') + ->share('Gitea.Repository.Transfer', [$this, 'getTransfer'], true); + + $container->alias(Trees::class, 'Gitea.Repository.Trees') + ->share('Gitea.Repository.Trees', [$this, 'getTrees'], true); + + $container->alias(Watchers::class, 'Gitea.Repository.Watchers') + ->share('Gitea.Repository.Watchers', [$this, 'getWatchers'], true); + + $container->alias(Wiki::class, 'Gitea.Repository.Wiki') + ->share('Gitea.Repository.Wiki', [$this, 'getWiki'], true); + } + + /** + * Get the Repository class + * + * @param Container $container The DI container. + * + * @return Repo + * @since 3.2.0 + */ + public function getRepository(Container $container): Repo + { + return new Repo( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Archive class + * + * @param Container $container The DI container. + * + * @return Archive + * @since 3.2.0 + */ + public function getArchive(Container $container): Archive + { + return new Archive( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Assignees class + * + * @param Container $container The DI container. + * + * @return Assignees + * @since 3.2.0 + */ + public function getAssignees(Container $container): Assignees + { + return new Assignees( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Attachments class + * + * @param Container $container The DI container. + * + * @return Attachments + * @since 3.2.0 + */ + public function getAttachments(Container $container): Attachments + { + return new Attachments( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Branch class + * + * @param Container $container The DI container. + * + * @return Branch + * @since 3.2.0 + */ + public function getBranch(Container $container): Branch + { + return new Branch( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Branch Protection class + * + * @param Container $container The DI container. + * + * @return Protection + * @since 3.2.0 + */ + public function getProtection(Container $container): Protection + { + return new Protection( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Collaborator class + * + * @param Container $container The DI container. + * + * @return Collaborator + * @since 3.2.0 + */ + public function getCollaborator(Container $container): Collaborator + { + return new Collaborator( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Commits class + * + * @param Container $container The DI container. + * + * @return Commits + * @since 3.2.0 + */ + public function getCommits(Container $container): Commits + { + return new Commits( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Contents class + * + * @param Container $container The DI container. + * + * @return Contents + * @since 3.2.0 + */ + public function getContents(Container $container): Contents + { + return new Contents( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Forks class + * + * @param Container $container The DI container. + * + * @return Forks + * @since 3.2.0 + */ + public function getForks(Container $container): Forks + { + return new Forks( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Gpg class + * + * @param Container $container The DI container. + * + * @return Gpg + * @since 3.2.0 + */ + public function getGpg(Container $container): Gpg + { + return new Gpg( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Hooks class + * + * @param Container $container The DI container. + * + * @return Hooks + * @since 3.2.0 + */ + public function getHooks(Container $container): Hooks + { + return new Hooks( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Hooks Git class + * + * @param Container $container The DI container. + * + * @return Git + * @since 3.2.0 + */ + public function getGit(Container $container): Git + { + return new Git( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Keys class + * + * @param Container $container The DI container. + * + * @return Keys + * @since 3.2.0 + */ + public function getKeys(Container $container): Keys + { + return new Keys( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Languages class + * + * @param Container $container The DI container. + * + * @return Languages + * @since 3.2.0 + */ + public function getLanguages(Container $container): Languages + { + return new Languages( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Media class + * + * @param Container $container The DI container. + * + * @return Media + * @since 3.2.0 + */ + public function getMedia(Container $container): Media + { + return new Media( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Merge class + * + * @param Container $container The DI container. + * + * @return Merge + * @since 3.2.0 + */ + public function getMerge(Container $container): Merge + { + return new Merge( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Mirror class + * + * @param Container $container The DI container. + * + * @return Mirror + * @since 3.2.0 + */ + public function getMirror(Container $container): Mirror + { + return new Mirror( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Mirrors class + * + * @param Container $container The DI container. + * + * @return Mirrors + * @since 3.2.0 + */ + public function getMirrors(Container $container): Mirrors + { + return new Mirrors( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Notes class + * + * @param Container $container The DI container. + * + * @return Notes + * @since 3.2.0 + */ + public function getNotes(Container $container): Notes + { + return new Notes( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Patch class + * + * @param Container $container The DI container. + * + * @return Patch + * @since 3.2.0 + */ + public function getPatch(Container $container): Patch + { + return new Patch( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Pulls class + * + * @param Container $container The DI container. + * + * @return Pulls + * @since 3.2.0 + */ + public function getPulls(Container $container): Pulls + { + return new Pulls( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Refs class + * + * @param Container $container The DI container. + * + * @return Refs + * @since 3.2.0 + */ + public function getRefs(Container $container): Refs + { + return new Refs( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Releases class + * + * @param Container $container The DI container. + * + * @return Releases + * @since 3.2.0 + */ + public function getReleases(Container $container): Releases + { + return new Releases( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Remote class + * + * @param Container $container The DI container. + * + * @return Remote + * @since 3.2.0 + */ + public function getRemote(Container $container): Remote + { + return new Remote( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Reviewers class + * + * @param Container $container The DI container. + * + * @return Reviewers + * @since 3.2.0 + */ + public function getReviewers(Container $container): Reviewers + { + return new Reviewers( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Reviews class + * + * @param Container $container The DI container. + * + * @return Reviews + * @since 3.2.0 + */ + public function getReviews(Container $container): Reviews + { + return new Reviews( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Stargazers class + * + * @param Container $container The DI container. + * + * @return Stargazers + * @since 3.2.0 + */ + public function getStargazers(Container $container): Stargazers + { + return new Stargazers( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Statuses class + * + * @param Container $container The DI container. + * + * @return Statuses + * @since 3.2.0 + */ + public function getStatuses(Container $container): Statuses + { + return new Statuses( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Tags class + * + * @param Container $container The DI container. + * + * @return Tags + * @since 3.2.0 + */ + public function getTags(Container $container): Tags + { + return new Tags( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Teams class + * + * @param Container $container The DI container. + * + * @return Teams + * @since 3.2.0 + */ + public function getTeams(Container $container): Teams + { + return new Teams( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Templates class + * + * @param Container $container The DI container. + * + * @return Templates + * @since 3.2.0 + */ + public function getTemplates(Container $container): Templates + { + return new Templates( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Times class + * + * @param Container $container The DI container. + * + * @return Times + * @since 3.2.0 + */ + public function getTimes(Container $container): Times + { + return new Times( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Topics class + * + * @param Container $container The DI container. + * + * @return Topics + * @since 3.2.0 + */ + public function getTopics(Container $container): Topics + { + return new Topics( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Transfer class + * + * @param Container $container The DI container. + * + * @return Transfer + * @since 3.2.0 + */ + public function getTransfer(Container $container): Transfer + { + return new Transfer( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Trees class + * + * @param Container $container The DI container. + * + * @return Trees + * @since 3.2.0 + */ + public function getTrees(Container $container): Trees + { + return new Trees( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Watchers class + * + * @param Container $container The DI container. + * + * @return Watchers + * @since 3.2.0 + */ + public function getWatchers(Container $container): Watchers + { + return new Watchers( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Wiki class + * + * @param Container $container The DI container. + * + * @return Wiki + * @since 3.2.0 + */ + public function getWiki(Container $container): Wiki + { + return new Wiki( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Settings.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Settings.php new file mode 100644 index 0000000..e4b1a7e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Settings.php @@ -0,0 +1,123 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VDM\Joomla\Gitea\Settings\Api; +use VDM\Joomla\Gitea\Settings\Attachment; +use VDM\Joomla\Gitea\Settings\Repository; +use VDM\Joomla\Gitea\Settings\Ui; + + +/** + * The Gitea Settings Service + * + * @since 3.2.0 + */ +class Settings implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 3.2.0 + */ + public function register(Container $container) + { + $container->alias(Api::class, 'Gitea.Settings.Api') + ->share('Gitea.Settings.Api', [$this, 'getApi'], true); + + $container->alias(Attachment::class, 'Gitea.Settings.Attachment') + ->share('Gitea.Settings.Attachment', [$this, 'getAttachment'], true); + + $container->alias(Repository::class, 'Gitea.Settings.Repository') + ->share('Gitea.Settings.Repository', [$this, 'getRepository'], true); + + $container->alias(Ui::class, 'Gitea.Settings.Ui') + ->share('Gitea.Settings.Ui', [$this, 'getUi'], true); + } + + /** + * Get the Api class + * + * @param Container $container The DI container. + * + * @return Api + * @since 3.2.0 + */ + public function getApi(Container $container): Api + { + return new Api( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Attachment class + * + * @param Container $container The DI container. + * + * @return Attachment + * @since 3.2.0 + */ + public function getAttachment(Container $container): Attachment + { + return new Attachment( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Repository class + * + * @param Container $container The DI container. + * + * @return Repository + * @since 3.2.0 + */ + public function getRepository(Container $container): Repository + { + return new Repository( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Ui class + * + * @param Container $container The DI container. + * + * @return Ui + * @since 3.2.0 + */ + public function getUi(Container $container): Ui + { + return new Ui( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/User.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/User.php new file mode 100644 index 0000000..63bc120 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/User.php @@ -0,0 +1,332 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VDM\Joomla\Gitea\User as Usr; +use VDM\Joomla\Gitea\User\Applications; +use VDM\Joomla\Gitea\User\Emails; +use VDM\Joomla\Gitea\User\Followers; +use VDM\Joomla\Gitea\User\Following; +use VDM\Joomla\Gitea\User\Gpg; +use VDM\Joomla\Gitea\User\Keys; +use VDM\Joomla\Gitea\User\Repos; +use VDM\Joomla\Gitea\User\Settings; +use VDM\Joomla\Gitea\User\Starred; +use VDM\Joomla\Gitea\User\Subscriptions; +use VDM\Joomla\Gitea\User\Teams; +use VDM\Joomla\Gitea\User\Times; +use VDM\Joomla\Gitea\User\Tokens; + + +/** + * The Gitea User Service + * + * @since 3.2.0 + */ +class User implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 3.2.0 + */ + public function register(Container $container) + { + $container->alias(Usr::class, 'Gitea.User') + ->share('Gitea.User', [$this, 'getUser'], true); + + $container->alias(Applications::class, 'Gitea.User.Applications') + ->share('Gitea.User.Applications', [$this, 'getApplications'], true); + + $container->alias(Emails::class, 'Gitea.User.Emails') + ->share('Gitea.User.Emails', [$this, 'getEmails'], true); + + $container->alias(Followers::class, 'Gitea.User.Followers') + ->share('Gitea.User.Followers', [$this, 'getFollowers'], true); + + $container->alias(Following::class, 'Gitea.User.Following') + ->share('Gitea.User.Following', [$this, 'getFollowing'], true); + + $container->alias(Gpg::class, 'Gitea.User.Gpg') + ->share('Gitea.User.Gpg', [$this, 'getGpg'], true); + + $container->alias(Keys::class, 'Gitea.User.Keys') + ->share('Gitea.User.Keys', [$this, 'getKeys'], true); + + $container->alias(Repos::class, 'Gitea.User.Repos') + ->share('Gitea.User.Repos', [$this, 'getRepos'], true); + + $container->alias(Settings::class, 'Gitea.User.Settings') + ->share('Gitea.User.Settings', [$this, 'getSettings'], true); + + $container->alias(Starred::class, 'Gitea.User.Starred') + ->share('Gitea.User.Starred', [$this, 'getStarred'], true); + + $container->alias(Subscriptions::class, 'Gitea.User.Subscriptions') + ->share('Gitea.User.Subscriptions', [$this, 'getSubscriptions'], true); + + $container->alias(Teams::class, 'Gitea.User.Teams') + ->share('Gitea.User.Teams', [$this, 'getTeams'], true); + + $container->alias(Times::class, 'Gitea.User.Times') + ->share('Gitea.User.Times', [$this, 'getTimes'], true); + + $container->alias(Tokens::class, 'Gitea.User.Tokens') + ->share('Gitea.User.Tokens', [$this, 'getTokens'], true); + } + + /** + * Get the User class + * + * @param Container $container The DI container. + * + * @return Usr + * @since 3.2.0 + */ + public function getUser(Container $container): Usr + { + return new Usr( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Applications class + * + * @param Container $container The DI container. + * + * @return Applications + * @since 3.2.0 + */ + public function getApplications(Container $container): Applications + { + return new Applications( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Emails class + * + * @param Container $container The DI container. + * + * @return Emails + * @since 3.2.0 + */ + public function getEmails(Container $container): Emails + { + return new Emails( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Followers class + * + * @param Container $container The DI container. + * + * @return Followers + * @since 3.2.0 + */ + public function getFollowers(Container $container): Followers + { + return new Followers( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Following class + * + * @param Container $container The DI container. + * + * @return Following + * @since 3.2.0 + */ + public function getFollowing(Container $container): Following + { + return new Following( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Gpg class + * + * @param Container $container The DI container. + * + * @return Gpg + * @since 3.2.0 + */ + public function getGpg(Container $container): Gpg + { + return new Gpg( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Keys class + * + * @param Container $container The DI container. + * + * @return Keys + * @since 3.2.0 + */ + public function getKeys(Container $container): Keys + { + return new Keys( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Repos class + * + * @param Container $container The DI container. + * + * @return Repos + * @since 3.2.0 + */ + public function getRepos(Container $container): Repos + { + return new Repos( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Settings class + * + * @param Container $container The DI container. + * + * @return Settings + * @since 3.2.0 + */ + public function getSettings(Container $container): Settings + { + return new Settings( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Starred class + * + * @param Container $container The DI container. + * + * @return Starred + * @since 3.2.0 + */ + public function getStarred(Container $container): Starred + { + return new Starred( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Subscriptions class + * + * @param Container $container The DI container. + * + * @return Subscriptions + * @since 3.2.0 + */ + public function getSubscriptions(Container $container): Subscriptions + { + return new Subscriptions( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Teams class + * + * @param Container $container The DI container. + * + * @return Teams + * @since 3.2.0 + */ + public function getTeams(Container $container): Teams + { + return new Teams( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Times class + * + * @param Container $container The DI container. + * + * @return Times + * @since 3.2.0 + */ + public function getTimes(Container $container): Times + { + return new Times( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + + /** + * Get the Tokens class + * + * @param Container $container The DI container. + * + * @return Tokens + * @since 3.2.0 + */ + public function getTokens(Container $container): Tokens + { + return new Tokens( + $container->get('Gitea.Utilities.Http'), + $container->get('Gitea.Dynamic.Uri'), + $container->get('Gitea.Utilities.Response') + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Utilities.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Utilities.php new file mode 100644 index 0000000..09112d2 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/Utilities.php @@ -0,0 +1,72 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VDM\Joomla\Gitea\Utilities\Uri; +use VDM\Joomla\Gitea\Utilities\Response; + + +/** + * The Gitea Utilities Service + * + * @since 3.2.0 + */ +class Utilities implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 3.2.0 + */ + public function register(Container $container) + { + $container->alias(Uri::class, 'Gitea.Utilities.Uri') + ->share('Gitea.Utilities.Uri', [$this, 'getUri'], true); + + $container->alias(Response::class, 'Gitea.Utilities.Response') + ->share('Gitea.Utilities.Response', [$this, 'getResponse'], true); + } + + /** + * Get the Uri class + * + * @param Container $container The DI container. + * + * @return Uri + * @since 3.2.0 + */ + public function getUri(Container $container): Uri + { + return new Uri(); + } + + /** + * Get the Response class + * + * @param Container $container The DI container. + * + * @return Response + * @since 3.2.0 + */ + public function getResponse(Container $container): Response + { + return new Response(); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/index.html b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Service/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Settings/Api.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Settings/Api.php new file mode 100644 index 0000000..cf2d56f --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Settings/Api.php @@ -0,0 +1,45 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Settings; + + +use VDM\Joomla\Gitea\Abstraction\Api as BaseAPI; + + +/** + * The Gitea Settings Api + * + * @since 3.2.0 + */ +class Api extends BaseAPI +{ + /** + * Get instance's global settings for API. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(): ?object + { + // Build the request path. + $path = "/settings/api"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Settings/Attachment.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Settings/Attachment.php new file mode 100644 index 0000000..9219388 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Settings/Attachment.php @@ -0,0 +1,45 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Settings; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Settings Attachment + * + * @since 3.2.0 + */ +class Attachment extends Api +{ + /** + * Get instance's global settings for Attachment. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(): ?object + { + // Build the request path. + $path = "/settings/attachment"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Settings/Repository.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Settings/Repository.php new file mode 100644 index 0000000..adbf908 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Settings/Repository.php @@ -0,0 +1,45 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Settings; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Settings Repository + * + * @since 3.2.0 + */ +class Repository extends Api +{ + /** + * Get instance's global settings for repositories. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(): ?object + { + // Build the request path. + $path = "/settings/repository"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Settings/Ui.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Settings/Ui.php new file mode 100644 index 0000000..def2668 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Settings/Ui.php @@ -0,0 +1,45 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Settings; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea Settings Ui + * + * @since 3.2.0 + */ +class Ui extends Api +{ + /** + * Get instance's global settings for UI. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(): ?object + { + // Build the request path. + $path = "/settings/ui"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Settings/index.html b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Settings/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Settings/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/User.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User.php new file mode 100644 index 0000000..bb9c82e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User.php @@ -0,0 +1,335 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea User + * + * @since 3.2.0 + */ +class User extends Api +{ + /** + * Get the authenticated user. + * + * @return object|null + * @since 3.2.0 + **/ + public function authenticate(): ?object + { + // Build the request path. + $path = '/user'; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Search for users. + * + * @param string $keyword The search keyword. + * @param int|null $uid Optional. ID of the user to search for. + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return object|null + * @since 3.2.0 + **/ + public function search( + string $keyword, + ?int $uid = null, + int $page = 1, + int $limit = 10 + ): ?object + { + // Build the request path. + $path = '/users/search'; + + // Build the URI with query parameters. + $uri = $this->uri->get($path); + $uri->setVar('q', $keyword); + + if ($uid !== null) + { + $uri->setVar('uid', $uid); + } + + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get a user by their username. + * + * @param string $username The username of the user to retrieve. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(string $username): o?bject + { + // Build the request path. + $path = "/users/{$username}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * List the given user's followers. + * + * @param string $userName The username of the user to retrieve followers for. + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function followers( + string $userName, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/users/{$userName}/followers"; + + // Build the URI with query parameters. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * List the users that the given user is following. + * + * @param string $userName The username of the user to retrieve the following users for. + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function following( + string $userName, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/users/{$userName}/following"; + + // Build the URI with query parameters. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Check if one user is following another user. + * + * @param string $username The username of the user to check. + * @param string $target The username of the target user. + * + * @return string + * @since 3.2.0 + **/ + public function check(string $username, string $target): string + { + // Build the request path. + $path = "/users/{$username}/following/{$target}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * List the given user's GPG keys. + * + * @param string $userName The username of the user to retrieve GPG keys for. + * @param int $page The page number of results to return (1-based). + * @param int $limit The page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function gpg( + string $userName, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/users/{$userName}/gpg_keys"; + + // Build the URI with query parameters. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get a user's heatmap. + * + * @param string $username The username of the user to retrieve heatmap for. + * + * @return array|null + * @since 3.2.0 + **/ + public function heatmap(string $username): ?array + { + // Build the request path. + $path = "/users/{$username}/heatmap"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * List the given user's public keys. + * + * @param string $userName The username of the user to retrieve public keys for. + * @param string|null $fingerprint Optional. The fingerprint of the key. + * @param int $page The page number of results to return (1-based). + * @param int $limit The page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function keys( + string $userName, + ?string $fingerprint = null, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/users/{$userName}/keys"; + + // Build the URI with query parameters. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + if ($fingerprint !== null) + { + $uri->setVar('fingerprint', $fingerprint); + } + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * List the repos that the given user has starred. + * + * @param string $userName The username of the user to retrieve starred repos for. + * @param int $page The page number of results to return (1-based). + * @param int $limit The page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function repos( + string $userName, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/users/{$userName}/starred"; + + // Build the URI with query parameters. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * List the repositories watched by a user. + * + * @param string $userName The username of the user to retrieve watched repositories for. + * @param int $page The page number of results to return (1-based). + * @param int $limit The page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function watched( + string $userName, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = "/users/{$userName}/subscriptions"; + + // Build the URI with query parameters. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Applications.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Applications.php new file mode 100644 index 0000000..10d8dc6 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Applications.php @@ -0,0 +1,166 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\User; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea User Applications + * + * @since 3.2.0 + */ +class Applications extends Api +{ + /** + * List the authenticated user's oauth2 applications. + * + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function get( + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = '/user/applications/oauth2'; + + // Build the URI with query parameters. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get an OAuth2 application by ID. + * + * @param int $id The OAuth2 application ID. + * + * @return object|null + * @since 3.2.0 + **/ + public function id(int $id): ?object + { + // Build the request path. + $path = "/user/applications/oauth2/{$id}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Creates a new OAuth2 application. + * + * @param string $appName The application name. + * @param array $redirectUris The application redirect URIs. + * @param bool $confidentialClient The confidentiality of the client (default: true). + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $appName, + array $redirectUris, + bool $confidentialClient = true + ): ?object + { + // Build the request path. + $path = '/user/applications/oauth2'; + + // Set the application data. + $data = new \stdClass(); + $data->name = $appName; + $data->redirect_uris = $redirectUris; + $data->confidential_client = $confidentialClient; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + json_encode($data) + ), 201 + ); + } + + /** + * Delete an OAuth2 application by ID. + * + * @param int $id The OAuth2 application ID. + * + * @return string + * @since 3.2.0 + **/ + public function delete(int $id): string + { + // Build the request path. + $path = "/user/applications/oauth2/{$id}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + + /** + * Update an OAuth2 application by ID, this includes regenerating the client secret. + * + * @param int $appId The OAuth2 application ID. + * @param string $appName The application name. + * @param array $redirectUris The application redirect URIs. + * @param bool $confidentialClient The confidentiality of the client (default: true). + * + * @return object|null + * @since 3.2.0 + **/ + public function update( + int $appId, + string $appName, + array $redirectUris, + bool $confidentialClient = true + ): ?object + { + // Build the request path. + $path = "/user/applications/oauth2/{$appId}"; + + // Set the application data. + $data = new \stdClass(); + $data->name = $appName; + $data->redirect_uris = $redirectUris; + $data->confidential_client = $confidentialClient; + + // Send the patch request. + return $this->response->get( + $this->http->patch( + $this->uri->get($path), + json_encode($data) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Emails.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Emails.php new file mode 100644 index 0000000..aa63b28 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Emails.php @@ -0,0 +1,94 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\User; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea User Emails + * + * @since 3.2.0 + */ +class Emails extends Api +{ + /** + * List the authenticated user's email addresses. + * + * @return array|null + * @since 3.2.0 + **/ + public function list(): ?array + { + // Build the request path. + $path = '/user/emails'; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Add email addresses for the authenticated user. + * + * @param array $emails An array of email addresses to add. + * + * @return array|null + * @since 3.2.0 + **/ + public function add(array $emails): ?array + { + // Build the request path. + $path = '/user/emails'; + + // Create the request body. + $body = new \stdClass(); + $body->emails = $emails; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + json_encode($body) + ), 201 + ); + } + + /** + * Delete email addresses for the authenticated user. + * + * @param array $$emails An array of email addresses to delete. + * + * @return string + * @since 3.2.0 + **/ + public function delete(array $emails): string + { + // Build the request path. + $path = '/user/emails'; + + // Build the URI. + $uri = $this->uri->get($path); + $uri->setVar('emails', json_encode($emails)); + + // Send the delete request. + return $this->response->get( + $this->http->delete($uri), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Followers.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Followers.php new file mode 100644 index 0000000..71b028a --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Followers.php @@ -0,0 +1,54 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\User; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea User Followers + * + * @since 3.2.0 + */ +class Followers extends Api +{ + /** + * List the authenticated user's followers. + * + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = '/user/followers'; + + // Build the URL + $url = $this->uri->get($path); + $url->setVar('page', $page); + $url->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($url) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Following.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Following.php new file mode 100644 index 0000000..3392449 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Following.php @@ -0,0 +1,122 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\User; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea User Following + * + * @since 3.2.0 + */ +class Following extends Api +{ + /** + * List the users that the authenticated user is following. + * + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = '/user/following'; + + // Build the URL + $url = $this->uri->get($path); + $url->setVar('page', $page); + $url->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($url) + ); + } + + /** + * Check whether a user is followed by the authenticated user. + * + * @param string $username The username to check. + * + * @return bool + * @since 3.2.0 + **/ + public function check(string $username): bool + { + // Build the request path. + $path = "/user/following/{$username}"; + + // Send the get request. + $response = $this->http->get( + $this->uri->get($path) + ); + + // Check if the user is followed by the authenticated user. + if ($response->code === 204) + { + return true; + } + return false; + } + + /** + * Follow a user. + * + * @param string $username The username to follow. + * + * @return string + * @since 3.2.0 + **/ + public function follow(string $username): string + { + // Build the request path. + $path = "/user/following/{$username}"; + + // Send the put request. + return $this->response->get( + $this->http->put( + $this->uri->get($path), '' + ), 204, 'success' + ); + } + + /** + * Unfollow a user. + * + * @param string $username The username to unfollow. + * + * @return string + * @since 3.2.0 + **/ + public function unfollow(string $username): string + { + // Build the request path. + $path = "/user/following/{$username}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Gpg.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Gpg.php new file mode 100644 index 0000000..bf8f6c6 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Gpg.php @@ -0,0 +1,173 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\User; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea User Gpg + * + * @since 3.2.0 + */ +class Gpg extends Api +{ + /** + * Create a GPG key for the authenticated user. + * + * @param string $armoredPublicKey The armored public GPG key. + * @param string|null $armoredSignature The armored signature (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function createGPGKey( + string $armoredPublicKey, + ?string $armoredSignature = null + ): ?object + { + // Build the request path. + $path = '/user/gpg_keys'; + + // Set the GPG key data. + $data = array_filter([ + 'armored_public_key' => $armoredPublicKey, + 'armored_signature' => $armoredSignature + ]); + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + json_encode($data) + ), 201 + ); + } + + /** + * Get a GPG key for the authenticated user. + * + * @param int $id The GPG key ID. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(int $id): ?object + { + // Build the request path. + $path = "/user/gpg_keys/{$id}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Get a token to verify. + * + * @return string|null + * @since 3.2.0 + **/ + public function token(): ?string + { + // Build the request path. + $path = '/user/gpg_key_token'; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Verify a GPG key. + * + * @param string $armoredPublicKey The armored public GPG key. + * + * @return object|null + * @since 3.2.0 + **/ + public function verify(string $armoredPublicKey): ?object + { + // Build the request path. + $path = '/user/gpg_key_verify'; + + // Set the GPG key data. + $data = new \stdClass(); + $data->armoredPublicKey = $armoredPublicKey; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + json_encode($data) + ), 201 + ); + } + + /** + * List the authenticated user's GPG keys. + * + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = '/user/gpg_keys'; + + // Build the URL + $url = $this->uri->get($path); + $url->setVar('page', $page); + $url->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($url) + ); + } + + /** + * Remove a GPG key for the authenticated user. + * + * @param int $id The GPG key ID. + * + * @return string + * @since 3.2.0 + **/ + public function remove(int $id): string + { + // Build the request path. + $path = "/user/gpg_keys/{$id}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Keys.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Keys.php new file mode 100644 index 0000000..ed22c40 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Keys.php @@ -0,0 +1,135 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\User; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea User Keys + * + * @since 3.2.0 + */ +class Keys extends Api +{ + /** + * Create a public key for the authenticated user. + * + * @param string $title The title of the public key. + * @param string $key The content of the public key. + * @param bool $readOnly Optional. True if the key has only read access, false for read/write access. + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $title, + string $key, + bool $readOnly = false + ): ?object + { + // Build the request path. + $path = '/user/keys'; + + // Set the public key data. + $data = new \stdClass(); + $data->title = $title; + $data->key = $key; + $data->read_only = $readOnly; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + json_encode($data) + ), 201 + ); + } + + /** + * List the authenticated user's public keys. + * + * @param string|null $fingerprint Optional. The fingerprint of the key. + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + ?string $fingerprint = null, + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = '/user/keys'; + + // Build the URI with query parameters. + $uri = $this->uri->get($path); + if ($fingerprint !== null) { + $uri->setVar('fingerprint', $fingerprint); + } + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Get a public key for the authenticated user. + * + * @param int $id The public key ID. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(int $id): ?object + { + // Build the request path. + $path = "/user/keys/{$id}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Delete a public key for the authenticated user. + * + * @param int $id The public key ID. + * + * @return string + * @since 3.2.0 + **/ + public function delete(int $id): string + { + // Build the request path. + $path = "/user/keys/{$id}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Repos.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Repos.php new file mode 100644 index 0000000..a7f8021 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Repos.php @@ -0,0 +1,188 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\User; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea User Repos + * + * @since 3.2.0 + */ +class Repos extends Api +{ + /** + * Create a repository for the authenticated user. + * + * @param string $name The name of the repository. + * @param string|null $description Optional. The description of the repository. + * @param bool $private Optional. Indicates whether the repository should be private or not. + * @param bool $autoInit Optional. Indicates whether the repository should be auto-initialized. + * @param string|null $defaultBranch Optional. The default branch of the repository. + * @param string|null $gitignores Optional. Gitignores to use. + * @param string|null $issueLabels Optional. Label-Set to use. + * @param string|null $license Optional. License to use. + * @param string|null $readme Optional. Readme of the repository to create. + * @param bool|null $template Optional. Whether the repository is a template. + * @param string|null $trustModel Optional. TrustModel of the repository. + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $name, + ?string $description = null, + bool $private = false, + bool $autoInit = false, + ?string $defaultBranch = null, + ?string $gitignores = null, + ?string $issueLabels = null, + ?string $license = null, + ?string $readme = null, + ?bool $template = null, + ?string $trustModel = null + ): ?object { + // Build the request path. + $path = '/user/repos'; + + // Set the repository data. + $data = new \stdClass(); + $data->name = $name; + + if ($description !== null) + { + $data->description = $description; + } + + $data->private = $private; + $data->auto_init = $autoInit; + + if ($defaultBranch !== null) + { + $data->default_branch = $defaultBranch; + } + + if ($gitignores !== null) + { + $data->gitignores = $gitignores; + } + + if ($issueLabels !== null) + { + $data->issue_labels = $issueLabels; + } + + if ($license !== null) + { + $data->license = $license; + } + + if ($readme !== null) + { + $data->readme = $readme; + } + + if ($template !== null) + { + $data->template = $template; + } + + if ($trustModel !== null) + { + $data->trust_model = $trustModel; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + json_encode($data) + ), 201 + ); + } + + /** + * List the repos that the authenticated user owns. + * + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = '/user/repos'; + + // Build the URI with query parameters. + $uri = $this->uri->get($path); + $uri->setVar('page', $page); + $uri->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Star the given repo for the authenticated user. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * + * @return string + * @since 3.2.0 + **/ + public function star(string $owner, string $repo): string + { + // Build the request path. + $path = "/user/starred/{$owner}/{$repo}"; + + // Send the put request. + return $this->response->get( + $this->http->put( + $this->uri->get($path), '' + ), 204, 'success' + ); + } + + /** + * Unstar the given repo for the authenticated user. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * + * @return string + * @since 3.2.0 + **/ + public function unstar(string $owner, string $repo): string + { + // Build the request path. + $path = "/user/starred/{$owner}/{$repo}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Settings.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Settings.php new file mode 100644 index 0000000..2118c9e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Settings.php @@ -0,0 +1,124 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\User; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea User Settings + * + * @since 3.2.0 + */ +class Settings extends Api +{ + /** + * Get user settings for the authenticated user. + * + * @return object|null + * @since 3.2.0 + **/ + public function get(): ?object + { + // Build the request path. + $path = '/user/settings'; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Update user settings for the authenticated user. + * + * @param string|null $description Optional. The description to update. + * @param string|null $diffViewStyle Optional. The diff view style to update. + * @param string|null $fullName Optional. The full name to update. + * @param bool|null $hideActivity Optional. Whether to hide activity or not. + * @param bool|null $hideEmail Optional. Whether to hide email or not. + * @param string|null $language Optional. The language to update. + * @param string|null $location Optional. The location to update. + * @param string|null $theme Optional. The theme to update. + * @param string|null $website Optional. The website to update. + * + * @return array|null + * @since 3.2.0 + **/ + public function update( + ?string $description = null, + ?string $diffViewStyle = null, + ?string $fullName = null, + ?bool $hideActivity = null, + ?bool $hideEmail = null, + ?string $language = null, + ?string $location = null, + ?string $theme = null, + ?string $website = null + ): ?array + { + // Prepare settings data + $settings = []; + if ($description !== null) + { + $settings['description'] = $description; + } + if ($diffViewStyle !== null) + { + $settings['diff_view_style'] = $diffViewStyle; + } + if ($fullName !== null) + { + $settings['full_name'] = $fullName; + } + if ($hideActivity !== null) + { + $settings['hide_activity'] = $hideActivity; + } + if ($hideEmail !== null) + { + $settings['hide_email'] = $hideEmail; + } + if ($language !== null) + { + $settings['language'] = $language; + } + if ($location !== null) + { + $settings['location'] = $location; + } + if ($theme !== null) + { + $settings['theme'] = $theme; + } + if ($website !== null) + { + $settings['website'] = $website; + } + + // Build the request path. + $path = '/user/settings'; + + // Send the patch request. + return $this->response->get( + $this->http->patch( + $this->uri->get($path), + json_encode($settings) + ) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Starred.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Starred.php new file mode 100644 index 0000000..2414066 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Starred.php @@ -0,0 +1,76 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\User; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea User Starred + * + * @since 3.2.0 + */ +class Starred extends Api +{ + /** + * List the repos that the authenticated user has starred. + * + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = '/user/starred'; + + // Build the URL + $url = $this->uri->get($path); + $url->setVar('page', $page); + $url->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($url) + ); + } + + /** + * Check whether the authenticated user is starring the repo. + * + * @param string $owner The owner name. + * @param string $repo The repository name. + * + * @return string + * @since 3.2.0 + **/ + public function check(string $owner, string $repo): string + { + // Build the request path. + $path = "/user/starred/{$owner}/{$repo}"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Subscriptions.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Subscriptions.php new file mode 100644 index 0000000..b627803 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Subscriptions.php @@ -0,0 +1,54 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\User; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea User Subscriptions + * + * @since 3.2.0 + */ +class Subscriptions extends Api +{ + /** + * List repositories watched by the authenticated user. + * + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = '/user/subscriptions'; + + // Build the URL + $url = $this->uri->get($path); + $url->setVar('page', $page); + $url->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($url) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Teams.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Teams.php new file mode 100644 index 0000000..ce3f32b --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Teams.php @@ -0,0 +1,54 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\User; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea User Teams + * + * @since 3.2.0 + */ +class Teams extends Api +{ + /** + * List all the teams a user belongs to. + * + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = '/user/teams'; + + // Build the URL + $url = $this->uri->get($path); + $url->setVar('page', $page); + $url->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($url) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Times.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Times.php new file mode 100644 index 0000000..0274058 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Times.php @@ -0,0 +1,96 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\User; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea User Times + * + * @since 3.2.0 + */ +class Times extends Api +{ + /** + * List the current user's tracked times. + * + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * @param string|null $since Optional. Only show times updated after the given time (RFC 3339 format). + * @param string|null $before Optional. Only show times updated before the given time (RFC 3339 format). + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + int $page = 1, + int $limit = 10, + ?string $since = null, + ?string $before = null + ): ?array + { + // Build the request path. + $path = '/user/times'; + + // Build the URL + $url = $this->uri->get($path); + $url->setVar('page', $page); + $url->setVar('limit', $limit); + + if ($since !== null) + { + $url->setVar('since', $since); + } + + if ($before !== null) + { + $url->setVar('before', $before); + } + + // Send the get request. + return $this->response->get( + $this->http->get($url) + ); + } + + /** + * Get list of all existing stopwatches for the authenticated user. + * + * @param int $page Page number of results to return (1-based). + * @param int $limit Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function stopwatches( + int $page = 1, + int $limit = 10 + ): ?array + { + // Build the request path. + $path = '/user/stopwatches'; + + // Build the URL + $url = $this->uri->get($path); + $url->setVar('page', $page); + $url->setVar('limit', $limit); + + // Send the get request. + return $this->response->get( + $this->http->get($url) + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Tokens.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Tokens.php new file mode 100644 index 0000000..431ba71 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/Tokens.php @@ -0,0 +1,111 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\User; + + +use VDM\Joomla\Gitea\Abstraction\Api; + + +/** + * The Gitea User Tokens + * + * @since 3.2.0 + */ +class Tokens extends Api +{ + /** + * List the authenticated user's access tokens. + * + * @param string $username The username of the authenticated user to retrieve access tokens for. + * @param int|null $page Optional. Page number of results to return (1-based). + * @param int|null $limit Optional. Page size of results. + * + * @return array|null + * @since 3.2.0 + **/ + public function list( + string $username, + ?int $page = null, + ?int $limit = null + ): ?array + { + // Build the request path. + $path = "/users/{$username}/tokens"; + + // Build the URL + $url = $this->uri->get($path); + if ($page !== null) + { + $url->setVar('page', $page); + } + if ($limit !== null) + { + $url->setVar('limit', $limit); + } + + // Send the get request. + return $this->response->get( + $this->http->get($url) + ); + } + + /** + * Create an access token for a user. + * + * @param string $username The username of the user to create the access token for. + * @param string $name The name of the access token. + * + * @return object|null + * @since 3.2.0 + **/ + public function create(string $username, string $name): ?object + { + // Build the request path. + $path = "/users/{$username}/tokens"; + + // Set the token data + $data = new \stdClass(); + $data->name = $name; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), + json_encode($data) + ), 201 + ); + } + + /** + * Delete an access token for a user. + * + * @param string $username The username of the user to delete the access token for. + * @param string $token The token to delete. + * + * @return string + * @since 3.2.0 + **/ + public function delete(string $username, string $token): string + { + // Build the request path. + $path = "/users/{$username}/tokens/{$token}"; + + // Send the delete request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ), 204, 'success' + ); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/index.html b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/User/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Utilities/Http.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Utilities/Http.php new file mode 100644 index 0000000..7f0b817 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Utilities/Http.php @@ -0,0 +1,78 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Utilities; + + +use Joomla\CMS\Http\Http as JoomlaHttp; +use Joomla\Registry\Registry; + + +/** + * The Gitea Http + * + * @since 3.2.0 + */ +final class Http extends JoomlaHttp +{ + /** + * Constructor. + * + * @param string|null $token The Gitea API token. + * + * @since 3.2.0 + * @throws \InvalidArgumentException + **/ + public function __construct(?string $token) + { + // setup config + $config = [ + 'userAgent' => 'JoomlaGitea/3.0', + 'headers' => [ + 'Content-Type' => 'application/json' + ] + ]; + + // add the token if given + if (is_string($token)) + { + $config['headers']['Authorization'] = 'token ' . $token; + } + + $options = new Registry($config); + + // run parent constructor + parent::__construct($options); + } + + /** + * Change the Token. + * + * @param string $token The Gitea API token. + * + * @since 3.2.0 + **/ + public function setToken(string $token) + { + // get the current headers + $headers = (array) $this->getOption('headers', [ + 'Content-Type' => 'application/json' + ] + ); + + // add the token + $headers['Authorization'] = 'token ' . $token; + + $this->setOption('headers', $headers); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Utilities/Response.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Utilities/Response.php new file mode 100644 index 0000000..4b3574e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Utilities/Response.php @@ -0,0 +1,146 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Utilities; + + +use Joomla\CMS\Http\Response as JoomlaResponse; +use VDM\Joomla\Utilities\JsonHelper; +use VDM\Joomla\Utilities\StringHelper; + + +/** + * The Gitea Response + * + * @since 3.2.0 + */ +final class Response +{ + /** + * Process the response and decode it. + * + * @param JoomlaResponse $response The response. + * @param integer $expectedCode The expected "good" code. + * @param mixed $default The default if body not have length + * + * @return mixed + * + * @since 3.2.0 + * @throws \DomainException + **/ + public function get(JoomlaResponse $response, int $expectedCode = 200, $default = null) + { + // Validate the response code. + if ($response->code != $expectedCode) + { + // Decode the error response and throw an exception. + $message = $this->error($response); + + throw new \DomainException("Invalid response received from API. $message", $response->code); + + } + + return $this->body($response, $default); + } + + /** + * Process the response and decode it. (when we have multiple success codes) + * + * @param JoomlaResponse $response The response. + * @param array [$expectedCode => $default] The expected "good" code. and The default if body not have length + * + * @return mixed + * + * @since 3.2.0 + * @throws \DomainException + **/ + public function get_(JoomlaResponse $response, array $validate = [200 => null]) + { + // Validate the response code. + if (!isset($validate[$response->code])) + { + // Decode the error response and throw an exception. + $message = $this->error($response); + + throw new \DomainException("Invalid response received from API. $message", $response->code); + + } + + return $this->body($response, $validate[$response->code]); + } + + /** + * Return the body from the response + * + * @param JoomlaResponse $response The response. + * @param mixed $default The default if body not have length + * + * @return mixed + * @since 3.2.0 + **/ + protected function body(JoomlaResponse $response, $default = null) + { + // check that we have a body and that its JSON + if (isset($response->body) && StringHelper::check($response->body)) + { + if (JsonHelper::check($response->body)) + { + $body = json_decode((string) $response->body); + + if (isset($body->content_base64)) + { + $body->content = base64_decode((string) $body->content_base64); + } + + return $body; + } + + return $response->body; + } + + return $default; + } + + /** + * Get the error message from the return object + * + * @param JoomlaResponse $response The response. + * + * @return string + * @since 3.2.0 + **/ + protected function error(JoomlaResponse $response): string + { + // do we have a json string + if (isset($response->body) && JsonHelper::check($response->body)) + { + $error = json_decode($response->body); + } + else + { + return ''; + } + + // check + if (isset($error->error)) + { + return $error->error; + } + elseif (isset($error->message)) + { + return $error->message; + } + + return ''; + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Utilities/Uri.php b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Utilities/Uri.php new file mode 100644 index 0000000..d31ac8e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Utilities/Uri.php @@ -0,0 +1,140 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Gitea\Utilities; + + +use Joomla\Uri\Uri as JoomlaUri; + + +/** + * The Gitea Uri + * + * @since 3.2.0 + */ +final class Uri +{ + /** + * The api endpoint + * + * @var string + * @since 3.2.0 + */ + private string $endpoint; + + /** + * The api version + * + * @var string + * @since 3.2.0 + */ + private string $version; + + /** + * The api URL + * + * @var string + * @since 3.2.0 + */ + private string $url; + + /** + * Constructor + * + * @param string $url URL to the gitea system + * example: https://git.vdm.dev + * @param string $endpoint Endpoint to the gitea system + * @param string $version Version to the gitea system + * + * @since 3.2.0 + **/ + public function __construct( + string $url = 'https://git.vdm.dev', + string $endpoint = 'api', + string $version = 'v1') + { + // set the API details + $this->setUrl($url); + $this->setEndpoint($endpoint); + $this->setVersion($version); + } + + /** + * Method to build and return a full request URL for the request. This method will + * add appropriate pagination details if necessary and also prepend the API url + * to have a complete URL for the request. + * + * @param string $path URL to inflect + * + * @return JoomlaUri + * @since 3.2.0 + **/ + public function get(string $path): JoomlaUri + { + // Get a new Uri object focusing the api url and given path. + $uri = new JoomlaUri($this->api() . $path); + + return $uri; + } + + /** + * Get the full API URL + * + * @return string + * @since 3.2.0 + **/ + public function api(): string + { + return $this->url . '/' . $this->endpoint . '/' . $this->version; + } + + /** + * Set the URL of the API + * + * @param string $url URL to your gitea system + * example: https://git.vdm.dev + * + * @return void + * @since 3.2.0 + **/ + public function setUrl(string $url) + { + return $this->url = $url; + } + + /** + * Set the endpoint of the API + * + * @param string $endpoint endpoint to your gitea API + * + * @return void + * @since 3.2.0 + **/ + private function setEndpoint(string $endpoint) + { + return $this->endpoint = $endpoint; + } + + /** + * Set the version of the API + * + * @param string $version version to your gitea API + * + * @return void + * @since 3.2.0 + **/ + private function setVersion($version) + { + return $this->version = $version; + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/Utilities/index.html b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Utilities/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/Utilities/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Gitea/src/index.html b/libraries/jcb_powers/VDM.Joomla.Gitea/src/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Gitea/src/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Openai/index.html b/libraries/jcb_powers/VDM.Joomla.Openai/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Openai/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Openai/src/Abstraction/Api.php b/libraries/jcb_powers/VDM.Joomla.Openai/src/Abstraction/Api.php new file mode 100644 index 0000000..2824706 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Openai/src/Abstraction/Api.php @@ -0,0 +1,67 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Openai\Abstraction; + + +use VDM\Joomla\Openai\Utilities\Http; +use VDM\Joomla\Openai\Utilities\Uri; +use VDM\Joomla\Openai\Utilities\Response; + + +/** + * The Openai Api + * + * @since 3.2.0 + */ +abstract class Api +{ + /** + * The Http class + * + * @var Http + * @since 3.2.0 + */ + protected Http $http; + + /** + * The Uri class + * + * @var Uri + * @since 3.2.0 + */ + protected Uri $uri; + + /** + * The Response class + * + * @var Response + * @since 3.2.0 + */ + protected Response $response; + + /** + * Constructor. + * + * @param Http $http The http class. + * @param Uri $uri The uri class. + * @param Response $response The response class. + * + * @since 3.2.0 + **/ + public function __construct(Http $http, Uri $uri, Response $response) + { + $this->http = $http; + $this->uri = $uri; + $this->response = $response; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Openai/src/Abstraction/index.html b/libraries/jcb_powers/VDM.Joomla.Openai/src/Abstraction/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Openai/src/Abstraction/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Openai/src/Chat.php b/libraries/jcb_powers/VDM.Joomla.Openai/src/Chat.php new file mode 100644 index 0000000..deb9097 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Openai/src/Chat.php @@ -0,0 +1,142 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Openai; + + +use VDM\Joomla\Openai\Abstraction\Api; + + +/** + * The Openai Chat + * + * @since 3.2.0 + */ +class Chat extends Api +{ + /** + * Create a chat completion with the OpenAI API. + * API Ref: https://platform.openai.com/docs/api-reference/chat/create + * + * @param string $model The model to use for completion. + * @param array $messages A list of messages describing the conversation so far. + * + * Each item in the array is an object with the following: + * - role (string) Required + * The role of the author of this message. + * One of system, user, or assistant. + * - content (string) Required + * The contents of the message. + * - name (string) Optional + * The name of the author of this message. + * May contain a-z, A-Z, 0-9, and underscores, + * with a maximum length of 64 characters. + * + * @param int|null $maxTokens Maximum number of tokens to generate (optional). + * @param float|null $temperature The sampling temperature to use (optional). + * @param float|null $topP The nucleus sampling parameter (optional). + * @param int|null $n The number of chat completion choices to generate (optional). + * @param bool|null $stream Partial message deltas (optional). + * @param mixed|null $stop Sequences where the API will stop generating tokens (optional). + * @param float|null $presencePenalty Penalty for new tokens based on whether they appear in the text (optional). + * @param float|null $frequencyPenalty Penalty for new tokens based on their frequency in the text (optional). + * @param array|null $logitBias Modify the likelihood of specified tokens appearing (optional). + * @param string|null $user A unique identifier representing the end-user (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $model, + array $messages, + ?int $maxTokens = null, + ?float $temperature = null, + ?float $topP = null, + ?int $n = null, + ?bool $stream = null, + $stop = null, + ?float $presencePenalty = null, + ?float $frequencyPenalty = null, + ?array $logitBias = null, + ?string $user = null + ): ?object + { + // Build the request path. + $path = "/chat/completions"; + + // Set the request data. + $data = new \stdClass(); + $data->model = $model; + $data->messages = $messages; + + if ($maxTokens !== null) + { + $data->max_tokens = $maxTokens; + } + + if ($temperature !== null) + { + $data->temperature = $temperature; + } + + if ($topP !== null) + { + $data->top_p = $topP; + } + + if ($n !== null) + { + $data->n = $n; + } + + if ($stream !== null) + { + $data->stream = $stream; + } + + if ($stop !== null) + { + $data->stop = $stop; + } + + if ($presencePenalty !== null) + { + $data->presence_penalty = $presencePenalty; + } + + if ($frequencyPenalty !== null) + { + $data->frequency_penalty = $frequencyPenalty; + } + + if ($logitBias !== null) + { + $data->logit_bias = new \stdClass(); + foreach ($logitBias as $key => $val) + { + $data->logit_bias->$key = $val; + } + } + + if ($user !== null) + { + $data->user = $user; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Openai/src/Completions.php b/libraries/jcb_powers/VDM.Joomla.Openai/src/Completions.php new file mode 100644 index 0000000..65769df --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Openai/src/Completions.php @@ -0,0 +1,158 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Openai; + + +use VDM\Joomla\Openai\Abstraction\Api; + + +/** + * The Openai Completions + * + * @since 3.2.0 + */ +class Completions extends Api +{ + /** + * Create a completion using the OpenAI API. + * API Ref: https://platform.openai.com/docs/api-reference/completions + * + * @param string $model The ID of the model to use. + * @param string|array $prompt The prompt(s) to generate completions for. + * @param int|null $maxTokens The maximum number of tokens to generate (optional). + * @param float|null $temperature The sampling temperature to use (optional). + * @param string $suffix The suffix that comes after a completion of inserted text. (optional). + * @param float|null $topP The top_p value for nucleus sampling (optional). + * @param int|null $n How many completions to generate (optional). + * @param bool|null $stream Whether to stream back partial progress (optional). + * @param int|null $logprobs Include the log probabilities on the most likely tokens (optional). + * @param bool|null $echo Echo back the prompt in addition to the completion (optional). + * @param string|null $stop Up to 4 sequences where the API will stop generating (optional). + * @param float|null $presencePenalty The presence penalty to use (optional). + * @param float|null $frequencyPenalty The frequency penalty to use (optional). + * @param int|null $bestOf Generates best_of completions server-side (optional). + * @param array|null $logitBias Modify the likelihood of specified tokens (optional). + * @param string|null $user A unique identifier representing your end-user (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $model, + $prompt, + ?int $maxTokens = null, + ?string $suffix = null, + ?float $temperature = null, + ?float $topP = null, + ?int $n = null, + ?bool $stream = null, + ?int $logprobs = null, + ?bool $echo = null, + $stop = null, + ?float $presencePenalty = null, + ?float $frequencyPenalty = null, + ?int $bestOf = null, + ?array $logitBias = null, + ?string $user = null + ): ?object + { + // Build the request path. + $path = "/completions"; + + // Set the completion data. + $data = new \stdClass(); + $data->model = $model; + $data->prompt = $prompt; + + if ($maxTokens !== null) + { + $data->max_tokens = $maxTokens; + } + + if ($temperature !== null) + { + $data->temperature = $temperature; + } + + if ($suffix !== null) + { + $data->suffix = $suffix; + } + + if ($topP !== null) + { + $data->top_p = $topP; + } + + if ($n !== null) + { + $data->n = $n; + } + + if ($stream !== null) + { + $data->stream = $stream; + } + + if ($logprobs !== null) + { + $data->logprobs = $logprobs; + } + + if ($echo !== null) + { + $data->echo = $echo; + } + + if ($stop !== null) + { + $data->stop = $stop; + } + + if ($presencePenalty !== null) + { + $data->presence_penalty = $presencePenalty; + } + + if ($frequencyPenalty !== null) + { + $data->frequency_penalty = $frequencyPenalty; + } + + if ($bestOf !== null) + { + $data->best_of = $bestOf; + } + + if ($logitBias !== null) + { + $data->logit_bias = new \stdClass(); + foreach ($logitBias as $key => $val) + { + $data->logit_bias->$key = $val; + } + } + + if ($user !== null) + { + $data->user = $user; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Openai/src/Models.php b/libraries/jcb_powers/VDM.Joomla.Openai/src/Models.php new file mode 100644 index 0000000..034cdd3 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Openai/src/Models.php @@ -0,0 +1,44 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Openai; + + +use VDM\Joomla\Openai\Abstraction\Api; + + +/** + * The Openai Models + * + * @since 3.2.0 + */ +class Models extends Api +{ + /** + * List the available models from OpenAI API. + * + * @return object|null + * @since 3.2.0 + **/ + public function list(): ?object + { + // Build the request path. + $path = "/models"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Openai/src/Moderate.php b/libraries/jcb_powers/VDM.Joomla.Openai/src/Moderate.php new file mode 100644 index 0000000..5f02896 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Openai/src/Moderate.php @@ -0,0 +1,60 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Openai; + + +use VDM\Joomla\Openai\Abstraction\Api; + + +/** + * The Openai Moderate + * + * @since 3.2.0 + */ +class Moderate extends Api +{ + /** + * Classify if text violates OpenAI's Content Policy. + * API Ref: https://platform.openai.com/docs/api-reference/moderations/create + * + * @param string|array $input The input text to classify. + * @param string|null $model The moderation model (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function text( + $input, + ?string $model = null + ): ?object + { + // Build the request path. + $path = "/moderations"; + + // Set the moderation data. + $data = new \stdClass(); + $data->input = $input; + + if ($model !== null) + { + $data->model = $model; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Openai/src/Service/Utilities.php b/libraries/jcb_powers/VDM.Joomla.Openai/src/Service/Utilities.php new file mode 100644 index 0000000..b7f6a4c --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Openai/src/Service/Utilities.php @@ -0,0 +1,113 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Openai\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VDM\Joomla\Openai\Utilities\Uri; +use VDM\Joomla\Openai\Utilities\Response; +use VDM\Joomla\Openai\Utilities\Http; +use VDM\Joomla\Utilities\Component\Helper; + + +/** + * The Openai Utilities Service + * + * @since 3.2.0 + */ +class Utilities implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 3.2.0 + */ + public function register(Container $container) + { + $container->alias(Uri::class, 'Openai.Utilities.Uri') + ->share('Openai.Utilities.Uri', [$this, 'getUri'], true); + + $container->alias(Response::class, 'Openai.Utilities.Response') + ->share('Openai.Utilities.Response', [$this, 'getResponse'], true); + + $container->alias(Http::class, 'Openai.Utilities.Http') + ->share('Openai.Utilities.Http', [$this, 'getHttp'], true); + } + + /** + * Get the Uri class + * + * @param Container $container The DI container. + * + * @return Uri + * @since 3.2.0 + */ + public function getUri(Container $container): Uri + { + return new Uri(); + } + + /** + * Get the Response class + * + * @param Container $container The DI container. + * + * @return Response + * @since 3.2.0 + */ + public function getResponse(Container $container): Response + { + return new Response(); + } + + /** + * Get the Http class + * + * @param Container $container The DI container. + * + * @return Http + * @since 3.2.0 + */ + public function getHttp(Container $container): Http + { + $openai_token = null; + $openai_org_token = null; + if (Helper::getParams()->get('enable_open_ai') == 1) + { + $openai_token = Helper::getParams()->get('openai_token'); + if (Helper::getParams()->get('enable_open_ai_org') == 1) + { + $openai_org_token = Helper::getParams()->get('openai_org_token'); + } + + if ($openai_token === 'secret') + { + $openai_token = null; + } + + if ($openai_org_token === 'secret') + { + $openai_org_token = null; + } + } + + return new Http( + $openai_token, + $openai_org_token + ); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Openai/src/Service/index.html b/libraries/jcb_powers/VDM.Joomla.Openai/src/Service/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Openai/src/Service/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Openai/src/Utilities/Http.php b/libraries/jcb_powers/VDM.Joomla.Openai/src/Utilities/Http.php new file mode 100644 index 0000000..6d0b705 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Openai/src/Utilities/Http.php @@ -0,0 +1,139 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Openai\Utilities; + + +use Joomla\CMS\Http\Http as JoomlaHttp; +use Joomla\Registry\Registry; + + +/** + * The Openai Http + * + * @since 3.2.0 + */ +final class Http extends JoomlaHttp +{ + /** + * The default Header + * + * @var array + * @since 3.2.0 + */ + protected array $defaultHeaders = ['Content-Type' => 'application/json']; + + /** + * Constructor. + * + * @param string|null $token The Openai API token. + * @param string|null $orgToken The Openai API Organization token. + * + * @since 3.2.0 + * @throws \InvalidArgumentException + **/ + public function __construct(?string $token, ?string $orgToken = null) + { + // add the token if given + if (is_string($token)) + { + $this->defaultHeaders['Authorization'] = 'Bearer ' . $token; + } + + // add the organization token if given + if (is_string($orgToken)) + { + $this->defaultHeaders['OpenAI-Organization'] = $orgToken; + } + + // setup config + $config = [ + 'userAgent' => 'JoomlaOpenai/3.0', + 'headers' => $this->defaultHeaders + ]; + + $options = new Registry($config); + + // run parent constructor + parent::__construct($options); + } + + /** + * Change the Tokens. + * + * @param string|null $token The Openai API token. + * @param string|null $orgToken The Openai API Organization token. + * + * @since 3.2.0 + **/ + public function setTokens(?string $token = null, ?string $orgToken = null) + { + // get the current headers + $this->defaultHeaders = (array) $this->getOption('headers', + $this->defaultHeaders + ); + + // add the token if given + if (is_string($token)) + { + $this->defaultHeaders['Authorization'] = 'Bearer ' . $token; + } + + // add the organization token if given + if (is_string($orgToken)) + { + $this->defaultHeaders['OpenAI-Organization'] = $orgToken; + } + + $this->setOption('headers', $this->defaultHeaders); + } + + /** + * Change the User Token. + * + * @param string $token The API token. + * + * @since 3.2.0 + **/ + public function setToken(string $token) + { + // get the current headers + $this->defaultHeaders = (array) $this->getOption('headers', + $this->defaultHeaders + ); + + // add the token + $this->defaultHeaders['Authorization'] = 'Bearer ' . $token; + + $this->setOption('headers', $this->defaultHeaders); + } + + /** + * Change the Organization Token. + * + * @param string $token The Organization API token. + * + * @since 3.2.0 + **/ + public function setOrgToken(string $token) + { + // get the current headers + $this->defaultHeaders = (array) $this->getOption('headers', + $this->defaultHeader + ); + + // add the token + $this->defaultHeaders['OpenAI-Organization'] = $token; + + $this->setOption('headers', $this->defaultHeaders); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Openai/src/Utilities/Response.php b/libraries/jcb_powers/VDM.Joomla.Openai/src/Utilities/Response.php new file mode 100644 index 0000000..b07d31d --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Openai/src/Utilities/Response.php @@ -0,0 +1,140 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Openai\Utilities; + + +use Joomla\CMS\Http\Response as JoomlaResponse; +use VDM\Joomla\Utilities\JsonHelper; +use VDM\Joomla\Utilities\StringHelper; + + +/** + * The Openai Response + * + * @since 3.2.0 + */ +final class Response +{ + /** + * Process the response and decode it. + * + * @param JoomlaResponse $response The response. + * @param integer $expectedCode The expected "good" code. + * @param mixed $default The default if body not have length + * + * @return mixed + * + * @since 3.2.0 + * @throws \DomainException + **/ + public function get(JoomlaResponse $response, int $expectedCode = 200, $default = null) + { + // Validate the response code. + if ($response->code != $expectedCode) + { + // Decode the error response and throw an exception. + $message = $this->error($response); + + // Throw an exception with the OpenAI error message and code. + throw new \DomainException($message, $response->code); + } + + return $this->body($response, $default); + } + + /** + * Process the response and decode it. (when we have multiple success codes) + * + * @param JoomlaResponse $response The response. + * @param array [$expectedCode => $default] The expected "good" code. and The default if body not have length + * + * @return mixed + * + * @since 3.2.0 + * @throws \DomainException + **/ + public function get_(JoomlaResponse $response, array $validate = [200 => null]) + { + // Validate the response code. + if (!isset($validate[$response->code])) + { + // Decode the error response and throw an exception. + $message = $this->error($response); + + // Throw an exception with the OpenAI error message and code. + throw new \DomainException($message, $response->code); + + } + + return $this->body($response, $validate[$response->code]); + } + + /** + * Return the body from the response + * + * @param JoomlaResponse $response The response. + * @param mixed $default The default if body not have length + * + * @return mixed + * @since 3.2.0 + **/ + protected function body(JoomlaResponse $response, $default = null) + { + // check that we have a body and that its JSON + if (isset($response->body) && StringHelper::check($response->body)) + { + if (JsonHelper::check($response->body)) + { + return json_decode((string) $response->body); + } + + return $response->body; + } + + return $default; + } + + /** + * Get the error message from the OpenAI API response + * + * @param JoomlaResponse $response The response. + * + * @return string + * @since 3.2.0 + **/ + protected function error(JoomlaResponse $response): string + { + // do we have a json string + if (isset($response->body) && JsonHelper::check($response->body)) + { + $error = json_decode($response->body); + } + else + { + return 'Invalid or empty response body.'; + } + + // check if OpenAI returned an error object + if (isset($error->error)) + { + // error object found, extract message and code + $errorMessage = isset($error->error->message) ? $error->error->message : 'Unknown error.'; + $errorCode = isset($error->error->code) ? $error->error->code : 'Unknown error code.'; + + // return formatted error message + return 'OpenAI Error: ' . $errorMessage . ' Code: ' . $errorCode; + } + + return 'No error information found in response.'; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Openai/src/Utilities/Uri.php b/libraries/jcb_powers/VDM.Joomla.Openai/src/Utilities/Uri.php new file mode 100644 index 0000000..ceeb5cd --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Openai/src/Utilities/Uri.php @@ -0,0 +1,115 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Openai\Utilities; + + +use Joomla\Uri\Uri as JoomlaUri; + + +/** + * The Openai Uri + * + * @since 3.2.0 + */ +final class Uri +{ + /** + * The api version + * + * @var string + * @since 3.2.0 + */ + private string $version; + + /** + * The api URL + * + * @var string + * @since 3.2.0 + */ + private string $url; + + /** + * Constructor + * + * @param string $url URL to the openai system + * example: https://api.openai.com + * @param string $version Version to the openai system + * + * @since 3.2.0 + **/ + public function __construct( + string $url = 'https://api.openai.com', + string $version = 'v1') + { + // set the API details + $this->setUrl($url); + $this->setVersion($version); + } + + /** + * Method to build and return a full request URL for the request. This method will + * add appropriate pagination details if necessary and also prepend the API url + * to have a complete URL for the request. + * + * @param string $path URL to inflect + * + * @return JoomlaUri + * @since 3.2.0 + **/ + public function get(string $path): JoomlaUri + { + // Get a new Uri object focusing the api url and given path. + $uri = new JoomlaUri($this->api() . $path); + + return $uri; + } + + /** + * Get the full API URL + * + * @return string + * @since 3.2.0 + **/ + public function api(): string + { + return $this->url . '/' . $this->version; + } + + /** + * Set the URL of the API + * + * @param string $url URL to your openai system + * example: https://api.openai.com + * + * @return void + * @since 3.2.0 + **/ + private function setUrl(string $url) + { + return $this->url = $url; + } + + /** + * Set the version of the API + * + * @param string $version version to your openai API + * + * @return void + * @since 3.2.0 + **/ + private function setVersion($version) + { + return $this->version = $version; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla.Openai/src/Utilities/index.html b/libraries/jcb_powers/VDM.Joomla.Openai/src/Utilities/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Openai/src/Utilities/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla.Openai/src/index.html b/libraries/jcb_powers/VDM.Joomla.Openai/src/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla.Openai/src/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla/index.html b/libraries/jcb_powers/VDM.Joomla/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla/src/Abstraction/BaseConfig.php b/libraries/jcb_powers/VDM.Joomla/src/Abstraction/BaseConfig.php new file mode 100644 index 0000000..fbd3c09 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Abstraction/BaseConfig.php @@ -0,0 +1,122 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Abstraction; + + +use Joomla\Registry\Registry as JoomlaRegistry; +use VDM\Joomla\Utilities\String\ClassfunctionHelper; + + +/** + * Config + * + * @since 3.2.0 + */ +abstract class BaseConfig extends JoomlaRegistry +{ + /** + * Constructor + * + * @since 3.2.0 + */ + public function __construct() + { + // Instantiate the internal data object. + $this->data = new \stdClass(); + } + + /** + * setting any config value + * + * @param string $key The value's key/path name + * @param mixed $value Optional default value, returned if the internal value is null. + * + * @since 3.2.0 + */ + public function __set(string $key, $value) + { + $this->set($key, $value); + } + + /** + * getting any valid value + * + * @param string $key The value's key/path name + * + * @since 3.2.0 + * @throws \InvalidArgumentException If $key is not a valid function name. + */ + public function __get(string $key) + { + // check if it has been set + if (($value = $this->get($key, '__N0T_S3T_Y3T_')) !== '__N0T_S3T_Y3T_') + { + return $value; + } + + throw new \InvalidArgumentException(sprintf('Argument %s could not be found as function or path.', $key)); + } + + /** + * Get a config value. + * + * @param string $path Registry path (e.g. joomla_content_showauthor) + * @param mixed $default Optional default value, returned if the internal value is null. + * + * @return mixed Value of entry or null + * + * @since 3.2.0 + */ + public function get($path, $default = null) + { + // function name with no underscores + $method = 'get' . ucfirst((string) ClassfunctionHelper::safe(str_replace('_', '', $path))); + + // check if it has been set + if (($value = parent::get($path, '__N0T_S3T_Y3T_')) !== '__N0T_S3T_Y3T_') + { + return $value; + } + elseif (method_exists($this, $method)) + { + $value = $this->{$method}($default); + + $this->set($path, $value); + + return $value; + } + + return $default; + } + + /** + * Append value to a path in registry of an array + * + * @param string $path Parent registry Path (e.g. joomla.content.showauthor) + * @param mixed $value Value of entry + * + * @return mixed The value of the that has been set. + * + * @since 3.2.0 + */ + public function appendArray(string $path, $value) + { + // check if it does not exist + if (!$this->exists($path)) + { + $this->set($path, []); + } + + return $this->append($path, $value); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Abstraction/BaseTable.php b/libraries/jcb_powers/VDM.Joomla/src/Abstraction/BaseTable.php new file mode 100644 index 0000000..468645b --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Abstraction/BaseTable.php @@ -0,0 +1,364 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Abstraction; + + +use VDM\Joomla\Interfaces\Tableinterface; + + +/** + * Base Table + * + * @since 3.2.0 + */ +abstract class BaseTable implements Tableinterface +{ + /** + * All areas/views/tables with their field details + * + * @var array + * @since 3.2.0 + **/ + protected array $tables; + + /** + * All default fields + * + * @var array + * @since 3.2.0 + **/ + protected array $defaults = [ + 'id' => [ + 'order' => -1, + 'name' => 'id', + 'label' => 'ID', + 'type' => 'text', + 'title' => false, + 'list' => NULL, + 'store' => NULL, + 'tab_name' => NULL + ], + 'ordering' => [ + 'name' => 'ordering', + 'label' => 'Ordering', + 'type' => 'number', + 'title' => false, + 'list' => NULL, + 'store' => NULL, + 'tab_name' => NULL + ], + 'published' => [ + 'name' => 'published', + 'label' => 'Status', + 'type' => 'list', + 'title' => false, + 'list' => NULL, + 'store' => NULL, + 'tab_name' => NULL + ], + 'modified_by' => [ + 'name' => 'modified_by', + 'label' => 'Modified by', + 'type' => 'user', + 'title' => false, + 'list' => NULL, + 'store' => NULL, + 'tab_name' => NULL + ], + 'modified' => [ + 'name' => 'modified', + 'label' => 'Modified', + 'type' => 'calendar', + 'title' => false, + 'list' => NULL, + 'store' => NULL, + 'tab_name' => NULL + ], + 'created_by' => [ + 'name' => 'created_by', + 'label' => 'Created by', + 'type' => 'user', + 'title' => false, + 'list' => NULL, + 'store' => NULL, + 'tab_name' => NULL + ], + 'created' => [ + 'name' => 'created', + 'label' => 'Created', + 'type' => 'calendar', + 'title' => false, + 'list' => NULL, + 'store' => NULL, + 'tab_name' => NULL + ], + 'hits' => [ + 'name' => 'hits', + 'label' => 'Hits', + 'type' => 'number', + 'title' => false, + 'list' => NULL, + 'store' => NULL, + 'tab_name' => NULL + ], + 'version' => [ + 'name' => 'version', + 'label' => 'Version', + 'type' => 'text', + 'title' => false, + 'list' => NULL, + 'store' => NULL, + 'tab_name' => NULL + ] + ]; + + /** + * Get any value from a item/field/column of an area/view/table + * Example: $this->get('table_name', 'field_name', 'value_key'); + * Get an item/field/column of an area/view/table + * Example: $this->get('table_name', 'field_name'); + * Get all items/fields/columns of an area/view/table + * Example: $this->get('table_name'); + * Get all areas/views/tables with all their item/field/column details + * Example: $this->get('All'); + * + * @param string $table The table + * @param string|null $field The field + * @param string|null $key The value key + * + * @return mixed + * @since 3.2.0 + */ + public function get(string $table, ?string $field = null, ?string $key = null) + { + // return the item/field/column of an area/view/table + if (is_string($field) && is_string($key)) + { + // return the value of a item/field/column of an area/view/table + if (isset($this->tables[$table][$field][$key])) + { + return $this->tables[$table][$field][$key]; + } + + return $this->getDefaultKey($field, $key); + } + // return the item/field/column of an area/view/table + elseif (is_string($field)) + { + if (isset($this->tables[$table][$field])) + { + return $this->tables[$table][$field]; + } + + return $this->getDefault($field); + } + // return an area/view/table + elseif ($table !== 'All') + { + if (isset($this->tables[$table])) + { + return $this->tables[$table]; + } + return null; + } + + // return all + return $this->tables; + } + + /** + * Get title field from an area/view/table + * + * @param string $table The area + * + * @return ?array + * @since 3.2.0 + */ + public function title(string $table): ?array + { + // return the title item/field/column of an area/view/table + if (($table = $this->get($table)) !== null) + { + foreach ($table as $item) + { + if ($item['title']) + { + return $item; + } + } + } + + // none found + return null; + } + + /** + * Get title field name + * + * @param string $table The area + * + * @return string + * @since 3.2.0 + */ + public function titleName(string $table): string + { + // return the title name of an area/view/table + if (($field = $this->title($table)) !== null) + { + return $field['name']; + } + + // none found default to ID + return 'id'; + } + + /** + * Get all tables + * + * @return array + * @since 3.2.0 + */ + public function tables(): array + { + // return all areas/views/tables + return array_keys($this->tables); + } + + /** + * Check if a table (and field) exist + * + * @param string $table The area + * @param string|null $field The area + * + * @return bool + * @since 3.2.0 + */ + public function exist(string $table, ?string $field = null): bool + { + if (isset($this->tables[$table])) + { + // if we have a field + if (is_string($field)) + { + if (isset($this->tables[$table][$field])) + { + return true; + } + } + else + { + return true; + } + } + + return $this->isDefault($field); + } + + /** + * Get all fields of an area/view/table + * + * @param string $table The area + * @param bool $default Add the default fields + * + * @return array|null On success an array of fields + * @since 3.2.0 + */ + public function fields(string $table, bool $default = false): ?array + { + // return all fields of an area/view/table + if (($table = $this->get($table)) !== null) + { + if ($default) + { + return $this->addDefault(array_keys($table)); + } + else + { + return array_keys($table); + } + } + + // none found + return null; + } + + /** + * Add the default fields + * + * @param array $fields The table dynamic fields + * + * @return array Fields (with defaults added) + * @since 3.2.0 + */ + protected function addDefault(array $fields): array + { + // add default fields + foreach ($this->defaults as $default) + { + // used just for loading the fields + $order = $default['order'] ?? 1; + unset($default['order']); + + if ($order < 0) + { + array_unshift($fields, $default['name']); + } + else + { + $fields[] = $default['name']; + } + } + + return $fields; + } + + /** + * Check if the field is a default field + * + * @param string $field The field to check + * + * @return bool True if a default field + * @since 3.2.0 + */ + protected function isDefault(string $field): bool + { + return isset($this->defaults[$field]); + } + + /** + * Get a default field + * + * @param string $field The field to check + * + * @return array|null True if a default field + * @since 3.2.0 + */ + protected function getDefault(string $field): ?array + { + return $this->defaults[$field] ?? null; + } + + /** + * Get a default field property + * + * @param string $field The field to check + * @param string $key The field key/property to check + * + * @return string|null String value if a default field property exist + * @since 3.2.0 + */ + protected function getDefaultKey(string $field, string $key): ?string + { + return $this->defaults[$field][$key] ?? null; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Abstraction/Database.php b/libraries/jcb_powers/VDM.Joomla/src/Abstraction/Database.php new file mode 100644 index 0000000..f615e70 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Abstraction/Database.php @@ -0,0 +1,118 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Abstraction; + + +use Joomla\CMS\Factory as JoomlaFactory; +use VDM\Joomla\Utilities\Component\Helper; + + +/** + * Database + * + * @since 3.2.0 + */ +abstract class Database +{ + /** + * Database object to query local DB + * + * @var \JDatabaseDriver + * @since 3.2.0 + */ + protected \JDatabaseDriver $db; + + /** + * Core Component Table Name + * + * @var string + * @since 3.2.0 + */ + protected string $table; + + /** + * Constructor + * + * @param \JDatabaseDriver|null $db The database driver + * + * @throws \Exception + * @since 3.2.0 + */ + public function __construct(?\JDatabaseDriver $db = null) + { + $this->db = $db ?: JoomlaFactory::getDbo(); + + // set the component table + $this->table = '#__' . Helper::getCode(); + } + + /** + * Set a value based on data type + * + * @param mixed $value The value to set + * + * @return mixed + * @since 3.2.0 + **/ + protected function quote($value) + { + if ($value === null) // hmm the null does pose an issue (will keep an eye on this) + { + return 'NULL'; + } + + if (is_numeric($value)) + { + if (filter_var($value, FILTER_VALIDATE_INT)) + { + return (int) $value; + } + elseif (filter_var($value, FILTER_VALIDATE_FLOAT)) + { + return (float) $value; + } + } + elseif (is_bool($value)) // not sure if this will work well (but its correct) + { + return $value ? 'TRUE' : 'FALSE'; + } + + // For date and datetime values + if ($value instanceof \DateTime) + { + return $this->db->quote($value->format('Y-m-d H:i:s')); + } + + // For other data types, just escape it + return $this->db->quote($value); + } + + /** + * Set a table name, adding the + * core component as needed + * + * @param string $table The table string + * + * @return string + * @since 3.2.0 + **/ + protected function getTable(string $table): string + { + if (strpos($table, '#__') === false) + { + return $this->table . '_' . $table; + } + + return $table; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Abstraction/Model.php b/libraries/jcb_powers/VDM.Joomla/src/Abstraction/Model.php new file mode 100644 index 0000000..9321eef --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Abstraction/Model.php @@ -0,0 +1,358 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Abstraction; + + +use VDM\Joomla\Utilities\StringHelper; +use VDM\Joomla\Utilities\ArrayHelper; +use VDM\Joomla\Interfaces\Tableinterface as Table; + + +/** + * Base Model + * + * @since 3.2.0 + */ +abstract class Model +{ + /** + * Last ID + * + * @var array + * @since 3.2.0 + */ + protected array $last; + + /** + * Search Table + * + * @var Table + * @since 3.2.0 + */ + protected Table $table; + + /** + * Constructor + * + * @param Table $table The search table object. + * + * @since 3.2.0 + */ + public function __construct(Table $table) + { + $this->table = $table; + } + + /** + * Model the value + * Example: $this->value(value, 'value_key', 'table_name'); + * + * @param mixed $value The value to model + * @param string $field The field key + * @param string|null $table The table + * + * @return mixed + * @since 3.2.0 + */ + abstract public function value($value, string $field, ?string $table = null); + + /** + * Model the values of an item + * Example: $this->item(Object, 'table_name'); + * + * @param object|null $item The item object + * @param string|null $table The table + * + * @return object|null + * @since 3.2.0 + */ + public function item(?object $item, ?string $table = null): ?object + { + // we must have an object + if (empty($item)) + { + return null; + } + + // set the table name + if (empty($table)) + { + $table = $this->getTable(); + } + + if (($fields = $this->getTableFields($table, true)) !== null) + { + // field counter + $field_number = 0; + + // check if this is a valid table + $item_bucket = new \stdClass(); + + foreach ($fields as $field) + { + // model a value if it exists + if(isset($item->{$field})) + { + if (!$this->validateBefore($item->{$field}, $field, $table)) + { + continue; + } + + $item->{$field} = $this->value($item->{$field}, $field, $table); + + if (!$this->validateAfter($item->{$field}, $field, $table)) + { + continue; + } + + $item_bucket->{$field} = $item->{$field}; + + $field_number++; + } + } + + // all items must have more than one field or its empty (1 = key) + if ($field_number > 1) + { + return $item_bucket; + } + } + + return null; + } + + /** + * Model the values of multiple items + * Example: $this->items(Array, 'table_name'); + * + * @param array|null $items The array of item objects + * @param string|null $table The table + * + * @return array|null + * @since 3.2.0 + */ + public function items(?array $items = null, ?string $table = null): ?array + { + // check if this is a valid table + if (ArrayHelper::check($items)) + { + // set the table name + if (empty($table)) + { + $table = $this->getTable(); + } + + foreach ($items as $id => &$item) + { + // model the item + if (($item = $this->item($item, $table)) !== null) + { + // add the last ID + $this->last[$table] = $item->id ?? $this->last[$table] ?? null; + } + else + { + unset($items[$id]); + } + } + + if (ArrayHelper::check($items)) + { + return $items; + } + } + + return null; + } + + /** + * Model the values of an row + * Example: $this->item(Array, 'table_name'); + * + * @param array|null $item The item array + * @param string|null $table The table + * + * @return array|null + * @since 3.2.0 + */ + public function row(?array $item, ?string $table = null): ?array + { + // we must have an array + if (empty($item)) + { + return null; + } + + // set the table name + if (empty($table)) + { + $table = $this->getTable(); + } + + if (($fields = $this->getTableFields($table, true)) !== null) + { + // field counter + $field_number = 0; + + // check if this is a valid table + $item_bucket = []; + + foreach ($fields as $field) + { + // model a value if it exists + if(isset($item[$field])) + { + if (!$this->validateBefore($item[$field], $field, $table)) + { + continue; + } + + $item[$field] = $this->value($item[$field], $field, $table); + + if (!$this->validateAfter($item[$field], $field, $table)) + { + continue; + } + + $item_bucket[$field] = $item[$field]; + + $field_number++; + } + } + + // all items must have more than one field or its empty (1 = id or guid) + if ($field_number > 1) + { + return $item_bucket; + } + } + + return null; + } + + /** + * Model the values of multiple rows + * Example: $this->items(Array, 'table_name'); + * + * @param array|null $items The array of item array + * @param string|null $table The table + * + * @return array|null + * @since 3.2.0 + */ + public function rows(?array $items = null, ?string $table = null): ?array + { + // check if this is a valid table + if (ArrayHelper::check($items)) + { + // set the table name + if (empty($table)) + { + $table = $this->getTable(); + } + + foreach ($items as $id => &$item) + { + // model the item + if (($item = $this->row($item, $table)) !== null) + { + // add the last ID + $this->last[$table] = $item['id'] ?? $this->last[$table] ?? null; + } + else + { + unset($items[$id]); + } + } + + if (ArrayHelper::check($items)) + { + return $items; + } + } + + return null; + } + + /** + * Get last modeled ID + * Example: $this->last('table_name'); + * + * @param string|null $table The table + * + * @return int|null + * @since 3.2.0 + */ + public function last(?string $table = null): ?int + { + // set the table name + if (empty($table)) + { + $table = $this->getTable(); + } + + // check if this is a valid table + if ($table && isset($this->last[$table])) + { + return $this->last[$table]; + } + + return null; + } + + /** + * Get the current active table's fields (including defaults) + * + * @param string $table The area + * @param bool $default Add the default fields + * + * @return array + * @since 3.2.0 + */ + protected function getTableFields(string $table, bool $default = false): ?array + { + return $this->table->fields($table, $default); + } + + /** + * Validate before the value is modelled (basic, override in child class) + * + * @param mixed $value The field value + * @param string|null $field The field key + * @param string|null $table The table + * + * @return bool + * @since 3.2.0 + */ + abstract protected function validateBefore(&$value, ?string $field = null, ?string $table = null): bool; + + /** + * Validate after the value is modelled (basic, override in child class) + * + * @param mixed $value The field value + * @param string|null $field The field key + * @param string|null $table The table + * + * @return bool + * @since 3.2.0 + */ + abstract protected function validateAfter(&$value, ?string $field = null, ?string $table = null): bool; + + /** + * Get the current active table + * + * @return string + * @since 3.2.0 + */ + abstract protected function getTable(): string; +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Abstraction/index.html b/libraries/jcb_powers/VDM.Joomla/src/Abstraction/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Abstraction/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla/src/Database/Insert.php b/libraries/jcb_powers/VDM.Joomla/src/Database/Insert.php new file mode 100644 index 0000000..bf7611a --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Database/Insert.php @@ -0,0 +1,290 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Database; + + +use Joomla\CMS\Date\Date; +use VDM\Joomla\Utilities\ArrayHelper; +use VDM\Joomla\Interfaces\InsertInterface; +use VDM\Joomla\Abstraction\Database; + + +/** + * Database Insert Class + * + * @since 3.2.0 + */ +final class Insert extends Database implements InsertInterface +{ + /** + * Switch to set the defaults + * + * @var bool + * @since 1.2.0 + **/ + protected bool $defaults = true; + + /** + * Switch to prevent/allow defaults from being added. + * + * @param bool $trigger toggle the defaults + * + * @return void + * @since 3.2.0 + **/ + public function defaults(bool $trigger = true) + { + $this->defaults = $trigger; + } + + /** + * Insert rows to the database (with remapping and filtering columns option) + * + * @param array $data Dataset to store in database [array of arrays (key => value)] + * @param string $table The table where the data is being added + * @param array $columns Data columns for remapping and filtering + * + * @return bool + * @since 3.2.0 + **/ + public function rows(array $data, string $table, array $columns = []): bool + { + if (!ArrayHelper::check($data)) + { + return false; + } + + if ($columns === []) + { + $columns = $this->getArrayColumns($data); + } + + return ($columns === []) ? false : $this->insert($data, $table, $columns, true); + } + + /** + * Insert items to the database (with remapping and filtering columns option) + * + * @param array $data Data to store in database (array of objects) + * @param string $table The table where the data is being added + * @param array $columns Data columns for remapping and filtering + * + * @return bool + * @since 3.2.0 + **/ + public function items(array $data, string $table, array $columns = []): bool + { + if (!ArrayHelper::check($data)) + { + return false; + } + + if ($columns === []) + { + $columns = $this->getObjectsColumns($data); + } + + return ($columns === []) ? false : $this->insert($data, $table, $columns, false); + } + + /** + * Insert row to the database + * + * @param array $data Dataset to store in database (key => value) + * @param string $table The table where the data is being added + * + * @return bool + * @since 3.2.0 + **/ + public function row(array $data, string $table): bool + { + return $this->rows([$data], $table); + } + + /** + * Insert item to the database + * + * @param object $data Dataset to store in database (key => value) + * @param string $table The table where the data is being added + * + * @return bool + * @since 3.2.0 + **/ + public function item(object $data, string $table): bool + { + return $this->items([$data], $table); + } + + /** + * Get columns from data array + * + * @param array $data Data array + * + * @return array + * @since 3.2.0 + **/ + protected function getArrayColumns(array &$data): array + { + $row = array_values($data)[0]; + + if (!ArrayHelper::check($row)) + { + return []; + } + + $columns = array_keys($row); + + return array_combine($columns, $columns); + } + + /** + * Get columns from data objects + * + * @param array $data Data objects + * + * @return array + * @since 3.2.0 + **/ + protected function getObjectsColumns(array &$data): array + { + $row = array_values($data)[0]; + + if (!is_object($row)) + { + return []; + } + + $columns = get_object_vars($row); + + return array_combine(array_keys($columns), array_keys($columns)); + } + + /** + * Insert data into the database + * + * @param array $data Data to store in database + * @param string $table The table where the data is being added + * @param array $columns Data columns for remapping and filtering + * @param bool $isArray Whether the data is an array of arrays or an array of objects + * + * @return bool + * @since 3.2.0 + **/ + protected function insert(array &$data, string $table, array $columns, bool $isArray): bool + { + // set joomla default columns + $add_created = false; + $add_version = false; + $add_published = false; + + // check if we should load the defaults + if ($this->defaults) + { + // get the date + $date = (new Date())->toSql(); + + if (!isset($columns['created'])) + { + $columns['created'] = ' (o_O) '; + $add_created = true; + } + + if (!isset($columns['version'])) + { + $columns['version'] = ' (o_O) '; + $add_version = true; + } + + if (!isset($columns['published'])) + { + $columns['published'] = ' (o_O) '; + $add_published = true; + } + // the (o_O) prevents an empty value from being loaded + } + + // get a query object + $query = $this->db->getQuery(true); + + // set the query targets + $query->insert($this->db->quoteName($this->getTable($table)))->columns($this->db->quoteName(array_keys($columns))); + + // limiting factor on the amount of rows to insert before we reset the query + $limit = 300; + + // set the insert values + foreach ($data as $nr => $value) + { + // check the limit + if ($limit <= 1) + { + // execute and reset the query + $this->db->setQuery($query); + $this->db->execute(); + + // reset limit + $limit = 300; + + // get a query object + $query = $this->db->getQuery(true); + + // set the query targets + $query->insert($this->db->quoteName($this->getTable($table)))->columns($this->db->quoteName(array_keys($columns))); + } + + $row = []; + foreach ($columns as $column => $key) + { + if (' (o_O) ' !== $key) + { + $row[] = ($isArray && isset($value[$key])) ? $this->quote($value[$key]) + : ((!$isArray && isset($value->{$key})) ? $this->quote($value->{$key}) : ''); + } + } + + // set joomla default columns + if ($add_created) + { + $row[] = $this->db->quote($date); + } + + if ($add_version) + { + $row[] = 1; + } + + if ($add_published) + { + $row[] = 1; + } + + // add to query + $query->values(implode(',', $row)); + + // decrement the limiter + $limit--; + + // clear the data from memory + unset($data[$nr]); + } + + // execute the final query + $this->db->setQuery($query); + $this->db->execute(); + + // always reset the default switch + $this->defaults(); + + return true; + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Database/Load.php b/libraries/jcb_powers/VDM.Joomla/src/Database/Load.php new file mode 100644 index 0000000..5d88778 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Database/Load.php @@ -0,0 +1,446 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Database; + + +use VDM\Joomla\Utilities\ArrayHelper; +use VDM\Joomla\Interfaces\LoadInterface; +use VDM\Joomla\Abstraction\Database; + + +/** + * Database Load + * + * @since 3.2.0 + */ +final class Load extends Database implements LoadInterface +{ + /** + * Load data rows as an array of associated arrays + * + * @param array $select Array of selection keys + * @param array $tables Array of tables to search + * @param array|null $where Array of where key=>value match exist + * @param array|null $order Array of how to order the data + * @param int|null $limit Limit the number of values returned + * + * @return array|null + * @since 3.2.0 + **/ + public function rows(array $select, array $tables, ?array $where = null, + ?array $order = null, ?int $limit = null): ?array + { + // set key if found + $key = ''; + if (isset($select['key'])) + { + if (is_string($select['key'])) + { + $key = $select['key']; + } + unset($select['key']); + } + + // check if we can get many rows + if ($this->many($select, $tables, $where, $order, $limit)) + { + // return associated arrays from the table records + return $this->db->loadAssocList($key); + } + + // data does not exist + return null; + } + + /** + * Load data rows as an array of objects + * + * @param array $select Array of selection keys + * @param array $tables Array of tables to search + * @param array|null $where Array of where key=>value match exist + * @param array|null $order Array of how to order the data + * @param int|null $limit Limit the number of values returned + * + * @return array|null + * @since 3.2.0 + **/ + public function items(array $select, array $tables, ?array $where = null, + ?array $order = null, ?int $limit = null): ?array + { + // set key if found + $key = ''; + if (isset($select['key'])) + { + if (is_string($select['key'])) + { + $key = $select['key']; + } + unset($select['key']); + } + + // check if we can get many rows + if ($this->many($select, $tables, $where, $order, $limit)) + { + // return associated arrays from the table records + return $this->db->loadObjectList($key); + } + + // data does not exist + return null; + } + + /** + * Load data row as an associated array + * + * @param array $select Array of selection keys + * @param array $tables Array of tables to search + * @param array|null $where Array of where key=>value match exist + * @param array|null $order Array of how to order the data + * + * @return array|null + * @since 3.2.0 + **/ + public function row(array $select, array $tables, ?array $where = null, ?array $order = null): ?array + { + // check if we can get one row + if ($this->one($select, $tables, $where, $order)) + { + return $this->db->loadAssoc(); + } + + // data does not exist + return null; + } + + /** + * Load data row as an object + * + * @param array $select Array of selection keys + * @param array $tables Array of tables to search + * @param array|null $where Array of where key=>value match exist + * @param array|null $order Array of how to order the data + * + * @return object|null + * @since 3.2.0 + **/ + public function item(array $select, array $tables, ?array $where = null, ?array $order = null): ?object + { + // check if we can get one row + if ($this->one($select, $tables, $where, $order)) + { + return $this->db->loadObject(); + } + + // data does not exist + return null; + } + + /** + * Get the max value based on a filtered result from a given table + * + * @param string $field The field key + * @param string $tables The tables + * @param array $filter The filter keys + * + * @return int|null + * @since 3.2.0 + **/ + public function max($field, array $tables, array $filter): ?int + { + // only do check if we have the table set + if (isset($tables['a'])) + { + // get the query + $query = $this->query(["all" => "MAX(`$field`)"], $tables, $filter); + + // Load the max number + $this->db->setQuery($query); + $this->db->execute(); + + // check if we have values + if ($this->db->getNumRows()) + { + return (int) $this->db->loadResult(); + } + } + + // data does not exist + return null; + } + + /** + * Count the number of items based on filter result from a given table + * + * @param string $tables The table + * @param array $filter The filter keys + * + * @return int|null + * @since 3.2.0 + **/ + public function count(array $tables, array $filter): ?int + { + // only do check if we have the table set + if (isset($tables['a'])) + { + // get the query + $query = $this->query(["all" => 'COUNT(*)'], $tables, $filter); + + // Load the max number + $this->db->setQuery($query); + $this->db->execute(); + + // check if we have values + if ($this->db->getNumRows()) + { + return (int) $this->db->loadResult(); + } + } + + // data does not exist + return null; + } + + /** + * Load one value from a row + * + * @param array $select Array of selection keys + * @param array $tables Array of tables to search + * @param array|null $where Array of where key=>value match exist + * @param array|null $order Array of how to order the data + * + * @return mixed + * @since 3.2.0 + **/ + public function value(array $select, array $tables, ?array $where = null, ?array $order = null) + { + // check if we can get one value + if ($this->one($select, $tables, $where, $order)) + { + return $this->db->loadResult(); + } + + // data does not exist + return null; + } + + /** + * Load many + * + * @param array $select Array of selection keys + * @param array $tables Array of tables to search + * @param array|null $where Array of where key=>value match exist + * @param array|null $order Array of how to order the data + * @param int|null $limit Limit the number of values returned + * + * @return bool + * @since 3.2.0 + **/ + protected function many(array $select, array $tables, ?array $where = null, + ?array $order = null, ?int $limit = null): bool + { + // only do check if we have the table set + if (isset($tables['a'])) + { + // get the query + $query = $this->query($select, $tables, $where, $order, $limit); + + // Load the items + $this->db->setQuery($query); + $this->db->execute(); + + // check if we have values + if ($this->db->getNumRows()) + { + return true; + } + } + + // data does not exist + return false; + } + + /** + * Load one + * + * @param array $select Array of selection keys + * @param array $tables Array of tables to search + * @param array|null $where Array of where key=>value match exist + * @param array|null $order Array of how to order the data + * + * @return bool + * @since 3.2.0 + **/ + protected function one(array $select, array $tables, ?array $where = null, ?array $order = null): bool + { + // only do check if we have the table set + if (isset($tables['a'])) + { + // get the query + $query = $this->query($select, $tables, $where, $order); + + // Load the item + $this->db->setQuery($query, 0, 1); + $this->db->execute(); + + // check if we have values + if ($this->db->getNumRows()) + { + return true; + } + } + + // data does not exist + return false; + } + + /** + * Get the query object + * + * @param array $select Array of selection keys + * @param array $tables Array of tables to search + * @param array|null $where Array of where key=>value match exist + * @param array|null $order Array of how to order the data + * @param int|null $limit Limit the number of values returned + * + * @return object|null The query object (DatabaseQuery) + * @since 3.2.0 + **/ + protected function query(array $select, array $tables, ?array $where = null, + ?array $order = null, ?int $limit = null): ?object + { + $query = $this->db->getQuery(true); + + // check if we have an all selection set + if (isset($select['all'])) + { + // all selection example array: ['all' => ['a.*', 'b.*']] + if (ArrayHelper::check($select['all'])) + { + foreach ($select['all'] as $select_all) + { + // set target selection + $query->select( + $select_all + ); + } + } + // all selection example string: ['all' =>'a.*'] + elseif (is_string($select['all'])) + { + // set target selection + $query->select( + $select['all'] + ); + } + unset($select['all']); + } + + // load the table where join + if (ArrayHelper::check($select)) + { + // set target selection + $query->select( + $this->db->quoteName( + array_keys($select), + array_values($select) + ) + ); + } + + // set main table + $query->from($this->db->quoteName($this->getTable($tables['a']), 'a')); + + // remove main table + unset($tables['a']); + + // load the table where join + if (ArrayHelper::check($tables)) + { + foreach ($tables as $as => $table) + { + $query->join( + 'LEFT', $this->db->quoteName( + $this->getTable($table['name']), $as + ) . ' ON (' . $this->db->quoteName($table['join_on']) + . ' = ' . $this->db->quoteName($table['as_on']) . ')' + ); + } + } + + // load the table where getters + if (ArrayHelper::check($where)) + { + foreach ($where as $key => $value) + { + if (ArrayHelper::check($value)) + { + if (isset($value['value']) && isset($value['operator'])) + { + if (ArrayHelper::check($value['value'])) + { + // add the where by array + $query->where($this->db->quoteName($key) . ' ' . + $value['operator'] . ' (' . + implode(',', + array_map( + fn($val) => $this->quote($val), + $value['value'] + ) + ) + . ')' + ); + } + else + { + // add the where + $query->where($this->db->quoteName($key) . ' ' . + $value['operator'] . ' ' . $this->quote($value['value'])); + } + } + else + { + // we should through an exception + // for security we just return nothing for now + return null; + } + } + else + { + // add the where + $query->where($this->db->quoteName($key) . + ' = ' . $this->quote($value)); + } + } + } + + // load the row ordering + if (ArrayHelper::check($order)) + { + foreach ($order as $key => $direction) + { + // add the ordering + $query->order($this->db->quoteName($key) . + ' ' . $direction); + } + } + + // only return a limited number + if (is_numeric($limit)) + { + $query->setLimit($limit); + } + + return $query; + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Database/Update.php b/libraries/jcb_powers/VDM.Joomla/src/Database/Update.php new file mode 100644 index 0000000..6c4a122 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Database/Update.php @@ -0,0 +1,188 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Database; + + +use VDM\Joomla\Interfaces\UpdateInterface; +use VDM\Joomla\Abstraction\Database; + + +/** + * Database Update Class + * + * @since 3.2.0 + */ +final class Update extends Database implements UpdateInterface +{ + /** + * Update rows in the database (with remapping and filtering columns option) + * + * @param array $data Dataset to update in database [array of arrays (key => value)] + * @param string $key Dataset key column to use in updating the values in the Database + * @param string $table The table where the data is being updated + * @param array $columns Data columns for remapping and filtering + * + * @return bool + * @since 3.2.0 + **/ + public function rows(array $data, string $key, string $table, array $columns = []): bool + { + // set the update columns + if ($data === [] || strlen($key) == 0) + { + return false; + } + + // set the update values + foreach ($data as $values) + { + if ($columns !== []) + { + // load only what is part of the columns set + $row = []; + foreach ($columns as $column => $key_) + { + if (isset($values[$key_])) + { + $row[$column] = $values[$key_]; + } + } + + // update the row + $this->row($row, $key, $table); + } + else + { + // update the row + $this->row((array) $values, $key, $table); + } + } + + return true; + } + + /** + * Update items in the database (with remapping and filtering columns option) + * + * @param array $data Data to updated in database (array of objects) + * @param string $key Dataset key column to use in updating the values in the Database + * @param string $table The table where the data is being update + * @param array $columns Data columns for remapping and filtering + * + * @return bool + * @since 3.2.0 + **/ + public function items(array $data, string $key, string $table, array $columns = []): bool + { + // set the update columns + if ($data === [] || strlen($key) == 0) + { + return false; + } + + // set the update values + foreach ($data as $nr => $values) + { + if ($columns !== []) + { + // load only what is part of the columns set + $row = []; + foreach ($columns as $column => $key_) + { + if (isset($values->{$key_})) + { + $row[$column] = $values->{$key_}; + } + } + + // update the row + $this->row($row, $key, $table); + } + else + { + // update the row + $this->row((array) $values, $key, $table); + } + } + + return true; + } + + /** + * Update row in the database + * + * @param array $data Dataset to update in database (key => value) + * @param string $key Dataset key column to use in updating the values in the Database + * @param string $table The table where the data is being updated + * + * @return bool + * @since 3.2.0 + **/ + public function row(array $data, string $key, string $table): bool + { + // set the update columns + if ($data === [] || strlen($key) == 0) + { + return false; + } + + // get a query object + $query = $this->db->getQuery(true); + + // set the query targets + $query->update($this->db->quoteName($this->getTable($table))); + + // set the update values + $key_ = null; + foreach ($data as $column => $value) + { + if ($column === $key) + { + $key_ = $value; + } + else + { + $query->set($this->db->quoteName($column) . ' = ' . $this->quote($value)); + } + } + + // add the key condition + if ($key_ !== null) + { + $query->where($this->db->quoteName($key) . ' = ' . $this->quote($key_)); + + // execute the final query + $this->db->setQuery($query); + + return $this->db->execute(); + } + + return false; + } + + /** + * Update item in the database + * + * @param object $data Dataset to update in database (key => value) + * @param string $key Dataset key column to use in updating the values in the Database + * @param string $table The table where the data is being updated + * + * @return bool + * @since 3.2.0 + **/ + public function item(object $data, string $key, string $table): bool + { + // convert to an array + return $this->row((array) get_object_vars($data), $key, $table); + } +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Database/index.html b/libraries/jcb_powers/VDM.Joomla/src/Database/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Database/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla/src/Interfaces/FactoryInterface.php b/libraries/jcb_powers/VDM.Joomla/src/Interfaces/FactoryInterface.php new file mode 100644 index 0000000..0dd2e4c --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Interfaces/FactoryInterface.php @@ -0,0 +1,41 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Interfaces; + + +use Joomla\DI\Container; + + +/** + * The Container Factory Interface + */ +interface FactoryInterface +{ + /** + * Get any class from the container + * + * @param string $key The container class key + * + * @return Mixed + * @since 3.2.0 + */ + public static function _(string $key); + + /** + * Get the global container + * + * @return Container + * @since 3.2.0 + */ + public static function getContainer(): Container; +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Interfaces/InsertInterface.php b/libraries/jcb_powers/VDM.Joomla/src/Interfaces/InsertInterface.php new file mode 100644 index 0000000..c76b97b --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Interfaces/InsertInterface.php @@ -0,0 +1,78 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Interfaces; + + +/** + * Database Insert Interface + * + * @since 3.2.0 + */ +interface InsertInterface +{ + /** + * Switch to prevent/allow defaults from being added. + * + * @param bool $trigger toggle the defaults + * + * @return void + * @since 3.2.0 + **/ + public function defaults(bool $trigger = true); + + /** + * Insert rows to the database (with remapping and filtering columns option) + * + * @param array $data Dataset to store in database [array of arrays (key => value)] + * @param string $table The table where the data is being added + * @param array $columns Data columns for remapping and filtering + * + * @return bool + * @since 3.2.0 + **/ + public function rows(array $data, string $table, array $columns = []): bool; + + /** + * Insert items to the database (with remapping and filtering columns option) + * + * @param array $data Data to store in database (array of objects) + * @param string $table The table where the data is being added + * @param array $columns Data columns for remapping and filtering + * + * @return bool + * @since 3.2.0 + **/ + public function items(array $data, string $table, array $columns = []): bool; + + /** + * Insert row to the database + * + * @param array $data Dataset to store in database (key => value) + * @param string $table The table where the data is being added + * + * @return bool + * @since 3.2.0 + **/ + public function row(array $data, string $table): bool; + + /** + * Insert item to the database + * + * @param object $data Dataset to store in database (key => value) + * @param string $table The table where the data is being added + * + * @return bool + * @since 3.2.0 + **/ + public function item(object $data, string $table): bool; +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Interfaces/LoadInterface.php b/libraries/jcb_powers/VDM.Joomla/src/Interfaces/LoadInterface.php new file mode 100644 index 0000000..31017c5 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Interfaces/LoadInterface.php @@ -0,0 +1,114 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Interfaces; + + +/** + * Database Load Interface + * + * @since 3.2.0 + */ +interface LoadInterface +{ + /** + * Load data rows as an array of associated arrays + * + * @param array $select Array of selection keys + * @param array $tables Array of tables to search + * @param array|null $where Array of where key=>value match exist + * @param array|null $order Array of how to order the data + * @param int|null $limit Limit the number of values returned + * + * @return array|null + * @since 3.2.0 + **/ + public function rows(array $select, array $tables, ?array $where = null, + ?array $order = null, ?int $limit = null): ?array; + + /** + * Load data rows as an array of objects + * + * @param array $select Array of selection keys + * @param array $tables Array of tables to search + * @param array|null $where Array of where key=>value match exist + * @param array|null $order Array of how to order the data + * @param int|null $limit Limit the number of values returned + * + * @return array|null + * @since 3.2.0 + **/ + public function items(array $select, array $tables, ?array $where = null, + ?array $order = null, ?int $limit = null): ?array; + + /** + * Load data row as an associated array + * + * @param array $select Array of selection keys + * @param array $tables Array of tables to search + * @param array|null $where Array of where key=>value match exist + * @param array|null $order Array of how to order the data + * + * @return array|null + * @since 3.2.0 + **/ + public function row(array $select, array $tables, ?array $where = null, ?array $order = null): ?array; + + /** + * Load data row as an object + * + * @param array $select Array of selection keys + * @param array $tables Array of tables to search + * @param array|null $where Array of where key=>value match exist + * @param array|null $order Array of how to order the data + * + * @return object|null + * @since 3.2.0 + **/ + public function item(array $select, array $tables, ?array $where = null, ?array $order = null): ?object; + + /** + * Get the max value based on a filtered result from a given table + * + * @param string $field The field key + * @param string $tables The table + * @param array $filter The filter keys + * + * @return int|null + * @since 3.2.0 + **/ + public function max($field, array $tables, array $filter): ?int; + + /** + * Count the number of items based on filter result from a given table + * + * @param string $tables The table + * @param array $filter The filter keys + * + * @return int|null + * @since 3.2.0 + **/ + public function count(array $tables, array $filter): ?int; + + /** + * Load one value from a row + * + * @param array $select Array of selection keys + * @param array $tables Array of tables to search + * @param array|null $where Array of where key=>value match exist + * @param array|null $order Array of how to order the data + * + * @return mixed + * @since 3.2.0 + **/ + public function value(array $select, array $tables, ?array $where = null, ?array $order = null); +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Interfaces/ModelInterface.php b/libraries/jcb_powers/VDM.Joomla/src/Interfaces/ModelInterface.php new file mode 100644 index 0000000..51f3424 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Interfaces/ModelInterface.php @@ -0,0 +1,94 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Interfaces; + + +/** + * Model Interface + * + * @since 3.2.0 + */ +interface ModelInterface +{ + /** + * Model the value + * Example: $this->value(value, 'value_key', 'table_name'); + * + * @param mixed $value The value to model + * @param string $field The field key + * @param string|null $table The table + * + * @return mixed + * @since 3.2.0 + */ + public function value($value, string $field, ?string $table = null); + + /** + * Model the values of an item + * Example: $this->item(Object, 'table_name'); + * + * @param object $item The item object + * @param string|null $table The table + * + * @return object|null + * @since 3.2.0 + */ + public function item(object $item, ?string $table = null): ?object; + + /** + * Model the values of multiple items + * Example: $this->items(Array, 'table_name'); + * + * @param array|null $items The array of item objects + * @param string|null $table The table + * + * @return array|null + * @since 3.2.0 + */ + public function items(?array $items = null, ?string $table = null): ?array; + + /** + * Model the values of an row + * Example: $this->item(Array, 'table_name'); + * + * @param array $item The item array + * @param string|null $table The table + * + * @return array|null + * @since 3.2.0 + */ + public function row(array $item, ?string $table = null): ?array; + + /** + * Model the values of multiple rows + * Example: $this->items(Array, 'table_name'); + * + * @param array|null $items The array of item array + * @param string|null $table The table + * + * @return array|null + * @since 3.2.0 + */ + public function rows(?array $items = null, ?string $table = null): ?array; + + /** + * Get last modeled ID + * Example: $this->last('table_name'); + * + * @param string|null $table The table + * + * @return int|null + * @since 3.2.0 + */ + public function last(?string $table = null): ?int; +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Interfaces/Tableinterface.php b/libraries/jcb_powers/VDM.Joomla/src/Interfaces/Tableinterface.php new file mode 100644 index 0000000..4d8f741 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Interfaces/Tableinterface.php @@ -0,0 +1,89 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Interfaces; + + +/** + * The VDM Core Table Interface + */ +interface Tableinterface +{ + /** + * Get any value from a item/field/column of an area/view/table + * Example: $this->get('table_name', 'field_name', 'value_key'); + * Get an item/field/column of an area/view/table + * Example: $this->get('table_name', 'field_name'); + * Get all items/fields/columns of an area/view/table + * Example: $this->get('table_name'); + * Get all areas/views/tables with all their item/field/column details + * Example: $this->get('All'); + * + * @param string $table The table + * @param string|null $field The field + * @param string|null $key The value key + * + * @return mixed + * @since 3.2.0 + */ + public function get(string $table, ?string $field = null, ?string $key = null); + + /** + * Get title field from an area/view/table + * + * @param string $table The area + * + * @return ?array + * @since 3.2.0 + */ + public function title(string $table): ?array; + + /** + * Get title field name + * + * @param string $table The area + * + * @return string + * @since 3.2.0 + */ + public function titleName(string $table): string; + + /** + * Get all tables + * + * @return array + * @since 3.2.0 + */ + public function tables(): array; + + /** + * Check if a table (and field) exist + * + * @param string $table The area + * @param string|null $field The area + * + * @return bool + * @since 3.2.0 + */ + public function exist(string $table, ?string $field = null): bool; + + /** + * Get all fields of an area/view/table + * + * @param string $table The area + * @param bool $default Add the default fields + * + * @return array|null On success an array of fields + * @since 3.2.0 + */ + public function fields(string $table, bool $default = false): ?array; +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Interfaces/UpdateInterface.php b/libraries/jcb_powers/VDM.Joomla/src/Interfaces/UpdateInterface.php new file mode 100644 index 0000000..3e43b16 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Interfaces/UpdateInterface.php @@ -0,0 +1,72 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Interfaces; + + +/** + * Database Update Interface + * + * @since 3.2.0 + */ +interface UpdateInterface +{ + /** + * Update rows in the database (with remapping and filtering columns option) + * + * @param array $data Dataset to update in database [array of arrays (key => value)] + * @param string $key Dataset key column to use in updating the values in the Database + * @param string $table The table where the data is being updated + * @param array $columns Data columns for remapping and filtering + * + * @return bool + * @since 3.2.0 + **/ + public function rows(array $data, string $key, string $table, array $columns = []): bool; + + /** + * Update items in the database (with remapping and filtering columns option) + * + * @param array $data Data to updated in database (array of objects) + * @param string $key Dataset key column to use in updating the values in the Database + * @param string $table The table where the data is being update + * @param array $columns Data columns for remapping and filtering + * + * @return bool + * @since 3.2.0 + **/ + public function items(array $data, string $key, string $table, array $columns = []): bool; + + /** + * Update row in the database + * + * @param array $data Dataset to update in database (key => value) + * @param string $key Dataset key column to use in updating the values in the Database + * @param string $table The table where the data is being updated + * + * @return bool + * @since 3.2.0 + **/ + public function row(array $data, string $key, string $table): bool; + + /** + * Update item in the database + * + * @param object $data Dataset to update in database (key => value) + * @param string $key Dataset key column to use in updating the values in the Database + * @param string $table The table where the data is being updated + * + * @return bool + * @since 3.2.0 + **/ + public function item(object $data, string $key, string $table): bool; +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Interfaces/index.html b/libraries/jcb_powers/VDM.Joomla/src/Interfaces/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Interfaces/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla/src/Utilities/ArrayHelper.php b/libraries/jcb_powers/VDM.Joomla/src/Utilities/ArrayHelper.php new file mode 100644 index 0000000..70cc939 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Utilities/ArrayHelper.php @@ -0,0 +1,107 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Utilities; + + +/** + * Some array tricks helper + * + * @since 3.0.9 + */ +abstract class ArrayHelper +{ + /** + * Check if have an array with a length + * + * @input array The array to check + * + * @returns int|false number of items in array on success + * + * @since 3.2.0 + */ + public static function check($array, $removeEmptyString = false) + { + if (is_array($array) && ($nr = count((array) $array)) > 0) + { + // also make sure the empty strings are removed + if ($removeEmptyString) + { + $array = array_filter($array); + + if ($array === []) + { + return false; + } + + return count($array); + } + + return $nr; + } + + return false; + } + + /** + * Merge an array of array's + * + * @input array The arrays you would like to merge + * + * @returns array|null merged array on success + * + * @since 3.0.9 + */ + public static function merge($arrays): ?array + { + if(self::check($arrays)) + { + $merged = []; + foreach ($arrays as $array) + { + if (self::check($array)) + { + $merged = array_merge($merged, $array); + } + } + return $merged; + } + return null; + } + + /** + * Check if arrays intersect + * + * @input array The first array + * @input array The second array + * + * @returns bool true if intersect else false + * + * @since 3.1.1 + */ + public static function intersect($a_array, $b_array): bool + { + // flip the second array + $b_array = array_flip($b_array); + + // loop the first array + foreach ($a_array as $v) + { + if (isset($b_array[$v])) + { + return true; + } + } + return false; + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Utilities/Component/Helper.php b/libraries/jcb_powers/VDM.Joomla/src/Utilities/Component/Helper.php new file mode 100644 index 0000000..61dbf59 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Utilities/Component/Helper.php @@ -0,0 +1,189 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Utilities\Component; + + +use Joomla\Input\Input; +use Joomla\CMS\Component\ComponentHelper; +use Joomla\Registry\Registry; + + +/** + * Some component helper + * + * @since 3.0.11 + */ +abstract class Helper +{ + /** + * The current option + * + * @var string + * @since 3.0.11 + */ + public static string $option; + + /** + * The component params list cache + * + * @var Registry[] + * @since 3.0.11 + */ + protected static array $params = []; + + /** + * Gets the parameter object for the component + * + * @param string|null $option The option for the component. + * + * @return Registry A Registry object. + * @see Registry + * @since 3.0.11 + */ + public static function getParams(?string $option = null): Registry + { + // check that we have an option + if (empty($option)) + { + $option = self::getOption(); + } + + // get global value + if (!isset(self::$params[$option]) || !self::$params[$option] instanceof Registry) + { + self::$params[$option] = ComponentHelper::getParams($option); + } + + return self::$params[$option]; + } + + /** + * Gets the component option + * + * @param string|null $default The default return value if none is found + * + * @return string|null A component option + * @since 3.0.11 + */ + public static function getOption(string $default = 'empty'): ?string + { + if (empty(self::$option)) + { + // get the option from the url input + self::$option = (new Input)->getString('option', false); + } + + if (self::$option) + { + return self::$option; + } + + return $default; + } + + /** + * Gets the component code name + * + * @param string|null $option The option for the component. + * @param string|null $default The default return value if none is found + * + * @return string|null A component code name + * @since 3.0.11 + */ + public static function getCode(?string $option = null, ?string $default = null): ?string + { + // check that we have an option + if (empty($option)) + { + $option = self::getOption(); + } + // option with com_ + if (is_string($option) && strpos($option, 'com_') === 0) + { + return strtolower(trim(substr($option, 4))); + } + + return $default; + } + + /** + * Gets the component abstract helper class + * + * @param string|null $option The option for the component. + * @param string|null $default The default return value if none is found + * + * @return string|null A component helper name + * + * @since 3.0.11 + */ + public static function get(string $option = null, string $default = null): ?string + { + // check that we have an option + // and get the code name from it + if (($code_name = self::getCode($option, false)) !== false) + { + // we build the helper class name + $helper_name = '\\' . \ucfirst($code_name) . 'Helper'; + // check if class exist + if (class_exists($helper_name)) + { + return $helper_name; + } + } + + return $default; + } + + /** + * Check if the helper class of this component has a method + * + * @param string $method The method name to search for + * @param string|null $option The option for the component. + * + * @return bool true if method exist + * + * @since 3.0.11 + */ + public static function methodExists(string $method, string $option = null): bool + { + // get the helper class + return ($helper = self::get($option, false)) !== false && + method_exists($helper, $method); + } + + /** + * Check if the helper class of this component has a method, and call it with the arguments + * + * @param string $method The method name to search for + * @param array $arguments The arguments for function. + * @param string|null $option The option for the component. + * + * @return mixed return whatever the method returns or null + * @since 3.2.0 + */ + public static function _(string $method, array $arguments = [], ?string $option = null) + { + // get the helper class + if (($helper = self::get($option, false)) !== false && + method_exists($helper, $method)) + { + // we know this is not ideal... + // so we need to move these + // functions to their own classes + return call_user_func_array([$helper, $method], $arguments); + } + + return null; + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Utilities/Component/index.html b/libraries/jcb_powers/VDM.Joomla/src/Utilities/Component/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Utilities/Component/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla/src/Utilities/FileHelper.php b/libraries/jcb_powers/VDM.Joomla/src/Utilities/FileHelper.php new file mode 100644 index 0000000..7bbc782 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Utilities/FileHelper.php @@ -0,0 +1,363 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Utilities; + + +use Joomla\CMS\Uri\Uri; +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\Filesystem\Path; +use Joomla\CMS\Filesystem\File; +use Joomla\CMS\Filesystem\Folder; +use Joomla\Archive\Archive; +use VDM\Joomla\Utilities\Component\Helper; + + +/** + * File helper + * + * @since 3.0.9 + */ +abstract class FileHelper +{ + /** + * Trigger error notice only once + * + * @var bool + * + * @since 3.0.9 + */ + protected static $curlError = false; + + /** + * The zipper method + * + * @param string $workingDirectory The directory where the items must be zipped + * @param string $filepath The path to where the zip file must be placed + * + * @return bool true On success + * + * @since 3.0.9 + */ + public static function zip($workingDirectory, &$filepath): bool + { + // store the current joomla working directory + $joomla = getcwd(); + + // we are changing the working directory to the component temp folder + chdir($workingDirectory); + + // the full file path of the zip file + $filepath = Path::clean($filepath); + + // delete an existing zip file (or use an exclusion parameter in Folder::files() + File::delete($filepath); + + // get a list of files in the current directory tree (also the hidden files) + $files = Folder::files('.', '', true, true, array('.svn', 'CVS', '.DS_Store', '__MACOSX'), array('.*~')); + + $zipArray = []; + // setup the zip array + foreach ($files as $file) + { + $tmp = []; + $tmp['name'] = str_replace('./', '', (string) $file); + $tmp['data'] = self::getContent($file); + $tmp['time'] = filemtime($file); + $zipArray[] = $tmp; + } + + // change back to joomla working directory + chdir($joomla); + + // get the zip adapter + $zip = (new Archive())->getAdapter('zip'); + + //create the zip file + return (bool) $zip->create($filepath, $zipArray); + } + + /** + * get the content of a file + * + * @param string $path The path to the file + * @param string/bool $none The return value if no content was found + * + * @return string On success + * + * @since 3.0.9 + */ + public static function getContent($path, $none = '') + { + if (StringHelper::check($path)) + { + // use basic file get content for now + if (($content = @file_get_contents($path)) !== FALSE) + { + return $content; + } + // use curl if available + elseif (function_exists('curl_version')) + { + // start curl + $ch = curl_init(); + // set the options + $options = []; + $options[CURLOPT_URL] = $path; + $options[CURLOPT_USERAGENT] = 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'; + $options[CURLOPT_RETURNTRANSFER] = TRUE; + $options[CURLOPT_SSL_VERIFYPEER] = FALSE; + // load the options + curl_setopt_array($ch, $options); + // get the content + $content = curl_exec($ch); + // close the connection + curl_close($ch); + + // return if found + if (StringHelper::check($content)) + { + return $content; + } + } + elseif (!self::$curlError) + { + // set the notice + Factory::getApplication()->enqueueMessage(Text::_('COM_GETBIBLE_HTWOCURL_NOT_FOUNDHTWOPPLEASE_SETUP_CURL_ON_YOUR_SYSTEM_OR_BGETBIBLEB_WILL_NOT_FUNCTION_CORRECTLYP'), 'Error'); + // load this notice only once + self::$curlError = true; + } + } + return $none; + } + + /** + * Write a file to the server + * + * @param string $path The path and file name where to safe the data + * @param string $data The data to safe + * + * @return bool true On success + * + * @since 3.0.9 + */ + public static function write($path, $data) + { + $klaar = false; + if (StringHelper::check($data)) + { + // open the file + $fh = fopen($path, "w"); + if (!is_resource($fh)) + { + return $klaar; + } + // write to the file + if (fwrite($fh, $data)) + { + // has been done + $klaar = true; + } + // close file. + fclose($fh); + } + return $klaar; + } + + /** + * get all the file paths in folder and sub folders + * + * @param string $folder The local path to parse + * @param array $fileTypes The type of files to get + * + * @return void + * + * @since 3.0.9 + */ + public static function getPaths($folder, $fileTypes = array('\.php', '\.js', '\.css', '\.less'), $recurse = true, $full = true) + { + if (Folder::exists($folder)) + { + // we must first store the current woking directory + $joomla = getcwd(); + // we are changing the working directory to the component path + chdir($folder); + + // make sure we have file type filter + if (ArrayHelper::check($fileTypes)) + { + // get the files + foreach ($fileTypes as $type) + { + // get a list of files in the current directory tree + $files[] = Folder::files('.', $type, $recurse, $full); + } + } + elseif (StringHelper::check($fileTypes)) + { + // get a list of files in the current directory tree + $files[] = Folder::files('.', $fileTypes, $recurse, $full); + } + else + { + // get a list of files in the current directory tree + $files[] = Folder::files('.', '.', $recurse, $full); + } + + // change back to Joomla working directory + chdir($joomla); + + // return array of files + return array_map( fn($file) => str_replace('./', '/', (string) $file), (array) ArrayHelper::merge($files)); + } + return false; + } + + /** + * Get the file path or url + * + * @param string $type The (url/path) type to return + * @param string $target The Params Target name (if set) + * @param string $fileType The kind of filename to generate (if not set no file name is generated) + * @param string $key The key to adjust the filename (if not set ignored) + * @param string $default The default path if not set in Params (fallback path) + * @param bool $createIfNotSet The switch to create the folder if not found + * + * @return string On success the path or url is returned based on the type requested + * + * @since 3.0.9 + */ + public static function getPath($type = 'path', $target = 'filepath', $fileType = null, $key = '', $default = '', $createIfNotSet = true) + { + // make sure to always have a string/path + if(!StringHelper::check($default)) + { + $default = JPATH_SITE . '/images/'; + } + + // get the global settings + $filePath = Helper::getParams()->get($target, $default); + + // check the file path (revert to default only of not a hidden file path) + if ('hiddenfilepath' !== $target && strpos((string) $filePath, (string) JPATH_SITE) === false) + { + $filePath = $default; + } + + // create the folder if it does not exist + if ($createIfNotSet && !Folder::exists($filePath)) + { + Folder::create($filePath); + } + + // setup the file name + $fileName = ''; + + // Get basic key + $basickey = 'Th!s_iS_n0t_sAfe_buT_b3tter_then_n0thiug'; + // get the component helper + $helper = Helper::get(); + // check if method exist in helper class + if ($helper && Helper::methodExists('getCryptKey')) + { + $basickey = $helper::getCryptKey('basic', $basickey); + } + + // check the key + if (!StringHelper::check($key)) + { + $key = 'vDm'; + } + + // set the file name + if (StringHelper::check($fileType)) + { + // set the name + $fileName = trim( md5($type . $target . $basickey . $key) . '.' . trim($fileType, '.')); + } + else + { + $fileName = trim( md5($type . $target . $basickey . $key)) . '.txt'; + } + + // return the url + if ('url' === $type) + { + if (\strpos((string) $filePath, (string) JPATH_SITE) !== false) + { + $filePath = trim( str_replace( JPATH_SITE, '', (string) $filePath), '/'); + + return Uri::root() . $filePath . '/' . $fileName; + } + + // since the path is behind the root folder of the site, return only the root url (may be used to build the link) + return Uri::root(); + } + + // sanitize the path + return '/' . trim((string) $filePath, '/' ) . '/' . $fileName; + } + + /** + * Check if file exist + * + * @param string $path The url/path to check + * + * @return bool If exist true + * + * @since 3.0.9 + */ + public static function exists($path) + { + $exists = false; + // if this is a local path + if (strpos($path, 'http:') === false && strpos($path, 'https:') === false) + { + if (file_exists($path)) + { + $exists = true; + } + } + // check if we can use curl + elseif (function_exists('curl_version')) + { + // initiate curl + $ch = curl_init($path); + // CURLOPT_NOBODY (do not return body) + curl_setopt($ch, CURLOPT_NOBODY, true); + // make call + $result = curl_exec($ch); + // check return value + if ($result !== false) + { + // get the http CODE + $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + if ($statusCode !== 404) + { + $exists = true; + } + } + // close the connection + curl_close($ch); + } + elseif ($headers = @get_headers($path)) + { + if(isset($headers[0]) && is_string($headers[0]) && strpos($headers[0],'404') === false) + { + $exists = true; + } + } + return $exists; + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Utilities/GetHelper.php b/libraries/jcb_powers/VDM.Joomla/src/Utilities/GetHelper.php new file mode 100644 index 0000000..f584097 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Utilities/GetHelper.php @@ -0,0 +1,253 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Utilities; + + +use Joomla\CMS\Factory; +use VDM\Joomla\Utilities\Component\Helper; + + +/** + * Some easy get... + * + * @since 3.0.9 + */ +abstract class GetHelper +{ + /** + * Get a Variable + * + * @param string|null $table The table from which to get the variable + * @param mixed $where The value where + * @param string $whereString The target/field string where/name + * @param string $what The return field + * @param string $operator The operator between $whereString/field and $where/value + * @param string $main The component in which the table is found + * + * @return mixed string/int/float + * @since 3.0.9 + */ + public static function var(?string $table = null, $where = null, + string $whereString = 'user', string $what = 'id', + string $operator = '=', ?string $main = null) + { + if(empty($where)) + { + $where = Factory::getUser()->id; + } + + if(empty($main)) + { + $main = Helper::getCode(); + } + + // Get a db connection. + $db = Factory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + $query->select($db->quoteName(array($what))); + + if (empty($table)) + { + $query->from($db->quoteName('#__' . $main)); + } + else + { + $query->from($db->quoteName('#__' . $main . '_' . $table)); + } + + if (is_numeric($where)) + { + $query->where($db->quoteName($whereString) . ' ' . $operator . ' ' . (int) $where); + } + elseif (is_string($where)) + { + $query->where($db->quoteName($whereString) . ' ' . $operator . ' ' . $db->quote((string)$where)); + } + else + { + return false; + } + + $db->setQuery($query); + $db->execute(); + + if ($db->getNumRows()) + { + return $db->loadResult(); + } + + return false; + } + + /** + * Get array of variables + * + * @param string|null $table The table from which to get the variables + * @param mixed $where The value where + * @param string $whereString The target/field string where/name + * @param string $what The return field + * @param string $operator The operator between $whereString/field and $where/value + * @param string $main The component in which the table is found + * @param bool $unique The switch to return a unique array + * + * @return array|null + * @since 3.0.9 + */ + public static function vars(?string $table = null, $where = null, + string $whereString = 'user', string $what = 'id', string $operator = 'IN', + ?string $main = null, bool $unique = true): ?array + { + if(empty($where)) + { + $where = Factory::getUser()->id; + } + + if(is_null($main)) + { + $main = Helper::getCode(); + } + + if (!ArrayHelper::check($where) && $where > 0) + { + $where = array($where); + } + + if (ArrayHelper::check($where)) + { + // prep main <-- why? well if $main='' is empty then $table can be categories or users + if (StringHelper::check($main)) + { + $main = '_' . ltrim($main, '_'); + } + + // Get a db connection. + $db = Factory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + $query->select($db->quoteName(array($what))); + + if (empty($table)) + { + $query->from($db->quoteName('#__' . $main)); + } + else + { + $query->from($db->quoteName('#_' . $main . '_' . $table)); + } + + // add strings to array search + if ('IN_STRINGS' === $operator || 'NOT IN_STRINGS' === $operator) + { + $query->where($db->quoteName($whereString) . ' ' . str_replace('_STRINGS', '', $operator) . ' ("' . implode('","', $where) . '")'); + } + else + { + $query->where($db->quoteName($whereString) . ' ' . $operator . ' (' . implode(',', $where) . ')'); + } + + $db->setQuery($query); + $db->execute(); + + if ($db->getNumRows()) + { + if ($unique) + { + return array_unique($db->loadColumn()); + } + return $db->loadColumn(); + } + } + + return null; + } + + /** + * get all strings between two other strings + * + * @param string $content The content to search + * @param string $start The starting value + * @param string $end The ending value + * + * @return array|null On success + * @since 3.0.9 + */ + public static function allBetween(string $content, string $start, string $end): ?array + { + // reset bucket + $bucket = []; + for ($i = 0; ; $i++) + { + // search for string + $found = self::between($content, $start, $end); + + if (StringHelper::check($found)) + { + // add to bucket + $bucket[] = $found; + + // build removal string + $remove = $start . $found . $end; + + // remove from content + $content = str_replace($remove, '', $content); + } + else + { + break; + } + + // safety catch + if ($i == 500) + { + break; + } + } + + // only return unique array of values + if (ArrayHelper::check($bucket)) + { + return array_unique($bucket); + } + + return null; + } + + /** + * get a string between two other strings + * + * @param string $content The content to search + * @param string $start The starting value + * @param string $end The ending value + * @param string $default The default value if none found + * + * @return string On success / empty string on failure + * @since 3.0.9 + */ + public static function between(string $content, string $start, string $end, string $default = ''): string + { + $array = explode($start, $content); + if (isset($array[1]) && strpos($array[1], $end) !== false) + { + $array = explode($end, $array[1]); + + // return string found between + return $array[0]; + } + + return $default; + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Utilities/GuidHelper.php b/libraries/jcb_powers/VDM.Joomla/src/Utilities/GuidHelper.php new file mode 100644 index 0000000..e219473 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Utilities/GuidHelper.php @@ -0,0 +1,215 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Utilities; + + +use Joomla\CMS\Factory; +use VDM\Joomla\Utilities\Component\Helper; + + +/** + * Global Unique ID Helper + * + * @since 3.0.9 + */ +abstract class GuidHelper +{ + /** + * Returns a GUIDv4 string + * + * Thanks to Dave Pearson (and other) + * https://www.php.net/manual/en/function.com-create-guid.php#119168 + * + * Uses the best cryptographically secure method + * for all supported platforms with fallback to an older, + * less secure version. + * + * @param bool $trim + * + * @return string + * + * @since 3.0.9 + */ + public static function get(bool $trim = true): string + { + // Windows + if (function_exists('com_create_guid')) + { + if ($trim) + { + return trim(com_create_guid(), '{}'); + } + return com_create_guid(); + } + + // set the braces if needed + $lbrace = $trim ? "" : chr(123); // "{" + $rbrace = $trim ? "" : chr(125); // "}" + + // OSX/Linux + if (function_exists('openssl_random_pseudo_bytes')) + { + $data = openssl_random_pseudo_bytes(16); + $data[6] = chr( ord($data[6]) & 0x0f | 0x40); // set version to 0100 + $data[8] = chr( ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10 + return $lbrace . vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)) . $lbrace; + } + + // Fallback (PHP 4.2+) + mt_srand((double) microtime() * 10000); + $charid = strtolower( md5( uniqid( rand(), true))); + $hyphen = chr(45); // "-" + $guidv4 = $lbrace. + substr($charid, 0, 8). $hyphen. + substr($charid, 8, 4). $hyphen. + substr($charid, 12, 4). $hyphen. + substr($charid, 16, 4). $hyphen. + substr($charid, 20, 12). + $rbrace; + return $guidv4; + } + + /** + * Validate the Globally Unique Identifier ( and check if table already has this identifier) + * + * @param string $guid + * @param string|null $table + * @param int $id + * @param string|null $component + * + * @return bool + * + * @since 3.0.9 + */ + public static function valid($guid, ?string $table = null, int $id = 0, ?string $component = null): bool + { + // check if we have a string + if (self::validate($guid)) + { + // check if table already has this identifier + if (StringHelper::check($table)) + { + // check that we have the component code name + if (!is_string($component)) + { + $component = (string) Helper::getCode(); + } + // Get the database object and a new query object. + $db = Factory::getDbo(); + $query = $db->getQuery(true); + $query->select('COUNT(*)') + ->from('#__' . (string) $component . '_' . (string) $table) + ->where($db->quoteName('guid') . ' = ' . $db->quote($guid)); + + // remove this item from the list + if ($id > 0) + { + $query->where($db->quoteName('id') . ' <> ' . (int) $id); + } + + // Set and query the database. + $db->setQuery($query); + $duplicate = (bool) $db->loadResult(); + + if ($duplicate) + { + return false; + } + } + return true; + } + return false; + } + + /** + * get the item by guid in a table + * + * @param string $guid + * @param string $table + * @param string|array $what + * @param string|null $component + * + * @return mix + * + * @since 3.0.9 + */ + public static function item($guid, $table, $what = 'a.id', ?string $component = null) + { + // check if we have a string + // check if table already has this identifier + if (self::validate($guid) && StringHelper::check($table)) + { + // check that we have the component code name + if (!is_string($component)) + { + $component = (string) Helper::getCode(); + } + // Get the database object and a new query object. + $db = Factory::getDbo(); + $query = $db->getQuery(true); + + if (ArrayHelper::check($what)) + { + $query->select($db->quoteName($what)); + } + else + { + $query->select($what); + } + + $query->from($db->quoteName('#__' . (string) $component . '_' . (string) $table, 'a')) + ->where($db->quoteName('a.guid') . ' = ' . $db->quote($guid)); + + // Set and query the database. + $db->setQuery($query); + $db->execute(); + + if ($db->getNumRows()) + { + if (ArrayHelper::check($what) || $what === 'a.*') + { + return $db->loadObject(); + } + else + { + return $db->loadResult(); + } + } + } + + return null; + } + + /** + * Validate the Globally Unique Identifier + * + * Thanks to Lewie + * https://stackoverflow.com/a/1515456/1429677 + * + * @param string $guid + * + * @return bool + * + * @since 3.0.9 + */ + protected static function validate($guid) + { + // check if we have a string + if (StringHelper::check($guid)) + { + return preg_match("/^(\{)?[a-f\d]{8}(-[a-f\d]{4}){4}[a-f\d]{8}(?(1)\})$/i", $guid); + } + return false; + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Utilities/JsonHelper.php b/libraries/jcb_powers/VDM.Joomla/src/Utilities/JsonHelper.php new file mode 100644 index 0000000..47fbd24 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Utilities/JsonHelper.php @@ -0,0 +1,101 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Utilities; + + +/** + * The json checker + * + * @since 3.0.9 + */ +abstract class JsonHelper +{ + /** + * Check if you have a json string + * + * @input string $string The json string to check + * + * @returns bool true on success + * + * @since 3.0.9 + */ + public static function check($string): bool + { + if (StringHelper::check($string)) + { + json_decode((string) $string); + return (json_last_error() === JSON_ERROR_NONE); + } + + return false; + } + + /** + * Convert a json object to a string + * + * @input string $value The json string to convert + * + * @returns a string + * + * @since 3.0.9 + */ + public static function string($value, $separator = ", ", $table = null, $id = 'id', $name = 'name') + { + // do some table foot work + $external = false; + if (is_string($table) && strpos((string) $table, '#__') !== false) + { + $external = true; + $table = str_replace('#__', '', (string) $table); + } + + // check if string is JSON + $result = json_decode((string) $value, true); + if (json_last_error() === JSON_ERROR_NONE) + { + // is JSON + if (ArrayHelper::check($result)) + { + if (StringHelper::check($table)) + { + $names = []; + foreach ($result as $val) + { + if ($external) + { + if ($_name = GetHelper::var(null, $val, $id, $name, '=', $table)) + { + $names[] = $_name; + } + } + else + { + if ($_name = GetHelper::var($table, $val, $id, $name)) + { + $names[] = $_name; + } + } + } + if (ArrayHelper::check($names)) + { + return (string) implode($separator, $names); + } + } + return (string) implode($separator, $result); + } + return (string) json_decode((string) $value); + } + return $value; + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Utilities/ObjectHelper.php b/libraries/jcb_powers/VDM.Joomla/src/Utilities/ObjectHelper.php new file mode 100644 index 0000000..2646f7c --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Utilities/ObjectHelper.php @@ -0,0 +1,78 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Utilities; + + +/** + * Some object tricks + * + * @since 3.0.9 + */ +abstract class ObjectHelper +{ + /** + * Check if have an object with a length + * + * @input object The object to check + * + * @returns bool true on success + * + * @since 3.0.9 + */ + public static function check($object) + { + if (is_object($object)) + { + return count((array) $object) > 0; + } + + return false; + } + + /** + * Compare two objects for equality based on their property values. + * + * Note that this method works only for simple objects that don't + * contain any nested objects or resource references. If you need + * to compare more complex objects, you may need to use a + * more advanced method such as serialization or reflection. + * + * @param object|null $obj1 The first object to compare. + * @param object|null $obj2 The second object to compare. + * + * @return bool True if the objects have the same key-value pairs and false otherwise. + */ + public static function equal(?object $obj1, ?object $obj2): bool + { + // if any is null we return false as that means there is a none object + // we are not comparing null but objects + // but we allow null as some objects while + // not instantiate are still null + if (is_null($obj1) || is_null($obj2)) + { + return false; + } + + // Convert the objects to arrays of their property values using get_object_vars. + $array1 = get_object_vars($obj1); + $array2 = get_object_vars($obj2); + + // Compare the arrays using array_diff_assoc to detect any differences. + $diff1 = array_diff_assoc($array1, $array2); + $diff2 = array_diff_assoc($array2, $array1); + + // If the arrays have the same key-value pairs, they will have no differences, so return true. + return empty($diff1) && empty($diff2); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Utilities/String/ClassfunctionHelper.php b/libraries/jcb_powers/VDM.Joomla/src/Utilities/String/ClassfunctionHelper.php new file mode 100644 index 0000000..42d21af --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Utilities/String/ClassfunctionHelper.php @@ -0,0 +1,47 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Utilities\String; + + +use VDM\Joomla\Utilities\StringHelper; + + +/** + * Control the naming of a class and function + * + * @since 3.0.9 + */ +abstract class ClassfunctionHelper +{ + /** + * Making class or function name safe + * + * @input string The name you would like to make safe + * + * @returns string on success + * + * @since 3.0.9 + */ + public static function safe($name): string + { + // remove numbers if the first character is a number + if (is_numeric(substr((string) $name, 0, 1))) + { + $name = StringHelper::numbers($name); + } + + // remove all spaces and strange characters + return trim(preg_replace("/[^A-Za-z0-9_-]/", '', (string) $name)); + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Utilities/String/index.html b/libraries/jcb_powers/VDM.Joomla/src/Utilities/String/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Utilities/String/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/VDM.Joomla/src/Utilities/StringHelper.php b/libraries/jcb_powers/VDM.Joomla/src/Utilities/StringHelper.php new file mode 100644 index 0000000..3a37f2b --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Utilities/StringHelper.php @@ -0,0 +1,416 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Utilities; + + +use Joomla\CMS\Filter\InputFilter; +use Joomla\CMS\Language\Language; +use VDM\Joomla\Utilities\Component\Helper; + + +/** + * Some string tricks + * + * @since 3.0.9 + */ +abstract class StringHelper +{ + /** + * The Main Active Language + * + * @var string + * + * @since 3.0.9 + */ + public static $langTag; + + /** + * Check if we have a string with a length + * + * @input string $string The string to check + * + * @returns bool true on success + * + * @since 3.0.9 + */ + public static function check($string): bool + { + return is_string($string) && strlen($string) > 0; + } + + /** + * Shorten a string + * + * @input string The you would like to shorten + * + * @returns string on success + * + * @since 3.0.9 + */ + public static function shorten($string, $length = 40, $addTip = true) + { + if (self::check($string)) + { + $initial = strlen((string) $string); + $words = preg_split('/([\s\n\r]+)/', (string) $string, null, PREG_SPLIT_DELIM_CAPTURE); + $words_count = count((array)$words); + + $word_length = 0; + $last_word = 0; + for (; $last_word < $words_count; ++$last_word) + { + $word_length += strlen($words[$last_word]); + if ($word_length > $length) + { + break; + } + } + + $newString = implode(array_slice($words, 0, $last_word)); + $final = strlen($newString); + if ($initial !== $final && $addTip) + { + $title = self::shorten($string, 400 , false); + return '' . trim($newString) . '...'; + } + elseif ($initial !== $final && !$addTip) + { + return trim($newString) . '...'; + } + } + return $string; + } + + /** + * Making strings safe (various ways) + * + * @input string The you would like to make safe + * + * @returns string on success + * + * @since 3.0.9 + */ + public static function safe($string, $type = 'L', $spacer = '_', $replaceNumbers = true, $keepOnlyCharacters = true) + { + if ($replaceNumbers === true) + { + // remove all numbers and replace with English text version (works well only up to millions) + $string = self::numbers($string); + } + // 0nly continue if we have a string + if (self::check($string)) + { + // create file name without the extension that is safe + if ($type === 'filename') + { + // make sure VDM is not in the string + $string = str_replace('VDM', 'vDm', (string) $string); + // Remove anything which isn't a word, whitespace, number + // or any of the following caracters -_() + // If you don't need to handle multi-byte characters + // you can use preg_replace rather than mb_ereg_replace + // Thanks @Łukasz Rysiak! + // $string = mb_ereg_replace("([^\w\s\d\-_\(\)])", '', $string); + $string = preg_replace("([^\w\s\d\-_\(\)])", '', $string); + + // http://stackoverflow.com/a/2021729/1429677 + return preg_replace('/\s+/', ' ', (string) $string); + } + // remove all other characters + $string = trim((string) $string); + $string = preg_replace('/'.$spacer.'+/', ' ', $string); + $string = preg_replace('/\s+/', ' ', $string); + // Transliterate string + $string = self::transliterate($string); + // remove all and keep only characters + if ($keepOnlyCharacters) + { + $string = preg_replace("/[^A-Za-z ]/", '', (string) $string); + } + // keep both numbers and characters + else + { + $string = preg_replace("/[^A-Za-z0-9 ]/", '', (string) $string); + } + // select final adaptations + if ($type === 'L' || $type === 'strtolower') + { + // replace white space with underscore + $string = preg_replace('/\s+/', (string) $spacer, (string) $string); + // default is to return lower + return strtolower($string); + } + elseif ($type === 'W') + { + // return a string with all first letter of each word uppercase(no underscore) + return ucwords(strtolower($string)); + } + elseif ($type === 'w' || $type === 'word') + { + // return a string with all lowercase(no underscore) + return strtolower($string); + } + elseif ($type === 'Ww' || $type === 'Word') + { + // return a string with first letter of the first word uppercase and all the rest lowercase(no underscore) + return ucfirst(strtolower($string)); + } + elseif ($type === 'WW' || $type === 'WORD') + { + // return a string with all the uppercase(no underscore) + return strtoupper($string); + } + elseif ($type === 'U' || $type === 'strtoupper') + { + // replace white space with underscore + $string = preg_replace('/\s+/', (string) $spacer, $string); + // return all upper + return strtoupper($string); + } + elseif ($type === 'F' || $type === 'ucfirst') + { + // replace white space with underscore + $string = preg_replace('/\s+/', (string) $spacer, $string); + // return with first character to upper + return ucfirst(strtolower($string)); + } + elseif ($type === 'cA' || $type === 'cAmel' || $type === 'camelcase') + { + // convert all words to first letter uppercase + $string = ucwords(strtolower($string)); + // remove white space + $string = preg_replace('/\s+/', '', $string); + // now return first letter lowercase + return lcfirst($string); + } + // return string + return $string; + } + // not a string + return ''; + } + + /** + * Convert none English strings to code usable string + * + * @input an string + * + * @returns a string + * + * @since 3.0.9 + */ + public static function transliterate($string) + { + // set tag only once + if (!self::check(self::$langTag)) + { + // get global value + self::$langTag = Helper::getParams()->get('language', 'en-GB'); + } + + // Transliterate on the language requested + $lang = Language::getInstance(self::$langTag); + + return $lang->transliterate($string); + } + + /** + * make sure a string is HTML save + * + * @input an html string + * + * @returns a string + * + * @since 3.0.9 + */ + public static function html($var, $charset = 'UTF-8', $shorten = false, $length = 40, $addTip = true) + { + if (self::check($var)) + { + $filter = new InputFilter(); + $string = $filter->clean( + html_entity_decode( + htmlentities( + (string) $var, + ENT_COMPAT, + $charset + ) + ), + 'HTML' + ); + if ($shorten) + { + return self::shorten($string, $length, $addTip); + } + return $string; + } + else + { + return ''; + } + } + + /** + * Convert all int in a string to an English word string + * + * @input an string with numbers + * + * @returns a string + * + * @since 3.0.9 + */ + public static function numbers($string) + { + // set numbers array + $numbers = []; + $search_replace= []; + + // first get all numbers + preg_match_all('!\d+!', (string) $string, $numbers); + + // check if we have any numbers + if (isset($numbers[0]) && ArrayHelper::check($numbers[0])) + { + foreach ($numbers[0] as $number) + { + $search_replace[$number] = self::number((int)$number); + } + + // now replace numbers in string + $string = str_replace(array_keys($search_replace), array_values($search_replace), (string) $string); + + // check if we missed any, strange if we did. + return self::numbers($string); + } + + // return the string with no numbers remaining. + return $string; + } + + /** + * Convert an integer into an English word string + * Thanks to Tom Nicholson + * + * @input an int + * @returns a string + * + * @since 3.0.9 + */ + public static function number($x) + { + $nwords = array( "zero", "one", "two", "three", "four", "five", "six", "seven", + "eight", "nine", "ten", "eleven", "twelve", "thirteen", + "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", + "nineteen", "twenty", 30 => "thirty", 40 => "forty", + 50 => "fifty", 60 => "sixty", 70 => "seventy", 80 => "eighty", + 90 => "ninety" ); + + if(!is_numeric($x)) + { + $w = $x; + } + elseif(fmod($x, 1) != 0) + { + $w = $x; + } + else + { + if($x < 0) + { + $w = 'minus '; + $x = -$x; + } + else + { + $w = ''; + // ... now $x is a non-negative integer. + } + + if($x < 21) // 0 to 20 + { + $w .= $nwords[$x]; + } + elseif($x < 100) // 21 to 99 + { + $w .= $nwords[10 * floor($x/10)]; + $r = fmod($x, 10); + if($r > 0) + { + $w .= ' ' . $nwords[$r]; + } + } + elseif($x < 1000) // 100 to 999 + { + $w .= $nwords[floor($x/100)] .' hundred'; + $r = fmod($x, 100); + if($r > 0) + { + $w .= ' and '. self::number($r); + } + } + elseif($x < 1000000) // 1000 to 999999 + { + $w .= self::number(floor($x/1000)) .' thousand'; + $r = fmod($x, 1000); + if($r > 0) + { + $w .= ' '; + if($r < 100) + { + $w .= 'and '; + } + $w .= self::number($r); + } + } + else // millions + { + $w .= self::number(floor($x/1000000)) .' million'; + $r = fmod($x, 1000000); + if($r > 0) + { + $w .= ' '; + if($r < 100) + { + $w .= 'and '; + } + $w .= self::number($r); + } + } + } + return $w; + } + + /** + * Random Key + * + * @input int $size The size of the random string + * + * @returns a string + * @since 3.0.9 + */ + public static function random(int $size): string + { + $bag = "abcefghijknopqrstuwxyzABCDDEFGHIJKLLMMNOPQRSTUVVWXYZabcddefghijkllmmnopqrstuvvwxyzABCEFGHIJKNOPQRSTUWXYZ"; + $key = []; + $bagsize = strlen($bag) - 1; + + for ($i = 0; $i < $size; $i++) + { + $get = rand(0, $bagsize); + $key[] = $bag[$get]; + } + + return implode($key); + } + +} + diff --git a/libraries/jcb_powers/htaccess.txt b/libraries/jcb_powers/htaccess.txt new file mode 100644 index 0000000..9afb1a1 --- /dev/null +++ b/libraries/jcb_powers/htaccess.txt @@ -0,0 +1,9 @@ +# Apache 2.4+ + + Require all denied + + +# Apache 2.0-2.2 + + Deny from all + diff --git a/libraries/jcb_powers/index.html b/libraries/jcb_powers/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/libraries/jcb_powers/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/jcb_powers/web.config b/libraries/jcb_powers/web.config new file mode 100644 index 0000000..47b6d6d --- /dev/null +++ b/libraries/jcb_powers/web.config @@ -0,0 +1,7 @@ + + + + + + + diff --git a/media/css/index.html b/media/css/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/media/css/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/media/datatable/css/datatables.min.css b/media/datatable/css/datatables.min.css new file mode 100644 index 0000000..5c9d00a --- /dev/null +++ b/media/datatable/css/datatables.min.css @@ -0,0 +1,57 @@ +/* + * This combined file was created by the DataTables downloader builder: + * https://datatables.net/download + * + * To rebuild or modify this file with the latest versions of the included + * software please visit: + * https://datatables.net/download/#dt/jszip-2.5.0/dt-1.11.5/b-2.2.2/b-colvis-2.2.2/b-html5-2.2.2/b-print-2.2.2/cr-1.5.5/date-1.1.2/fc-4.0.2/fh-3.2.2/kt-2.6.4/r-2.2.9/rg-1.1.4/rr-1.2.8/sc-2.0.5/sb-1.3.2/sp-2.0.0/sl-1.3.4/sr-1.1.0 + * + * Included libraries: + * JSZip 2.5.0, DataTables 1.11.5, Buttons 2.2.2, Column visibility 2.2.2, HTML5 export 2.2.2, Print view 2.2.2, ColReorder 1.5.5, DateTime 1.1.2, FixedColumns 4.0.2, FixedHeader 3.2.2, KeyTable 2.6.4, Responsive 2.2.9, RowGroup 1.1.4, RowReorder 1.2.8, Scroller 2.0.5, SearchBuilder 1.3.2, SearchPanes 2.0.0, Select 1.3.4, StateRestore 1.1.0 + */ + +table.dataTable th.dt-left,table.dataTable td.dt-left{text-align:left}table.dataTable th.dt-center,table.dataTable td.dt-center,table.dataTable td.dataTables_empty{text-align:center}table.dataTable th.dt-right,table.dataTable td.dt-right{text-align:right}table.dataTable th.dt-justify,table.dataTable td.dt-justify{text-align:justify}table.dataTable th.dt-nowrap,table.dataTable td.dt-nowrap{white-space:nowrap}table.dataTable thead th.dt-head-left,table.dataTable thead td.dt-head-left,table.dataTable tfoot th.dt-head-left,table.dataTable tfoot td.dt-head-left{text-align:left}table.dataTable thead th.dt-head-center,table.dataTable thead td.dt-head-center,table.dataTable tfoot th.dt-head-center,table.dataTable tfoot td.dt-head-center{text-align:center}table.dataTable thead th.dt-head-right,table.dataTable thead td.dt-head-right,table.dataTable tfoot th.dt-head-right,table.dataTable tfoot td.dt-head-right{text-align:right}table.dataTable thead th.dt-head-justify,table.dataTable thead td.dt-head-justify,table.dataTable tfoot th.dt-head-justify,table.dataTable tfoot td.dt-head-justify{text-align:justify}table.dataTable thead th.dt-head-nowrap,table.dataTable thead td.dt-head-nowrap,table.dataTable tfoot th.dt-head-nowrap,table.dataTable tfoot td.dt-head-nowrap{white-space:nowrap}table.dataTable tbody th.dt-body-left,table.dataTable tbody td.dt-body-left{text-align:left}table.dataTable tbody th.dt-body-center,table.dataTable tbody td.dt-body-center{text-align:center}table.dataTable tbody th.dt-body-right,table.dataTable tbody td.dt-body-right{text-align:right}table.dataTable tbody th.dt-body-justify,table.dataTable tbody td.dt-body-justify{text-align:justify}table.dataTable tbody th.dt-body-nowrap,table.dataTable tbody td.dt-body-nowrap{white-space:nowrap}table.dataTable td.dt-control{text-align:center;cursor:pointer}table.dataTable td.dt-control:before{height:1em;width:1em;margin-top:-9px;display:inline-block;color:white;border:.15em solid white;border-radius:1em;box-shadow:0 0 .2em #444;box-sizing:content-box;text-align:center;text-indent:0 !important;font-family:"Courier New",Courier,monospace;line-height:1em;content:"+";background-color:#31b131}table.dataTable tr.dt-hasChild td.dt-control:before{content:"-";background-color:#d33333}table.dataTable{width:100%;margin:0 auto;clear:both;border-collapse:separate;border-spacing:0}table.dataTable thead th,table.dataTable tfoot th{font-weight:bold}table.dataTable thead th,table.dataTable thead td{padding:10px 18px;border-bottom:1px solid #111}table.dataTable thead th:active,table.dataTable thead td:active{outline:none}table.dataTable tfoot th,table.dataTable tfoot td{padding:10px 18px 6px 18px;border-top:1px solid #111}table.dataTable thead .sorting,table.dataTable thead .sorting_asc,table.dataTable thead .sorting_desc,table.dataTable thead .sorting_asc_disabled,table.dataTable thead .sorting_desc_disabled{cursor:pointer;*cursor:hand;background-repeat:no-repeat;background-position:center right}table.dataTable thead .sorting{background-image:url("/DataTables-1.11.5/images/sort_both.png")}table.dataTable thead .sorting_asc{background-image:url("/DataTables-1.11.5/images/sort_asc.png") !important}table.dataTable thead .sorting_desc{background-image:url("/DataTables-1.11.5/images/sort_desc.png") !important}table.dataTable thead .sorting_asc_disabled{background-image:url("/DataTables-1.11.5/images/sort_asc_disabled.png")}table.dataTable thead .sorting_desc_disabled{background-image:url("/DataTables-1.11.5/images/sort_desc_disabled.png")}table.dataTable tbody tr{background-color:#fff}table.dataTable tbody tr.selected{background-color:#b0bed9}table.dataTable tbody th,table.dataTable tbody td{padding:8px 10px}table.dataTable.row-border tbody th,table.dataTable.row-border tbody td,table.dataTable.display tbody th,table.dataTable.display tbody td{border-top:1px solid #ddd}table.dataTable.row-border tbody tr:first-child th,table.dataTable.row-border tbody tr:first-child td,table.dataTable.display tbody tr:first-child th,table.dataTable.display tbody tr:first-child td{border-top:none}table.dataTable.cell-border tbody th,table.dataTable.cell-border tbody td{border-top:1px solid #ddd;border-right:1px solid #ddd}table.dataTable.cell-border tbody tr th:first-child,table.dataTable.cell-border tbody tr td:first-child{border-left:1px solid #ddd}table.dataTable.cell-border tbody tr:first-child th,table.dataTable.cell-border tbody tr:first-child td{border-top:none}table.dataTable.stripe tbody tr.odd,table.dataTable.display tbody tr.odd{background-color:#f9f9f9}table.dataTable.stripe tbody tr.odd.selected,table.dataTable.display tbody tr.odd.selected{background-color:#acbad4}table.dataTable.hover tbody tr:hover,table.dataTable.display tbody tr:hover{background-color:#f6f6f6}table.dataTable.hover tbody tr:hover.selected,table.dataTable.display tbody tr:hover.selected{background-color:#aab7d1}table.dataTable.order-column tbody tr>.sorting_1,table.dataTable.order-column tbody tr>.sorting_2,table.dataTable.order-column tbody tr>.sorting_3,table.dataTable.display tbody tr>.sorting_1,table.dataTable.display tbody tr>.sorting_2,table.dataTable.display tbody tr>.sorting_3{background-color:#fafafa}table.dataTable.order-column tbody tr.selected>.sorting_1,table.dataTable.order-column tbody tr.selected>.sorting_2,table.dataTable.order-column tbody tr.selected>.sorting_3,table.dataTable.display tbody tr.selected>.sorting_1,table.dataTable.display tbody tr.selected>.sorting_2,table.dataTable.display tbody tr.selected>.sorting_3{background-color:#acbad5}table.dataTable.display tbody tr.odd>.sorting_1,table.dataTable.order-column.stripe tbody tr.odd>.sorting_1{background-color:#f1f1f1}table.dataTable.display tbody tr.odd>.sorting_2,table.dataTable.order-column.stripe tbody tr.odd>.sorting_2{background-color:#f3f3f3}table.dataTable.display tbody tr.odd>.sorting_3,table.dataTable.order-column.stripe tbody tr.odd>.sorting_3{background-color:whitesmoke}table.dataTable.display tbody tr.odd.selected>.sorting_1,table.dataTable.order-column.stripe tbody tr.odd.selected>.sorting_1{background-color:#a6b4cd}table.dataTable.display tbody tr.odd.selected>.sorting_2,table.dataTable.order-column.stripe tbody tr.odd.selected>.sorting_2{background-color:#a8b5cf}table.dataTable.display tbody tr.odd.selected>.sorting_3,table.dataTable.order-column.stripe tbody tr.odd.selected>.sorting_3{background-color:#a9b7d1}table.dataTable.display tbody tr.even>.sorting_1,table.dataTable.order-column.stripe tbody tr.even>.sorting_1{background-color:#fafafa}table.dataTable.display tbody tr.even>.sorting_2,table.dataTable.order-column.stripe tbody tr.even>.sorting_2{background-color:#fcfcfc}table.dataTable.display tbody tr.even>.sorting_3,table.dataTable.order-column.stripe tbody tr.even>.sorting_3{background-color:#fefefe}table.dataTable.display tbody tr.even.selected>.sorting_1,table.dataTable.order-column.stripe tbody tr.even.selected>.sorting_1{background-color:#acbad5}table.dataTable.display tbody tr.even.selected>.sorting_2,table.dataTable.order-column.stripe tbody tr.even.selected>.sorting_2{background-color:#aebcd6}table.dataTable.display tbody tr.even.selected>.sorting_3,table.dataTable.order-column.stripe tbody tr.even.selected>.sorting_3{background-color:#afbdd8}table.dataTable.display tbody tr:hover>.sorting_1,table.dataTable.order-column.hover tbody tr:hover>.sorting_1{background-color:#eaeaea}table.dataTable.display tbody tr:hover>.sorting_2,table.dataTable.order-column.hover tbody tr:hover>.sorting_2{background-color:#ececec}table.dataTable.display tbody tr:hover>.sorting_3,table.dataTable.order-column.hover tbody tr:hover>.sorting_3{background-color:#efefef}table.dataTable.display tbody tr:hover.selected>.sorting_1,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_1{background-color:#a2aec7}table.dataTable.display tbody tr:hover.selected>.sorting_2,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_2{background-color:#a3b0c9}table.dataTable.display tbody tr:hover.selected>.sorting_3,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_3{background-color:#a5b2cb}table.dataTable.no-footer{border-bottom:1px solid #111}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}table.dataTable.compact thead th,table.dataTable.compact thead td{padding:4px 17px}table.dataTable.compact tfoot th,table.dataTable.compact tfoot td{padding:4px}table.dataTable.compact tbody th,table.dataTable.compact tbody td{padding:4px}table.dataTable th,table.dataTable td{box-sizing:content-box}.dataTables_wrapper{position:relative;clear:both}.dataTables_wrapper .dataTables_length{float:left}.dataTables_wrapper .dataTables_length select{border:1px solid #aaa;border-radius:3px;padding:5px;background-color:transparent;padding:4px}.dataTables_wrapper .dataTables_filter{float:right;text-align:right}.dataTables_wrapper .dataTables_filter input{border:1px solid #aaa;border-radius:3px;padding:5px;background-color:transparent;margin-left:3px}.dataTables_wrapper .dataTables_info{clear:both;float:left;padding-top:.755em}.dataTables_wrapper .dataTables_paginate{float:right;text-align:right;padding-top:.25em}.dataTables_wrapper .dataTables_paginate .paginate_button{box-sizing:border-box;display:inline-block;min-width:1.5em;padding:.5em 1em;margin-left:2px;text-align:center;text-decoration:none !important;cursor:pointer;*cursor:hand;color:#333 !important;border:1px solid transparent;border-radius:2px}.dataTables_wrapper .dataTables_paginate .paginate_button.current,.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover{color:#333 !important;border:1px solid #979797;background-color:white;background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, white), color-stop(100%, #dcdcdc));background:-webkit-linear-gradient(top, white 0%, #dcdcdc 100%);background:-moz-linear-gradient(top, white 0%, #dcdcdc 100%);background:-ms-linear-gradient(top, white 0%, #dcdcdc 100%);background:-o-linear-gradient(top, white 0%, #dcdcdc 100%);background:linear-gradient(to bottom, white 0%, #dcdcdc 100%)}.dataTables_wrapper .dataTables_paginate .paginate_button.disabled,.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover,.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active{cursor:default;color:#666 !important;border:1px solid transparent;background:transparent;box-shadow:none}.dataTables_wrapper .dataTables_paginate .paginate_button:hover{color:white !important;border:1px solid #111;background-color:#585858;background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111));background:-webkit-linear-gradient(top, #585858 0%, #111 100%);background:-moz-linear-gradient(top, #585858 0%, #111 100%);background:-ms-linear-gradient(top, #585858 0%, #111 100%);background:-o-linear-gradient(top, #585858 0%, #111 100%);background:linear-gradient(to bottom, #585858 0%, #111 100%)}.dataTables_wrapper .dataTables_paginate .paginate_button:active{outline:none;background-color:#2b2b2b;background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #2b2b2b), color-stop(100%, #0c0c0c));background:-webkit-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-moz-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-ms-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-o-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:linear-gradient(to bottom, #2b2b2b 0%, #0c0c0c 100%);box-shadow:inset 0 0 3px #111}.dataTables_wrapper .dataTables_paginate .ellipsis{padding:0 1em}.dataTables_wrapper .dataTables_processing{position:absolute;top:50%;left:50%;width:100%;height:40px;margin-left:-50%;margin-top:-25px;padding-top:20px;text-align:center;font-size:1.2em;background-color:white;background:-webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(25%, rgba(255, 255, 255, 0.9)), color-stop(75%, rgba(255, 255, 255, 0.9)), color-stop(100%, rgba(255, 255, 255, 0)));background:-webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);background:-moz-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);background:-ms-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);background:-o-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);background:linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%)}.dataTables_wrapper .dataTables_length,.dataTables_wrapper .dataTables_filter,.dataTables_wrapper .dataTables_info,.dataTables_wrapper .dataTables_processing,.dataTables_wrapper .dataTables_paginate{color:#333}.dataTables_wrapper .dataTables_scroll{clear:both}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody{*margin-top:-1px;-webkit-overflow-scrolling:touch}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>th,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>td,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>th,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>td{vertical-align:middle}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>th>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>td>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>th>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>td>div.dataTables_sizing{height:0;overflow:hidden;margin:0 !important;padding:0 !important}.dataTables_wrapper.no-footer .dataTables_scrollBody{border-bottom:1px solid #111}.dataTables_wrapper.no-footer div.dataTables_scrollHead table.dataTable,.dataTables_wrapper.no-footer div.dataTables_scrollBody>table{border-bottom:none}.dataTables_wrapper:after{visibility:hidden;display:block;content:"";clear:both;height:0}@media screen and (max-width: 767px){.dataTables_wrapper .dataTables_info,.dataTables_wrapper .dataTables_paginate{float:none;text-align:center}.dataTables_wrapper .dataTables_paginate{margin-top:.5em}}@media screen and (max-width: 640px){.dataTables_wrapper .dataTables_length,.dataTables_wrapper .dataTables_filter{float:none;text-align:center}.dataTables_wrapper .dataTables_filter{margin-top:.5em}} + + +@keyframes dtb-spinner{100%{transform:rotate(360deg)}}@-o-keyframes dtb-spinner{100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@-ms-keyframes dtb-spinner{100%{-ms-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes dtb-spinner{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes dtb-spinner{100%{-moz-transform:rotate(360deg);transform:rotate(360deg)}}div.dataTables_wrapper{position:relative}div.dt-buttons{position:initial}div.dt-button-info{position:fixed;top:50%;left:50%;width:400px;margin-top:-100px;margin-left:-200px;background-color:white;border:2px solid #111;box-shadow:3px 4px 10px 1px rgba(0, 0, 0, 0.3);border-radius:3px;text-align:center;z-index:21}div.dt-button-info h2{padding:.5em;margin:0;font-weight:normal;border-bottom:1px solid #ddd;background-color:#f3f3f3}div.dt-button-info>div{padding:1em}div.dtb-popover-close{position:absolute;top:10px;right:10px;width:22px;height:22px;border:1px solid #eaeaea;background-color:#f9f9f9;text-align:center;border-radius:3px;cursor:pointer;z-index:12}button.dtb-hide-drop{display:none !important}div.dt-button-collection-title{text-align:center;padding:.3em 0 .5em;margin-left:.5em;margin-right:.5em;font-size:.9em}div.dt-button-collection-title:empty{display:none}span.dt-button-spacer{display:inline-block;margin:.5em;white-space:nowrap}span.dt-button-spacer.bar{border-left:1px solid rgba(0, 0, 0, 0.3);vertical-align:middle;padding-left:.5em}span.dt-button-spacer.bar:empty{height:1em;width:1px;padding-left:0}div.dt-button-collection span.dt-button-spacer{width:100%;font-size:.9em;text-align:center;margin:.5em 0}div.dt-button-collection span.dt-button-spacer:empty{height:0;width:100%}div.dt-button-collection span.dt-button-spacer.bar{border-left:none;border-bottom:1px solid rgba(0, 0, 0, 0.3);padding-left:0}button.dt-button,div.dt-button,a.dt-button,input.dt-button{position:relative;display:inline-block;box-sizing:border-box;margin-left:.167em;margin-right:.167em;margin-bottom:.333em;padding:.5em 1em;border:1px solid rgba(0, 0, 0, 0.3);border-radius:2px;cursor:pointer;font-size:.88em;line-height:1.6em;color:black;white-space:nowrap;overflow:hidden;background-color:rgba(0, 0, 0, 0.1);background:-webkit-linear-gradient(top, rgba(230, 230, 230, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:-moz-linear-gradient(top, rgba(230, 230, 230, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:-ms-linear-gradient(top, rgba(230, 230, 230, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:-o-linear-gradient(top, rgba(230, 230, 230, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:linear-gradient(to bottom, rgba(230, 230, 230, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr="rgba(230, 230, 230, 0.1)", EndColorStr="rgba(0, 0, 0, 0.1)");-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-decoration:none;outline:none;text-overflow:ellipsis}button.dt-button:first-child,div.dt-button:first-child,a.dt-button:first-child,input.dt-button:first-child{margin-left:0}button.dt-button.disabled,div.dt-button.disabled,a.dt-button.disabled,input.dt-button.disabled{cursor:default;opacity:.4}button.dt-button:active:not(.disabled),button.dt-button.active:not(.disabled),div.dt-button:active:not(.disabled),div.dt-button.active:not(.disabled),a.dt-button:active:not(.disabled),a.dt-button.active:not(.disabled),input.dt-button:active:not(.disabled),input.dt-button.active:not(.disabled){background-color:rgba(0, 0, 0, 0.1);background:-webkit-linear-gradient(top, rgba(179, 179, 179, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:-moz-linear-gradient(top, rgba(179, 179, 179, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:-ms-linear-gradient(top, rgba(179, 179, 179, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:-o-linear-gradient(top, rgba(179, 179, 179, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:linear-gradient(to bottom, rgba(179, 179, 179, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr="rgba(179, 179, 179, 0.1)", EndColorStr="rgba(0, 0, 0, 0.1)");box-shadow:inset 1px 1px 3px #999}button.dt-button:active:not(.disabled):hover:not(.disabled),button.dt-button.active:not(.disabled):hover:not(.disabled),div.dt-button:active:not(.disabled):hover:not(.disabled),div.dt-button.active:not(.disabled):hover:not(.disabled),a.dt-button:active:not(.disabled):hover:not(.disabled),a.dt-button.active:not(.disabled):hover:not(.disabled),input.dt-button:active:not(.disabled):hover:not(.disabled),input.dt-button.active:not(.disabled):hover:not(.disabled){box-shadow:inset 1px 1px 3px #999;background-color:rgba(0, 0, 0, 0.1);background:-webkit-linear-gradient(top, rgba(128, 128, 128, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:-moz-linear-gradient(top, rgba(128, 128, 128, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:-ms-linear-gradient(top, rgba(128, 128, 128, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:-o-linear-gradient(top, rgba(128, 128, 128, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:linear-gradient(to bottom, rgba(128, 128, 128, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr="rgba(128, 128, 128, 0.1)", EndColorStr="rgba(0, 0, 0, 0.1)")}button.dt-button:hover,div.dt-button:hover,a.dt-button:hover,input.dt-button:hover{text-decoration:none}button.dt-button:hover:not(.disabled),div.dt-button:hover:not(.disabled),a.dt-button:hover:not(.disabled),input.dt-button:hover:not(.disabled){border:1px solid #666;background-color:rgba(0, 0, 0, 0.1);background:-webkit-linear-gradient(top, rgba(153, 153, 153, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:-moz-linear-gradient(top, rgba(153, 153, 153, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:-ms-linear-gradient(top, rgba(153, 153, 153, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:-o-linear-gradient(top, rgba(153, 153, 153, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:linear-gradient(to bottom, rgba(153, 153, 153, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr="rgba(153, 153, 153, 0.1)", EndColorStr="rgba(0, 0, 0, 0.1)")}button.dt-button:focus:not(.disabled),div.dt-button:focus:not(.disabled),a.dt-button:focus:not(.disabled),input.dt-button:focus:not(.disabled){border:1px solid #426c9e;text-shadow:0 1px 0 #c4def1;outline:none;background-color:#79ace9;background:-webkit-linear-gradient(top, #d1e2f7 0%, #79ace9 100%);background:-moz-linear-gradient(top, #d1e2f7 0%, #79ace9 100%);background:-ms-linear-gradient(top, #d1e2f7 0%, #79ace9 100%);background:-o-linear-gradient(top, #d1e2f7 0%, #79ace9 100%);background:linear-gradient(to bottom, #d1e2f7 0%, #79ace9 100%);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr="#d1e2f7", EndColorStr="#79ace9")}button.dt-button span.dt-down-arrow,div.dt-button span.dt-down-arrow,a.dt-button span.dt-down-arrow,input.dt-button span.dt-down-arrow{position:relative;top:-2px;color:rgba(70, 70, 70, 0.75);font-size:8px;padding-left:10px;line-height:1em}.dt-button embed{outline:none}div.dt-buttons{float:left}div.dt-buttons.buttons-right{float:right}div.dataTables_layout_cell div.dt-buttons{float:none}div.dataTables_layout_cell div.dt-buttons.buttons-right{float:none}div.dt-btn-split-wrapper{display:inline-block}div.dt-button-collection{position:absolute;top:0;left:0;width:200px;margin-top:3px;margin-bottom:3px;padding:4px 4px 2px 4px;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.4);background-color:white;overflow:hidden;z-index:2002;border-radius:5px;box-shadow:3px 4px 10px 1px rgba(0, 0, 0, 0.3);box-sizing:border-box}div.dt-button-collection button.dt-button,div.dt-button-collection div.dt-button,div.dt-button-collection a.dt-button{position:relative;left:0;right:0;width:100%;display:block;float:none;margin:4px 0 2px 0}div.dt-button-collection button.dt-button:active:not(.disabled),div.dt-button-collection button.dt-button.active:not(.disabled),div.dt-button-collection div.dt-button:active:not(.disabled),div.dt-button-collection div.dt-button.active:not(.disabled),div.dt-button-collection a.dt-button:active:not(.disabled),div.dt-button-collection a.dt-button.active:not(.disabled){background-color:#dadada;background:-webkit-linear-gradient(top, #f0f0f0 0%, #dadada 100%);background:-moz-linear-gradient(top, #f0f0f0 0%, #dadada 100%);background:-ms-linear-gradient(top, #f0f0f0 0%, #dadada 100%);background:-o-linear-gradient(top, #f0f0f0 0%, #dadada 100%);background:linear-gradient(to bottom, #f0f0f0 0%, #dadada 100%);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr="#f0f0f0", EndColorStr="#dadada");box-shadow:inset 1px 1px 3px #666}div.dt-button-collection button.dt-button:first-child,div.dt-button-collection div.dt-button:first-child,div.dt-button-collection a.dt-button:first-child{margin-top:0;border-top-left-radius:3px;border-top-right-radius:3px}div.dt-button-collection button.dt-button:last-child,div.dt-button-collection div.dt-button:last-child,div.dt-button-collection a.dt-button:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}div.dt-button-collection div.dt-btn-split-wrapper{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-start;align-content:flex-start;align-items:stretch;margin:4px 0 2px 0}div.dt-button-collection div.dt-btn-split-wrapper button.dt-button{margin:0;display:inline-block;width:0;flex-grow:1;flex-shrink:0;flex-basis:50px;border-radius:0}div.dt-button-collection div.dt-btn-split-wrapper button.dt-btn-split-drop{min-width:20px;flex-grow:0;flex-shrink:0;flex-basis:0}div.dt-button-collection div.dt-btn-split-wrapper:first-child{margin-top:0}div.dt-button-collection div.dt-btn-split-wrapper:first-child button.dt-button{border-top-left-radius:3px}div.dt-button-collection div.dt-btn-split-wrapper:first-child button.dt-btn-split-drop{border-top-right-radius:3px}div.dt-button-collection div.dt-btn-split-wrapper:last-child button.dt-button{border-bottom-left-radius:3px}div.dt-button-collection div.dt-btn-split-wrapper:last-child button.dt-btn-split-drop{border-bottom-right-radius:3px}div.dt-button-collection div.dt-btn-split-wrapper:active:not(.disabled) button.dt-button,div.dt-button-collection div.dt-btn-split-wrapper.active:not(.disabled) button.dt-button{background-color:#dadada;background:-webkit-linear-gradient(top, #f0f0f0 0%, #dadada 100%);background:-moz-linear-gradient(top, #f0f0f0 0%, #dadada 100%);background:-ms-linear-gradient(top, #f0f0f0 0%, #dadada 100%);background:-o-linear-gradient(top, #f0f0f0 0%, #dadada 100%);background:linear-gradient(to bottom, #f0f0f0 0%, #dadada 100%);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr="#f0f0f0", EndColorStr="#dadada");box-shadow:inset 0px 0px 4px #666}div.dt-button-collection div.dt-btn-split-wrapper:active:not(.disabled) button.dt-btn-split-drop,div.dt-button-collection div.dt-btn-split-wrapper.active:not(.disabled) button.dt-btn-split-drop{box-shadow:none}div.dt-button-collection.fixed .dt-button:first-child{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}div.dt-button-collection.fixed .dt-button:last-child{border-bottom-left-radius:0;border-bottom-right-radius:0}div.dt-button-collection.fixed{position:fixed;display:block;top:50%;left:50%;margin-left:-75px;border-radius:5px;background-color:white}div.dt-button-collection.fixed.two-column{margin-left:-200px}div.dt-button-collection.fixed.three-column{margin-left:-225px}div.dt-button-collection.fixed.four-column{margin-left:-300px}div.dt-button-collection.fixed.columns{margin-left:-409px}@media screen and (max-width: 1024px){div.dt-button-collection.fixed.columns{margin-left:-308px}}@media screen and (max-width: 640px){div.dt-button-collection.fixed.columns{margin-left:-203px}}@media screen and (max-width: 460px){div.dt-button-collection.fixed.columns{margin-left:-100px}}div.dt-button-collection.fixed>:last-child{max-height:100vh;overflow:auto}div.dt-button-collection.two-column>:last-child,div.dt-button-collection.three-column>:last-child,div.dt-button-collection.four-column>:last-child{display:block !important;-webkit-column-gap:8px;-moz-column-gap:8px;-ms-column-gap:8px;-o-column-gap:8px;column-gap:8px}div.dt-button-collection.two-column>:last-child>*,div.dt-button-collection.three-column>:last-child>*,div.dt-button-collection.four-column>:last-child>*{-webkit-column-break-inside:avoid;break-inside:avoid}div.dt-button-collection.two-column{width:400px}div.dt-button-collection.two-column>:last-child{padding-bottom:1px;column-count:2}div.dt-button-collection.three-column{width:450px}div.dt-button-collection.three-column>:last-child{padding-bottom:1px;column-count:3}div.dt-button-collection.four-column{width:600px}div.dt-button-collection.four-column>:last-child{padding-bottom:1px;column-count:4}div.dt-button-collection .dt-button{border-radius:0}div.dt-button-collection.columns{width:auto}div.dt-button-collection.columns>:last-child{display:flex;flex-wrap:wrap;justify-content:flex-start;align-items:center;gap:6px;width:818px;padding-bottom:1px}div.dt-button-collection.columns>:last-child .dt-button{min-width:200px;flex:0 1;margin:0}div.dt-button-collection.columns.dtb-b3>:last-child,div.dt-button-collection.columns.dtb-b2>:last-child,div.dt-button-collection.columns.dtb-b1>:last-child{justify-content:space-between}div.dt-button-collection.columns.dtb-b3 .dt-button{flex:1 1 32%}div.dt-button-collection.columns.dtb-b2 .dt-button{flex:1 1 48%}div.dt-button-collection.columns.dtb-b1 .dt-button{flex:1 1 100%}@media screen and (max-width: 1024px){div.dt-button-collection.columns>:last-child{width:612px}}@media screen and (max-width: 640px){div.dt-button-collection.columns>:last-child{width:406px}div.dt-button-collection.columns.dtb-b3 .dt-button{flex:0 1 32%}}@media screen and (max-width: 460px){div.dt-button-collection.columns>:last-child{width:200px}}div.dt-button-background{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0, 0, 0, 0.7);background:-ms-radial-gradient(center, ellipse farthest-corner, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);background:-moz-radial-gradient(center, ellipse farthest-corner, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);background:-o-radial-gradient(center, ellipse farthest-corner, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);background:-webkit-gradient(radial, center center, 0, center center, 497, color-stop(0, rgba(0, 0, 0, 0.3)), color-stop(1, rgba(0, 0, 0, 0.7)));background:-webkit-radial-gradient(center, ellipse farthest-corner, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);background:radial-gradient(ellipse farthest-corner at center, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);z-index:2001}@media screen and (max-width: 640px){div.dt-buttons{float:none !important;text-align:center}}button.dt-button.processing,div.dt-button.processing,a.dt-button.processing{color:rgba(0, 0, 0, 0.2)}button.dt-button.processing:after,div.dt-button.processing:after,a.dt-button.processing:after{position:absolute;top:50%;left:50%;width:16px;height:16px;margin:-8px 0 0 -8px;box-sizing:border-box;display:block;content:" ";border:2px solid #282828;border-radius:50%;border-left-color:transparent;border-right-color:transparent;animation:dtb-spinner 1500ms infinite linear;-o-animation:dtb-spinner 1500ms infinite linear;-ms-animation:dtb-spinner 1500ms infinite linear;-webkit-animation:dtb-spinner 1500ms infinite linear;-moz-animation:dtb-spinner 1500ms infinite linear}button.dt-btn-split-drop{margin-left:calc(-1px - .333em);padding-bottom:calc(.5em - 1px);border-radius:0px 1px 1px 0px;color:rgba(70, 70, 70, 0.9);border-left:none}button.dt-btn-split-drop span.dt-btn-split-drop-arrow{position:relative;top:-1px;left:-2px;font-size:8px}button.dt-btn-split-drop:hover{z-index:2}button.buttons-split{border-right:1px solid rgba(70, 70, 70, 0);border-radius:1px 0px 0px 1px}button.dt-btn-split-drop-button{background-color:white}button.dt-btn-split-drop-button:hover{background-color:white} + + +table.DTCR_clonedTable.dataTable{position:absolute !important;background-color:rgba(255, 255, 255, 0.7);z-index:202}div.DTCR_pointer{width:1px;background-color:#0259c4;z-index:201} + + +div.dt-datetime{position:absolute;background-color:white;z-index:2050;border:1px solid #ccc;box-shadow:0 5px 15px -5px rgba(0, 0, 0, 0.5);padding:0 20px 6px 20px;width:275px}div.dt-datetime.inline{position:relative;box-shadow:none}div.dt-datetime div.dt-datetime-title{text-align:center;padding:5px 0px 3px}div.dt-datetime div.dt-datetime-buttons{text-align:center}div.dt-datetime div.dt-datetime-buttons a{display:inline-block;padding:0 .5em .5em .5em;margin:0;font-size:.9em}div.dt-datetime div.dt-datetime-buttons a:hover{text-decoration:underline}div.dt-datetime table{border-spacing:0;margin:12px 0;width:100%}div.dt-datetime table.dt-datetime-table-nospace{margin-top:-12px}div.dt-datetime table th{font-size:.8em;color:#777;font-weight:normal;width:14.285714286%;padding:0 0 4px 0;text-align:center}div.dt-datetime table td{font-size:.9em;color:#444;padding:0}div.dt-datetime table td.selectable{text-align:center;background:#f5f5f5}div.dt-datetime table td.selectable.disabled{color:#aaa;background:white}div.dt-datetime table td.selectable.disabled button:hover{color:#aaa;background:white}div.dt-datetime table td.selectable.now{background-color:#ddd}div.dt-datetime table td.selectable.now button{font-weight:bold}div.dt-datetime table td.selectable.selected button{background:#4e6ca3;color:white;border-radius:2px}div.dt-datetime table td.selectable button:hover{background:#ff8000;color:white;border-radius:2px}div.dt-datetime table td.dt-datetime-week{font-size:.7em}div.dt-datetime table button{width:100%;box-sizing:border-box;border:none;background:transparent;font-size:inherit;color:inherit;text-align:center;padding:4px 0;cursor:pointer;margin:0}div.dt-datetime table button span{display:inline-block;min-width:14px;text-align:right}div.dt-datetime table.weekNumber th{width:12.5%}div.dt-datetime div.dt-datetime-calendar table{margin-top:0}div.dt-datetime div.dt-datetime-label{position:relative;display:inline-block;height:30px;padding:5px 6px;border:1px solid transparent;box-sizing:border-box;cursor:pointer}div.dt-datetime div.dt-datetime-label:hover{border:1px solid #ddd;border-radius:2px;background-color:#f5f5f5}div.dt-datetime div.dt-datetime-label select{position:absolute;top:6px;left:0;cursor:pointer;opacity:0}div.dt-datetime.horizontal{width:550px}div.dt-datetime.horizontal div.dt-datetime-date,div.dt-datetime.horizontal div.dt-datetime-time{width:48%}div.dt-datetime.horizontal div.dt-datetime-time{margin-left:4%}div.dt-datetime div.dt-datetime-date{position:relative;float:left;width:100%}div.dt-datetime div.dt-datetime-time{position:relative;float:left;width:100%;text-align:center}div.dt-datetime div.dt-datetime-time>span{vertical-align:middle}div.dt-datetime div.dt-datetime-time th{text-align:left}div.dt-datetime div.dt-datetime-time div.dt-datetime-timeblock{display:inline-block;vertical-align:middle}div.dt-datetime div.dt-datetime-iconLeft,div.dt-datetime div.dt-datetime-iconRight,div.dt-datetime div.dt-datetime-iconUp,div.dt-datetime div.dt-datetime-iconDown{width:30px;height:30px;background-position:center;background-repeat:no-repeat;opacity:.3;overflow:hidden;box-sizing:border-box}div.dt-datetime div.dt-datetime-iconLeft:hover,div.dt-datetime div.dt-datetime-iconRight:hover,div.dt-datetime div.dt-datetime-iconUp:hover,div.dt-datetime div.dt-datetime-iconDown:hover{border:1px solid #ccc;border-radius:2px;background-color:#f0f0f0;opacity:.6}div.dt-datetime div.dt-datetime-iconLeft button,div.dt-datetime div.dt-datetime-iconRight button,div.dt-datetime div.dt-datetime-iconUp button,div.dt-datetime div.dt-datetime-iconDown button{border:none;background:transparent;text-indent:30px;height:100%;width:100%;cursor:pointer}div.dt-datetime div.dt-datetime-iconLeft{position:absolute;top:5px;left:5px;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAUklEQVR42u3VMQoAIBADQf8Pgj+OD9hG2CtONJB2ymQkKe0HbwAP0xucDiQWARITIDEBEnMgMQ8S8+AqBIl6kKgHiXqQqAeJepBo/z38J/U0uAHlaBkBl9I4GwAAAABJRU5ErkJggg==")}div.dt-datetime div.dt-datetime-iconRight{position:absolute;top:5px;right:5px;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAU0lEQVR42u3VOwoAMAgE0dwfAnNjU26bYkBCFGwfiL9VVWoO+BJ4Gf3gtsEKKoFBNTCoCAYVwaAiGNQGMUHMkjGbgjk2mIONuXo0nC8XnCf1JXgArVIZAQh5TKYAAAAASUVORK5CYII=")}div.dt-datetime div.dt-datetime-iconUp{height:20px;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAALCAMAAABf9c24AAAAFVBMVEX///99fX1+fn57e3t6enoAAAAAAAC73bqPAAAABnRSTlMAYmJkZt92bnysAAAAL0lEQVR4AWOgJmBhxCvLyopHnpmVjY2VCadeoCxIHrcsWJ4RlyxCHlMWCTBRJxwAjrIBDMWSiM0AAAAASUVORK5CYII=")}div.dt-datetime div.dt-datetime-iconDown{height:20px;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAALCAMAAABf9c24AAAAFVBMVEX///99fX1+fn57e3t6enoAAAAAAAC73bqPAAAABnRSTlMAYmJkZt92bnysAAAAMElEQVR4AWOgDmBiRQIsmPKMrGxQgJDFlEfIYpoPk8Utz8qM232MYFfhkQfKUg8AANefAQxecJ58AAAAAElFTkSuQmCC")}div.dt-datetime-error{clear:both;padding:0 1em;max-width:240px;font-size:11px;line-height:1.25em;text-align:center;color:#b11f1f} + + +table.dataTable.display tbody tr.DTFC_NoData{background-color:transparent}tr.even td{background-color:#fff}tr.odd td{background-color:#f9f9f9}tr.selected td{background-color:#a6b4cd}thead th{background-color:white}tfoot th{background-color:white}tr.dt-rowReorder-moving td.dtfc-fixed-left,tr.dt-rowReorder-moving td.dtfc-fixed-right{border-top:2px solid #555 !important;border-bottom:2px solid #555 !important}tr.dt-rowReorder-moving td.dtfc-fixed-left:first-child{border-left:2px solid #555 !important}tr.dt-rowReorder-moving td.dtfc-fixed-right:last-child{border-right:2px solid #555 !important} + + +table.fixedHeader-floating{background-color:white}table.fixedHeader-floating.no-footer{border-bottom-width:0}table.fixedHeader-locked{position:absolute !important;background-color:white}@media print{table.fixedHeader-floating{display:none}} + + +table.dataTable tbody th.focus,table.dataTable tbody td.focus{box-shadow:inset 0 0 1px 2px #36f}div.dtk-focus-alt table.dataTable tbody th.focus,div.dtk-focus-alt table.dataTable tbody td.focus{box-shadow:inset 0 0 1px 2px #ff8b33} + + +table.dataTable.dtr-inline.collapsed>tbody>tr>td.child,table.dataTable.dtr-inline.collapsed>tbody>tr>th.child,table.dataTable.dtr-inline.collapsed>tbody>tr>td.dataTables_empty{cursor:default !important}table.dataTable.dtr-inline.collapsed>tbody>tr>td.child:before,table.dataTable.dtr-inline.collapsed>tbody>tr>th.child:before,table.dataTable.dtr-inline.collapsed>tbody>tr>td.dataTables_empty:before{display:none !important}table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control,table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control{position:relative;padding-left:30px;cursor:pointer}table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before,table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before{top:50%;left:5px;height:1em;width:1em;margin-top:-9px;display:block;position:absolute;color:white;border:.15em solid white;border-radius:1em;box-shadow:0 0 .2em #444;box-sizing:content-box;text-align:center;text-indent:0 !important;font-family:"Courier New",Courier,monospace;line-height:1em;content:"+";background-color:#31b131}table.dataTable.dtr-inline.collapsed>tbody>tr.parent>td.dtr-control:before,table.dataTable.dtr-inline.collapsed>tbody>tr.parent>th.dtr-control:before{content:"-";background-color:#d33333}table.dataTable.dtr-inline.collapsed.compact>tbody>tr>td.dtr-control,table.dataTable.dtr-inline.collapsed.compact>tbody>tr>th.dtr-control{padding-left:27px}table.dataTable.dtr-inline.collapsed.compact>tbody>tr>td.dtr-control:before,table.dataTable.dtr-inline.collapsed.compact>tbody>tr>th.dtr-control:before{left:4px;height:14px;width:14px;border-radius:14px;line-height:14px;text-indent:3px}table.dataTable.dtr-column>tbody>tr>td.dtr-control,table.dataTable.dtr-column>tbody>tr>th.dtr-control,table.dataTable.dtr-column>tbody>tr>td.control,table.dataTable.dtr-column>tbody>tr>th.control{position:relative;cursor:pointer}table.dataTable.dtr-column>tbody>tr>td.dtr-control:before,table.dataTable.dtr-column>tbody>tr>th.dtr-control:before,table.dataTable.dtr-column>tbody>tr>td.control:before,table.dataTable.dtr-column>tbody>tr>th.control:before{top:50%;left:50%;height:.8em;width:.8em;margin-top:-0.5em;margin-left:-0.5em;display:block;position:absolute;color:white;border:.15em solid white;border-radius:1em;box-shadow:0 0 .2em #444;box-sizing:content-box;text-align:center;text-indent:0 !important;font-family:"Courier New",Courier,monospace;line-height:1em;content:"+";background-color:#31b131}table.dataTable.dtr-column>tbody>tr.parent td.dtr-control:before,table.dataTable.dtr-column>tbody>tr.parent th.dtr-control:before,table.dataTable.dtr-column>tbody>tr.parent td.control:before,table.dataTable.dtr-column>tbody>tr.parent th.control:before{content:"-";background-color:#d33333}table.dataTable>tbody>tr.child{padding:.5em 1em}table.dataTable>tbody>tr.child:hover{background:transparent !important}table.dataTable>tbody>tr.child ul.dtr-details{display:inline-block;list-style-type:none;margin:0;padding:0}table.dataTable>tbody>tr.child ul.dtr-details>li{border-bottom:1px solid #efefef;padding:.5em 0}table.dataTable>tbody>tr.child ul.dtr-details>li:first-child{padding-top:0}table.dataTable>tbody>tr.child ul.dtr-details>li:last-child{border-bottom:none}table.dataTable>tbody>tr.child span.dtr-title{display:inline-block;min-width:75px;font-weight:bold}div.dtr-modal{position:fixed;box-sizing:border-box;top:0;left:0;height:100%;width:100%;z-index:100;padding:10em 1em}div.dtr-modal div.dtr-modal-display{position:absolute;top:0;left:0;bottom:0;right:0;width:50%;height:50%;overflow:auto;margin:auto;z-index:102;overflow:auto;background-color:#f5f5f7;border:1px solid black;border-radius:.5em;box-shadow:0 12px 30px rgba(0, 0, 0, 0.6)}div.dtr-modal div.dtr-modal-content{position:relative;padding:1em}div.dtr-modal div.dtr-modal-close{position:absolute;top:6px;right:6px;width:22px;height:22px;border:1px solid #eaeaea;background-color:#f9f9f9;text-align:center;border-radius:3px;cursor:pointer;z-index:12}div.dtr-modal div.dtr-modal-close:hover{background-color:#eaeaea}div.dtr-modal div.dtr-modal-background{position:fixed;top:0;left:0;right:0;bottom:0;z-index:101;background:rgba(0, 0, 0, 0.6)}@media screen and (max-width: 767px){div.dtr-modal div.dtr-modal-display{width:95%}} + + +table.dataTable tr.dtrg-group td{background-color:#e0e0e0}table.dataTable tr.dtrg-group.dtrg-level-0 td{font-weight:bold}table.dataTable tr.dtrg-group.dtrg-level-1 td,table.dataTable tr.dtrg-group.dtrg-level-2 td,table.dataTable tr.dtrg-group.dtrg-level-3 td,table.dataTable tr.dtrg-group.dtrg-level-4 td,table.dataTable tr.dtrg-group.dtrg-level-5 td{background-color:#f0f0f0;padding-top:.25em;padding-bottom:.25em;padding-left:2em;font-size:.9em}table.dataTable tr.dtrg-group.dtrg-level-2 td{background-color:#f3f3f3;padding-left:2.5em}table.dataTable tr.dtrg-group.dtrg-level-3 td{background-color:#f3f3f3;padding-left:3em}table.dataTable tr.dtrg-group.dtrg-level-4 td{background-color:#f3f3f3;padding-left:3.5em}table.dataTable tr.dtrg-group.dtrg-level-5 td{background-color:#f3f3f3;padding-left:4em} + + +table.dt-rowReorder-float{position:absolute !important;opacity:.8;table-layout:fixed;outline:2px solid #888;outline-offset:-2px;z-index:2001}tr.dt-rowReorder-moving{outline:2px solid #555;outline-offset:-2px}body.dt-rowReorder-noOverflow{overflow-x:hidden}table.dataTable td.reorder{text-align:center;cursor:move} + + +div.dts{display:block !important}div.dts tbody th,div.dts tbody td{white-space:nowrap}div.dts div.dts_loading{z-index:1}div.dts div.dts_label{position:absolute;right:10px;background:rgba(0, 0, 0, 0.8);color:white;box-shadow:3px 3px 10px rgba(0, 0, 0, 0.5);text-align:right;border-radius:3px;padding:.4em;z-index:2;display:none}div.dts div.dataTables_scrollBody{background:repeating-linear-gradient(45deg, #edeeff, #edeeff 10px, white 10px, white 20px)}div.dts div.dataTables_scrollBody table{z-index:2}div.dts div.dataTables_paginate,div.dts div.dataTables_length{display:none} + + +div.dt-button-collection{overflow:visible !important;z-index:2002 !important}div.dt-button-collection div.dtsb-searchBuilder{width:99% !important;padding-left:10px !important;padding-right:10px !important}div.dt-button-collection.dtb-collection-closeable div.dtsb-titleRow{padding-right:40px}.dtsb-greyscale{border:1px solid #cecece !important}div.dtsb-logicContainer .dtsb-greyscale{border:none !important}div.dtsb-searchBuilder{justify-content:space-evenly;cursor:default;margin-bottom:1em;text-align:left}div.dtsb-searchBuilder button.dtsb-button,div.dtsb-searchBuilder select{font-size:1em}div.dtsb-searchBuilder div.dtsb-titleRow{justify-content:space-evenly;margin-bottom:.5em}div.dtsb-searchBuilder div.dtsb-titleRow div.dtsb-title{display:inline-block;padding-top:6px}div.dtsb-searchBuilder div.dtsb-titleRow div.dtsb-title:empty{display:inline}div.dtsb-searchBuilder div.dtsb-titleRow button.dtsb-clearAll{float:right;margin-bottom:.333em}div.dtsb-searchBuilder div.dtsb-vertical .dtsb-value,div.dtsb-searchBuilder div.dtsb-vertical .dtsb-data,div.dtsb-searchBuilder div.dtsb-vertical .dtsb-condition{display:block}div.dtsb-searchBuilder div.dtsb-group{position:relative;clear:both;margin-bottom:.8em}div.dtsb-searchBuilder div.dtsb-group button.dtsb-clearGroup{margin:2px;text-align:center;padding:0}div.dtsb-searchBuilder div.dtsb-group div.dtsb-logicContainer{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-o-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg);position:absolute;margin-top:.8em;margin-right:.8em}div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria{margin-bottom:.8em}div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria select.dtsb-dropDown,div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria input.dtsb-input{padding:.4em;margin-right:.8em;max-width:20em;background-color:rgba(200, 200, 200, 0.3)}div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria select.dtsb-dropDown option.dtsb-notItalic,div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria input.dtsb-input option.dtsb-notItalic{font-style:normal}div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria select.dtsb-italic{font-style:italic}div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria div.dtsb-buttonContainer{float:right;display:inline-block}div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria div.dtsb-buttonContainer button.dtsb-delete,div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria div.dtsb-buttonContainer button.dtsb-right,div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria div.dtsb-buttonContainer button.dtsb-left{margin-right:.8em}div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria div.dtsb-buttonContainer button.dtsb-delete:last-child,div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria div.dtsb-buttonContainer button.dtsb-right:last-child,div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria div.dtsb-buttonContainer button.dtsb-left:last-child{margin-right:0}div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria span.dtsp-joiner{margin-right:.8em}div.dtsb-searchBuilder button,div.dtsb-searchBuilder select,div.dtsb-searchBuilder input{background-color:#f9f9f9}div.dtsb-searchBuilder button.dtsb-button{position:relative;display:inline-block;box-sizing:border-box;padding:.5em 1em;border:1px solid rgba(0, 0, 0, 0.3);border-radius:2px;cursor:pointer;font-size:.88em;line-height:1.6em;color:black;white-space:nowrap;overflow:hidden;background-color:rgba(0, 0, 0, 0.1);background:linear-gradient(to bottom, rgba(230, 230, 230, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-decoration:none;outline:none;text-overflow:ellipsis}div.dtsb-searchBuilder button.dtsb-button:hover{background-color:#cecece !important;cursor:pointer}div.dtsb-searchBuilder div.dtsb-logicContainer{border:1px solid rgba(0, 0, 0, 0.3);background-color:rgba(0, 0, 0, 0.1);background:linear-gradient(to right, rgba(230, 230, 230, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%)}div.dtsb-searchBuilder div.dtsb-logicContainer button{border:1px solid transparent;background:transparent}div.dtsb-searchBuilder button.dtsb-clearGroup{min-width:2em;padding:0}div.dtsb-searchBuilder button.dtsb-iptbtn{min-width:100px;text-align:left}div.dtsb-searchBuilder div.dtsb-group div.dtsb-logicContainer{border:1px solid;border-color:#cecece;border-radius:3px;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-start;align-content:flex-start;align-items:flex-start}div.dtsb-searchBuilder div.dtsb-group div.dtsb-logicContainer button.dtsb-logic{border:none;border-radius:0px;flex-grow:1;flex-shrink:0;flex-basis:3em;margin:0px}div.dtsb-searchBuilder div.dtsb-group div.dtsb-logicContainer button.dtsb-clearGroup{border:none;border-radius:0px;width:2em;margin:0px}div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria select.dtsb-dropDown,div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria input.dtsb-input{border:1px solid;border-radius:3px}div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria select.dtsb-condition{border-color:#48b13c}div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria select.dtsb-data{border-color:#e70f00}div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria select.dtsb-value,div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria input.dtsb-value{border-color:#0069ba}div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria select.dtsb-condition option.dtsb-option,div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria select.dtsb-data option.dtsb-option,div.dtsb-searchBuilder div.dtsb-group div.dtsb-criteria select.dtsb-value option.dtsb-option{background-color:white} + + +div.dtsp-topRow{display:flex;flex-direction:row;flex-wrap:nowrap;border:2px solid rgba(0, 0, 0, 0);border-radius:3px;justify-content:space-around;align-content:flex-start;align-items:flex-start;min-height:37px}div.dtsp-topRow input.dtsp-search{text-overflow:ellipsis;min-width:50px;flex-basis:90px;max-width:none}div.dtsp-topRow input.dtsp-search::placeholder{color:black}div.dtsp-topRow div.dtsp-subRow1{display:flex;flex-direction:row;flex-wrap:nowrap;flex:1 1 auto}div.dtsp-topRow div.dtsp-subRow1 div.dtsp-searchCont{position:relative;width:100%}div.dtsp-topRow div.dtsp-subRow1 div.dtsp-searchCont input.dtsp-disabledButton{padding-top:10px;padding-bottom:10px;background-color:transparent}div.dtsp-topRow div.dtsp-subRow1 input{padding-right:2em;width:100% !important;box-sizing:border-box;font-size:1em}div.dtsp-topRow div.dtsp-subRow1 button.dtsp-searchIcon{position:absolute;top:0;right:0;bottom:0;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAABbmlDQ1BpY2MAACiRdZE7SwNBFIU/EyWikRRaiFhsoWKhEBREO42FTZAQFYza7G5eQhKX3QQJtoKNhWAh2vgq/AfaCrYKgqAIIhb+Al+NhPVOEkiQZJbZ+3FmzmXmDHjCGTPrtAYhm8vb0bmQthxb0Xzv+PHRxRSabjrWTCQSpun4eaRF1YdR1av5voajM55wTGhpF54wLTsvPC0c3sxbineFe8y0Hhc+ER6x5YDCt0o3KvymOFXhL8X2YnQWPKqnlqpjo47NtJ0VHhYeyGYKZvU86ib+RG5pQWqfzH4coswRQsOgwDoZ8oxKzUlmjX3Bsm+eDfGY8rcoYosjRVq8I6IWpGtCalL0hHwZiir3/3k6yfGxSnd/CNpeXfdzEHz7UNpz3d9T1y2dgfcFrnM1/4bkNPkt+l5NGziGwDZc3tQ04wCudqD32dJtvSx5ZXqSSfi4gK4YdN9Dx2olq+o650+wuCVPdAeHRzAk+wNrfw8JaBFXEnV+AAAACXBIWXMAAA9hAAAPYQGoP6dpAAABMUlEQVQoU6XRr0vDQRjH8akoM4iIjqGoOIZ5oIjB5XWxajaYDGLSIhhNYjcPRDSJwbQNw+L+BNGgYYo/5pT5/shz8vDlBgMPXux7z3N3z+25VOofYyCyd4ZYCavI4gXPsRp9LqiDdrEMH+8wv8Vh8gBfWclFPOEUN3hAHjlMoRa7wTzBS5xgKLFglPkZLjDic6HyDsEMNvGR2Nxifoci3tEI+X770JU0XmPXIlax+LTPh83fFox1X6kxyzdjm9UcdXi9S+Vti6svfyNULhNR9TVsYNhW6Ff9KKCNR7/Zv6eeaQ+6+qcdpu9BqGlp1HFgud+FYdzzUcUExu0Q/cdzHGEFetIlXKPjK/sbqYoOftMiS+j9jzEJPd1Wt+5+kdR/9EM9ucIC5jCbyPc01Q32kfsBppYz3hYFcCwAAAAASUVORK5CYII=") !important;background-repeat:no-repeat;background-position:center;background-size:12px}div.dtsp-topRow div.dtsp-subRow2{white-space:nowrap;flex:0 0 auto}div.dtsp-topRow button.dtsp-nameButton{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACMAAAAjCAYAAAAe2bNZAAABcGlDQ1BpY2MAACiRdZHNSwJBGMYftTDS8FCHkA57sOigIAXRMQzyYh3UIKvL7rirwe66zK6IdA26dBA6RF36OvQf1DXoWhAERRAR9B/0dQnZ3nEFJXSG2ffHs/O8zDwD+DM6M+yBJGCYDs+mU9JaYV0KviNMM4QoEjKzreXcUh59x88jfKI+JESv/vt6jlBRtRngGyKeYxZ3iBeIMzXHErxHPMbKcpH4hDjO6YDEt0JXPH4TXPL4SzDPZxcBv+gplbpY6WJW5gbxNHHM0KusfR5xk7BqruaoRmlNwEYWaaQgQUEVW9DhIEHVpMx6+5It3woq5GH0tVAHJ0cJZfLGSa1SV5WqRrpKU0dd5P4/T1ubnfG6h1PA4Kvrfk4CwX2g2XDd31PXbZ4BgRfg2uz4K5TT/DfpjY4WOwYiO8DlTUdTDoCrXWD82ZK53JICtPyaBnxcACMFYPQeGN7wsmr/x/kTkN+mJ7oDDo+AKdof2fwDCBRoDkL8UccAAAAJcEhZcwAAD2EAAA9hAag/p2kAAAK2SURBVFgJ7ZY9j41BFICvryCExrJBQ6HyEYVEIREaUZDQIRoR2ViJKCioxV+gkVXYTVZEQiEUhG2EQnxUCh0FKolY4ut5XnM2cyfva3Pt5m7EPcmzZ2bemTNnzjkzd1utnvQi0IvAfxiBy5z5FoxO89kPY+8mbMjtzs47RXs5/WVpbAG6bWExt5PuIibvhVkwmC+ck3eK9ln6/fAddFojYzBVuYSBpcnIEvRaqOw2RcaN18FPuJH0JvRUxbT3wWf4ltiKPgfVidWlbGZgPozDFfgAC+EA/K2EI4cwcAJ+gPaeQ+VQU2SOMMGcPgPl/m/V2p50rrbRsRgt9Iv5h6xtpP22Bz7Ce1C+gFFxfKzOmShcU+Qmyh2w3w8rIJfddHTck66EukL/xPhj+JM8rHNmFys0Pg4v0up3aFNlwR9NYyodd3OL/C64zpsymcTFcf6ElM4YzjAWKYrJkaq8kE/yUYNP4BoYvS1QRo+hNtF5xfkTUjoTheukSFFMjlTFm6PjceOca/SMpKfeCR1L6Uzk/y2WIkVhNFJlJAZhP+hYns7b9D3IPuhY5mYrIv8OrQJvR5NYyNaW4jsU8pSGNySiVx4o5tXq3JkoXE/mg5R/M8dGJCJpKhaDcjBRdbI/Rm8g69c122om33BHmj2CHoV5qa9jUXBraJ+G1fAVjIBO1klc87ro1K4JZ/K35SWW3TwcyDd6TecqnAEd8cGq2+w84xvBm1n3vS0izKkkwh5XNC/GmFPqqAtPF89AOScKuemaNzoTV1SD5dtSbmLf1/RV+tC0WTgcj6R7HEtrVGWaqu/lYDZ/2pvxQ/kIyw/gFByHC9AHw910hv1aUUumyd8yy0QfhmEkfiNod0Xusct68J1qc8Tdux0Z97Q+hsDb+AYGYEbF/4Guw2Q/qDPqZG/zXgT+3Qj8AtKnfWhFwmuAAAAAAElFTkSuQmCC") !important;background-repeat:no-repeat;background-position:center;background-size:23px;vertical-align:bottom}div.dtsp-topRow button.dtsp-countButton{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAABcGlDQ1BpY2MAACiRdZHNSwJBGMYftTDS8FCHkA57sOigIAXRMQzyYh3UIKvL7rirwe66zK6IdA26dBA6RF36OvQf1DXoWhAERRAR9B/0dQnZ3nEFJXSG2ffHs/O8zDwD+DM6M+yBJGCYDs+mU9JaYV0KviNMM4QoEjKzreXcUh59x88jfKI+JESv/vt6jlBRtRngGyKeYxZ3iBeIMzXHErxHPMbKcpH4hDjO6YDEt0JXPH4TXPL4SzDPZxcBv+gplbpY6WJW5gbxNHHM0KusfR5xk7BqruaoRmlNwEYWaaQgQUEVW9DhIEHVpMx6+5It3woq5GH0tVAHJ0cJZfLGSa1SV5WqRrpKU0dd5P4/T1ubnfG6h1PA4Kvrfk4CwX2g2XDd31PXbZ4BgRfg2uz4K5TT/DfpjY4WOwYiO8DlTUdTDoCrXWD82ZK53JICtPyaBnxcACMFYPQeGN7wsmr/x/kTkN+mJ7oDDo+AKdof2fwDCBRoDkL8UccAAAAJcEhZcwAAD2EAAA9hAag/p2kAAAG5SURBVEgN3VU9LwVBFF0fiYhofUSlEQkKhU7z/oBCQkIiGr9BgUbhVzy9BAnhFyjV/AYFiU5ICM7ZN+c5Zud5dm3lJmfmzrkz9+7cu3c3y/6jjOBSF8CxXS7FmTkbwqIJjDpJvTcmsJ4K3KPZUpyZsx0sxoB9J6mnAkyC7wGuuCFIipNtEcpcWExgXpOBc78vgj6N+QO4NVsjwdFM59tUIDxDrHMBOeIQ34C5ZDregXuAQm4YcI68nN9B3wr2PcwPAIPkN2EqtJH6b+QZm1ajjTx7BqwAr26Lb+C2Kvpbt0Mb2HAJ7NrGFGfmXO3DeA4UshDfQAVmH0gaUFg852TTTDvlxwBlCtxy9zXyBhQFaq0wMmIdRebrfgosA3zb2hKnqG0oqchp4QbuR8X0TjzABhbdOT8jnQ/atcgqpnfwOA7yqZyTU587ZkIGdesLTt2EkynOnbreMUUKMI/dA4B/QVOcO13CQh+5wWCgDwo/75u59odB/wjmfhbgvACcAOyZPHihMWAoIwxyCLgf1oxfgjzVbgBXSTzIN+f0pg6s5DkcesLMRpsBrgE2XO3CN64JFP7JtUeKHX4CKtRRXFZ+7dEAAAAASUVORK5CYII=") !important;background-repeat:no-repeat;background-position:center;background-size:18px;vertical-align:bottom}div.dtsp-topRow button.dtsp-collapseButton span.dtsp-caret{position:relative;top:2px;display:inline-block}div.dtsp-topRow button.dtsp-collapseButton.dtsp-rotated{transform:rotate(180deg)}div.dtsp-topRow.dtsp-bordered{border:2px solid #f0f0f0;border-radius:3px}div.dtsp-topRow.dtsp-bordered:hover{background-color:#f0f0f0;opacity:.6;border:2px solid #cfcfcf;border-radius:3px;cursor:pointer !important}div.dtsp-panesContainer div.dtsp-searchPanes div.dtsp-searchPane table thead th,div.dtsp-panesContainer div.dtsp-searchPanes div.dtsp-searchPane table thead td{width:100% !important}div.dt-button-collection{z-index:2002}div.dt-button-collection.dtb-collection-closeable div.dtsp-titleRow{padding-right:25px}div.dtsp-columns-1{max-width:100%;margin:0px !important}div.dtsp-columns-2{max-width:49%;margin:0px !important}div.dtsp-columns-3{max-width:32%;margin:0px !important}div.dtsp-columns-4{max-width:24%;margin:0px !important}div.dtsp-columns-5{max-width:19%;margin:0px !important}div.dtsp-columns-6{max-width:16%;margin:0px !important}div.dtsp-columns-7{max-width:14%;margin:0px !important}div.dtsp-columns-8{min-width:12%;margin:0px !important}div.dtsp-columns-9{max-width:10.5%;margin:0px !important}div.dt-button-collection{float:none}div.dtsp-panesContainer{margin-bottom:1em}div.dtsp-panesContainer div.dataTables_wrapper{width:100%}div.dtsp-panesContainer div.dataTables_wrapper div.dataTables_layout_cell{padding:0}div.dtsp-panesContainer div.dataTables_wrapper div.dataTables_scrollHead{display:none !important}div.dtsp-panesContainer div.dataTables_wrapper div.dataTables_scrollBody{background:white !important;border-bottom:none}div.dtsp-panesContainer div.dataTables_wrapper div.dataTables_scrollBody thead{display:none}div.dtsp-panesContainer div.dataTables_wrapper div.dataTables_scrollBody table{table-layout:fixed}div.dtsp-panesContainer div.dataTables_wrapper div.dataTables_scrollBody table tr>th,div.dtsp-panesContainer div.dataTables_wrapper div.dataTables_scrollBody table tr>td{padding:5px 10px}div.dtsp-panesContainer div.dataTables_wrapper div.dataTables_scrollBody td.dtsp-nameColumn{width:100% !important}div.dtsp-panesContainer div.dataTables_wrapper div.dataTables_scrollBody div.dtsp-nameCont{width:100%;display:flex;flex-direction:row;justify-content:flex-start;align-content:flex-start;align-items:flex-start}div.dtsp-panesContainer div.dataTables_wrapper div.dataTables_scrollBody div.dtsp-nameCont span.dtsp-name,div.dtsp-panesContainer div.dataTables_wrapper div.dataTables_scrollBody div.dtsp-nameCont span.dtsp-pill{cursor:default}div.dtsp-panesContainer div.dataTables_wrapper div.dataTables_scrollBody div.dtsp-nameCont span.dtsp-name{text-overflow:ellipsis;overflow:hidden;display:inline-block;vertical-align:middle;white-space:nowrap;flex-grow:1;text-align:left}div.dtsp-panesContainer div.dataTables_wrapper div.dataTables_scrollBody div.dtsp-nameCont span.dtsp-pill{display:inline-block;background-color:#cfcfcf;text-align:center;border:1px solid #cfcfcf;border-radius:10px;width:auto;min-width:30px;color:black;font-size:.9em;padding:0 4px}div.dtsp-panesContainer div.dataTables_wrapper div.dataTables_scrollBody div.dtsp-nameCont span.dtsp-pill:empty{display:none}div.dtsp-panesContainer{clear:both;padding-left:0;padding-right:0;text-align:center}div.dtsp-panesContainer div.dtsp-searchPanes{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:space-between;align-content:flex-start;align-items:stretch;clear:both;text-align:left}div.dtsp-panesContainer div.dtsp-searchPanes div.dtsp-searchPane{flex-grow:1;flex-shrink:0;font-size:.9em;margin-top:15px !important}div.dtsp-panesContainer div.dtsp-searchPanes div.dtsp-searchPane div.dataTables_wrapper{flex:1;box-sizing:border-box}div.dtsp-panesContainer div.dtsp-searchPanes div.dtsp-searchPane div.dataTables_wrapper div.dataTables_filter{display:none}div.dtsp-panesContainer div.dtsp-title{float:left;padding:10px 0}div.dtsp-panesContainer button.dtsp-clearAll,div.dtsp-panesContainer button.dtsp-collapseAll,div.dtsp-panesContainer button.dtsp-showAll{float:right;padding:10px}div.dtsp-hidden{display:none !important}div.dtsp-panesContainer div.dtsp-searchPanes div.dtsp-searchPane div.dataTables_wrapper{border:2px solid #f0f0f0;border-radius:4px}div.dtsp-panesContainer div.dtsp-searchPanes div.dtsp-searchPane div.dataTables_wrapper:hover{border:2px solid #cfcfcf}div.dtsp-panesContainer div.dtsp-searchPanes div.dtsp-searchPane div.dtsp-selected{border:2px solid #3276b1;border-radius:4px}div.dtsp-panesContainer div.dtsp-searchPanes div.dtsp-searchPane div.dtsp-selected:hover{border:2px solid #286092}div.dtsp-panesContainer div.dtsp-searchPanes div.dtsp-searchPane div.dtsp-topRow div.dtsp-searchCont input.dtsp-search{border:none;padding-left:3px}div.dtsp-panesContainer div.dtsp-searchPanes div.dtsp-searchPane input.dtsp-paneInputButton,div.dtsp-panesContainer div.dtsp-searchPanes div.dtsp-searchPane button.dtsp-paneButton{height:35px;width:35px;min-width:0;display:inline-block;margin:2px;border:0px solid transparent;background-color:transparent;margin-bottom:0px}div.dtsp-panesContainer div.dtsp-searchPanes div.dtsp-searchPane input.dtsp-paneInputButton:hover,div.dtsp-panesContainer div.dtsp-searchPanes div.dtsp-searchPane button.dtsp-paneButton:hover{background-color:#f0f0f0;border-radius:2px;cursor:pointer}div.dtsp-panesContainer div.dtsp-searchPanes div.dtsp-searchPane button.dtsp-paneButton{opacity:.6}div.dtsp-panesContainer button.dtsp-clearAll,div.dtsp-panesContainer button.dtsp-collapseAll,div.dtsp-panesContainer button.dtsp-showAll{border:1px solid transparent;background-color:transparent}div.dtsp-panesContainer button.dtsp-clearAll:hover,div.dtsp-panesContainer button.dtsp-collapseAll:hover,div.dtsp-panesContainer button.dtsp-showAll:hover{background-color:#f0f0f0;border-radius:2px;cursor:pointer}div.dtsp-panesContainer button.dtsp-disabledButton{cursor:default !important;color:#7c7c7c}div.dtsp-panesContainer button.dtsp-disabledButton:hover{background-color:transparent}div.dtsp-panesContainer button.dtsp-disabledButton:focus{outline:none}div.dtsp-topRow.dtsp-bordered:hover button.dtsp-disabledButton{cursor:pointer !important;pointer-events:none}div.dtsp-topRow.dtsp-bordered:hover input.dtsp-paneInputButton{pointer-events:none}div.dtsp-narrow{flex-direction:column !important}div.dtsp-narrow div.dtsp-subRows{width:100%;text-align:right}@media screen and (max-width: 767px){div.dtsp-columns-4,div.dtsp-columns-5,div.dtsp-columns-6{max-width:31% !important;min-width:31% !important}}@media screen and (max-width: 640px){div.dtsp-searchPanes{flex-direction:column !important}div.dtsp-searchPane{max-width:98% !important;min-width:98% !important}} + + +table.dataTable tbody>tr.selected,table.dataTable tbody>tr>.selected{background-color:#b0bed9}table.dataTable.stripe tbody>tr.odd.selected,table.dataTable.stripe tbody>tr.odd>.selected,table.dataTable.display tbody>tr.odd.selected,table.dataTable.display tbody>tr.odd>.selected{background-color:#acbad4}table.dataTable.hover tbody>tr.selected:hover,table.dataTable.hover tbody>tr>.selected:hover,table.dataTable.display tbody>tr.selected:hover,table.dataTable.display tbody>tr>.selected:hover{background-color:#aab7d1}table.dataTable.order-column tbody>tr.selected>.sorting_1,table.dataTable.order-column tbody>tr.selected>.sorting_2,table.dataTable.order-column tbody>tr.selected>.sorting_3,table.dataTable.order-column tbody>tr>.selected,table.dataTable.display tbody>tr.selected>.sorting_1,table.dataTable.display tbody>tr.selected>.sorting_2,table.dataTable.display tbody>tr.selected>.sorting_3,table.dataTable.display tbody>tr>.selected{background-color:#acbad5}table.dataTable.display tbody>tr.odd.selected>.sorting_1,table.dataTable.order-column.stripe tbody>tr.odd.selected>.sorting_1{background-color:#a6b4cd}table.dataTable.display tbody>tr.odd.selected>.sorting_2,table.dataTable.order-column.stripe tbody>tr.odd.selected>.sorting_2{background-color:#a8b5cf}table.dataTable.display tbody>tr.odd.selected>.sorting_3,table.dataTable.order-column.stripe tbody>tr.odd.selected>.sorting_3{background-color:#a9b7d1}table.dataTable.display tbody>tr.even.selected>.sorting_1,table.dataTable.order-column.stripe tbody>tr.even.selected>.sorting_1{background-color:#acbad5}table.dataTable.display tbody>tr.even.selected>.sorting_2,table.dataTable.order-column.stripe tbody>tr.even.selected>.sorting_2{background-color:#aebcd6}table.dataTable.display tbody>tr.even.selected>.sorting_3,table.dataTable.order-column.stripe tbody>tr.even.selected>.sorting_3{background-color:#afbdd8}table.dataTable.display tbody>tr.odd>.selected,table.dataTable.order-column.stripe tbody>tr.odd>.selected{background-color:#a6b4cd}table.dataTable.display tbody>tr.even>.selected,table.dataTable.order-column.stripe tbody>tr.even>.selected{background-color:#acbad5}table.dataTable.display tbody>tr.selected:hover>.sorting_1,table.dataTable.order-column.hover tbody>tr.selected:hover>.sorting_1{background-color:#a2aec7}table.dataTable.display tbody>tr.selected:hover>.sorting_2,table.dataTable.order-column.hover tbody>tr.selected:hover>.sorting_2{background-color:#a3b0c9}table.dataTable.display tbody>tr.selected:hover>.sorting_3,table.dataTable.order-column.hover tbody>tr.selected:hover>.sorting_3{background-color:#a5b2cb}table.dataTable.display tbody>tr:hover>.selected,table.dataTable.display tbody>tr>.selected:hover,table.dataTable.order-column.hover tbody>tr:hover>.selected,table.dataTable.order-column.hover tbody>tr>.selected:hover{background-color:#a2aec7}table.dataTable tbody td.select-checkbox,table.dataTable tbody th.select-checkbox{position:relative}table.dataTable tbody td.select-checkbox:before,table.dataTable tbody td.select-checkbox:after,table.dataTable tbody th.select-checkbox:before,table.dataTable tbody th.select-checkbox:after{display:block;position:absolute;top:1.2em;left:50%;width:12px;height:12px;box-sizing:border-box}table.dataTable tbody td.select-checkbox:before,table.dataTable tbody th.select-checkbox:before{content:" ";margin-top:-6px;margin-left:-6px;border:1px solid black;border-radius:3px}table.dataTable tr.selected td.select-checkbox:after,table.dataTable tr.selected th.select-checkbox:after{content:"✓";font-size:20px;margin-top:-19px;margin-left:-6px;text-align:center;text-shadow:1px 1px #b0bed9,-1px -1px #b0bed9,1px -1px #b0bed9,-1px 1px #b0bed9}table.dataTable.compact tbody td.select-checkbox:before,table.dataTable.compact tbody th.select-checkbox:before{margin-top:-12px}table.dataTable.compact tr.selected td.select-checkbox:after,table.dataTable.compact tr.selected th.select-checkbox:after{margin-top:-16px}div.dataTables_wrapper span.select-info,div.dataTables_wrapper span.select-item{margin-left:.5em}@media screen and (max-width: 640px){div.dataTables_wrapper span.select-info,div.dataTables_wrapper span.select-item{margin-left:0;display:block}} + + +div.dtsr-confirmation,div.dtsr-creation{position:fixed;top:20%;left:50%;width:500px;background-color:white;margin-left:-250px;border-radius:6px;box-shadow:0 0 5px #555;border:2px solid #444;z-index:2003;box-sizing:border-box;padding:1em}div.dtsr-confirmation div.dtsr-confirmation-title-row,div.dtsr-creation div.dtsr-confirmation-title-row{text-align:left}div.dtsr-confirmation div.dtsr-confirmation-title-row h2,div.dtsr-creation div.dtsr-confirmation-title-row h2{border-bottom:0px;margin-top:0px;padding-top:0px}div.dtsr-confirmation div.dtsr-confirmation-text,div.dtsr-creation div.dtsr-confirmation-text{text-align:center}div.dtsr-confirmation div.dtsr-confirmation-buttons,div.dtsr-creation div.dtsr-confirmation-buttons{text-align:right;margin-top:1em}div.dtsr-confirmation div.dtsr-confirmation-buttons button.dtsr-confirmation-button,div.dtsr-creation div.dtsr-confirmation-buttons button.dtsr-confirmation-button{margin:0px}div.dtsr-confirmation div.dtsr-creation-text,div.dtsr-creation div.dtsr-creation-text{text-align:left;padding:0px;border:none}div.dtsr-confirmation div.dtsr-creation-text span,div.dtsr-creation div.dtsr-creation-text span{font-size:20px}div.dtsr-confirmation div.dtsr-creation-form div.dtsr-left,div.dtsr-confirmation div.dtsr-creation-form div.dtsr-right,div.dtsr-creation div.dtsr-creation-form div.dtsr-left,div.dtsr-creation div.dtsr-creation-form div.dtsr-right{display:inline-block;width:50%}div.dtsr-confirmation div.dtsr-creation-form div.dtsr-left,div.dtsr-creation div.dtsr-creation-form div.dtsr-left{text-align:right}div.dtsr-confirmation div.dtsr-creation-form div.dtsr-right,div.dtsr-confirmation div.dtsr-creation-form div.dtsr-name-row,div.dtsr-creation div.dtsr-creation-form div.dtsr-right,div.dtsr-creation div.dtsr-creation-form div.dtsr-name-row{text-align:left}div.dtsr-confirmation div.dtsr-creation-form div.dtsr-form-row label.dtsr-name-label,div.dtsr-creation div.dtsr-creation-form div.dtsr-form-row label.dtsr-name-label{width:33.3%;display:inline-block;text-align:right;padding-right:15px;padding-left:15px}div.dtsr-confirmation div.dtsr-creation-form div.dtsr-form-row input.dtsr-name-input,div.dtsr-creation div.dtsr-creation-form div.dtsr-form-row input.dtsr-name-input{width:66.6%;display:inline-block}div.dtsr-confirmation div.dtsr-creation-form div.dtsr-form-row input.dtsr-check-box,div.dtsr-creation div.dtsr-creation-form div.dtsr-form-row input.dtsr-check-box{margin-left:33.3%;margin-right:14px;display:inline-block}div.dtsr-confirmation div.dtsr-creation-form div.dtsr-form-row label.dtsr-toggle-title,div.dtsr-creation div.dtsr-creation-form div.dtsr-form-row label.dtsr-toggle-title{margin-right:-33.3%}div.dtsr-confirmation div.dtsr-confirmation-text,div.dtsr-creation div.dtsr-confirmation-text{text-align:left}div.dtsr-confirmation div.dtsr-confirmation-text label.dtsr-name-label,div.dtsr-creation div.dtsr-confirmation-text label.dtsr-name-label{width:auto;display:inline-block;text-align:right;padding-right:15px}div.dtsr-confirmation div.dtsr-confirmation-text input.dtsr-name-input,div.dtsr-creation div.dtsr-confirmation-text input.dtsr-name-input{width:66.6%;display:inline-block}div.dtsr-confirmation div.dtsr-confirmation-text input.dtsr-check-box,div.dtsr-creation div.dtsr-confirmation-text input.dtsr-check-box{margin-left:33.3%;margin-right:14px;display:inline-block}div.dtsr-confirmation div.dtsr-modal-foot,div.dtsr-creation div.dtsr-modal-foot{text-align:right;padding-top:10px}div.dtsr-confirmation span.dtsr-modal-error,div.dtsr-creation span.dtsr-modal-error{color:red;font-size:.9em}div.dtsr-creation{top:10%}div.dtsr-form-row{padding:10px}div.dtsr-check-row{padding-top:0px}div.dtsr-creation-text{padding:10px}div.dtsr-popover-close{position:absolute;top:10px;right:10px;width:22px;height:22px;border:1px solid #eaeaea;background-color:#f9f9f9;text-align:center;border-radius:3px;cursor:pointer;z-index:12}div.dtsr-background{z-index:2002;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0, 0, 0, 0.7);background:radial-gradient(ellipse farthest-corner at center, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%)}div.dt-button-collection h3{text-align:center;margin-top:4px;margin-bottom:8px;font-size:1.5em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}div.dt-button-collection span.dtsr-emptyStates{border-radius:5px;display:inline-block;line-height:1.6em;white-space:nowrap;text-align:center;vertical-align:middle;width:100%;padding-bottom:7px;padding-top:3px}div.dt-button-collection h3{font-size:1.1em}div.dtsr-creation-form div.dtsr-form-row input.dtsr-name-input{width:57% !important;padding:5px 4px;border:1px solid #aaa;border-radius:3px}div.dtsr-creation-form div.dtsr-form-row input.dtsr-check-box{margin-left:calc(33.3% + 30px) !important}div.dtsr-creation-form div.dtsr-form-row label.dtsr-toggle-title{margin-right:calc(-33.3% - 30px) !important} + + diff --git a/media/datatable/css/index.html b/media/datatable/css/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/media/datatable/css/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/media/datatable/index.html b/media/datatable/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/media/datatable/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/media/datatable/js/datatables.min.js b/media/datatable/js/datatables.min.js new file mode 100644 index 0000000..cd9d163 --- /dev/null +++ b/media/datatable/js/datatables.min.js @@ -0,0 +1,1238 @@ +/* + * This combined file was created by the DataTables downloader builder: + * https://datatables.net/download + * + * To rebuild or modify this file with the latest versions of the included + * software please visit: + * https://datatables.net/download/#dt/jszip-2.5.0/dt-1.11.5/b-2.2.2/b-colvis-2.2.2/b-html5-2.2.2/b-print-2.2.2/cr-1.5.5/date-1.1.2/fc-4.0.2/fh-3.2.2/kt-2.6.4/r-2.2.9/rg-1.1.4/rr-1.2.8/sc-2.0.5/sb-1.3.2/sp-2.0.0/sl-1.3.4/sr-1.1.0 + * + * Included libraries: + * JSZip 2.5.0, DataTables 1.11.5, Buttons 2.2.2, Column visibility 2.2.2, HTML5 export 2.2.2, Print view 2.2.2, ColReorder 1.5.5, DateTime 1.1.2, FixedColumns 4.0.2, FixedHeader 3.2.2, KeyTable 2.6.4, Responsive 2.2.9, RowGroup 1.1.4, RowReorder 1.2.8, Scroller 2.0.5, SearchBuilder 1.3.2, SearchPanes 2.0.0, Select 1.3.4, StateRestore 1.1.0 + */ + +/*! + +JSZip - A Javascript class for generating and reading zip files + + +(c) 2009-2014 Stuart Knightley +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown. + +JSZip uses the library pako released under the MIT license : +https://github.com/nodeca/pako/blob/master/LICENSE +*/ +!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;"undefined"!=typeof window?b=window:"undefined"!=typeof global?b=global:"undefined"!=typeof self&&(b=self),b.JSZip=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g>2,g=(3&b)<<4|c>>4,h=(15&c)<<2|e>>6,i=63&e,isNaN(c)?h=i=64:isNaN(e)&&(i=64),j=j+d.charAt(f)+d.charAt(g)+d.charAt(h)+d.charAt(i);return j},c.decode=function(a){var b,c,e,f,g,h,i,j="",k=0;for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");k>4,c=(15&g)<<4|h>>2,e=(3&h)<<6|i,j+=String.fromCharCode(b),64!=h&&(j+=String.fromCharCode(c)),64!=i&&(j+=String.fromCharCode(e));return j}},{}],2:[function(a,b){"use strict";function c(){this.compressedSize=0,this.uncompressedSize=0,this.crc32=0,this.compressionMethod=null,this.compressedContent=null}c.prototype={getContent:function(){return null},getCompressedContent:function(){return null}},b.exports=c},{}],3:[function(a,b,c){"use strict";c.STORE={magic:"\x00\x00",compress:function(a){return a},uncompress:function(a){return a},compressInputType:null,uncompressInputType:null},c.DEFLATE=a("./flate")},{"./flate":8}],4:[function(a,b){"use strict";var c=a("./utils"),d=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117];b.exports=function(a,b){if("undefined"==typeof a||!a.length)return 0;var e="string"!==c.getTypeOf(a);"undefined"==typeof b&&(b=0);var f=0,g=0,h=0;b=-1^b;for(var i=0,j=a.length;j>i;i++)h=e?a[i]:a.charCodeAt(i),g=255&(b^h),f=d[g],b=b>>>8^f;return-1^b}},{"./utils":21}],5:[function(a,b){"use strict";function c(){this.data=null,this.length=0,this.index=0}var d=a("./utils");c.prototype={checkOffset:function(a){this.checkIndex(this.index+a)},checkIndex:function(a){if(this.lengtha)throw new Error("End of data reached (data length = "+this.length+", asked index = "+a+"). Corrupted zip ?")},setIndex:function(a){this.checkIndex(a),this.index=a},skip:function(a){this.setIndex(this.index+a)},byteAt:function(){},readInt:function(a){var b,c=0;for(this.checkOffset(a),b=this.index+a-1;b>=this.index;b--)c=(c<<8)+this.byteAt(b);return this.index+=a,c},readString:function(a){return d.transformTo("string",this.readData(a))},readData:function(){},lastIndexOfSignature:function(){},readDate:function(){var a=this.readInt(4);return new Date((a>>25&127)+1980,(a>>21&15)-1,a>>16&31,a>>11&31,a>>5&63,(31&a)<<1)}},b.exports=c},{"./utils":21}],6:[function(a,b,c){"use strict";c.base64=!1,c.binary=!1,c.dir=!1,c.createFolders=!1,c.date=null,c.compression=null,c.compressionOptions=null,c.comment=null,c.unixPermissions=null,c.dosPermissions=null},{}],7:[function(a,b,c){"use strict";var d=a("./utils");c.string2binary=function(a){return d.string2binary(a)},c.string2Uint8Array=function(a){return d.transformTo("uint8array",a)},c.uint8Array2String=function(a){return d.transformTo("string",a)},c.string2Blob=function(a){var b=d.transformTo("arraybuffer",a);return d.arrayBuffer2Blob(b)},c.arrayBuffer2Blob=function(a){return d.arrayBuffer2Blob(a)},c.transformTo=function(a,b){return d.transformTo(a,b)},c.getTypeOf=function(a){return d.getTypeOf(a)},c.checkSupport=function(a){return d.checkSupport(a)},c.MAX_VALUE_16BITS=d.MAX_VALUE_16BITS,c.MAX_VALUE_32BITS=d.MAX_VALUE_32BITS,c.pretty=function(a){return d.pretty(a)},c.findCompression=function(a){return d.findCompression(a)},c.isRegExp=function(a){return d.isRegExp(a)}},{"./utils":21}],8:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,e=a("pako");c.uncompressInputType=d?"uint8array":"array",c.compressInputType=d?"uint8array":"array",c.magic="\b\x00",c.compress=function(a,b){return e.deflateRaw(a,{level:b.level||-1})},c.uncompress=function(a){return e.inflateRaw(a)}},{pako:24}],9:[function(a,b){"use strict";function c(a,b){return this instanceof c?(this.files={},this.comment=null,this.root="",a&&this.load(a,b),void(this.clone=function(){var a=new c;for(var b in this)"function"!=typeof this[b]&&(a[b]=this[b]);return a})):new c(a,b)}var d=a("./base64");c.prototype=a("./object"),c.prototype.load=a("./load"),c.support=a("./support"),c.defaults=a("./defaults"),c.utils=a("./deprecatedPublicUtils"),c.base64={encode:function(a){return d.encode(a)},decode:function(a){return d.decode(a)}},c.compressions=a("./compressions"),b.exports=c},{"./base64":1,"./compressions":3,"./defaults":6,"./deprecatedPublicUtils":7,"./load":10,"./object":13,"./support":17}],10:[function(a,b){"use strict";var c=a("./base64"),d=a("./zipEntries");b.exports=function(a,b){var e,f,g,h;for(b=b||{},b.base64&&(a=c.decode(a)),f=new d(a,b),e=f.files,g=0;gc;c++)d+=String.fromCharCode(255&a),a>>>=8;return d},t=function(){var a,b,c={};for(a=0;a0?a.substring(0,b):""},x=function(a){return"/"!=a.slice(-1)&&(a+="/"),a},y=function(a,b){return b="undefined"!=typeof b?b:!1,a=x(a),this.files[a]||v.call(this,a,null,{dir:!0,createFolders:b}),this.files[a]},z=function(a,b,c){var f,g=new j;return a._data instanceof j?(g.uncompressedSize=a._data.uncompressedSize,g.crc32=a._data.crc32,0===g.uncompressedSize||a.dir?(b=i.STORE,g.compressedContent="",g.crc32=0):a._data.compressionMethod===b.magic?g.compressedContent=a._data.getCompressedContent():(f=a._data.getContent(),g.compressedContent=b.compress(d.transformTo(b.compressInputType,f),c))):(f=p(a),(!f||0===f.length||a.dir)&&(b=i.STORE,f=""),g.uncompressedSize=f.length,g.crc32=e(f),g.compressedContent=b.compress(d.transformTo(b.compressInputType,f),c)),g.compressedSize=g.compressedContent.length,g.compressionMethod=b.magic,g},A=function(a,b){var c=a;return a||(c=b?16893:33204),(65535&c)<<16},B=function(a){return 63&(a||0)},C=function(a,b,c,g,h){var i,j,k,m,n=(c.compressedContent,d.transformTo("string",l.utf8encode(b.name))),o=b.comment||"",p=d.transformTo("string",l.utf8encode(o)),q=n.length!==b.name.length,r=p.length!==o.length,t=b.options,u="",v="",w="";k=b._initialMetadata.dir!==b.dir?b.dir:t.dir,m=b._initialMetadata.date!==b.date?b.date:t.date;var x=0,y=0;k&&(x|=16),"UNIX"===h?(y=798,x|=A(b.unixPermissions,k)):(y=20,x|=B(b.dosPermissions,k)),i=m.getHours(),i<<=6,i|=m.getMinutes(),i<<=5,i|=m.getSeconds()/2,j=m.getFullYear()-1980,j<<=4,j|=m.getMonth()+1,j<<=5,j|=m.getDate(),q&&(v=s(1,1)+s(e(n),4)+n,u+="up"+s(v.length,2)+v),r&&(w=s(1,1)+s(this.crc32(p),4)+p,u+="uc"+s(w.length,2)+w);var z="";z+="\n\x00",z+=q||r?"\x00\b":"\x00\x00",z+=c.compressionMethod,z+=s(i,2),z+=s(j,2),z+=s(c.crc32,4),z+=s(c.compressedSize,4),z+=s(c.uncompressedSize,4),z+=s(n.length,2),z+=s(u.length,2);var C=f.LOCAL_FILE_HEADER+z+n+u,D=f.CENTRAL_FILE_HEADER+s(y,2)+z+s(p.length,2)+"\x00\x00\x00\x00"+s(x,4)+s(g,4)+n+u+p;return{fileRecord:C,dirRecord:D,compressedObject:c}},D={load:function(){throw new Error("Load method is not defined. Is the file jszip-load.js included ?")},filter:function(a){var b,c,d,e,f=[];for(b in this.files)this.files.hasOwnProperty(b)&&(d=this.files[b],e=new r(d.name,d._data,t(d.options)),c=b.slice(this.root.length,b.length),b.slice(0,this.root.length)===this.root&&a(c,e)&&f.push(e));return f},file:function(a,b,c){if(1===arguments.length){if(d.isRegExp(a)){var e=a;return this.filter(function(a,b){return!b.dir&&e.test(a)})}return this.filter(function(b,c){return!c.dir&&b===a})[0]||null}return a=this.root+a,v.call(this,a,b,c),this},folder:function(a){if(!a)return this;if(d.isRegExp(a))return this.filter(function(b,c){return c.dir&&a.test(b)});var b=this.root+a,c=y.call(this,b),e=this.clone();return e.root=c.name,e},remove:function(a){a=this.root+a;var b=this.files[a];if(b||("/"!=a.slice(-1)&&(a+="/"),b=this.files[a]),b&&!b.dir)delete this.files[a];else for(var c=this.filter(function(b,c){return c.name.slice(0,a.length)===a}),d=0;d=0;--f)if(this.data[f]===b&&this.data[f+1]===c&&this.data[f+2]===d&&this.data[f+3]===e)return f;return-1},c.prototype.readData=function(a){if(this.checkOffset(a),0===a)return new Uint8Array(0);var b=this.data.subarray(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./dataReader":5}],19:[function(a,b){"use strict";var c=a("./utils"),d=function(a){this.data=new Uint8Array(a),this.index=0};d.prototype={append:function(a){0!==a.length&&(a=c.transformTo("uint8array",a),this.data.set(a,this.index),this.index+=a.length)},finalize:function(){return this.data}},b.exports=d},{"./utils":21}],20:[function(a,b,c){"use strict";for(var d=a("./utils"),e=a("./support"),f=a("./nodeBuffer"),g=new Array(256),h=0;256>h;h++)g[h]=h>=252?6:h>=248?5:h>=240?4:h>=224?3:h>=192?2:1;g[254]=g[254]=1;var i=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=e.uint8array?new Uint8Array(i):new Array(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},j=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+g[a[c]]>b?c:b},k=function(a){var b,c,e,f,h=a.length,i=new Array(2*h);for(c=0,b=0;h>b;)if(e=a[b++],128>e)i[c++]=e;else if(f=g[e],f>4)i[c++]=65533,b+=f-1;else{for(e&=2===f?31:3===f?15:7;f>1&&h>b;)e=e<<6|63&a[b++],f--;f>1?i[c++]=65533:65536>e?i[c++]=e:(e-=65536,i[c++]=55296|e>>10&1023,i[c++]=56320|1023&e)}return i.length!==c&&(i.subarray?i=i.subarray(0,c):i.length=c),d.applyFromCharCode(i)};c.utf8encode=function(a){return e.nodebuffer?f(a,"utf-8"):i(a)},c.utf8decode=function(a){if(e.nodebuffer)return d.transformTo("nodebuffer",a).toString("utf-8");a=d.transformTo(e.uint8array?"uint8array":"array",a);for(var b=[],c=0,f=a.length,g=65536;f>c;){var h=j(a,Math.min(c+g,f));b.push(e.uint8array?k(a.subarray(c,h)):k(a.slice(c,h))),c=h}return b.join("")}},{"./nodeBuffer":11,"./support":17,"./utils":21}],21:[function(a,b,c){"use strict";function d(a){return a}function e(a,b){for(var c=0;cg&&b>1;)try{d.push("array"===f||"nodebuffer"===f?String.fromCharCode.apply(null,a.slice(g,Math.min(g+b,e))):String.fromCharCode.apply(null,a.subarray(g,Math.min(g+b,e)))),g+=b}catch(i){b=Math.floor(b/2)}return d.join("")}function g(a,b){for(var c=0;cb?"0":"")+b.toString(16).toUpperCase();return d},c.findCompression=function(a){for(var b in i)if(i.hasOwnProperty(b)&&i[b].magic===a)return i[b];return null},c.isRegExp=function(a){return"[object RegExp]"===Object.prototype.toString.call(a)}},{"./compressions":3,"./nodeBuffer":11,"./support":17}],22:[function(a,b){"use strict";function c(a,b){this.files=[],this.loadOptions=b,a&&this.load(a)}var d=a("./stringReader"),e=a("./nodeBufferReader"),f=a("./uint8ArrayReader"),g=a("./utils"),h=a("./signature"),i=a("./zipEntry"),j=a("./support"),k=a("./object");c.prototype={checkSignature:function(a){var b=this.reader.readString(4);if(b!==a)throw new Error("Corrupted zip or bug : unexpected signature ("+g.pretty(b)+", expected "+g.pretty(a)+")")},readBlockEndOfCentral:function(){this.diskNumber=this.reader.readInt(2),this.diskWithCentralDirStart=this.reader.readInt(2),this.centralDirRecordsOnThisDisk=this.reader.readInt(2),this.centralDirRecords=this.reader.readInt(2),this.centralDirSize=this.reader.readInt(4),this.centralDirOffset=this.reader.readInt(4),this.zipCommentLength=this.reader.readInt(2),this.zipComment=this.reader.readString(this.zipCommentLength),this.zipComment=k.utf8decode(this.zipComment)},readBlockZip64EndOfCentral:function(){this.zip64EndOfCentralSize=this.reader.readInt(8),this.versionMadeBy=this.reader.readString(2),this.versionNeeded=this.reader.readInt(2),this.diskNumber=this.reader.readInt(4),this.diskWithCentralDirStart=this.reader.readInt(4),this.centralDirRecordsOnThisDisk=this.reader.readInt(8),this.centralDirRecords=this.reader.readInt(8),this.centralDirSize=this.reader.readInt(8),this.centralDirOffset=this.reader.readInt(8),this.zip64ExtensibleData={};for(var a,b,c,d=this.zip64EndOfCentralSize-44,e=0;d>e;)a=this.reader.readInt(2),b=this.reader.readInt(4),c=this.reader.readString(b),this.zip64ExtensibleData[a]={id:a,length:b,value:c}},readBlockZip64EndOfCentralLocator:function(){if(this.diskWithZip64CentralDirStart=this.reader.readInt(4),this.relativeOffsetEndOfZip64CentralDir=this.reader.readInt(8),this.disksCount=this.reader.readInt(4),this.disksCount>1)throw new Error("Multi-volumes zip are not supported")},readLocalFiles:function(){var a,b;for(a=0;a>8;this.dir=16&this.externalFileAttributes?!0:!1,a===h&&(this.dosPermissions=63&this.externalFileAttributes),a===i&&(this.unixPermissions=this.externalFileAttributes>>16&65535),this.dir||"/"!==this.fileName.slice(-1)||(this.dir=!0)},parseZIP64ExtraField:function(){if(this.extraFields[1]){var a=new d(this.extraFields[1].value);this.uncompressedSize===e.MAX_VALUE_32BITS&&(this.uncompressedSize=a.readInt(8)),this.compressedSize===e.MAX_VALUE_32BITS&&(this.compressedSize=a.readInt(8)),this.localHeaderOffset===e.MAX_VALUE_32BITS&&(this.localHeaderOffset=a.readInt(8)),this.diskNumberStart===e.MAX_VALUE_32BITS&&(this.diskNumberStart=a.readInt(4))}},readExtraFields:function(a){var b,c,d,e=a.index;for(this.extraFields=this.extraFields||{};a.index0?b.windowBits=-b.windowBits:b.gzip&&b.windowBits>0&&b.windowBits<16&&(b.windowBits+=16),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=g.deflateInit2(this.strm,b.level,b.method,b.windowBits,b.memLevel,b.strategy);if(c!==n)throw new Error(j[c]);b.header&&g.deflateSetHeader(this.strm,b.header)};s.prototype.push=function(a,b){var c,d,e=this.strm,f=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?m:l,e.input="string"==typeof a?i.string2buf(a):a,e.next_in=0,e.avail_in=e.input.length;do{if(0===e.avail_out&&(e.output=new h.Buf8(f),e.next_out=0,e.avail_out=f),c=g.deflate(e,d),c!==o&&c!==n)return this.onEnd(c),this.ended=!0,!1;(0===e.avail_out||0===e.avail_in&&d===m)&&this.onData("string"===this.options.to?i.buf2binstring(h.shrinkBuf(e.output,e.next_out)):h.shrinkBuf(e.output,e.next_out))}while((e.avail_in>0||0===e.avail_out)&&c!==o);return d===m?(c=g.deflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===n):!0},s.prototype.onData=function(a){this.chunks.push(a)},s.prototype.onEnd=function(a){a===n&&(this.result="string"===this.options.to?this.chunks.join(""):h.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Deflate=s,c.deflate=d,c.deflateRaw=e,c.gzip=f},{"./utils/common":27,"./utils/strings":28,"./zlib/deflate.js":32,"./zlib/messages":37,"./zlib/zstream":39}],26:[function(a,b,c){"use strict";function d(a,b){var c=new m(b);if(c.push(a,!0),c.err)throw c.msg;return c.result}function e(a,b){return b=b||{},b.raw=!0,d(a,b)}var f=a("./zlib/inflate.js"),g=a("./utils/common"),h=a("./utils/strings"),i=a("./zlib/constants"),j=a("./zlib/messages"),k=a("./zlib/zstream"),l=a("./zlib/gzheader"),m=function(a){this.options=g.assign({chunkSize:16384,windowBits:0,to:""},a||{});var b=this.options;b.raw&&b.windowBits>=0&&b.windowBits<16&&(b.windowBits=-b.windowBits,0===b.windowBits&&(b.windowBits=-15)),!(b.windowBits>=0&&b.windowBits<16)||a&&a.windowBits||(b.windowBits+=32),b.windowBits>15&&b.windowBits<48&&0===(15&b.windowBits)&&(b.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=f.inflateInit2(this.strm,b.windowBits);if(c!==i.Z_OK)throw new Error(j[c]);this.header=new l,f.inflateGetHeader(this.strm,this.header)};m.prototype.push=function(a,b){var c,d,e,j,k,l=this.strm,m=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?i.Z_FINISH:i.Z_NO_FLUSH,l.input="string"==typeof a?h.binstring2buf(a):a,l.next_in=0,l.avail_in=l.input.length;do{if(0===l.avail_out&&(l.output=new g.Buf8(m),l.next_out=0,l.avail_out=m),c=f.inflate(l,i.Z_NO_FLUSH),c!==i.Z_STREAM_END&&c!==i.Z_OK)return this.onEnd(c),this.ended=!0,!1;l.next_out&&(0===l.avail_out||c===i.Z_STREAM_END||0===l.avail_in&&d===i.Z_FINISH)&&("string"===this.options.to?(e=h.utf8border(l.output,l.next_out),j=l.next_out-e,k=h.buf2string(l.output,e),l.next_out=j,l.avail_out=m-j,j&&g.arraySet(l.output,l.output,e,j,0),this.onData(k)):this.onData(g.shrinkBuf(l.output,l.next_out)))}while(l.avail_in>0&&c!==i.Z_STREAM_END);return c===i.Z_STREAM_END&&(d=i.Z_FINISH),d===i.Z_FINISH?(c=f.inflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===i.Z_OK):!0},m.prototype.onData=function(a){this.chunks.push(a)},m.prototype.onEnd=function(a){a===i.Z_OK&&(this.result="string"===this.options.to?this.chunks.join(""):g.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Inflate=m,c.inflate=d,c.inflateRaw=e,c.ungzip=d},{"./utils/common":27,"./utils/strings":28,"./zlib/constants":30,"./zlib/gzheader":33,"./zlib/inflate.js":35,"./zlib/messages":37,"./zlib/zstream":39}],27:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;c.assign=function(a){for(var b=Array.prototype.slice.call(arguments,1);b.length;){var c=b.shift();if(c){if("object"!=typeof c)throw new TypeError(c+"must be non-object");for(var d in c)c.hasOwnProperty(d)&&(a[d]=c[d])}}return a},c.shrinkBuf=function(a,b){return a.length===b?a:a.subarray?a.subarray(0,b):(a.length=b,a)};var e={arraySet:function(a,b,c,d,e){if(b.subarray&&a.subarray)return void a.set(b.subarray(c,c+d),e);for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){var b,c,d,e,f,g;for(d=0,b=0,c=a.length;c>b;b++)d+=a[b].length;for(g=new Uint8Array(d),e=0,b=0,c=a.length;c>b;b++)f=a[b],g.set(f,e),e+=f.length;return g}},f={arraySet:function(a,b,c,d,e){for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){return[].concat.apply([],a)}};c.setTyped=function(a){a?(c.Buf8=Uint8Array,c.Buf16=Uint16Array,c.Buf32=Int32Array,c.assign(c,e)):(c.Buf8=Array,c.Buf16=Array,c.Buf32=Array,c.assign(c,f))},c.setTyped(d)},{}],28:[function(a,b,c){"use strict";function d(a,b){if(65537>b&&(a.subarray&&g||!a.subarray&&f))return String.fromCharCode.apply(null,e.shrinkBuf(a,b));for(var c="",d=0;b>d;d++)c+=String.fromCharCode(a[d]);return c}var e=a("./common"),f=!0,g=!0;try{String.fromCharCode.apply(null,[0])}catch(h){f=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(h){g=!1}for(var i=new e.Buf8(256),j=0;256>j;j++)i[j]=j>=252?6:j>=248?5:j>=240?4:j>=224?3:j>=192?2:1;i[254]=i[254]=1,c.string2buf=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=new e.Buf8(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},c.buf2binstring=function(a){return d(a,a.length)},c.binstring2buf=function(a){for(var b=new e.Buf8(a.length),c=0,d=b.length;d>c;c++)b[c]=a.charCodeAt(c);return b},c.buf2string=function(a,b){var c,e,f,g,h=b||a.length,j=new Array(2*h);for(e=0,c=0;h>c;)if(f=a[c++],128>f)j[e++]=f;else if(g=i[f],g>4)j[e++]=65533,c+=g-1;else{for(f&=2===g?31:3===g?15:7;g>1&&h>c;)f=f<<6|63&a[c++],g--;g>1?j[e++]=65533:65536>f?j[e++]=f:(f-=65536,j[e++]=55296|f>>10&1023,j[e++]=56320|1023&f)}return d(j,e)},c.utf8border=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+i[a[c]]>b?c:b}},{"./common":27}],29:[function(a,b){"use strict";function c(a,b,c,d){for(var e=65535&a|0,f=a>>>16&65535|0,g=0;0!==c;){g=c>2e3?2e3:c,c-=g;do e=e+b[d++]|0,f=f+e|0;while(--g);e%=65521,f%=65521}return e|f<<16|0}b.exports=c},{}],30:[function(a,b){b.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],31:[function(a,b){"use strict";function c(){for(var a,b=[],c=0;256>c;c++){a=c;for(var d=0;8>d;d++)a=1&a?3988292384^a>>>1:a>>>1;b[c]=a}return b}function d(a,b,c,d){var f=e,g=d+c;a=-1^a;for(var h=d;g>h;h++)a=a>>>8^f[255&(a^b[h])];return-1^a}var e=c();b.exports=d},{}],32:[function(a,b,c){"use strict";function d(a,b){return a.msg=G[b],b}function e(a){return(a<<1)-(a>4?9:0)}function f(a){for(var b=a.length;--b>=0;)a[b]=0}function g(a){var b=a.state,c=b.pending;c>a.avail_out&&(c=a.avail_out),0!==c&&(C.arraySet(a.output,b.pending_buf,b.pending_out,c,a.next_out),a.next_out+=c,b.pending_out+=c,a.total_out+=c,a.avail_out-=c,b.pending-=c,0===b.pending&&(b.pending_out=0))}function h(a,b){D._tr_flush_block(a,a.block_start>=0?a.block_start:-1,a.strstart-a.block_start,b),a.block_start=a.strstart,g(a.strm)}function i(a,b){a.pending_buf[a.pending++]=b}function j(a,b){a.pending_buf[a.pending++]=b>>>8&255,a.pending_buf[a.pending++]=255&b}function k(a,b,c,d){var e=a.avail_in;return e>d&&(e=d),0===e?0:(a.avail_in-=e,C.arraySet(b,a.input,a.next_in,e,c),1===a.state.wrap?a.adler=E(a.adler,b,e,c):2===a.state.wrap&&(a.adler=F(a.adler,b,e,c)),a.next_in+=e,a.total_in+=e,e)}function l(a,b){var c,d,e=a.max_chain_length,f=a.strstart,g=a.prev_length,h=a.nice_match,i=a.strstart>a.w_size-jb?a.strstart-(a.w_size-jb):0,j=a.window,k=a.w_mask,l=a.prev,m=a.strstart+ib,n=j[f+g-1],o=j[f+g];a.prev_length>=a.good_match&&(e>>=2),h>a.lookahead&&(h=a.lookahead);do if(c=b,j[c+g]===o&&j[c+g-1]===n&&j[c]===j[f]&&j[++c]===j[f+1]){f+=2,c++;do;while(j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&m>f);if(d=ib-(m-f),f=m-ib,d>g){if(a.match_start=b,g=d,d>=h)break;n=j[f+g-1],o=j[f+g]}}while((b=l[b&k])>i&&0!==--e);return g<=a.lookahead?g:a.lookahead}function m(a){var b,c,d,e,f,g=a.w_size;do{if(e=a.window_size-a.lookahead-a.strstart,a.strstart>=g+(g-jb)){C.arraySet(a.window,a.window,g,g,0),a.match_start-=g,a.strstart-=g,a.block_start-=g,c=a.hash_size,b=c;do d=a.head[--b],a.head[b]=d>=g?d-g:0;while(--c);c=g,b=c;do d=a.prev[--b],a.prev[b]=d>=g?d-g:0;while(--c);e+=g}if(0===a.strm.avail_in)break;if(c=k(a.strm,a.window,a.strstart+a.lookahead,e),a.lookahead+=c,a.lookahead+a.insert>=hb)for(f=a.strstart-a.insert,a.ins_h=a.window[f],a.ins_h=(a.ins_h<a.pending_buf_size-5&&(c=a.pending_buf_size-5);;){if(a.lookahead<=1){if(m(a),0===a.lookahead&&b===H)return sb;if(0===a.lookahead)break}a.strstart+=a.lookahead,a.lookahead=0;var d=a.block_start+c;if((0===a.strstart||a.strstart>=d)&&(a.lookahead=a.strstart-d,a.strstart=d,h(a,!1),0===a.strm.avail_out))return sb;if(a.strstart-a.block_start>=a.w_size-jb&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.strstart>a.block_start&&(h(a,!1),0===a.strm.avail_out)?sb:sb}function o(a,b){for(var c,d;;){if(a.lookahead=hb&&(a.ins_h=(a.ins_h<=hb)if(d=D._tr_tally(a,a.strstart-a.match_start,a.match_length-hb),a.lookahead-=a.match_length,a.match_length<=a.max_lazy_match&&a.lookahead>=hb){a.match_length--;do a.strstart++,a.ins_h=(a.ins_h<=hb&&(a.ins_h=(a.ins_h<4096)&&(a.match_length=hb-1)),a.prev_length>=hb&&a.match_length<=a.prev_length){e=a.strstart+a.lookahead-hb,d=D._tr_tally(a,a.strstart-1-a.prev_match,a.prev_length-hb),a.lookahead-=a.prev_length-1,a.prev_length-=2;do++a.strstart<=e&&(a.ins_h=(a.ins_h<=hb&&a.strstart>0&&(e=a.strstart-1,d=g[e],d===g[++e]&&d===g[++e]&&d===g[++e])){f=a.strstart+ib;do;while(d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&f>e);a.match_length=ib-(f-e),a.match_length>a.lookahead&&(a.match_length=a.lookahead)}if(a.match_length>=hb?(c=D._tr_tally(a,1,a.match_length-hb),a.lookahead-=a.match_length,a.strstart+=a.match_length,a.match_length=0):(c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++),c&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function r(a,b){for(var c;;){if(0===a.lookahead&&(m(a),0===a.lookahead)){if(b===H)return sb;break}if(a.match_length=0,c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++,c&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function s(a){a.window_size=2*a.w_size,f(a.head),a.max_lazy_match=B[a.level].max_lazy,a.good_match=B[a.level].good_length,a.nice_match=B[a.level].nice_length,a.max_chain_length=B[a.level].max_chain,a.strstart=0,a.block_start=0,a.lookahead=0,a.insert=0,a.match_length=a.prev_length=hb-1,a.match_available=0,a.ins_h=0}function t(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=Y,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new C.Buf16(2*fb),this.dyn_dtree=new C.Buf16(2*(2*db+1)),this.bl_tree=new C.Buf16(2*(2*eb+1)),f(this.dyn_ltree),f(this.dyn_dtree),f(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new C.Buf16(gb+1),this.heap=new C.Buf16(2*cb+1),f(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new C.Buf16(2*cb+1),f(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function u(a){var b;return a&&a.state?(a.total_in=a.total_out=0,a.data_type=X,b=a.state,b.pending=0,b.pending_out=0,b.wrap<0&&(b.wrap=-b.wrap),b.status=b.wrap?lb:qb,a.adler=2===b.wrap?0:1,b.last_flush=H,D._tr_init(b),M):d(a,O)}function v(a){var b=u(a);return b===M&&s(a.state),b}function w(a,b){return a&&a.state?2!==a.state.wrap?O:(a.state.gzhead=b,M):O}function x(a,b,c,e,f,g){if(!a)return O;var h=1;if(b===R&&(b=6),0>e?(h=0,e=-e):e>15&&(h=2,e-=16),1>f||f>Z||c!==Y||8>e||e>15||0>b||b>9||0>g||g>V)return d(a,O);8===e&&(e=9);var i=new t;return a.state=i,i.strm=a,i.wrap=h,i.gzhead=null,i.w_bits=e,i.w_size=1<>1,i.l_buf=3*i.lit_bufsize,i.level=b,i.strategy=g,i.method=c,v(a)}function y(a,b){return x(a,b,Y,$,_,W)}function z(a,b){var c,h,k,l;if(!a||!a.state||b>L||0>b)return a?d(a,O):O;if(h=a.state,!a.output||!a.input&&0!==a.avail_in||h.status===rb&&b!==K)return d(a,0===a.avail_out?Q:O);if(h.strm=a,c=h.last_flush,h.last_flush=b,h.status===lb)if(2===h.wrap)a.adler=0,i(h,31),i(h,139),i(h,8),h.gzhead?(i(h,(h.gzhead.text?1:0)+(h.gzhead.hcrc?2:0)+(h.gzhead.extra?4:0)+(h.gzhead.name?8:0)+(h.gzhead.comment?16:0)),i(h,255&h.gzhead.time),i(h,h.gzhead.time>>8&255),i(h,h.gzhead.time>>16&255),i(h,h.gzhead.time>>24&255),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,255&h.gzhead.os),h.gzhead.extra&&h.gzhead.extra.length&&(i(h,255&h.gzhead.extra.length),i(h,h.gzhead.extra.length>>8&255)),h.gzhead.hcrc&&(a.adler=F(a.adler,h.pending_buf,h.pending,0)),h.gzindex=0,h.status=mb):(i(h,0),i(h,0),i(h,0),i(h,0),i(h,0),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,wb),h.status=qb);else{var m=Y+(h.w_bits-8<<4)<<8,n=-1;n=h.strategy>=T||h.level<2?0:h.level<6?1:6===h.level?2:3,m|=n<<6,0!==h.strstart&&(m|=kb),m+=31-m%31,h.status=qb,j(h,m),0!==h.strstart&&(j(h,a.adler>>>16),j(h,65535&a.adler)),a.adler=1}if(h.status===mb)if(h.gzhead.extra){for(k=h.pending;h.gzindex<(65535&h.gzhead.extra.length)&&(h.pending!==h.pending_buf_size||(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending!==h.pending_buf_size));)i(h,255&h.gzhead.extra[h.gzindex]),h.gzindex++;h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),h.gzindex===h.gzhead.extra.length&&(h.gzindex=0,h.status=nb)}else h.status=nb;if(h.status===nb)if(h.gzhead.name){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindexk&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.gzindex=0,h.status=ob)}else h.status=ob;if(h.status===ob)if(h.gzhead.comment){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindexk&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.status=pb)}else h.status=pb;if(h.status===pb&&(h.gzhead.hcrc?(h.pending+2>h.pending_buf_size&&g(a),h.pending+2<=h.pending_buf_size&&(i(h,255&a.adler),i(h,a.adler>>8&255),a.adler=0,h.status=qb)):h.status=qb),0!==h.pending){if(g(a),0===a.avail_out)return h.last_flush=-1,M}else if(0===a.avail_in&&e(b)<=e(c)&&b!==K)return d(a,Q);if(h.status===rb&&0!==a.avail_in)return d(a,Q);if(0!==a.avail_in||0!==h.lookahead||b!==H&&h.status!==rb){var o=h.strategy===T?r(h,b):h.strategy===U?q(h,b):B[h.level].func(h,b);if((o===ub||o===vb)&&(h.status=rb),o===sb||o===ub)return 0===a.avail_out&&(h.last_flush=-1),M;if(o===tb&&(b===I?D._tr_align(h):b!==L&&(D._tr_stored_block(h,0,0,!1),b===J&&(f(h.head),0===h.lookahead&&(h.strstart=0,h.block_start=0,h.insert=0))),g(a),0===a.avail_out))return h.last_flush=-1,M}return b!==K?M:h.wrap<=0?N:(2===h.wrap?(i(h,255&a.adler),i(h,a.adler>>8&255),i(h,a.adler>>16&255),i(h,a.adler>>24&255),i(h,255&a.total_in),i(h,a.total_in>>8&255),i(h,a.total_in>>16&255),i(h,a.total_in>>24&255)):(j(h,a.adler>>>16),j(h,65535&a.adler)),g(a),h.wrap>0&&(h.wrap=-h.wrap),0!==h.pending?M:N)}function A(a){var b;return a&&a.state?(b=a.state.status,b!==lb&&b!==mb&&b!==nb&&b!==ob&&b!==pb&&b!==qb&&b!==rb?d(a,O):(a.state=null,b===qb?d(a,P):M)):O}var B,C=a("../utils/common"),D=a("./trees"),E=a("./adler32"),F=a("./crc32"),G=a("./messages"),H=0,I=1,J=3,K=4,L=5,M=0,N=1,O=-2,P=-3,Q=-5,R=-1,S=1,T=2,U=3,V=4,W=0,X=2,Y=8,Z=9,$=15,_=8,ab=29,bb=256,cb=bb+1+ab,db=30,eb=19,fb=2*cb+1,gb=15,hb=3,ib=258,jb=ib+hb+1,kb=32,lb=42,mb=69,nb=73,ob=91,pb=103,qb=113,rb=666,sb=1,tb=2,ub=3,vb=4,wb=3,xb=function(a,b,c,d,e){this.good_length=a,this.max_lazy=b,this.nice_length=c,this.max_chain=d,this.func=e};B=[new xb(0,0,0,0,n),new xb(4,4,8,4,o),new xb(4,5,16,8,o),new xb(4,6,32,32,o),new xb(4,4,16,16,p),new xb(8,16,32,32,p),new xb(8,16,128,128,p),new xb(8,32,128,256,p),new xb(32,128,258,1024,p),new xb(32,258,258,4096,p)],c.deflateInit=y,c.deflateInit2=x,c.deflateReset=v,c.deflateResetKeep=u,c.deflateSetHeader=w,c.deflate=z,c.deflateEnd=A,c.deflateInfo="pako deflate (from Nodeca project)"},{"../utils/common":27,"./adler32":29,"./crc32":31,"./messages":37,"./trees":38}],33:[function(a,b){"use strict";function c(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}b.exports=c},{}],34:[function(a,b){"use strict";var c=30,d=12;b.exports=function(a,b){var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C;e=a.state,f=a.next_in,B=a.input,g=f+(a.avail_in-5),h=a.next_out,C=a.output,i=h-(b-a.avail_out),j=h+(a.avail_out-257),k=e.dmax,l=e.wsize,m=e.whave,n=e.wnext,o=e.window,p=e.hold,q=e.bits,r=e.lencode,s=e.distcode,t=(1<q&&(p+=B[f++]<>>24,p>>>=w,q-=w,w=v>>>16&255,0===w)C[h++]=65535&v;else{if(!(16&w)){if(0===(64&w)){v=r[(65535&v)+(p&(1<q&&(p+=B[f++]<>>=w,q-=w),15>q&&(p+=B[f++]<>>24,p>>>=w,q-=w,w=v>>>16&255,!(16&w)){if(0===(64&w)){v=s[(65535&v)+(p&(1<q&&(p+=B[f++]<q&&(p+=B[f++]<k){a.msg="invalid distance too far back",e.mode=c;break a}if(p>>>=w,q-=w,w=h-i,y>w){if(w=y-w,w>m&&e.sane){a.msg="invalid distance too far back",e.mode=c;break a}if(z=0,A=o,0===n){if(z+=l-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}else if(w>n){if(z+=l+n-w,w-=n,x>w){x-=w;do C[h++]=o[z++];while(--w);if(z=0,x>n){w=n,x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}}else if(z+=n-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}for(;x>2;)C[h++]=A[z++],C[h++]=A[z++],C[h++]=A[z++],x-=3;x&&(C[h++]=A[z++],x>1&&(C[h++]=A[z++]))}else{z=h-y;do C[h++]=C[z++],C[h++]=C[z++],C[h++]=C[z++],x-=3;while(x>2);x&&(C[h++]=C[z++],x>1&&(C[h++]=C[z++]))}break}}break}}while(g>f&&j>h);x=q>>3,f-=x,q-=x<<3,p&=(1<f?5+(g-f):5-(f-g),a.avail_out=j>h?257+(j-h):257-(h-j),e.hold=p,e.bits=q}},{}],35:[function(a,b,c){"use strict";function d(a){return(a>>>24&255)+(a>>>8&65280)+((65280&a)<<8)+((255&a)<<24)}function e(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new r.Buf16(320),this.work=new r.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function f(a){var b;return a&&a.state?(b=a.state,a.total_in=a.total_out=b.total=0,a.msg="",b.wrap&&(a.adler=1&b.wrap),b.mode=K,b.last=0,b.havedict=0,b.dmax=32768,b.head=null,b.hold=0,b.bits=0,b.lencode=b.lendyn=new r.Buf32(ob),b.distcode=b.distdyn=new r.Buf32(pb),b.sane=1,b.back=-1,C):F}function g(a){var b;return a&&a.state?(b=a.state,b.wsize=0,b.whave=0,b.wnext=0,f(a)):F}function h(a,b){var c,d;return a&&a.state?(d=a.state,0>b?(c=0,b=-b):(c=(b>>4)+1,48>b&&(b&=15)),b&&(8>b||b>15)?F:(null!==d.window&&d.wbits!==b&&(d.window=null),d.wrap=c,d.wbits=b,g(a))):F}function i(a,b){var c,d;return a?(d=new e,a.state=d,d.window=null,c=h(a,b),c!==C&&(a.state=null),c):F}function j(a){return i(a,rb)}function k(a){if(sb){var b;for(p=new r.Buf32(512),q=new r.Buf32(32),b=0;144>b;)a.lens[b++]=8;for(;256>b;)a.lens[b++]=9;for(;280>b;)a.lens[b++]=7;for(;288>b;)a.lens[b++]=8;for(v(x,a.lens,0,288,p,0,a.work,{bits:9}),b=0;32>b;)a.lens[b++]=5;v(y,a.lens,0,32,q,0,a.work,{bits:5}),sb=!1}a.lencode=p,a.lenbits=9,a.distcode=q,a.distbits=5}function l(a,b,c,d){var e,f=a.state;return null===f.window&&(f.wsize=1<=f.wsize?(r.arraySet(f.window,b,c-f.wsize,f.wsize,0),f.wnext=0,f.whave=f.wsize):(e=f.wsize-f.wnext,e>d&&(e=d),r.arraySet(f.window,b,c-d,e,f.wnext),d-=e,d?(r.arraySet(f.window,b,c-d,d,0),f.wnext=d,f.whave=f.wsize):(f.wnext+=e,f.wnext===f.wsize&&(f.wnext=0),f.whaven;){if(0===i)break a;i--,m+=e[g++]<>>8&255,c.check=t(c.check,Bb,2,0),m=0,n=0,c.mode=L;break}if(c.flags=0,c.head&&(c.head.done=!1),!(1&c.wrap)||(((255&m)<<8)+(m>>8))%31){a.msg="incorrect header check",c.mode=lb;break}if((15&m)!==J){a.msg="unknown compression method",c.mode=lb;break}if(m>>>=4,n-=4,wb=(15&m)+8,0===c.wbits)c.wbits=wb;else if(wb>c.wbits){a.msg="invalid window size",c.mode=lb;break}c.dmax=1<n;){if(0===i)break a;i--,m+=e[g++]<>8&1),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0,c.mode=M;case M:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<>>8&255,Bb[2]=m>>>16&255,Bb[3]=m>>>24&255,c.check=t(c.check,Bb,4,0)),m=0,n=0,c.mode=N;case N:for(;16>n;){if(0===i)break a;i--,m+=e[g++]<>8),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0,c.mode=O;case O:if(1024&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0}else c.head&&(c.head.extra=null);c.mode=P;case P:if(1024&c.flags&&(q=c.length,q>i&&(q=i),q&&(c.head&&(wb=c.head.extra_len-c.length,c.head.extra||(c.head.extra=new Array(c.head.extra_len)),r.arraySet(c.head.extra,e,g,q,wb)),512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,c.length-=q),c.length))break a;c.length=0,c.mode=Q;case Q:if(2048&c.flags){if(0===i)break a;q=0;do wb=e[g+q++],c.head&&wb&&c.length<65536&&(c.head.name+=String.fromCharCode(wb));while(wb&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wb)break a}else c.head&&(c.head.name=null);c.length=0,c.mode=R;case R:if(4096&c.flags){if(0===i)break a;q=0;do wb=e[g+q++],c.head&&wb&&c.length<65536&&(c.head.comment+=String.fromCharCode(wb));while(wb&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wb)break a}else c.head&&(c.head.comment=null);c.mode=S;case S:if(512&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<>9&1,c.head.done=!0),a.adler=c.check=0,c.mode=V;break;case T:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<>>=7&n,n-=7&n,c.mode=ib;break}for(;3>n;){if(0===i)break a;i--,m+=e[g++]<>>=1,n-=1,3&m){case 0:c.mode=X;break;case 1:if(k(c),c.mode=bb,b===B){m>>>=2,n-=2;break a}break;case 2:c.mode=$;break;case 3:a.msg="invalid block type",c.mode=lb}m>>>=2,n-=2;break;case X:for(m>>>=7&n,n-=7&n;32>n;){if(0===i)break a;i--,m+=e[g++]<>>16^65535)){a.msg="invalid stored block lengths",c.mode=lb;break}if(c.length=65535&m,m=0,n=0,c.mode=Y,b===B)break a;case Y:c.mode=Z;case Z:if(q=c.length){if(q>i&&(q=i),q>j&&(q=j),0===q)break a;r.arraySet(f,e,g,q,h),i-=q,g+=q,j-=q,h+=q,c.length-=q;break}c.mode=V;break;case $:for(;14>n;){if(0===i)break a;i--,m+=e[g++]<>>=5,n-=5,c.ndist=(31&m)+1,m>>>=5,n-=5,c.ncode=(15&m)+4,m>>>=4,n-=4,c.nlen>286||c.ndist>30){a.msg="too many length or distance symbols",c.mode=lb;break}c.have=0,c.mode=_;case _:for(;c.haven;){if(0===i)break a;i--,m+=e[g++]<>>=3,n-=3}for(;c.have<19;)c.lens[Cb[c.have++]]=0;if(c.lencode=c.lendyn,c.lenbits=7,yb={bits:c.lenbits},xb=v(w,c.lens,0,19,c.lencode,0,c.work,yb),c.lenbits=yb.bits,xb){a.msg="invalid code lengths set",c.mode=lb;break}c.have=0,c.mode=ab;case ab:for(;c.have>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<sb)m>>>=qb,n-=qb,c.lens[c.have++]=sb;else{if(16===sb){for(zb=qb+2;zb>n;){if(0===i)break a;i--,m+=e[g++]<>>=qb,n-=qb,0===c.have){a.msg="invalid bit length repeat",c.mode=lb;break}wb=c.lens[c.have-1],q=3+(3&m),m>>>=2,n-=2}else if(17===sb){for(zb=qb+3;zb>n;){if(0===i)break a;i--,m+=e[g++]<>>=qb,n-=qb,wb=0,q=3+(7&m),m>>>=3,n-=3}else{for(zb=qb+7;zb>n;){if(0===i)break a;i--,m+=e[g++]<>>=qb,n-=qb,wb=0,q=11+(127&m),m>>>=7,n-=7}if(c.have+q>c.nlen+c.ndist){a.msg="invalid bit length repeat",c.mode=lb;break}for(;q--;)c.lens[c.have++]=wb}}if(c.mode===lb)break;if(0===c.lens[256]){a.msg="invalid code -- missing end-of-block",c.mode=lb;break}if(c.lenbits=9,yb={bits:c.lenbits},xb=v(x,c.lens,0,c.nlen,c.lencode,0,c.work,yb),c.lenbits=yb.bits,xb){a.msg="invalid literal/lengths set",c.mode=lb;break}if(c.distbits=6,c.distcode=c.distdyn,yb={bits:c.distbits},xb=v(y,c.lens,c.nlen,c.ndist,c.distcode,0,c.work,yb),c.distbits=yb.bits,xb){a.msg="invalid distances set",c.mode=lb;break}if(c.mode=bb,b===B)break a;case bb:c.mode=cb;case cb:if(i>=6&&j>=258){a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,u(a,p),h=a.next_out,f=a.output,j=a.avail_out,g=a.next_in,e=a.input,i=a.avail_in,m=c.hold,n=c.bits,c.mode===V&&(c.back=-1); +break}for(c.back=0;Ab=c.lencode[m&(1<>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<>tb)],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=tb+qb);){if(0===i)break a;i--,m+=e[g++]<>>=tb,n-=tb,c.back+=tb}if(m>>>=qb,n-=qb,c.back+=qb,c.length=sb,0===rb){c.mode=hb;break}if(32&rb){c.back=-1,c.mode=V;break}if(64&rb){a.msg="invalid literal/length code",c.mode=lb;break}c.extra=15&rb,c.mode=db;case db:if(c.extra){for(zb=c.extra;zb>n;){if(0===i)break a;i--,m+=e[g++]<>>=c.extra,n-=c.extra,c.back+=c.extra}c.was=c.length,c.mode=eb;case eb:for(;Ab=c.distcode[m&(1<>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<>tb)],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=tb+qb);){if(0===i)break a;i--,m+=e[g++]<>>=tb,n-=tb,c.back+=tb}if(m>>>=qb,n-=qb,c.back+=qb,64&rb){a.msg="invalid distance code",c.mode=lb;break}c.offset=sb,c.extra=15&rb,c.mode=fb;case fb:if(c.extra){for(zb=c.extra;zb>n;){if(0===i)break a;i--,m+=e[g++]<>>=c.extra,n-=c.extra,c.back+=c.extra}if(c.offset>c.dmax){a.msg="invalid distance too far back",c.mode=lb;break}c.mode=gb;case gb:if(0===j)break a;if(q=p-j,c.offset>q){if(q=c.offset-q,q>c.whave&&c.sane){a.msg="invalid distance too far back",c.mode=lb;break}q>c.wnext?(q-=c.wnext,ob=c.wsize-q):ob=c.wnext-q,q>c.length&&(q=c.length),pb=c.window}else pb=f,ob=h-c.offset,q=c.length;q>j&&(q=j),j-=q,c.length-=q;do f[h++]=pb[ob++];while(--q);0===c.length&&(c.mode=cb);break;case hb:if(0===j)break a;f[h++]=c.length,j--,c.mode=cb;break;case ib:if(c.wrap){for(;32>n;){if(0===i)break a;i--,m|=e[g++]<n;){if(0===i)break a;i--,m+=e[g++]<=D;D++)P[D]=0;for(E=0;o>E;E++)P[b[n+E]]++;for(H=C,G=d;G>=1&&0===P[G];G--);if(H>G&&(H=G),0===G)return p[q++]=20971520,p[q++]=20971520,s.bits=1,0;for(F=1;G>F&&0===P[F];F++);for(F>H&&(H=F),K=1,D=1;d>=D;D++)if(K<<=1,K-=P[D],0>K)return-1;if(K>0&&(a===g||1!==G))return-1;for(Q[1]=0,D=1;d>D;D++)Q[D+1]=Q[D]+P[D];for(E=0;o>E;E++)0!==b[n+E]&&(r[Q[b[n+E]]++]=E);if(a===g?(N=R=r,y=19):a===h?(N=j,O-=257,R=k,S-=257,y=256):(N=l,R=m,y=-1),M=0,E=0,D=F,x=q,I=H,J=0,v=-1,L=1<e||a===i&&L>f)return 1;for(var T=0;;){T++,z=D-J,r[E]y?(A=R[S+r[E]],B=N[O+r[E]]):(A=96,B=0),t=1<>J)+u]=z<<24|A<<16|B|0;while(0!==u);for(t=1<>=1;if(0!==t?(M&=t-1,M+=t):M=0,E++,0===--P[D]){if(D===G)break;D=b[n+r[E]]}if(D>H&&(M&w)!==v){for(0===J&&(J=H),x+=F,I=D-J,K=1<I+J&&(K-=P[I+J],!(0>=K));)I++,K<<=1;if(L+=1<e||a===i&&L>f)return 1;v=M&w,p[v]=H<<24|I<<16|x-q|0}}return 0!==M&&(p[x+M]=D-J<<24|64<<16|0),s.bits=H,0}},{"../utils/common":27}],37:[function(a,b){"use strict";b.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],38:[function(a,b,c){"use strict";function d(a){for(var b=a.length;--b>=0;)a[b]=0}function e(a){return 256>a?gb[a]:gb[256+(a>>>7)]}function f(a,b){a.pending_buf[a.pending++]=255&b,a.pending_buf[a.pending++]=b>>>8&255}function g(a,b,c){a.bi_valid>V-c?(a.bi_buf|=b<>V-a.bi_valid,a.bi_valid+=c-V):(a.bi_buf|=b<>>=1,c<<=1;while(--b>0);return c>>>1}function j(a){16===a.bi_valid?(f(a,a.bi_buf),a.bi_buf=0,a.bi_valid=0):a.bi_valid>=8&&(a.pending_buf[a.pending++]=255&a.bi_buf,a.bi_buf>>=8,a.bi_valid-=8)}function k(a,b){var c,d,e,f,g,h,i=b.dyn_tree,j=b.max_code,k=b.stat_desc.static_tree,l=b.stat_desc.has_stree,m=b.stat_desc.extra_bits,n=b.stat_desc.extra_base,o=b.stat_desc.max_length,p=0;for(f=0;U>=f;f++)a.bl_count[f]=0;for(i[2*a.heap[a.heap_max]+1]=0,c=a.heap_max+1;T>c;c++)d=a.heap[c],f=i[2*i[2*d+1]+1]+1,f>o&&(f=o,p++),i[2*d+1]=f,d>j||(a.bl_count[f]++,g=0,d>=n&&(g=m[d-n]),h=i[2*d],a.opt_len+=h*(f+g),l&&(a.static_len+=h*(k[2*d+1]+g)));if(0!==p){do{for(f=o-1;0===a.bl_count[f];)f--;a.bl_count[f]--,a.bl_count[f+1]+=2,a.bl_count[o]--,p-=2}while(p>0);for(f=o;0!==f;f--)for(d=a.bl_count[f];0!==d;)e=a.heap[--c],e>j||(i[2*e+1]!==f&&(a.opt_len+=(f-i[2*e+1])*i[2*e],i[2*e+1]=f),d--)}}function l(a,b,c){var d,e,f=new Array(U+1),g=0;for(d=1;U>=d;d++)f[d]=g=g+c[d-1]<<1;for(e=0;b>=e;e++){var h=a[2*e+1];0!==h&&(a[2*e]=i(f[h]++,h))}}function m(){var a,b,c,d,e,f=new Array(U+1);for(c=0,d=0;O-1>d;d++)for(ib[d]=c,a=0;a<1<<_[d];a++)hb[c++]=d;for(hb[c-1]=d,e=0,d=0;16>d;d++)for(jb[d]=e,a=0;a<1<>=7;R>d;d++)for(jb[d]=e<<7,a=0;a<1<=b;b++)f[b]=0;for(a=0;143>=a;)eb[2*a+1]=8,a++,f[8]++;for(;255>=a;)eb[2*a+1]=9,a++,f[9]++;for(;279>=a;)eb[2*a+1]=7,a++,f[7]++;for(;287>=a;)eb[2*a+1]=8,a++,f[8]++;for(l(eb,Q+1,f),a=0;R>a;a++)fb[2*a+1]=5,fb[2*a]=i(a,5);kb=new nb(eb,_,P+1,Q,U),lb=new nb(fb,ab,0,R,U),mb=new nb(new Array(0),bb,0,S,W)}function n(a){var b;for(b=0;Q>b;b++)a.dyn_ltree[2*b]=0;for(b=0;R>b;b++)a.dyn_dtree[2*b]=0;for(b=0;S>b;b++)a.bl_tree[2*b]=0;a.dyn_ltree[2*X]=1,a.opt_len=a.static_len=0,a.last_lit=a.matches=0}function o(a){a.bi_valid>8?f(a,a.bi_buf):a.bi_valid>0&&(a.pending_buf[a.pending++]=a.bi_buf),a.bi_buf=0,a.bi_valid=0}function p(a,b,c,d){o(a),d&&(f(a,c),f(a,~c)),E.arraySet(a.pending_buf,a.window,b,c,a.pending),a.pending+=c}function q(a,b,c,d){var e=2*b,f=2*c;return a[e]c;c++)0!==f[2*c]?(a.heap[++a.heap_len]=j=c,a.depth[c]=0):f[2*c+1]=0;for(;a.heap_len<2;)e=a.heap[++a.heap_len]=2>j?++j:0,f[2*e]=1,a.depth[e]=0,a.opt_len--,h&&(a.static_len-=g[2*e+1]);for(b.max_code=j,c=a.heap_len>>1;c>=1;c--)r(a,f,c);e=i;do c=a.heap[1],a.heap[1]=a.heap[a.heap_len--],r(a,f,1),d=a.heap[1],a.heap[--a.heap_max]=c,a.heap[--a.heap_max]=d,f[2*e]=f[2*c]+f[2*d],a.depth[e]=(a.depth[c]>=a.depth[d]?a.depth[c]:a.depth[d])+1,f[2*c+1]=f[2*d+1]=e,a.heap[1]=e++,r(a,f,1);while(a.heap_len>=2);a.heap[--a.heap_max]=a.heap[1],k(a,b),l(f,j,a.bl_count)}function u(a,b,c){var d,e,f=-1,g=b[1],h=0,i=7,j=4;for(0===g&&(i=138,j=3),b[2*(c+1)+1]=65535,d=0;c>=d;d++)e=g,g=b[2*(d+1)+1],++hh?a.bl_tree[2*e]+=h:0!==e?(e!==f&&a.bl_tree[2*e]++,a.bl_tree[2*Y]++):10>=h?a.bl_tree[2*Z]++:a.bl_tree[2*$]++,h=0,f=e,0===g?(i=138,j=3):e===g?(i=6,j=3):(i=7,j=4))}function v(a,b,c){var d,e,f=-1,i=b[1],j=0,k=7,l=4;for(0===i&&(k=138,l=3),d=0;c>=d;d++)if(e=i,i=b[2*(d+1)+1],!(++jj){do h(a,e,a.bl_tree);while(0!==--j)}else 0!==e?(e!==f&&(h(a,e,a.bl_tree),j--),h(a,Y,a.bl_tree),g(a,j-3,2)):10>=j?(h(a,Z,a.bl_tree),g(a,j-3,3)):(h(a,$,a.bl_tree),g(a,j-11,7));j=0,f=e,0===i?(k=138,l=3):e===i?(k=6,l=3):(k=7,l=4)}}function w(a){var b;for(u(a,a.dyn_ltree,a.l_desc.max_code),u(a,a.dyn_dtree,a.d_desc.max_code),t(a,a.bl_desc),b=S-1;b>=3&&0===a.bl_tree[2*cb[b]+1];b--);return a.opt_len+=3*(b+1)+5+5+4,b}function x(a,b,c,d){var e;for(g(a,b-257,5),g(a,c-1,5),g(a,d-4,4),e=0;d>e;e++)g(a,a.bl_tree[2*cb[e]+1],3);v(a,a.dyn_ltree,b-1),v(a,a.dyn_dtree,c-1)}function y(a){var b,c=4093624447;for(b=0;31>=b;b++,c>>>=1)if(1&c&&0!==a.dyn_ltree[2*b])return G;if(0!==a.dyn_ltree[18]||0!==a.dyn_ltree[20]||0!==a.dyn_ltree[26])return H;for(b=32;P>b;b++)if(0!==a.dyn_ltree[2*b])return H;return G}function z(a){pb||(m(),pb=!0),a.l_desc=new ob(a.dyn_ltree,kb),a.d_desc=new ob(a.dyn_dtree,lb),a.bl_desc=new ob(a.bl_tree,mb),a.bi_buf=0,a.bi_valid=0,n(a)}function A(a,b,c,d){g(a,(J<<1)+(d?1:0),3),p(a,b,c,!0)}function B(a){g(a,K<<1,3),h(a,X,eb),j(a)}function C(a,b,c,d){var e,f,h=0;a.level>0?(a.strm.data_type===I&&(a.strm.data_type=y(a)),t(a,a.l_desc),t(a,a.d_desc),h=w(a),e=a.opt_len+3+7>>>3,f=a.static_len+3+7>>>3,e>=f&&(e=f)):e=f=c+5,e>=c+4&&-1!==b?A(a,b,c,d):a.strategy===F||f===e?(g(a,(K<<1)+(d?1:0),3),s(a,eb,fb)):(g(a,(L<<1)+(d?1:0),3),x(a,a.l_desc.max_code+1,a.d_desc.max_code+1,h+1),s(a,a.dyn_ltree,a.dyn_dtree)),n(a),d&&o(a)}function D(a,b,c){return a.pending_buf[a.d_buf+2*a.last_lit]=b>>>8&255,a.pending_buf[a.d_buf+2*a.last_lit+1]=255&b,a.pending_buf[a.l_buf+a.last_lit]=255&c,a.last_lit++,0===b?a.dyn_ltree[2*c]++:(a.matches++,b--,a.dyn_ltree[2*(hb[c]+P+1)]++,a.dyn_dtree[2*e(b)]++),a.last_lit===a.lit_bufsize-1}var E=a("../utils/common"),F=4,G=0,H=1,I=2,J=0,K=1,L=2,M=3,N=258,O=29,P=256,Q=P+1+O,R=30,S=19,T=2*Q+1,U=15,V=16,W=7,X=256,Y=16,Z=17,$=18,_=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],ab=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],bb=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],cb=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],db=512,eb=new Array(2*(Q+2));d(eb);var fb=new Array(2*R);d(fb);var gb=new Array(db);d(gb);var hb=new Array(N-M+1);d(hb);var ib=new Array(O);d(ib);var jb=new Array(R);d(jb);var kb,lb,mb,nb=function(a,b,c,d,e){this.static_tree=a,this.extra_bits=b,this.extra_base=c,this.elems=d,this.max_length=e,this.has_stree=a&&a.length},ob=function(a,b){this.dyn_tree=a,this.max_code=0,this.stat_desc=b},pb=!1;c._tr_init=z,c._tr_stored_block=A,c._tr_flush_block=C,c._tr_tally=D,c._tr_align=B},{"../utils/common":27}],39:[function(a,b){"use strict";function c(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}b.exports=c},{}]},{},[9])(9)}); + +/*! + Copyright 2008-2021 SpryMedia Ltd. + + This source file is free software, available under the following license: + MIT license - http://datatables.net/license + + This source file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. + + For details please refer to: http://www.datatables.net + DataTables 1.11.5 + ©2008-2021 SpryMedia Ltd - datatables.net/license +*/ +var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.findInternal=function(l,z,A){l instanceof String&&(l=String(l));for(var q=l.length,E=0;E").css({position:"fixed",top:0,left:-1*l(z).scrollLeft(),height:1, +width:1,overflow:"hidden"}).append(l("
").css({position:"absolute",top:1,left:1,width:100,overflow:"scroll"}).append(l("
").css({width:"100%",height:10}))).appendTo("body"),d=c.children(),e=d.children();b.barWidth=d[0].offsetWidth-d[0].clientWidth;b.bScrollOversize=100===e[0].offsetWidth&&100!==d[0].clientWidth;b.bScrollbarLeft=1!==Math.round(e.offset().left);b.bBounding=c[0].getBoundingClientRect().width?!0:!1;c.remove()}l.extend(a.oBrowser,u.__browser);a.oScroll.iBarWidth=u.__browser.barWidth} +function Cb(a,b,c,d,e,h){var f=!1;if(c!==q){var g=c;f=!0}for(;d!==e;)a.hasOwnProperty(d)&&(g=f?b(g,a[d],d,a):a[d],f=!0,d+=h);return g}function Ya(a,b){var c=u.defaults.column,d=a.aoColumns.length;c=l.extend({},u.models.oColumn,c,{nTh:b?b:A.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.mData:d,idx:d});a.aoColumns.push(c);c=a.aoPreSearchCols;c[d]=l.extend({},u.models.oSearch,c[d]);Ga(a,d,l(b).data())}function Ga(a,b,c){b=a.aoColumns[b]; +var d=a.oClasses,e=l(b.nTh);if(!b.sWidthOrig){b.sWidthOrig=e.attr("width")||null;var h=(e.attr("style")||"").match(/width:\s*(\d+[pxem%]+)/);h&&(b.sWidthOrig=h[1])}c!==q&&null!==c&&(Ab(c),P(u.defaults.column,c,!0),c.mDataProp===q||c.mData||(c.mData=c.mDataProp),c.sType&&(b._sManualType=c.sType),c.className&&!c.sClass&&(c.sClass=c.className),c.sClass&&e.addClass(c.sClass),l.extend(b,c),X(b,c,"sWidth","sWidthOrig"),c.iDataSort!==q&&(b.aDataSort=[c.iDataSort]),X(b,c,"aDataSort"));var f=b.mData,g=na(f), +k=b.mRender?na(b.mRender):null;c=function(m){return"string"===typeof m&&-1!==m.indexOf("@")};b._bAttrSrc=l.isPlainObject(f)&&(c(f.sort)||c(f.type)||c(f.filter));b._setter=null;b.fnGetData=function(m,n,p){var t=g(m,n,q,p);return k&&n?k(t,n,m,p):t};b.fnSetData=function(m,n,p){return ha(f)(m,n,p)};"number"!==typeof f&&(a._rowReadObject=!0);a.oFeatures.bSort||(b.bSortable=!1,e.addClass(d.sSortableNone));a=-1!==l.inArray("asc",b.asSorting);c=-1!==l.inArray("desc",b.asSorting);b.bSortable&&(a||c)?a&&!c? +(b.sSortingClass=d.sSortableAsc,b.sSortingClassJUI=d.sSortJUIAscAllowed):!a&&c?(b.sSortingClass=d.sSortableDesc,b.sSortingClassJUI=d.sSortJUIDescAllowed):(b.sSortingClass=d.sSortable,b.sSortingClassJUI=d.sSortJUI):(b.sSortingClass=d.sSortableNone,b.sSortingClassJUI="")}function sa(a){if(!1!==a.oFeatures.bAutoWidth){var b=a.aoColumns;Za(a);for(var c=0,d=b.length;cm[n])d(g.length+m[n],k);else if("string"===typeof m[n]){var p=0;for(f=g.length;pb&&a[e]--; -1!=d&&c===q&&a.splice(d,1)}function va(a,b,c,d){var e=a.aoData[b],h,f=function(k,m){for(;k.childNodes.length;)k.removeChild(k.firstChild);k.innerHTML=T(a,b,m,"display")};if("dom"!==c&&(c&&"auto"!==c||"dom"!==e.src)){var g=e.anCells;if(g)if(d!==q)f(g[d],d);else for(c=0,h=g.length;c").appendTo(d));var k=0;for(b=g.length;k=a.fnRecordsDisplay()?0:d,a.iInitDisplayStart=-1);c=F(a,"aoPreDrawCallback","preDraw",[a]);if(-1!==l.inArray(!1,c))V(a,!1);else{c=[];var e=0;d=a.asStripeClasses;var h=d.length,f=a.oLanguage,g="ssp"==Q(a),k=a.aiDisplay,m=a._iDisplayStart,n=a.fnDisplayEnd();a.bDrawing=!0;if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++,V(a,!1);else if(!g)a.iDraw++;else if(!a.bDestroying&&!b){Gb(a);return}if(0!==k.length)for(b=g?a.aoData.length:n,f=g?0:m;f",{"class":h?d[0]:""}).append(l("",{valign:"top",colSpan:oa(a),"class":a.oClasses.sRowEmpty}).html(e))[0];F(a,"aoHeaderCallback","header",[l(a.nTHead).children("tr")[0],db(a),m,n,k]);F(a,"aoFooterCallback", +"footer",[l(a.nTFoot).children("tr")[0],db(a),m,n,k]);d=l(a.nTBody);d.children().detach();d.append(l(c));F(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing=!1}}function ka(a,b){var c=a.oFeatures,d=c.bFilter;c.bSort&&Hb(a);d?ya(a,a.oPreviousSearch):a.aiDisplay=a.aiDisplayMaster.slice();!0!==b&&(a._iDisplayStart=0);a._drawHold=b;ja(a);a._drawHold=!1}function Ib(a){var b=a.oClasses,c=l(a.nTable);c=l("
").insertBefore(c);var d=a.oFeatures,e=l("
",{id:a.sTableId+"_wrapper", +"class":b.sWrapper+(a.nTFoot?"":" "+b.sNoFooter)});a.nHolding=c[0];a.nTableWrapper=e[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var h=a.sDom.split(""),f,g,k,m,n,p,t=0;t")[0];m=h[t+1];if("'"==m||'"'==m){n="";for(p=2;h[t+p]!=m;)n+=h[t+p],p++;"H"==n?n=b.sJUIHeader:"F"==n&&(n=b.sJUIFooter);-1!=n.indexOf(".")?(m=n.split("."),k.id=m[0].substr(1,m[0].length-1),k.className=m[1]):"#"==n.charAt(0)?k.id=n.substr(1,n.length-1):k.className=n;t+=p}e.append(k); +e=l(k)}else if(">"==g)e=e.parent();else if("l"==g&&d.bPaginate&&d.bLengthChange)f=Jb(a);else if("f"==g&&d.bFilter)f=Kb(a);else if("r"==g&&d.bProcessing)f=Lb(a);else if("t"==g)f=Mb(a);else if("i"==g&&d.bInfo)f=Nb(a);else if("p"==g&&d.bPaginate)f=Ob(a);else if(0!==u.ext.feature.length)for(k=u.ext.feature,p=0,m=k.length;p',g=d.sSearch;g=g.match(/_INPUT_/)?g.replace("_INPUT_",f):g+f;b=l("
",{id:h.f?null:c+"_filter","class":b.sFilter}).append(l("
").addClass(b.sLength);a.aanFeatures.l||(k[0].id=c+"_length");k.children().append(a.oLanguage.sLengthMenu.replace("_MENU_",e[0].outerHTML));l("select",k).val(a._iDisplayLength).on("change.DT",function(m){kb(a,l(this).val());ja(a)});l(a.nTable).on("length.dt.DT",function(m,n,p){a===n&&l("select",k).val(p)});return k[0]}function Ob(a){var b=a.sPaginationType,c=u.ext.pager[b],d="function"===typeof c,e=function(f){ja(f)};b=l("
").addClass(a.oClasses.sPaging+b)[0]; +var h=a.aanFeatures;d||c.fnInit(a,b,e);h.p||(b.id=a.sTableId+"_paginate",a.aoDrawCallback.push({fn:function(f){if(d){var g=f._iDisplayStart,k=f._iDisplayLength,m=f.fnRecordsDisplay(),n=-1===k;g=n?0:Math.ceil(g/k);k=n?1:Math.ceil(m/k);m=c(g,k);var p;n=0;for(p=h.p.length;nh&& +(d=0)):"first"==b?d=0:"previous"==b?(d=0<=e?d-e:0,0>d&&(d=0)):"next"==b?d+e",{id:a.aanFeatures.r?null:a.sTableId+"_processing","class":a.oClasses.sProcessing}).html(a.oLanguage.sProcessing).insertBefore(a.nTable)[0]}function V(a,b){a.oFeatures.bProcessing&&l(a.aanFeatures.r).css("display",b?"block":"none"); +F(a,null,"processing",[a,b])}function Mb(a){var b=l(a.nTable),c=a.oScroll;if(""===c.sX&&""===c.sY)return a.nTable;var d=c.sX,e=c.sY,h=a.oClasses,f=b.children("caption"),g=f.length?f[0]._captionSide:null,k=l(b[0].cloneNode(!1)),m=l(b[0].cloneNode(!1)),n=b.children("tfoot");n.length||(n=null);k=l("
",{"class":h.sScrollWrapper}).append(l("
",{"class":h.sScrollHead}).css({overflow:"hidden",position:"relative",border:0,width:d?d?K(d):null:"100%"}).append(l("
",{"class":h.sScrollHeadInner}).css({"box-sizing":"content-box", +width:c.sXInner||"100%"}).append(k.removeAttr("id").css("margin-left",0).append("top"===g?f:null).append(b.children("thead"))))).append(l("
",{"class":h.sScrollBody}).css({position:"relative",overflow:"auto",width:d?K(d):null}).append(b));n&&k.append(l("
",{"class":h.sScrollFoot}).css({overflow:"hidden",border:0,width:d?d?K(d):null:"100%"}).append(l("
",{"class":h.sScrollFootInner}).append(m.removeAttr("id").css("margin-left",0).append("bottom"===g?f:null).append(b.children("tfoot"))))); +b=k.children();var p=b[0];h=b[1];var t=n?b[2]:null;if(d)l(h).on("scroll.DT",function(v){v=this.scrollLeft;p.scrollLeft=v;n&&(t.scrollLeft=v)});l(h).css("max-height",e);c.bCollapse||l(h).css("height",e);a.nScrollHead=p;a.nScrollBody=h;a.nScrollFoot=t;a.aoDrawCallback.push({fn:Ha,sName:"scrolling"});return k[0]}function Ha(a){var b=a.oScroll,c=b.sX,d=b.sXInner,e=b.sY;b=b.iBarWidth;var h=l(a.nScrollHead),f=h[0].style,g=h.children("div"),k=g[0].style,m=g.children("table");g=a.nScrollBody;var n=l(g),p= +g.style,t=l(a.nScrollFoot).children("div"),v=t.children("table"),x=l(a.nTHead),w=l(a.nTable),r=w[0],C=r.style,G=a.nTFoot?l(a.nTFoot):null,aa=a.oBrowser,L=aa.bScrollOversize;U(a.aoColumns,"nTh");var O=[],I=[],H=[],ea=[],Y,Ba=function(D){D=D.style;D.paddingTop="0";D.paddingBottom="0";D.borderTopWidth="0";D.borderBottomWidth="0";D.height=0};var fa=g.scrollHeight>g.clientHeight;if(a.scrollBarVis!==fa&&a.scrollBarVis!==q)a.scrollBarVis=fa,sa(a);else{a.scrollBarVis=fa;w.children("thead, tfoot").remove(); +if(G){var ba=G.clone().prependTo(w);var la=G.find("tr");ba=ba.find("tr")}var mb=x.clone().prependTo(w);x=x.find("tr");fa=mb.find("tr");mb.find("th, td").removeAttr("tabindex");c||(p.width="100%",h[0].style.width="100%");l.each(Na(a,mb),function(D,W){Y=ta(a,D);W.style.width=a.aoColumns[Y].sWidth});G&&ca(function(D){D.style.width=""},ba);h=w.outerWidth();""===c?(C.width="100%",L&&(w.find("tbody").height()>g.offsetHeight||"scroll"==n.css("overflow-y"))&&(C.width=K(w.outerWidth()-b)),h=w.outerWidth()): +""!==d&&(C.width=K(d),h=w.outerWidth());ca(Ba,fa);ca(function(D){var W=z.getComputedStyle?z.getComputedStyle(D).width:K(l(D).width());H.push(D.innerHTML);O.push(W)},fa);ca(function(D,W){D.style.width=O[W]},x);l(fa).css("height",0);G&&(ca(Ba,ba),ca(function(D){ea.push(D.innerHTML);I.push(K(l(D).css("width")))},ba),ca(function(D,W){D.style.width=I[W]},la),l(ba).height(0));ca(function(D,W){D.innerHTML='
'+H[W]+"
";D.childNodes[0].style.height="0";D.childNodes[0].style.overflow= +"hidden";D.style.width=O[W]},fa);G&&ca(function(D,W){D.innerHTML='
'+ea[W]+"
";D.childNodes[0].style.height="0";D.childNodes[0].style.overflow="hidden";D.style.width=I[W]},ba);Math.round(w.outerWidth())g.offsetHeight||"scroll"==n.css("overflow-y")?h+b:h,L&&(g.scrollHeight>g.offsetHeight||"scroll"==n.css("overflow-y"))&&(C.width=K(la-b)),""!==c&&""===d||da(a,1,"Possible column misalignment",6)):la="100%";p.width=K(la);f.width=K(la); +G&&(a.nScrollFoot.style.width=K(la));!e&&L&&(p.height=K(r.offsetHeight+b));c=w.outerWidth();m[0].style.width=K(c);k.width=K(c);d=w.height()>g.clientHeight||"scroll"==n.css("overflow-y");e="padding"+(aa.bScrollbarLeft?"Left":"Right");k[e]=d?b+"px":"0px";G&&(v[0].style.width=K(c),t[0].style.width=K(c),t[0].style[e]=d?b+"px":"0px");w.children("colgroup").insertBefore(w.children("thead"));n.trigger("scroll");!a.bSorted&&!a.bFiltered||a._drawHold||(g.scrollTop=0)}}function ca(a,b,c){for(var d=0,e=0,h= +b.length,f,g;e").appendTo(g.find("tbody"));g.find("thead, tfoot").remove();g.append(l(a.nTHead).clone()).append(l(a.nTFoot).clone());g.find("tfoot th, tfoot td").css("width","");m=Na(a,g.find("thead")[0]);for(v=0;v").css({width:w.sWidthOrig,margin:0,padding:0,border:0,height:1}));if(a.aoData.length)for(v=0;v").css(h||e?{position:"absolute",top:0,left:0,height:1,right:0,overflow:"hidden"}:{}).append(g).appendTo(p);h&&f?g.width(f):h?(g.css("width","auto"),g.removeAttr("width"),g.width()").css("width",K(a)).appendTo(b||A.body);b=a[0].offsetWidth;a.remove();return b}function $b(a,b){var c= +ac(a,b);if(0>c)return null;var d=a.aoData[c];return d.nTr?d.anCells[b]:l("").html(T(a,c,b,"display"))[0]}function ac(a,b){for(var c,d=-1,e=-1,h=0,f=a.aoData.length;hd&&(d=c.length,e=h);return e}function K(a){return null===a?"0px":"number"==typeof a?0>a?"0px":a+"px":a.match(/\d$/)?a+"px":a}function pa(a){var b=[],c=a.aoColumns;var d=a.aaSortingFixed;var e=l.isPlainObject(d);var h=[];var f=function(n){n.length&& +!Array.isArray(n[0])?h.push(n):l.merge(h,n)};Array.isArray(d)&&f(d);e&&d.pre&&f(d.pre);f(a.aaSorting);e&&d.post&&f(d.post);for(a=0;aG?1:0;if(0!==C)return"asc"===r.dir?C:-C}C=c[n];G=c[p];return CG?1:0}):f.sort(function(n,p){var t,v=g.length,x=e[n]._aSortData,w=e[p]._aSortData;for(t=0;tG?1:0})}a.bSorted=!0}function cc(a){var b=a.aoColumns,c=pa(a);a=a.oLanguage.oAria;for(var d=0,e=b.length;d/g,"");var k=h.nTh;k.removeAttribute("aria-sort");h.bSortable&&(0e?e+1:3))}e= +0;for(h=d.length;ee?e+1:3))}a.aLastSort=d}function bc(a,b){var c=a.aoColumns[b],d=u.ext.order[c.sSortDataType],e;d&&(e=d.call(a.oInstance,a,b,ua(a,b)));for(var h,f=u.ext.type.order[c.sType+"-pre"],g=0,k=a.aoData.length;g=e.length?[0,m[1]]:m)}));b.search!==q&&l.extend(a.oPreviousSearch,Wb(b.search));if(b.columns){f=0;for(d=b.columns.length;f=c&&(b=c-d);b-=b%d;if(-1===d||0>b)b=0;a._iDisplayStart=b}function gb(a,b){a=a.renderer;var c=u.ext.renderer[b];return l.isPlainObject(a)&&a[b]?c[a[b]]||c._:"string"===typeof a?c[a]||c._:c._}function Q(a){return a.oFeatures.bServerSide? +"ssp":a.ajax||a.sAjaxSource?"ajax":"dom"}function Da(a,b){var c=ec.numbers_length,d=Math.floor(c/2);b<=c?a=qa(0,b):a<=d?(a=qa(0,c-2),a.push("ellipsis"),a.push(b-1)):(a>=b-1-d?a=qa(b-(c-2),b):(a=qa(a-d+2,a+d-1),a.push("ellipsis"),a.push(b-1)),a.splice(0,0,"ellipsis"),a.splice(0,0,0));a.DT_el="span";return a}function Xa(a){l.each({num:function(b){return Ua(b,a)},"num-fmt":function(b){return Ua(b,a,rb)},"html-num":function(b){return Ua(b,a,Va)},"html-num-fmt":function(b){return Ua(b,a,Va,rb)}},function(b, +c){M.type.order[b+a+"-pre"]=c;b.match(/^html\-/)&&(M.type.search[b+a]=M.type.search.html)})}function fc(a){return function(){var b=[Ta(this[u.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return u.ext.internal[a].apply(this,b)}}var u=function(a,b){if(this instanceof u)return l(a).DataTable(b);b=a;this.$=function(f,g){return this.api(!0).$(f,g)};this._=function(f,g){return this.api(!0).rows(f,g).data()};this.api=function(f){return f?new B(Ta(this[M.iApiIndex])):new B(this)};this.fnAddData= +function(f,g){var k=this.api(!0);f=Array.isArray(f)&&(Array.isArray(f[0])||l.isPlainObject(f[0]))?k.rows.add(f):k.row.add(f);(g===q||g)&&k.draw();return f.flatten().toArray()};this.fnAdjustColumnSizing=function(f){var g=this.api(!0).columns.adjust(),k=g.settings()[0],m=k.oScroll;f===q||f?g.draw(!1):(""!==m.sX||""!==m.sY)&&Ha(k)};this.fnClearTable=function(f){var g=this.api(!0).clear();(f===q||f)&&g.draw()};this.fnClose=function(f){this.api(!0).row(f).child.hide()};this.fnDeleteRow=function(f,g,k){var m= +this.api(!0);f=m.rows(f);var n=f.settings()[0],p=n.aoData[f[0][0]];f.remove();g&&g.call(this,n,p);(k===q||k)&&m.draw();return p};this.fnDestroy=function(f){this.api(!0).destroy(f)};this.fnDraw=function(f){this.api(!0).draw(f)};this.fnFilter=function(f,g,k,m,n,p){n=this.api(!0);null===g||g===q?n.search(f,k,m,p):n.column(g).search(f,k,m,p);n.draw()};this.fnGetData=function(f,g){var k=this.api(!0);if(f!==q){var m=f.nodeName?f.nodeName.toLowerCase():"";return g!==q||"td"==m||"th"==m?k.cell(f,g).data(): +k.row(f).data()||null}return k.data().toArray()};this.fnGetNodes=function(f){var g=this.api(!0);return f!==q?g.row(f).node():g.rows().nodes().flatten().toArray()};this.fnGetPosition=function(f){var g=this.api(!0),k=f.nodeName.toUpperCase();return"TR"==k?g.row(f).index():"TD"==k||"TH"==k?(f=g.cell(f).index(),[f.row,f.columnVisible,f.column]):null};this.fnIsOpen=function(f){return this.api(!0).row(f).child.isShown()};this.fnOpen=function(f,g,k){return this.api(!0).row(f).child(g,k).show().child()[0]}; +this.fnPageChange=function(f,g){f=this.api(!0).page(f);(g===q||g)&&f.draw(!1)};this.fnSetColumnVis=function(f,g,k){f=this.api(!0).column(f).visible(g);(k===q||k)&&f.columns.adjust().draw()};this.fnSettings=function(){return Ta(this[M.iApiIndex])};this.fnSort=function(f){this.api(!0).order(f).draw()};this.fnSortListener=function(f,g,k){this.api(!0).order.listener(f,g,k)};this.fnUpdate=function(f,g,k,m,n){var p=this.api(!0);k===q||null===k?p.row(g).data(f):p.cell(g,k).data(f);(n===q||n)&&p.columns.adjust(); +(m===q||m)&&p.draw();return 0};this.fnVersionCheck=M.fnVersionCheck;var c=this,d=b===q,e=this.length;d&&(b={});this.oApi=this.internal=M.internal;for(var h in u.ext.internal)h&&(this[h]=fc(h));this.each(function(){var f={},g=1").appendTo(t));r.nTHead=H[0];var ea=t.children("tbody");0===ea.length&&(ea=l("").insertAfter(H));r.nTBody=ea[0];H=t.children("tfoot");0===H.length&&0").appendTo(t));0===H.length||0===H.children().length?t.addClass(C.sNoFooter):0/g,vc=/^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/,wc=/(\/|\.|\*|\+|\?|\||\(|\)|\[|\]|\{|\}|\\|\$|\^|\-)/g,rb=/['\u00A0,$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi,Z=function(a){return a&&!0!==a&&"-"!==a?!1:!0},hc= +function(a){var b=parseInt(a,10);return!isNaN(b)&&isFinite(a)?b:null},ic=function(a,b){sb[b]||(sb[b]=new RegExp(jb(b),"g"));return"string"===typeof a&&"."!==b?a.replace(/\./g,"").replace(sb[b],"."):a},tb=function(a,b,c){var d="string"===typeof a;if(Z(a))return!0;b&&d&&(a=ic(a,b));c&&d&&(a=a.replace(rb,""));return!isNaN(parseFloat(a))&&isFinite(a)},jc=function(a,b,c){return Z(a)?!0:Z(a)||"string"===typeof a?tb(a.replace(Va,""),b,c)?!0:null:null},U=function(a,b,c){var d=[],e=0,h=a.length;if(c!==q)for(;e< +h;e++)a[e]&&a[e][b]&&d.push(a[e][b][c]);else for(;ea.length)){var b=a.slice().sort();for(var c=b[0],d=1,e=b.length;d< +e;d++){if(b[d]===c){b=!1;break a}c=b[d]}}b=!0}if(b)return a.slice();b=[];e=a.length;var h,f=0;d=0;a:for(;d")[0],tc=Qa.textContent!==q,uc=/<.*?>/g,hb=u.util.throttle,nc=[],N=Array.prototype,xc=function(a){var b,c=u.settings,d=l.map(c,function(h,f){return h.nTable});if(a){if(a.nTable&&a.oApi)return[a];if(a.nodeName&&"table"===a.nodeName.toLowerCase()){var e= +l.inArray(a,d);return-1!==e?[c[e]]:null}if(a&&"function"===typeof a.settings)return a.settings().toArray();"string"===typeof a?b=l(a):a instanceof l&&(b=a)}else return[];if(b)return b.map(function(h){e=l.inArray(this,d);return-1!==e?c[e]:null}).toArray()};var B=function(a,b){if(!(this instanceof B))return new B(a,b);var c=[],d=function(f){(f=xc(f))&&c.push.apply(c,f)};if(Array.isArray(a))for(var e=0,h=a.length;ea?new B(b[a],this[a]):null},filter:function(a){var b=[];if(N.filter)b=N.filter.call(this,a,this);else for(var c=0,d=this.length;c").addClass(g),l("td",k).addClass(g).html(f)[0].colSpan=oa(a),e.push(k[0]))};h(c,d);b._details&&b._details.detach();b._details=l(e);b._detailsShow&&b._details.insertAfter(b.nTr)},qc=u.util.throttle(function(a){Ca(a[0])},500),xb=function(a,b){var c=a.context;c.length&&(a=c[0].aoData[b!== +q?b:a[0]])&&a._details&&(a._details.remove(),a._detailsShow=q,a._details=q,l(a.nTr).removeClass("dt-hasChild"),qc(c))},rc=function(a,b){var c=a.context;if(c.length&&a.length){var d=c[0].aoData[a[0]];d._details&&((d._detailsShow=b)?(d._details.insertAfter(d.nTr),l(d.nTr).addClass("dt-hasChild")):(d._details.detach(),l(d.nTr).removeClass("dt-hasChild")),F(c[0],null,"childRow",[b,a.row(a[0])]),Ac(c[0]),qc(c))}},Ac=function(a){var b=new B(a),c=a.aoData;b.off("draw.dt.DT_details column-visibility.dt.DT_details destroy.dt.DT_details"); +0g){var n=l.map(d,function(p,t){return p.bVisible?t:null});return[n[n.length+g]]}return[ta(a,g)];case "name":return l.map(e,function(p,t){return p===m[1]?t:null});default:return[]}if(f.nodeName&&f._DT_CellIndex)return[f._DT_CellIndex.column];g=l(h).filter(f).map(function(){return l.inArray(this,h)}).toArray();if(g.length||!f.nodeName)return g;g=l(f).closest("*[data-dt-column]");return g.length?[g.data("dt-column")]:[]},a,c)}; +y("columns()",function(a,b){a===q?a="":l.isPlainObject(a)&&(b=a,a="");b=vb(b);var c=this.iterator("table",function(d){return Cc(d,a,b)},1);c.selector.cols=a;c.selector.opts=b;return c});J("columns().header()","column().header()",function(a,b){return this.iterator("column",function(c,d){return c.aoColumns[d].nTh},1)});J("columns().footer()","column().footer()",function(a,b){return this.iterator("column",function(c,d){return c.aoColumns[d].nTf},1)});J("columns().data()","column().data()",function(){return this.iterator("column-rows", +sc,1)});J("columns().dataSrc()","column().dataSrc()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].mData},1)});J("columns().cache()","column().cache()",function(a){return this.iterator("column-rows",function(b,c,d,e,h){return Ea(b.aoData,h,"search"===a?"_aFilterData":"_aSortData",c)},1)});J("columns().nodes()","column().nodes()",function(){return this.iterator("column-rows",function(a,b,c,d,e){return Ea(a.aoData,e,"anCells",b)},1)});J("columns().visible()","column().visible()", +function(a,b){var c=this,d=this.iterator("column",function(e,h){if(a===q)return e.aoColumns[h].bVisible;var f=e.aoColumns,g=f[h],k=e.aoData,m;if(a!==q&&g.bVisible!==a){if(a){var n=l.inArray(!0,U(f,"bVisible"),h+1);f=0;for(m=k.length;fd;return!0};u.isDataTable=u.fnIsDataTable=function(a){var b=l(a).get(0),c=!1;if(a instanceof u.Api)return!0;l.each(u.settings,function(d,e){d=e.nScrollHead?l("table",e.nScrollHead)[0]:null;var h=e.nScrollFoot?l("table",e.nScrollFoot)[0]:null;if(e.nTable===b||d===b||h===b)c=!0});return c};u.tables=u.fnTables=function(a){var b= +!1;l.isPlainObject(a)&&(b=a.api,a=a.visible);var c=l.map(u.settings,function(d){if(!a||a&&l(d.nTable).is(":visible"))return d.nTable});return b?new B(c):c};u.camelToHungarian=P;y("$()",function(a,b){b=this.rows(b).nodes();b=l(b);return l([].concat(b.filter(a).toArray(),b.find(a).toArray()))});l.each(["on","one","off"],function(a,b){y(b+"()",function(){var c=Array.prototype.slice.call(arguments);c[0]=l.map(c[0].split(/\s/),function(e){return e.match(/\.dt\b/)?e:e+".dt"}).join(" ");var d=l(this.tables().nodes()); +d[b].apply(d,c);return this})});y("clear()",function(){return this.iterator("table",function(a){Ka(a)})});y("settings()",function(){return new B(this.context,this.context)});y("init()",function(){var a=this.context;return a.length?a[0].oInit:null});y("data()",function(){return this.iterator("table",function(a){return U(a.aoData,"_aData")}).flatten()});y("destroy()",function(a){a=a||!1;return this.iterator("table",function(b){var c=b.nTableWrapper.parentNode,d=b.oClasses,e=b.nTable,h=b.nTBody,f=b.nTHead, +g=b.nTFoot,k=l(e);h=l(h);var m=l(b.nTableWrapper),n=l.map(b.aoData,function(t){return t.nTr}),p;b.bDestroying=!0;F(b,"aoDestroyCallback","destroy",[b]);a||(new B(b)).columns().visible(!0);m.off(".DT").find(":not(tbody *)").off(".DT");l(z).off(".DT-"+b.sInstance);e!=f.parentNode&&(k.children("thead").detach(),k.append(f));g&&e!=g.parentNode&&(k.children("tfoot").detach(),k.append(g));b.aaSorting=[];b.aaSortingFixed=[];Sa(b);l(n).removeClass(b.asStripeClasses.join(" "));l("th, td",f).removeClass(d.sSortable+ +" "+d.sSortableAsc+" "+d.sSortableDesc+" "+d.sSortableNone);h.children().detach();h.append(n);f=a?"remove":"detach";k[f]();m[f]();!a&&c&&(c.insertBefore(e,b.nTableReinsertBefore),k.css("width",b.sDestroyWidth).removeClass(d.sTable),(p=b.asDestroyStripes.length)&&h.children().each(function(t){l(this).addClass(b.asDestroyStripes[t%p])}));c=l.inArray(b,u.settings);-1!==c&&u.settings.splice(c,1)})});l.each(["column","row","cell"],function(a,b){y(b+"s().every()",function(c){var d=this.selector.opts,e= +this;return this.iterator(b,function(h,f,g,k,m){c.call(e[b](f,"cell"===b?g:d,"cell"===b?d:q),f,g,k,m)})})});y("i18n()",function(a,b,c){var d=this.context[0];a=na(a)(d.oLanguage);a===q&&(a=b);c!==q&&l.isPlainObject(a)&&(a=a[c]!==q?a[c]:a._);return a.replace("%d",c)});u.version="1.11.5";u.settings=[];u.models={};u.models.oSearch={bCaseInsensitive:!0,sSearch:"",bRegex:!1,bSmart:!0,"return":!1};u.models.oRow={nTr:null,anCells:null,_aData:[],_aSortData:null,_aFilterData:null,_sFilterRow:null,_sRowStripe:"", +src:null,idx:-1};u.models.oColumn={idx:null,aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bVisible:null,_sManualType:null,_bAttrSrc:!1,fnCreatedCell:null,fnGetData:null,fnSetData:null,mData:null,mRender:null,nTh:null,nTf:null,sClass:null,sContentPadding:null,sDefaultContent:null,sName:null,sSortDataType:"std",sSortingClass:null,sSortingClassJUI:null,sTitle:null,sType:null,sWidth:null,sWidthOrig:null};u.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:[],ajax:null,aLengthMenu:[10, +25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bLengthChange:!0,bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollCollapse:!1,bServerSide:!1,bSort:!0,bSortMulti:!0,bSortCellsTop:!1,bSortClasses:!0,bStateSave:!1,fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,fnFormatNumber:function(a){return a.toString().replace(/\B(?=(\d{3})+(?!\d))/g,this.oLanguage.sThousands)},fnHeaderCallback:null,fnInfoCallback:null, +fnInitComplete:null,fnPreDrawCallback:null,fnRowCallback:null,fnServerData:null,fnServerParams:null,fnStateLoadCallback:function(a){try{return JSON.parse((-1===a.iStateDuration?sessionStorage:localStorage).getItem("DataTables_"+a.sInstance+"_"+location.pathname))}catch(b){return{}}},fnStateLoadParams:null,fnStateLoaded:null,fnStateSaveCallback:function(a,b){try{(-1===a.iStateDuration?sessionStorage:localStorage).setItem("DataTables_"+a.sInstance+"_"+location.pathname,JSON.stringify(b))}catch(c){}}, +fnStateSaveParams:null,iStateDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iTabIndex:0,oClasses:{},oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"},oPaginate:{sFirst:"First",sLast:"Last",sNext:"Next",sPrevious:"Previous"},sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)", +sInfoPostFix:"",sDecimal:"",sThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"Processing...",sSearch:"Search:",sSearchPlaceholder:"",sUrl:"",sZeroRecords:"No matching records found"},oSearch:l.extend({},u.models.oSearch),sAjaxDataProp:"data",sAjaxSource:null,sDom:"lfrtip",searchDelay:null,sPaginationType:"simple_numbers",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET",renderer:null,rowId:"DT_RowId"};E(u.defaults);u.defaults.column={aDataSort:null, +iDataSort:-1,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bVisible:!0,fnCreatedCell:null,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};E(u.defaults.column);u.models.oSettings={oFeatures:{bAutoWidth:null,bDeferRender:null,bFilter:null,bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,bSort:null,bSortMulti:null,bSortClasses:null,bStateSave:null},oScroll:{bCollapse:null, +iBarWidth:0,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1,bScrollbarLeft:!1,bBounding:!1,barWidth:0},ajax:null,aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aIds:{},aoColumns:[],aoHeader:[],aoFooter:[],oPreviousSearch:{},aoPreSearchCols:[],aaSorting:null,aaSortingFixed:[],asStripeClasses:null,asDestroyStripes:[],sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[],aoFooterCallback:[],aoDrawCallback:[],aoRowCreatedCallback:[],aoPreDrawCallback:[], +aoInitComplete:[],aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null,nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,searchDelay:null,sPaginationType:"two_button",iStateDuration:0,aoStateSave:[],aoStateLoad:[],oSavedState:null,oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null,jqXHR:null,json:q,oAjaxData:q,fnServerData:null,aoServerParams:[],sServerMethod:null,fnFormatNumber:null,aLengthMenu:null,iDraw:0, +bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iRecordsTotal:0,_iRecordsDisplay:0,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null,oInit:null,aoDestroyCallback:[],fnRecordsTotal:function(){return"ssp"==Q(this)?1*this._iRecordsTotal:this.aiDisplayMaster.length},fnRecordsDisplay:function(){return"ssp"==Q(this)?1*this._iRecordsDisplay:this.aiDisplay.length},fnDisplayEnd:function(){var a=this._iDisplayLength,b=this._iDisplayStart,c=b+a,d=this.aiDisplay.length,e=this.oFeatures,h= +e.bPaginate;return e.bServerSide?!1===h||-1===a?b+d:Math.min(b+a,this._iRecordsDisplay):!h||c>d||-1===a?d:c},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null,nScrollFoot:null,aLastSort:[],oPlugins:{},rowIdFn:null,rowId:null};u.ext=M={buttons:{},classes:{},builder:"dt/jszip-2.5.0/dt-1.11.5/b-2.2.2/b-colvis-2.2.2/b-html5-2.2.2/b-print-2.2.2/cr-1.5.5/date-1.1.2/fc-4.0.2/fh-3.2.2/kt-2.6.4/r-2.2.9/rg-1.1.4/rr-1.2.8/sc-2.0.5/sb-1.3.2/sp-2.0.0/sl-1.3.4/sr-1.1.0",errMode:"alert",feature:[],search:[],selector:{cell:[],column:[],row:[]},internal:{},legacy:{ajax:null},pager:{},renderer:{pageButton:{},header:{}},order:{},type:{detect:[],search:{},order:{}},_unique:0,fnVersionCheck:u.fnVersionCheck, +iApiIndex:0,oJUIClasses:{},sVersion:u.version};l.extend(M,{afnFiltering:M.search,aTypes:M.type.detect,ofnSearch:M.type.search,oSort:M.type.order,afnSortData:M.order,aoFeatures:M.feature,oApi:M.internal,oStdClasses:M.classes,oPagination:M.pager});l.extend(u.ext.classes,{sTable:"dataTable",sNoFooter:"no-footer",sPageButton:"paginate_button",sPageButtonActive:"current",sPageButtonDisabled:"disabled",sStripeOdd:"odd",sStripeEven:"even",sRowEmpty:"dataTables_empty",sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter", +sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_desc_disabled",sSortableDesc:"sorting_asc_disabled",sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sFilterInput:"",sLengthSelect:"",sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody", +sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sHeaderTH:"",sFooterTH:"",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"",sJUIHeader:"",sJUIFooter:""});var ec=u.ext.pager;l.extend(ec,{simple:function(a,b){return["previous","next"]},full:function(a,b){return["first","previous","next","last"]},numbers:function(a,b){return[Da(a,b)]},simple_numbers:function(a,b){return["previous",Da(a,b),"next"]}, +full_numbers:function(a,b){return["first","previous",Da(a,b),"next","last"]},first_last_numbers:function(a,b){return["first",Da(a,b),"last"]},_numbers:Da,numbers_length:7});l.extend(!0,u.ext.renderer,{pageButton:{_:function(a,b,c,d,e,h){var f=a.oClasses,g=a.oLanguage.oPaginate,k=a.oLanguage.oAria.paginate||{},m,n,p=0,t=function(x,w){var r,C=f.sPageButtonDisabled,G=function(I){Ra(a,I.data.action,!0)};var aa=0;for(r=w.length;aa").appendTo(x); +t(O,L)}else{m=null;n=L;O=a.iTabIndex;switch(L){case "ellipsis":x.append('');break;case "first":m=g.sFirst;0===e&&(O=-1,n+=" "+C);break;case "previous":m=g.sPrevious;0===e&&(O=-1,n+=" "+C);break;case "next":m=g.sNext;if(0===h||e===h-1)O=-1,n+=" "+C;break;case "last":m=g.sLast;if(0===h||e===h-1)O=-1,n+=" "+C;break;default:m=a.fnFormatNumber(L+1),n=e===L?f.sPageButtonActive:""}null!==m&&(O=l("",{"class":f.sPageButton+" "+n,"aria-controls":a.sTableId,"aria-label":k[L], +"data-dt-idx":p,tabindex:O,id:0===c&&"string"===typeof L?a.sTableId+"_"+L:null}).html(m).appendTo(x),ob(O,{action:L},G),p++)}}};try{var v=l(b).find(A.activeElement).data("dt-idx")}catch(x){}t(l(b).empty(),d);v!==q&&l(b).find("[data-dt-idx="+v+"]").trigger("focus")}}});l.extend(u.ext.type.detect,[function(a,b){b=b.oLanguage.sDecimal;return tb(a,b)?"num"+b:null},function(a,b){if(a&&!(a instanceof Date)&&!vc.test(a))return null;b=Date.parse(a);return null!==b&&!isNaN(b)||Z(a)?"date":null},function(a, +b){b=b.oLanguage.sDecimal;return tb(a,b,!0)?"num-fmt"+b:null},function(a,b){b=b.oLanguage.sDecimal;return jc(a,b)?"html-num"+b:null},function(a,b){b=b.oLanguage.sDecimal;return jc(a,b,!0)?"html-num-fmt"+b:null},function(a,b){return Z(a)||"string"===typeof a&&-1!==a.indexOf("<")?"html":null}]);l.extend(u.ext.type.search,{html:function(a){return Z(a)?a:"string"===typeof a?a.replace(gc," ").replace(Va,""):""},string:function(a){return Z(a)?a:"string"===typeof a?a.replace(gc," "):a}});var Ua=function(a, +b,c,d){if(0!==a&&(!a||"-"===a))return-Infinity;b&&(a=ic(a,b));a.replace&&(c&&(a=a.replace(c,"")),d&&(a=a.replace(d,"")));return 1*a};l.extend(M.type.order,{"date-pre":function(a){a=Date.parse(a);return isNaN(a)?-Infinity:a},"html-pre":function(a){return Z(a)?"":a.replace?a.replace(/<.*?>/g,"").toLowerCase():a+""},"string-pre":function(a){return Z(a)?"":"string"===typeof a?a.toLowerCase():a.toString?a.toString():""},"string-asc":function(a,b){return ab?1:0},"string-desc":function(a,b){return a< +b?1:a>b?-1:0}});Xa("");l.extend(!0,u.ext.renderer,{header:{_:function(a,b,c,d){l(a.nTable).on("order.dt.DT",function(e,h,f,g){a===h&&(e=c.idx,b.removeClass(d.sSortAsc+" "+d.sSortDesc).addClass("asc"==g[e]?d.sSortAsc:"desc"==g[e]?d.sSortDesc:c.sSortingClass))})},jqueryui:function(a,b,c,d){l("
").addClass(d.sSortJUIWrapper).append(b.contents()).append(l("").addClass(d.sSortIcon+" "+c.sSortingClassJUI)).appendTo(b);l(a.nTable).on("order.dt.DT",function(e,h,f,g){a===h&&(e=c.idx,b.removeClass(d.sSortAsc+ +" "+d.sSortDesc).addClass("asc"==g[e]?d.sSortAsc:"desc"==g[e]?d.sSortDesc:c.sSortingClass),b.find("span."+d.sSortIcon).removeClass(d.sSortJUIAsc+" "+d.sSortJUIDesc+" "+d.sSortJUI+" "+d.sSortJUIAscAllowed+" "+d.sSortJUIDescAllowed).addClass("asc"==g[e]?d.sSortJUIAsc:"desc"==g[e]?d.sSortJUIDesc:c.sSortingClassJUI))})}}});var yb=function(a){Array.isArray(a)&&(a=a.join(","));return"string"===typeof a?a.replace(/&/g,"&").replace(//g,">").replace(/"/g,"""):a};u.render= +{number:function(a,b,c,d,e){return{display:function(h){if("number"!==typeof h&&"string"!==typeof h)return h;var f=0>h?"-":"",g=parseFloat(h);if(isNaN(g))return yb(h);g=g.toFixed(c);h=Math.abs(g);g=parseInt(h,10);h=c?b+(h-g).toFixed(c).substring(2):"";0===g&&0===parseFloat(h)&&(f="");return f+(d||"")+g.toString().replace(/\B(?=(\d{3})+(?!\d))/g,a)+h+(e||"")}}},text:function(){return{display:yb,filter:yb}}};l.extend(u.ext.internal,{_fnExternApiFunc:fc,_fnBuildAjax:Oa,_fnAjaxUpdate:Gb,_fnAjaxParameters:Pb, +_fnAjaxUpdateDraw:Qb,_fnAjaxDataSrc:za,_fnAddColumn:Ya,_fnColumnOptions:Ga,_fnAdjustColumnSizing:sa,_fnVisibleToColumnIndex:ta,_fnColumnIndexToVisible:ua,_fnVisbleColumns:oa,_fnGetColumns:Ia,_fnColumnTypes:$a,_fnApplyColumnDefs:Db,_fnHungarianMap:E,_fnCamelToHungarian:P,_fnLanguageCompat:ma,_fnBrowserDetect:Bb,_fnAddData:ia,_fnAddTr:Ja,_fnNodeToDataIndex:function(a,b){return b._DT_RowIndex!==q?b._DT_RowIndex:null},_fnNodeToColumnIndex:function(a,b,c){return l.inArray(c,a.aoData[b].anCells)},_fnGetCellData:T, +_fnSetCellData:Eb,_fnSplitObjNotation:cb,_fnGetObjectDataFn:na,_fnSetObjectDataFn:ha,_fnGetDataMaster:db,_fnClearTable:Ka,_fnDeleteIndex:La,_fnInvalidate:va,_fnGetRowElements:bb,_fnCreateTr:ab,_fnBuildHead:Fb,_fnDrawHead:xa,_fnDraw:ja,_fnReDraw:ka,_fnAddOptionsHtml:Ib,_fnDetectHeader:wa,_fnGetUniqueThs:Na,_fnFeatureHtmlFilter:Kb,_fnFilterComplete:ya,_fnFilterCustom:Tb,_fnFilterColumn:Sb,_fnFilter:Rb,_fnFilterCreateSearch:ib,_fnEscapeRegex:jb,_fnFilterData:Ub,_fnFeatureHtmlInfo:Nb,_fnUpdateInfo:Xb, +_fnInfoMacros:Yb,_fnInitialise:Aa,_fnInitComplete:Pa,_fnLengthChange:kb,_fnFeatureHtmlLength:Jb,_fnFeatureHtmlPaginate:Ob,_fnPageChange:Ra,_fnFeatureHtmlProcessing:Lb,_fnProcessingDisplay:V,_fnFeatureHtmlTable:Mb,_fnScrollDraw:Ha,_fnApplyToChildren:ca,_fnCalculateColumnWidths:Za,_fnThrottle:hb,_fnConvertToWidth:Zb,_fnGetWidestNode:$b,_fnGetMaxLenString:ac,_fnStringToCss:K,_fnSortFlatten:pa,_fnSort:Hb,_fnSortAria:cc,_fnSortListener:nb,_fnSortAttachListener:fb,_fnSortingClasses:Sa,_fnSortData:bc,_fnSaveState:Ca, +_fnLoadState:dc,_fnImplementState:pb,_fnSettingsFromNode:Ta,_fnLog:da,_fnMap:X,_fnBindAction:ob,_fnCallbackReg:R,_fnCallbackFire:F,_fnLengthOverflow:lb,_fnRenderer:gb,_fnDataSource:Q,_fnRowAttributes:eb,_fnExtend:qb,_fnCalculateEnd:function(){}});l.fn.dataTable=u;u.$=l;l.fn.dataTableSettings=u.settings;l.fn.dataTableExt=u.ext;l.fn.DataTable=function(a){return l(this).dataTable(a).api()};l.each(u,function(a,b){l.fn.DataTable[a]=b});return u}); + + +/*! + DataTables styling integration + ©2018 SpryMedia Ltd - datatables.net/license +*/ +(function(c){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(a){return c(a,window,document)}):"object"===typeof exports?module.exports=function(a,b){a||(a=window);b&&b.fn.dataTable||(b=require("datatables.net")(a,b).$);return c(b,a,a.document)}:c(jQuery,window,document)})(function(c,a,b,d){return c.fn.dataTable}); + + +/*! + Buttons for DataTables 2.2.2 + ©2016-2022 SpryMedia Ltd - datatables.net/license +*/ +(function(d){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(z){return d(z,window,document)}):"object"===typeof exports?module.exports=function(z,B){z||(z=window);B&&B.fn.dataTable||(B=require("datatables.net")(z,B).$);return d(B,z,z.document)}:d(jQuery,window,document)})(function(d,z,B,p){function I(a,b,c){d.fn.animate?a.stop().fadeIn(b,c):(a.css("display","block"),c&&c.call(a))}function J(a,b,c){d.fn.animate?a.stop().fadeOut(b,c):(a.css("display","none"),c&&c.call(a))} +function L(a,b){a=new u.Api(a);b=b?b:a.init().buttons||u.defaults.buttons;return(new x(a,b)).container()}var u=d.fn.dataTable,O=0,P=0,C=u.ext.buttons,x=function(a,b){if(!(this instanceof x))return function(c){return(new x(c,a)).container()};"undefined"===typeof b&&(b={});!0===b&&(b={});Array.isArray(b)&&(b={buttons:b});this.c=d.extend(!0,{},x.defaults,b);b.buttons&&(this.c.buttons=b.buttons);this.s={dt:new u.Api(a),buttons:[],listenKeys:"",namespace:"dtb"+O++};this.dom={container:d("<"+this.c.dom.container.tag+ +"/>").addClass(this.c.dom.container.className)};this._constructor()};d.extend(x.prototype,{action:function(a,b){a=this._nodeToButton(a);if(b===p)return a.conf.action;a.conf.action=b;return this},active:function(a,b){var c=this._nodeToButton(a);a=this.c.dom.button.active;c=d(c.node);if(b===p)return c.hasClass(a);c.toggleClass(a,b===p?!0:b);return this},add:function(a,b,c){var e=this.s.buttons;if("string"===typeof b){b=b.split("-");var h=this.s;e=0;for(var f=b.length-1;e");k.conf._collection=k.collection;if(k.conf.split)for(var t=0;t'+this.c.dom.splitDropdown.text+""));this._expandButton(k.buttons,k.conf.buttons,k.conf.split,!b,b,f,k.conf)}k.conf.parent=g;n.init&&n.init.call(l.button(k.node),l,d(k.node),n);m++}}}},_buildButton:function(a,b,c,e){var h=this.c.dom.button,f=this.c.dom.buttonLiner,g=this.c.dom.collection,l=this.c.dom.splitCollection,m=this.c.dom.splitDropdownButton, +r=this.s.dt,q=function(w){return"function"===typeof w?w(r,k,a):w};if(a.spacer){var n=d("").addClass("dt-button-spacer "+a.style+" "+h.spacerClass).html(q(a.text));return{conf:a,node:n,inserter:n,buttons:[],inCollection:b,isSplit:c,inSplit:e,collection:null}}!c&&e&&l?h=m:!c&&b&&g.button&&(h=g.button);!c&&e&&l.buttonLiner?f=l.buttonLiner:!c&&b&&g.buttonLiner&&(f=g.buttonLiner);if(a.available&&!a.available(r,a)&&!a.hasOwnProperty("html"))return!1;if(a.hasOwnProperty("html"))var k=d(a.html); +else{var t=function(w,D,F,G){G.action.call(D.button(F),w,D,F,G);d(D.table().node()).triggerHandler("buttons-action.dt",[D.button(F),D,F,G])};g=a.tag||h.tag;var y=a.clickBlurs===p?!0:a.clickBlurs;k=d("<"+g+"/>").addClass(h.className).addClass(e?this.c.dom.splitDropdownButton.className:"").attr("tabindex",this.s.dt.settings()[0].iTabIndex).attr("aria-controls",this.s.dt.table().node().id).on("click.dtb",function(w){w.preventDefault();!k.hasClass(h.disabled)&&a.action&&t(w,r,k,a);y&&k.trigger("blur")}).on("keypress.dtb", +function(w){13===w.keyCode&&(w.preventDefault(),!k.hasClass(h.disabled)&&a.action&&t(w,r,k,a))});"a"===g.toLowerCase()&&k.attr("href","#");"button"===g.toLowerCase()&&k.attr("type","button");f.tag?(g=d("<"+f.tag+"/>").html(q(a.text)).addClass(f.className),"a"===f.tag.toLowerCase()&&g.attr("href","#"),k.append(g)):k.html(q(a.text));!1===a.enabled&&k.addClass(h.disabled);a.className&&k.addClass(a.className);a.titleAttr&&k.attr("title",q(a.titleAttr));a.attr&&k.attr(a.attr);a.namespace||(a.namespace= +".dt-button-"+P++);a.config!==p&&a.config.split&&(a.split=a.config.split)}f=(f=this.c.dom.buttonContainer)&&f.tag?d("<"+f.tag+"/>").addClass(f.className).append(k):k;this._addKey(a);this.c.buttonCreated&&(f=this.c.buttonCreated(a,f));if(c){n=d("
").addClass(this.c.dom.splitWrapper.className);n.append(k);var v=d.extend(a,{text:this.c.dom.splitDropdown.text,className:this.c.dom.splitDropdown.className,closeButton:!1,attr:{"aria-haspopup":!0,"aria-expanded":!1},align:this.c.dom.splitDropdown.align, +splitAlignClass:this.c.dom.splitDropdown.splitAlignClass});this._addKey(v);var E=function(w,D,F,G){C.split.action.call(D.button(d("div.dt-btn-split-wrapper")[0]),w,D,F,G);d(D.table().node()).triggerHandler("buttons-action.dt",[D.button(F),D,F,G]);F.attr("aria-expanded",!0)},A=d('").on("click.dtb",function(w){w.preventDefault();w.stopPropagation(); +A.hasClass(h.disabled)||E(w,r,A,v);y&&A.trigger("blur")}).on("keypress.dtb",function(w){13===w.keyCode&&(w.preventDefault(),A.hasClass(h.disabled)||E(w,r,A,v))});0===a.split.length&&A.addClass("dtb-hide-drop");n.append(A).attr(v.attr)}return{conf:a,node:c?n.get(0):k.get(0),inserter:c?n:f,buttons:[],inCollection:b,isSplit:c,inSplit:e,collection:null}},_nodeToButton:function(a,b){b||(b=this.s.buttons);for(var c=0,e=b.length;c").addClass("dt-button-collection").addClass(f.collectionLayout).addClass(f.splitAlignClass).addClass(e).css("display","none");a=d(a).addClass(f.contentClassName).attr("role","menu").appendTo(m);g.attr("aria-expanded","true");g.parents("body")[0]!== +B.body&&(g=B.body.lastChild);f.popoverTitle?m.prepend('
'+f.popoverTitle+"
"):f.collectionTitle&&m.prepend('
'+f.collectionTitle+"
");f.closeButton&&m.prepend('
x
').addClass("dtb-collection-closeable");I(m.insertAfter(g),f.fade);c=d(b.table().container());var r=m.css("position");if("container"===f.span||"dt-container"===f.align)g=g.parent(),m.css("width",c.width());if("absolute"=== +r){var q=d(g[0].offsetParent);c=g.position();e=g.offset();var n=q.offset(),k=q.position(),t=z.getComputedStyle(q[0]);n.height=q.outerHeight();n.width=q.width()+parseFloat(t.paddingLeft);n.right=n.left+n.width;n.bottom=n.top+n.height;q=c.top+g.outerHeight();var y=c.left;m.css({top:q,left:y});t=z.getComputedStyle(m[0]);var v=m.offset();v.height=m.outerHeight();v.width=m.outerWidth();v.right=v.left+v.width;v.bottom=v.top+v.height;v.marginTop=parseFloat(t.marginTop);v.marginBottom=parseFloat(t.marginBottom); +f.dropup&&(q=c.top-v.height-v.marginTop-v.marginBottom);if("button-right"===f.align||m.hasClass(f.rightAlignClassName))y=c.left-v.width+g.outerWidth();if("dt-container"===f.align||"container"===f.align)yn.width&&(y=n.width-v.width);k.left+y+v.width>d(z).width()&&(y=d(z).width()-v.width-k.left);0>e.left+y&&(y=-e.left);k.top+q+v.height>d(z).height()+d(z).scrollTop()&&(q=c.top-v.height-v.marginTop-v.marginBottom);k.top+qE&&(A=E);m.css("marginTop",-1*A)},r(),d(z).on("resize.dtb-collection",function(){r()});f.background&&x.background(!0,f.backgroundClassName,f.fade,f.backgroundHost||g);d("div.dt-button-background").on("click.dtb-collection",function(){});f.autoClose&&setTimeout(function(){b.on("buttons-action.b-internal",function(E,A,w,D){D[0]!==g[0]&&l()})},0);d(m).trigger("buttons-popover.dt");b.on("destroy",l);setTimeout(function(){h=!1;d("body").on("click.dtb-collection", +function(E){if(!h){var A=d.fn.addBack?"addBack":"andSelf",w=d(E.target).parent()[0];(!d(E.target).parents()[A]().filter(a).length&&!d(w).hasClass("dt-buttons")||d(E.target).hasClass("dt-button-background"))&&l()}}).on("keyup.dtb-collection",function(E){27===E.keyCode&&l()})},0)}}});x.background=function(a,b,c,e){c===p&&(c=400);e||(e=B.body);a?I(d("
").addClass(b).css("display","none").insertAfter(e),c):J(d("div."+b),c,function(){d(this).removeClass(b).remove()})};x.instanceSelector=function(a, +b){if(a===p||null===a)return d.map(b,function(f){return f.inst});var c=[],e=d.map(b,function(f){return f.name}),h=function(f){if(Array.isArray(f))for(var g=0,l=f.length;g)<[^<]*)*<\/script>/gi,"");a=a.replace(//g,"");if(!b||b.stripHtml)a=a.replace(/<[^>]*>/g,"");if(!b||b.trim)a=a.replace(/^\s+|\s+$/g,"");if(!b||b.stripNewlines)a=a.replace(/\n/g," ");if(!b||b.decodeEntities)M.innerHTML=a,a=M.value;return a};x.defaults={buttons:["copy","excel","csv","pdf","print"],name:"main",tabIndex:0,dom:{container:{tag:"div",className:"dt-buttons"},collection:{tag:"div",className:""},button:{tag:"button", +className:"dt-button",active:"active",disabled:"disabled",spacerClass:""},buttonLiner:{tag:"span",className:""},split:{tag:"div",className:"dt-button-split"},splitWrapper:{tag:"div",className:"dt-btn-split-wrapper"},splitDropdown:{tag:"button",text:"▼",className:"dt-btn-split-drop",align:"split-right",splitAlignClass:"dt-button-split-left"},splitDropdownButton:{tag:"button",className:"dt-btn-split-drop-button dt-button"},splitCollection:{tag:"div",className:"dt-button-split-collection"}}}; +x.version="2.2.2";d.extend(C,{collection:{text:function(a){return a.i18n("buttons.collection","Collection")},className:"buttons-collection",closeButton:!1,init:function(a,b,c){b.attr("aria-expanded",!1)},action:function(a,b,c,e){e._collection.parents("body").length?this.popover(!1,e):this.popover(e._collection,e)},attr:{"aria-haspopup":!0}},split:{text:function(a){return a.i18n("buttons.split","Split")},className:"buttons-split",closeButton:!1,init:function(a,b,c){return b.attr("aria-expanded",!1)}, +action:function(a,b,c,e){this.popover(e._collection,e)},attr:{"aria-haspopup":!0}},copy:function(a,b){if(C.copyHtml5)return"copyHtml5"},csv:function(a,b){if(C.csvHtml5&&C.csvHtml5.available(a,b))return"csvHtml5"},excel:function(a,b){if(C.excelHtml5&&C.excelHtml5.available(a,b))return"excelHtml5"},pdf:function(a,b){if(C.pdfHtml5&&C.pdfHtml5.available(a,b))return"pdfHtml5"},pageLength:function(a){a=a.settings()[0].aLengthMenu;var b=[],c=[];if(Array.isArray(a[0]))b=a[0],c=a[1];else for(var e=0;e"+a+"":"";I(d('
').html(a).append(d("
")["string"=== +typeof b?"html":"append"](b)).css("display","none").appendTo("body"));c!==p&&0!==c&&(H=setTimeout(function(){e.buttons.info(!1)},c));this.on("destroy.btn-info",function(){e.buttons.info(!1)});return this});u.Api.register("buttons.exportData()",function(a){if(this.context.length)return Q(new u.Api(this.context[0]),a)});u.Api.register("buttons.exportInfo()",function(a){a||(a={});var b=a;var c="*"===b.filename&&"*"!==b.title&&b.title!==p&&null!==b.title&&""!==b.title?b.title:b.filename;"function"=== +typeof c&&(c=c());c===p||null===c?c=null:(-1!==c.indexOf("*")&&(c=c.replace("*",d("head > title").text()).trim()),c=c.replace(/[^a-zA-Z0-9_\u00A1-\uFFFF\.,\-_ !\(\)]/g,""),(b=K(b.extension))||(b=""),c+=b);b=K(a.title);b=null===b?null:-1!==b.indexOf("*")?b.replace("*",d("head > title").text()||"Exported data"):b;return{filename:c,title:b,messageTop:N(this,a.message||a.messageTop,"top"),messageBottom:N(this,a.messageBottom,"bottom")}});var K=function(a){return null===a||a===p?null:"function"===typeof a? +a():a},N=function(a,b,c){b=K(b);if(null===b)return null;a=d("caption",a.table().container()).eq(0);return"*"===b?a.css("caption-side")!==c?null:a.length?a.text():"":b},M=d(" + +
+ modalState->main = 'notes'; ?> + modalState->one = 'tags'; ?> + modalState->oneText = JText::_('COM_GETBIBLE_TAGS'); ?> + modalState->two = 'sharing'; ?> + modalState->twoText = JText::_('COM_GETBIBLE_SHARE'); ?> + loadTemplate('getbibleappmodalbottom'); ?> +
+
+ diff --git a/site/views/app/tmpl/default_getbibleappsettings.php b/site/views/app/tmpl/default_getbibleappsettings.php new file mode 100644 index 0000000..021fc29 --- /dev/null +++ b/site/views/app/tmpl/default_getbibleappsettings.php @@ -0,0 +1,159 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
+
+
+

+ 'getbible-settings-session-linker', 'label' => JText::_('COM_GETBIBLE_SESSION_KEY'), 'class_other' => 'getbible-linker-guid-input uk-text-center', 'value' => $this->linker['guid']]); ?> +

+

+ + +

+
+
+
+
+
+
+

+

+

+
+
+
+
+

+

+

+
+
+
+
+
+ diff --git a/site/views/app/tmpl/default_getbibleappshare.php b/site/views/app/tmpl/default_getbibleappshare.php new file mode 100644 index 0000000..1b9fe22 --- /dev/null +++ b/site/views/app/tmpl/default_getbibleappshare.php @@ -0,0 +1,425 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
+
+ +
+

chapter->book_name; ?> chapter->chapter; ?>:

+ +
+
+
+
+
+
    +
  • + +
    +
    +
    + + +
    +
    +
    +
    +
    ...
    + +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    + +
    +
    +
    +
  • +
+
+ modalState->main = 'sharing'; ?> + modalState->one = 'notes'; ?> + modalState->oneText = JText::_('COM_GETBIBLE_NOTES'); ?> + modalState->two = 'tags'; ?> + modalState->twoText = JText::_('COM_GETBIBLE_TAGS'); ?> + loadTemplate('getbibleappmodalbottom'); ?> +
+
+ diff --git a/site/views/app/tmpl/default_getbibleapptags.php b/site/views/app/tmpl/default_getbibleapptags.php new file mode 100644 index 0000000..d1ddea8 --- /dev/null +++ b/site/views/app/tmpl/default_getbibleapptags.php @@ -0,0 +1,108 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
+
+ +
+

chapter->book_name; ?> chapter->chapter; ?>:1

+ +
+
+
+
+
+

+
+
+
+

+
+ +
+
+
+
+

+
+ +
+
+
+
+
+

+
+
+

+
+
+
+ modalState->main = 'tags'; ?> + modalState->one = 'notes'; ?> + modalState->oneText = JText::_('COM_GETBIBLE_NOTES'); ?> + modalState->two = 'sharing'; ?> + modalState->twoText = JText::_('COM_GETBIBLE_SHARE'); ?> + loadTemplate('getbibleappmodalbottom'); ?> +
+
+ diff --git a/site/views/app/tmpl/default_getbibleapptopmenu.php b/site/views/app/tmpl/default_getbibleapptopmenu.php new file mode 100644 index 0000000..c6dc5dc --- /dev/null +++ b/site/views/app/tmpl/default_getbibleapptopmenu.php @@ -0,0 +1,59 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +$type = $this->params->get('top_menu_type'); + +if ($type == 2) +{ + $menu_type = 'class="uk-margin-small uk-flex-center" uk-tab '; +} +else +{ + $menu_type = 'class="el-nav uk-margin-small uk-subnav uk-subnav-pill uk-flex-center" '; +} + +?> + diff --git a/site/views/app/tmpl/default_getbibleappword.php b/site/views/app/tmpl/default_getbibleappword.php new file mode 100644 index 0000000..91e4664 --- /dev/null +++ b/site/views/app/tmpl/default_getbibleappword.php @@ -0,0 +1,172 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
+
+ +
+ WORD + ... +
+
+ params->get('activate_search') == 1): ?> + + + params->get('enable_open_ai') == 1 && ($buttons = $this->promptIntegration($this->prompts, [1,3])) !== null): ?> + + escape($button->name); ?> + + +
+
+
+ diff --git a/site/views/app/tmpl/default_getbiblebooks.php b/site/views/app/tmpl/default_getbiblebooks.php new file mode 100644 index 0000000..11c0349 --- /dev/null +++ b/site/views/app/tmpl/default_getbiblebooks.php @@ -0,0 +1,38 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
+ books as $book): ?> +
+
+ nr !== $this->chapter->book_nr): ?> + + name; ?> + + + + name; ?> + + +
+
+ +
diff --git a/site/views/app/tmpl/default_getbiblechapters.php b/site/views/app/tmpl/default_getbiblechapters.php new file mode 100644 index 0000000..b80622b --- /dev/null +++ b/site/views/app/tmpl/default_getbiblechapters.php @@ -0,0 +1,38 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
+ chapters as $chapter): ?> +
+
+ chapter !== $this->chapter->chapter): ?> + + chapter; ?> + + + + chapter; ?> + + +
+
+ +
diff --git a/site/views/app/tmpl/default_getbiblefavouriteverseselector.php b/site/views/app/tmpl/default_getbiblefavouriteverseselector.php new file mode 100644 index 0000000..64685a2 --- /dev/null +++ b/site/views/app/tmpl/default_getbiblefavouriteverseselector.php @@ -0,0 +1,110 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// set content +$options = array_map( function ($item) { + return (object) ['key' => $item->nr, 'value' => $item->name]; +}, $this->books); +$content = ''; +$content .= '

' . JText::_('COM_GETBIBLE_YOU_SHOULD_SELECT_ONE_OF_BYOUR_FAVOURITEB_VERSES') . '

'; +$content .= '

' . JText::_('COM_GETBIBLE_THIS_VERSE_IN_COMBINATION_WITH_YOUR_ISESSION_KEYI_WILL_BE_USED_TO_AUTHENTICATE_YOU_IN_THE_FUTURE') . '

'; +$content .= '
'; +$content .= '
'; +$content .= JLayoutHelper::render('selectbox', ['id' => 'getbible_favourite_book', 'label' => JText::_('COM_GETBIBLE_BOOKS'), 'options' => $options, 'default' => $this->chapter->book_nr]); +$content .= '
'; +$options = array_map( function ($item) { + return (object) ['key' => $item, 'value' => $item]; +}, range(1, 150)); +$content .= '
'; +$content .= JLayoutHelper::render('selectbox', ['id' => 'getbible_favourite_chapter', 'label' => JText::_('COM_GETBIBLE_CHAPTERS'), 'options' => $options, 'default' => $this->chapter->chapter]); +$content .= '
'; +$options = array_map( function ($item) { + return (object) ['key' => $item, 'value' => $item]; +}, range(1, 176)); +$content .= '
'; +$content .= JLayoutHelper::render('selectbox', ['id' => 'getbible_favourite_verse', 'label' => JText::_('COM_GETBIBLE_VERSES'), 'options' => $options, 'default' => (string) $this->verses->first]); +$content .= '
'; +$content .= '
'; +$content .= '

' . JText::_('COM_GETBIBLE_THIS_IS_CURRENTLY_THE_ACTIVE_SESSION_KEY') . '

'; +$content .= '
'; +$content .= JLayoutHelper::render('inputbox', ['id' => 'getbible_favourite_linker', 'class_other' => 'getbible-linker-guid-input uk-text-center', 'label' => JText::_('COM_GETBIBLE_SESSION_KEY'), 'placeholder' => JText::_('COM_GETBIBLE_AUTO_GENERATED')]); +$content .= '
'; +$content .= '

' . JText::_('COM_GETBIBLE_SHOULD_YOU_HAVE_BANOTHER_SESSION_KEYB_FROM_A_PREVIOUS_SESSION') . '
' . JText::_('COM_GETBIBLE_YOU_CAN_ADD_IT_HERE_TO_LOAD_YOUR_PREVIOUS_SESSION') . '

'; + +// set buttons +$buttons = [ + ['name' => JText::_('COM_GETBIBLE_SELECT'), 'onclick' => "activeLinkerAccess();", 'class' => 'uk-button uk-button-default uk-width-2-3'], + ['close' => true, 'name' => JText::_('COM_GETBIBLE_CANCEL'), 'class' => 'uk-button uk-button-danger uk-width-1-3'] +]; + + +?> + 'getbible_favourite_verse_selector', + 'header' => JText::_('COM_GETBIBLE_FAVOURITE_VERSE'), + 'header_class_other' => 'uk-text-center', + 'close' => true, + 'content' => $content, + 'buttons_class' => 'uk-button-group uk-width-1-1', + 'buttons_id' => 'getbible-favourite-buttons', + 'buttons' => $buttons +]); ?> + diff --git a/site/views/app/tmpl/default_getbibleinstallbutton.php b/site/views/app/tmpl/default_getbibleinstallbutton.php new file mode 100644 index 0000000..e76326a --- /dev/null +++ b/site/views/app/tmpl/default_getbibleinstallbutton.php @@ -0,0 +1,170 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +params->get('show_install_button') == 1): ?> +' . $this->totalVerse . ''; ?> +

+ + + + + + diff --git a/site/views/app/tmpl/default_getbibletext.php b/site/views/app/tmpl/default_getbibletext.php new file mode 100644 index 0000000..571e948 --- /dev/null +++ b/site/views/app/tmpl/default_getbibletext.php @@ -0,0 +1,63 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +params->get('previous_next_navigation') == 1): ?> +
+ previous); ?> +
+ +params->get('activate_sharing') == 1 || $this->params->get('activate_search') == 1 || empty($this->item['daily'])): ?> + translation->direction) === 'ltr'): ?> +
+ +
+ + item['daily'])): ?> + + + params->get('activate_search') == 1): ?> + + + params->get('activate_sharing') == 1): ?> + + +
+ +params->get('activate_search') == 1 || ($this->params->get('enable_open_ai') == 1 && !empty($this->prompts))): ?> + loadTemplate('getbibleappword'); ?> + +
+ params->get('show_header') == 1): ?> +
+ chapter->name; ?> +
+ + params->get('verse_per_line') == 1): ?> + loadTemplate('versesunorderedlist'); ?> + + loadTemplate('versesparagraph'); ?> + +
+params->get('previous_next_navigation') == 1): ?> +
+ next); ?> +
+ diff --git a/site/views/app/tmpl/default_getbibletranslations.php b/site/views/app/tmpl/default_getbibletranslations.php new file mode 100644 index 0000000..0cb88b5 --- /dev/null +++ b/site/views/app/tmpl/default_getbibletranslations.php @@ -0,0 +1,38 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
+ translations as $translation): ?> +
+
+ abbreviation !== $this->chapter->abbreviation): ?> + + translation; ?> (abbreviation; ?>) + + + + translation; ?> (abbreviation; ?>) + + +
+
+ +
diff --git a/site/views/app/tmpl/default_versesparagraph.php b/site/views/app/tmpl/default_versesparagraph.php new file mode 100644 index 0000000..3901f30 --- /dev/null +++ b/site/views/app/tmpl/default_versesparagraph.php @@ -0,0 +1,38 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +

+ chapter->html_verses as $verse): ?> + $verse, + 'active' => $this->active, + 'tag' => $this->taggedVerse((int) $verse->verse), + 'selected' => $this->selectedVerse((int) $verse->verse) + ]); + // add note if found + if (($note = $this->getVerseNote((int) $verse->verse)) !== null) + { + echo ' ' . JLayoutHelper::render('getbibleappnotelink', ['number' => $verse->verse, 'note' => $note]); + } + ?> + +

diff --git a/site/views/app/tmpl/default_versesunorderedlist.php b/site/views/app/tmpl/default_versesunorderedlist.php new file mode 100644 index 0000000..d5568f1 --- /dev/null +++ b/site/views/app/tmpl/default_versesunorderedlist.php @@ -0,0 +1,40 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
+
    + chapter->html_verses as $verse): ?> +
  • $verse, + 'active' => $this->active, + 'tag' => $this->taggedVerse((int) $verse->verse), + 'selected' => $this->selectedVerse((int) $verse->verse) + ]); + // add note if found + if (($note = $this->getVerseNote((int) $verse->verse)) !== null) + { + echo '
    ' . JLayoutHelper::render('getbibleappnote', ['number' => $verse->verse, 'note' => $note]); + } + ?>
  • + +
+
diff --git a/site/views/app/tmpl/index.html b/site/views/app/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/site/views/app/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/site/views/app/view.html.php b/site/views/app/view.html.php new file mode 100644 index 0000000..85b33d2 --- /dev/null +++ b/site/views/app/view.html.php @@ -0,0 +1,845 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); +jimport('joomla.application.module.helper'); + +use Joomla\CMS\MVC\View\HtmlView; +use VDM\Joomla\GetBible\Factory; + +/** + * Getbible Html View class for the App + */ +class GetbibleViewApp extends HtmlView +{ + // Overwriting JView display method + function display($tpl = null) + { + // get combined params of both component and menu + $this->app = JFactory::getApplication(); + $this->params = $this->app->getParams(); + $this->menu = $this->app->getMenu()->getActive(); + // get the user object + $this->user = JFactory::getUser(); + // Initialise variables. + $this->item = $this->get('Item'); + $this->chapter = $this->get('Chapter'); + $this->translations = $this->get('Translations'); + $this->books = $this->get('Books'); + $this->chapters = $this->get('Chapters'); + $this->next = $this->get('Next'); + $this->previous = $this->get('Previous'); + $this->translation = $this->get('Translation'); + $this->notes = $this->get('Notes'); + $this->linkernotes = $this->get('LinkerNotes'); + $this->tags = $this->get('Tags'); + $this->taggedverses = $this->get('TaggedVerses'); + $this->prompts = $this->get('Prompts'); + $this->linkertaggedverses = $this->get('LinkerTaggedVerses'); + $this->linkertags = $this->get('LinkerTags'); + if ($this->item) + { + // get the input values + $this->input = $this->app->input; + + // set the linker + $this->linker = $this->getLinker(); + + // merge the system and linker + $this->mergeNotes(); + $this->mergeTags(); + $this->mergeTaggedVerses(); + + // should we not have tags at this point we should not load the tag feature + if (empty($this->tags)) + { + $this->params->set('activate_tags', null); + } + + // build the tab menu + $this->setTabsMenu(); + + if ($this->params->get('activate_search') == 1) + { + // set the search URL + $this->setSearchUrl(); + } + + // set the base URL + $this->setDailyVerseUrl(); + + // set the selected verses + $this->verses = new \stdClass(); + $this->verses->selected = $this->item['verses'] ? $this->getSelectedVerses($this->item['verses']) : null; + $this->verses->first = 1; + $this->verses->last = 2; + if (!empty($this->verses->selected)) + { + $this->verses->first = reset($this->verses->selected); + $this->verses->last = end($this->verses->selected); + } + // set the last verse in the chapter + $this->last_verse = end($this->chapter->verses)->verse; + + $this->active = new \stdClass(); + $this->active->verse = false; + // check if we have activity active + if ($this->params->get('activate_notes') == 1 || $this->params->get('activate_tags') == 1 || $this->params->get('activate_sharing') == 1) + { + $this->active->verse = true; + $this->active->target = ($this->params->get('activate_sharing') == 1) ? 'sharing' : (($this->params->get('activate_tags') == 1) ? 'tags' : 'notes'); + $this->active->tooltip = JText::_('COM_GETBIBLE_OPEN'); + } + + // start the modal state + $this->modalState = new \stdClass(); + } + else + { + $this->tab_name_placeholders = null; + } + + // we get the verse count if we are going to show the install button + if ($this->params->get('show_install_button') == 1) + { + $this->totalVerse = Factory::_('GetBible.Watcher')->totalVerses($this->translation->abbreviation ?? 'kjv'); + } + + // Set the toolbar + $this->addToolBar(); + + // set the document + $this->_prepareDocument(); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode(PHP_EOL, $errors), 500); + } + + parent::display($tpl); + } + + /** + * Set the tabs menu + * + * @return void + * @since 2.0.1 + */ + protected function setTabsMenu() + { + // set the active tab + $this->tab_menu['active_tab'] = $this->input->getWord('tab', 'scripture'); + + // check if we have set this before + if (!isset($this->tab_menu['scripture_icon'])) + { + // set the tab icons + $icon = ($this->params->get('custom_icons') == 1) ? $this->params->get('scripture_icon', 'heart') : 'heart'; + $this->tab_menu['scripture_icon'] = ($this->params->get('show_scripture_icon') == 1) ? ' ' : ''; + $icon = ($this->params->get('custom_icons') == 1) ? $this->params->get('translations_icon', 'world') : 'world'; + $this->tab_menu['translations_icon'] = ($this->params->get('show_translations_icon') == 1) ? ' ' : ''; + $icon = ($this->params->get('custom_icons') == 1) ? $this->params->get('books_icon', 'album') : 'album'; + $this->tab_menu['books_icon'] = ($this->params->get('show_books_icon') == 1) ? ' ' : ''; + $icon = ($this->params->get('custom_icons') == 1) ? $this->params->get('chapters_icon', 'grid') : 'grid'; + $this->tab_menu['chapters_icon'] = ($this->params->get('show_chapters_icon') == 1) ? ' ' : ''; + + // set the tab names + $this->tab_menu['scripture'] = ($this->params->get('show_scripture_tab_text') == 1) ? $this->chapter->name . ' (' . $this->chapter->abbreviation . ')' : ''; + $this->tab_menu['translations'] = ($this->params->get('show_translations_tab_text') == 1) ? '[translations]' : ''; + $this->tab_menu['books'] = ($this->params->get('show_books_tab_text') == 1) ? '[books]' : ''; + $this->tab_menu['chapters'] = ($this->params->get('show_chapters_tab_text') == 1) ? '[chapters]' : ''; + + // use updated tab names + if ($this->params->get('set_default_tab_names') == 1) + { + $this->tab_menu['scripture'] = $this->params->get('scripture_tab') ?? $this->tab_menu['scripture']; + $this->tab_menu['translations'] = $this->params->get('translations_tab') ?? $this->tab_menu['translations']; + $this->tab_menu['books'] = $this->params->get('books_tab') ?? $this->tab_menu['books']; + $this->tab_menu['chapters'] = $this->params->get('chapters_tab') ?? $this->tab_menu['chapters']; + } + + // the dynamic placeholders + $this->tab_name_placeholders = [ + '[translations]' => JText::_('COM_GETBIBLE_TRANSLATIONS'), + '[books]' => JText::_('COM_GETBIBLE_BOOKS'), + '[chapters]' => JText::_('COM_GETBIBLE_CHAPTERS'), + '[details]' => JText::_('COM_GETBIBLE_DETAILS'), + '[settings]' => JText::_('COM_GETBIBLE_SETTINGS'), + '[translation]' => $this->chapter->translation, + '[abbreviation]' => $this->chapter->abbreviation, + '[lang]' => $this->chapter->lang, + '[language]' => $this->chapter->language, + '[book_nr]' => $this->chapter->book_nr, + '[book_name]' => $this->chapter->book_name, + '[chapter]' => $this->chapter->chapter, + '[name]' => $this->chapter->name + ]; + + // we do some placeholder updates for the scripture tab + $this->tab_menu['scripture'] = str_replace( + array_keys($this->tab_name_placeholders), + array_values($this->tab_name_placeholders), + $this->tab_menu['scripture'] + ); + + // we do some placeholder updates for the translations tab + $this->tab_menu['translations'] = str_replace( + array_keys($this->tab_name_placeholders), + array_values($this->tab_name_placeholders), + $this->tab_menu['translations'] + ); + + // we do some placeholder updates for the books tab + $this->tab_menu['books'] = str_replace( + array_keys($this->tab_name_placeholders), + array_values($this->tab_name_placeholders), + $this->tab_menu['books'] + ); + + // we do some placeholder updates for the chapters tab + $this->tab_menu['chapters'] = str_replace( + array_keys($this->tab_name_placeholders), + array_values($this->tab_name_placeholders), + $this->tab_menu['chapters'] + ); + + if ($this->params->get('show_settings') == 1) + { + $icon = ($this->params->get('custom_icons') == 1) ? $this->params->get('settings_icon', 'settings') : 'settings'; + $this->tab_menu['settings_icon'] = ($this->params->get('show_settings_icon') == 1) ? ' ' : ''; + $this->tab_menu['settings'] = ($this->params->get('show_settings_tab_text') == 1) ? $this->params->get('settings_tab') ?? '[settings]' : ''; + // we do some placeholder updates for the settings tab + $this->tab_menu['settings'] = str_replace( + array_keys($this->tab_name_placeholders), + array_values($this->tab_name_placeholders), + $this->tab_menu['settings'] + ); + } + + if ($this->params->get('show_details') == 1) + { + $icon = ($this->params->get('custom_icons') == 1) ? $this->params->get('details_icon', 'info') : 'info'; + $this->tab_menu['details_icon'] = ($this->params->get('show_details_icon') == 1) ? ' ' : ''; + $this->tab_menu['details'] = ($this->params->get('show_details_tab_text') == 1) ? $this->params->get('details_tab') ?? '[details]' : ''; + // we do some placeholder updates for the details tab + $this->tab_menu['details'] = str_replace( + array_keys($this->tab_name_placeholders), + array_values($this->tab_name_placeholders), + $this->tab_menu['details'] + ); + } + } + } + + /** + * Merge system and linker notes + * + * @return void + * @since 2.0.1 + */ + protected function mergeNotes(): void + { + $mergedNotes = []; + + // If $this->notes is an array and is not empty, add its elements to $mergedNotes + if (is_array($this->notes) && $this->notes !== []) + { + foreach ($this->notes as $note) + { + // Use the 'verse' attribute as the key + $mergedNotes[$note->verse] = $note; + } + } + + // If $this->linkernotes is an array and is not empty, add or replace its elements in $mergedNotes + if (is_array($this->linkernotes) && $this->linkernotes !== []) + { + foreach ($this->linkernotes as $note) + { + // If the verse already exists in $mergedNotes, this will replace it + // If it doesn't exist, this will add it + $mergedNotes[$note->verse] = $note; + } + } + + // update the notes array if we have values + if ($mergedNotes !== []) + { + // Reset the keys to be numeric and start from 0 + $this->notes = array_values($mergedNotes); + } + } + + /** + * Merge system and linker tags + * + * @return void + * @since 2.0.1 + */ + protected function mergeTags(): void + { + $mergeTags = []; + + // If $this->tags is an array and is not empty, add its elements to $mergeTags + if (is_array($this->tags) && $this->tags !== []) + { + foreach ($this->tags as $tag) + { + // set the tag url + $tag->url = JRoute::_('index.php?option=com_getbible&view=tag&Itemid=' . $this->params->get('app_menu', 0) . '&guid=' . $tag->guid . '&t=' . $this->translation->abbreviation); + // Use the 'verse' attribute as the key + $mergeTags[$tag->id] = $tag; + } + } + + // If $this->linkertags is an array and is not empty, add or replace its elements in $mergeTags + if (is_array($this->linkertags) && $this->linkertags !== []) + { + foreach ($this->linkertags as $tag) + { + if ($tag->published != 1) + { + // we remove the tag if not published + unset($mergeTags[$tag->id]); + continue; + } + // set the tag url + $tag->url = JRoute::_('index.php?option=com_getbible&view=tag&Itemid=' . $this->params->get('app_menu', 0) . '&guid=' . $tag->guid . '&t=' . $this->translation->abbreviation); + // If the verse already exists in $mergeTags, this will replace it + // If it doesn't exist, this will add it + $mergeTags[$tag->id] = $tag; + } + } + + // update the notes array if we have values + if ($mergeTags !== []) + { + // Reset the keys to be numeric and start from 0 + $this->tags = array_values($mergeTags); + } + } + + /** + * Merge system and linker tagged verses + * + * @return void + * @since 2.0.1 + */ + protected function mergeTaggedVerses(): void + { + $mergeTags = []; + + // If $this->taggedverses is an array and is not empty, add its elements to $mergeTags + if (is_array($this->taggedverses) && $this->taggedverses !== []) + { + foreach ($this->taggedverses as $tag) + { + // we build the key + $key = $tag->tag . '-' . $tag->verse; + // set the tag url + $tag->url = JRoute::_('index.php?option=com_getbible&view=tag&Itemid=' . $this->params->get('app_menu', 0) . '&guid=' . $tag->tag . '&t=' . $this->translation->abbreviation); + // Use the 'verse' attribute as the key + $mergeTags[$key] = $tag; + } + } + + // If $this->linkertaggedverses is an array and is not empty, add or replace its elements in $mergeTags + if (is_array($this->linkertaggedverses) && $this->linkertaggedverses !== []) + { + foreach ($this->linkertaggedverses as $tag) + { + // we build the key + $key = $tag->tag . '-' . $tag->verse; + if ($tag->published != 1) + { + // we remove the tag if not published + unset($mergeTags[$key]); + continue; + } + // set the tag url + $tag->url = JRoute::_('index.php?option=com_getbible&view=tag&Itemid=' . $this->params->get('app_menu', 0) . '&guid=' . $tag->tag . '&t=' . $this->translation->abbreviation); + // If the verse already exists in $mergeTags, this will replace it + // If it doesn't exist, this will add it + $mergeTags[$key] = $tag; + } + } + + // update the notes array if we have values + if ($mergeTags !== []) + { + // Reset the keys to be numeric and start from 0 + $this->taggedverses = array_values($mergeTags); + } + } + + /** + * Set the daily verse url + * + * @return void + * @since 2.0.1 + */ + protected function setDailyVerseUrl() + { + $this->url_daily = JRoute::_('index.php?option=com_getbible&view=app&Itemid=' . $this->params->get('app_menu', 0) . '&t=' . $this->translation->abbreviation); + } + + /** + * Set the search url + * + * @return void + * @since 2.0.1 + */ + protected function setSearchUrl() + { + $words = $this->params->get('search_word', 1); + $match = $this->params->get('search_match', 1); + $case = $this->params->get('search_case', 1); + + // set the current search URL + $this->url_search = JRoute::_('index.php?option=com_getbible&view=search&t=' . $this->translation->abbreviation . '&words=' . $words . '&match=' . $match . '&case=' . $case . '&target=1000'); + } + + /** + * Check if the verse is a selected verse + * + * @param int $number The verse number to check + * + * @return bool True if verse is selected + * @since 2.0.1 + */ + protected function selectedVerse(int $number): bool + { + if ($this->verses->selected && in_array($number, $this->verses->selected)) + { + return true; + } + + return false; + } + + /** + * Check if the verse is a tagged verse + * + * @param int $number The verse number to check + * + * @return int 1 = Active, 0 = no tags, -1 = Inactive + * @since 2.0.1 + */ + protected function taggedVerse(int $number): int + { + // Check the global activation status + if ($this->params->get('activate_tags') != 1) + { + return 0; // Tags are globally inactive + } + + // Check if taggedVerses is a non-empty array + if (!is_array($this->taggedverses) || empty($this->taggedverses)) + { + return -1; // No active tags + } + + // Iterate over taggedVerses to find a match + foreach ($this->taggedverses as $tag) + { + // Check if verse property exists and matches the input number + if (property_exists($tag, 'verse') && is_numeric($tag->verse) && (int) $tag->verse === $number) + { + return 1; // Verse has an active tag active + } + } + + // Verse is inactive if no match is found + return -1; + } + + /** + * Check if the verse has a note + * + * @param int $number The verse number to check + * + * @return string|null True if verse has a note + * @since 2.0.1 + */ + protected function getVerseNote(int $number): ?string + { + if ($this->notes && is_array($this->notes) && $this->notes !== []) + { + foreach ($this->notes as $note) + { + if (isset($note->verse) && is_numeric($note->verse) && (int) $note->verse === $number && + isset($note->note) && strlen($note->note) > 0 && ($this->params->get('activate_notes', 1) == 1)) + { + return $note->note; + } + } + } + + return null; + } + + /** + * Get the selected verses as an array + * + * @param string $verses The string of verses reference + * + * @return array The array of verses + * @since 2.0.1 + */ + protected function getSelectedVerses(string $verses): array + { + $result = []; + + $parts = explode(',', $verses); + foreach ($parts as $part) + { + if (strpos($part, '-') !== false) + { + list($start, $end) = explode('-', $part); + for ($i = (int)$start; $i <= (int)$end; $i++) + { + $result[] = $i; + } + } + else + { + $result[] = (int)$part; + } + } + + return $result; + } + + /** + * Get the targeted integration areas prompts + * + * @param array|null $prompts The array of prompts + * @param array $targets The array targets + * + * @return array|null The targeted prompts + * @since 2.0.1 + */ + protected function promptIntegration($prompts, array $targets): ?array + { + if (is_array($prompts) && $prompts !== [] && $targets !== []) + { + $found = []; + foreach ($prompts as $prompt) + { + if (in_array($prompt->integration, $targets)) + { + $found[] = $prompt; + } + } + + if ($found !== []) + { + return $found; + } + } + + return null; + } + + /** + * Get the Linker Details + * + * @return array The linker array. + * @since 2.0.1 + */ + protected function getLinker(): array + { + return [ + 'guid' => Factory::_('GetBible.Linker')->active(), + 'share' => Factory::_('GetBible.Linker')->share() + ]; + } + + /** + * Prepares the document + */ + protected function _prepareDocument() + { + + // Only load jQuery if needed. (default is true) + if ($this->params->get('add_jquery_framework', 1) == 1) + { + JHtml::_('jquery.framework'); + } + // Load the header checker class. + require_once( JPATH_COMPONENT_SITE.'/helpers/headercheck.php' ); + // Initialize the header checker. + $HeaderCheck = new getbibleHeaderCheck; + + // always load these files. + JHtml::_('stylesheet', "media/com_getbible/nouislider/css/nouislider.min.css", ['version' => 'auto']); + JHtml::_('script', "media/com_getbible/nouislider/js/nouislider.min.js", ['version' => 'auto']); + + // Add View JavaScript File + JHtml::_('script', "components/com_getbible/assets/js/app.js", ['version' => 'auto']); + + // Load uikit options. + $uikit = $this->params->get('uikit_load'); + // Set script size. + $size = $this->params->get('uikit_min'); + // The uikit css. + if ((!$HeaderCheck->css_loaded('uikit.min') || $uikit == 1) && $uikit != 2 && $uikit != 3) + { + JHtml::_('stylesheet', 'media/com_getbible/uikit-v3/css/uikit'.$size.'.css', ['version' => 'auto']); + } + // The uikit js. + if ((!$HeaderCheck->js_loaded('uikit.min') || $uikit == 1) && $uikit != 2 && $uikit != 3) + { + JHtml::_('script', 'media/com_getbible/uikit-v3/js/uikit'.$size.'.js', ['version' => 'auto']); + JHtml::_('script', 'media/com_getbible/uikit-v3/js/uikit-icons'.$size.'.js', ['version' => 'auto']); + } + // load the meta description + if (isset($this->item->metadesc) && $this->item->metadesc) + { + $this->document->setDescription($this->item->metadesc); + } + elseif ($this->params->get('menu-meta_description')) + { + $this->document->setDescription($this->params->get('menu-meta_description')); + } + // load the key words if set + if (isset($this->item->metakey) && $this->item->metakey) + { + $this->document->setMetadata('keywords', $this->item->metakey); + } + elseif ($this->params->get('menu-meta_keywords')) + { + $this->document->setMetadata('keywords', $this->params->get('menu-meta_keywords')); + } + // check the robot params + if (isset($this->item->robots) && $this->item->robots) + { + $this->document->setMetadata('robots', $this->item->robots); + } + elseif ($this->params->get('robots')) + { + $this->document->setMetadata('robots', $this->params->get('robots')); + } + // check if autor is to be set + if (isset($this->item->created_by) && $this->params->get('MetaAuthor') == '1') + { + $this->document->setMetaData('author', $this->item->created_by); + } + // check if metadata is available + if (isset($this->item->metadata) && $this->item->metadata) + { + $mdata = json_decode($this->item->metadata,true); + foreach ($mdata as $k => $v) + { + if ($v) + { + $this->document->setMetadata($k, $v); + } + } + } + // get color + $verse_selected_color = $this->params->get('verse_selected_color', '#4747ff'); + + // get search defaults + $search_words = $this->params->get('search_words', 1); + $search_match = $this->params->get('search_match', 1); + $search_case = $this->params->get('search_case', 1); + + // set the ajax url + $url_ajax = JUri::base() . 'index.php?option=com_getbible&format=json&raw=true&' . JSession::getFormToken() . '=1&task=ajax.'; + + // set some lang + JText::script('COM_GETBIBLE_VIEW_ALL_VERSES_TAGGED'); + // add the document default css file + JHtml::_('stylesheet', 'components/com_getbible/assets/css/app.css', ['version' => 'auto']); + // Set the Custom CSS script to view + $this->document->addStyleDeclaration(" + .getbible-verse-selected { + font-weight: bolder; + color: $verse_selected_color; + } + "); + // Set the Custom JS script to view + $this->document->addScriptDeclaration(" + const UrlAjax = '$url_ajax'; + + const getShareHisWordUrl = (linker, translation, book, chapter) => { + // build share His Word url + return UrlAjax + + 'getShareHisWordUrl&translation=' + translation + + '&linker=' + linker + '&book=' + book + + '&chapter=' + chapter; + }; + + const getCheckValidLinkerUrl = (linker, oldLinker) => { + // build share His Word url + return UrlAjax + + 'checkValidLinker&linker=' + linker + '&old=' + oldLinker; + }; + + const getSearchURL = (search, translation) => { + // build search url + return UrlAjax + + 'getSearchUrl&translation=' + translation + + '&words=$search_words' + '&match=$search_match' + + '&case=$search_case' + '&target=1000' + + '&book=' + 0 + '&search=' + search; + }; + + const getOpenaiURL = (guid, words, verse, chapter, book, translation) => { + // build open ai url + return UrlAjax + + 'getOpenaiURL&translation=' + translation + + '&guid=' + guid + '&book=' + book + + '&chapter=' + chapter + '&verse=' + verse + + '&words=' + words; + }; + + const getSetLinkerURL = (linker) => { + // build set linker url + return UrlAjax + + 'setLinker&linker=' + linker; + }; + + const getSetLinkerAccessURL = (linker, pass, oldPass) => { + // build set linker access url + return UrlAjax + 'setLinkerAccess'; + }; + + const getSetNoteURL = () => { + // build set note url + return UrlAjax + 'setNote'; + }; + + const getSetTagURL = (name) => { + // build create tag url + return UrlAjax + + 'setTag&name=' + name; + }; + + const getTagVerseURL = (translation, book, chapter, verse, tag) => { + // build set tag url + return UrlAjax + + 'tagVerse&translation=' + translation + '&book=' + book + '&chapter=' + chapter + + '&verse=' + verse + '&tag=' + tag; + }; + + const getRemoveTagFromVerseURL = (tag) => { + // build set tag url + return UrlAjax + + 'removeTagFromVerse&tag=' + tag; + }; + + const installBibleChapterURL = (translation, book, chapter) => { + // build load Bible url + return UrlAjax + 'installBibleChapter&translation=' + translation + + '&book=' + book + '&chapter=' + chapter; + }; + "); + } + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('app'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + // now initiate the toolbar + $this->toolbar = JToolbar::getInstance(); + } + + /** + * Get the modules published in a position + */ + public function getModules($position, $seperator = '', $class = '') + { + // set default + $found = false; + // check if we aleady have these modules loaded + if (isset($this->setModules[$position])) + { + $found = true; + } + else + { + // this is where you want to load your module position + $modules = JModuleHelper::getModules($position); + if (GetbibleHelper::checkArray($modules, true)) + { + // set the place holder + $this->setModules[$position] = array(); + foreach($modules as $module) + { + $this->setModules[$position][] = JModuleHelper::renderModule($module); + } + $found = true; + } + } + // check if modules were found + if ($found && isset($this->setModules[$position]) && GetbibleHelper::checkArray($this->setModules[$position])) + { + // set class + if (GetbibleHelper::checkString($class)) + { + $class = ' class="'.$class.'" '; + } + // set seperating return values + switch($seperator) + { + case 'none': + return implode('', $this->setModules[$position]); + break; + case 'div': + return ''.implode('
', $this->setModules[$position]).'
'; + break; + case 'list': + return '
  • '.implode('
  • ', $this->setModules[$position]).'
  • '; + break; + case 'array': + case 'Array': + return $this->setModules[$position]; + break; + default: + return implode('
    ', $this->setModules[$position]); + break; + + } + } + return false; + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var, $sorten = false, $length = 40) + { + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset, $sorten, $length); + } +} diff --git a/site/views/index.html b/site/views/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/site/views/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/site/views/openai/index.html b/site/views/openai/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/site/views/openai/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/site/views/openai/tmpl/default.php b/site/views/openai/tmpl/default.php new file mode 100644 index 0000000..1d750c6 --- /dev/null +++ b/site/views/openai/tmpl/default.php @@ -0,0 +1,37 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + + +?> + +item): ?> + loadTemplate('getbibleai'); ?> + item) > 1) : ?> + loadTemplate('getbibleaifilter'); ?> + + +
    +

    +

    +
    + +params->get('debug') == 1): ?> + loadTemplate('getbibleaidebug'); ?> + diff --git a/site/views/openai/tmpl/default_getbibleai.php b/site/views/openai/tmpl/default_getbibleai.php new file mode 100644 index 0000000..a0b37a0 --- /dev/null +++ b/site/views/openai/tmpl/default_getbibleai.php @@ -0,0 +1,43 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
    +
    +
    +
    +
    + params->get('show_top_menu') == 1): ?> + loadTemplate('getbibleaitopmenu'); ?> + + loadTemplate('getbibleaibody'); ?> + params->get('show_bottom_menu') == 1): ?> + loadTemplate('getbibleaibottommenu'); ?> + +
    + params->get('show_getbible_link') == 1): ?> +
    + loadTemplate('getbibleaifooter'); ?> +
    + +
    +
    +
    +
    diff --git a/site/views/openai/tmpl/default_getbibleaibody.php b/site/views/openai/tmpl/default_getbibleaibody.php new file mode 100644 index 0000000..bff1495 --- /dev/null +++ b/site/views/openai/tmpl/default_getbibleaibody.php @@ -0,0 +1,73 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +$type = $this->params->get('top_menu_type'); +if ($type == 2) +{ + $menu_type = ' uk-card-body'; +} +else +{ + $menu_type = ' uk-card-small'; +} + +$ai_card = ($this->params->get('show_ai_card') == 1) ? 'uk-card uk-card-' . $this->params->get('ai_card_style', 'default') . ' uk-card-body' : 'uk-card' . $menu_type; +$prompt_card = ($this->params->get('show_prompt_card') == 1) ? 'uk-card uk-card-' . $this->params->get('prompt_card_style', 'default') . ' uk-card-body' : 'uk-card' . $menu_type; + +if ($this->params->get('show_prompt_settings', 1) == 1) +{ + $settings_card = ($this->params->get('show_prompt_settings_card') == 1) ? 'uk-card uk-card-' . $this->params->get('prompt_settings_card_style', 'default') . ' uk-card-body' : 'uk-card' . $menu_type; +} + +if ($this->params->get('show_openai_details', 1) == 1) +{ + $details_card = ($this->params->get('show_openai_details_card') == 1) ? 'uk-card uk-card-' . $this->params->get('openai_details_card_style', 'default') . ' uk-card-body' : 'uk-card' . $menu_type; +} + +?> +
      +
    • +
      + loadTemplate('getbibleaimessages'); ?> +
      +
    • +
    • +
      + loadTemplate('getbibleaipromptmessages'); ?> +
      +
    • + params->get('show_prompt_settings', 1) == 1): ?> +
    • +
      + loadTemplate('getbiblepromptsettings'); ?> +
      +
    • + + params->get('show_openai_details', 1) == 1): ?> +
    • +
      + loadTemplate('getbibleaidetails'); ?> +
      +
    • + + params->get('set_custom_ai_tabs') == 1): ?> + loadTemplate('getbibleaicustomtabs'); ?> + +
    diff --git a/site/views/openai/tmpl/default_getbibleaibottommenu.php b/site/views/openai/tmpl/default_getbibleaibottommenu.php new file mode 100644 index 0000000..67cb83e --- /dev/null +++ b/site/views/openai/tmpl/default_getbibleaibottommenu.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +$type = $this->params->get('bottom_menu_type'); + +if ($type == 2) +{ + $menu_type = 'class="uk-margin-small uk-flex-center" uk-tab '; +} +else +{ + $menu_type = 'class="el-nav uk-margin-small uk-subnav uk-subnav-pill uk-flex-center" '; +} + +?> +
      uk-switcher="connect: #get-bible-ai-body; animation: uk-animation-scale-up;"> +
    • + +
    • +
    • + +
    • + params->get('show_prompt_settings', 1) == 1): ?> +
    • + +
    • + + params->get('show_openai_details', 1) == 1): ?> +
    • + +
    • + + params->get('set_custom_ai_tabs') == 1): ?> + loadTemplate('getbibleaicustomtabsmenu'); ?> + +
    diff --git a/site/views/openai/tmpl/default_getbibleaicustomtabs.php b/site/views/openai/tmpl/default_getbibleaicustomtabs.php new file mode 100644 index 0000000..031cdcc --- /dev/null +++ b/site/views/openai/tmpl/default_getbibleaicustomtabs.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); +use VDM\Joomla\Utilities\ObjectHelper; + +$modules = $this->params->get('custom_ai_tabs'); +$tabs = []; +if (ObjectHelper::check($modules)) +{ + foreach ($modules as $module) + { + if (isset($module->position) && strlen($module->position) > 0) + { + if (($content = $this->getModules($module->position, $module->separator ?? '', $module->class ?? '')) !== false) + { + $tabs[$module->position] = $content; + } + else + { + $tabs[$module->position] = JLayoutHelper::render('modulepositionerror', ['position' => $module->position, 'page' => 'GetBible AI']); + } + } + } +} + +$custom_tabs_card = ($this->params->get('show_custom_tabs_card') == 1) ? 'uk-card uk-card-' . $this->params->get('custom_tabs_card_style', 'default') . ' uk-card-body' : ''; + +?> + + +
  • +
    + +
    +
  • + + diff --git a/site/views/openai/tmpl/default_getbibleaicustomtabsmenu.php b/site/views/openai/tmpl/default_getbibleaicustomtabsmenu.php new file mode 100644 index 0000000..fabf1cc --- /dev/null +++ b/site/views/openai/tmpl/default_getbibleaicustomtabsmenu.php @@ -0,0 +1,42 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); +use VDM\Joomla\Utilities\ObjectHelper; + +$modules = $this->params->get('custom_ai_tabs'); +$menus = []; +if (ObjectHelper::check($modules)) +{ + foreach ($modules as $module) + { + if (isset($module->position) && strlen($module->position) > 0) + { + $menus[$module->position] = $this->escape($module->name); + } + } +} + +?> + + +
  • + +
  • + + diff --git a/site/views/openai/tmpl/default_getbibleaidebug.php b/site/views/openai/tmpl/default_getbibleaidebug.php new file mode 100644 index 0000000..298290a --- /dev/null +++ b/site/views/openai/tmpl/default_getbibleaidebug.php @@ -0,0 +1,34 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
    +

    +

    +
      +
    • + +
      +
      +item); ?>
      +
      +
      +
    • +
    diff --git a/site/views/openai/tmpl/default_getbibleaidetails.php b/site/views/openai/tmpl/default_getbibleaidetails.php new file mode 100644 index 0000000..127008f --- /dev/null +++ b/site/views/openai/tmpl/default_getbibleaidetails.php @@ -0,0 +1,28 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
    +item as $response): ?> +
    + +
    + +
    diff --git a/site/views/openai/tmpl/default_getbibleaifilter.php b/site/views/openai/tmpl/default_getbibleaifilter.php new file mode 100644 index 0000000..c188731 --- /dev/null +++ b/site/views/openai/tmpl/default_getbibleaifilter.php @@ -0,0 +1,37 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
      + item as $response): ?> +
    • + +
    • + response_id; + endforeach; + ?> +
    + + diff --git a/site/views/openai/tmpl/default_getbibleaifooter.php b/site/views/openai/tmpl/default_getbibleaifooter.php new file mode 100644 index 0000000..a851187 --- /dev/null +++ b/site/views/openai/tmpl/default_getbibleaifooter.php @@ -0,0 +1,25 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + $this->params->get('show_getbible_link'), + 'logo' => $this->params->get('show_getbible_logo') +]); ?> diff --git a/site/views/openai/tmpl/default_getbibleaimessages.php b/site/views/openai/tmpl/default_getbibleaimessages.php new file mode 100644 index 0000000..a4dd46c --- /dev/null +++ b/site/views/openai/tmpl/default_getbibleaimessages.php @@ -0,0 +1,34 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
    +item as $response): ?> + messages)): ?> + messages as $message): ?> + source == 2): ?> +
    + +
    + + + + +
    diff --git a/site/views/openai/tmpl/default_getbibleaipromptmessages.php b/site/views/openai/tmpl/default_getbibleaipromptmessages.php new file mode 100644 index 0000000..b02a40c --- /dev/null +++ b/site/views/openai/tmpl/default_getbibleaipromptmessages.php @@ -0,0 +1,34 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
    +item as $response): ?> + messages)): ?> + messages as $message): ?> + source == 1): ?> +
    + +
    + + + + +
    diff --git a/site/views/openai/tmpl/default_getbibleaitopmenu.php b/site/views/openai/tmpl/default_getbibleaitopmenu.php new file mode 100644 index 0000000..e7349a8 --- /dev/null +++ b/site/views/openai/tmpl/default_getbibleaitopmenu.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +$type = $this->params->get('top_menu_type'); + +if ($type == 2) +{ + $menu_type = 'class="uk-margin-small uk-flex-center" uk-tab '; +} +else +{ + $menu_type = 'class="el-nav uk-margin-small uk-subnav uk-subnav-pill uk-flex-center" '; +} + +?> +
      uk-switcher="connect: #get-bible-ai-body; animation: uk-animation-scale-up;"> +
    • + +
    • +
    • + +
    • + params->get('show_prompt_settings', 1) == 1): ?> +
    • + +
    • + + params->get('show_openai_details', 1) == 1): ?> +
    • + +
    • + + params->get('set_custom_ai_tabs') == 1): ?> + loadTemplate('getbibleaicustomtabsmenu'); ?> + +
    diff --git a/site/views/openai/tmpl/default_getbiblepromptsettings.php b/site/views/openai/tmpl/default_getbiblepromptsettings.php new file mode 100644 index 0000000..1938e2e --- /dev/null +++ b/site/views/openai/tmpl/default_getbiblepromptsettings.php @@ -0,0 +1,28 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
    +item as $response): ?> +
    + +
    + +
    diff --git a/site/views/openai/tmpl/index.html b/site/views/openai/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/site/views/openai/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/site/views/openai/view.html.php b/site/views/openai/view.html.php new file mode 100644 index 0000000..bc49e22 --- /dev/null +++ b/site/views/openai/view.html.php @@ -0,0 +1,183 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); +jimport('joomla.application.module.helper'); + +use Joomla\CMS\MVC\View\HtmlView; + +/** + * Getbible Html View class for the Openai + */ +class GetbibleViewOpenai extends HtmlView +{ + // Overwriting JView display method + function display($tpl = null) + { + // get combined params of both component and menu + $this->app = JFactory::getApplication(); + $this->params = $this->app->getParams(); + $this->menu = $this->app->getMenu()->getActive(); + // get the user object + $this->user = JFactory::getUser(); + // Initialise variables. + $this->item = $this->get('Item'); + $this->translation = $this->get('Translation'); + + // Set the toolbar + $this->addToolBar(); + + // set the document + $this->_prepareDocument(); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode(PHP_EOL, $errors), 500); + } + + parent::display($tpl); + } + + /** + * Prepares the document + */ + protected function _prepareDocument() + { + + // Only load jQuery if needed. (default is true) + if ($this->params->get('add_jquery_framework', 1) == 1) + { + JHtml::_('jquery.framework'); + } + // Load the header checker class. + require_once( JPATH_COMPONENT_SITE.'/helpers/headercheck.php' ); + // Initialize the header checker. + $HeaderCheck = new getbibleHeaderCheck; + + // Add View JavaScript File + JHtml::_('script', "components/com_getbible/assets/js/openai.js", ['version' => 'auto']); + + // Load uikit options. + $uikit = $this->params->get('uikit_load'); + // Set script size. + $size = $this->params->get('uikit_min'); + // The uikit css. + if ((!$HeaderCheck->css_loaded('uikit.min') || $uikit == 1) && $uikit != 2 && $uikit != 3) + { + JHtml::_('stylesheet', 'media/com_getbible/uikit-v3/css/uikit'.$size.'.css', ['version' => 'auto']); + } + // The uikit js. + if ((!$HeaderCheck->js_loaded('uikit.min') || $uikit == 1) && $uikit != 2 && $uikit != 3) + { + JHtml::_('script', 'media/com_getbible/uikit-v3/js/uikit'.$size.'.js', ['version' => 'auto']); + JHtml::_('script', 'media/com_getbible/uikit-v3/js/uikit-icons'.$size.'.js', ['version' => 'auto']); + } + // add the document default css file + JHtml::_('stylesheet', 'components/com_getbible/assets/css/openai.css', ['version' => 'auto']); + } + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('openai'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + // now initiate the toolbar + $this->toolbar = JToolbar::getInstance(); + } + + /** + * Get the modules published in a position + */ + public function getModules($position, $seperator = '', $class = '') + { + // set default + $found = false; + // check if we aleady have these modules loaded + if (isset($this->setModules[$position])) + { + $found = true; + } + else + { + // this is where you want to load your module position + $modules = JModuleHelper::getModules($position); + if (GetbibleHelper::checkArray($modules, true)) + { + // set the place holder + $this->setModules[$position] = array(); + foreach($modules as $module) + { + $this->setModules[$position][] = JModuleHelper::renderModule($module); + } + $found = true; + } + } + // check if modules were found + if ($found && isset($this->setModules[$position]) && GetbibleHelper::checkArray($this->setModules[$position])) + { + // set class + if (GetbibleHelper::checkString($class)) + { + $class = ' class="'.$class.'" '; + } + // set seperating return values + switch($seperator) + { + case 'none': + return implode('', $this->setModules[$position]); + break; + case 'div': + return ''.implode('
    ', $this->setModules[$position]).'
    '; + break; + case 'list': + return '
  • '.implode('
  • ', $this->setModules[$position]).'
  • '; + break; + case 'array': + case 'Array': + return $this->setModules[$position]; + break; + default: + return implode('
    ', $this->setModules[$position]); + break; + + } + } + return false; + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var, $sorten = false, $length = 40) + { + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset, $sorten, $length); + } +} diff --git a/site/views/search/index.html b/site/views/search/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/site/views/search/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/site/views/search/tmpl/default.php b/site/views/search/tmpl/default.php new file mode 100644 index 0000000..9d4f4d5 --- /dev/null +++ b/site/views/search/tmpl/default.php @@ -0,0 +1,30 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + + +?> + +params->get('activate_search') == 1): ?> + loadTemplate('getbiblesearch'); ?> + +
    +

    +
    + diff --git a/site/views/search/tmpl/default_getbiblesearch.php b/site/views/search/tmpl/default_getbiblesearch.php new file mode 100644 index 0000000..bc1536c --- /dev/null +++ b/site/views/search/tmpl/default_getbiblesearch.php @@ -0,0 +1,34 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +loadTemplate('getbiblesearchinput'); ?> +loadTemplate('getbiblesearchnotenoughverses'); ?> +items): ?> + loadTemplate('getbiblesearchtable'); ?> + +
    + search) > 0): ?> +

    + +

    + +
    + diff --git a/site/views/search/tmpl/default_getbiblesearchbox.php b/site/views/search/tmpl/default_getbiblesearchbox.php new file mode 100644 index 0000000..4c6da9d --- /dev/null +++ b/site/views/search/tmpl/default_getbiblesearchbox.php @@ -0,0 +1,46 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + diff --git a/site/views/search/tmpl/default_getbiblesearchinput.php b/site/views/search/tmpl/default_getbiblesearchinput.php new file mode 100644 index 0000000..8d12a29 --- /dev/null +++ b/site/views/search/tmpl/default_getbiblesearchinput.php @@ -0,0 +1,55 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
    + loadTemplate('getbiblesearchbox'); ?> + loadTemplate('getbiblesearchoptions'); ?> +
    + diff --git a/site/views/search/tmpl/default_getbiblesearchnotenoughverses.php b/site/views/search/tmpl/default_getbiblesearchnotenoughverses.php new file mode 100644 index 0000000..84cad87 --- /dev/null +++ b/site/views/search/tmpl/default_getbiblesearchnotenoughverses.php @@ -0,0 +1,26 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +enoughVerses): ?> +
    +

    translation->translation); ?>

    +
    + diff --git a/site/views/search/tmpl/default_getbiblesearchoptions.php b/site/views/search/tmpl/default_getbiblesearchoptions.php new file mode 100644 index 0000000..387c13d --- /dev/null +++ b/site/views/search/tmpl/default_getbiblesearchoptions.php @@ -0,0 +1,114 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + diff --git a/site/views/search/tmpl/default_getbiblesearchtable.php b/site/views/search/tmpl/default_getbiblesearchtable.php new file mode 100644 index 0000000..f8e5ce2 --- /dev/null +++ b/site/views/search/tmpl/default_getbiblesearchtable.php @@ -0,0 +1,98 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +$table_id = 'getbible_search_result_table'; +$headers = [ + 'abbreviation' => JText::_('COM_GETBIBLE_TRANSLATION'), + 'book_nr' => JText::_('COM_GETBIBLE_BOOK_NUMBER'), + 'name' => JText::_('COM_GETBIBLE_BOOK_NAME'), + 'chapter' => JText::_('COM_GETBIBLE_CHAPTER'), + 'verse' => JText::_('COM_GETBIBLE_VERSE'), + 'text' => JText::_('COM_GETBIBLE_SCRIPTURE') +]; + +?> +items) >= 1000): ?> + + + $table_id, + 'table_class' => 'uk-table uk-table-hover uk-table-striped uk-width-1-1 direction-' . strtolower($this->translation->direction) . '" dir="' . $this->translation->direction . '"', + 'name' => JText::_('COM_GETBIBLE_SEARCH_RESULTS'), + 'headers' => $headers, + 'items' => $this->items, + 'init' => false + ] +); ?> + diff --git a/site/views/search/tmpl/index.html b/site/views/search/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/site/views/search/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/site/views/search/view.html.php b/site/views/search/view.html.php new file mode 100644 index 0000000..752cc51 --- /dev/null +++ b/site/views/search/view.html.php @@ -0,0 +1,224 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; +use VDM\Joomla\GetBible\Factory; + +/** + * Getbible Html View class for the Search + */ +class GetbibleViewSearch extends HtmlView +{ + // Overwriting JView display method + function display($tpl = null) + { + // get combined params of both component and menu + $this->app = JFactory::getApplication(); + $this->params = $this->app->getParams(); + $this->menu = $this->app->getMenu()->getActive(); + // get the user object + $this->user = JFactory::getUser(); + // Initialise variables. + $this->items = $this->get('Items'); + $this->translations = $this->get('Translations'); + $this->books = $this->get('Books'); + $this->translation = $this->get('Translation'); + if ($this->params->get('activate_search') == 1) + { + $this->input = $this->app->input; + + // set the search Params + $this->setSearchParams(); + + // set the enough verses witch + $this->enoughVerses = Factory::_('GetBible.Watcher')->enoughVerses($this->translation->abbreviation ?? 'kjv'); + } + + // Set the toolbar + $this->addToolBar(); + + // set the document + $this->_prepareDocument(); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode(PHP_EOL, $errors), 500); + } + + parent::display($tpl); + } + + /** + * Set the search params + * + * @return void + * @since 2.0.1 + */ + public function setSearchParams() + { + $this->words = $this->input->getInt('words', $this->params->get('search_word', 1)); + $this->match = $this->input->getInt('match', $this->params->get('search_match', 1)); + $this->case = $this->input->getInt('case', $this->params->get('search_case', 1)); + $this->target = $this->input->getInt('target', 1000); + $this->target = ($this->target == 4000) ? $this->input->getInt('book') : $this->target; + $this->search = $this->input->getString('search') ?? $this->input->getString('s') ?? ''; + + // set the value names + $words = [ + 1 => JText::_('COM_GETBIBLE_ALL_WORDS'), + 2 => JText::_('COM_GETBIBLE_ANY_WORDS'), + 3 => JText::_('COM_GETBIBLE_EXACT_WORDS') + ]; + $match = [ + 1 => JText::_('COM_GETBIBLE_EXACT_MATCH'), + 2 => JText::_('COM_GETBIBLE_PARTIAL_MATCH') + ]; + $case = [ + 1 => JText::_('COM_GETBIBLE_CASE_INSENSITIVE'), + 2 => JText::_('COM_GETBIBLE_CASE_SENSITIVE') + ]; + $target = [ + 1000 => JText::_('COM_GETBIBLE_ALL_BOOKS'), + 2000 => JText::_('COM_GETBIBLE_OLD_TESTAMENT'), + 3000 => JText::_('COM_GETBIBLE_NEW_TESTAMENT'), + 4000 => JText::_('COM_GETBIBLE_A_BOOK') + ]; + + $this->options_text = []; + $this->options_text[] = $words[$this->words] ?? JText::_('COM_GETBIBLE_ALL_WORDS'); + $this->options_text[] = $match[$this->match] ?? JText::_('COM_GETBIBLE_EXACT_MATCH'); + $this->options_text[] = $case[$this->case] ?? JText::_('COM_GETBIBLE_CASE_INSENSITIVE'); + $this->options_text[] = $target[$this->target] ?? JText::_('COM_GETBIBLE_A_BOOK'); + + // set the current search URL + $this->url_search = JRoute::_('index.php?option=com_getbible&view=search&t=' . $this->translation->abbreviation . '&words=' . $this->words . '&match=' . $this->match . '&case=' . $this->case . '&target=' . $this->target . '&search=' . $this->search); + $this->url_base = JUri::base(); + $this->url_bible = JRoute::_('index.php?option=com_getbible&view=app&Itemid=' . $this->params->get('app_menu', 0) . '&t=' . $this->translation->abbreviation); + + // referer the referer page + //$referer = $this->input->server->get('HTTP_REFERER', null, 'STRING'); + //if (strpos($referer, $this->url_bible) !== null && strpos($referer, $this->url_base) !== null) + //{ + // $this->url_bible = $referer; // needs more work! + //} + } + + /** + * Prepares the document + */ + protected function _prepareDocument() + { + + // Only load jQuery if needed. (default is true) + if ($this->params->get('add_jquery_framework', 1) == 1) + { + JHtml::_('jquery.framework'); + } + // Load the header checker class. + require_once( JPATH_COMPONENT_SITE.'/helpers/headercheck.php' ); + // Initialize the header checker. + $HeaderCheck = new getbibleHeaderCheck; + + // always load these files. + JHtml::_('stylesheet', "media/com_getbible/datatable/css/datatables.min.css", ['version' => 'auto']); + JHtml::_('script', "media/com_getbible/datatable/js/pdfmake.min.js", ['version' => 'auto']); + JHtml::_('script', "media/com_getbible/datatable/js/vfs_fonts.js", ['version' => 'auto']); + JHtml::_('script', "media/com_getbible/datatable/js/datatables.min.js", ['version' => 'auto']); + + // Add View JavaScript File + JHtml::_('script', "components/com_getbible/assets/js/search.js", ['version' => 'auto']); + + // Load uikit options. + $uikit = $this->params->get('uikit_load'); + // Set script size. + $size = $this->params->get('uikit_min'); + // The uikit css. + if ((!$HeaderCheck->css_loaded('uikit.min') || $uikit == 1) && $uikit != 2 && $uikit != 3) + { + JHtml::_('stylesheet', 'media/com_getbible/uikit-v3/css/uikit'.$size.'.css', ['version' => 'auto']); + } + // The uikit js. + if ((!$HeaderCheck->js_loaded('uikit.min') || $uikit == 1) && $uikit != 2 && $uikit != 3) + { + JHtml::_('script', 'media/com_getbible/uikit-v3/js/uikit'.$size.'.js', ['version' => 'auto']); + JHtml::_('script', 'media/com_getbible/uikit-v3/js/uikit-icons'.$size.'.js', ['version' => 'auto']); + } + $search_found_color = $this->params->get('search_found_color', '#4747ff'); + $table_selection_color = $this->params->get('table_selection_color', '#dfdfdf'); + // add the document default css file + JHtml::_('stylesheet', 'components/com_getbible/assets/css/search.css', ['version' => 'auto']); + // Set the Custom CSS script to view + $this->document->addStyleDeclaration(" + .uk-table tr { + cursor: pointer; + } + .uk-table table.dataTable tbody > tr.selected, .uk-table table.dataTable tbody > tr > .selected { + background-color: $table_selection_color; + } + .uk-table tr.selected td { + background-color: $table_selection_color; + } + .getbible-word-found { + font-weight: bolder; + color: $search_found_color; + } + .direction-rtl { + direction: rtl; + text-align: right; + unicode-bidi: bidi-override; + } + .direction-ltr { + direction: ltr; + text-align: left; + unicode-bidi: bidi-override; + } + "); + } + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('search'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + // now initiate the toolbar + $this->toolbar = JToolbar::getInstance(); + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var, $sorten = false, $length = 40) + { + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset, $sorten, $length); + } +} diff --git a/site/views/tag/index.html b/site/views/tag/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/site/views/tag/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/site/views/tag/tmpl/default.php b/site/views/tag/tmpl/default.php new file mode 100644 index 0000000..b8e1b22 --- /dev/null +++ b/site/views/tag/tmpl/default.php @@ -0,0 +1,38 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + + +?> + +params->get('activate_tags') == 1): ?> + items)): ?> + loadTemplate('getbibletag'); ?> + + loadTemplate('getbiblenotag'); ?> + + +
    +

    +

    +
    + +params->get('debug') == 1): ?> + loadTemplate('getbibletagdebug'); ?> + diff --git a/site/views/tag/tmpl/default_getbiblenotag.php b/site/views/tag/tmpl/default_getbiblenotag.php new file mode 100644 index 0000000..c0a2a9d --- /dev/null +++ b/site/views/tag/tmpl/default_getbiblenotag.php @@ -0,0 +1,43 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
    +
    +
    +
    +
    +

    tag->name ?? JText::_('COM_GETBIBLE_NO_TAG_SELECTED'); ?>

    +

    tag->description ?? ''; ?>

    +
    +

    !

    +

    +
    + loadTemplate('getbibleselecttags'); ?> +
    + params->get('show_getbible_link') == 1): ?> +
    + loadTemplate('getbibletagfooter'); ?> +
    + +
    +
    +
    +
    diff --git a/site/views/tag/tmpl/default_getbibleselecttags.php b/site/views/tag/tmpl/default_getbibleselecttags.php new file mode 100644 index 0000000..73a2547 --- /dev/null +++ b/site/views/tag/tmpl/default_getbibleselecttags.php @@ -0,0 +1,32 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
    + tags as $tag): ?> +
    + tag) && isset($this->tag->guid) && $tag->guid == $this->tag->guid) :?> + + + name; ?> + +
    + +
    diff --git a/site/views/tag/tmpl/default_getbibletag.php b/site/views/tag/tmpl/default_getbibletag.php new file mode 100644 index 0000000..d6f2058 --- /dev/null +++ b/site/views/tag/tmpl/default_getbibletag.php @@ -0,0 +1,43 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
    +
    +
    +
    +
    + params->get('show_top_menu') == 1): ?> + loadTemplate('getbibletagtopmenu'); ?> + + loadTemplate('getbibletagbody'); ?> + params->get('show_bottom_menu') == 1): ?> + loadTemplate('getbibletagbottommenu'); ?> + +
    + params->get('show_getbible_link') == 1): ?> +
    + loadTemplate('getbibletagfooter'); ?> +
    + +
    +
    +
    +
    diff --git a/site/views/tag/tmpl/default_getbibletagbody.php b/site/views/tag/tmpl/default_getbibletagbody.php new file mode 100644 index 0000000..57e4c7c --- /dev/null +++ b/site/views/tag/tmpl/default_getbibletagbody.php @@ -0,0 +1,52 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +$type = $this->params->get('top_menu_type'); +if ($type == 2) +{ + $menu_type = ' uk-card-body'; +} +else +{ + $menu_type = ' uk-card-small'; +} + +$tagged_card = ($this->params->get('show_tagged_card') == 1) ? 'uk-card uk-card-' . $this->params->get('tagged_card_style', 'default') . ' uk-card-body' : 'uk-card' . $menu_type; +$tags_card = ($this->params->get('show_tags_card') == 1) ? 'uk-card uk-card-' . $this->params->get('tags_card_style', 'default') . ' uk-card-body' : 'uk-card' . $menu_type; + +?> +
      +
    • +
      +

      tag->name; ?>

      +

      tag->description; ?>

      + loadTemplate('getbibletagparagraphssorter'); ?> + loadTemplate('getbibletagparagraphs'); ?> +
      +
    • +
    • +
      + loadTemplate('getbibleselecttags'); ?> +
      +
    • + params->get('set_custom_tag_tabs') == 1): ?> + loadTemplate('getbibletagcustomtabs'); ?> + +
    diff --git a/site/views/tag/tmpl/default_getbibletagbottommenu.php b/site/views/tag/tmpl/default_getbibletagbottommenu.php new file mode 100644 index 0000000..1437efa --- /dev/null +++ b/site/views/tag/tmpl/default_getbibletagbottommenu.php @@ -0,0 +1,43 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +$type = $this->params->get('bottom_menu_type'); + +if ($type == 2) +{ + $menu_type = 'class="uk-margin-small uk-flex-center" uk-tab '; +} +else +{ + $menu_type = 'class="el-nav uk-margin-small uk-subnav uk-subnav-pill uk-flex-center" '; +} + +?> +
      uk-switcher="connect: #get-bible-tag-body; animation: uk-animation-scale-up;"> +
    • + +
    • +
    • + +
    • + params->get('set_custom_tag_tabs') == 1): ?> + loadTemplate('getbibletagcustomtabsmenu'); ?> + +
    diff --git a/site/views/tag/tmpl/default_getbibletagcustomtabs.php b/site/views/tag/tmpl/default_getbibletagcustomtabs.php new file mode 100644 index 0000000..85e9fd7 --- /dev/null +++ b/site/views/tag/tmpl/default_getbibletagcustomtabs.php @@ -0,0 +1,53 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); +use VDM\Joomla\Utilities\ObjectHelper; + +$modules = $this->params->get('custom_tag_tabs'); +$tabs = []; +if (ObjectHelper::check($modules)) +{ + foreach ($modules as $module) + { + if (isset($module->position) && strlen($module->position) > 0) + { + if (($content = $this->getModules($module->position, $module->separator ?? '', $module->class ?? '')) !== false) + { + $tabs[$module->position] = $content; + } + else + { + $tabs[$module->position] = JLayoutHelper::render('modulepositionerror', ['position' => $module->position, 'page' => 'GetBible Tag']); + } + } + } +} + +$custom_tabs_card = ($this->params->get('show_custom_tabs_card') == 1) ? 'uk-card uk-card-' . $this->params->get('custom_tabs_card_style', 'default') . ' uk-card-body' : ''; + +?> + + +
  • +
    + +
    +
  • + + diff --git a/site/views/tag/tmpl/default_getbibletagcustomtabsmenu.php b/site/views/tag/tmpl/default_getbibletagcustomtabsmenu.php new file mode 100644 index 0000000..d7910ad --- /dev/null +++ b/site/views/tag/tmpl/default_getbibletagcustomtabsmenu.php @@ -0,0 +1,42 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); +use VDM\Joomla\Utilities\ObjectHelper; + +$modules = $this->params->get('custom_tag_tabs'); +$menus = []; +if (ObjectHelper::check($modules)) +{ + foreach ($modules as $module) + { + if (isset($module->position) && strlen($module->position) > 0) + { + $menus[$module->position] = $this->escape($module->name); + } + } +} + +?> + + +
  • + +
  • + + diff --git a/site/views/tag/tmpl/default_getbibletagdebug.php b/site/views/tag/tmpl/default_getbibletagdebug.php new file mode 100644 index 0000000..6aa4a56 --- /dev/null +++ b/site/views/tag/tmpl/default_getbibletagdebug.php @@ -0,0 +1,34 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
    +

    +

    +
      +
    • + +
      +
      +items); ?>
      +
      +
      +
    • +
    diff --git a/site/views/tag/tmpl/default_getbibletagfooter.php b/site/views/tag/tmpl/default_getbibletagfooter.php new file mode 100644 index 0000000..a851187 --- /dev/null +++ b/site/views/tag/tmpl/default_getbibletagfooter.php @@ -0,0 +1,25 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + $this->params->get('show_getbible_link'), + 'logo' => $this->params->get('show_getbible_logo') +]); ?> diff --git a/site/views/tag/tmpl/default_getbibletagparagraphs.php b/site/views/tag/tmpl/default_getbibletagparagraphs.php new file mode 100644 index 0000000..290c058 --- /dev/null +++ b/site/views/tag/tmpl/default_getbibletagparagraphs.php @@ -0,0 +1,31 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +
    + items as $paragraph): ?> +
    +
    +
    + +
    +books) && is_array($this->books) && count($this->books) > 1): ?> +
    + diff --git a/site/views/tag/tmpl/default_getbibletagparagraphssorter.php b/site/views/tag/tmpl/default_getbibletagparagraphssorter.php new file mode 100644 index 0000000..0435e14 --- /dev/null +++ b/site/views/tag/tmpl/default_getbibletagparagraphssorter.php @@ -0,0 +1,30 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> +books) && is_array($this->books) && count($this->books) > 1): ?> +
    +
      +
    • + books as $key => $name): ?> +
    • + +
    + diff --git a/site/views/tag/tmpl/default_getbibletagtopmenu.php b/site/views/tag/tmpl/default_getbibletagtopmenu.php new file mode 100644 index 0000000..21c0423 --- /dev/null +++ b/site/views/tag/tmpl/default_getbibletagtopmenu.php @@ -0,0 +1,43 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +$type = $this->params->get('top_menu_type'); + +if ($type == 2) +{ + $menu_type = 'class="uk-margin-small uk-flex-center" uk-tab '; +} +else +{ + $menu_type = 'class="el-nav uk-margin-small uk-subnav uk-subnav-pill uk-flex-center" '; +} + +?> +
      uk-switcher="connect: #get-bible-tag-body; animation: uk-animation-scale-up;"> +
    • + +
    • +
    • + +
    • + params->get('set_custom_tag_tabs') == 1): ?> + loadTemplate('getbibletagcustomtabsmenu'); ?> + +
    diff --git a/site/views/tag/tmpl/index.html b/site/views/tag/tmpl/index.html new file mode 100644 index 0000000..fa6d84e --- /dev/null +++ b/site/views/tag/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/site/views/tag/view.html.php b/site/views/tag/view.html.php new file mode 100644 index 0000000..7e9de1e --- /dev/null +++ b/site/views/tag/view.html.php @@ -0,0 +1,338 @@ + + @git Get Bible + @github Get Bible + @support Get Bible + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + +/------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); +jimport('joomla.application.module.helper'); + +use Joomla\CMS\MVC\View\HtmlView; +use VDM\Joomla\GetBible\Factory; + +/** + * Getbible Html View class for the Tag + */ +class GetbibleViewTag extends HtmlView +{ + // Overwriting JView display method + function display($tpl = null) + { + // get combined params of both component and menu + $this->app = JFactory::getApplication(); + $this->params = $this->app->getParams(); + $this->menu = $this->app->getMenu()->getActive(); + // get the user object + $this->user = JFactory::getUser(); + // Initialise variables. + $this->items = $this->get('Items'); + $this->translation = $this->get('Translation'); + $this->tags = $this->get('Tags'); + $this->linkertags = $this->get('LinkerTags'); + $this->tag = $this->get('Tag'); + $this->linkertagged = $this->get('LinkerTagged'); + // should we not have tags at this point we should not load the tag feature + if (empty($this->tags)) + { + $this->params->set('activate_tags', null); + } + else + { + $this->mergeTags(); + } + + // check if we have some tagged verses + if (!empty($this->items) || !empty($this->linkertagged)) + { + // set the linker + $this->linker = $this->getLinker(); + + // merge the system and linker + $this->mergeTaggedVerses(); + + // see if we have any tagged verses left + if (!empty($this->items)) + { + // sort the tagged verses in to paragraphs + $this->items = Factory::_('GetBible.Tagged.Paragraphs')->get($this->items, $this->translation->abbreviation ?? 'kjv'); + + // set sorting books option + $this->setBooks(); + } + } + + // Set the toolbar + $this->addToolBar(); + + // set the document + $this->_prepareDocument(); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode(PHP_EOL, $errors), 500); + } + + parent::display($tpl); + } + + /** + * Merge system and linker tags + * + * @return void + * @since 2.0.1 + */ + protected function mergeTags(): void + { + $mergeTags = []; + + // If $this->tags is an array and is not empty, add its elements to $mergeTags + if (is_array($this->tags) && $this->tags !== []) + { + foreach ($this->tags as $tag) + { + // set the tag url + $tag->url = JRoute::_('index.php?option=com_getbible&view=tag&Itemid=' . $this->params->get('app_menu', 0) . '&guid=' . $tag->guid . '&t=' . $this->translation->abbreviation); + // Use the 'verse' attribute as the key + $mergeTags[$tag->id] = $tag; + } + } + + // If $this->linkertags is an array and is not empty, add or replace its elements in $mergeTags + if (is_array($this->linkertags) && $this->linkertags !== []) + { + foreach ($this->linkertags as $tag) + { + if ($tag->published != 1) + { + // we remove the tag if not published + unset($mergeTags[$tag->id]); + continue; + } + // set the tag url + $tag->url = JRoute::_('index.php?option=com_getbible&view=tag&Itemid=' . $this->params->get('app_menu', 0) . '&guid=' . $tag->guid . '&t=' . $this->translation->abbreviation); + // If the verse already exists in $mergeTags, this will replace it + // If it doesn't exist, this will add it + $mergeTags[$tag->id] = $tag; + } + } + + // update the notes array if we have values + if ($mergeTags !== []) + { + // Reset the keys to be numeric and start from 0 + $this->tags = array_values($mergeTags); + } + } + + /** + * Merge system and linker tagged verses + * + * @return void + * @since 2.0.1 + */ + protected function mergeTaggedVerses(): void + { + $mergeTags = []; + + // If this->items is an array and is not empty, add its elements to $mergeTags + foreach ($this->items as $tag) + { + // we build the key + $key = $tag->book_nr . '-' . $tag->chapter . '-' . $tag->verse . '_' . $tag->tag; + // Use the 'verse' attribute as the key + $mergeTags[$key] = $tag; + } + + // If $this->linkertagged is an array and is not empty, add or replace its elements in $mergeTags + if (is_array($this->linkertagged) && $this->linkertagged !== []) + { + foreach ($this->linkertagged as $tag) + { + // we build the key + $key = $tag->book_nr . '-' . $tag->chapter . '-' . $tag->verse . '_' . $tag->tag; + if ($tag->published != 1) + { + // we remove the tag if not published + unset($mergeTags[$key]); + continue; + } + // If the verse already exists in $mergeTags, this will replace it + // If it doesn't exist, this will add it + $mergeTags[$key] = $tag; + } + } + + // update the notes array if we have values + if ($mergeTags !== []) + { + // Reset the keys to be numeric and start from 0 + $this->items = array_values($mergeTags); + } + } + + /** + * Set the books + * + * @return void + * @since 2.0.1 + */ + protected function setBooks(): void + { + $this->books = []; + if (!empty($this->items)) + { + foreach ($this->items as $item) + { + $this->books[$item['data_book']] = $item['book']; + } + } + } + + /** + * Get the Linker Details + * + * @return array The linker array. + * @since 2.0.1 + */ + protected function getLinker(): array + { + return ['guid' => Factory::_('GetBible.Linker')->active()]; + } + + /** + * Prepares the document + */ + protected function _prepareDocument() + { + + // Only load jQuery if needed. (default is true) + if ($this->params->get('add_jquery_framework', 1) == 1) + { + JHtml::_('jquery.framework'); + } + // Load the header checker class. + require_once( JPATH_COMPONENT_SITE.'/helpers/headercheck.php' ); + // Initialize the header checker. + $HeaderCheck = new getbibleHeaderCheck; + + // Load uikit options. + $uikit = $this->params->get('uikit_load'); + // Set script size. + $size = $this->params->get('uikit_min'); + // The uikit css. + if ((!$HeaderCheck->css_loaded('uikit.min') || $uikit == 1) && $uikit != 2 && $uikit != 3) + { + JHtml::_('stylesheet', 'media/com_getbible/uikit-v3/css/uikit'.$size.'.css', ['version' => 'auto']); + } + // The uikit js. + if ((!$HeaderCheck->js_loaded('uikit.min') || $uikit == 1) && $uikit != 2 && $uikit != 3) + { + JHtml::_('script', 'media/com_getbible/uikit-v3/js/uikit'.$size.'.js', ['version' => 'auto']); + JHtml::_('script', 'media/com_getbible/uikit-v3/js/uikit-icons'.$size.'.js', ['version' => 'auto']); + } + // add the document default css file + JHtml::_('stylesheet', 'components/com_getbible/assets/css/tag.css', ['version' => 'auto']); + } + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + + // set help url for this view if found + $this->help_url = GetbibleHelper::getHelpUrl('tag'); + if (GetbibleHelper::checkString($this->help_url)) + { + JToolbarHelper::help('COM_GETBIBLE_HELP_MANAGER', false, $this->help_url); + } + // now initiate the toolbar + $this->toolbar = JToolbar::getInstance(); + } + + /** + * Get the modules published in a position + */ + public function getModules($position, $seperator = '', $class = '') + { + // set default + $found = false; + // check if we aleady have these modules loaded + if (isset($this->setModules[$position])) + { + $found = true; + } + else + { + // this is where you want to load your module position + $modules = JModuleHelper::getModules($position); + if (GetbibleHelper::checkArray($modules, true)) + { + // set the place holder + $this->setModules[$position] = array(); + foreach($modules as $module) + { + $this->setModules[$position][] = JModuleHelper::renderModule($module); + } + $found = true; + } + } + // check if modules were found + if ($found && isset($this->setModules[$position]) && GetbibleHelper::checkArray($this->setModules[$position])) + { + // set class + if (GetbibleHelper::checkString($class)) + { + $class = ' class="'.$class.'" '; + } + // set seperating return values + switch($seperator) + { + case 'none': + return implode('', $this->setModules[$position]); + break; + case 'div': + return ''.implode('
    ', $this->setModules[$position]).'
    '; + break; + case 'list': + return '
  • '.implode('
  • ', $this->setModules[$position]).'
  • '; + break; + case 'array': + case 'Array': + return $this->setModules[$position]; + break; + default: + return implode('
    ', $this->setModules[$position]); + break; + + } + } + return false; + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var, $sorten = false, $length = 40) + { + // use the helper htmlEscape method instead. + return GetbibleHelper::htmlEscape($var, $this->_charset, $sorten, $length); + } +} diff --git a/update_server.xml b/update_server.xml new file mode 100644 index 0000000..f7b2d69 --- /dev/null +++ b/update_server.xml @@ -0,0 +1,20 @@ + + + Get Bible + The Bible for Joomla + pkg_getbible + package + site + 2.0.1 + https://getbible.net + + https://git.vdm.dev/api/v1/repos/getBible/joomla-pkg/archive/v2.0.1.zip + + + stable + + Llewellyn van der Merwe + https://getbible.net + + + \ No newline at end of file