├── .gitignore ├── README.md ├── assets ├── plugins │ └── simplegallery │ │ ├── .htaccess │ │ ├── ajax.php │ │ ├── css │ │ ├── simplegallery.css │ │ └── styles.json │ │ ├── js │ │ ├── _custom.json │ │ ├── empty.json │ │ ├── lang │ │ │ ├── de.js │ │ │ ├── en.js │ │ │ ├── es.js │ │ │ ├── nl.js │ │ │ ├── pl.js │ │ │ └── ru.js │ │ ├── plugin │ │ │ ├── editrte.js │ │ │ └── simplegallery.js │ │ ├── scripts.json │ │ └── tpl │ │ │ ├── editForm.handlebars │ │ │ ├── moveForm.handlebars │ │ │ ├── preview.handlebars │ │ │ ├── readme.txt │ │ │ ├── refreshForm.handlebars │ │ │ ├── rteForm.handlebars │ │ │ ├── rteForm.js │ │ │ └── templates.js │ │ ├── lib │ │ ├── controller.class.php │ │ ├── plugin.class.php │ │ └── table.class.php │ │ ├── plugin.sgthumb.php │ │ ├── plugin.simplegallery.php │ │ └── tpl │ │ ├── empty.tpl │ │ └── simplegallery.tpl └── snippets │ └── simplegallery │ ├── config │ └── sgLister.json │ ├── controller │ └── sg_site_content.php │ ├── sgController.php │ ├── sgLister.php │ └── sgThumb.php └── install └── assets ├── plugins ├── sgThumb.tpl └── simplegallery.tpl └── snippets ├── sgController.tpl ├── sgLister.tpl └── sgThumb.tpl /.gitignore: -------------------------------------------------------------------------------- 1 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 2 | 3 | *.iml 4 | 5 | ## Directory-based project format: 6 | .idea/ 7 | # if you remove the above rule, at least ignore the following: 8 | 9 | # User-specific stuff: 10 | # .idea/workspace.xml 11 | # .idea/tasks.xml 12 | # .idea/dictionaries 13 | 14 | # Sensitive or high-churn files: 15 | # .idea/dataSources.ids 16 | # .idea/dataSources.xml 17 | # .idea/sqlDataSources.xml 18 | # .idea/dynamic.xml 19 | # .idea/uiDesigner.xml 20 | 21 | # Gradle: 22 | # .idea/gradle.xml 23 | # .idea/libraries 24 | 25 | # Mongo Explorer plugin: 26 | # .idea/mongoSettings.xml 27 | 28 | ## File-based project format: 29 | *.ipr 30 | *.iws 31 | 32 | ## Plugin-specific files: 33 | 34 | # IntelliJ 35 | out/ 36 | 37 | # mpeltonen/sbt-idea plugin 38 | .idea_modules/ 39 | 40 | # JIRA plugin 41 | atlassian-ide-plugin.xml 42 | 43 | # Crashlytics plugin (for Android Studio and IntelliJ) 44 | com_crashlytics_export_strings.xml 45 | crashlytics.properties 46 | crashlytics-build.properties -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SimpleGallery 2 | ============= 3 | 4 | Evolution CMS plugin to manage images. 5 | 6 | ## Dependencies 7 | 8 | - DocLister 9 | 10 | ## Installation 11 | 12 | 1. If DocLister snippet is not installed, install it from Extras. 13 | 2. Install SimpleGallery package from Extras. 14 | 15 | ## Documentation 16 | 17 | http://docs.evo.im/en/04_extras/simplegallery.html 18 | 19 | ## Screenshots 20 | 21 | ![screenshot_1](https://user-images.githubusercontent.com/10888055/38867603-bd71022c-4244-11e8-833e-c092de77c368.png) 22 | 23 | ![screenshot_2](https://user-images.githubusercontent.com/10888055/38867604-bd90faaa-4244-11e8-8c87-7829571b3449.png) 24 | 25 | ![screenshot_3](https://user-images.githubusercontent.com/10888055/38867605-bdacc4d8-4244-11e8-88ea-83533a00d452.png) 26 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/.htaccess: -------------------------------------------------------------------------------- 1 | IndexIgnore */* 2 | 3 | Order Deny,Allow 4 | Deny from all 5 | 6 | 7 | Allow from All 8 | 9 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/ajax.php: -------------------------------------------------------------------------------- 1 | db->connect(); 7 | if (empty ($modx->config)) { 8 | $modx->getSettings(); 9 | } 10 | if(!isset($_SESSION['mgrValidated'])){ 11 | die(); 12 | } 13 | $modx->invokeEvent('OnManagerPageInit',array('invokedBy'=>'SimpleGallery')); 14 | if (isset($modx->pluginCache['SimpleGalleryProps'])) { 15 | $modx->event->params = $modx->parseProperties($modx->pluginCache['SimpleGalleryProps'],'SimpleGallery','plugin'); 16 | } else { 17 | die(); 18 | } 19 | $params = $modx->event->params; 20 | 21 | $roles = isset($params['role']) ? explode(',',$params['role']) : false; 22 | if ($roles && !in_array($_SESSION['mgrRole'], $roles)) die(); 23 | 24 | $mode = (isset($_REQUEST['mode']) && is_scalar($_REQUEST['mode'])) ? $_REQUEST['mode'] : null; 25 | $out = null; 26 | $controllerClass = isset($modx->event->params['controller']) ? $modx->event->params['controller'] : ''; 27 | if (empty($controllerClass) || !class_exists($controllerClass)) { 28 | require_once (MODX_BASE_PATH . 'assets/plugins/simplegallery/lib/controller.class.php'); 29 | $controllerClass = '\SimpleGallery\sgController'; 30 | } 31 | $controller = new $controllerClass($modx); 32 | if($controller instanceof \SimpleTab\AbstractController){ 33 | if (!empty($mode) && method_exists($controller, $mode)) { 34 | $out = call_user_func_array(array($controller, $mode), array()); 35 | }else{ 36 | $out = call_user_func_array(array($controller, 'listing'), array()); 37 | } 38 | $controller->callExit(); 39 | } 40 | echo ($out = is_array($out) ? json_encode($out) : $out); -------------------------------------------------------------------------------- /assets/plugins/simplegallery/css/simplegallery.css: -------------------------------------------------------------------------------- 1 | .btn-left { 2 | display:inline-block; 3 | } 4 | .btn-right { 5 | float: right; 6 | margin-left: 10px; 7 | } 8 | #sg_pages { 9 | margin-top:20px; 10 | background:#efefef; 11 | border:1px solid #ccc; 12 | } 13 | #sg_images { 14 | margin:20px 0; 15 | } 16 | .sg_image { 17 | display:inline-block; 18 | border:1px solid #ccc; 19 | margin:0 13px 13px 0; 20 | padding:5px; 21 | border-radius: 5px; 22 | background: none; 23 | position:relative; 24 | box-sizing: content-box; 25 | } 26 | .sg_image:hover { 27 | background: #ddebf8; 28 | } 29 | .sg_image .img { 30 | background-color:#fff; 31 | background-position: center center; 32 | background-repeat: no-repeat; 33 | } 34 | .selected,.selected:hover { 35 | background: #5b9bda; 36 | } 37 | .sg_image .name { 38 | font-weight: bold; 39 | height: 32px; 40 | margin-top: 5px; 41 | overflow: hidden; 42 | text-align: center; 43 | font-size:11px; 44 | font-family:Tahoma,Verdana,Arial,sans-serif; 45 | text-overflow: ellipsis; 46 | } 47 | .sg_image .notactive { 48 | color:red; 49 | font-style: italic; 50 | } 51 | .sg_image .del, .sg_image .edit { 52 | display: inline-block; 53 | position: absolute; 54 | } 55 | .sg_image .del { 56 | top:-8px; 57 | right:-8px; 58 | color:red; 59 | font-size:16px; 60 | } 61 | .sg_image .edit { 62 | color: #ffcc00; 63 | left:10px; 64 | top:10px; 65 | text-shadow: 1px 1px 0 #000, -1px -1px 0 #000,1px -1px 0 #000, -1px 1px 0 #000; 66 | } 67 | .sg_image a { 68 | opacity:.8; 69 | } 70 | .sg_image a:hover { 71 | opacity: 1; 72 | } 73 | .sortable-ghost { 74 | opacity: .2; 75 | cursor: move; 76 | } 77 | #sgEdit img { 78 | max-width: 100%; 79 | max-height: 210px; 80 | } 81 | #sgEdit .sgRow { 82 | width: 300px; 83 | float:left; 84 | } 85 | #sgEdit .sgRow > div { 86 | padding:10px; 87 | } 88 | #sgEdit table { 89 | width:100%; 90 | word-break: break-all; 91 | } 92 | #sgEdit table td { 93 | padding:0 5px; 94 | vertical-align: top; 95 | } 96 | #sgEdit table td.rowTitle { 97 | font-weight: bold; 98 | text-align: right; 99 | width:70px; 100 | } 101 | .sgForm label { 102 | display: block; 103 | margin:3px 0; 104 | font-weight: bold; 105 | } 106 | .sgForm input[type="text"], .sgForm textarea { 107 | width:270px; 108 | padding:4px; 109 | margin-bottom:5px; 110 | } 111 | .sgForm input[type="checkbox"] { 112 | vertical-align: bottom; 113 | } 114 | .sgForm textarea { 115 | height:112px; 116 | } 117 | #sgRefresh, #sgMove { 118 | padding:10px; 119 | } 120 | #sgRefreshTpls { 121 | padding:0 0 10px; 122 | } 123 | #sgRefresh .group, #sgMove form { 124 | margin-bottom:15px; 125 | } 126 | #sgRefresh .elements { 127 | display:none; 128 | } 129 | #sgRefresh label { 130 | display:block; 131 | margin-bottom:5px; 132 | } 133 | #sgRefresh .templates label { 134 | display: inline-block; 135 | width:200px; 136 | } 137 | #sgRefresh input[type="checkbox"] { 138 | vertical-align: bottom; 139 | } 140 | #sgRefresh input[name="ids"] { 141 | width:100%; 142 | } 143 | .btn-red { 144 | color:red; 145 | } 146 | .btn-green { 147 | color:green; 148 | } 149 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/css/styles.json: -------------------------------------------------------------------------------- 1 | { 2 | "styles": { 3 | "EasyUIMODX" : { 4 | "version":"1.5.2", 5 | "src":"assets/js/easy-ui/themes/modx/easyui.css" 6 | }, 7 | "EUIUploaderCss" : { 8 | "version":"1.2.0", 9 | "src":"assets/js/euiuploader/css/euiuploader.css" 10 | }, 11 | "SimpleGalleryCss" : { 12 | "version":"1.2.0", 13 | "src":"assets/plugins/simplegallery/css/simplegallery.css" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/js/_custom.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "TinyMCE4": { 4 | "version":"4.3.6", 5 | "src":"assets/plugins/tinymce4/tinymce/tinymce.min.js" 6 | }, 7 | "rteForm" : { 8 | "version":"1.4.1", 9 | "src":"assets/plugins/simplegallery/js/tpl/rteForm.js" 10 | }, 11 | "editrte":{ 12 | "version":"1.4.1", 13 | "src":"assets/plugins/simplegallery/js/plugin/editrte.js" 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /assets/plugins/simplegallery/js/empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "sg-lang-en":{ 4 | "version":"1.0.0", 5 | "src":"assets/plugins/simplegallery/js/lang/en.js" 6 | }, 7 | "sg-lang-[+lang+]":{ 8 | "version":"1.0.0", 9 | "src":"assets/plugins/simplegallery/js/lang/[+lang+].js" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/js/lang/de.js: -------------------------------------------------------------------------------- 1 | _sgLang['cancel'] = 'Abbrechen'; 2 | _sgLang['from'] = 'von'; 3 | _sgLang['close'] = 'Schließen'; 4 | _sgLang['file'] = 'Datei'; 5 | _sgLang['size'] = 'Größe'; 6 | _sgLang['delete'] = 'Löschen'; 7 | _sgLang['are_you_sure_to_delete'] = 'Das Bild wirklich löschen?'; 8 | _sgLang['error'] = 'Fehler'; 9 | _sgLang['delete_fail'] = 'Fehler beim Löschen.'; 10 | _sgLang['are_you_sure_to_delete_many'] = 'Ausgewählte Bilder wirklich löschen?'; 11 | _sgLang['createdon'] = 'Erstellt am'; 12 | _sgLang['title'] = 'Titel'; 13 | _sgLang['description'] = 'Beschreibung'; 14 | _sgLang['add'] = 'Additional'; 15 | _sgLang['show'] = 'Zeigen'; 16 | _sgLang['yes'] = 'Ja'; 17 | _sgLang['save'] = 'Speichern'; 18 | _sgLang['save_fail'] = 'Fehler beim Speichern.'; 19 | _sgLang['refresh_previews'] = 'Vorschauen erneuern'; 20 | _sgLang['are_you_sure_to_refresh'] = 'Dies kann lange dauern. Wirklich fortfahren?'; 21 | _sgLang['emptydesc'] = 'Bild-Beschreibung ist leer. Zum Bearbeiten anklicken.'; 22 | _sgLang['continue'] = 'Fortfahren'; 23 | _sgLang['refresh_current'] = 'Aktuelle Galerie erneuern'; 24 | _sgLang['refresh_ids'] = 'Erneuern anhand der ID'; 25 | _sgLang['refresh_tpls'] = 'Erneuern anhand des Templates'; 26 | _sgLang['refresh_fail'] = 'Fehler bei Erneuern der Vorschauen.'; 27 | _sgLang['move'] = 'Verschieben'; 28 | _sgLang['are_you_sure_to_move'] = 'Ausgewählte Bilder wirklich verschieben?'; 29 | _sgLang['move_fail'] = 'Fehler beim Verschieben.'; 30 | _sgLang['select_resource_id'] = 'ID des Dokuments auswählen:'; 31 | _sgLang['save_document_to_continue'] = 'Dokument speichern, um mit der Galerie zu arbeiten.'; 32 | _sgLang['server_error'] = 'Server-Fehler: '; 33 | _sgLang['parse_error'] = 'Fehler bei der Verarbeitung'; -------------------------------------------------------------------------------- /assets/plugins/simplegallery/js/lang/en.js: -------------------------------------------------------------------------------- 1 | _sgLang = []; 2 | _sgLang['cancel'] = 'Cancel'; 3 | _sgLang['from'] = 'from'; 4 | _sgLang['close'] = 'Close'; 5 | _sgLang['file'] = 'File'; 6 | _sgLang['size'] = 'Size'; 7 | _sgLang['delete'] = 'Delete'; 8 | _sgLang['are_you_sure_to_delete'] = 'Are you sure to delete image?'; 9 | _sgLang['error'] = 'Error'; 10 | _sgLang['delete_fail'] = 'Failed to delete.'; 11 | _sgLang['are_you_sure_to_delete_many'] = 'Are you sure to delete selected images?'; 12 | _sgLang['createdon'] = 'Created on'; 13 | _sgLang['title'] = 'Title'; 14 | _sgLang['description'] = 'Description'; 15 | _sgLang['add'] = 'Additional'; 16 | _sgLang['show'] = 'Show'; 17 | _sgLang['yes'] = 'Yes'; 18 | _sgLang['save'] = 'Save'; 19 | _sgLang['save_fail'] = 'Failed to save.'; 20 | _sgLang['refresh_previews'] = 'Refresh previews'; 21 | _sgLang['are_you_sure_to_refresh'] = 'This process can take a lot of time. Are you sure to continue?'; 22 | _sgLang['emptydesc'] = 'Image description is empty. Click to edit.'; 23 | _sgLang['continue'] = 'Continue'; 24 | _sgLang['refresh_current'] = 'Refresh current gallery'; 25 | _sgLang['refresh_ids'] = 'Refresh by id'; 26 | _sgLang['refresh_tpls'] = 'Refresh by template'; 27 | _sgLang['refresh_fail'] = 'Failed to refresh previews.'; 28 | _sgLang['move'] = 'Move'; 29 | _sgLang['are_you_sure_to_move'] = 'Are you sure to move selected images?'; 30 | _sgLang['move_fail'] = 'Failed to move.'; 31 | _sgLang['select_resource_id'] = 'Enter target document ID:'; 32 | _sgLang['save_document_to_continue'] = 'Save document to work with gallery.'; 33 | _sgLang['server_error'] = 'Server error: '; 34 | _sgLang['parse_error'] = 'Failed to process server response'; 35 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/js/lang/es.js: -------------------------------------------------------------------------------- 1 | _sgLang = []; 2 | _sgLang['cancel'] = 'Cancelar'; 3 | _sgLang['from'] = 'de'; 4 | _sgLang['close'] = 'Cerrar'; 5 | _sgLang['file'] = 'Archivo'; 6 | _sgLang['size'] = 'Tamaño'; 7 | _sgLang['delete'] = 'Elimiar'; 8 | _sgLang['are_you_sure_to_delete'] = '¿Está seguro de eliminar la imagen?'; 9 | _sgLang['error'] = 'Error'; 10 | _sgLang['delete_fail'] = 'Error al eliminar.'; 11 | _sgLang['are_you_sure_to_delete_many'] = '¿Está seguro de eliminar las imágenes selectadas?'; 12 | _sgLang['createdon'] = 'Creado en'; 13 | _sgLang['title'] = 'Título'; 14 | _sgLang['description'] = 'Descripción'; 15 | _sgLang['add'] = 'Adicional'; 16 | _sgLang['show'] = 'Mostrar'; 17 | _sgLang['yes'] = 'Sí'; 18 | _sgLang['save'] = 'Guardar'; 19 | _sgLang['save_fail'] = 'Error al guardar.'; 20 | _sgLang['refresh_previews'] = 'Actualizar vistas previas'; 21 | _sgLang['are_you_sure_to_refresh'] = 'Este process puede pasar por mucho tiempo. ¿Está seguro de continuar?'; 22 | _sgLang['emptydesc'] = 'La descripción de imagen esta vacía. Clic para editar.'; 23 | _sgLang['continue'] = 'Continuar'; 24 | _sgLang['refresh_current'] = 'Actializar galería actual'; 25 | _sgLang['refresh_ids'] = 'Actualizar por id'; 26 | _sgLang['refresh_tpls'] = 'Actualizar por plantilla'; 27 | _sgLang['refresh_fail'] = 'Error al actualizar las vistas previas.'; 28 | _sgLang['move'] = 'Mover'; 29 | _sgLang['are_you_sure_to_move'] = '¿Está seguro de mover las imágenes selectadas?'; 30 | _sgLang['move_fail'] = 'Error de mover.'; 31 | _sgLang['select_resource_id'] = 'Entrar ID del recurso de destino.:'; 32 | _sgLang['save_document_to_continue'] = 'Guardar el recurso para la gelería.'; 33 | _sgLang['server_error'] = 'Error de servidor: '; 34 | _sgLang['parse_error'] = 'Error al procesar la respuesta de servideor'; 35 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/js/lang/nl.js: -------------------------------------------------------------------------------- 1 | _sgLang['cancel'] = 'Annuleer'; 2 | _sgLang['from'] = 'van'; 3 | _sgLang['close'] = 'Sluit'; 4 | _sgLang['file'] = 'Bestand'; 5 | _sgLang['size'] = 'Afmeting'; 6 | _sgLang['delete'] = 'Verwijder'; 7 | _sgLang['are_you_sure_to_delete'] = 'Weet je zeker dat je de afbeelding wil verwijderen?'; 8 | _sgLang['error'] = 'Error'; 9 | _sgLang['delete_fail'] = 'Verwijderen mislukt.'; 10 | _sgLang['are_you_sure_to_delete_many'] = 'Weet je zeker dat je de geselecteerde afbeeldingen wilt verwijderen?'; 11 | _sgLang['createdon'] = 'Gemaakt op'; 12 | _sgLang['title'] = 'Titel'; 13 | _sgLang['description'] = 'Omschrijving'; 14 | _sgLang['add'] = 'Toevoeging'; 15 | _sgLang['show'] = 'Toon'; 16 | _sgLang['yes'] = 'Ja'; 17 | _sgLang['save'] = 'Opslaan'; 18 | _sgLang['save_fail'] = 'Opslaan mislukt.'; 19 | _sgLang['refresh_previews'] = 'Ververs pagina'; 20 | _sgLang['are_you_sure_to_refresh'] = 'Dit proces kan veel tijd in beslag nemen. Weet je het zeker?'; 21 | _sgLang['emptydesc'] = 'Afbeelding omschrijving is leeg. Klik om te bewerken.'; 22 | _sgLang['continue'] = 'Doorgaan'; 23 | _sgLang['refresh_current'] = 'Vernieuw de huidige galerij'; 24 | _sgLang['refresh_ids'] = 'Ververs per id'; 25 | _sgLang['refresh_tpls'] = 'Ververs per template'; 26 | _sgLang['refresh_fail'] = 'Vertoning verversen mislukt.'; 27 | _sgLang['move'] = 'Verplaats'; 28 | _sgLang['are_you_sure_to_move'] = 'Weet je zeker dat je de geselecteerde afbeeldingen wilt verplaatsen?'; 29 | _sgLang['move_fail'] = 'Verplaatsen mislukt.'; 30 | _sgLang['select_resource_id'] = 'Voer doeldocument ID in:'; 31 | _sgLang['save_document_to_continue'] = 'Document opslaan om met galerij te werken.'; 32 | _sgLang['server_error'] = 'Server error: '; 33 | _sgLang['parse_error'] = 'Serverrespons mislukt'; 34 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/js/lang/pl.js: -------------------------------------------------------------------------------- 1 | _sgLang['cancel'] = 'Anuluj'; 2 | _sgLang['from'] = 'z'; 3 | _sgLang['close'] = 'Zamknij'; 4 | _sgLang['file'] = 'Plik'; 5 | _sgLang['size'] = 'Rozmiar'; 6 | _sgLang['delete'] = 'Usuń'; 7 | _sgLang['are_you_sure_to_delete'] = 'Czy na pewno chcesz usunąć ten obraz?'; 8 | _sgLang['error'] = 'Błąd'; 9 | _sgLang['delete_fail'] = 'Nie udało się usunąć.'; 10 | _sgLang['are_you_sure_to_delete_many'] = 'Czy na pewno chcesz usunąć wybrane obrazy?'; 11 | _sgLang['createdon'] = 'Utworzony'; 12 | _sgLang['title'] = 'Tytuł'; 13 | _sgLang['description'] = 'Opis'; 14 | _sgLang['add'] = 'Dodatkowe'; 15 | _sgLang['show'] = 'Widoczny'; 16 | _sgLang['yes'] = 'Tak'; 17 | _sgLang['save'] = 'Zapisz'; 18 | _sgLang['save_fail'] = 'Nie udało się zapisać.'; 19 | _sgLang['refresh_previews'] = 'Odśwież miniatury'; 20 | _sgLang['are_you_sure_to_refresh'] = 'Ta czynność może zająć trochę czasu. Czy chcesz kontynuować?'; 21 | _sgLang['emptydesc'] = 'Opis obrazu jest pusty. Kliknij aby edytować.'; 22 | _sgLang['continue'] = 'Kontynuuj'; 23 | _sgLang['refresh_current'] = 'Odśwież aktualną galerię'; 24 | _sgLang['refresh_ids'] = 'Odśwież używając ID'; 25 | _sgLang['refresh_tpls'] = 'Odśwież używając szablonu'; 26 | _sgLang['refresh_fail'] = 'Nie udało się odświeżyć miniatur.'; 27 | _sgLang['move'] = 'Przenieś'; 28 | _sgLang['are_you_sure_to_move'] = 'Czy na pewno chcesz przenieść wybrane obrazy?'; 29 | _sgLang['move_fail'] = 'Nie udało się przenieść.'; 30 | _sgLang['select_resource_id'] = 'Podaj ID docelowego dokumentu:'; 31 | _sgLang['save_document_to_continue'] = 'Aby używać galerii, zapisz najpierw dokument.'; 32 | _sgLang['server_error'] = 'Błąd serwera: '; 33 | _sgLang['parse_error'] = 'Nie udało się przetworzyć odpowiedzi serwera'; 34 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/js/lang/ru.js: -------------------------------------------------------------------------------- 1 | _sgLang['cancel'] = 'Отменить'; 2 | _sgLang['from'] = 'из'; 3 | _sgLang['file'] = 'Файл'; 4 | _sgLang['size'] = 'Размер'; 5 | _sgLang['close'] = 'Закрыть'; 6 | _sgLang['delete'] = 'Удаление'; 7 | _sgLang['are_you_sure_to_delete'] = 'Вы уверены, что хотите удалить картинку?'; 8 | _sgLang['error'] = 'Ошибка'; 9 | _sgLang['delete_fail'] = 'Не удалось удалить.'; 10 | _sgLang['are_you_sure_to_delete_many'] = 'Вы уверены, что хотите удалить выделенные картинки?'; 11 | _sgLang['createdon'] = 'Добавлен'; 12 | _sgLang['title'] = 'Название'; 13 | _sgLang['description'] = 'Описание'; 14 | _sgLang['add'] = 'Дополнительно'; 15 | _sgLang['show'] = 'Показывать'; 16 | _sgLang['yes'] = 'Да'; 17 | _sgLang['save'] = 'Сохранить'; 18 | _sgLang['save_fail'] = 'Не удалось сохранить'; 19 | _sgLang['refresh_previews'] = 'Обновить превью'; 20 | _sgLang['are_you_sure_to_refresh'] = 'Обновление может занять много времени. Вы уверены, что хотите продолжить?'; 21 | _sgLang['emptydesc'] = 'Описание картинки не заполнено. Нажмите для редактирования.'; 22 | _sgLang['continue'] = 'Продолжить'; 23 | _sgLang['refresh_current'] = 'Обновить текущую галерею'; 24 | _sgLang['refresh_ids'] = 'Обновить по id'; 25 | _sgLang['refresh_tpls'] = 'Обновить по шаблону'; 26 | _sgLang['refresh_fail'] = 'Не удалось обновить превью.'; 27 | _sgLang['move'] = 'Перемещение'; 28 | _sgLang['are_you_sure_to_move'] = 'Вы уверены, что хотите переместить выделенные картинки?'; 29 | _sgLang['move_fail'] = 'Не удалось переместить.'; 30 | _sgLang['select_resource_id'] = 'Введите ID документа, в который нужно переместить:'; 31 | _sgLang['save_document_to_continue'] = 'Для работы с галереей необходимо сохранить документ.'; 32 | _sgLang['server_error'] = 'Ошибка сервера: '; 33 | _sgLang['parse_error'] = 'Не удалось обработать ответ сервера'; 34 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/js/plugin/editrte.js: -------------------------------------------------------------------------------- 1 | (function($){ 2 | sgHelper.initRTE = function() { 3 | tinymce.init({ 4 | selector:'#rteField', 5 | relative_urls:true, 6 | remove_script_host:true, 7 | convert_urls:true, 8 | resize:false, 9 | forced_root_block:'p', 10 | skin:'lightgray', 11 | width:'100%', 12 | height:400, 13 | menubar:true, 14 | statusbar:true, 15 | document_base_url:sgConfig._modxSiteUrl, 16 | entity_encoding:'named', 17 | language:'ru', 18 | language_url:sgConfig._modxSiteUrl+'/assets/plugins/tinymce4/tinymce/langs/ru.js', 19 | schema:'html5', 20 | element_format:'xhtml', 21 | image_caption:true, 22 | image_advtab:true, 23 | image_class_list:[{title: "None", value: ""},{title: "Float left", value: "justifyleft"},{title: "Float right", value: "justifyright"},{title: "Image Responsive",value: "img-responsive"}], 24 | browser_spellcheck:false, 25 | paste_word_valid_elements:'a[href|name],p,b,strong,i,em,h1,h2,h3,h4,h5,h6,table,th,td[colspan|rowspan],tr,thead,tfoot,tbody,br,hr,sub,sup,u', 26 | plugins:'anchor autolink lists spellchecker pagebreak layer table save hr modxlink image imagetools code emoticons insertdatetime preview media searchreplace print contextmenu paste directionality fullscreen noneditable visualchars nonbreaking youtube autosave advlist visualblocks charmap', 27 | toolbar1:'bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | styleselect formatselect', 28 | toolbar2:'bullist numlist | outdent indent | undo redo | link unlink anchor image help code', 29 | style_formats:[{"title":"Inline","items":[{"title":"InlineTitle","inline":"span","classes":"cssClass1"},{"title":"InlineTitle2","inline":"span","classes":"cssClass2"}]},{"title":"Block","items":[{"title":"BlockTitle","selector":"*","classes":"cssClass3"},{"title":"BlockTitle2","selector":"*","classes":"cssClass4"}]}], 30 | block_formats:'', 31 | toolbar3:'hr removeformat visualblocks | subscript superscript | charmap', 32 | file_browser_callback: function (field, url, type, win) { 33 | if (type == 'image') { 34 | type = 'images'; 35 | } 36 | if (type == 'file') { 37 | type = 'files'; 38 | } 39 | tinyMCE.activeEditor.windowManager.open({ 40 | file: sgConfig._modxSiteUrl+'/manager/media/browser/mcpuk/browse.php?opener=tinymce4&field=' + field + '&type=' + type, 41 | title: 'KCFinder', 42 | width: 840, 43 | height: 600, 44 | inline: true, 45 | close_previous: false 46 | }, { 47 | window: win, 48 | input: field 49 | }); 50 | return false; 51 | } 52 | 53 | }); 54 | } 55 | sgHelper.rteForm = function(textarea) { 56 | var context = { 57 | textarea: textarea.val(), 58 | }; 59 | var rteForm = $(Handlebars.templates.rteForm(context)); 60 | rteForm.dialog({ 61 | modal:true, 62 | title:"Редактирование", 63 | collapsible:false, 64 | minimizable:false, 65 | maximizable:false, 66 | resizable:false, 67 | buttons:[ 68 | { 69 | text:'Сохранить', 70 | iconCls: 'btn-green fa fa-check fa-lg', 71 | handler:function(){ 72 | var content = tinymce.activeEditor.getContent(); 73 | textarea.val(content); 74 | rteForm.window('close',true); 75 | } 76 | },{ 77 | text:'Закрыть', 78 | iconCls: 'btn-red fa fa-ban fa-lg', 79 | handler:function(){ 80 | rteForm.window('close', true); 81 | } 82 | } 83 | ], 84 | onOpen: function() { 85 | sgHelper.initRTE(); 86 | }, 87 | onClose: function() { 88 | var mask = $('.window-mask'); 89 | tinymce.execCommand('mceRemoveEditor',true,"rteField"); 90 | sgHelper.destroyWindow(rteForm); 91 | $('body').append(mask); 92 | } 93 | }) 94 | }; 95 | sgHelper.edit = function(image) { 96 | var data = image.data('properties'); 97 | var context = { 98 | data: data, 99 | modxSiteUrl: sgConfig._modxSiteUrl, 100 | sgLang: _sgLang 101 | }; 102 | sgConfig.sgDisableSelectAll = true; 103 | var editForm = $(Handlebars.templates.editForm(context)); 104 | editForm.dialog({ 105 | modal: true, 106 | title: '[' + data.sg_id + '] ' + sgHelper.escape(Handlebars.helpers.stripText(data.sg_title, 80)), 107 | doSize: true, 108 | collapsible: false, 109 | minimizable: false, 110 | maximizable: false, 111 | resizable: false, 112 | buttons: [{ 113 | iconCls: 'btn-green fa fa-check fa-lg', 114 | text: _sgLang['save'], 115 | handler: function () { 116 | $.post( 117 | sgConfig._xtAjaxUrl + '?mode=edit', 118 | $('#sgForm').serialize(), 119 | function (response) { 120 | if (response.success) { 121 | editForm.window('close', true); 122 | sgHelper.update(); 123 | } else { 124 | $.messager.alert(_sgLang['error'], _sgLang['save_fail']); 125 | } 126 | }, 'json' 127 | ).fail(sgHelper.handleAjaxError); 128 | } 129 | }, { 130 | iconCls: 'btn-red fa fa-ban fa-lg', 131 | text: _sgLang['cancel'], 132 | handler: function () { 133 | editForm.window('close', true); 134 | } 135 | }], 136 | onOpen: function() { 137 | var descriptionField = $('textarea[name="sg_description"]','#sgEdit'); 138 | descriptionField.after('Редактировать'); 139 | $('.btn-rte').click(function(e){ 140 | sgHelper.rteForm(descriptionField); 141 | }); 142 | $('.image img',editForm).on('load',function() { 143 | var nWidth = this.naturalWidth, 144 | nHeight = this.naturalHeight; 145 | var wWidth = $(window).width() - 200, 146 | wHeight = $(window).height() - 200; 147 | if (nWidth > 280 || nHeight > 210) { 148 | var img = $(this); 149 | var minRatio = Math.min(1, wWidth / nWidth, wHeight / nHeight ); 150 | var width = Math.floor( minRatio * nWidth ); 151 | var height = Math.floor( minRatio * nHeight ); 152 | 153 | img.wrap('').parent().click(function(e) { 154 | e.preventDefault(); 155 | img.clone().css({ 156 | width:width, 157 | height:height 158 | }).wrap('
').parent().window({ 159 | title: '[' + data.sg_id + '] ' + sgHelper.escape(Handlebars.helpers.stripText(data.sg_title, 80)), 160 | modal:true, 161 | collapsible:false, 162 | minimizable:false, 163 | maximizable:false, 164 | resizable:false 165 | }).window('open'); 166 | }); 167 | } 168 | }); 169 | }, 170 | onClose: function () { 171 | sgConfig.sgDisableSelectAll = false; 172 | sgHelper.destroyWindow(editForm); 173 | } 174 | }); 175 | } 176 | })(jQuery) -------------------------------------------------------------------------------- /assets/plugins/simplegallery/js/plugin/simplegallery.js: -------------------------------------------------------------------------------- 1 | var sgHelper = {}; 2 | (function ($) { 3 | sgHelper = { 4 | init: function () { 5 | var workspace = $('#SimpleGallery'); 6 | workspace.append('
' + (sgConfig._xtRefreshBtn ? '' : '') + '
'); 7 | $('#sgShowRefreshFormBtn').linkbutton({ 8 | iconCls: 'fa fa-recycle fa-lg', 9 | onClick: function () { 10 | sgHelper.refresh(); 11 | } 12 | }); 13 | var uploaderOptions = { 14 | workspace: '#SimpleGallery', 15 | dndArea: '.js-fileapi-wrapper', 16 | uploadBtn: '#sgUploadBtn', 17 | url: sgConfig._xtAjaxUrl, 18 | data: { 19 | mode: 'upload', 20 | sg_rid: sgConfig.rid 21 | }, 22 | filterFn: function (file) { 23 | return /jpeg|gif|png|webp$/.test(file.type); 24 | }, 25 | completeCallback: function () { 26 | sgHelper.update(); 27 | } 28 | }; 29 | if (Object.keys(sgConfig.clientResize).length) { 30 | uploaderOptions.imageTransform = sgConfig.clientResize; 31 | uploaderOptions.imageAutoOrientation = true; 32 | } else { 33 | uploaderOptions.imageAutoOrientation = false; 34 | } 35 | var sgUploader = new EUIUploader(uploaderOptions); 36 | this.initImages(); 37 | var buttons = []; 38 | buttons.push({ 39 | iconCls: 'btn-red fa fa-trash fa-lg btn-extra', 40 | handler: function () { 41 | sgHelper.delete(); 42 | } 43 | }); 44 | if (sgConfig._xtRefreshBtn) { 45 | buttons.push({ 46 | iconCls: 'btn-green fa fa-mail-forward fa-lg btn-extra', 47 | handler: function () { 48 | sgHelper.move(); 49 | } 50 | }); 51 | } 52 | buttons.push({ 53 | iconCls: 'fa fa-arrow-up fa-lg btn-extra', 54 | handler: function () { 55 | sgHelper.place('top'); 56 | } 57 | },{ 58 | iconCls: 'fa fa-arrow-down fa-lg btn-extra', 59 | handler: function () { 60 | sgHelper.place('bottom'); 61 | } 62 | }); 63 | $('#sg_pages').pagination({ 64 | total: 0, 65 | pageSize: 50, 66 | pageList: [50, 100, 150, 200], 67 | buttons: buttons, 68 | onSelectPage: function (pageNumber, pageSize) { 69 | $(this).pagination('loading'); 70 | $.post( 71 | sgConfig._xtAjaxUrl, 72 | { 73 | rows: pageSize, 74 | page: pageNumber, 75 | sg_rid: sgConfig.rid 76 | }, 77 | function (response) { 78 | $('#sg_pages').pagination('refresh', {total: response.total}); 79 | sgHelper.renderImages(response.rows); 80 | }, 'json' 81 | ).fail(sgHelper.handleAjaxError); 82 | $(this).pagination('loaded'); 83 | $('.btn-extra').parent().parent().hide(); 84 | } 85 | }); 86 | }, 87 | update: function () { 88 | $('#sg_pages').pagination('select'); 89 | }, 90 | destroyWindow: function (wnd) { 91 | wnd.window('destroy', true); 92 | $('.window-shadow,.window-mask').remove(); 93 | $('body').css('overflow', 'auto'); 94 | }, 95 | renderImages: function (rows) { 96 | var len = rows.length; 97 | var placeholder = $('#sg_images'); 98 | placeholder.html(''); 99 | for (i = 0; i < len; i++) { 100 | var context = { 101 | data: rows[i], 102 | sgLang: _sgLang, 103 | thumbPrefix: sgConfig._xtThumbPrefix 104 | }; 105 | var image = $(Handlebars.templates.preview(context)); 106 | image.data('properties', rows[i]); 107 | placeholder.append(image); 108 | } 109 | }, 110 | initImages: function () { 111 | var _this = this; 112 | $('#sg_images').on('click', '.del', function () { 113 | _this.delete($(this).parent()); 114 | }).on('click', '.edit', function () { 115 | _this.edit($(this).parent()); 116 | }).on('click', '.sg_image', function (e) { 117 | _this.unselect(); 118 | _this.select($(this), e); 119 | }).on('dblclick', '.sg_image', function (e) { 120 | _this.unselect(); 121 | _this.edit($(this)); 122 | }); 123 | $(document).on('keydown', function (e) { 124 | return !_this.selectAll(e); 125 | }); 126 | $('body').attr('ondragstart', ''); 127 | if (sgConfig.sgSort !== null) sgConfig.sgSort.destroy(); 128 | var sg_images = document.getElementById('sg_images'); 129 | sgConfig.sgSort = new Sortable(sg_images, { 130 | draggable: '.sg_image', 131 | onStart: function (e) { 132 | sgConfig.sgBeforeDragState = { 133 | prev: e.item.previousSibling != null ? $(e.item.previousSibling).data('properties').sg_index : -1, 134 | next: e.item.nextSibling != null ? $(e.item.nextSibling).data('properties').sg_index : -1 135 | }; 136 | }, 137 | onEnd: function (e) { 138 | var sgAfterDragState = { 139 | prev: e.item.previousSibling != null ? $(e.item.previousSibling).data('properties').sg_index : -1, 140 | next: e.item.nextSibling != null ? $(e.item.nextSibling).data('properties').sg_index : -1 141 | }; 142 | if (sgAfterDragState.prev == sgConfig.sgBeforeDragState.prev && sgAfterDragState.next == sgConfig.sgBeforeDragState.next) return; 143 | var source = $(e.item).data('properties'); 144 | sourceIndex = parseInt(source.sg_index); 145 | sourceId = source.sg_id; 146 | var target = e.item.nextSibling == null ? $(e.item.previousSibling).data('properties') : $(e.item.nextSibling).data('properties'); 147 | targetIndex = parseInt(target.sg_index); 148 | if (targetIndex < sourceIndex && sgAfterDragState.next != -1) targetIndex++; 149 | 150 | var tempIndex = targetIndex, 151 | item = e.item; 152 | if (sourceIndex < targetIndex) { 153 | while (tempIndex >= sourceIndex) { 154 | $(item).data('properties').sg_index = tempIndex--; 155 | item = item.nextSibling == null ? item : item.nextSibling; 156 | } 157 | } else { 158 | while (tempIndex <= sourceIndex) { 159 | $(item).data('properties').sg_index = tempIndex++; 160 | item = item.previousSibling == null ? item : item.previousSibling; 161 | } 162 | } 163 | $.post( 164 | sgConfig._xtAjaxUrl + '?mode=reorder', { 165 | sg_rid: sgConfig.rid, 166 | sourceId: sourceId, 167 | sourceIndex: sourceIndex, 168 | targetIndex: targetIndex 169 | }, 170 | function (response) { 171 | if (!response.success) { 172 | _this.update(); 173 | } 174 | }, 'json' 175 | ).fail(function (xhr) { 176 | $.messager.alert(_sgLang['error'], _sgLang['server_error'] + xhr.status + ' ' + xhr.statusText, 'error'); 177 | }); 178 | } 179 | }); 180 | }, 181 | unselect: function () { 182 | if (document.selection && document.selection.empty) 183 | document.selection.empty(); 184 | else if (window.getSelection) { 185 | var sel = window.getSelection(); 186 | if (sel && sel.removeAllRanges) 187 | sel.removeAllRanges(); 188 | } 189 | }, 190 | select: function (image, e) { 191 | var _image = $('.sg_image'); 192 | if (!sgConfig.sgLastChecked) 193 | sgConfig.sgLastChecked = image; 194 | if (e.ctrlKey || e.metaKey) { 195 | if (image.hasClass('selected')) 196 | image.removeClass('selected'); 197 | else 198 | image.addClass('selected'); 199 | } else if (e.shiftKey) { 200 | var start = _image.index(image); 201 | var end = _image.index(sgConfig.sgLastChecked); 202 | _image.slice(Math.min(start, end), Math.max(start, end) + 1).addClass('selected'); 203 | 204 | } else { 205 | _image.removeClass('selected'); 206 | image.addClass('selected'); 207 | sgConfig.sgLastChecked = image; 208 | } 209 | var images = $('.sg_image.selected').get(); 210 | if (images.length) { 211 | $('.btn-extra').parent().parent().show(); 212 | } else { 213 | $('.btn-extra').parent().parent().hide(); 214 | } 215 | }, 216 | selectAll: function (e) { 217 | if (sgConfig.sgDisableSelectAll || (!e.ctrlKey && !e.metaKey) || ((e.keyCode != 65) && (e.keyCode != 97))) 218 | return false; 219 | var images = $('.sg_image').get(); 220 | if (images.length) { 221 | $.each(images, function (i, image) { 222 | if (!$(image).hasClass('selected')) 223 | $(image).addClass('selected'); 224 | }); 225 | } 226 | $('.btn-extra').parent().parent().show(); 227 | return true; 228 | }, 229 | getSelected: function () { 230 | var ids = []; 231 | var images = $('.sg_image.selected'); 232 | if (images.length) { 233 | $.each(images, function (i, image) { 234 | ids.push($(image).data('properties').sg_id); 235 | }); 236 | } 237 | return ids; 238 | }, 239 | delete: function (image) { 240 | var ids = image === undefined ? this.getSelected() : [image.data('properties').sg_id]; 241 | $.messager.confirm(_sgLang['delete'], (ids.length > 1 ? _sgLang['are_you_sure_to_delete_many'] : _sgLang['are_you_sure_to_delete']), function (r) { 242 | if (r && ids.length > 0) { 243 | $.post( 244 | sgConfig._xtAjaxUrl + '?mode=remove', 245 | { 246 | ids: ids.join(), 247 | sg_rid: sgConfig.rid 248 | }, 249 | function (response) { 250 | if (response.success) { 251 | sgHelper.update(); 252 | } else { 253 | $.messager.alert(_sgLang['error'], _sgLang['delete_fail']); 254 | } 255 | }, 'json' 256 | ).fail(sgHelper.handleAjaxError); 257 | } 258 | }); 259 | }, 260 | move: function () { 261 | var total = 0, 262 | progressbar = {}, 263 | abort = false; 264 | function refreshStatus() { 265 | if (abort) return; 266 | $.post( 267 | sgConfig._xtAjaxUrl + '?mode=getMoveRefreshStatus', 268 | function (response) { 269 | if (response.success) { 270 | var part = total > 0 ? 100 * response.processed / total : 0; 271 | progressbar.progressbar('setText', response.processed + ' ' + _sgLang['from'] + ' ' + total + ' ({value}%)').progressbar('setValue', Math.floor(part)); 272 | if (response.processed < total) { 273 | processRefresh(); 274 | } 275 | if (part == 100) { 276 | $('#sgCancelMove').linkbutton({text:_sgLang['close']}); 277 | } 278 | } else { 279 | $.messager.alert(_sgLang['error'], _sgLang['refresh_fail']); 280 | } 281 | }, 'json' 282 | ).fail(function (xhr) { 283 | $.messager.alert(_sgLang['error'], _sgLang['server_error'] + xhr.status + ' ' + xhr.statusText, 'error'); 284 | }); 285 | } 286 | 287 | function processRefresh() { 288 | if (abort) return; 289 | $.ajax({ 290 | url: sgConfig._xtAjaxUrl + '?mode=processMoveRefresh', 291 | type: 'POST', 292 | timeout: 35000, 293 | dataType: 'json', 294 | success: function (response) { 295 | if (response.success) { 296 | refreshStatus(); 297 | } else { 298 | $.messager.alert(_sgLang['error'], _sgLang['refresh_fail']); 299 | } 300 | }, 301 | complete: function (xhr, textStatus) { 302 | if (textStatus != "success") { 303 | refreshStatus(); 304 | } 305 | } 306 | }) 307 | } 308 | 309 | var ids = this.getSelected(); 310 | var context = { 311 | sgLang: _sgLang 312 | }; 313 | var moveForm = $(Handlebars.templates.moveForm(context)); 314 | moveForm.dialog({ 315 | modal: true, 316 | title: _sgLang['move'], 317 | doSize: true, 318 | collapsible: false, 319 | minimizable: false, 320 | maximizable: false, 321 | resizable: false, 322 | buttons: [{ 323 | iconCls: 'btn-green fa fa-check fa-lg', 324 | text: _sgLang['continue'], 325 | handler: function () { 326 | var btn = $(this); 327 | btn.hide(); 328 | var _to = $('#sgMoveTo').val(); 329 | if (_to <= 0 || _to == sgConfig.rid) { 330 | btn.show(); 331 | return $.messager.alert(_sgLang['error'], _sgLang['move_fail']); 332 | } 333 | $.post( 334 | sgConfig._xtAjaxUrl + '?mode=move', 335 | { 336 | sg_rid: sgConfig.rid, 337 | ids: ids.join(), 338 | to: _to 339 | }, 340 | function (response) { 341 | if (response.success) { 342 | total = response.total > 0 ? response.total : 0; 343 | $('#sgMoveTo').prop('disabled',true); 344 | progressbar = $('#sgMoveRefreshProgress',moveForm).progressbar(); 345 | progressbar.progressbar('setText', '0 ' + _sgLang['from'] + ' ' + total + ' ({value}%)'); 346 | processRefresh(); 347 | sgHelper.update(); 348 | } else { 349 | btn.show(); 350 | $.messager.alert(_sgLang['error'], _sgLang['move_fail']); 351 | } 352 | }, 'json' 353 | ).fail(sgHelper.handleAjaxError); 354 | } 355 | }, { 356 | iconCls: 'btn-red fa fa-ban fa-lg', 357 | text: _sgLang['cancel'], 358 | id: 'sgCancelMove', 359 | handler: function () { 360 | abort = true; 361 | moveForm.window('close', true); 362 | } 363 | }], 364 | onClose: function () { 365 | sgHelper.destroyWindow(moveForm); 366 | } 367 | }); 368 | }, 369 | place: function (dir) { 370 | var ids = this.getSelected(); 371 | $.messager.confirm(_sgLang['move'], _sgLang['are_you_sure_to_move'], function (r) { 372 | if (r) { 373 | $.post( 374 | sgConfig._xtAjaxUrl + '?mode=place', 375 | { 376 | sg_rid: sgConfig.rid, 377 | ids: ids.join(), 378 | dir: dir 379 | }, 380 | function (response) { 381 | if (response.success) { 382 | sgHelper.update(); 383 | } else { 384 | $.messager.alert(_sgLang['error'], _sgLang['move_fail']); 385 | } 386 | }, 'json' 387 | ).fail(sgHelper.handleAjaxError); 388 | } 389 | }); 390 | }, 391 | edit: function (image) { 392 | var data = image.data('properties'); 393 | var context = { 394 | data: data, 395 | modxSiteUrl: sgConfig._modxSiteUrl, 396 | sgLang: _sgLang 397 | }; 398 | sgConfig.sgDisableSelectAll = true; 399 | var editForm = $(Handlebars.templates.editForm(context)); 400 | editForm.dialog({ 401 | modal: true, 402 | title: '[' + data.sg_id + '] ' + sgHelper.escape(Handlebars.helpers.stripText(data.sg_title, 80)), 403 | doSize: true, 404 | collapsible: false, 405 | minimizable: false, 406 | maximizable: false, 407 | resizable: false, 408 | buttons: [{ 409 | iconCls: 'btn-green fa fa-check fa-lg', 410 | text: _sgLang['save'], 411 | handler: function () { 412 | $.post( 413 | sgConfig._xtAjaxUrl + '?mode=edit', 414 | $('#sgForm').serialize(), 415 | function (response) { 416 | if (response.success) { 417 | editForm.window('close', true); 418 | sgHelper.update(); 419 | } else { 420 | $.messager.alert(_sgLang['error'], _sgLang['save_fail']); 421 | } 422 | }, 'json' 423 | ).fail(sgHelper.handleAjaxError); 424 | } 425 | }, { 426 | iconCls: 'btn-red fa fa-ban fa-lg', 427 | text: _sgLang['cancel'], 428 | handler: function () { 429 | editForm.window('close', true); 430 | } 431 | }], 432 | onOpen: function() { 433 | $('.image img',editForm).on('load',function() { 434 | var nWidth = this.naturalWidth, 435 | nHeight = this.naturalHeight; 436 | var wWidth = $(window).width() - 200, 437 | wHeight = $(window).height() - 200; 438 | if (nWidth > 280 || nHeight > 210) { 439 | var img = $(this); 440 | var minRatio = Math.min(1, wWidth / nWidth, wHeight / nHeight ); 441 | var width = Math.floor( minRatio * nWidth ); 442 | var height = Math.floor( minRatio * nHeight ); 443 | 444 | img.wrap('').parent().click(function(e) { 445 | e.preventDefault(); 446 | img.clone().css({ 447 | width:width, 448 | height:height 449 | }).wrap('
').parent().window({ 450 | title: '[' + data.sg_id + '] ' + sgHelper.escape(Handlebars.helpers.stripText(data.sg_title, 80)), 451 | modal:true, 452 | collapsible:false, 453 | minimizable:false, 454 | maximizable:false, 455 | resizable:false 456 | }).window('open'); 457 | }); 458 | } 459 | }); 460 | }, 461 | onClose: function () { 462 | sgConfig.sgDisableSelectAll = false; 463 | sgHelper.destroyWindow(editForm); 464 | } 465 | }); 466 | }, 467 | handleAjaxError: function(xhr) { 468 | var message = xhr.status == 200 ? _sgLang['parse_error'] : _sgLang['server_error'] + xhr.status + ' ' + xhr.statusText; 469 | $.messager.alert(_sgLang['error'], message, 'error'); 470 | }, 471 | escape: function (str) { 472 | return str 473 | .replace(/&/g, '&') 474 | .replace(/>/g, '>') 475 | .replace(/ 0 ? 100 * response.processed / total : 0; 513 | progressbar.progressbar('setText', response.processed + ' ' + _sgLang['from'] + ' ' + total + ' ({value}%)').progressbar('setValue', Math.floor(part)); 514 | if (response.processed < total) { 515 | processRefresh(); 516 | } else { 517 | $('#sgRunRefreshBtn').linkbutton({ 518 | iconCls: 'btn-red fa fa-ban fa-lg', 519 | text: _sgLang['close'], 520 | onClick: function () { 521 | $('#sgRefresh').window('close'); 522 | } 523 | }); 524 | } 525 | } else { 526 | $.messager.alert(_sgLang['error'], _sgLang['refresh_fail']); 527 | } 528 | }, 'json' 529 | ).fail(function (xhr) { 530 | $.messager.alert(_sgLang['error'], _sgLang['server_error'] + xhr.status + ' ' + xhr.statusText, 'error'); 531 | }); 532 | } 533 | 534 | $.messager.confirm(_sgLang['refresh_previews'], _sgLang['are_you_sure_to_refresh'], function (r) { 535 | if (r) { 536 | var tpls = $.parseJSON(sgConfig._xtTpls); 537 | var context = { 538 | tpls: tpls, 539 | sgLang: _sgLang, 540 | }; 541 | var refreshForm = $(Handlebars.templates.refreshForm(context)); 542 | refreshForm.dialog({ 543 | width: 450, 544 | modal: true, 545 | title: _sgLang['refresh_previews'], 546 | doSize: true, 547 | collapsible: false, 548 | minimizable: false, 549 | maximizable: false, 550 | resizable: false, 551 | buttons: [{ 552 | id: 'sgRunRefreshBtn', 553 | iconCls: 'btn-green fa fa-check fa-lg', 554 | text: _sgLang['continue'], 555 | onClick: function () { 556 | var method = $('form input[name="method"]:checked', '#sgRefresh').val(); 557 | var formdata = {}; 558 | switch (method) { 559 | case "0": 560 | formdata.method = 'rid'; 561 | formdata.ids = sgConfig.rid; 562 | break; 563 | case "1": 564 | formdata.method = 'rid'; 565 | formdata.ids = $('form input[name="ids"]', '#sgRefresh').val(); 566 | break; 567 | case "2": 568 | formdata.method = 'template'; 569 | formdata.ids = $('form input[name="template[]"]:checked', '#sgRefresh').map(function(){return $(this).val();}).get().join(); 570 | break; 571 | } 572 | if (formdata.ids.length == 0) return; 573 | $('form input', '#sgRefresh').prop('disabled',true); 574 | $.post( 575 | sgConfig._xtAjaxUrl + '?mode=initRefresh', 576 | formdata, 577 | function (response) { 578 | if (response.success) { 579 | total = response.total > 0 ? response.total : 0; 580 | progressbar.progressbar('setText', '0 ' + _sgLang['from'] + ' ' + total + ' ({value}%)').show(); 581 | $('#sgRunRefreshBtn').linkbutton({ 582 | iconCls: 'btn-red fa fa-ban fa-lg', 583 | text: _sgLang['cancel'], 584 | onClick: function () { 585 | abort = true; 586 | $('#sgRefresh').window('close'); 587 | } 588 | }); 589 | refreshStatus(); 590 | } else { 591 | $.messager.alert(_sgLang['error'], _sgLang['refresh_fail']); 592 | } 593 | }, 'json' 594 | ).fail(function (xhr) { 595 | $.messager.alert(_sgLang['error'], _sgLang['server_error'] + xhr.status + ' ' + xhr.statusText, 'error'); 596 | }); 597 | } 598 | } 599 | ], 600 | onOpen: function () { 601 | progressbar = $('#sgRefreshProgress').progressbar().hide(); 602 | $('#sgRefresh').off().on('change','input[name="method"]',function(){ 603 | $('.elements','#sgRefresh').hide(); 604 | switch (this.value) { 605 | case "1": 606 | $('input[name="ids"]','#sgRefresh').show(); 607 | break; 608 | case "2": 609 | $('.templates','#sgRefresh').show(); 610 | break; 611 | } 612 | }); 613 | }, 614 | onClose: function () { 615 | sgHelper.destroyWindow(refreshForm); 616 | } 617 | }); 618 | } 619 | }); 620 | } 621 | } 622 | })(jQuery); 623 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/js/scripts.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "EasyUI" : { 4 | "version":"1.5.2", 5 | "src":"assets/js/easy-ui/jquery.easyui.min.js" 6 | }, 7 | "easyui-lang-[+lang+]":{ 8 | "version":"1.5.2", 9 | "src":"assets/js/easy-ui/locale/easyui-lang-[+lang+].js" 10 | }, 11 | "FileAPI": { 12 | "version":"2.0.20", 13 | "src":"assets/js/fileapi/FileAPI/FileAPI.min.js" 14 | }, 15 | "FileAPIExif": { 16 | "version":"2.0.8", 17 | "src":"assets/js/fileapi/FileAPI/FileAPI.exif.js" 18 | }, 19 | "Sortable":{ 20 | "version":"1.2.0", 21 | "src":"assets/js/sortable/Sortable.min.js" 22 | }, 23 | "handlebars":{ 24 | "version":"2.0.0", 25 | "src":"assets/js/handlebars/handlebars.runtime.min.js" 26 | }, 27 | "handlebars-helpers":{ 28 | "version":"2.0.0", 29 | "src":"assets/js/handlebars/helpers.js" 30 | }, 31 | "templates":{ 32 | "version":"1.2.0", 33 | "src":"assets/plugins/simplegallery/js/tpl/templates.js" 34 | }, 35 | "EUIUploader":{ 36 | "version":"1.2.0", 37 | "src":"assets/js/euiuploader/js/euiuploader.js" 38 | }, 39 | "EUIUploader-lang-en":{ 40 | "version":"1.2.0", 41 | "src":"assets/js/euiuploader/lang/en.js" 42 | }, 43 | "EUIUploader-lang-[+lang+]":{ 44 | "version":"1.2.0", 45 | "src":"assets/js/euiuploader/lang/[+lang+].js" 46 | }, 47 | "SimpleGallery":{ 48 | "version":"1.2.0", 49 | "src":"assets/plugins/simplegallery/js/plugin/simplegallery.js" 50 | }, 51 | "sg-lang-en":{ 52 | "version":"1.2.0", 53 | "src":"assets/plugins/simplegallery/js/lang/en.js" 54 | }, 55 | "sg-lang-[+lang+]":{ 56 | "version":"1.2.0", 57 | "src":"assets/plugins/simplegallery/js/lang/[+lang+].js" 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/js/tpl/editForm.handlebars: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
ID{{data.sg_id}}
{{sgLang.file}}{{data.sg_image}}
{{sgLang.size}}{{data.sg_properties.width}}x{{data.sg_properties.height}}, {{bytesToSize data.sg_properties.size}}
{{sgLang.createdon}}{{data.sg_createdon}}
24 |
25 |
26 |
27 |
28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | {{sgLang.yes}} 37 |
38 |
39 |
40 |
41 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/js/tpl/moveForm.handlebars: -------------------------------------------------------------------------------- 1 |
2 |

