Commit eb4f24fe06642f9dac8d222fa43143066a5fc08c

Authored by Charl Joseph Mert
1 parent 3110bf31

Brand server without requiring access to FS

PT: 1243391

Added ability to choose between best try proportional scale and top left crop images.

Updated by: Charl Joseph Mert
plugins/ktcore/KTCorePlugin.php
... ... @@ -200,6 +200,7 @@ class KTCorePlugin extends KTPlugin {
200 200 $this->registerWidget('KTCoreLayerWidget', 'ktcore.widgets.layer', 'KTWidgets.php');
201 201 $this->registerWidget('KTCoreConditionalSelectionWidget', 'ktcore.widgets.conditionalselection', 'KTWidgets.php');
202 202 $this->registerWidget('KTCoreImageWidget', 'ktcore.widgets.image', 'KTWidgets.php');
  203 + $this->registerWidget('KTCoreImageSelectWidget', 'ktcore.widgets.imageselect', 'KTWidgets.php');
203 204 $this->registerWidget('KTCoreImageCropWidget', 'ktcore.widgets.imagecrop', 'KTWidgets.php');
204 205  
205 206 $this->registerPage('collection', 'KTCoreCollectionPage', 'KTWidgets.php');
... ...
plugins/ktcore/KTWidgets.php
... ... @@ -1140,6 +1140,56 @@ class KTCoreImageWidget extends KTWidget {
1140 1140 return $oTemplate->render($aTemplateData);
1141 1141 }
1142 1142  
  1143 +}
  1144 +
  1145 +class KTCoreImageSelectWidget extends KTWidget {
  1146 + var $sNamespace = 'ktcore.widgets.imageselect';
  1147 + var $sTemplate = 'ktcore/forms/widgets/imageselect';
  1148 +
  1149 + function configure($aOptions) {
  1150 + $res = parent::configure($aOptions);
  1151 + if (PEAR::isError($res)) {
  1152 + return $res;
  1153 + }
  1154 +
  1155 + }
  1156 +
  1157 + function render() {
  1158 + $oTemplating =& KTTemplating::getSingleton();
  1159 + $oTemplate = $oTemplating->loadTemplate('ktcore/forms/widgets/base');
  1160 +
  1161 + $this->aJavascript[] = 'thirdpartyjs/jquery/jquery-1.3.2.js';
  1162 +
  1163 + if (!empty($this->aJavascript)) {
  1164 + // grab our inner page.
  1165 + $oPage =& $GLOBALS['main'];
  1166 + $oPage->requireJSResources($this->aJavascript);
  1167 + }
  1168 +
  1169 + $this->aCSS[] = 'resources/css/kt_imageselect.css';
  1170 +
  1171 + if (!empty($this->aCSS)) {
  1172 + // grab our inner page.
  1173 + $oPage =& $GLOBALS['main'];
  1174 + $oPage->requireCSSResources($this->aCSS);
  1175 + }
  1176 +
  1177 + $widget_content = $this->getWidget();
  1178 +
  1179 + $aTemplateData = array(
  1180 + "context" => $this,
  1181 + "label" => $this->sLabel,
  1182 + "description" => $this->sDescription,
  1183 + "name" => $this->sName,
  1184 + "has_value" => ($this->value !== null),
  1185 + "value" => $this->value,
  1186 + "has_errors" => $bHasErrors,
  1187 + "errors" => $this->aErrors,
  1188 + "options" => $this->aOptions,
  1189 + "widget" => $widget_content,
  1190 + );
  1191 + return $oTemplate->render($aTemplateData);
  1192 + }
1143 1193  
1144 1194 }
1145 1195  
... ...
plugins/ktcore/admin/manageBranding.php
... ... @@ -84,7 +84,7 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
84 84 'encoding' => 'multipart/form-data',
85 85 'context' => &$this,
86 86 'extraargs' => $this->meldPersistQuery("","",true),
87   - 'description' => _kt('The logo upload facility allows you to upload a logo to brand your knowledgetree site.')
  87 + 'description' => _kt('You can upload a logo to brand your KnowledgeTree site.')
88 88 ));
89 89  
90 90 $oWF =& KTWidgetFactory::getSingleton();
... ... @@ -99,7 +99,7 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
99 99 'name' => 'file',
100 100 'id' => 'file',
101 101 'value' => '',
102   - 'description' => _kt('The logo should be 313px by 50px in dimension. If you don\'t have a 313x50 logo you should choose to either "crop" or "scale" it. If you are certain that your logo has the correct dimentions you can safely skip by the selecting "Don\'t do anything"'),
  102 + 'description' => _kt("The logo's dimensions should be 313px width by 50px height. If your logo doesn't fit these dimensions, you can choose to crop or scale it."),
