Changeset 1917 for plugins/apostrophePlugin/trunk
- Timestamp:
- 08/08/10 12:18:34 (22 months ago)
- Location:
- plugins/apostrophePlugin/trunk
- Files:
-
- 27 modified
- 11 copied
-
. (modified) (1 prop)
-
config/doctrine/schema.yml (modified) (4 diffs)
-
lib/action/BaseaMediaActions.class.php (modified) (10 diffs)
-
lib/action/BaseaMediaBackendActions.class.php (modified) (3 diffs)
-
lib/action/BaseaMediaComponents.class.php (modified) (1 diff)
-
lib/action/BaseaSlideshowSlotComponents.class.php (modified) (1 diff)
-
lib/model/doctrine/PluginaMediaItem.class.php (modified) (4 diffs)
-
lib/model/doctrine/PluginaMediaItemTable.class.php (modified) (1 diff)
-
lib/toolkit/aDimensions.class.php (modified) (2 diffs)
-
lib/toolkit/aDoctrine.class.php (modified) (1 diff)
-
lib/toolkit/aImageConverter.class.php (modified) (3 diffs)
-
lib/toolkit/aImageConverterTest.php (modified) (1 diff)
-
lib/toolkit/aMediaAPI.php (modified) (1 diff)
-
lib/toolkit/aMediaRouting.php (modified) (2 diffs)
-
lib/toolkit/aMediaSelect.class.php (copied) (copied from plugins/apostrophePlugin/branches/features/cropping/lib/toolkit/aMediaSelect.class.php)
-
lib/toolkit/aMediaTools.php (modified) (3 diffs)
-
modules/aImageSlot/templates/_normalView.php (modified) (1 diff)
-
modules/aMedia/templates/_browser.php (modified) (1 diff)
-
modules/aMedia/templates/_describeConstraints.php (modified) (1 diff)
-
modules/aMedia/templates/_mediaItem.php (modified) (1 diff)
-
modules/aMedia/templates/_multipleList.php (modified) (5 diffs)
-
modules/aMedia/templates/_multiplePreview.php (copied) (copied from plugins/apostrophePlugin/branches/features/cropping/modules/aMedia/templates/_multiplePreview.php) (1 diff)
-
modules/aMedia/templates/_selectMultiple.php (modified) (2 diffs)
-
modules/aMedia/templates/_selectSingle.php (modified) (1 diff)
-
modules/aMedia/templates/cropSuccess.php (copied) (copied from plugins/apostrophePlugin/branches/features/cropping/modules/aMedia/templates/cropSuccess.php)
-
modules/aMedia/templates/indexSuccess.php (modified) (3 diffs)
-
modules/aMedia/templates/updateMultiplePreviewSuccess.php (copied) (copied from plugins/apostrophePlugin/branches/features/cropping/modules/aMedia/templates/updateMultiplePreviewSuccess.php)
-
modules/aSlideshowSlot/templates/_normalView.php (modified) (1 diff)
-
modules/aVideoSlot/templates/_normalView.php (modified) (1 diff)
-
web/css/Jcrop (copied) (copied from plugins/apostrophePlugin/branches/features/cropping/web/css/Jcrop)
-
web/css/Jcrop/Jcrop.gif (copied) (copied from plugins/apostrophePlugin/branches/features/cropping/web/css/Jcrop/Jcrop.gif)
-
web/css/Jcrop/jquery.Jcrop.css (copied) (copied from plugins/apostrophePlugin/branches/features/cropping/web/css/Jcrop/jquery.Jcrop.css)
-
web/css/a.css (modified) (9 diffs, 1 prop)
-
web/css/jquery.Jcrop.css (copied) (copied from plugins/apostrophePlugin/branches/features/cropping/web/css/jquery.Jcrop.css)
-
web/images (modified) (1 prop)
-
web/images/a-icon-crop.png (copied) (copied from plugins/apostrophePlugin/branches/features/cropping/web/images/a-icon-crop.png)
-
web/js/aCrop.js (copied) (copied from plugins/apostrophePlugin/branches/features/cropping/web/js/aCrop.js)
-
web/js/plugins/jquery.Jcrop.min.js (copied) (copied from plugins/apostrophePlugin/branches/features/cropping/web/js/plugins/jquery.Jcrop.min.js)
Legend:
- Unmodified
- Added
- Removed
-
plugins/apostrophePlugin/trunk
- Property svn:mergeinfo changed
-
plugins/apostrophePlugin/trunk/config/doctrine/schema.yml
r1704 r1917 373 373 Timestampable: ~ 374 374 Taggable: ~ 375 376 # For virtual media items that are just croppings of others, we explicitly set slug. 377 # If this item is a crop of another item, the slug will 378 # look like this: original_slug.cropLeft.cropTop.cropWidth.cropHeight 379 # The aMediaBackend/image action then sees these extra 380 # parameters in the route and behaves accordingly 381 # and we can look directly at that file to finish the job 382 383 # Otherwise we let the behavior do its job 384 375 385 Sluggable: 376 386 fields: [title] … … 378 388 # We unified this 379 389 builder: aTools::slugify 390 380 391 columns: 381 392 id: … … 404 415 format: 405 416 type: string(10) 417 406 418 # Preferred still image or video dimensions. For a still image 407 419 # these are the dimensions of the original. For video they are … … 411 423 height: 412 424 type: integer(4) 413 425 414 426 # If this field is non-null, it contains HTML embed/object code to 415 427 # be used without alteration (except for replacing _WIDTH_ and _HEIGHT_) -
plugins/apostrophePlugin/trunk/lib/action/BaseaMediaActions.class.php
r1872 r1917 31 31 } 32 32 33 // Supported for backwards compatibility. See also 34 // aMediaSelect::select() 35 33 36 public function executeSelect(sfRequest $request) 34 37 { … … 45 48 $selection = array($request->getParameter('aMediaId') + 0); 46 49 } 47 $items = aMediaItemTable::retrieveByIds($selection);48 $ids = array();49 foreach ($items as $item)50 {51 $ids[] = $item->getId();52 }53 50 $options = array(); 54 51 $optional = array('type', 'aspect-width', 'aspect-height', … … 61 58 } 62 59 } 63 aMediaTools::setSelecting($after, $multiple, $ ids, $options);60 aMediaTools::setSelecting($after, $multiple, $selection, $options); 64 61 65 62 return $this->redirect("aMedia/index"); … … 113 110 $aspectWidth = floor(aMediaTools::getAttribute('aspect-width')); 114 111 $aspectHeight = floor(aMediaTools::getAttribute('aspect-height')); 115 // TODO: performance of these is not awesome (it's a linear search). 116 // It would be more awesome with the right kind of indexing. For the 117 // aspect ratio test to be more efficient we'd have to store the lowest 118 // common denominator aspect ratio and index that. 119 if ($aspectWidth && $aspectHeight) 120 { 121 $params['aspect-width'] = $aspectWidth; 122 $params['aspect-height'] = $aspectHeight; 123 } 124 125 $minimumWidth = floor(aMediaTools::getAttribute('minimum-width')); 126 if ($minimumWidth) 127 { 112 113 if ($type === 'image') 114 { 115 // Now that we provide cropping tools, width and height should only exclude images 116 // that are too small to ever be cropped to that size 117 $minimumWidth = floor(aMediaTools::getAttribute('minimum-width')); 118 $width = floor(aMediaTools::getAttribute('width')); 119 $minimumWidth = max($minimumWidth, $width); 120 $minimumHeight = floor(aMediaTools::getAttribute('minimum-height')); 121 $height = floor(aMediaTools::getAttribute('height')); 122 $minimumHeight = max($minimumHeight, $height); 123 // Careful, aspect ratio can impose a bound on the other dimension 124 if ($minimumWidth && $aspectWidth) 125 { 126 $minimumHeight = max($minimumHeight, $minimumWidth * $aspectHeight / $aspectWidth); 127 } 128 if ($minimumHeight && $aspectHeight) 129 { 130 $minimumWidth = max($minimumWidth, $minimumHeight * $aspectWidth / $aspectHeight); 131 } 132 // We've updated these with implicit constraints from the aspect ratio, the width and height params, etc. 133 aMediaTools::setAttribute('minimum-width', $minimumWidth); 134 aMediaTools::setAttribute('minimum-height', $minimumHeight); 128 135 $params['minimum-width'] = $minimumWidth; 129 }130 $minimumHeight = floor(aMediaTools::getAttribute('minimum-height'));131 if ($minimumHeight)132 {133 136 $params['minimum-height'] = $minimumHeight; 134 137 } 135 $width = floor(aMediaTools::getAttribute('width')); 136 if ($width) 137 { 138 $params['width'] = $width; 139 } 140 $height = floor(aMediaTools::getAttribute('height')); 141 if ($height) 142 { 143 $params['height'] = $height; 144 } 145 138 else 139 { 140 // TODO: performance of these is not awesome (it's a linear search). 141 // It would be more awesome with the right kind of indexing. For the 142 // aspect ratio test to be more efficient we'd have to store the lowest 143 // common denominator aspect ratio and index that. 144 if ($aspectWidth && $aspectHeight) 145 { 146 $params['aspect-width'] = $aspectWidth; 147 $params['aspect-height'] = $aspectHeight; 148 } 149 150 $minimumWidth = floor(aMediaTools::getAttribute('minimum-width')); 151 if ($minimumWidth) 152 { 153 $params['minimum-width'] = $minimumWidth; 154 } 155 $minimumHeight = floor(aMediaTools::getAttribute('minimum-height')); 156 if ($minimumHeight) 157 { 158 $params['minimum-height'] = $minimumHeight; 159 } 160 $width = floor(aMediaTools::getAttribute('width')); 161 if ($width) 162 { 163 $params['width'] = $width; 164 } 165 $height = floor(aMediaTools::getAttribute('height')); 166 if ($height) 167 { 168 $params['height'] = $height; 169 } 170 } 171 146 172 // The media module is now an engine module. There is always a page, and that 147 173 // page might have a restricted set of categories associated with it … … 162 188 $this->pager->init(); 163 189 $this->results = $this->pager->getResults(); 190 164 191 aMediaTools::setSearchParameters( 165 192 array("tag" => $tag, "type" => $type, … … 175 202 $this->label = aMediaTools::getAttribute("label"); 176 203 } 177 $this->limitSizes = false; 178 if ($aspectWidth || $aspectHeight || $minimumWidth || $minimumHeight || 179 $width || $height) 180 { 181 $this->limitSizes = true; 182 } 204 $this->limitSizes = ($minimumWidth || $minimumHeight); 183 205 } 184 206 } … … 215 237 $parameters)); 216 238 } 217 239 240 // Accept and store cropping information for a particular image which must already be part of the selection 241 public function executeCrop(sfRequest $request) 242 { 243 $selection = aMediaTools::getSelection(); 244 $id = $request->getParameter('id'); 245 $index = array_search($id, $selection); 246 if ($index === false) 247 { 248 error_log("ID is $id and not found in index which is " . implode(',', $selection)); 249 $this->forward404(); 250 } 251 $cropLeft = floor($request->getParameter('cropLeft')); 252 $cropTop = floor($request->getParameter('cropTop')); 253 $cropWidth = floor($request->getParameter('cropWidth')); 254 $cropHeight = floor($request->getParameter('cropHeight')); 255 $width = floor($request->getParameter('width')); 256 $height = floor($request->getParameter('height')); 257 $imageInfo = aMediaTools::getAttribute('imageInfo'); 258 $imageInfo[$id]['cropLeft'] = $cropLeft; 259 $imageInfo[$id]['cropTop'] = $cropTop; 260 $imageInfo[$id]['cropWidth'] = $cropWidth; 261 $imageInfo[$id]['cropHeight'] = $cropHeight; 262 $imageInfo[$id]['width'] = $width; 263 $imageInfo[$id]['height'] = $height; 264 aMediaTools::setAttribute('imageInfo', $imageInfo); 265 } 266 218 267 public function executeMultipleAdd(sfRequest $request) 219 268 { 220 $this->forward404Unless(aMediaTools::isMultiple());221 269 $id = $request->getParameter('id') + 0; 222 270 $item = Doctrine::getTable("aMediaItem")->find($id); 223 271 $this->forward404Unless($item); 224 272 $selection = aMediaTools::getSelection(); 225 $index = array_search($id, $selection); 226 // One occurrence each. If this changes we'll have to rethink 227 // the way reordering and deletion work (probably go by index). 228 if ($index === false) 229 { 230 $selection[] = $id; 273 if (!aMediaTools::isMultiple()) 274 { 275 $selection = array($id); 276 } 277 else 278 { 279 $index = array_search($id, $selection); 280 // One occurrence each. If this changes we'll have to rethink 281 // the way reordering and deletion work (probably go by index). 282 if ($index === false) 283 { 284 $selection[] = $id; 285 } 231 286 } 232 287 aMediaTools::setSelection($selection); 288 $imageInfo = aMediaTools::getAttribute('imageInfo'); 289 // Make no attempt to scrub out a previous crop, which could be handy 290 $imageInfo[$id]['width'] = $item->getWidth(); 291 $imageInfo[$id]['height'] = $item->getHeight(); 292 aMediaTools::setAttribute('imageInfo', $imageInfo); 293 // If no previous crop info is set, we must set an intial cropping mask 294 // so that the cropped media item id gets linked instead of the original 295 // media item. This is a little dangerous because JavaScript computes an 296 // intial crop mask on the client side. 297 aMediaTools::setDefaultCropDimensions($item); 298 if ((!aMediaTools::isMultiple()) && aMediaTools::getAttribute('type') !== 'image') 299 { 300 return $this->redirect('aMedia/selected'); 301 } 233 302 return $this->renderComponent("aMedia", "multipleList"); 234 303 } … … 236 305 public function executeMultipleRemove(sfRequest $request) 237 306 { 238 $this->forward404Unless(aMediaTools::isMultiple());239 307 $id = $request->getParameter('id'); 240 308 $item = Doctrine::getTable("aMediaItem")->find($id); … … 250 318 } 251 319 320 public function executeUpdateMultiplePreview(sfRequest $request) 321 { 322 return $this->renderComponent('aMedia', 'multiplePreview'); 323 } 324 252 325 public function executeMultipleOrder(sfRequest $request) 253 326 { 254 327 $this->logMessage("*****MULTIPLE ORDER", "info"); 255 328 $order = $request->getParameter('a-media-selection-list-item'); 256 $oldSelection = aMediaTools::getSelection(); 329 $oldSelection = aMediaTools::getSelection(); 257 330 $keys = array_flip($oldSelection); 258 331 $selection = array(); … … 269 342 $this->logMessage(">>>KEEPING " . $item->getId(), "info"); 270 343 } 271 $this->logMessage(">>>SUCCEEDED: " . implode(", ", $selection), "info"); 344 $this->logMessage(">>>SUCCEEDED: " . implode(", ", $selection), "info"); 272 345 aMediaTools::setSelection($selection); 273 346 return $this->renderComponent("aMedia", "multipleList"); 274 347 } 348 275 349 public function executeSelected(sfRequest $request) 276 350 { 277 $controller = $this->getController();278 351 $this->forward404Unless(aMediaTools::isSelecting()); 279 if (aMediaTools::isMultiple()) 280 { 281 $selection = aMediaTools::getSelection(); 282 // Ooops best to get this before clearing it huh 283 $after = aMediaTools::getAfter(); 284 // Oops I forgot to call this in the multiple case 352 $selection = aMediaTools::getSelection(); 353 $imageInfo = aMediaTools::getAttribute('imageInfo'); 354 // Get all the items in preparation for possible cropping 355 if (count($selection)) 356 { 357 $items = Doctrine::getTable('aMediaItem')->createQuery('m')->whereIn('m.id', $selection)->execute(); 358 } 359 else 360 { 361 $items = array(); 362 } 363 $items = aArray::listToHashById($items); 364 $newSelection = array(); 365 foreach ($selection as $id) 366 { 367 if (isset($imageInfo[$id]['cropLeft'])) 368 { 369 // We need to make a crop 370 $item = $items[$id]; 371 $crop = $item->findOrCreateCrop($imageInfo[$id]); 372 $crop->save(); 373 $newSelection[] = $crop->id; 374 } 375 else 376 { 377 $newSelection[] = $id; 378 } 379 } 380 // Ooops best to get this before clearing it huh 381 $after = aMediaTools::getAfter(); 382 383 // addParamsNoDelete never attempts to eliminate a field just because 384 // its value is empty. This is how we distinguish between cancellation 385 // and selecting zero items 386 387 if (!aMediaTools::isMultiple()) 388 { 389 // Call this too soon and you lose isMultiple 285 390 aMediaTools::clearSelecting(); 286 // I thought about submitting this like a multiple select, 287 // but there's no clean way to implement that feature in 288 // addParam, and it wastes URL space anyway 289 // (remember the 1024-byte limit) 290 291 // addParamsNoDelete never attempts to eliminate a field just because 292 // its value is empty. This is how we distinguish between cancellation 293 // and selecting zero items 294 return $this->redirect( 295 aUrl::addParamsNoDelete($after, 296 array("aMediaIds" => implode(",", $selection)))); 297 } 298 // Single select 299 $id = $request->getParameter('id'); 300 $item = Doctrine::getTable("aMediaItem")->find($id); 301 $this->forward404Unless($item); 302 $after = aMediaTools::getAfter(); 303 $after = aUrl::addParams($after, 304 array("aMediaId" => $id)); 305 aMediaTools::clearSelecting(); 306 return $this->redirect($after); 391 if (count($newSelection)) 392 { 393 $after = aUrl::addParams($after, 394 array("aMediaId" => $newSelection[0])); 395 return $this->redirect($after); 396 } 397 else 398 { 399 $this->forward404(); 400 } 401 } 402 else 403 { 404 aMediaTools::clearSelecting(); 405 $url = aUrl::addParamsNoDelete($after, 406 array("aMediaIds" => implode(",", $newSelection))); 407 return $this->redirect($url); 408 } 307 409 } 308 410 -
plugins/apostrophePlugin/trunk/lib/action/BaseaMediaBackendActions.class.php
r1255 r1917 39 39 array_keys(aMediaItemTable::$mimeTypes))); 40 40 $this->forward404Unless(($resizeType !== 'c') || ($resizeType !== 's')); 41 $output = $this->getDirectory() . 42 DIRECTORY_SEPARATOR . "$slug.$width.$height.$resizeType.$format"; 41 // EDITED FOR ARBITRARY CROPPING 42 $cropLeft = $request->getParameter('cropLeft'); 43 $cropTop = $request->getParameter('cropTop'); 44 $cropWidth = $request->getParameter('cropWidth'); 45 $cropHeight = $request->getParameter('cropHeight'); 46 47 if (!is_null($cropWidth) && !is_null($cropHeight) && !is_null($cropLeft) && !is_null($cropTop)) 48 { 49 $cropLeft = ceil($cropLeft + 0); 50 $cropTop = ceil($cropTop + 0); 51 $cropWidth = ceil($cropWidth + 0); 52 $cropHeight = ceil($cropHeight + 0); 53 // Explicit cropping always preempts any automatic cropping, so there's no difference between c and s, 54 // and only the cropOriginal method actually supports cropping parameters, so 55 $resizeType = 'c'; 56 57 $output = $this->getDirectory() . 58 DIRECTORY_SEPARATOR . "$slug.$cropLeft.$cropTop.$cropWidth.$cropHeight.$width.$height.$resizeType.$format"; 59 } 60 else 61 { 62 $cropLeft = null; 63 $cropTop = null; 64 $cropWidth = null; 65 $cropHeight = null; 66 $output = $this->getDirectory() . 67 DIRECTORY_SEPARATOR . "$slug.$width.$height.$resizeType.$format"; 68 } 69 43 70 // If .htaccess has not been set up, or we are not running 44 71 // from the default front controller, then we may get here … … 57 84 $method = 'scaleToFit'; 58 85 } 59 $quality = sfConfig::get('app_aMedia_jpeg_quality', 75);60 86 aImageConverter::$method( 61 87 aMediaItemTable::getDirectory() . … … 65 91 $width, 66 92 $height, 67 sfConfig::get('app_aMedia_jpeg_quality', 75)); 93 sfConfig::get('app_aMedia_jpeg_quality', 75), 94 $cropLeft, 95 $cropTop, 96 $cropWidth, 97 $cropHeight); 68 98 } 69 99 // The FIRST time, we output this here. Later it -
plugins/apostrophePlugin/trunk/lib/action/BaseaMediaComponents.class.php
r448 r1917 110 110 } 111 111 112 public function executeSelectMultiple($request) 113 { 114 $this->items = aMediaTools::getSelectedItems(); 115 } 116 117 public function executeSelectSingle($request) 118 { 119 $this->items = aMediaTools::getSelectedItems(); 120 } 121 112 122 public function executeMultipleList($request) 113 123 { 114 if (!aMediaTools::isMultiple()) 115 { 116 throw new Exception("multiple list component, but multiple is off"); 117 } 118 $selection = aMediaTools::getSelection(); 119 if (!is_array($selection)) 120 { 121 throw new Exception("selection is not an array"); 122 } 123 // Work around the fact that whereIn doesn't evaluate to AND FALSE 124 // when the array is empty (it just does nothing; which is an 125 // interesting variation on MySQL giving you an ERROR when the 126 // list is empty, sigh) 127 if (count($selection)) 128 { 129 // Work around the unsorted results of whereIn. You can also 130 // do that with a FIELD function 131 $unsortedItems = Doctrine_Query::create()-> 132 from('aMediaItem i')-> 133 whereIn('i.id', $selection)-> 134 execute(); 135 $itemsById = array(); 136 foreach ($unsortedItems as $item) 137 { 138 $itemsById[$item->getId()] = $item; 139 } 140 $this->items = array(); 141 foreach ($selection as $id) 142 { 143 if (isset($itemsById[$id])) 144 { 145 $this->items[] = $itemsById[$id]; 146 } 147 } 148 } 149 else 150 { 151 $this->items = array(); 152 } 124 $this->items = aMediaTools::getSelectedItems(); 125 } 126 127 public function executeMultiplePreview() 128 { 129 $this->items = aMediaTools::getSelectedItems(); 153 130 } 154 131 } -
plugins/apostrophePlugin/trunk/lib/action/BaseaSlideshowSlotComponents.class.php
r1449 r1917 32 32 } 33 33 $this->itemIds = aArray::getIds($this->items); 34 foreach ($this->items as $item)35 {36 $this->itemIds[] = $item->id;37 }38 34 if ($this->getOption('random', false)) 39 35 { -
plugins/apostrophePlugin/trunk/lib/model/doctrine/PluginaMediaItem.class.php
r1701 r1917 20 20 } 21 21 // Let the culture be the user's culture 22 return aZendSearch::saveInDoctrineAndLucene($this, null, $conn); 22 $result = aZendSearch::saveInDoctrineAndLucene($this, null, $conn); 23 $crops = $this->getCrops(); 24 foreach ($crops as $crop) 25 { 26 $crop->setTitle($this->getTitle()); 27 $crop->setDescription($this->getDescription()); 28 $crop->setCredit($this->getCredit()); 29 $crop->save(); 30 } 31 return $result; 23 32 } 24 33 … … 33 42 $ret = aZendSearch::deleteFromDoctrineAndLucene($this, null, $conn); 34 43 $this->clearImageCache(); 44 45 $this->deleteCrops(); 46 35 47 // Don't even think about trashing the original until we know 36 48 // it's gone from the db and so forth … … 132 144 $path = $this->getOriginalPath($this->getFormat()); 133 145 $result = copy($file, $path); 146 // Crops are invalid if you replace the original image 147 $this->deleteCrops(); 134 148 return $result; 135 149 } … … 249 263 $options = aDimensions::constrain($this->getWidth(), $this->getHeight(), $this->getFormat(), $options); 250 264 251 return "aMediaBackend/image?" . http_build_query( 252 array("slug" => $this->slug, "width" => $options['width'], "height" => $options['height'], 253 "resizeType" => $options['resizeType'], "format" => $options['format'])); 265 $params = array("slug" => $this->slug, "width" => $options['width'], "height" => $options['height'], 266 "resizeType" => $options['resizeType'], "format" => $options['format']); 267 268 // check for null because 0 is valid 269 if (!is_null($options['cropLeft']) && !is_null($options['cropTop']) && !is_null($options['cropWidth']) && !is_null($options['cropHeight'])) 270 { 271 $params = array_merge( 272 $params, 273 array("cropLeft" => $options['cropLeft'], "cropTop" => $options['cropTop'], 274 "cropWidth" => $options['cropWidth'], "cropHeight" => $options['cropHeight']) 275 ); 276 } 277 return "aMediaBackend/image?" . http_build_query($params); 278 } 279 280 public function getCropThumbnailUrl() 281 { 282 $selectedConstraints = aMediaTools::getOption('selected_constraints'); 283 284 if ($aspectRatio = aMediaTools::getAspectRatio()) // this returns 0 if aspect-width and aspect-height were not set 285 { 286 $selectedConstraints = array_merge( 287 $selectedConstraints, 288 array('height' => floor($selectedConstraints['width'] / $aspectRatio)) 289 ); 290 } 291 292 293 $imageInfo = aMediaTools::getAttribute('imageInfo'); 294 if (isset($imageInfo[$this->id]['cropLeft']) && 295 isset($imageInfo[$this->id]['cropTop']) && isset($imageInfo[$this->id]['cropWidth']) && isset($imageInfo[$this->id]['cropHeight'])) 296 { 297 $selectedConstraints = array_merge( 298 $selectedConstraints, 299 array( 300 'cropLeft' => $imageInfo[$this->id]['cropLeft'], 301 'cropTop' => $imageInfo[$this->id]['cropTop'], 302 'cropWidth' => $imageInfo[$this->id]['cropWidth'], 303 'cropHeight' => $imageInfo[$this->id]['cropHeight'] 304 ) 305 ); 306 } 307 308 return $this->getScaledUrl($selectedConstraints); 309 } 310 311 // Crops of other images have periods in the slug. Real slugs are always [\w_]+ (well, the i18n equivalent) 312 public function isCrop() 313 { 314 return (strpos($this->slug, '.') !== false); 315 } 316 317 public function getCrops() 318 { 319 // This should perform well because there is an index on the slug and 320 // indexes are great with prefix queries 321 return $this->getTable()->createQuery('m')->where('m.slug LIKE ?', array($this->slug . '.%'))->execute(); 322 323 } 324 325 public function deleteCrops() 326 { 327 $crops = $this->getCrops(); 328 // Let's make darn sure the PHP stuff gets called rather than using a delete all trick of some sort 329 foreach ($crops as $crop) 330 { 331 $crop->delete(); 332 } 333 } 334 335 public function findOrCreateCrop($info) 336 { 337 $slug = $this->slug . '.' . $info['cropLeft'] . '.' . $info['cropTop'] . '.' . $info['cropWidth'] . '.' . $info['cropHeight']; 338 $crop = $this->getTable()->findOneBySlug($slug); 339 if (!$crop) 340 { 341 $crop = $this->copy(false); 342 $crop->slug = $slug; 343 $crop->width = $info['cropWidth']; 344 $crop->height = $info['cropHeight']; 345 } 346 return $crop; 347 } 348 349 public function getCroppingInfo() 350 { 351 $p = preg_split('/\./', $this->slug); 352 if (count($p) == 5) 353 { 354 return array('cropLeft' => $p[1], 'cropTop' => $p[2], 'cropWidth' => $p[3], 'cropHeight' => $p[4]); 355 } 356 else 357 { 358 return array(); 359 } 360 } 361 362 public function getCropOriginal() 363 { 364 if (!$this->isCrop()) 365 { 366 return $this; 367 } 368 $p = preg_split('/\./', $this->slug); 369 return $this->getTable()->findOneBySlug($p[0]); 254 370 } 255 371 } -
plugins/apostrophePlugin/trunk/lib/model/doctrine/PluginaMediaItemTable.class.php
r846 r1917 164 164 $query->andWhere('aMediaItem.height = ?', array($params['height'] + 0)); 165 165 } 166 // No crops in the browser please 167 $query->andWhere("aMediaItem.slug NOT LIKE '%.%'"); 168 166 169 return $query; 167 170 } -
plugins/apostrophePlugin/trunk/lib/toolkit/aDimensions.class.php
r9 r1917 24 24 } 25 25 $resizeType = $options['resizeType']; 26 $cropLeft = isset($options['cropLeft']) ? $options['cropLeft'] : null; 27 $cropTop = isset($options['cropTop']) ? $options['cropTop'] : null; 28 $cropWidth = isset($options['cropWidth']) ? $options['cropWidth'] : null; 29 $cropHeight = isset($options['cropHeight']) ? $options['cropHeight'] : null; 30 31 if (isset($options['scaleWidth']) && isset($options['scaleHeight']) && !is_null($cropLeft) && !is_null($cropTop) && !is_null($cropWidth) && !is_null($cropHeight)) 32 { 33 $scalingFactor = $originalWidth / $options['scaleWidth']; 34 35 $cropLeft = floor($scalingFactor * $cropLeft); 36 $cropTop = floor($scalingFactor * $cropTop); 37 $cropWidth = floor($scalingFactor * $cropWidth); 38 $cropHeight = floor($scalingFactor * $cropHeight); 39 } 40 26 41 if (!(isset($options['forceScale']) && $options['forceScale'])) 27 42 { … … 54 69 } 55 70 56 return array("width" => $width, "height" => $height, "format" => $format, "resizeType" => $resizeType); 71 return array("width" => $width, "height" => $height, "format" => $format, "resizeType" => $resizeType, 72 "cropLeft" => $cropLeft, "cropTop" => $cropTop, "cropWidth" => $cropWidth, "cropHeight" => $cropHeight); 57 73 } 58 74 } -
plugins/apostrophePlugin/trunk/lib/toolkit/aDoctrine.class.php
r268 r1917 18 18 // Example: 19 19 // 20 // $q = Doctrine::getTable('aMediaItem')->createQuery('m')->select('m.*' ->whereIn('m.id', $ids);20 // $q = Doctrine::getTable('aMediaItem')->createQuery('m')->select('m.*')->whereIn('m.id', $ids); 21 21 // $mediaItems = aDoctrine::orderByList($q, $ids)->execute(); 22 22 -
plugins/apostrophePlugin/trunk/lib/toolkit/aImageConverter.class.php
r1872 r1917 55 55 } 56 56 57 static public function cropOriginal($fileIn, $fileOut, $width, $height, $quality = 75) 58 { 57 // $width and $height are the dimensions of the final rendered image. $quality is the JPEG quality setting (where needed). 58 // The $crop parameters, when not null (all four must be null or not null), are used to crop the original before scaling/distorting 59 // to the specified width and height and are always in the original image's coordinates. 60 61 // If cropping coordinates are not specified, the largest possible portion of the center of the original image is scaled to fit into the 62 // destination image without distortion 63 64 static public function cropOriginal($fileIn, $fileOut, $width, $height, $quality = 75, $cropLeft = null, $cropTop = null, $cropWidth = null, $cropHeight = null) 65 { 66 // Allow skipping of parameters 67 if (is_null($quality)) 68 { 69 $quality = 75; 70 } 59 71 $width = ceil($width); 60 72 $height = ceil($height); … … 67 79 $iratio = $iwidth / $iheight; 68 80 $ratio = $width / $height; 81 82 // Spike's contribution: arbitrary cropping 83 if (!is_null($cropWidth) && !is_null($cropHeight) && !is_null($cropLeft) && !is_null($cropTop)) 84 { 85 $cropTop = ceil($cropTop + 0); 86 $cropLeft = ceil($cropLeft + 0); 87 $cropWidth = ceil($cropWidth + 0); 88 $cropHeight = ceil($cropHeight + 0); 89 90 $scale = array('xysize' => array($width + 0, $height + 0)); 91 $crop = array('left' => $cropLeft, 'top' => $cropTop, 'width' => $cropWidth, 'height' => $cropHeight); 92 return self::scaleBody($fileIn, $fileOut, $scale, $crop, $quality); 93 } 69 94 70 95 $scale = array('xysize' => array($width + 0, $height + 0)); … … 356 381 $width = $scaleParameters['xysize'][0]; 357 382 $height = $scaleParameters['xysize'][1]; 358 383 // This was backwards until 05/31/2010, making things bigger rather than smaller if their 384 // aspect ratios differed from the original. Be consistent with netpbm which makes things 385 // smaller not bigger 359 386 if (($width / $height) > ($swidth / $sheight)) 360 387 { 361 // Wider than the original. So it will be shorter than requested362 $ height = ceil($width * ($sheight / $swidth));388 // Wider than the original. So it will be narrower than requested 389 $width = ceil($height * ($swidth / $sheight)); 363 390 } 364 391 else 365 392 { 366 // Taller than the original. So it will be narrower than requested367 $ width = ceil($height * ($swidth / $sheight));393 // Taller than the original. So it will be shorter than requested 394 $height = ceil($width * ($sheight / $swidth)); 368 395 } 369 396 $out = self::createTrueColorAlpha($width, $height); -
plugins/apostrophePlugin/trunk/lib/toolkit/aImageConverterTest.php
r9 r1917 1 1 <?php 2 2 3 class sfConfig 4 { 5 static public function get($key, $default) 6 { 7 return $default; 8 } 9 } 3 10 require 'aImageConverter.class.php'; 4 11 5 12 // aImageConverter::scaleToFit("testin.jpg", "testoutscaletofit.jpg", 400, 300); 6 13 // aImageConverter::scaleByFactor("testin.jpg", "testoutscalebyfactor.jpg", 0.5); 7 aImageConverter::scaleToFit("testin.jpg", "testoutscaleoriginalbobbi.jpg", 340, 451);14 // aImageConverter::scaleToFit("testin.jpg", "testoutscaleoriginalbobbi.jpg", 340, 451); 8 15 // aImageConverter::cropOriginal("testin.jpg", "testoutcroporiginaltall.jpg", 100, 300); 9 16 // aImageConverter::scaleToNarrowerAxis("testin.jpg", "testoutscaletonarroweraxis.jpg", 300, 200); 17 // aImageConverter::cropOriginal("testin.jpg", "testoutcroporiginaltall.jpg", 100, 300); 18 aImageConverter::cropOriginal("testin.jpg", "testoutcroporiginalcorner.jpg", 100, 100, null, 200, 200, 200, 200); -
plugins/apostrophePlugin/trunk/lib/toolkit/aMediaAPI.php
r9 r1917 1 1 <?php 2 2 3 // Conveniences for Symfony code that uses the API. 3 // DEPRECATED: based on the old REST API, which we do not enable by default and found 4 // to be a serious maintenance hassle as our client projects simply don't call for 5 // shared media repositories. 6 7 // Conveniences for Symfony code that uses the REST API. 4 8 5 9 class aMediaAPI -
plugins/apostrophePlugin/trunk/lib/toolkit/aMediaRouting.php
r883 r1917 26 26 'action' => 'original' 27 27 ), array('slug' => '^' . aTools::getSlugRegexpFragment() . '$', 'format' => '^(jpg|png|gif|pdf)$'))); 28 28 29 29 $route = new sfRoute('/uploads/media_items/:slug.:width.:height.:resizeType.:format', array( 30 30 'module' => 'aMediaBackend', … … 38 38 )); 39 39 $r->prependRoute('a_media_image', $route); 40 41 $route = new sfRoute('/uploads/media_items/:slug.:cropLeft.:cropTop.:cropWidth.:cropHeight.:width.:height.:resizeType.:format', array( 42 'module' => 'aMediaBackend', 43 'action' => 'image' 44 ), array( 45 'slug' => '^' . aTools::getSlugRegexpFragment() . '$', 46 'width' => '^\d+$', 47 'height' => '^\d+$', 48 'cropLeft' => '^\d+$', 49 'cropTop' => '^\d+$', 50 'cropWidth' => '^\d+$', 51 'cropHeight' => '^\d+$', 52 'resizeType' => '^\w$', 53 'format' => '^(jpg|png|gif)$' 54 )); 55 $r->prependRoute('a_media_image_cropped', $route); 40 56 41 57 // What we want: -
plugins/apostrophePlugin/trunk/lib/toolkit/aMediaTools.php
r883 r1917 3 3 class aMediaTools 4 4 { 5 // These are used internally. If you want to select something 6 // with the media module please see the README, do not use these 7 // methods directly 5 // These are used internally. See aMediaSelect for the methods you probably want 8 6 9 7 static public function setSelecting($after, $multiple, $selection, 10 8 $options = array()) 11 9 { 10 $items = aMediaItemTable::retrieveByIds($selection); 11 $ids = array(); 12 $imageInfo = array(); 13 $selection = array(); 14 foreach ($items as $item) 15 { 16 $croppingInfo = array(); 17 if ($item->isCrop()) 18 { 19 $croppingInfo = $item->getCroppingInfo(); 20 $item = $item->getCropOriginal(); 21 } 22 $id = $item->id; 23 $selection[] = $id; 24 $info = array('width' => $item->width, 'height' => $item->height); 25 $info = array_merge($info, $croppingInfo); 26 $imageInfo[$item->id] = $info; 27 } 28 29 $cropping = isset($options['cropping']) && $options['cropping']; 30 12 31 self::clearSelecting(); 13 32 self::setAttribute("selecting", true); 14 33 self::setAttribute("after", $after); 15 34 self::setAttribute("multiple", $multiple); 35 self::setAttribute("cropping", $cropping); 16 36 self::setAttribute("selection", $selection); 37 self::setAttribute("imageInfo", $imageInfo); 17 38 foreach ($options as $key => $val) 18 39 { … … 140 161 "selected_constraints" => array( 141 162 "width" => 100, 142 "height" => 75,143 "resizeType" => "c" ),163 "height" => false, 164 "resizeType" => "c",), 144 165 "show_constraints" => array( 145 166 "width" => 720, 146 167 "height" => false, 168 "resizeType" => "s"), 169 "crop_constraints" => array( 170 "width" => 679, 171 "height" => 400, 147 172 "resizeType" => "s"), 148 173 'routes_register' => true, … … 188 213 return $item; 189 214 } 215 216 // refactored this into this static method from executeMultipleList() because it is now needed 217 // for executeUpdateMultiplePreview() for cropping slideshow items 218 static public function getSelectedItems() 219 { 220 $selection = self::getSelection(); 221 if (!is_array($selection)) 222 { 223 throw new Exception("selection is not an array"); 224 } 225 // Work around the fact that whereIn doesn't evaluate to AND FALSE 226 // when the array is empty (it just does nothing; which is an 227 // interesting variation on MySQL giving you an ERROR when the 228 // list is empty, sigh) 229 if (count($selection)) 230 { 231 // Work around the unsorted results of whereIn. You can also 232 // do that with a FIELD function 233 $unsortedItems = Doctrine_Query::create()-> 234 from('aMediaItem i')-> 235 whereIn('i.id', $selection)-> 236 execute(); 237 $itemsById = array(); 238 foreach ($unsortedItems as $item) 239 { 240 $itemsById[$item->getId()] = $item; 241 } 242 $items = array(); 243 foreach ($selection as $id) 244 { 245 if (isset($itemsById[$id])) 246 { 247 $items[] = $itemsById[$id]; 248 } 249 } 250 } 251 else 252 { 253 $items = array(); 254 } 255 256 return $items; 257 } 258 259 static public function getAspectRatio() 260 { 261 if (self::getAttribute('aspect-width') && self::getAttribute('aspect-width')) 262 { 263 return self::getAttribute('aspect-width') / self::getAttribute('aspect-height'); 264 } 265 return 0; 266 } 267 268 static public function getSelectedThumbnailHeight() 269 { 270 $selectedConstraints = self::getOption('selected_constraints'); 271 if (false === $selectedConstraints['height']) 272 { 273 if ($aspectRatio = self::getAspectRatio()) 274 { 275 return $selectedConstraints['width'] / $aspectRatio; 276 } 277 return 0; // Let's not divide by zero. 278 } 279 return $selectedConstraints['height']; 280 } 281 282 /** 283 * This mirrors the default size math in aCrop.setAspectMask() in aCrop.js 284 */ 285 static public function setDefaultCropDimensions($mediaItem) 286 { 287 $imageInfo = self::getAttribute('imageInfo'); 288 $aspectRatio = self::getAspectRatio(); 289 290 if ($aspectRatio) 291 { 292 if ($aspectRatio > 1) 293 { 294 $imageInfo[$mediaItem->id]['cropWidth'] = $mediaItem->getWidth(); 295 $imageInfo[$mediaItem->id]['cropHeight'] = floor($mediaItem->getWidth() / $aspectRatio); 296 } 297 else 298 { 299 $imageInfo[$mediaItem->id]['cropHeight'] = $mediaItem->getHeight(); 300 $imageInfo[$mediaItem->id]['cropWidth'] = floor($mediaItem->getHeight() * $aspectRatio); 301 } 302 } 303 else 304 { 305 $imageInfo[$mediaItem->id]['cropWidth'] = $mediaItem->getWidth(); 306 $imageInfo[$mediaItem->id]['cropHeight'] = $mediaItem->getHeight(); 307 } 308 309 $imageInfo[$mediaItem->id]['cropLeft'] = 0; 310 $imageInfo[$mediaItem->id]['cropTop'] = floor(($mediaItem->getHeight() - $imageInfo[$mediaItem->id]['cropHeight']) / 2); 311 312 self::setAttribute('imageInfo', $imageInfo); 313 } 190 314 } -
plugins/apostrophePlugin/trunk/modules/aImageSlot/templates/_normalView.php
r1914 r1917 16 16 $slug = isset($slug) ? $sf_data->getRaw('slug') : null; 17 17 $title = isset($title) ? $sf_data->getRaw('title') : null; 18 $embed = isset($embed) ? $sf_data->getRaw('embed') : null; 18 19 ?> 19 20 <?php use_helper('I18N') ?> -
plugins/apostrophePlugin/trunk/modules/aMedia/templates/_browser.php
r1914 r1917 11 11 ?> 12 12 <?php use_helper('I18N') ?> 13 <?php // Media is now an engine, so there's a page ?> 14 <?php $page = aTools::getCurrentPage() ?> 13 15 14 16 <?php // Entire media browser goes into what would otherwise be the regular apostrophe subnav ?> 15 17 <?php slot('a-subnav') ?> 16 17 <?php // Media is now an engine, so there's a page ?>18 <?php $page = aTools::getCurrentPage() ?>19 18 20 19 <?php // For backwards compatibility reasons it is best to implement these as before and after partials ?> -
plugins/apostrophePlugin/trunk/modules/aMedia/templates/_describeConstraints.php
r1655 r1917 1 1 <?php // Yes, this is template code, but we use regular PHP syntax because we are building a sentence and the introduction of ?> 2 <?php // newlines wrecks the punctuation. ?> 3 <?php 4 use_helper('I18N'); 5 $clauses = array(); 6 if (aMediaTools::getAttribute('aspect-width') && aMediaTools::getAttribute('aspect-height')) 7 { 8 $clauses[] = __('A %w%x%h% aspect ratio', array('%w%' => aMediaTools::getAttribute('aspect-width'), '%h%' => aMediaTools::getAttribute('aspect-height')), 'apostrophe'); 9 } 10 if (aMediaTools::getAttribute('minimum-width')) 11 { 12 $clauses[] = __('A minimum width of %mw% pixels', array('%mw%' => aMediaTools::getAttribute('minimum-width')), 'apostrophe'); 13 } 14 if (aMediaTools::getAttribute('minimum-height')) 15 { 16 $clauses[] = __('A minimum height of %mh% pixels', array('%mh%' => aMediaTools::getAttribute('minimum-height')), 'apostrophe'); 17 } 18 if (aMediaTools::getAttribute('width')) 19 { 20 $clauses[] = __('A width of exactly %w% pixels', array('%w%' => aMediaTools::getAttribute('width')), 'apostrophe'); 21 } 22 if (aMediaTools::getAttribute('height')) 23 { 24 $clauses[] = __('A height of exactly %h% pixels', array('%h%' => aMediaTools::getAttribute('height')), 'apostrophe'); 25 } 26 if (aMediaTools::getAttribute('type')) 27 { 28 // Internationalize the plural so that can be correct too 29 $type = __(aMediaTools::getAttribute('type') . "s", null, 'apostrophe'); 30 } 31 else 32 { 33 $type = __("items", null, 'apostrophe'); 34 } 35 if (count($clauses)) 36 { 37 // Markup change: for I18N it's better to use a list here rather than 38 // trying to create a sentence with commas and 'and' 39 echo('<h3 class="a-constraints-description">' . __("Displaying only %t% with:", array('%t%' => $type), 'apostrophe') . '</h3>'); 40 echo('<ul class="a-constraints">'); 41 foreach ($clauses as $clause) 2 <?php // newlines wrecks the punctuation. (OK, we're building a ul list now...) ?> 3 <?php use_helper('I18N') ?> 4 <?php // Images support cropping, which makes some of the constraints unnecessary to display ?> 5 <?php // With other media types we must find an item that satisfies all of them. ?> 6 <?php if (aMediaTools::getAttribute('type') === 'image'): ?> 7 <?php // We went with something simpler when cropping is present ?> 8 <?php if ($limitSizes): ?> 9 <h4 class="a-help"><?php echo __('Some images in your media library may not be large enough to be selected. Only images that can be used are displayed below.', null, 'apostrophe') ?></h4> 10 <?php endif ?> 11 <?php else: ?> 12 <?php // No cropping, their only hope is to get proper details from us on what is allowed ?> 13 <?php 14 $clauses = array(); 15 if (aMediaTools::getAttribute('aspect-width') && aMediaTools::getAttribute('aspect-height')) 42 16 { 43 echo('<li>' . $clause . '</li>');17 $clauses[] = __('A %w%x%h% aspect ratio', array('%w%' => aMediaTools::getAttribute('aspect-width'), '%h%' => aMediaTools::getAttribute('aspect-height')), 'apostrophe'); 44 18 } 45 echo('</ul>'); 46 } 19 if (aMediaTools::getAttribute('minimum-width')) 20 { 21 $clauses[] = __('A minimum width of %mw% pixels', array('%mw%' => aMediaTools::getAttribute('minimum-width')), 'apostrophe'); 22 } 23 if (aMediaTools::getAttribute('minimum-height')) 24 { 25 $clauses[] = __('A minimum height of %mh% pixels', array('%mh%' => aMediaTools::getAttribute('minimum-height')), 'apostrophe'); 26 } 27 if (aMediaTools::getAttribute('width')) 28 { 29 $clauses[] = __('A width of exactly %w% pixels', array('%w%' => aMediaTools::getAttribute('width')), 'apostrophe'); 30 } 31 if (aMediaTools::getAttribute('height')) 32 { 33 $clauses[] = __('A height of exactly %h% pixels', array('%h%' => aMediaTools::getAttribute('height')), 'apostrophe'); 34 } 35 if (aMediaTools::getAttribute('type')) 36 { 37 // Internationalize the plural so that can be correct too 38 $type = __(aMediaTools::getAttribute('type') . "s", null, 'apostrophe'); 39 } 40 else 41 { 42 $type = __("items", null, 'apostrophe'); 43 } 44 if (count($clauses)) 45 { 46 // Markup change: for I18N it's better to use a list here rather than 47 // trying to create a sentence with commas and 'and' 48 echo('<h4 class="a-constraints-description">' . __("Displaying only %t% with:", array('%t%' => $type), 'apostrophe') . '</h4>'); 49 echo('<ul class="a-constraints">'); 50 foreach ($clauses as $clause) 51 { 52 echo('<li>' . $clause . '</li>'); 53 } 54 echo('</ul>'); 55 } 56 ?> 57 <?php endif ?> -
plugins/apostrophePlugin/trunk/modules/aMedia/templates/_mediaItem.php
r1914 r1917 11 11 <?php if (aMediaTools::isSelecting()): ?> 12 12 13 <?php if (aMediaTools::isMultiple() ): ?>13 <?php if (aMediaTools::isMultiple() || ($type === 'image')): ?> 14 14 <?php $linkAttributes = 'href = "#" onClick="'. 15 15 jq_remote_function(array( 16 "update" => "a-media-selection-list",17 'complete' => "aUI('a-media-selection-list');",16 "update" => "a-media-selection-list", 17 'complete' => "aUI('a-media-selection-list'); aMediaUpdatePreview();", 18 18 "url" => "aMedia/multipleAdd?id=$id")).'; return false;"' ?> 19 <?php else: ?> 20 <?php $linkAttributes = 'href = "' . url_for("aMedia/selected?id=$id") . '"' ?> 21 <?php endif ?> 19 <?php else: ?> 20 <?php // Non-image single select. The multiple add action is a bit of a misnomer here ?> 21 <?php // and redirects to aMedia/selected after adding the media item ?> 22 <?php $linkAttributes = 'href = "' . url_for("aMedia/multipleAdd?id=$id") . '"' ?> 23 <?php endif ?> 22 24 23 25 <?php else: ?> -
plugins/apostrophePlugin/trunk/modules/aMedia/templates/_multipleList.php
r1914 r1917 5 5 <?php use_helper('I18N', 'jQuery') ?> 6 6 7 <?php $ids = array() ?>8 9 7 <?php foreach ($items as $item): ?> 10 8 <li id="a-media-selection-list-item-<?php echo $item->getId() ?>" class="a-media-selection-list-item"> 11 9 <?php $id = $item->getId() ?> 12 10 <ul class="a-controls a-media-multiple-list-controls"> 11 <li> 12 <a href="#crop" onclick="return false;" class="a-btn icon a-crop no-label" title="<?php echo __('Crop', null, 'apostrophe') ?>"><?php echo __('Crop', null, 'apostrophe') ?></a> 13 </li> 13 14 <li><?php echo jq_link_to_remote(__("remove this item", null, 'apostrophe'), 14 15 array( 15 16 'url' => 'aMedia/multipleRemove?id='.$id, 16 17 'update' => 'a-media-selection-list', 17 'complete' => 'aUI("a-media-selection-list"); aMediaDeselectItem('.$id.') ',18 'complete' => 'aUI("a-media-selection-list"); aMediaDeselectItem('.$id.'); aMediaUpdatePreview()', 18 19 ), array( 19 20 'class'=> 'a-btn icon a-delete no-label', … … 22 23 </ul> 23 24 24 <div class="a-media-selected-item-drag-overlay" title="<?php echo __('Drag & Drop to Order', null, 'apostrophe') ?>"></div> 25 <?php if (aMediaTools::isMultiple()): ?> 26 <div class="a-media-selected-item-drag-overlay" title="<?php echo __('Drag & Drop to Order', null, 'apostrophe') ?>"></div> 27 <?php endif ?> 25 28 <div class="a-media-selected-item-overlay"></div> 26 <img src="<?php echo url_for($item->getScaledUrl(aMediaTools::getOption('selected_constraints'))) ?>" /> 27 28 <?php $ids[] = $item->getId() ?> 29 29 <img src="<?php echo url_for($item->getCropThumbnailUrl()) ?>" class="a-thumbnail" /> 30 30 </li> 31 31 <?php endforeach ?> … … 33 33 <script type="text/javascript" charset="utf-8"> 34 34 35 function aMediaItemsIndicateSelected( ids)35 function aMediaItemsIndicateSelected(cropOptions) 36 36 { 37 $('.a-media-selected-overlay').remove(); 37 var ids = cropOptions.ids; 38 aCrop.init(cropOptions); 39 $('.a-media-selected-overlay').remove(); 40 $('.a-media-selected').removeClass('a-media-selected'); 38 41 39 42 var i; … … 47 50 } 48 51 } 49 52 50 53 $('.a-media-item.a-media-selected').each(function(){ 51 54 $(this).children('.a-media-item-thumbnail').prepend('<div class="a-media-selected-overlay"></div>'); 52 55 }); 56 57 $('#a-media-selection-list-caption').hide(); 58 if (!ids.length) { 59 $('#a-media-selection-list-caption').show(); 60 } 53 61 54 62 $('.a-media-selected-overlay').fadeTo(0, 0.66); 63 } 64 65 function aMediaUpdatePreview() 66 { 67 $('#a-media-selection-preview').load('<?php echo url_for('aMedia/updateMultiplePreview') ?>', function(){ 68 // the preview images are by default set to display:none 69 $('#a-media-selection-preview li:first').addClass('current'); 70 // set up cropping again; do hard reset to reinstantiate Jcrop 71 aCrop.resetCrop(true); 72 }); 55 73 } 56 74 … … 66 84 67 85 $(document).ready(function() { // On page ready indicate selected items 68 aMediaItemsIndicateSelected(<?php echo json_encode($ids) ?>) 86 var cropOptions = { 87 ids: <?php echo json_encode(aMediaTools::getSelection()) ?>, 88 aspectRatio: <?php echo aMediaTools::getAspectRatio() ?>, 89 minimumSize: [<?php echo aMediaTools::getAttribute('minimum-width') ?>, <?php echo aMediaTools::getAttribute('minimum-height') ?>], 90 maximumSize: [<?php echo aMediaTools::getAttribute('maximum-width') ?>, <?php echo aMediaTools::getAttribute('maximum-height') ?>], 91 <?php // width height cropLeft cropTop cropWidth cropHeight hashed by image id ?> 92 imageInfo: <?php echo json_encode(aMediaTools::getAttribute('imageInfo')) ?> 93 }; 94 95 aMediaItemsIndicateSelected(cropOptions); 96 69 97 $('.a-media-selected-item-overlay').fadeTo(0,.35); //cross-browser opacity for overlay 70 98 $('.a-media-selection-list-item').hover(function(){ -
plugins/apostrophePlugin/trunk/modules/aMedia/templates/_multiplePreview.php
r1909 r1917 1 <?php // Make sure we're compatible with sf_escaping_strategy: true ?> 2 <?php $items = $sf_data->getRaw('items') ?> 1 3 <?php foreach ($items as $item): ?> 2 4 <li id="a-media-selection-preview-<?php echo $item->getId() ?>" class="a-media-selection-preview-item"> -
plugins/apostrophePlugin/trunk/modules/aMedia/templates/_selectMultiple.php
r1914 r1917 2 2 // Compatible with sf_escaping_strategy: true 3 3 $limitSizes = isset($limitSizes) ? $sf_data->getRaw('limitSizes') : null; 4 $items = $sf_data->getRaw('items') ? $sf_data->getRaw('items') : null; 4 5 ?> 6 <?php // Known as selectMultiple for historic reasons, but we use it for both single and multiple select now that ?> 7 <?php // we have a need for cropping which requires a pause in both cases anyway. ?> 5 8 <?php use_helper('I18N') ?> 9 <?php use_javascript("/apostrophePlugin/js/plugins/jquery.jCrop.min.js") ?> 10 <?php use_javascript("/apostrophePlugin/js/aCrop.js") ?> 11 <?php use_stylesheet("/apostrophePlugin/css/Jcrop/jquery.Jcrop.css") ?> 6 12 <div class="a-media-select"> 7 13 <?php $type = aMediaTools::getAttribute('type') ?> … … 9 15 <?php $type = "media item" ?> 10 16 <?php endif ?> 11 <p><?php echo __('Select one or more %typeplural% by clicking on them below. Drag and drop %typeplural% to reorder them within the list of selected items. Remove %typeplural% by clicking on the trashcan.', array('%typeplural%' => __($type . 's')), 'apostrophe') ?> 12 <?php if ($limitSizes): ?> 13 <?php echo __('Only appropriately sized %typeplural% are shown.', array('%typeplural%' => __($type . 's')), 'apostrophe') ?> 14 <?php endif ?> 15 <?php echo __('When you\'re done, click "Save."', null, 'apostrophe') ?></p> 17 <h3><?php echo $label ?></h3> 16 18 17 <ul id="a-media-selection-list"> 18 <?php include_component("aMedia", "multipleList") ?> 19 <div id="a-media-selection-list-caption"> 20 <h4><?php echo __("Preview your selected image%plural% here.", array('%plural%' => aMediaTools::isMultiple() ? 's':' '), 'apostrophe') ?></h4> 21 </div> 22 <div id="a-media-selection-wrapper"> 23 <ul id="a-media-selection-list" style="min-height:<?php echo ($thumbHeight = aMediaTools::getSelectedThumbnailHeight()) ? $thumbHeight + 10 : 85 ?>px;"> 24 <?php if($items): ?> 25 <?php include_partial("aMedia/multipleList", array("items" => $items)) ?> 26 <?php else: ?> 27 <?php if (aMediaTools::isMultiple()): ?> 28 <li class="a-media-selection-placeholder"><?php echo __('Add images to your slideshow', null, 'apostrophe') ?></li> 29 <?php else: ?> 30 <li class="a-media-selection-placeholder"><?php echo __('Select an image', null, 'apostrophe') ?></li> 31 <?php endif ?> 32 <?php endif ?> 33 </ul> 34 35 <?php echo jq_sortable_element("#a-media-selection-list", array("url" => "aMedia/multipleOrder")) ?> 36 <br class="c"/> 37 38 <div class="a-crop-workspace"> 39 <ul id="a-media-selection-preview"> 40 <?php include_partial("aMedia/multiplePreview", array("items" => $items)) ?> 41 </ul> 42 <ul class="a-controls a-media-crop-controls"> 43 <li><?php echo jq_link_to_function(__("Crop", null, 'apostrophe'), "aCrop.setCrop('".url_for('aMedia/crop')."')", array("class"=>"a-btn save")) ?></li> 44 <li><?php echo jq_link_to_function(__("Cancel", null, 'apostrophe'), "aCrop.resetCrop()", array("class"=>"a-btn icon a-cancel event-default")) ?></li> 45 </ul> 46 </div> 47 </div> 48 <ul class="a-controls a-media-slideshow-controls"> 49 <li><?php echo link_to(aMediaTools::isMultiple() ? __("Save Slideshow", null, 'apostrophe') : __("Save Selection", null, 'apostrophe'), "aMedia/selected", array("class"=>"a-btn save big")) ?></li> 50 <li><?php echo link_to(__("Cancel", null, 'apostrophe'), "aMedia/selectCancel", array("class"=>"a-btn icon a-cancel big")) ?></li> 19 51 </ul> 20 21 <?php echo jq_sortable_element("#a-media-selection-list", array("url" => "aMedia/multipleOrder")) ?>22 23 <br class="c"/>24 25 <ul class="a-controls a-media-slideshow-controls">26 <li><?php echo link_to(__("Save", null, 'apostrophe'), "aMedia/selected", array("class"=>"a-btn save")) ?></li>27 <li><?php echo link_to(__("Cancel", null, 'apostrophe'), "aMedia/selectCancel", array("class"=>"a-btn icon a-cancel")) ?></li>28 </ul>29 30 52 </div> 31 <br class="c"/> 53 </div> 54 <br class="c"/> -
plugins/apostrophePlugin/trunk/modules/aMedia/templates/_selectSingle.php
r1914 r1917 17 17 <?php endif ?> 18 18 </p> 19 <?php 20 //removing this cancel link for now, it exists above in the header 21 // echo link_to("cancel", "aMedia/selectCancel", array("class"=>"a-cancel")) 22 ?> 19 <ul class="a-controls"> 20 <li><?php echo link_to("cancel", "aMedia/selectCancel", array("class"=>"a-cancel")) ?></li> 21 </ul> 23 22 </div> -
plugins/apostrophePlugin/trunk/modules/aMedia/templates/indexSuccess.php
r1914 r1917 7 7 $results = isset($results) ? $sf_data->getRaw('results') : null; 8 8 ?> 9 <?php use_helper('I18N' ) ?>9 <?php use_helper('I18N','jQuery') ?> 10 10 <?php slot('body_class') ?>a-media<?php end_slot() ?> 11 12 <?php use_helper('jQuery') ?>11 <?php $type = aMediaTools::getAttribute('type') ?> 12 <?php $selecting = aMediaTools::isSelecting() ?> 13 13 14 14 <div id="a-media-plugin"> … … 20 20 <?php if (aMediaTools::isSelecting()): ?> 21 21 22 <?php if (isset($label)): ?> 23 <h3><?php echo htmlspecialchars($label) ?> or <?php echo link_to(__("Cancel", null, 'apostrophe'), "aMedia/selectCancel", array("class"=>"a-btn a-cancel text-only")) ?></h3> 22 <?php if (($type === 'image') || (aMediaTools::isMultiple())): ?> 23 <?php include_component('aMedia', 'selectMultiple', array('limitSizes' => $limitSizes, 'label' => (isset($label)?$label:null))) ?> 24 <?php else: ?> 25 <?php include_component('aMedia', 'selectSingle', array('limitSizes' => $limitSizes, 'label' => (isset($label)?$label:null))) ?> 24 26 <?php endif ?> 25 26 <?php include_partial('aMedia/describeConstraints') ?>27 28 <?php if (aMediaTools::isMultiple()): ?>29 <?php include_partial('aMedia/selectMultiple', array('limitSizes' => $limitSizes)) ?>30 <?php else: ?>31 <?php include_partial('aMedia/selectSingle', array('limitSizes' => $limitSizes)) ?>32 <?php endif ?>33 34 27 <?php endif ?> 35 28 36 <?php if (aMediaTools::userHasUploadPrivilege()): ?>37 38 <ul class="a-controls a-media-controls">39 <?php $selecting = aMediaTools::isSelecting() ?>40 <?php $type = aMediaTools::getAttribute('type') ?>41 42 <?php if (!($selecting && $type && ($type !== 'image'))): ?>43 <li><a href="<?php echo url_for("aMedia/uploadImages") ?>" class="a-btn icon a-add"><?php echo __('Add Images', null, 'apostrophe') ?></a></li>44 <?php endif ?>45 46 <?php if (!($selecting && $type && ($type !== 'video'))): ?>47 <li><a href="<?php echo url_for("aMedia/newVideo") ?>" class="a-btn icon a-add"><?php echo __('Add Video', null, 'apostrophe') ?></a></li>48 <?php endif ?>49 50 <?php if (!($selecting && $type && ($type !== 'pdf'))): ?>51 <li><a href="<?php echo url_for("aMedia/editPdf") ?>" class="a-btn icon a-add"><?php echo __('Add PDF', null, 'apostrophe') ?></a></li>52 <?php endif ?>53 54 </ul>55 56 <?php endif ?>57 29 </div> 58 30 … … 60 32 61 33 <div class="a-media-library"> 34 35 <h3>Media Library</h3> 36 37 <?php include_partial('aMedia/describeConstraints', array('limitSizes' => $limitSizes)) ?> 38 39 <?php if (aMediaTools::userHasUploadPrivilege()): ?> 40 <ul class="a-controls a-media-controls"> 41 42 <?php if (!($selecting && $type && ($type !== 'image'))): ?> 43 <li><a href="<?php echo url_for("aMedia/uploadImages") ?>" class="a-btn icon big a-add"><?php echo __('Add Images', null, 'apostrophe') ?></a></li> 44 <?php endif ?> 45 46 <?php if (!($selecting && $type && ($type !== 'video'))): ?> 47 <li><a href="<?php echo url_for("aMedia/newVideo") ?>" class="a-btn icon big a-add"><?php echo __('Add Video', null, 'apostrophe') ?></a></li> 48 <?php endif ?> 49 50 <?php if (!($selecting && $type && ($type !== 'pdf'))): ?> 51 <li><a href="<?php echo url_for("aMedia/editPdf") ?>" class="a-btn icon big a-add"><?php echo __('Add PDF', null, 'apostrophe') ?></a></li> 52 <?php endif ?> 53 </ul> 54 <?php endif ?> 55 62 56 <?php for ($n = 0; ($n < count($results)); $n += 2): ?> 63 57 <div class="a-media-row"> -
plugins/apostrophePlugin/trunk/modules/aSlideshowSlot/templates/_normalView.php
r1914 r1917 33 33 "aMediaIds" => implode(",", $itemIds), 34 34 "type" => "image", 35 "label" => __(" Create a Slideshow", null, 'apostrophe'),35 "label" => __("You are creating a slideshow of images.", null, 'apostrophe'), 36 36 "after" => url_for("aSlideshowSlot/edit") . "?" . 37 37 http_build_query( -
plugins/apostrophePlugin/trunk/modules/aVideoSlot/templates/_normalView.php
r1914 r1917 14 14 $slug = isset($slug) ? $sf_data->getRaw('slug') : null; 15 15 $title = isset($title) ? $sf_data->getRaw('title') : null; 16 $embed = isset($embed) ? $sf_data->getRaw('embed') : null; 16 17 ?> 17 18 <?php use_helper('I18N') ?> -
plugins/apostrophePlugin/trunk/web/css/a.css
- Property svn:mergeinfo changed
r1879 r1917 721 721 { 722 722 padding: 0 !important; 723 } 724 725 .icon.a-crop 726 { 727 background-image: url(/apostrophePlugin/images/a-icon-crop.png); 723 728 } 724 729 … … 3725 3730 width: 720px; 3726 3731 float: right; 3727 margin-bottom: 20px; 3732 /*margin-bottom: 20px;*/ 3728 3733 /*overflow: hidden;*/ 3729 3734 } … … 3731 3736 .a-media-toolbar 3732 3737 { 3733 padding-bottom: 20px;3734 b order-bottom: 1px solid #ddd;3738 padding-bottom: 15px; 3739 background:url("/apostropheBlogPlugin/images/a-blog-td-bg.png") repeat-x scroll 0 bottom transparent; 3735 3740 } 3736 3741 … … 3742 3747 } 3743 3748 3744 .a-media-toolbar .a-media-controls,3745 3749 .a-media-toolbar .a-media-slideshow-controls 3746 3750 { 3747 3751 clear: both; 3748 3752 } 3753 3754 .a-media-library .a-controls.a-media-controls 3755 { 3756 clear:both; 3757 float:left; 3758 display:inline; 3759 margin:15px 0 30px 0!important; 3760 } 3761 3762 .a-media-library .a-controls.a-media-controls li 3763 { 3764 margin:0 !important; 3765 } 3766 3767 3749 3768 3750 3769 .a-media-toolbar h3 … … 3753 3772 /*float: left;*/ 3754 3773 margin: 0 0 10px 0; 3774 color:#333; 3755 3775 } 3756 3776 … … 3826 3846 } 3827 3847 3828 .a-media-item.even3829 {3830 /*margin-right: 20px;*/3831 }3832 3833 3848 .a-media-item-title h3 a 3834 3849 { … … 3846 3861 { 3847 3862 margin-bottom: 10px; 3848 float: left;3849 display: inline;3850 3863 padding-bottom:10px; 3864 padding: 10px; 3865 margin: 0 0 20px -1px; 3866 background-color: #efefef; 3867 -moz-border-radius: 4px; 3868 -webkit-border-radius: 4px; 3869 border-radius: 4px; 3870 border: 1px solid #ccc; 3871 overflow: auto; 3872 } 3873 3874 #a-media-selection-wrapper 3875 { 3876 display: inline; 3877 position: relative; 3878 float: left; 3879 width:680px; 3880 padding:10px; 3881 margin-bottom: 20px; 3882 background-color: #222; 3883 -moz-border-radius: 4px; 3884 -webkit-border-radius: 4px; 3885 border-radius: 4px; 3886 box-shadow:inset 0 0 10px #000000; 3887 -moz-box-shadow:inset 0 0 10px #000000; 3888 -webkit-box-shadow:inset 0 0 10px #000000; 3851 3889 } 3852 3890 3853 3891 #a-media-selection-list 3854 3892 { 3855 float: left; 3856 margin: 10px 0; 3893 display: block; 3894 overflow: hidden; 3895 position: relative; 3896 width:690px; 3897 left:-10px; 3898 /*border: 1px dashed #999;*/ 3899 -moz-border-radius: 4px; 3900 -webkit-border-radius: 4px; 3901 border-radius: 4px; 3902 /*background-color: #e6e6e6;*/ 3903 } 3904 3905 .a-media-selection-placeholder 3906 { 3907 margin-left: 10px; 3908 float: left; 3909 width: 80px; 3910 height: 50px; 3911 border: 2px dashed #ddd; 3912 padding: 10px; 3913 color: #fff; 3857 3914 } 3858 3915 … … 3860 3917 { 3861 3918 float: left; 3862 margin: 0 16px 16px 0;3919 margin: 5px 0px 5px 10px; 3863 3920 cursor: move; 3864 3921 position: relative; 3922 background: #fff url(/apostrophePlugin/images/a-icon-loader.gif) center center no-repeat; 3923 border: 2px solid #222; 3924 } 3925 3926 .cropping-now 3927 { 3928 border: 2px solid #ddd; 3865 3929 } 3866 3930 … … 3891 3955 { 3892 3956 float: left; 3957 } 3958 3959 #a-media-selection-list-caption { 3960 display: none; 3961 position: absolute; 3962 padding: 45px; 3963 z-index: 1; 3964 } 3965 #a-media-selection-list-caption h4 { 3966 font-size: 1.2em; 3967 color: #999; 3968 } 3969 3970 #a-media-selection-preview 3971 { 3972 display:inline; 3973 float:left; 3974 width:100%; 3975 margin:10px 0 0; 3976 } 3977 3978 li.a-media-selection-preview-item { 3979 display:none; 3980 position:relative; 3981 width:auto; 3982 height:auto; 3983 } 3984 li.a-media-selection-preview-item.current { 3985 display: block !important; 3986 } 3987 3988 li.a-media-selection-preview-item .jcrop-holder { 3989 margin-bottom:28px; 3990 } 3991 3992 ul.a-media-crop-controls 3993 { 3994 position: absolute; 3995 display: none; 3996 bottom: -29px; 3997 } 3998 3999 .a-crop-workspace 4000 { 4001 overflow: hidden; 4002 display: none; 4003 /*margin: 0 0 10px; 4004 padding: 10px; 4005 background-color: #222; 4006 -moz-border-radius: 4px; 4007 -webkit-border-radius: 4px; 4008 border-radius: 4px; 4009 box-shadow:inset 0 0 10px #000000; 4010 -moz-box-shadow:inset 0 0 10px #000000; 4011 -webkit-box-shadow:inset 0 0 10px #000000;*/ 4012 } 4013 4014 4015 .a-crop-workspace h4 4016 { 4017 color:#ddd; 4018 margin-bottom:10px; 3893 4019 } 3894 4020 -
plugins/apostrophePlugin/trunk/web/images
- Property svn:mergeinfo changed
/plugins/apostrophePlugin/branches/cropping/web/images (added) merged: 1470-1489 /plugins/apostrophePlugin/branches/features/cropping/web/images (added) merged: 1847
- Property svn:mergeinfo changed