{{sgLang.select_resource_id}}

3 |
4 |
5 |
6 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/js/tpl/preview.handlebars: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
{{data.sg_title}}
5 | {{#ifCond data.sg_description ""}}{{/ifCond}} 6 |
7 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/js/tpl/readme.txt: -------------------------------------------------------------------------------- 1 | 1. Install the Handlebars commandline script: 2 | npm install -g handlebars 3 | 4 | 2. Go to assets/plugins/simplegallery/js/tpl/ 5 | 6 | 3. Compile templates: 7 | handlebars *.handlebars -f templates.js -m -------------------------------------------------------------------------------- /assets/plugins/simplegallery/js/tpl/refreshForm.handlebars: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | 6 |
7 |
8 |
9 | {{#each tpls}} 10 | 11 | {{/each}} 12 |
13 |
14 |
15 |
16 |
17 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/js/tpl/rteForm.handlebars: -------------------------------------------------------------------------------- 1 |
2 | 3 |
-------------------------------------------------------------------------------- /assets/plugins/simplegallery/js/tpl/rteForm.js: -------------------------------------------------------------------------------- 1 | !function(){var e=Handlebars.template,t=Handlebars.templates=Handlebars.templates||{};t.rteForm=e({compiler:[6,">= 2.0.0-beta.1"],main:function(e,t,a,r){var n,i="function",l=t.helperMissing,s=this.escapeExpression;return'
\r\n \r\n
"},useData:!0})}(); -------------------------------------------------------------------------------- /assets/plugins/simplegallery/js/tpl/templates.js: -------------------------------------------------------------------------------- 1 | !function(){var l=Handlebars.template,n=Handlebars.templates=Handlebars.templates||{};n.editForm=l({1:function(){return" checked"},compiler:[6,">= 2.0.0-beta.1"],main:function(l,n,e,a){var t,s,i="function",d=n.helperMissing,r=this.escapeExpression,u=this.lambda,o='
\n
\n
\n \n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
ID'+r(u(null!=(t=null!=l?l.data:l)?t.sg_id:t,l))+'
'+r(u(null!=(t=null!=l?l.sgLang:l)?t.file:t,l))+""+r(u(null!=(t=null!=l?l.data:l)?t.sg_image:t,l))+'
'+r(u(null!=(t=null!=l?l.sgLang:l)?t.size:t,l))+""+r(u(null!=(t=null!=(t=null!=l?l.data:l)?t.sg_properties:t)?t.width:t,l))+"x"+r(u(null!=(t=null!=(t=null!=l?l.data:l)?t.sg_properties:t)?t.height:t,l))+", "+r((n.bytesToSize||l&&l.bytesToSize||d).call(l,null!=(t=null!=(t=null!=l?l.data:l)?t.sg_properties:t)?t.size:t,{name:"bytesToSize",hash:{},data:a}))+'
'+r(u(null!=(t=null!=l?l.sgLang:l)?t.createdon:t,l))+""+r(u(null!=(t=null!=l?l.data:l)?t.sg_createdon:t,l))+'
\n
\n
\n
\n
\n
\n \n \n \n \n \n \n \n "+r(u(null!=(t=null!=l?l.sgLang:l)?t.yes:t,l))+"\n
\n
\n
\n
\n"},useData:!0}),n.moveForm=l({compiler:[6,">= 2.0.0-beta.1"],main:function(l){var n,e=this.lambda,a=this.escapeExpression;return'
\n

'+a(e(null!=(n=null!=l?l.sgLang:l)?n.select_resource_id:n,l))+'

\n
\n
\n
\n'},useData:!0}),n.preview=l({1:function(){return" notactive"},3:function(l){var n,e=this.lambda,a=this.escapeExpression;return''},compiler:[6,">= 2.0.0-beta.1"],main:function(l,n,e,a){var t,s,i=this.lambda,d=this.escapeExpression,r=n.helperMissing,u="function",o='
\n \n
\n
'+d(i(null!=(t=null!=l?l.data:l)?t.sg_title:t,l))+"
\n ",t=(n.ifCond||l&&l.ifCond||r).call(l,null!=(t=null!=l?l.data:l)?t.sg_description:t,"",{name:"ifCond",hash:{},fn:this.program(3,a),inverse:this.noop,data:a}),null!=t&&(o+=t),o+"\n
\n"},useData:!0}),n.refreshForm=l({1:function(l,n,e,a){var t=this.lambda,s=this.escapeExpression,i=n.helperMissing;return' \n"},compiler:[6,">= 2.0.0-beta.1"],main:function(l,n,e,a){var t,s=this.lambda,i=this.escapeExpression,d='
\n
\n
\n
\n \n
\n
\n
\n';return t=n.each.call(l,null!=l?l.tpls:l,{name:"each",hash:{},fn:this.program(1,a),inverse:this.noop,data:a}),null!=t&&(d+=t),d+'
\n
\n
\n
\n
\n'},useData:!0})}(); -------------------------------------------------------------------------------- /assets/plugins/simplegallery/lib/controller.class.php: -------------------------------------------------------------------------------- 1 | data = new sgData($this->modx); 23 | $this->data->setParams($this->params); 24 | $this->dlInit(); 25 | } 26 | 27 | /** 28 | * 29 | */ 30 | public function upload() 31 | { 32 | if (!empty($_SERVER['HTTP_ORIGIN'])) { 33 | // Enable CORS 34 | header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']); 35 | header('Access-Control-Allow-Methods: POST, GET, OPTIONS'); 36 | header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Range, Content-Disposition, Content-Type'); 37 | } 38 | if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { 39 | $this->isExit = true; 40 | $this->output = json_encode(array( 41 | 'success' => false, 42 | 'message' => 'upload_failed_4' 43 | )); 44 | 45 | return; 46 | } 47 | 48 | if (strtoupper($_SERVER['REQUEST_METHOD']) == 'POST') { 49 | $file = $_FILES['file']; 50 | $dir = $this->params['folder'] . $this->rid . "/"; 51 | $flag = $this->FS->makeDir($dir, $this->modx->config['new_folder_permissions']); 52 | $message = ''; 53 | if ($flag && $file['error'] == UPLOAD_ERR_OK) { 54 | $tmp_name = $file["tmp_name"]; 55 | $name = $this->data->stripName($file["name"]); 56 | $name = $this->FS->getInexistantFilename($dir . $name, true); 57 | $ext = $this->FS->takeFileExt($name, true); 58 | if (in_array($ext, array('png', 'jpg', 'gif', 'jpeg', 'webp'))) { 59 | if (@move_uploaded_file($tmp_name, $name)) { 60 | $out = $this->data->upload($name, $this->rid, 61 | preg_replace('/\\.[^.\\s]{2,4}$/', '', $file["name"]), true); 62 | if (!$out) { 63 | @unlink($name); 64 | $message = 'unable_to_process_file'; 65 | } 66 | } else { 67 | $message = 'unable_to_move'; 68 | } 69 | } else { 70 | $message = 'forbidden_file'; 71 | } 72 | } else { 73 | $message = $flag ? 'upload_failed_' . $file['error'] : 'unable_to_create_folder'; 74 | } 75 | $this->isExit = true; 76 | $this->output = json_encode(array( 77 | 'success' => empty($message), 78 | 'message' => $message 79 | )); 80 | } else { 81 | $this->isExit = true; 82 | $this->output = json_encode(array( 83 | 'success' => false, 84 | 'message' => 'upload_failed_4' 85 | )); 86 | } 87 | } 88 | 89 | /** 90 | * @return array 91 | */ 92 | public function remove() 93 | { 94 | $out = array(); 95 | $ids = isset($_POST['ids']) ? (string)$_POST['ids'] : ''; 96 | $ids = isset($_POST['id']) ? (string)$_POST['id'] : $ids; 97 | $out['success'] = false; 98 | if (!empty($ids)) { 99 | if ($this->data->deleteAll($ids, $this->rid, true)) { 100 | $out['success'] = true; 101 | } 102 | } 103 | 104 | return $out; 105 | } 106 | 107 | /** 108 | * @return array 109 | */ 110 | public function move() 111 | { 112 | $out = array(); 113 | $ids = isset($_POST['ids']) ? (string)$_POST['ids'] : ''; 114 | $to = isset($_POST['to']) ? (int)$_POST['to'] : 0; 115 | $out['success'] = false; 116 | if ($_SESSION['mgrRole'] != 1) { 117 | return $out; 118 | } 119 | 120 | if (!empty($ids) && $to !== $this->rid && $to > 0) { 121 | if ($this->data->move($ids, $this->rid, $to, true)) { 122 | $out['success'] = true; 123 | unset($_SESSION['move']); 124 | $ids = explode(',',$ids); 125 | $_SESSION['move']['ids'] = $ids; 126 | $out['total'] = $_SESSION['move']['total'] = count($ids); 127 | $_SESSION['move']['processed'] = 0; 128 | } 129 | } 130 | 131 | return $out; 132 | } 133 | 134 | /** 135 | * @return array 136 | */ 137 | public function edit() 138 | { 139 | $out = array(); 140 | $id = isset($_POST['sg_id']) ? (int)$_POST['sg_id'] : 0; 141 | if ($id) { 142 | $fields = array( 143 | 'sg_title' => $_POST['sg_title'], 144 | 'sg_description' => $_POST['sg_description'], 145 | 'sg_add' => $_POST['sg_add'] 146 | ); 147 | $fields['sg_isactive'] = isset($_POST['sg_isactive']) ? 1 : 0; 148 | $out['success'] = $this->data->edit($id)->fromArray($fields)->save(true); 149 | } else { 150 | $out['success'] = false; 151 | } 152 | 153 | return $out; 154 | } 155 | 156 | /** 157 | * @return array 158 | */ 159 | public function reorder() 160 | { 161 | $out = array(); 162 | $sourceIndex = (int)$_POST['sourceIndex']; 163 | $targetIndex = (int)$_POST['targetIndex']; 164 | $sourceId = (int)$_POST['sourceId']; 165 | $source = array('sg_index' => $sourceIndex, 'sg_id' => $sourceId); 166 | $target = array('sg_index' => $targetIndex); 167 | $point = $sourceIndex < $targetIndex ? 'top' : 'bottom'; 168 | $orderDir = 'desc'; 169 | $rows = $this->data->reorder($source, $target, $point, $this->rid, $orderDir); 170 | $out['success'] = $rows; 171 | 172 | return $out; 173 | } 174 | 175 | public function thumb() 176 | { 177 | $w = 140; 178 | $h = 105; 179 | $url = $_GET['url']; 180 | $thumbsCache = $this->data->thumbsCache; 181 | if (isset($this->params)) { 182 | if (isset($this->params['thumbsCache'])) { 183 | $thumbsCache = $this->params['thumbsCache']; 184 | } 185 | if (isset($this->params['w'])) { 186 | $w = $this->params['w']; 187 | } 188 | if (isset($this->params['h'])) { 189 | $h = $this->params['h']; 190 | } 191 | } 192 | $file = MODX_BASE_PATH . $thumbsCache . $url; 193 | if ($this->FS->checkFile($file)) { 194 | $info = getimagesize($file); 195 | if ($w != $info[0] || $h != $info[1]) { 196 | $this->data->makeBackEndThumb($url); 197 | } 198 | } else { 199 | $this->data->makeBackEndThumb($url); 200 | } 201 | session_start(); 202 | header("Cache-Control: private, max-age=10800, pre-check=10800"); 203 | header("Pragma: private"); 204 | header("Expires: " . date(DATE_RFC822, strtotime(" 360 day"))); 205 | if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && (strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == filemtime($file))) { 206 | header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($file)) . ' GMT', true, 304); 207 | $this->isExit = true; 208 | 209 | return; 210 | } 211 | header("Content-type: image/jpeg"); 212 | header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($file)) . ' GMT'); 213 | ob_clean(); 214 | readfile($file); 215 | 216 | return; 217 | } 218 | 219 | public function processMoveRefresh(){ 220 | $out = array(); 221 | $_time = microtime(true); 222 | $_ids = implode(',',$_SESSION['move']['ids']); 223 | $table = $this->modx->getFullTableName('sg_images'); 224 | $sql = "SELECT `sg`.*,`c`.`template` FROM {$table} `sg` LEFT JOIN {$this->modx->getFullTableName('site_content')} `c` ON `c`.`id` = `sg`.`sg_rid` WHERE `sg`.`sg_id` IN ({$_ids})"; 225 | $rows = $this->modx->db->query($sql); //TODO 226 | while ($image = $this->modx->db->getRow($rows)) { 227 | $this->data->refresh($image, true); 228 | $_SESSION['move']['processed']++; 229 | array_pop($_SESSION['move']['ids']); 230 | $time = microtime(true) - $_time; 231 | if ($time > 25) break; 232 | } 233 | $out['success'] = true; 234 | 235 | return $out; 236 | } 237 | 238 | /** 239 | * @return array 240 | */ 241 | public function getMoveRefreshStatus() 242 | { 243 | $out = array(); 244 | 245 | $out['success'] = true; 246 | if (!isset($_SESSION['move']['processed'])) { 247 | $out['processed'] = 0; 248 | } else { 249 | $out['processed'] = $_SESSION['move']['processed'] < $_SESSION['move']['total'] ? $_SESSION['move']['processed'] : $_SESSION['move']['total']; 250 | } 251 | 252 | return $out; 253 | } 254 | 255 | /** 256 | * @return array 257 | */ 258 | public function initRefresh() 259 | { 260 | $out = array(); 261 | $out['success'] = false; 262 | if ($_SESSION['mgrRole'] != 1) { 263 | return $out; 264 | } 265 | 266 | unset($_SESSION['refresh']); 267 | if (!empty($_POST['ids']) && !empty($_POST['method'])) { 268 | $ids = explode(',', $_POST['ids']); 269 | foreach ($ids as &$id) { 270 | $id = (int)$id; 271 | } 272 | $ids = array_unique(array_filter($ids)); 273 | if (!empty($ids)) { 274 | $table = $this->modx->getFullTableName('site_content'); 275 | if ($_POST['method'] == 'template') { 276 | $_ids = implode(',', $ids); 277 | $q = $this->modx->db->query("SELECT `id` FROM {$table} WHERE `template` IN ({$_ids})"); 278 | $ids = $this->modx->db->getColumn('id', $q); 279 | if (empty($ids)) { 280 | return $out; 281 | } 282 | } 283 | 284 | $ids = $_SESSION['refresh']['ids'] = implode(',', $ids); 285 | $table = $this->modx->getFullTableName('sg_images'); 286 | $q = $this->modx->db->query("SELECT COUNT(*) FROM {$table} WHERE `sg_rid` IN ({$ids})"); 287 | $total = $this->modx->db->getValue($q); 288 | $q = $this->modx->db->query("SELECT MIN(`sg_id`) FROM {$table} WHERE `sg_rid` IN ({$ids})"); 289 | $_SESSION['refresh']['minId'] = $this->modx->db->getValue($q); 290 | $out['success'] = true; 291 | $out['total'] = (int)$_SESSION['refresh']['total'] = $total; 292 | } 293 | } 294 | 295 | return $out; 296 | } 297 | 298 | /** 299 | * @return array 300 | */ 301 | public function getRefreshStatus() 302 | { 303 | $out = array(); 304 | 305 | $out['success'] = true; 306 | if (!isset($_SESSION['refresh']['processed'])) { 307 | $out['processed'] = 0; 308 | } else { 309 | $out['processed'] = $_SESSION['refresh']['processed'] < $_SESSION['refresh']['total'] ? $_SESSION['refresh']['processed'] : $_SESSION['refresh']['total']; 310 | } 311 | 312 | return $out; 313 | } 314 | 315 | /** 316 | * @return array 317 | */ 318 | public function processRefresh() 319 | { 320 | $out = array(); 321 | $_time = microtime(true); 322 | $ids = $_SESSION['refresh']['ids']; 323 | $table = $this->modx->getFullTableName('sg_images'); 324 | $minId = (int)$_SESSION['refresh']['minId']; 325 | $sql = "SELECT `sg`.*,`c`.`template` FROM {$table} `sg` LEFT JOIN {$this->modx->getFullTableName('site_content')} `c` ON `c`.`id` = `sg`.`sg_rid` WHERE `sg`.`sg_rid` IN ({$ids}) AND `sg`.`sg_id` >= {$minId} ORDER BY `sg`.`sg_id` ASC"; 326 | $rows = $this->modx->db->query($sql); //TODO 327 | while ($image = $this->modx->db->getRow($rows)) { 328 | $this->data->refresh($image, true); 329 | $_SESSION['refresh']['minId'] = $image['sg_id']; 330 | $_SESSION['refresh']['processed']++; 331 | $time = microtime(true) - $_time; 332 | if ($time > 25) break; 333 | } 334 | $out['success'] = true; 335 | 336 | return $this->getRefreshStatus(); 337 | } 338 | 339 | /** 340 | * 341 | */ 342 | public function dlInit() 343 | { 344 | parent::dlInit(); 345 | $this->dlParams['sortBy'] = 'sg_index'; 346 | $this->dlParams['sortDir'] = 'DESC'; 347 | $this->dlParams['dateSource'] = 'date'; 348 | $this->dlParams['prepare'] = function ($data) { 349 | $data['sg_properties'] = \jsonHelper::jsonDecode($data['sg_properties'], array('assoc' => true)); 350 | if (empty($data['sg_properties'])) { 351 | $data['sg_properties'] = array('width' => 0, 'height' => 0, 'size' => 0); 352 | } 353 | 354 | return $data; 355 | }; 356 | } 357 | } 358 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/lib/plugin.class.php: -------------------------------------------------------------------------------- 1 | params['templates'] ?? ''))), ','); 35 | $tpls = '[]'; 36 | if (!empty($templates)) { 37 | $table = $this->modx->getFullTableName('site_templates'); 38 | $sql = "SELECT `id`, `templatename` FROM {$table} WHERE `id` IN ({$templates}) ORDER BY `templatename` ASC"; 39 | $tpls = json_encode($this->modx->db->makeArray($this->modx->db->query($sql))); 40 | } 41 | $ph = array( 42 | 'lang' => evo()->getLocale(), 43 | 'url' => $this->modx->config['site_url'] . 'assets/plugins/simplegallery/ajax.php', 44 | 'site_url' => $this->modx->config['site_url'], 45 | 'manager_url' => MODX_MANAGER_URL, 46 | 'thumb_prefix' => $this->modx->config['site_url'] . 'assets/plugins/simplegallery/ajax.php?mode=thumb&url=', 47 | 'kcfinder_url' => MODX_MANAGER_URL . "media/browser/mcpuk/browse.php?type=images", 48 | 'w' => isset($this->params['w']) ? $this->params['w'] : '200', 49 | 'h' => isset($this->params['h']) ? $this->params['h'] : '150', 50 | 'refreshBtn' => (int)($_SESSION['mgrRole'] == 1), 51 | 'tpls' => $tpls, 52 | 'clientResize' => $this->params['clientResize'] == 'Yes' ? 53 | "{maxWidth: {$this->modx->config['maxImageWidth']}, maxHeight: {$this->modx->config['maxImageHeight']}, quality:{$this->params['jpegQuality']}}" : 54 | "{}" 55 | ); 56 | 57 | return array_merge($this->params, $ph); 58 | } 59 | 60 | public function copyFolders($src, $dst) { 61 | $dir = opendir($src); 62 | @mkdir($dst); 63 | while(false !== ( $file = readdir($dir)) ) { 64 | if (( $file != '.' ) && ( $file != '..' )) { 65 | if ( is_dir($src . '/' . $file) ) { 66 | $this->copyFolders($src . '/' . $file,$dst . '/' . $file); 67 | } 68 | else { 69 | copy($src . '/' . $file,$dst . '/' . $file); 70 | } 71 | } 72 | } 73 | closedir($dir); 74 | } 75 | 76 | /** 77 | * @return mixed 78 | */ 79 | public function createTable() 80 | { 81 | $sql = <<< OUT 82 | CREATE TABLE IF NOT EXISTS {$this->_table} ( 83 | `sg_id` int(10) NOT NULL auto_increment, 84 | `sg_image` TEXT NOT NULL, 85 | `sg_title` varchar(255) NOT NULL default '', 86 | `sg_description` TEXT NOT NULL, 87 | `sg_properties` TEXT NOT NULL, 88 | `sg_add` TEXT NOT NULL, 89 | `sg_isactive` int(1) NOT NULL default '1', 90 | `sg_rid` int(10) default NULL, 91 | `sg_index` int(10) NOT NULL default '0', 92 | `sg_createdon` datetime NOT NULL, 93 | PRIMARY KEY (`sg_id`), 94 | KEY `sg_rid` (`sg_rid`), 95 | KEY `sg_index` (`sg_index`), 96 | KEY `sg_isactive` (`sg_isactive`) 97 | ) ENGINE=MyISAM COMMENT='Datatable for SimpleGallery plugin.'; 98 | OUT; 99 | 100 | return $this->modx->db->query($sql); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/lib/table.class.php: -------------------------------------------------------------------------------- 1 | '', 26 | 'sg_title' => '', 27 | 'sg_description' => '', 28 | 'sg_properties' => '', 29 | 'sg_add' => '', 30 | 'sg_isactive' => 1, 31 | 'sg_rid' => 0, 32 | 'sg_index' => 0, 33 | 'sg_createdon' => '', 34 | ); 35 | public $thumbsCache = 'assets/.sgThumbs/'; 36 | protected $params = array(); 37 | /** 38 | * @var \Helpers\FS 39 | */ 40 | protected $fs = null; 41 | 42 | /** 43 | * @param $ids 44 | * @param int $rid 45 | * @param bool $fire_events 46 | * @return mixed 47 | */ 48 | public function deleteAll($ids, $rid, $fire_events = false) 49 | { 50 | $ids = $this->cleanIDs($ids, ',', array(0)); 51 | if (empty($ids) || is_scalar($ids)) { 52 | return false; 53 | } 54 | $_ids = $this->sanitarIn($ids); 55 | $images = $this->query("SELECT `sg`.*,`c`.`template` FROM {$this->makeTable($this->table)} `sg` LEFT JOIN {$this->makeTable($this->parentTable)} `c` ON `c`.`id` = `sg`.`sg_rid` WHERE `sg`.`sg_id` IN ({$_ids}) AND `sg`.`sg_rid`={$rid}"); 56 | $tmp = array(); 57 | while ($row = $this->modx->db->getRow($images)) { 58 | $row['filepath'] = $this->fs->takeFileDir($row['sg_image']); 59 | $row['name'] = $this->fs->takeFileName($row['sg_image']); 60 | $row['filename'] = $this->fs->takeFileBasename($row['sg_image']); 61 | $row['ext'] = $this->fs->takeFileExt($row['sg_image']); 62 | $row['mime'] = $this->fs->takeFileMIME($row['sg_image']); 63 | $results = $this->getInvokeEventResult('OnBeforeSimpleGalleryDelete',$row,$fire_events); 64 | $flag = is_array($results) && !empty($results); 65 | if (!$flag) $tmp[$row['sg_id']] = $row; 66 | } 67 | 68 | $ids = array_keys($tmp); 69 | $out = !empty($ids); 70 | if ($out) { 71 | $out = parent::deleteAll($ids, $rid, $fire_events); 72 | foreach ($tmp as $id => $image) { 73 | $this->deleteThumb($image['sg_image']); 74 | $this->invokeEvent('OnSimpleGalleryDelete', $image, $fire_events); 75 | } 76 | } 77 | 78 | return $out; 79 | } 80 | 81 | /** 82 | * @param $ids 83 | * @param $rid 84 | * @param int $to 85 | * @param bool $fire_events 86 | * @return bool 87 | */ 88 | public function move($ids, $rid, $to, $fire_events = false) 89 | { 90 | $ids = $this->cleanIDs($ids, ',', array(0)); 91 | $templates = isset($this->params['templates']) ? $this->params['templates'] : array(); 92 | $templates = $this->cleanIDs($templates, ',', array(0)); 93 | $documents = isset($this->params['documents']) ? $this->params['documents'] : array(); 94 | $documents = $this->cleanIDs($documents, ',', array(0)); 95 | $ignoreDocuments = isset($this->params['ignoreDoc']) ? $this->params['ignoreDoc'] : array(); 96 | $ignoreDocuments = $this->cleanIDs($ignoreDocuments, ',', array(0)); 97 | 98 | if (empty($ids) || !$to) { 99 | return false; 100 | } 101 | 102 | $template = $this->getTemplate($to); 103 | $flag = false; 104 | if (!empty($templates) && in_array($template, $templates)) { 105 | $flag = true; 106 | } 107 | if (!empty($documents) && in_array($to,$documents) &&!in_array($to,$ignoreDocuments)) { 108 | $flag = $flag || true; 109 | } 110 | if (!$flag) { 111 | return false; 112 | } 113 | 114 | $ids = implode(',', $ids); 115 | $rows = $this->query("SELECT `sg_id`,`sg_image` FROM {$this->makeTable($this->table)} WHERE `sg_id` IN ({$ids})"); 116 | $images = $this->modx->db->makeArray($rows); 117 | $_old = $this->params['folder'] . $rid . '/'; 118 | $_new = $this->params['folder'] . $to . '/'; 119 | $flag = $this->fs->makeDir(MODX_BASE_PATH . $_new, $this->modx->config['new_folder_permissions']); 120 | if ($flag) { 121 | foreach ($images as $image) { 122 | $oldFile = MODX_BASE_PATH . $image['sg_image']; 123 | $newFile = str_replace($_old, $_new, $oldFile); 124 | if (!@rename($oldFile, $newFile)) { 125 | $this->modx->logEvent(0, 3, "Cannot move {$oldFile} to {$_new}", "SimpleGallery"); 126 | } else { 127 | $this->deleteThumb($image['sg_image']); 128 | $this->invokeEvent('OnSimpleGalleryMove', array( 129 | 'sg_id' => $image['sg_id'], 130 | 'sg_image' => $image['sg_image'], 131 | 'sg_rid' => $rid, 132 | 'to' => $to, 133 | 'oldFile' => $oldFile, 134 | 'newFile' => $newFile, 135 | 'template' => $template 136 | ), $fire_events); 137 | } 138 | } 139 | $rows = $this->query("SELECT count(`sg_id`) FROM {$this->makeTable($this->table)} WHERE `sg_rid`={$to}"); 140 | $index = $this->modx->db->getValue($rows); 141 | $this->query("UPDATE {$this->makeTable($this->table)} SET `sg_rid` = {$to}, `sg_image` = REPLACE(`sg_image`,'{$_old}','{$_new}') WHERE (`sg_id` IN ({$ids})) ORDER BY `sg_index` ASC"); 142 | $out = $this->modx->db->getAffectedRows(); 143 | $this->clearIndexes($ids, $rid); 144 | $this->query("SET @index := " . ($index - 1)); 145 | $this->query("UPDATE {$this->makeTable($this->table)} SET `sg_index` = (@index := @index + 1) WHERE (`sg_id` IN ({$ids})) ORDER BY `sg_index` ASC"); 146 | } else { 147 | $this->modx->logEvent(0, 3, "Cannot create {$_new} folder", "SimpleGallery"); 148 | $out = false; 149 | } 150 | 151 | return $out; 152 | } 153 | 154 | /** 155 | * @param $key 156 | * @return mixed 157 | */ 158 | public function get($key) 159 | { 160 | switch ($key) { 161 | case 'filepath': { 162 | $image = $this->get('sg_image'); 163 | $out = $this->fs->takeFileDir($image); 164 | break; 165 | } 166 | case 'filename': { 167 | $image = $this->get('sg_image'); 168 | $out = $this->fs->takeFileBasename($image); 169 | break; 170 | } 171 | case 'ext': { 172 | $image = $this->get('sg_image'); 173 | $out = $this->fs->takeFileExt($image); 174 | break; 175 | } 176 | case 'mime': { 177 | $image = $this->get('sg_image'); 178 | $out = $this->fs->takeFileMIME($image); 179 | break; 180 | } 181 | default: { 182 | $out = parent::get($key); 183 | } 184 | } 185 | 186 | return $out; 187 | } 188 | 189 | /** 190 | * @param $key 191 | * @param $value 192 | * @return $this 193 | */ 194 | public function set($key, $value) 195 | { 196 | switch ($key) { 197 | case 'sg_image': { 198 | if (empty($value) || !is_scalar($value) || !$this->fs->checkFile($value)) { 199 | $value = ''; 200 | } 201 | break; 202 | } 203 | case 'sg_isactive': 204 | case 'sg_rid': 205 | case 'sg_index': { 206 | $value = (int)$value; 207 | if ($value < 0) { 208 | $value = 0; 209 | } 210 | break; 211 | } 212 | case 'sg_createdon': 213 | case 'sg_add': 214 | case 'sg_description': 215 | case 'sg_title': { 216 | if (!is_scalar($value)) { 217 | $value = ''; 218 | } 219 | break; 220 | } 221 | } 222 | parent::set($key, $value); 223 | 224 | return $this; 225 | } 226 | 227 | /** 228 | * @param bool $fire_events 229 | * @param bool $clearCache 230 | * @return bool|int|null 231 | */ 232 | public function save($fire_events = false, $clearCache = false) 233 | { 234 | $out = $this->_save($fire_events, $clearCache); 235 | if ($out === false) { 236 | $this->modx->logEvent(0, 3, implode("
", $this->getLog()), 'SimpleGallery'); 237 | $this->clearLog(); 238 | } 239 | 240 | return $out; 241 | } 242 | 243 | /** 244 | * @param bool $fire_events 245 | * @param bool $clearCache 246 | * @return int|null 247 | */ 248 | protected function _save($fire_events = false, $clearCache = false) 249 | { 250 | if (empty($this->field['sg_image'])) { 251 | $this->log['emptyImage'] = 'Image is empty in
' . print_r($this->field, true) . '
'; 252 | 253 | return false; 254 | } 255 | $rid = $this->get('sg_rid'); 256 | if (empty($rid)) { 257 | $rid = $this->default_field['sg_rid']; 258 | } 259 | $rid = (int)$rid; 260 | 261 | $template = $this->getTemplate($rid); 262 | $this->set('template', $template); 263 | if ($this->newDoc) { 264 | $q = $this->query('SELECT count(`sg_id`) FROM ' . $this->makeTable($this->table) . ' WHERE `sg_rid`=' . $rid); 265 | $this->field['sg_index'] = $this->modx->db->getValue($q); 266 | $this->touch('sg_createdon'); 267 | } 268 | 269 | $fields = $this->toArray(); 270 | $fields['sgObj'] = $this; 271 | $fields['newDoc'] = $this->newDoc; 272 | $results = $this->getInvokeEventResult('OnBeforeSimpleGallerySave', $fields, $fire_events); 273 | $flag = is_array($results) && !empty($results); 274 | $out = null; 275 | if (!$flag && ($out = parent::save($fire_events, $clearCache))) { 276 | $fields = $this->toArray(); 277 | $this->invokeEvent('OnSimpleGallerySave', $fields, $fire_events); 278 | } 279 | 280 | return $out; 281 | } 282 | 283 | /** 284 | * @param int|array $item 285 | * @param bool $fire_events 286 | */ 287 | public function refresh($item, $fire_events = false) 288 | { 289 | $fields = array(); 290 | if (is_int($item)) { 291 | $this->edit($item); 292 | if ($this->getID()) { 293 | $fields = $this->toArray(); 294 | $fields['template'] = $this->getTemplate($fields['sg_rid']); 295 | $fields['filepath'] = $this->get('filepath'); 296 | $fields['filename'] = $this->get('filename'); 297 | } 298 | } elseif (is_array($item)) { 299 | $fields = $item; 300 | $fields['sg_properties'] = \jsonHelper::jsonDecode($fields['sg_properties'], array('assoc' => true), true); 301 | $fields['filepath'] = $this->fs->takeFileDir($fields['sg_image']); 302 | $fields['filename'] = $this->fs->takeFileBasename($fields['sg_image']); 303 | } 304 | if ($fields) { 305 | $this->invokeEvent('OnSimpleGalleryRefresh', $fields, $fire_events); 306 | } 307 | } 308 | 309 | /** 310 | * @param $rid 311 | * @return mixed 312 | */ 313 | protected function getTemplate($rid) 314 | { 315 | $q = $this->query("SELECT `template` FROM {$this->makeTable($this->parentTable)} WHERE `id`={$rid} LIMIT 1"); 316 | 317 | return $this->modx->db->getValue($q); 318 | } 319 | 320 | /** 321 | * @param $file 322 | * @param $rid 323 | * @param array|string $data 324 | * @param bool $fire_events 325 | * @return bool|int 326 | */ 327 | public function upload($file, $rid, $data = '', $fire_events = false) 328 | { 329 | $out = false; 330 | $file = $this->fs->relativePath($file); 331 | if (!$this->fs->checkFile($file)) { 332 | $this->log['fileFailed'] = 'File check failed: ' . $file; 333 | 334 | return $out; 335 | } 336 | $info = getimagesize(MODX_BASE_PATH . $file); 337 | $options = array(); 338 | if ($info[0] > $this->modx->config['maxImageWidth'] || $info[1] > $this->modx->config['maxImageHeight']) { 339 | $options[] = "w={$this->modx->config['maxImageWidth']}&h={$this->modx->config['maxImageHeight']}"; 340 | } 341 | 342 | $ext = $this->fs->takeFileExt($file, true); 343 | if (in_array($ext, array('jpg', 'jpeg')) && isset($this->params['jpegQuality'])) { 344 | $quality = 100 * $this->params['jpegQuality']; 345 | $options[] = "q={$quality}&ar=x"; 346 | } 347 | 348 | $options = implode('&', $options); 349 | if (empty($options) || (isset($this->params['clientResize']) && $this->params['clientResize'] == 'Yes') || (isset($this->params['skipPHPThumb']) && $this->params['skipPHPThumb'] == 'Yes') ? true : @$this->makeThumb('', 350 | $this->fs->relativePath($file), $options) 351 | ) { 352 | $info = getimagesize(MODX_BASE_PATH . $file); 353 | $properties = array( 354 | 'width' => $info[0], 355 | 'height' => $info[1], 356 | 'size' => $this->fs->fileSize($file) 357 | ); 358 | $this->create(array( 359 | 'sg_image' => $this->fs->relativePath($file), 360 | 'sg_rid' => $rid, 361 | 'sg_properties' => $properties 362 | )); 363 | if (is_array($data)) { 364 | $this->fromArray($data); 365 | } elseif (is_scalar($data)) { 366 | $this->set('sg_title', $data); 367 | } 368 | 369 | $results = $this->getInvokeEventResult('OnBeforeFileBrowserUpload', array( 370 | 'sgObj' => $this, 371 | 'filepath' => $this->get('filepath'), 372 | 'filename' => $this->get('filename'), 373 | 'template' => $this->get('template'), 374 | 'sg_rid' => $rid 375 | ), $fire_events); 376 | $flag = is_array($results) && !empty($results); 377 | if (!$flag) { 378 | $out = $this->save($fire_events); 379 | } 380 | if ($out) { 381 | $this->invokeEvent('OnFileBrowserUpload', array( 382 | 'sgObj' => $this, 383 | 'filepath' => $this->get('filepath'), 384 | 'filename' => $this->get('filename'), 385 | 'template' => $this->get('template'), 386 | 'sg_rid' => $rid 387 | ), $fire_events); 388 | $this->makeBackEndThumb($this->get('sg_image')); 389 | } 390 | } 391 | 392 | return $out; 393 | } 394 | 395 | /** 396 | * @param $url 397 | * @return bool 398 | */ 399 | public function makeBackEndThumb($url) 400 | { 401 | $w = 140; 402 | $h = 105; 403 | $thumbsCache = $this->thumbsCache; 404 | if (isset($this->params)) { 405 | if (isset($this->params['thumbsCache'])) { 406 | $thumbsCache = $this->params['thumbsCache']; 407 | } 408 | if (isset($this->params['w'])) { 409 | $w = $this->params['w']; 410 | } 411 | if (isset($this->params['h'])) { 412 | $h = $this->params['h']; 413 | } 414 | } 415 | $thumbOptions = isset($this->params['customThumbOptions']) ? $this->params['customThumbOptions'] : 'w=[+w+]&h=[+h+]&far=C&bg=FFFFFF&f=jpg'; 416 | $thumbOptions = urldecode(str_replace(array('[+w+]', '[+h+]'), array($w, $h), $thumbOptions)); 417 | return $this->makeThumb($thumbsCache, $url, $thumbOptions); 418 | } 419 | } 420 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/plugin.sgthumb.php: -------------------------------------------------------------------------------- 1 | event; 13 | if (!function_exists('getThumbConfig')) { 14 | function getThumbConfig($tconfig,$rid,$template) { 15 | $out = array(); 16 | include_once (MODX_BASE_PATH.'assets/snippets/DocLister/lib/jsonHelper.class.php'); 17 | $thumbs = \jsonHelper::jsonDecode(urldecode($tconfig), array('assoc' => true), true); 18 | foreach ($thumbs as $thumb) { 19 | if (isset($thumb['rid'])) { 20 | $_rid = explode(',',$thumb['rid']); 21 | if (in_array($rid, $_rid)) $out[] = $thumb; 22 | } elseif (isset($thumb['template'])) { 23 | $_template = explode(',',$thumb['template']); 24 | if (in_array($template, $_template)) $out[] = $thumb; 25 | } 26 | } 27 | return $out; 28 | } 29 | } 30 | if (!isset($template)) { 31 | return; 32 | } 33 | $fs = \Helpers\FS::getInstance(); 34 | $thumbConfig = getThumbConfig($tconfig,$sg_rid,$template); 35 | $keepOriginal = $keepOriginal == 'Yes' && !empty($originalFolder); 36 | if ($keepOriginal) { 37 | $originalFolder = $filepath.'/'.$originalFolder; 38 | $fs->makeDir($originalFolder); 39 | } 40 | if ($e->name == 'OnFileBrowserUpload' && $keepOriginal) { 41 | $fs->copyFile($filepath.'/'.$filename,$originalFolder.'/'.$filename); 42 | } 43 | if ($e->name == 'OnSimpleGalleryRefresh' && $keepOriginal) { 44 | $file = $originalFolder.'/'.$filename; 45 | if ($fs->checkFile($file)) { 46 | $fs->copyFile($file,$filepath.'/'.$filename); 47 | } else { 48 | $fs->copyFile($filepath.'/'.$filename,$file); 49 | } 50 | } 51 | if ($e->name == "OnFileBrowserUpload" || $e->name == "OnSimpleGalleryRefresh") { 52 | $thumb = new \Helpers\PHPThumb(); 53 | $thumb->optimize($filepath.'/'.$filename); 54 | if (!empty($thumbConfig)) { 55 | foreach ($thumbConfig as $_thumbConfig) { 56 | extract($_thumbConfig); 57 | $thumb = new \Helpers\PHPThumb(); 58 | $fs->makeDir($filepath.'/'.$folder); 59 | $thumb->create($filepath.'/'.$filename,$filepath.'/'.$folder.'/'.$filename,$options); 60 | $thumb->optimize($filepath.'/'.$folder.'/'.$filename); 61 | } 62 | } 63 | } 64 | if ($e->name == "OnSimpleGalleryDelete") { 65 | if ($keepOriginal) { 66 | $file = $originalFolder.'/'.$filename; 67 | $fs->unlink($file); 68 | } 69 | if (!empty($thumbConfig)) { 70 | foreach ($thumbConfig as $_thumbConfig) { 71 | extract($_thumbConfig); 72 | $file = $filepath.'/'.$folder.'/'.$filename; 73 | $fs->unlink($file); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/plugin.simplegallery.php: -------------------------------------------------------------------------------- 1 | event; 6 | if ($e->name == 'OnDocFormRender') { 7 | include_once(MODX_BASE_PATH . 'assets/plugins/simplegallery/lib/plugin.class.php'); 8 | global $richtexteditorIds; 9 | //Hack to check if TinyMCE scripts are loaded 10 | if (isset($richtexteditorIds['TinyMCE4'])) { 11 | $modx->loadedjscripts['TinyMCE4'] = array('version' => '4.3.6'); 12 | } 13 | $plugin = new \SimpleGallery\sgPlugin($modx, $modx->getConfig('lang_code')); 14 | if ($id) { 15 | $output = $plugin->render(); 16 | } else { 17 | $output = $plugin->renderEmpty(); 18 | } 19 | if ($output) { 20 | $modx->event->output($output); 21 | } 22 | } 23 | if ($e->name == 'OnEmptyTrash') { 24 | if (empty($ids)) { 25 | return; 26 | } 27 | include_once(MODX_BASE_PATH . 'assets/plugins/simplegallery/lib/plugin.class.php'); 28 | $plugin = new \SimpleGallery\sgPlugin($modx); 29 | $where = implode(',', $ids); 30 | $modx->db->delete($plugin->_table, "`sg_rid` IN ({$where})"); 31 | $plugin->clearFolders($ids, MODX_BASE_PATH . $e->params['thumbsCache'] . $e->params['folder']); 32 | $plugin->clearFolders($ids, MODX_BASE_PATH . $e->params['folder']); 33 | $sql = "ALTER TABLE {$plugin->_table} AUTO_INCREMENT = 1"; 34 | $rows = $modx->db->query($sql); 35 | } 36 | if ($e->name == 'OnDocDuplicate' && isset($allowDuplicate) && $allowDuplicate == 'Yes') { 37 | include_once(MODX_BASE_PATH . 'assets/plugins/simplegallery/lib/plugin.class.php'); 38 | $plugin = new \SimpleGallery\sgPlugin($modx); 39 | $sql = "SHOW COLUMNS FROM {$plugin->_table}"; 40 | $rows = $modx->db->query($sql); 41 | $columns = array(); 42 | while ($row = $modx->db->getRow($rows)) { 43 | if ($row['Key'] == 'PRI') { 44 | continue; 45 | } 46 | $columns[] = '`' . $row['Field'] . '`'; 47 | } 48 | $q = $modx->db->query("SELECT `sg_id` FROM {$plugin->_table} WHERE `sg_rid`={$id} LIMIT 1"); 49 | if (!$modx->db->getValue($q)) { 50 | return; 51 | } 52 | $fields = implode(',', $columns); 53 | $oldFolder = $e->params['folder'] . $id . '/'; 54 | $newFolder = $e->params['folder'] . $new_id . '/'; 55 | $values = str_replace(['`sg_rid`', '`sg_image`'], [$new_id, "REPLACE(`sg_image`,'{$oldFolder}', '{$newFolder}')"], 56 | $fields); 57 | $sql = "INSERT INTO {$plugin->_table} ({$fields}) SELECT {$values} FROM {$plugin->_table} WHERE `sg_rid`={$id}"; 58 | $modx->db->query($sql); 59 | $plugin->copyFolders(MODX_BASE_PATH . $oldFolder, MODX_BASE_PATH . $newFolder); 60 | $oldFolder = $e->params['thumbsCache'] . $e->params['folder'] . $id . '/'; 61 | $newFolder = $e->params['thumbsCache'] . $e->params['folder'] . $new_id . '/'; 62 | $plugin->copyFolders(MODX_BASE_PATH . $oldFolder, MODX_BASE_PATH . $newFolder); 63 | } 64 | -------------------------------------------------------------------------------- /assets/plugins/simplegallery/tpl/empty.tpl: -------------------------------------------------------------------------------- 1 |
2 |

[+tabName+]

3 | 6 |
-------------------------------------------------------------------------------- /assets/plugins/simplegallery/tpl/simplegallery.tpl: -------------------------------------------------------------------------------- 1 | 13 | 43 |
44 |

[+tabName+]

45 |
46 | -------------------------------------------------------------------------------- /assets/snippets/simplegallery/config/sgLister.json: -------------------------------------------------------------------------------- 1 | { 2 | "table": "sg_images", 3 | "idField": "sg_id", 4 | "parentField" : "sg_rid", 5 | "idType": "parents", 6 | "ignoreEmpty": "1", 7 | "orderBy": "sg_index DESC", 8 | "prepare": "", 9 | "addWhereList" : "`sg_isactive`=1", 10 | "thumbOptions" : "hp=90&wl=90&far=C", 11 | "imageField" : "sg_image", 12 | "noneWrapOuter" : "0", 13 | "e" : "sg_title,sg_description,sg_add" 14 | } 15 | -------------------------------------------------------------------------------- /assets/snippets/simplegallery/controller/sg_site_content.php: -------------------------------------------------------------------------------- 1 | , kabachello 13 | * 14 | * @TODO add parameter showFolder - include document container in result data whithout children document if you set depth parameter. 15 | * @TODO st placeholder [+dl.title+] if menutitle not empty 16 | */ 17 | include_once(MODX_BASE_PATH . 'assets/snippets/DocLister/core/controller/site_content.php'); 18 | class sg_site_contentDocLister extends site_contentDocLister 19 | { 20 | public function getDocs($tvlist = '') 21 | { 22 | $docs = parent::getDocs($tvlist); 23 | 24 | $table = $this->getTable('sg_images'); 25 | $rid = $this->modx->db->escape(implode(',',array_keys($docs))); 26 | $sgOrderBy = $this->modx->db->escape($this->getCFGDef('sgOrderBy','sg_index ASC')); 27 | 28 | $sgDisplay = $this->getCFGDef('sgDisplay','all'); 29 | $sgAddWhereList = $this->getCFGDef('sgAddWhereList',''); 30 | 31 | if (!empty($sgAddWhereList)) $sgAddWhereList = ' AND ('.$sgAddWhereList.')'; 32 | if (!empty($rid) && ($sgDisplay == 'all' || is_numeric($sgDisplay))) { 33 | switch ($sgDisplay) { 34 | case 'all': 35 | $sql = "SELECT * FROM {$table} WHERE `sg_rid` IN ({$rid}) {$sgAddWhereList} ORDER BY {$sgOrderBy}"; 36 | break; 37 | case '1': 38 | $sql = "SELECT * FROM (SELECT * FROM {$table} WHERE `sg_rid` IN ({$rid}) {$sgAddWhereList} ORDER BY {$sgOrderBy} LIMIT 4294967295) sg GROUP BY sg_rid"; 39 | break; 40 | default: 41 | $sql = "SELECT * FROM (SELECT *, @rn := IF(@prev = `sg_rid`, @rn + 1, 1) AS rn, @prev := `sg_rid` FROM {$table} JOIN (SELECT @prev := NULL, @rn := 0) AS vars WHERE `sg_rid` IN ({$rid}) ORDER BY sg_rid, {$sgOrderBy}) AS sg WHERE rn <= {$sgDisplay}"; 42 | break; 43 | } 44 | $images = $this->dbQuery($sql); 45 | $count = $this->getCFGDef('count',0); 46 | if ($count) { 47 | $sql = "SELECT `sg_rid`, COUNT(`sg_rid`) AS cnt FROM {$table} WHERE `sg_rid` IN ({$rid}) {$sgAddWhereList} GROUP BY sg_rid"; 48 | $_count = $this->dbQuery($sql); 49 | while ($count = $this->modx->db->getRow($_count)) { 50 | $_rid = $count['sg_rid']; 51 | $docs[$_rid]['count'] = $count['cnt']; 52 | } 53 | } 54 | while ($image = $this->modx->db->getRow($images)) { 55 | $_rid = $image['sg_rid']; 56 | $docs[$_rid]['images'][] = $image; 57 | } 58 | } 59 | $this->_docs = $docs; 60 | return $docs; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /assets/snippets/simplegallery/sgController.php: -------------------------------------------------------------------------------- 1 | event->params, 'BeforePrepare', ''); 6 | $prepare[] = 'DLsgController::prepare'; 7 | $prepare[] = \APIhelpers::getkey($modx->event->params, 'AfterPrepare', ''); 8 | $modx->event->params['prepare'] = trim(implode(',', $prepare), ','); 9 | 10 | $params = array_merge(array( 11 | 'controller' => 'sg_site_content', 12 | 'dir' => 'assets/snippets/simplegallery/controller/' 13 | ), $modx->event->params); 14 | if (!class_exists('DLsgController', false)) { 15 | /** 16 | * Class DLsgController 17 | */ 18 | class DLsgController 19 | { 20 | /** 21 | * @param array $data 22 | * @param DocumentParser $modx 23 | * @param $_DocLister 24 | * @param prepare_DL_Extender $_extDocLister 25 | * @return array 26 | */ 27 | public static function prepare ( 28 | array $data, 29 | DocumentParser $modx, 30 | $_DocLister 31 | ) { 32 | if (isset($data['images'])) { 33 | $wrapper = ''; 34 | $imageField = $_DocLister->getCfgDef('imageField', 'sg_image'); 35 | $thumbOptions = $_DocLister->getCfgDef('thumbOptions'); 36 | $thumbSnippet = $_DocLister->getCfgDef('thumbSnippet'); 37 | foreach ($data['images'] as $image) { 38 | $ph = $image; 39 | if (!empty($thumbOptions) && !empty($thumbSnippet)) { 40 | $_thumbOptions = jsonHelper::jsonDecode($thumbOptions, ['assoc' => true], true); 41 | if (!empty($_thumbOptions) && is_array($_thumbOptions)) { 42 | foreach ($_thumbOptions as $key => $value) { 43 | $postfix = $key == 'default' ? '.' : '_' . $key . '.'; 44 | $ph['thumb' . $postfix . $imageField] = $modx->runSnippet($thumbSnippet, array( 45 | 'input' => $ph[$imageField], 46 | 'options' => $value 47 | )); 48 | $file = MODX_BASE_PATH . $ph['thumb' . $postfix . $imageField]; 49 | if (file_exists($file) && is_readable($file) && ($info = getimagesize($file))) { 50 | $ph['thumb' . $postfix . 'width.' . $imageField] = $info[0]; 51 | $ph['thumb' . $postfix . 'height.' . $imageField] = $info[1]; 52 | } 53 | } 54 | } else { 55 | $ph['thumb.' . $imageField] = $modx->runSnippet($thumbSnippet, array( 56 | 'input' => $ph[$imageField], 57 | 'options' => $thumbOptions 58 | )); 59 | $file = MODX_BASE_PATH . $ph['thumb.' . $imageField]; 60 | if (file_exists($file) && is_readable($file) && ($info = getimagesize($file))) { 61 | $ph['thumb.width.' . $imageField] = $info[0]; 62 | $ph['thumb.height.' . $imageField] = $info[1]; 63 | } 64 | } 65 | } 66 | //сделали превьюшку 67 | 68 | $ph['e.sg_title'] = htmlentities($image['sg_title'], ENT_COMPAT, 'UTF-8', false); 69 | $ph['e.sg_description'] = htmlentities($image['sg_description'], ENT_COMPAT, 'UTF-8', false); 70 | //добавили поля e.sg_title и e.sg_description 71 | $properties = jsonHelper::jsonDecode($image['sg_properties'], ['assoc' => true], true); 72 | if (is_array($properties)) { 73 | foreach ($properties as $key => $value) { 74 | $ph['properties.' . $key] = $value; 75 | } 76 | } 77 | $wrapper .= $_DocLister->parseChunk($_DocLister->getCfgDef('sgRowTpl'), $ph); 78 | //обработали чанк sgRowTpl - для каждой картинки 79 | } 80 | $data['images'] = $_DocLister->parseChunk($_DocLister->getCfgDef('sgOuterTpl'), array('wrapper' => $wrapper)); 81 | //обработали чанк sgOuterTpl 82 | } 83 | 84 | return $data; 85 | } 86 | } 87 | } 88 | 89 | return $modx->runSnippet('DocLister', $params); 90 | -------------------------------------------------------------------------------- /assets/snippets/simplegallery/sgLister.php: -------------------------------------------------------------------------------- 1 | event->params, 'BeforePrepare', ''); 24 | $prepare = array_merge($prepare, $_prepare); 25 | $prepare[] = 'DLsgLister::prepare'; 26 | $prepare[] = \APIhelpers::getkey($modx->event->params, 'AfterPrepare', ''); 27 | $modx->event->params['prepare'] = trim(implode(',', $prepare), ','); 28 | 29 | $params = array_merge(array( 30 | 'depth' => 0, 31 | 'controller' => 'onetable', 32 | 'config' => 'sgLister:assets/snippets/simplegallery/config/' 33 | ), $modx->event->params, array( 34 | 'showParent' => '-1' 35 | )); 36 | 37 | if (!class_exists('DLsgLister', false)) { 38 | class DLsgLister 39 | { 40 | public static function prepare ( 41 | array $data, 42 | DocumentParser $modx, 43 | $_DL 44 | ) { 45 | $imageField = $_DL->getCfgDef('imageField'); 46 | $thumbOptions = $_DL->getCfgDef('thumbOptions'); 47 | $thumbSnippet = $_DL->getCfgDef('thumbSnippet'); 48 | if (!empty($thumbOptions) && !empty($thumbSnippet)) { 49 | $_thumbOptions = jsonHelper::jsonDecode($thumbOptions, ['assoc' => true], true); 50 | if (!empty($_thumbOptions) && is_array($_thumbOptions)) { 51 | foreach ($_thumbOptions as $key => $value) { 52 | $postfix = $key == 'default' ? '.' : '_' . $key . '.'; 53 | $data['thumb' . $postfix . $imageField] = $modx->runSnippet($thumbSnippet, array( 54 | 'input' => $data[$imageField], 55 | 'options' => $value 56 | )); 57 | $fileFull = urldecode(MODX_BASE_PATH . $data['thumb' . $postfix . $imageField]); 58 | if (file_exists($fileFull)) { 59 | $info = getimagesize($fileFull); 60 | if ($info) { 61 | $data['thumb' . $postfix . 'width.' . $imageField] = $info[0]; 62 | $data['thumb' . $postfix . 'height.' . $imageField] = $info[1]; 63 | } 64 | } 65 | } 66 | } else { 67 | $data['thumb.' . $imageField] = $modx->runSnippet($thumbSnippet, array( 68 | 'input' => $data[$imageField], 69 | 'options' => $thumbOptions 70 | )); 71 | $fileFull = urldecode(MODX_BASE_PATH . $data['thumb.' . $imageField]); 72 | if (file_exists($fileFull)) { 73 | $info = getimagesize($fileFull); 74 | if ($info) { 75 | $data['thumb.width.' . $imageField] = $info[0]; 76 | $data['thumb.height.' . $imageField] = $info[1]; 77 | } 78 | } 79 | } 80 | } 81 | $properties = jsonHelper::jsonDecode($data['sg_properties'], ['assoc' => true], true); 82 | if (is_array($properties)) { 83 | foreach ($properties as $key => $value) { 84 | $data['properties.' . $key] = $value; 85 | } 86 | } 87 | 88 | return $data; 89 | } 90 | } 91 | } 92 | 93 | return $modx->runSnippet('DocLister', $params); 94 | -------------------------------------------------------------------------------- /assets/snippets/simplegallery/sgThumb.php: -------------------------------------------------------------------------------- 1 |