103 103 ));
104 104  
105 105 $aVocab['crop'] = 'Crop - Cut out a selection';
... ... @@ -142,6 +142,61 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
142 142  
143 143  
144 144 /**
  145 + * Returns the scale logo form
  146 + *
  147 + * This form will display a preview of all the possible sclaled combinations.
  148 + * This includes:
  149 + *
  150 + * Stretched, Top Left Cropped, Proportional Stretch, Proportional Top Left Cropped
  151 + *
  152 + * @return KTForm
  153 + *
  154 + */
  155 +
  156 + function getScaleLogoForm($logoItems = array()) {
  157 + $this->oPage->setBreadcrumbDetails(_kt("Scale Logo"));
  158 +
  159 + $oForm = new KTForm;
  160 + $oForm->setOptions(array(
  161 + 'identifier' => 'ktcore.folder.branding',
  162 + 'label' => _kt('Choose Logo'),
  163 + 'submit_label' => _kt('Select'),
  164 + 'action' => 'selectLogo',
  165 + 'fail_action' => 'main',
  166 + 'encoding' => 'multipart/form-data',
  167 + 'context' => &$this,
  168 + 'extraargs' => $this->meldPersistQuery("","",true),
  169 + 'description' => _kt('Choose a logo by clicking on one of the images')
  170 + ));
  171 +
  172 + $oWF =& KTWidgetFactory::getSingleton();
  173 +
  174 + $widgets = array();
  175 + $validators = array();
  176 +
  177 + $logoFileName = 'var'.DIRECTORY_SEPARATOR.'branding'.DIRECTORY_SEPARATOR.'logo'.DIRECTORY_SEPARATOR.$logoFileName;
  178 +
  179 + // Adding the image select widget (User will select the best image)
  180 + $widgets[] = $oWF->get('ktcore.widgets.imageselect', array(
  181 + 'label' => _kt('Logo Preview'),
  182 + 'name' => $logoFileName,
  183 + 'value' => $logoItems,
  184 + ));
  185 +
  186 + // Adding the Hidden FileName Input String
  187 + $widgets[] = $oWF->get('ktcore.widgets.hidden', array(
  188 + 'name' => 'kt_imageselect',
  189 + 'value' => $logoItems[0],
  190 + ));
  191 +
  192 + $oForm->setWidgets($widgets);
  193 + $oForm->setValidators($validators);
  194 +
  195 + return $oForm;
  196 + }
  197 +
  198 +
  199 + /**
145 200 * Returns the crop logo form
146 201 *
147 202 * This form will assist the user in selecting an area of the image to use as the logo
... ... @@ -311,7 +366,7 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
311 366  
312 367 //Changing to logo.jpg (Need to preserve extention as GD requires the exact image type to work)
313 368 $ext = end(explode('.', $logoFileName));
314   - $logoFileName = 'logo_tmp.'.$ext;
  369 + $logoFileName = 'logo_tmp_'.md5(Date('ymd-hms')).'.'.$ext; //Fighting the browser cache here
315 370 $logoFile = $logoDir.DIRECTORY_SEPARATOR.$logoFileName;
316 371  
317 372 // deleting old tmp file
... ... @@ -329,6 +384,8 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
329 384  
330 385 $resizeMethod = $_REQUEST['data']['resize_method'];
331 386  
  387 + $relDir = 'var'.DIRECTORY_SEPARATOR.'branding'.DIRECTORY_SEPARATOR.'logo'.DIRECTORY_SEPARATOR;
  388 +
332 389 switch ($resizeMethod) {
333 390 case 'crop':
334 391 $cropLogoForm = $this->getCropLogoForm($logoFileName);
... ... @@ -336,9 +393,24 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
336 393  
337 394 case 'scale':
338 395 $type = $_FILES['_kt_attempt_unique_file']['type'];
339   - $res = $this->scaleImage($logoFile, $logoFile, $this->maxLogoWidth, $this->maxLogoHeight, $type);
340 396  
341   - $form = $this->getApplyLogoForm($logoFileName);
  397 + $logoFileNameStretched = 'logo_tmp_stretched_'.md5(Date('ymd-hms')).'.'.$ext; //Fighting the browser cache here
  398 + $logoFileStretched = $logoDir.DIRECTORY_SEPARATOR.$logoFileNameStretched;
  399 +
  400 + $logoFileNameCropped = 'logo_tmp_cropped_'.md5(Date('ymd-hms')).'.'.$ext; //Fighting the browser cache here
  401 + $logoFileCropped = $logoDir.DIRECTORY_SEPARATOR.$logoFileNameCropped;
  402 +
  403 + //Creating stretched image
  404 + $res = $this->scaleImage($logoFile, $logoFileStretched, $this->maxLogoWidth, $this->maxLogoHeight, $type, false, false);
  405 +
  406 + //Creating top-left cropped image
  407 + $res = $this->scaleImage($logoFile, $logoFileCropped, $this->maxLogoWidth, $this->maxLogoHeight, $type, false, true);
  408 + $res = $this->cropImage($logoFileCropped, $logoFileCropped, 0, 0, $this->maxLogoWidth, $this->maxLogoHeight, $type);
  409 +
  410 + $logoItem[] = $relDir.$logoFileNameStretched;
  411 + $logoItem[] = $relDir.$logoFileNameCropped;
  412 +
  413 + $form = $this->getScaleLogoForm($logoItem);
342 414 return $form->render();
343 415  
344 416 default:
... ... @@ -354,7 +426,7 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
354 426 * - Supported images are jpeg, png and gif
355 427 *
356 428 */
357   - public function scaleImage( $origFile, $destFile, $width, $height, $type = 'image/jpeg', $scaleUp = true) {
  429 + public function scaleImage( $origFile, $destFile, $width, $height, $type = 'image/jpeg', $scaleUp = false, $keepProportion = true) {
358 430 global $default;
359 431  
360 432 //Requires the GD library if not exit gracefully
... ... @@ -399,7 +471,11 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
399 471  
400 472 $image_x = $width;
401 473 $image_y = $height;
402   - //$image_y = round(($orig_y * $image_x) / $orig_x); //Preserve proportion
  474 +
  475 + //Constraining proportion
  476 + if ($keepProportion) {
  477 + $image_y = round(($orig_y * $image_x) / $orig_x); //Preserve proportion
  478 + }
403 479  
404 480 /*
405 481 * create the new image, and scale the original into it.
... ... @@ -426,7 +502,6 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
426 502 return false;
427 503 }
428 504  
429   -
430 505 } else {
431 506 //Handle Error
432 507 $default->log->error("Couldn't obtain a valid GD resource");
... ... @@ -446,9 +521,13 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
446 521 function do_crop(){
447 522 global $default;
448 523  
449   - $logoFileName = $_REQUEST['data']['logo_file_name'];
  524 + $logoFileName = $_REQUEST['data']['logo_file_name'];
450 525 $logoFile = 'var'.DIRECTORY_SEPARATOR.'branding'.DIRECTORY_SEPARATOR.'logo'.DIRECTORY_SEPARATOR.$logoFileName;
451   -
  526 +
  527 + $ext = end(explode('.', $logoFileName));
  528 + $destFileName = 'logo_tmp_'.md5(Date('ymd-hms')).'.'.$ext;
  529 + $destFile = 'var'.DIRECTORY_SEPARATOR.'branding'.DIRECTORY_SEPARATOR.'logo'.DIRECTORY_SEPARATOR.$destFileName;
  530 +
452 531 $x1 = $_REQUEST['data']['crop_x1'];
453 532 $y1 = $_REQUEST['data']['crop_y1'];
454 533  
... ... @@ -458,7 +537,7 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
458 537 $type = $this->getMime($logoFileName);
459 538  
460 539 //GD Crop
461   - $res = $this->cropImage($logoFile, $logoFile, $x1, $y1, $x2, $y2, $type);
  540 + $res = $this->cropImage($logoFile, $destFile, $x1, $y1, $x2, $y2, $type);
462 541  
463 542 //If dimensions don't conform then will scale it further
464 543 $width = $x2 - $x1;
... ... @@ -466,7 +545,7 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
466 545  
467 546 if (($width > $this->maxLogoWidth) || ($height > $this->maxLogoHeight)) {
468 547 $default->log->info('SCALING IMAGE AFTER CROP');
469   - $res = $this->scaleImage($logoFile, $logoFile, $this->maxLogoWidth, $this->maxLogoHeight, $type);
  548 + $res = $this->scaleImage($logoFile, $destFile, $this->maxLogoWidth, $this->maxLogoHeight, $type);
470 549 }
471 550  
472 551 // ImageMagick Crop
... ... @@ -485,7 +564,7 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
485 564 $result = KTUtil::pexec($cmd);
486 565 */
487 566  
488   - $applyLogoForm = $this->getApplyLogoForm($logoFileName);
  567 + $applyLogoForm = $this->getApplyLogoForm($destFileName);
489 568 return $applyLogoForm->render();
490 569  
491 570 }
... ... @@ -600,6 +679,21 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
600 679 }
601 680  
602 681  
  682 + /*
  683 + * Action responsible for selecting the logo after it has been scaled.
  684 + *
  685 + */
  686 + function do_selectLogo(){
  687 + global $default;
  688 +
  689 + $tmpLogoFileName = end(explode(DIRECTORY_SEPARATOR, $_REQUEST['kt_imageselect']));
  690 +
  691 + $form = $this->getApplyLogoForm($tmpLogoFileName);
  692 + return $form->render();
  693 +
  694 + }
  695 +
  696 +
