Explorar el Código

#294 Uploader with cropping: apply to cover photos in Persons, Orgs and Groups

Alex Trofimov hace 10 años
padre
commit
7a6a13c8d5
Se han modificado 37 ficheros con 418 adiciones y 170 borrados
  1. 4 4
      inc/classes/BxDolUploader.php
  2. 1 1
      modules/base/general/classes/BxBaseModGeneralFormEntry.php
  3. 4 2
      modules/base/general/classes/BxBaseModGeneralFormsEntryHelper.php
  4. 35 121
      modules/base/profile/classes/BxBaseModProfileFormEntry.php
  5. 3 0
      modules/base/profile/classes/BxBaseModProfileFormsEntryHelper.php
  6. 72 0
      modules/base/profile/classes/BxBaseModProfileUploaderCoverCrop.php
  7. 70 0
      modules/base/profile/classes/BxBaseModProfileUploaderPictureCrop.php
  8. 4 0
      modules/base/profile/template/css/forms.css
  9. 44 0
      modules/base/profile/template/uploader_form_crop_cover.html
  10. 1 1
      modules/base/text/classes/BxBaseModTextFormEntry.php
  11. 2 2
      modules/boonex/albums/classes/BxAlbumsFormEntry.php
  12. 2 2
      modules/boonex/groups/classes/BxGroupsConfig.php
  13. 21 0
      modules/boonex/groups/classes/BxGroupsUploaderCoverCrop.php
  14. 21 0
      modules/boonex/groups/classes/BxGroupsUploaderPictureCrop.php
  15. 4 0
      modules/boonex/groups/install/sql/disable.sql
  16. 6 0
      modules/boonex/groups/install/sql/enable.sql
  17. 2 10
      modules/boonex/groups/install/sql/install.sql
  18. 1 0
      modules/boonex/groups/template/uploader_form_crop_cover.html
  19. 2 2
      modules/boonex/market/classes/BxMarketFormEntry.php
  20. 2 2
      modules/boonex/organizations/classes/BxOrgsConfig.php
  21. 21 0
      modules/boonex/organizations/classes/BxOrgsUploaderCoverCrop.php
  22. 21 0
      modules/boonex/organizations/classes/BxOrgsUploaderPictureCrop.php
  23. 3 0
      modules/boonex/organizations/install/sql/disable.sql
  24. 6 0
      modules/boonex/organizations/install/sql/enable.sql
  25. 2 8
      modules/boonex/organizations/install/sql/install.sql
  26. 1 0
      modules/boonex/organizations/template/uploader_form_crop_cover.html
  27. 2 2
      modules/boonex/persons/classes/BxPersonsConfig.php
  28. 21 0
      modules/boonex/persons/classes/BxPersonsUploaderCoverCrop.php
  29. 21 0
      modules/boonex/persons/classes/BxPersonsUploaderPictureCrop.php
  30. 3 0
      modules/boonex/persons/install/sql/disable.sql
  31. 4 0
      modules/boonex/persons/install/sql/enable.sql
  32. 2 8
      modules/boonex/persons/install/sql/install.sql
  33. 1 0
      modules/boonex/persons/template/uploader_form_crop_cover.html
  34. 3 1
      template/scripts/BxBaseUploaderCrop.php
  35. 3 2
      template/scripts/BxBaseUploaderHTML5.php
  36. 2 1
      template/scripts/BxBaseUploaderSimple.php
  37. 1 1
      template/uploader_button_crop_js.html

+ 4 - 4
inc/classes/BxDolUploader.php

@@ -217,7 +217,7 @@ abstract class BxDolUploader extends BxDol
             $aMultipleFiles = array($mixedFiles);
 
         if (!$isMultiple)
-            $this->cleanupGhostsForProfile($iProfileId, $iContentId);
+            $this->deleteGhostsForProfile($iProfileId, $iContentId);
 
         foreach ($aMultipleFiles as $aFile) {
 
@@ -379,15 +379,15 @@ abstract class BxDolUploader extends BxDol
      * Delete all ghosts files for the specified profile
      * @return number of delete ghost files
      */
-    public function cleanupGhostsForProfile($iProfileId, $iContentId = false)
+    public function deleteGhostsForProfile($iProfileId, $iContentId = false)
     {
         $iCount = 0;
 
         $oStorage = BxDolStorage::getObjectInstance($this->_sStorageObject);
 
-        $aGhosts = $oStorage->getGhosts($iProfileId, $iContentId);
+        $aGhosts = $oStorage->getGhosts($iProfileId, $iContentId, $iContentId ? true : false);
         foreach ($aGhosts as $aFile)
-            $iCount += $oStorage->afterUploadCleanup($aFile['id'], $iProfileId);
+            $iCount += $oStorage->deleteFile($aFile['id']);
 
         return $iCount;
     }

+ 1 - 1
modules/base/general/classes/BxBaseModGeneralFormEntry.php

@@ -163,7 +163,7 @@ class BxBaseModGeneralFormEntry extends BxTemplFormView
             if ($aFile['private'])
                 $oStorage->setFilePrivate ($aFile['id'], 0);
             if ($iContentId)
-                $this->_associalFileWithContent($oStorage, $aFile['id'], $iProfileId, $iContentId);
+                $this->_associalFileWithContent($oStorage, $aFile['id'], $iProfileId, $iContentId, $sFieldFile);
         }
 
         return true;

+ 4 - 2
modules/base/general/classes/BxBaseModGeneralFormsEntryHelper.php

@@ -32,9 +32,11 @@ class BxBaseModGeneralFormsEntryHelper extends BxDolProfileForms
         return BxDolForm::getObjectInstance($this->_oModule->_oConfig->CNF['OBJECT_FORM_ENTRY'], $this->_oModule->_oConfig->CNF['OBJECT_FORM_ENTRY_DISPLAY_ADD'], $this->_oModule->_oTemplate);
     }
 
-    public function getObjectFormEdit ()
+    public function getObjectFormEdit ($sDisplay = false)
     {
-        return BxDolForm::getObjectInstance($this->_oModule->_oConfig->CNF['OBJECT_FORM_ENTRY'], $this->_oModule->_oConfig->CNF['OBJECT_FORM_ENTRY_DISPLAY_EDIT'], $this->_oModule->_oTemplate);
+        if (false === $sDisplay)
+            $sDisplay = $this->_oModule->_oConfig->CNF['OBJECT_FORM_ENTRY_DISPLAY_EDIT'];        
+        return BxDolForm::getObjectInstance($this->_oModule->_oConfig->CNF['OBJECT_FORM_ENTRY'], $sDisplay, $this->_oModule->_oTemplate);
     }
 
     public function getObjectFormDelete ()

+ 35 - 121
modules/base/profile/classes/BxBaseModProfileFormEntry.php

@@ -31,25 +31,30 @@ class BxBaseModProfileFormEntry extends BxBaseModGeneralFormEntry
 		}
 
         if (!empty($CNF['FIELD_PICTURE']) && isset($this->aInputs[$CNF['FIELD_PICTURE']])) {
-            $this->aInputs[$CNF['FIELD_PICTURE']]['storage_object'] = $CNF['OBJECT_STORAGE'];
-            $this->aInputs[$CNF['FIELD_PICTURE']]['uploaders'] = !empty($this->aInputs[$CNF['FIELD_PICTURE']]['value']) ? unserialize($this->aInputs[$CNF['FIELD_PICTURE']]['value']) : $CNF['OBJECT_UPLOADERS'];
-            $this->aInputs[$CNF['FIELD_PICTURE']]['images_transcoder'] = $CNF['OBJECT_IMAGES_TRANSCODER_THUMB'];
-            $this->aInputs[$CNF['FIELD_PICTURE']]['storage_private'] = 0;
-            $this->aInputs[$CNF['FIELD_PICTURE']]['multiple'] = false;
-            $this->aInputs[$CNF['FIELD_PICTURE']]['content_id'] = 0;
-            $this->aInputs[$CNF['FIELD_PICTURE']]['ghost_template'] = '';
+            $this->_aImageFields[$CNF['FIELD_PICTURE']] = array (
+                'storage_object' => $CNF['OBJECT_STORAGE'],
+                'images_transcoder' => $CNF['OBJECT_IMAGES_TRANSCODER_THUMB'],
+                'uploaders' => $CNF['OBJECT_UPLOADERS_PICTURE'],
+            );
         }
 