603 697  
604 698 /*
605 699 * Action responsible for applying the logo
... ... @@ -628,10 +722,12 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
628 722 $brandDir = $default->varDirectory.DIRECTORY_SEPARATOR.'branding'.DIRECTORY_SEPARATOR.'logo'.DIRECTORY_SEPARATOR;
629 723 $handle = opendir($brandDir);
630 724 while (false !== ($file = readdir($handle))) {
631   - if (!is_dir($file) && $file != 'logo_tmp.jpg' && $file != $logoFileName) {
  725 + if (!is_dir($file) && $file != $tmpLogoFileName && $file != $logoFileName) {
632 726 if (!@unlink($brandDir.$file)) {
633 727 $default->log->error("Couldn't delete '".$brandDir.$file."'");
634   - }
  728 + } else {
  729 + $default->log->error("Cleaning Brand Logo Dir: Deleted '".$brandDir.$file."'");
  730 + }
635 731 }
636 732 }
637 733 }
... ... @@ -665,128 +761,6 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
665 761 $this->successRedirectTo('', _kt("Logo succesfully applied."));
666 762 }
667 763  
668   -
669   - /*
670   -
671   - Old Manage Views Code!
672   - Crap, must delete
673   -
674   - */
675   - function do_editView() {
676   - $oTemplating =& KTTemplating::getSingleton();
677   - $oTemplate = $oTemplating->loadTemplate('ktcore/misc/columns/edit_view');
678   -
679   - $oColumnRegistry =& KTColumnRegistry::getSingleton();
680   - $aColumns = $oColumnRegistry->getColumnsForView($_REQUEST['viewNS']);
681   - //var_dump($aColumns); exit(0);
682   - $aAllColumns = $oColumnRegistry->getColumns();
683   -
684   - $view_name = $oColumnRegistry->getViewName(($_REQUEST['viewNS']));
685   - $this->oPage->setTitle($view_name);
686   - $this->oPage->setBreadcrumbDetails($view_name);
687   -
688   - $aOptions = array();
689   - $vocab = array();
690   - foreach ($aAllColumns as $aInfo) {
691   - $vocab[$aInfo['namespace']] = $aInfo['name'];
692   - }
693   - $aOptions['vocab'] = $vocab;
694   - $add_field = new KTLookupWidget(_kt("Columns"), _kt("Select a column to add to the view. Please note that while you can add multiple copies of a column, they will all behave as a single column"), 'column_ns', null, $this->oPage, true, null, $aErrors = null, $aOptions);
695   -
696   - $aTemplateData = array(
697   - 'context' => $this,
698   - 'current_columns' => $aColumns,
699   - 'all_columns' => $aAllColumns,
700   - 'view' => $_REQUEST['viewNS'],
701   - 'add_field' => $add_field,
702   - );
703   - return $oTemplate->render($aTemplateData);
704   - }
705   -
706   - function do_deleteEntry() {
707   - $entry_id = KTUtil::arrayGet($_REQUEST, 'entry_id');
708   - $view = KTUtil::arrayGet($_REQUEST, 'viewNS');
709   -
710   - // none of these conditions can be reached "normally".
711   -
712   - $oEntry = KTColumnEntry::get($entry_id);
713   - if (PEAR::isError($oEntry)) {
714   - $this->errorRedirectToMain(_kt("Unable to locate the entry"));
715   - }
716   -
717   - if ($oEntry->getRequired()) {
718   - $this->errorRedirectToMain(_kt("That column is required"));
719   - }
720   -
721   - if ($oEntry->getViewNamespace() != $view) {
722   - $this->errorRedirectToMain(_kt("That column is not for the specified view"));
723   - }
724   -
725   - $res = $oEntry->delete();
726   -
727   - if (PEAR::isError($res)) {
728   - $this->errorRedirectToMain(sprintf(_kt("Failed to remove that column: %s"), $res->getMessage()));
729   - }
730   -
731   - $this->successRedirectTo("editView", _kt("Deleted Entry"), sprintf("viewNS=%s", $view));
732   - }
733   -
734   - function do_addEntry() {
735   - $column_ns = KTUtil::arrayGet($_REQUEST, 'column_ns');
736   - $view = KTUtil::arrayGet($_REQUEST, 'viewNS');
737   -
738   - $this->startTransaction();
739   -
740   - $position = KTColumnEntry::getNextEntryPosition($view);
741   - $oEntry = KTColumnEntry::createFromArray(array(
742   - 'ColumnNamespace' => $column_ns,
743   - 'ViewNamespace' => $view,
744   - 'Position' => $position, // start it at the bottom
745   - 'config' => array(), // stub, for now.
746   - 'Required' => 0
747   - ));
748   -
749   - $this->successRedirectTo("editView", _kt("Added Entry"), sprintf("viewNS=%s", $view));
750   - }
751   -
752   - function do_orderUp(){
753   - $entryId = $_REQUEST['entry_id'];
754   - $view = $_REQUEST['viewNS'];
755   -
756   - $oEntry = KTColumnEntry::get($entryId);
757   - if (PEAR::isError($oEntry)) {
758   - $this->errorRedirectTo('editView', _kt('Unable to locate the column entry'), "viewNS={$view}");
759   - exit();
760   - }
761   -
762   - $res = $oEntry->movePosition($view, $entryId, 'up');
763   - if (PEAR::isError($res)) {
764   - $this->errorRedirectTo('editView', $res->getMessage(), "viewNS={$view}");
765   - exit();
766   - }
767   -
768   - $this->redirectTo('editView', "viewNS={$view}");
769   - }
770   -
771   - function do_orderDown(){
772   - $entryId = $_REQUEST['entry_id'];
773   - $view = $_REQUEST['viewNS'];
774   -
775   - $oEntry = KTColumnEntry::get($entryId);
776   - if (PEAR::isError($oEntry)) {
777   - $this->errorRedirectTo('editView', _kt('Unable to locate the column entry'), "viewNS={$view}");
778   - exit();
779   - }
780   -
781   - $res = $oEntry->movePosition($view, $entryId, 'down');
782   - if (PEAR::isError($res)) {
783   - $this->errorRedirectTo('editView', $res->getMessage(), "viewNS={$view}");
784   - exit();
785   - }
786   -
787   - $this->redirectTo("editView", "viewNS={$view}");
788   - }
789   -
790 764 }
791 765  
792 766 ?>
... ...
resources/css/kt_imageselect.css 0 → 100644
  1 +#kt_image_select_container img {
  2 + cursor: pointer;
  3 + text-decoration: none;
  4 + border: 10px solid white;
  5 +}
  6 +
  7 +#kt_image_select_container img:hover {
  8 + text-decoration: none;
  9 + border: 10px solid white;
  10 +}
  11 +
... ...
templates/ktcore/forms/widgets/imageselect.smarty 0 → 100755
  1 +<fieldset {if $has_name}title="{$name}"{/if}>
  2 + <field>
  3 + <div id="kt_image_select_container">
  4 +
  5 + {foreach key=id item=src from=$value}
  6 +
  7 + <img class="kt_image_select" id="kt_image_select_{$id}" src="{$src}" border="0"/>
  8 +
  9 + <script type="text/javascript">
  10 + var toggle_{$id} = 1;
  11 + var selected = '';
  12 +
  13 + var multiselect = false;
  14 +
  15 + var hover = '#f9f9f9';
  16 + var click = '#f2943a'; //Orange
  17 + var background_color = 'white'; //also set in css
  18 +
  19 + jQuery('#kt_image_select_{$id}').click(function(){ldelim}
  20 + jQuery('#kt_image_select').val('{$src}');
  21 +
  22 + //Resetting background:
  23 + jQuery("img[id*='kt_image_select_']").css('border', '10px solid ' + background_color);
  24 + jQuery('#kt_image_select_{$id}').css('border', '10px solid ' + click);
  25 + window.console.log('#kt_image_select_{$id} = {$src} : toggle_{$id} [' + toggle_{$id} + ']');
  26 + {rdelim})
  27 + </script>
  28 +
  29 + {/foreach}
  30 +
  31 + </div>
  32 +
  33 + <input type="hidden" name="kt_imageselect" value="" id="kt_image_select"/>
  34 + </field>
  35 +</fieldset>
... ...