-        if (!empty($CNF['FIELD_COVER'])) {
+        if (!empty($CNF['FIELD_COVER']) && isset($this->aInputs[$CNF['FIELD_COVER']])) {
             $this->_aImageFields[$CNF['FIELD_COVER']] = array (
                 'storage_object' => $CNF['OBJECT_STORAGE_COVER'],
                 'images_transcoder' => $CNF['OBJECT_IMAGES_TRANSCODER_COVER_THUMB'],
-                'field_preview' => $CNF['FIELD_COVER_PREVIEW'],
+                'uploaders' => $CNF['OBJECT_UPLOADERS_COVER'],
             );
         }
 
-        if (!empty($CNF['FIELD_COVER_PREVIEW']))
-            $this->_aImageFields[$CNF['FIELD_COVER_PREVIEW']] = $this->_aImageFields[$CNF['FIELD_COVER']];
+        foreach ($this->_aImageFields as $sField => $aParams) {
+            $this->aInputs[$sField]['storage_object'] = $aParams['storage_object'];
+            $this->aInputs[$sField]['uploaders'] = !empty($this->aInputs[$sField]['value']) ? unserialize($this->aInputs[$sField]['value']) : $aParams['uploaders'];
+            $this->aInputs[$sField]['images_transcoder'] = $aParams['images_transcoder'];
+            $this->aInputs[$sField]['storage_private'] = 0;
+            $this->aInputs[$sField]['multiple'] = false;
+            $this->aInputs[$sField]['content_id'] = 0;
+            $this->aInputs[$sField]['ghost_template'] = '';
+        }
 
         $oAccountProfile = BxDolProfile::getInstanceAccountProfile();
         if ($oAccountProfile)
@@ -60,68 +65,24 @@ class BxBaseModProfileFormEntry extends BxBaseModGeneralFormEntry
     {
         $CNF = &$this->_oModule->_oConfig->CNF;
 
-        if (isset($this->aInputs[$CNF['FIELD_PICTURE']])) {
-
-            $aContentInfo = false;
-            if ($aValues && !empty($aValues[$CNF['FIELD_ID']])) {
-                $aContentInfo = $this->_oModule->_oDb->getContentInfoById ($aValues[$CNF['FIELD_ID']]);
-                $this->aInputs[$CNF['FIELD_PICTURE']]['content_id'] = $aValues[$CNF['FIELD_ID']];
-            }
-
-            $this->aInputs[$CNF['FIELD_PICTURE']]['ghost_template'] = $this->_oModule->_oTemplate->parseHtmlByName('form_ghost_template.html', $this->_getPhotoGhostTmplVars($aContentInfo));
-        }
-
-        parent::initChecker($aValues, $aSpecificValues);
-
-        foreach ($this->_aImageFields as $sField => $aVals) {
-            if (!isset($this->aInputs[$sField]))
-                continue;
+        $aContentInfo = false;
+        $aContentInfo = $this->_oModule->_oDb->getContentInfoById ($aValues[$CNF['FIELD_ID']]);
+        
+        foreach ($this->_aImageFields as $sField => $aParams) {
 
             if ($aValues && !empty($aValues[$CNF['FIELD_ID']]))
                 $this->aInputs[$sField]['content_id'] = $aValues[$CNF['FIELD_ID']];
 
-            $sErrorString = '';
-            $this->aInputs[$sField]['file_id'] = $this->_processFile (!empty($aValues[$CNF['FIELD_ID']]) ? $aValues[$CNF['FIELD_ID']] : 0, $sField, isset($aValues[$sField]) ? $aValues[$sField] : 0, $sErrorString);
-            if ($sErrorString) {
-                $this->aInputs[$sField]['error'] = $sErrorString;
-                $this->setValid(false);
-            }
-
-            if (!isset($this->aInputs[$aVals['field_preview']]) || !empty($this->aInputs[$aVals['field_preview']]['content']))
-                continue;
-
-            $oTranscoder = BxDolTranscoderImage::getObjectInstance($aVals['images_transcoder']);
-
-            $aVars = array (
-                'bx_if:picture' => array (
-                    'condition' => $oTranscoder && isset($aValues[$sField]) && $aValues[$sField] ? true : false,
-                    'content' => array (
-                        'picture_url' => $oTranscoder && isset($aValues[$sField]) && $aValues[$sField] ? $oTranscoder->getFileUrl($aValues[$sField]) : '',
-                    ),
-                ),
-                'bx_if:no_picture' => array (
-                    'condition' => !$oTranscoder || !isset($aValues[$sField]) || !$aValues[$sField] ? true : false,
-                    'content' => array (),
-                ),
-                'bx_if:delete' => array (
-                    'condition' => $oTranscoder && isset($aValues[$sField]) && $aValues[$sField] && $sField == $CNF['FIELD_COVER'] ? true : false,
-                    'content' => array ('action_ajax' => isset($aValues[$sField]) ? BX_DOL_URL_ROOT . $this->_oModule->_oConfig->getBaseUri() . 'delete_profile_img/' . $aValues[$sField] . '/' . (!empty($aValues[$CNF['FIELD_ID']]) ? $aValues[$CNF['FIELD_ID']] : 0) . '/' . $sField : ''),
-                ),
-            );
-            $this->aInputs[$aVals['field_preview']]['content'] = $this->_oModule->_oTemplate->parseHtmlByName('picture_preview.html', $aVars);
+            $this->aInputs[$sField]['ghost_template'] = $this->_oModule->_oTemplate->parseHtmlByName('form_ghost_template.html', $this->_getPhotoGhostTmplVars($sField, $aContentInfo));
         }
+
+        parent::initChecker($aValues, $aSpecificValues);
     }
 
     public function insert ($aValsToAdd = array(), $isIgnore = false)
     {
         $CNF = &$this->_oModule->_oConfig->CNF;
 
-        if (!empty($this->aInputs[$CNF['FIELD_COVER']]) && !empty($this->aInputs[$CNF['FIELD_COVER']]['file_id'])) {
-            $aValsToAdd = array_merge($aValsToAdd, array (
-                $CNF['FIELD_COVER'] => $this->aInputs[$CNF['FIELD_COVER']]['file_id'],
-            ));
-        }
-
         if (isset($CNF['FIELD_PICTURE']))
             $aValsToAdd[$CNF['FIELD_PICTURE']] = 0; // we will update this field later, since we don't know content id yet
         
@@ -132,11 +93,8 @@ class BxBaseModProfileFormEntry extends BxBaseModGeneralFormEntry
     {
         $CNF = &$this->_oModule->_oConfig->CNF;
 
-        if (!empty($this->aInputs[$CNF['FIELD_COVER']]) && !empty($this->aInputs[$CNF['FIELD_COVER']]['file_id']))
-            $aValsToAdd[$CNF['FIELD_COVER']] = $this->aInputs[$CNF['FIELD_COVER']]['file_id'];
-
-        if (isset($CNF['FIELD_PICTURE']))
-            $aValsToAdd[$CNF['FIELD_PICTURE']] = 0; // we will update this field later
+        foreach ($this->_aImageFields as $sField => $aParams)
+            $aValsToAdd[$sField] = 0; // we will update this field later
         
         return parent::update ($iContentId, $aValsToAdd, $aTrackTextFieldsChanges);
     }
@@ -145,14 +103,12 @@ class BxBaseModProfileFormEntry extends BxBaseModGeneralFormEntry
     {
         $CNF = &$this->_oModule->_oConfig->CNF;
 
-        foreach ($this->_aImageFields as $sField => $aVals) {
-            if (isset($aContentInfo[$sField]) && $aContentInfo[$sField])
-                $this->_deleteFile ($iContentId, $sField, $aContentInfo[$sField]);
-        }
+        $iProfileId = $this->getContentOwnerProfileId($iContentId);
+        $aFiles = $oStorage->getGhosts($iProfileId, $iContentId);
+
+        foreach ($this->_aImageFields as $sField => $aParams) {
+            $oStorage = BxDolStorage::getObjectInstance($aParams['storage_object']);
 
-        if (isset($CNF['FIELD_PICTURE']) && isset($CNF['OBJECT_STORAGE']) && $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE'])) {
-            $iProfileId = $this->getContentOwnerProfileId($iContentId);
-            $aFiles = $oStorage->getGhosts($iProfileId, $iContentId);
             foreach ($aFiles as $aFile) {
                 if (!$oStorage->getFile($aFile['id']))
                     continue;
@@ -163,61 +119,19 @@ class BxBaseModProfileFormEntry extends BxBaseModGeneralFormEntry
         return parent::delete($iContentId, $aContentInfo);
     }
 
-    function _processFile ($iContentId, $sField, $iFileIdOld, &$sErrorString)
-    {
-        if (empty($_FILES[$sField]['tmp_name']))
-            return $iFileIdOld;
-
-        $oStorage = BxDolStorage::getObjectInstance($this->_aImageFields[$sField]['storage_object']);
-        if (!$oStorage)
-            return $iFileIdOld;
-
-        // delete previous file
-        $this->_deleteFile($iContentId, $sField, $iFileIdOld);
-
-        // process new file and return new file id
-        if (!($iFileId = $oStorage->storeFileFromForm($_FILES[$sField], false, $this->_iAccountProfileId))) {
-            $sErrorString = $oStorage->getErrorString();
-            return 0;
-        }
-
-        return $iFileId;
-    }
-
-    protected function _associalFileWithContent($oStorage, $iFileId, $iProfileId, $iContentId)
+    protected function _associalFileWithContent($oStorage, $iFileId, $iProfileId, $iContentId, $sPictureField = '')
     {
         $oStorage->updateGhostsContentId ($iFileId, $iProfileId, $iContentId);
-        $this->_oModule->_oDb->updateContentPictureById($iContentId, 0/*$iProfileId*/, $iFileId, $this->_oModule->_oConfig->CNF['FIELD_PICTURE']);
-    }
-    
-    function _deleteFile ($iContentId, $sFieldPicture, $iFileId, $bForceFieldUpdate = false)
-    {
-        if (!$iFileId)
-            return true;
-
-        if (!$this->_aImageFields[$sFieldPicture]['storage_object'])
-            return false;
-
-        if (!($oStorage = BxDolStorage::getObjectInstance($this->_aImageFields[$sFieldPicture]['storage_object'])))
-            return false;
-
-        if (!$oStorage->getFile($iFileId))
-            return true;
-
-        if (($bRet = $oStorage->deleteFile($iFileId, $this->_iAccountProfileId)) && $bForceFieldUpdate) {
-            $this->_oModule->_oDb->updateContentPictureById($iContentId, 0, 0, $sFieldPicture);
-        }
-
-        return $bRet;
+        $this->_oModule->_oDb->updateContentPictureById($iContentId, 0/*$iProfileId*/, $iFileId, $sPictureField);
     }
 
-    protected function _getPhotoGhostTmplVars($aContentInfo = array())
+    protected function _getPhotoGhostTmplVars($sField, $aContentInfo = array())
     {
     	$CNF = &$this->_oModule->_oConfig->CNF;
 
     	return array (
-			'name' => $this->aInputs[$CNF['FIELD_PICTURE']]['name'],
-            'content_id' => $this->aInputs[$CNF['FIELD_PICTURE']]['content_id'],
+			'name' => $this->aInputs[$sField]['name'],
+            'content_id' => $this->aInputs[$sField]['content_id'],
 			'bx_if:set_thumb' => array (
 				'condition' => false,
 				'content' => array (),

+ 3 - 0
modules/base/profile/classes/BxBaseModProfileFormsEntryHelper.php

@@ -93,6 +93,8 @@ class BxBaseModProfileFormsEntryHelper extends BxBaseModGeneralFormsEntryHelper
         // process uploaded files
         $oForm = $this->getObjectFormEdit();
         $oForm->processFiles($CNF['FIELD_PICTURE'], $iContentId, false);
+        $oForm = $this->getObjectFormEdit($CNF['OBJECT_FORM_ENTRY_DISPLAY_EDIT_COVER']);
+        $oForm->processFiles($CNF['FIELD_COVER'], $iContentId, false);
 
         // create an alert
         bx_alert($this->_oModule->getName(), 'edited', $aContentInfo[$CNF['FIELD_ID']]);
@@ -124,6 +126,7 @@ class BxBaseModProfileFormsEntryHelper extends BxBaseModGeneralFormsEntryHelper
         // process uploaded files
         $oForm = $this->getObjectFormAdd();
         $oForm->processFiles($CNF['FIELD_PICTURE'], $iContentId, true);
+        $oForm->processFiles($CNF['FIELD_COVER'], $iContentId, true);
 
         // alert
         bx_alert($this->_oModule->getName(), 'added', $iContentId);

+ 72 - 0
modules/base/profile/classes/BxBaseModProfileUploaderCoverCrop.php

@@ -0,0 +1,72 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    BaseProfile Base classes for profile modules
+ * @ingroup     TridentModules
+ *
+ * @{
+ */
+
+class BxBaseModProfileUploaderCoverCrop extends BxTemplUploaderCrop
+{
+    protected $_oModule;
+
+    public function __construct ($aObject, $sStorageObject, $sUniqId, $oTemplate)
+    {
+        parent::__construct($aObject, $sStorageObject, $sUniqId, $oTemplate ? $oTemplate : $this->_oModule->_oTemplate);
+        $this->_sUploaderFormTemplate = 'uploader_form_crop_cover.html';
+    }
+
+    public function deleteGhostsForProfile($iProfileId, $iContentId = false)
+    {
+        if (!$iContentId)
+            return parent::deleteGhostsForProfile($iProfileId, $iContentId);
+
+        $CNF = $this->_oModule->_oConfig->CNF;
+        $aContentInfo = $this->_oModule->_oDb->getContentInfoById($iContentId);
+        
+        $iCount = 0;
+
+        $oStorage = BxDolStorage::getObjectInstance($this->_sStorageObject);
+
+        $aGhosts = $oStorage->getGhosts($iProfileId, $iContentId, $iContentId ? true : false);
+        foreach ($aGhosts as $aFile) {
+
+            // for cover image delete only unassigned ghosts and currently set covers
+            if ($aFile['id'] == $aContentInfo[$CNF['FIELD_COVER']] || $aFile['id'] != $aContentInfo[$CNF['FIELD_PICTURE']])
+                $iCount += $oStorage->deleteFile($aFile['id']);
+
+        }
+
+        return $iCount;
+    }
+    
+    public function getGhosts($iProfileId, $sFormat, $sImagesTranscoder = false, $iContentId = false)
+    {
+        $s = parent::getGhosts($iProfileId, $sFormat, $sImagesTranscoder, $iContentId);
+        if (!$s || !$iContentId) // if we're creating new profile return all ghosts
+            return $s;
+
+        $a = json_decode($s, true);
+        if (!$a)
+            return $s;
+
+        // filter out thumbnails
+        $CNF = $this->_oModule->_oConfig->CNF;
+        $aContentInfo = $this->_oModule->_oDb->getContentInfoById($iContentId);
+        $aResult = array();
+        foreach ($a as $aFile) {
+
+            // for cover image show only unassigned ghosts and currently set covers
+            if ($aFile['file_id'] == $aContentInfo[$CNF['FIELD_COVER']] || $aFile['file_id'] != $aContentInfo[$CNF['FIELD_PICTURE']])
+                $aResult[] = $aFile;
+
+        }
+
+        return json_encode($aResult);
+    }    
+}
+
+/** @} */

+ 70 - 0
modules/base/profile/classes/BxBaseModProfileUploaderPictureCrop.php

@@ -0,0 +1,70 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    BaseProfile Base classes for profile modules
+ * @ingroup     TridentModules
+ *
+ * @{
+ */
+
+class BxBaseModProfileUploaderPictureCrop extends BxTemplUploaderCrop
+{
+    protected $_oModule;
+
+    public function __construct ($aObject, $sStorageObject, $sUniqId, $oTemplate)
+    {
+        parent::__construct($aObject, $sStorageObject, $sUniqId, $oTemplate);
+    }
+
+    public function deleteGhostsForProfile($iProfileId, $iContentId = false)
+    {
+        if (!$iContentId)
+            return parent::deleteGhostsForProfile($iProfileId, $iContentId);
+
+        $CNF = $this->_oModule->_oConfig->CNF;
+        $aContentInfo = $this->_oModule->_oDb->getContentInfoById($iContentId);
+        
+        $iCount = 0;
+
+        $oStorage = BxDolStorage::getObjectInstance($this->_sStorageObject);
+
+        $aGhosts = $oStorage->getGhosts($iProfileId, $iContentId, $iContentId ? true : false);
+        foreach ($aGhosts as $aFile) {
+
+            // for profile image delete only unassigned ghosts and currently set profile pictures
+            if ($aFile['id'] == $aContentInfo[$CNF['FIELD_PICTURE']] || $aFile['id'] != $aContentInfo[$CNF['FIELD_COVER']])
+                $iCount += $oStorage->deleteFile($aFile['id']);
+
+        }
+
+        return $iCount;
+    }
+    
+    public function getGhosts($iProfileId, $sFormat, $sImagesTranscoder = false, $iContentId = false)
+    {
+        $s = parent::getGhosts($iProfileId, $sFormat, $sImagesTranscoder, $iContentId);
+        if (!$s || !$iContentId) // if we're creating new profile return all ghosts
+            return $s;
+
+        $a = json_decode($s, true);
+        if (!$a)
+            return $s;
+
+        // filter out thumbnails
+        $CNF = $this->_oModule->_oConfig->CNF;
+        $aContentInfo = $this->_oModule->_oDb->getContentInfoById($iContentId);
+        $aResult = array();
+        foreach ($a as $aFile) {
+
+            // for profile pictures show only unassigned ghosts and currently set profile pictures
+            if ($sImagesTranscoder == $CNF['OBJECT_IMAGES_TRANSCODER_THUMB'] && ($aFile['file_id'] == $aContentInfo[$CNF['FIELD_PICTURE']] || $aFile['file_id'] != $aContentInfo[$CNF['FIELD_COVER']]))
+                $aResult[] = $aFile;            
+        }
+
+        return json_encode($aResult);
+    }    
+}
+
+/** @} */

+ 4 - 0
modules/base/profile/template/css/forms.css

@@ -1 +1,5 @@
 @import url(../../../general/template/css/forms.css);
+
+.bx-popup-content-wrapped .bx-croppie-container.bx-base-general-croppie-container {
+    min-height:190px;
+}

+ 44 - 0
modules/base/profile/template/uploader_form_crop_cover.html

@@ -0,0 +1,44 @@
+<div id="__form_container_id__" class="bx-uploader-form-cont bx-popup-width">
+
+    <input name="f" type="file" />
+
+    <div class="bx-uploader-loading"></div>
+    <div class="bx-def-padding-sec-bottom bx-croppie-msg"></div>
+    <div class="bx-def-padding-sec-bottom" id="__errors_container_id__"></div>
+
+    <div class="bx-croppie-container bx-base-general-croppie-container bx-def-margin-topbottom"></div>
+
+    <div class="bx-def-padding-top bx-clearfix">
+        <button class="bx-crop-action bx-btn bx-btn-disabled bx-def-margin-sec-right bx-def-margin-sec-top bx-crop-upload bx-btn-primary"><bx_text:_sys_uploader_crop_submit_button /></button>
+        <button class="bx-crop-action bx-btn bx-btn-disabled bx-def-margin-sec-right bx-def-margin-sec-top bx-crop-rotate" data-deg="-90"><bx_text:_sys_uploader_crop_rotate_left /></button>
+        <button class="bx-crop-action bx-btn bx-btn-disabled bx-def-margin-sec-right bx-def-margin-sec-top bx-crop-rotate" data-deg="90"><bx_text:_sys_uploader_crop_rotate_right /></button>
+        <div class="bx-btn bx-def-margin-sec-top" onclick="__uploader_instance_name__.onClickCancel()"><bx_text:_sys_uploader_close /></div>
+    </div>
+
+</div>
+
+<script>
+setTimeout(function () {    
+    __uploader_instance_name__.initUploader({
+        bx_form: {
+            uo: "__engine__",
+            so: "__storage_object__",
+            uid: "__uniq_id__",
+            m: "__multiple__",
+            c: "__content_id__",
+            p: "__storage_private__",
+            a: "upload"
+        },
+        viewport: {
+            width: 240,
+            height: 90,
+            // type: 'circle'
+        },
+        boundary: {
+            width: 280,
+            height: 130
+        },
+        enableOrientation: true
+    });
+}, 100);
+</script>

+ 1 - 1
modules/base/text/classes/BxBaseModTextFormEntry.php

@@ -117,7 +117,7 @@ class BxBaseModTextFormEntry extends BxBaseModGeneralFormEntry
         return $oStorage->deleteFile($iFileId, $iProfileId);
     }
 
-    protected function _associalFileWithContent($oStorage, $iFileId, $iProfileId, $iContentId)
+    protected function _associalFileWithContent($oStorage, $iFileId, $iProfileId, $iContentId, $sPictureField = '')
     {
         $oStorage->updateGhostsContentId ($iFileId, $iProfileId, $iContentId);
     }

+ 2 - 2
modules/boonex/albums/classes/BxAlbumsFormEntry.php

@@ -20,9 +20,9 @@ class BxAlbumsFormEntry extends BxBaseModTextFormEntry
         parent::__construct($aInfo, $oTemplate);
     }
 
-    protected function _associalFileWithContent($oStorage, $iFileId, $iProfileId, $iContentId)
+    protected function _associalFileWithContent($oStorage, $iFileId, $iProfileId, $iContentId, $sPictureField = '')
     {
-        parent::_associalFileWithContent($oStorage, $iFileId, $iProfileId, $iContentId);
+        parent::_associalFileWithContent($oStorage, $iFileId, $iProfileId, $iContentId, $sPictureField);
 
         $CNF = &$this->_oModule->_oConfig->CNF;
 

+ 2 - 2
modules/boonex/groups/classes/BxGroupsConfig.php

@@ -48,7 +48,6 @@ class BxGroupsConfig extends BxBaseModProfileConfig
             'FIELD_PICTURE' => 'picture',
             'FIELD_PICTURE_PREVIEW' => 'picture_preview',
             'FIELD_COVER' => 'cover',
-            'FIELD_COVER_PREVIEW' => 'cover_preview',
             'FIELD_ALLOW_VIEW_TO' => 'allow_view_to',
             'FIELDS_QUICK_SEARCH' => array('group_name'),
             'FIELDS_WITH_KEYWORDS' => 'auto', // can be 'auto', array of fields or comma separated string of field names, works only when OBJECT_METATAGS is specified
@@ -101,7 +100,8 @@ class BxGroupsConfig extends BxBaseModProfileConfig
         	'OBJECT_GRID_COMMON' => 'bx_groups_common',
             'OBJECT_GRID_CONNECTIONS' => 'bx_groups_fans',
             'OBJECT_CONNECTIONS' => 'bx_groups_fans',
-            'OBJECT_UPLOADERS' => array('sys_simple', 'sys_html5', 'sys_crop'),
+            'OBJECT_UPLOADERS_COVER' => array('bx_groups_cover_crop'),
+            'OBJECT_UPLOADERS_PICTURE' => array('bx_groups_picture_crop'),
 
             'EMAIL_INVITATION' => 'bx_groups_invitation',
             'EMAIL_JOIN_REQUEST' => 'bx_groups_join_request',

+ 21 - 0
modules/boonex/groups/classes/BxGroupsUploaderCoverCrop.php

@@ -0,0 +1,21 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    Groups Groups
+ * @ingroup     TridentModules
+ *
+ * @{
+ */
+
+class BxGroupsUploaderCoverCrop extends BxBaseModProfileUploaderCoverCrop
+{
+    public function __construct ($aObject, $sStorageObject, $sUniqId, $oTemplate)
+    {
+        $this->_oModule = BxDolModule::getInstance('bx_groups');
+        parent::__construct($aObject, $sStorageObject, $sUniqId, $oTemplate);
+    }
+}
+
+/** @} */

+ 21 - 0
modules/boonex/groups/classes/BxGroupsUploaderPictureCrop.php

@@ -0,0 +1,21 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    Groups Groups
+ * @ingroup     TridentModules
+ *
+ * @{
+ */
+
+class BxGroupsUploaderPictureCrop extends BxBaseModProfileUploaderPictureCrop
+{
+    public function __construct ($aObject, $sStorageObject, $sUniqId, $oTemplate)
+    {
+        $this->_oModule = BxDolModule::getInstance('bx_groups');
+        parent::__construct($aObject, $sStorageObject, $sUniqId, $oTemplate);
+    }
+}
+
+/** @} */

+ 4 - 0
modules/boonex/groups/install/sql/disable.sql

@@ -62,3 +62,7 @@ DELETE FROM `sys_objects_privacy` WHERE `object` IN('bx_groups_allow_view_to', '
 
 DELETE FROM `sys_email_templates` WHERE `Module` = 'bx_groups';
 
+-- UPLOADERS
+
+DELETE FROM `sys_objects_uploader` WHERE `object` IN('bx_groups_cover_crop', 'bx_groups_picture_crop');
+

+ 6 - 0
modules/boonex/groups/install/sql/enable.sql

@@ -405,3 +405,9 @@ INSERT INTO `sys_email_templates` (`Module`, `NameSystem`, `Name`, `Subject`, `B
 ('bx_groups', '_bx_groups_email_admin_become_fan', 'bx_groups_admin_become_fan', '_bx_groups_email_admin_become_fan_subject', '_bx_groups_email_admin_become_fan_body'),
 ('bx_groups', '_bx_groups_email_invitation', 'bx_groups_invitation', '_bx_groups_email_invitation_subject', '_bx_groups_email_invitation_body');
 
+-- UPLOADERS
+
+INSERT INTO `sys_objects_uploader` (`object`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_groups_cover_crop', 1, 'BxGroupsUploaderCoverCrop', 'modules/boonex/groups/classes/BxGroupsUploaderCoverCrop.php'),
+('bx_groups_picture_crop', 1, 'BxGroupsUploaderPictureCrop', 'modules/boonex/groups/classes/BxGroupsUploaderPictureCrop.php');
+

+ 2 - 10
modules/boonex/groups/install/sql/install.sql

@@ -165,8 +165,6 @@ INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`,
 
 INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
 ('bx_group', 'bx_groups', 'allow_view_to', 3, '', 0, 'custom', '_bx_groups_form_profile_input_sys_allow_view_to', '_bx_groups_form_profile_input_allow_view_to', '_bx_groups_form_profile_input_allow_view_to_desc', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
-('bx_group', 'bx_groups', 'cover', '', '', 0, 'file', '_bx_groups_form_profile_input_sys_cover', '_bx_groups_form_profile_input_cover', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
-('bx_group', 'bx_groups', 'cover_preview', '', '', 0, 'custom', '_bx_groups_form_profile_input_sys_cover_preview', '_bx_groups_form_profile_input_cover_preview', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
 ('bx_group', 'bx_groups', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_groups_form_profile_input_sys_delete_confirm', '_bx_groups_form_profile_input_delete_confirm', '_bx_groups_form_profile_input_delete_confirm_info', 1, 0, 0, '', '', '', 'avail', '', '_bx_groups_form_profile_input_delete_confirm_error', '', '', 1, 0),
 ('bx_group', 'bx_groups', 'do_submit', '_sys_form_account_input_submit', '', 0, 'submit', '_bx_groups_form_profile_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
 ('bx_group', 'bx_groups', 'group_desc', '', '', 0, 'textarea', '_bx_groups_form_profile_input_sys_group_desc', '_bx_groups_form_profile_input_group_desc', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 1),
@@ -174,12 +172,10 @@ INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `ch
 ('bx_group', 'bx_groups', 'group_name', '', '', 0, 'text', '_bx_groups_form_profile_input_sys_group_name', '_bx_groups_form_profile_input_group_name', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_groups_form_profile_input_group_name_err', 'Xss', '', 1, 0),
 ('bx_group', 'bx_groups', 'initial_members', '', '', 0, 'custom', '_bx_groups_form_profile_input_sys_initial_members', '_bx_groups_form_profile_input_initial_members', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 1),
 ('bx_group', 'bx_groups', 'join_confirmation', 1, '', 1, 'switcher', '_bx_groups_form_profile_input_sys_join_confirm', '_bx_groups_form_profile_input_join_confirm', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
-('bx_group', 'bx_groups', 'picture', 'a:1:{i:0;s:8:"sys_crop";}', 'a:3:{s:10:"sys_simple";s:26:"_sys_uploader_simple_title";s:9:"sys_html5";s:25:"_sys_uploader_html5_title";s:8:"sys_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_groups_form_profile_input_sys_picture', '_bx_groups_form_profile_input_picture', '', 0, 0, 0, '', '', '', '', '', '_bx_groups_form_profile_input_picture_err', 'Int', '', 1, 0);
-
-
+('bx_group', 'bx_groups', 'cover', 'a:1:{i:0;s:20:"bx_groups_cover_crop";}', 'a:1:{s:20:"bx_groups_cover_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_groups_form_profile_input_sys_cover', '_bx_groups_form_profile_input_cover', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_group', 'bx_groups', 'picture', 'a:1:{i:0;s:22:"bx_groups_picture_crop";}', 'a:1:{s:22:"bx_groups_picture_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_groups_form_profile_input_sys_picture', '_bx_groups_form_profile_input_picture', '', 0, 0, 0, '', '', '', '', '', '_bx_groups_form_profile_input_picture_err', 'Int', '', 1, 0);
 
 INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
-('bx_group_add', 'cover_preview', 2147483647, 0, 1),
 ('bx_group_add', 'delete_confirm', 2147483647, 0, 3),
 ('bx_group_add', 'cover', 2147483647, 0, 4),
 ('bx_group_add', 'initial_members', 2147483647, 1, 5),
@@ -192,12 +188,10 @@ INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for
 ('bx_group_add', 'do_submit', 2147483647, 1, 12),
 ('bx_group_delete', 'delete_confirm', 2147483647, 1, 0),
 ('bx_group_delete', 'cover', 2147483647, 0, 0),
-('bx_group_delete', 'cover_preview', 2147483647, 0, 0),
 ('bx_group_delete', 'picture', 2147483647, 0, 0),
 ('bx_group_delete', 'do_submit', 2147483647, 1, 1),
 ('bx_group_delete', 'group_name', 2147483647, 0, 2),
 ('bx_group_delete', 'group_cat', 2147483647, 0, 3),
-('bx_group_edit', 'cover_preview', 2147483647, 0, 1),
 ('bx_group_edit', 'delete_confirm', 2147483647, 0, 2),
 ('bx_group_edit', 'cover', 2147483647, 0, 3),
 ('bx_group_edit', 'picture', 2147483647, 1, 5),
@@ -213,10 +207,8 @@ INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for
 ('bx_group_edit_cover', 'group_name', 2147483647, 0, 2),
 ('bx_group_edit_cover', 'picture', 2147483647, 0, 3),
 ('bx_group_edit_cover', 'group_cat', 2147483647, 0, 5),
-('bx_group_edit_cover', 'cover_preview', 2147483647, 1, 6),
 ('bx_group_edit_cover', 'cover', 2147483647, 1, 7),
 ('bx_group_edit_cover', 'do_submit', 2147483647, 1, 8),
-('bx_group_view', 'cover_preview', 2147483647, 0, 1),
 ('bx_group_view', 'delete_confirm', 2147483647, 0, 3),
 ('bx_group_view', 'picture', 2147483647, 0, 4),
 ('bx_group_view', 'cover', 2147483647, 0, 5),

+ 1 - 0
modules/boonex/groups/template/uploader_form_crop_cover.html

@@ -0,0 +1 @@
+<bx_include_base:../modules/base/profile/template/uploader_form_crop_cover.html />

+ 2 - 2
modules/boonex/market/classes/BxMarketFormEntry.php

@@ -158,9 +158,9 @@ class BxMarketFormEntry extends BxBaseModTextFormEntry
 		return $bResult;
     }
 
-    protected function _associalFileWithContent($oStorage, $iFileId, $iProfileId, $iContentId)
+    protected function _associalFileWithContent($oStorage, $iFileId, $iProfileId, $iContentId, $sPictureField = '')
     {
-        parent::_associalFileWithContent($oStorage, $iFileId, $iProfileId, $iContentId);
+        parent::_associalFileWithContent($oStorage, $iFileId, $iProfileId, $iContentId, $sPictureField);
 
         $sStorage = $oStorage->getObject();
         switch($sStorage) {

+ 2 - 2
modules/boonex/organizations/classes/BxOrgsConfig.php

@@ -46,7 +46,6 @@ class BxOrgsConfig extends BxBaseModProfileConfig
             'FIELD_PICTURE' => 'picture',
             'FIELD_PICTURE_PREVIEW' => 'picture_preview',
             'FIELD_COVER' => 'cover',
-            'FIELD_COVER_PREVIEW' => 'cover_preview',
             'FIELD_ALLOW_VIEW_TO' => 'allow_view_to',
             'FIELDS_QUICK_SEARCH' => array('org_name'),
             'FIELDS_WITH_KEYWORDS' => 'auto', // can be 'auto', array of fields or comma separated string of field names, works only when OBJECT_METATAGS is specified
@@ -97,7 +96,8 @@ class BxOrgsConfig extends BxBaseModProfileConfig
             'OBJECT_PRIVACY_VIEW' => 'bx_organizations_allow_view_to',
             'OBJECT_GRID_ADMINISTRATION' => 'bx_organizations_administration',
             'OBJECT_GRID_COMMON' => 'bx_organizations_common',
-            'OBJECT_UPLOADERS' => array('sys_simple', 'sys_html5', 'sys_crop'),
+            'OBJECT_UPLOADERS_COVER' => array('bx_organizations_cover_crop'),
+            'OBJECT_UPLOADERS_PICTURE' => array('bx_organizations_picture_crop'),
 
             'TRIGGER_MENU_PROFILE_VIEW_SUBMENU' => 'trigger_profile_view_submenu',
             'TRIGGER_MENU_PROFILE_VIEW_ACTIONS' => 'trigger_profile_view_actions',

+ 21 - 0
modules/boonex/organizations/classes/BxOrgsUploaderCoverCrop.php

@@ -0,0 +1,21 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    Organizations Organizations
+ * @ingroup     TridentModules
+ *
+ * @{
+ */
+
+class BxOrgsUploaderCoverCrop extends BxBaseModProfileUploaderCoverCrop
+{
+    public function __construct ($aObject, $sStorageObject, $sUniqId, $oTemplate)
+    {
+        $this->_oModule = BxDolModule::getInstance('bx_organizations');
+        parent::__construct($aObject, $sStorageObject, $sUniqId, $oTemplate);
+    }
+}
+
+/** @} */

+ 21 - 0
modules/boonex/organizations/classes/BxOrgsUploaderPictureCrop.php

@@ -0,0 +1,21 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    Organizations Organizations
+ * @ingroup     TridentModules
+ *
+ * @{
+ */
+
+class BxOrgsUploaderPictureCrop extends BxBaseModProfileUploaderPictureCrop
+{
+    public function __construct ($aObject, $sStorageObject, $sUniqId, $oTemplate)
+    {
+        $this->_oModule = BxDolModule::getInstance('bx_organizations');
+        parent::__construct($aObject, $sStorageObject, $sUniqId, $oTemplate);
+    }
+}
+
+/** @} */

+ 3 - 0
modules/boonex/organizations/install/sql/disable.sql

@@ -47,3 +47,6 @@ DELETE FROM `sys_alerts_handlers` WHERE `id` = @iHandler;
 -- PRIVACY 
 DELETE FROM `sys_objects_privacy` WHERE `object` IN('bx_organizations_allow_view_to');
 
+-- UPLOADERS
+DELETE FROM `sys_objects_uploader` WHERE `object` IN('bx_organizations_cover_crop', 'bx_organizations_picture_crop');
+

+ 6 - 0
modules/boonex/organizations/install/sql/enable.sql

@@ -369,3 +369,9 @@ INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
 INSERT INTO `sys_objects_privacy` (`object`, `module`, `action`, `title`, `default_group`, `table`, `table_field_id`, `table_field_author`, `override_class_name`, `override_class_file`) VALUES
 ('bx_organizations_allow_view_to', 'bx_organizations', 'view', '_bx_orgs_form_profile_input_allow_view_to', '3', 'bx_organizations_data', 'id', 'author', 'BxOrgsPrivacy', 'modules/boonex/organizations/classes/BxOrgsPrivacy.php');
 
+-- UPLOADERS
+
+INSERT INTO `sys_objects_uploader` (`object`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_organizations_cover_crop', 1, 'BxOrgsUploaderCoverCrop', 'modules/boonex/organizations/classes/BxOrgsUploaderCoverCrop.php'),
+('bx_organizations_picture_crop', 1, 'BxOrgsUploaderPictureCrop', 'modules/boonex/organizations/classes/BxOrgsUploaderPictureCrop.php');
+

+ 2 - 8
modules/boonex/organizations/install/sql/install.sql

@@ -102,18 +102,16 @@ INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`,
 
 INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
 ('bx_organization', 'bx_organization', 'allow_view_to', 3, '', 0, 'custom', '_bx_orgs_form_profile_input_sys_allow_view_to', '_bx_orgs_form_profile_input_allow_view_to', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
-('bx_organization', 'bx_organizations', 'cover', '', '', 0, 'file', '_bx_orgs_form_profile_input_sys_cover', '_bx_orgs_form_profile_input_cover', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
-('bx_organization', 'bx_organizations', 'cover_preview', '', '', 0, 'custom', '_bx_orgs_form_profile_input_sys_cover_preview', '_bx_orgs_form_profile_input_cover_preview', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
 ('bx_organization', 'bx_organizations', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_orgs_form_profile_input_sys_delete_confirm', '_bx_orgs_form_profile_input_delete_confirm', '_bx_orgs_form_profile_input_delete_confirm_info', 1, 0, 0, '', '', '', 'avail', '', '_bx_orgs_form_profile_input_delete_confirm_error', '', '', 1, 0),
 ('bx_organization', 'bx_organizations', 'do_submit', '_sys_form_account_input_submit', '', 0, 'submit', '_bx_orgs_form_profile_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
 ('bx_organization', 'bx_organizations', 'org_desc', '', '', 0, 'textarea', '_bx_orgs_form_profile_input_sys_org_desc', '_bx_orgs_form_profile_input_org_desc', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 1),
 ('bx_organization', 'bx_organizations', 'org_cat', '', '#!bx_organizations_cats', 0, 'select', '_bx_orgs_form_profile_input_sys_org_cat', '_bx_orgs_form_profile_input_org_cat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_orgs_form_profile_input_org_cat_err', 'Xss', '', 1, 1),
 ('bx_organization', 'bx_organizations', 'org_name', '', '', 0, 'text', '_bx_orgs_form_profile_input_sys_org_name', '_bx_orgs_form_profile_input_org_name', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_orgs_form_profile_input_org_name_err', 'Xss', '', 1, 0),
-('bx_organization', 'bx_organizations', 'picture', 'a:1:{i:0;s:8:"sys_crop";}', 'a:3:{s:10:"sys_simple";s:26:"_sys_uploader_simple_title";s:9:"sys_html5";s:25:"_sys_uploader_html5_title";s:8:"sys_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_orgs_form_profile_input_sys_picture', '_bx_orgs_form_profile_input_picture', '', 0, 0, 0, '', '', '', '', '', '_bx_orgs_form_profile_input_picture_err', 'Int', '', 1, 0);
+('bx_organization', 'bx_organizations', 'cover', 'a:1:{i:0;s:27:"bx_organizations_cover_crop";}', 'a:1:{s:27:"bx_organizations_cover_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_orgs_form_profile_input_sys_cover', '_bx_orgs_form_profile_input_cover', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_organization', 'bx_organizations', 'picture', 'a:1:{i:0;s:29:"bx_organizations_picture_crop";}', 'a:1:{s:29:"bx_organizations_picture_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_orgs_form_profile_input_sys_picture', '_bx_orgs_form_profile_input_picture', '', 0, 0, 0, '', '', '', '', '', '_bx_orgs_form_profile_input_picture_err', 'Int', '', 1, 0);
 
 
 INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
-('bx_organization_add', 'cover_preview', 2147483647, 0, 1),
 ('bx_organization_add', 'delete_confirm', 2147483647, 0, 3),
 ('bx_organization_add', 'cover', 2147483647, 0, 4),
 ('bx_organization_add', 'picture', 2147483647, 1, 5),
@@ -122,14 +120,12 @@ INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for
 ('bx_organization_add', 'org_desc', 2147483647, 1, 8),
 ('bx_organization_add', 'allow_view_to', 2147483647, 1, 9),
 ('bx_organization_add', 'do_submit', 2147483647, 1, 10),
-('bx_organization_delete', 'cover_preview', 2147483647, 0, 0),
 ('bx_organization_delete', 'picture', 2147483647, 0, 0),
 ('bx_organization_delete', 'delete_confirm', 2147483647, 1, 0),
 ('bx_organization_delete', 'cover', 2147483647, 0, 0),
 ('bx_organization_delete', 'do_submit', 2147483647, 1, 1),
 ('bx_organization_delete', 'org_name', 2147483647, 0, 2),
 ('bx_organization_delete', 'org_cat', 2147483647, 0, 3),
-('bx_organization_edit', 'cover_preview', 2147483647, 0, 1),
 ('bx_organization_edit', 'delete_confirm', 2147483647, 0, 2),
 ('bx_organization_edit', 'cover', 2147483647, 0, 3),
 ('bx_organization_edit', 'picture', 2147483647, 1, 5),
@@ -142,10 +138,8 @@ INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for
 ('bx_organization_edit_cover', 'org_name', 2147483647, 0, 2),
 ('bx_organization_edit_cover', 'picture', 2147483647, 0, 3),
 ('bx_organization_edit_cover', 'org_cat', 2147483647, 0, 5),
-('bx_organization_edit_cover', 'cover_preview', 2147483647, 1, 6),
 ('bx_organization_edit_cover', 'cover', 2147483647, 1, 7),
 ('bx_organization_edit_cover', 'do_submit', 2147483647, 1, 8),
-('bx_organization_view', 'cover_preview', 2147483647, 0, 1),
 ('bx_organization_view', 'delete_confirm', 2147483647, 0, 3),
 ('bx_organization_view', 'picture', 2147483647, 0, 4),
 ('bx_organization_view', 'cover', 2147483647, 0, 5),

+ 1 - 0
modules/boonex/organizations/template/uploader_form_crop_cover.html

@@ -0,0 +1 @@
+<bx_include_base:../modules/base/profile/template/uploader_form_crop_cover.html />

+ 2 - 2
modules/boonex/persons/classes/BxPersonsConfig.php

@@ -46,7 +46,6 @@ class BxPersonsConfig extends BxBaseModProfileConfig
             'FIELD_PICTURE' => 'picture',
             'FIELD_PICTURE_PREVIEW' => 'picture_preview',
             'FIELD_COVER' => 'cover',
-            'FIELD_COVER_PREVIEW' => 'cover_preview',
             'FIELD_ALLOW_VIEW_TO' => 'allow_view_to',
             'FIELDS_QUICK_SEARCH' => array('fullname'),
             'FIELDS_WITH_KEYWORDS' => 'auto', // can be 'auto', array of fields or comma separated string of field names, works only when OBJECT_METATAGS is specified
@@ -97,7 +96,8 @@ class BxPersonsConfig extends BxBaseModProfileConfig
             'OBJECT_PRIVACY_VIEW' => 'bx_persons_allow_view_to',
             'OBJECT_GRID_ADMINISTRATION' => 'bx_persons_administration',
             'OBJECT_GRID_COMMON' => 'bx_persons_common',
-            'OBJECT_UPLOADERS' => array('sys_simple', 'sys_html5', 'sys_crop'),
+            'OBJECT_UPLOADERS_COVER' => array('bx_persons_cover_crop'),
+            'OBJECT_UPLOADERS_PICTURE' => array('bx_persons_picture_crop'),
 
             'TRIGGER_MENU_PROFILE_VIEW_SUBMENU' => 'trigger_profile_view_submenu',
             'TRIGGER_MENU_PROFILE_VIEW_ACTIONS' => 'trigger_profile_view_actions',

+ 21 - 0
modules/boonex/persons/classes/BxPersonsUploaderCoverCrop.php

@@ -0,0 +1,21 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    Persons Persons
+ * @ingroup     TridentModules
+ *
+ * @{
+ */
+
+class BxPersonsUploaderCoverCrop extends BxBaseModProfileUploaderCoverCrop
+{
+    public function __construct ($aObject, $sStorageObject, $sUniqId, $oTemplate)
+    {
+        $this->_oModule = BxDolModule::getInstance('bx_persons');
+        parent::__construct($aObject, $sStorageObject, $sUniqId, $oTemplate);
+    }
+}
+
+/** @} */

+ 21 - 0
modules/boonex/persons/classes/BxPersonsUploaderPictureCrop.php

@@ -0,0 +1,21 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    Persons Persons
+ * @ingroup     TridentModules
+ *
+ * @{
+ */
+
+class BxPersonsUploaderPictureCrop extends BxBaseModProfileUploaderPictureCrop
+{
+    public function __construct ($aObject, $sStorageObject, $sUniqId, $oTemplate)
+    {
+        $this->_oModule = BxDolModule::getInstance('bx_persons');
+        parent::__construct($aObject, $sStorageObject, $sUniqId, $oTemplate);
+    }
+}
+
+/** @} */

+ 3 - 0
modules/boonex/persons/install/sql/disable.sql

@@ -44,3 +44,6 @@ DELETE FROM `sys_alerts_handlers` WHERE `id` = @iHandler;
 -- PRIVACY 
 DELETE FROM `sys_objects_privacy` WHERE `object` IN('bx_persons_allow_view_to');
 
+-- UPLOADERS
+DELETE FROM `sys_objects_uploader` WHERE `object` IN('bx_persons_cover_crop', 'bx_persons_picture_crop');
+

+ 4 - 0
modules/boonex/persons/install/sql/enable.sql

@@ -360,3 +360,7 @@ INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
 INSERT INTO `sys_objects_privacy` (`object`, `module`, `action`, `title`, `default_group`, `table`, `table_field_id`, `table_field_author`, `override_class_name`, `override_class_file`) VALUES
 ('bx_persons_allow_view_to', 'bx_persons', 'view', '_bx_persons_form_profile_input_allow_view_to', '3', 'bx_persons_data', 'id', 'author', 'BxPersonsPrivacy', 'modules/boonex/persons/classes/BxPersonsPrivacy.php');
 
+-- UPLOADERS
+INSERT INTO `sys_objects_uploader` (`object`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_persons_cover_crop', 1, 'BxPersonsUploaderCoverCrop', 'modules/boonex/persons/classes/BxPersonsUploaderCoverCrop.php'),
+('bx_persons_picture_crop', 1, 'BxPersonsUploaderPictureCrop', 'modules/boonex/persons/classes/BxPersonsUploaderPictureCrop.php');

+ 2 - 8
modules/boonex/persons/install/sql/install.sql

@@ -102,17 +102,15 @@ INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`,
 
 INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
 ('bx_person', 'bx_persons', 'allow_view_to', 3, '', 0, 'custom', '_bx_persons_form_profile_input_sys_allow_view_to', '_bx_persons_form_profile_input_allow_view_to', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
-('bx_person', 'bx_persons', 'cover', '', '', 0, 'file', '_bx_persons_form_profile_input_sys_cover', '_bx_persons_form_profile_input_cover', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
-('bx_person', 'bx_persons', 'cover_preview', '', '', 0, 'custom', '_bx_persons_form_profile_input_sys_cover_preview', '_bx_persons_form_profile_input_cover_preview', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
 ('bx_person', 'bx_persons', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_persons_form_profile_input_sys_delete_confirm', '_bx_persons_form_profile_input_delete_confirm', '_bx_persons_form_profile_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_persons_form_profile_input_delete_confirm_error', '', '', 1, 0),
 ('bx_person', 'bx_persons', 'do_submit', '_bx_persons_form_profile_input_submit', '', 0, 'submit', '_bx_persons_form_profile_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
 ('bx_person', 'bx_persons', 'description', '', '', 0, 'textarea', '_bx_persons_form_profile_input_sys_desc', '_bx_persons_form_profile_input_desc', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 1),
 ('bx_person', 'bx_persons', 'fullname', '', '', 0, 'text', '_bx_persons_form_profile_input_sys_fullname', '_bx_persons_form_profile_input_fullname', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_persons_form_profile_input_fullname_err', 'Xss', '', 1, 0),
-('bx_person', 'bx_persons', 'picture', 'a:1:{i:0;s:8:"sys_crop";}', 'a:3:{s:10:"sys_simple";s:26:"_sys_uploader_simple_title";s:9:"sys_html5";s:25:"_sys_uploader_html5_title";s:8:"sys_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_persons_form_profile_input_sys_picture', '_bx_persons_form_profile_input_picture', '', 0, 0, 0, '', '', '', '', '', '_bx_persons_form_profile_input_picture_err', 'Int', '', 1, 0);
+('bx_person', 'bx_persons', 'cover', 'a:1:{i:0;s:21:"bx_persons_cover_crop";}', 'a:1:{s:21:"bx_persons_cover_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_persons_form_profile_input_sys_cover', '_bx_persons_form_profile_input_cover', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_person', 'bx_persons', 'picture', 'a:1:{i:0;s:23:"bx_persons_picture_crop";}', 'a:1:{s:23:"bx_persons_picture_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_persons_form_profile_input_sys_picture', '_bx_persons_form_profile_input_picture', '', 0, 0, 0, '', '', '', '', '', '_bx_persons_form_profile_input_picture_err', 'Int', '', 1, 0);
 
 
 INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
-('bx_person_add', 'cover_preview', 2147483647, 0, 1),
 ('bx_person_add', 'delete_confirm', 2147483647, 0, 3),
 ('bx_person_add', 'cover', 2147483647, 0, 4),
 ('bx_person_add', 'picture', 2147483647, 1, 5),
@@ -121,12 +119,10 @@ INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for
 ('bx_person_add', 'allow_view_to', 2147483647, 1, 9),
 ('bx_person_add', 'do_submit', 2147483647, 1, 10),
 ('bx_person_delete', 'cover', 2147483647, 0, 0),
-('bx_person_delete', 'cover_preview', 2147483647, 0, 0),
 ('bx_person_delete', 'picture', 2147483647, 0, 0),
 ('bx_person_delete', 'delete_confirm', 2147483647, 1, 0),
 ('bx_person_delete', 'do_submit', 2147483647, 1, 1),
 ('bx_person_delete', 'fullname', 2147483647, 0, 2),
-('bx_person_edit', 'cover_preview', 2147483647, 0, 1),
 ('bx_person_edit', 'delete_confirm', 2147483647, 0, 2),
 ('bx_person_edit', 'cover', 2147483647, 0, 3),
 ('bx_person_edit', 'picture', 2147483647, 1, 5),
@@ -137,10 +133,8 @@ INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for
 ('bx_person_edit_cover', 'delete_confirm', 2147483647, 0, 1),
 ('bx_person_edit_cover', 'fullname', 2147483647, 0, 2),
 ('bx_person_edit_cover', 'picture', 2147483647, 0, 3),
-('bx_person_edit_cover', 'cover_preview', 2147483647, 1, 6),
 ('bx_person_edit_cover', 'cover', 2147483647, 1, 7),
 ('bx_person_edit_cover', 'do_submit', 2147483647, 1, 8),
-('bx_person_view', 'cover_preview', 2147483647, 0, 1),
 ('bx_person_view', 'delete_confirm', 2147483647, 0, 3),
 ('bx_person_view', 'picture', 2147483647, 0, 4),
 ('bx_person_view', 'cover', 2147483647, 0, 5),

+ 1 - 0
modules/boonex/persons/template/uploader_form_crop_cover.html

@@ -0,0 +1 @@
+<bx_include_base:../modules/base/profile/template/uploader_form_crop_cover.html />

+ 3 - 1
template/scripts/BxBaseUploaderCrop.php

@@ -13,6 +13,8 @@
  */
 class BxBaseUploaderCrop extends BxDolUploader
 {
+    protected $_sUploaderFormTemplate = 'uploader_form_crop.html';
+    
     function __construct ($aObject, $sStorageObject, $sUniqId, $oTemplate)
     {
         parent::__construct($aObject, $sStorageObject, $sUniqId, $oTemplate);
@@ -49,7 +51,7 @@ class BxBaseUploaderCrop extends BxDolUploader
      */
     public function getUploaderForm($isMultiple = true, $iContentId = false, $isPrivate = true)
     {
-        return $this->_oTemplate->parseHtmlByName('uploader_form_crop.html', array(
+        return $this->_oTemplate->parseHtmlByName($this->_sUploaderFormTemplate, array(
             'form_container_id' => $this->_sFormContainerId,
             'errors_container_id' => $this->_sErrorsContainerId,
             'uploader_instance_name' => $this->getNameJsInstanceUploader(),

+ 3 - 2
template/scripts/BxBaseUploaderHTML5.php

@@ -15,6 +15,7 @@
 class BxBaseUploaderHTML5 extends BxDolUploader
 {
     protected $_sDivId; ///< div id where upload button will be placed
+    protected $_sUploaderFormTemplate = 'uploader_form_html5.html';
 
     function __construct ($aObject, $sStorageObject, $sUniqId, $oTemplate)
     {
@@ -52,7 +53,7 @@ class BxBaseUploaderHTML5 extends BxDolUploader
      */
     public function getUploaderForm($isMultiple = true, $iContentId = false, $isPrivate = true)
     {
-        return $this->_oTemplate->parseHtmlByName('uploader_form_html5.html', array(
+        return $this->_oTemplate->parseHtmlByName($this->_sUploaderFormTemplate, array(
             'form_container_id' => $this->_sFormContainerId,
             'errors_container_id' => $this->_sErrorsContainerId,
             'uploader_instance_name' => $this->getNameJsInstanceUploader(),
@@ -73,7 +74,7 @@ class BxBaseUploaderHTML5 extends BxDolUploader
         $oStorage = BxDolStorage::getObjectInstance($this->_sStorageObject);
 
         if (!$isMultiple)
-            $this->cleanupGhostsForProfile($iProfileId, $iContentId);
+            $this->deleteGhostsForProfile($iProfileId, $iContentId);
 
         if (bx_get('qqfile'))
             $iId = $oStorage->storeFileFromXhr(bx_get('qqfile'), $bPrivate, $iProfileId, $iContentId);

+ 2 - 1
template/scripts/BxBaseUploaderSimple.php

@@ -14,6 +14,7 @@
 class BxBaseUploaderSimple extends BxDolUploader
 {
     protected $_sIframeId;
+    protected $_sUploaderFormTemplate = 'uploader_form_simple.html';
 
     function __construct ($aObject, $sStorageObject, $sUniqId, $oTemplate)
     {
@@ -41,7 +42,7 @@ class BxBaseUploaderSimple extends BxDolUploader
      */
     public function getUploaderForm($isMultiple = true, $iContentId = false, $isPrivate = true)
     {
-        return $this->_oTemplate->parseHtmlByName('uploader_form_simple.html', array(
+        return $this->_oTemplate->parseHtmlByName($this->_sUploaderFormTemplate, array(
             'form_container_id' => $this->_sFormContainerId,
             'errors_container_id' => $this->_sErrorsContainerId,
             'uploader_instance_name' => $this->getNameJsInstanceUploader(),

+ 1 - 1
template/uploader_button_crop_js.html

@@ -1,7 +1,7 @@
 <script>
     $(document).ready(function(){
         __uploader_instance_name__ = new BxDolUploaderCrop('__engine__', '__storage_object__', '__uniq_id__', {
-            'multiple': true,
+            'multiple': __multiple__,
             'content_id': '__content_id__',
             'images_transcoder' : '__images_transcoder__',
             'storage_private' : '__storage_private__',