From 4263d9e6a4fde49a62424f7c99ecfdeef04dbdc5 Mon Sep 17 00:00:00 2001 From: Jang Rush Date: Tue, 21 Apr 2020 12:20:39 +0800 Subject: [PATCH 1/4] chore: be careful when creating tags --- Hacking.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Hacking.md b/Hacking.md index 1ccc647..bfef931 100644 --- a/Hacking.md +++ b/Hacking.md @@ -47,7 +47,10 @@ and edit `Changelog.md` (git log subjects are for reference only, do not leave t Commit changes and send a pull request at leancloud/php-sdk. -If everything is O.K., the maintainer will merge the pull request, push a new tag, and publish a new release at GitHub. +If everything is O.K., the maintainer will merge the pull request, create a new tag, and publish a new release at GitHub. +Then a new version will be published at Packagist automatically. +It is recommended for the maintainer to create the tag when drafting a new release on GitHub web interface. +If you prefer creating a tag locally, do not forget to pull from origin before creating a new tag. Then a new version will be published at Packagist automatically. ## Run Tests with Coverage From a3f4083951ff65b53fd3625a9a621e6338ee25a4 Mon Sep 17 00:00:00 2001 From: Jang Rush Date: Tue, 15 Dec 2020 11:15:04 +0800 Subject: [PATCH 2/4] docs: change log for v0.14.0 --- Changelog.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Changelog.md b/Changelog.md index adc47e9..4aaf5bf 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,11 @@ +0.14.0 Released on 2020-12-15 +---- + +- Add `runRemote()` (invoking cloud function remotely). +- Allow specifying the file key/path with `masterKey`. +- Add license (Apache-2.0). + 0.13.0 Released on 2020-07-15 ---- From 555f397a21bdffa6919d5e63188dc42cb2e46e1b Mon Sep 17 00:00:00 2001 From: Jang Rush Date: Tue, 15 Dec 2020 11:16:04 +0800 Subject: [PATCH 3/4] docs: update api doc --- docs/class-LeanCloud.Client.html | 2 +- docs/class-LeanCloud.File.html | 116 +++- docs/source-class-LeanCloud.Client.html | 2 +- docs/source-class-LeanCloud.File.html | 800 ++++++++++++------------ 4 files changed, 498 insertions(+), 422 deletions(-) diff --git a/docs/class-LeanCloud.Client.html b/docs/class-LeanCloud.Client.html index 38f250d..267fcb7 100644 --- a/docs/class-LeanCloud.Client.html +++ b/docs/class-LeanCloud.Client.html @@ -1282,7 +1282,7 @@

Returns

# - '0.13.0' + '0.14.0'
diff --git a/docs/class-LeanCloud.File.html b/docs/class-LeanCloud.File.html index 66d7523..af921bb 100644 --- a/docs/class-LeanCloud.File.html +++ b/docs/class-LeanCloud.File.html @@ -135,7 +135,7 @@

Class File

Namespace: LeanCloud
- Located at LeanCloud/File.php + Located at LeanCloud/File.php
@@ -155,7 +155,7 @@

Class File

# - __construct( string $name, mixed $data = null, string $mimeType = null ) + __construct( string $name, mixed $data = null, string $mimeType = null )

Initialize file

@@ -194,7 +194,7 @@

Parameters

# - createWithUrl( string $name, string $url, string $mimeType = null ) + createWithUrl( string $name, string $url, string $mimeType = null )

Create file with public external URL

@@ -237,7 +237,7 @@

Returns

# - createWithData( string $name, string $data, string $mimeType = null ) + createWithData( string $name, string $data, string $mimeType = null )

Create file with raw data

@@ -280,7 +280,7 @@

Returns

# - createWithLocalFile( string $filepath, string $mimeType = null, string $name = null ) + createWithLocalFile( string $filepath, string $mimeType = null, string $name = null )

Create file from disk

@@ -327,7 +327,7 @@

Throws

# - get( string $key ) + get( string $key )

Get file attribute

@@ -366,7 +366,7 @@

Returns

# - getName( ) + getName( )

Get name of file

@@ -385,6 +385,74 @@

Returns

+
+
+ + + + + public + + string + + + + +
+ # + getKey( ) + +
+

Get key of file

+
+ + +
+ + + + + public + + LeanCloud\File + + + + +
+ # + setKey( $val ) + +
+

Set key of file

+
+ +
@@ -400,7 +468,7 @@

Returns

# - getObjectId( ) + getObjectId( )

Get objectId of file

@@ -434,7 +502,7 @@

Returns

# - getCreatedAt( ) + getCreatedAt( )
@@ -468,7 +536,7 @@

Returns

# - getUpdatedAt( ) + getUpdatedAt( )
@@ -502,7 +570,7 @@

Returns

# - getMimeType( ) + getMimeType( )

Get file MIME type

@@ -536,7 +604,7 @@

Returns

# - getUrl( ) + getUrl( )

Get file url

@@ -570,7 +638,7 @@

Returns

# - getThumbUrl( float|integer $width, float|integer $height, float|integer $quality = 100, boolean $scaleToFit = true, string $format = "png" ) + getThumbUrl( float|integer $width, float|integer $height, float|integer $quality = 100, boolean $scaleToFit = true, string $format = "png" )

Get thumbnail URL

@@ -621,7 +689,7 @@

Returns

# - getSize( ) + getSize( )

Get file size

@@ -655,7 +723,7 @@

Returns

# - getOwnerId( ) + getOwnerId( )

Get id of uploaded user

@@ -689,7 +757,7 @@

Returns

# - setMeta( string $key, miexed $val ) + setMeta( string $key, miexed $val )

Set meta data

@@ -730,7 +798,7 @@

Returns

# - getMeta( string $key = null ) + getMeta( string $key = null )

Get meta data

@@ -771,7 +839,7 @@

Returns

# - mergeAfterSave( array $data ) + mergeAfterSave( array $data )

Merge server response after save

@@ -806,7 +874,7 @@

Parameters

# - mergeAfterFetch( array $data ) + mergeAfterFetch( array $data )

Merge server response after fetch

@@ -841,7 +909,7 @@

Parameters

# - isDirty( ) + isDirty( )

If there are unsaved changes.

@@ -875,7 +943,7 @@

Returns

# - save( ) + save( )

Save file on the cloud

@@ -909,7 +977,7 @@

Throws

# - fetch( $objectId ) + fetch( $objectId )

Fetch file object by id

@@ -946,7 +1014,7 @@

Returns

# - destroy( ) + destroy( )

Delete file on cloud

@@ -980,7 +1048,7 @@

Throws

# - encode( ) + encode( )

Encode to JSON representation

diff --git a/docs/source-class-LeanCloud.Client.html b/docs/source-class-LeanCloud.Client.html index 3de77ce..604cc03 100644 --- a/docs/source-class-LeanCloud.Client.html +++ b/docs/source-class-LeanCloud.Client.html @@ -161,7 +161,7 @@

Exceptions

/** * Client version */ - const VERSION = '0.13.0'; + const VERSION = '0.14.0'; /** * API Version string diff --git a/docs/source-class-LeanCloud.File.html b/docs/source-class-LeanCloud.File.html index 967edcd..d7c4255 100644 --- a/docs/source-class-LeanCloud.File.html +++ b/docs/source-class-LeanCloud.File.html @@ -134,7 +134,7 @@

Exceptions

-
  1:   2:   3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13:  14:  15:  16:  17:  18:  19:  20:  21:  22:  23:  24:  25:  26:  27:  28:  29:  30:  31:  32:  33:  34:  35:  36:  37:  38:  39:  40:  41:  42:  43:  44:  45:  46:  47:  48:  49:  50:  51:  52:  53:  54:  55:  56:  57:  58:  59:  60:  61:  62:  63:  64:  65:  66:  67:  68:  69:  70:  71:  72:  73:  74:  75:  76:  77:  78:  79:  80:  81:  82:  83:  84:  85:  86:  87:  88:  89:  90:  91:  92:  93:  94:  95:  96:  97:  98:  99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 
+
  1:   2:   3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13:  14:  15:  16:  17:  18:  19:  20:  21:  22:  23:  24:  25:  26:  27:  28:  29:  30:  31:  32:  33:  34:  35:  36:  37:  38:  39:  40:  41:  42:  43:  44:  45:  46:  47:  48:  49:  50:  51:  52:  53:  54:  55:  56:  57:  58:  59:  60:  61:  62:  63:  64:  65:  66:  67:  68:  69:  70:  71:  72:  73:  74:  75:  76:  77:  78:  79:  80:  81:  82:  83:  84:  85:  86:  87:  88:  89:  90:  91:  92:  93:  94:  95:  96:  97:  98:  99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460: 
<?php
 namespace LeanCloud;
 
@@ -186,407 +186,415 @@ 

Exceptions

*/ public function __construct($name, $data=null, $mimeType=null) { $this->_data["name"] = $name; - $this->_source = $data; - - if (!$mimeType) { - $ext = pathinfo($name, PATHINFO_EXTENSION); - $mimeType = MIMEType::getType($ext); - } - $this->_data["mime_type"] = $mimeType; - - $this->_metaData["owner"] = "unknown"; - if (User::$currentUser) { - $this->_metaData["owner"] = User::$currentUser->getObjectId(); - } - if ($this->_source) { - $this->_metaData["size"] = strlen($this->_source); - } - } - - /** - * Create file with public external URL - * - * @param string $name File base name - * @param string $url Public URL - * @param string $mimeType (optional) - * @return File - */ - public static function createWithUrl($name, $url, $mimeType=null) { - $file = new File($name, null, $mimeType); - $file->_data["url"] = $url; - $file->_metaData["__source"] = "external"; - return $file; - } - - /** - * Create file with raw data - * - * @param string $name File name - * @param string $data File content - * @param string $mimeType - * @return File - */ - public static function createWithData($name, $data, $mimeType=null) { - $file = new File($name, $data, $mimeType); - return $file; - } - - /** - * Create file from disk - * - * @param string $filepath Absolute file path - * @param string $mimeType E.g. "image/png" - * @param string $name Name of file - * @return File - * @throws RuntimeException - */ - public static function createWithLocalFile($filepath, $mimeType=null, $name=null) { - $content = file_get_contents($filepath); - if ($content === false) { - throw new \RuntimeException("Read file error at $filepath"); - } - if (!$name) { - $name = basename($filepath); - } - return static::createWithData($name, $content, $mimeType); - } - - /** - * Get file attribute - * - * @param string $key - * @return mixed - */ - public function get($key) { - if (isset($this->_data[$key])) { - return $this->_data[$key]; - } - return null; - } - - /** - * Get name of file - * - * @return string - */ - public function getName() { - return $this->get("name"); - } - - /** - * Get objectId of file - * - * @return string - */ - public function getObjectId() { - return $this->get("objectId"); - } - + $this->_data["key"] = null; + $this->_source = $data; + + if (!$mimeType) { + $ext = pathinfo($name, PATHINFO_EXTENSION); + $mimeType = MIMEType::getType($ext); + } + $this->_data["mime_type"] = $mimeType; + + $this->_metaData["owner"] = "unknown"; + if (User::$currentUser) { + $this->_metaData["owner"] = User::$currentUser->getObjectId(); + } + if ($this->_source) { + $this->_metaData["size"] = strlen($this->_source); + } + } + + /** + * Create file with public external URL + * + * @param string $name File base name + * @param string $url Public URL + * @param string $mimeType (optional) + * @return File + */ + public static function createWithUrl($name, $url, $mimeType=null) { + $file = new File($name, null, $mimeType); + $file->_data["url"] = $url; + $file->_metaData["__source"] = "external"; + return $file; + } + + /** + * Create file with raw data + * + * @param string $name File name + * @param string $data File content + * @param string $mimeType + * @return File + */ + public static function createWithData($name, $data, $mimeType=null) { + $file = new File($name, $data, $mimeType); + return $file; + } + + /** + * Create file from disk + * + * @param string $filepath Absolute file path + * @param string $mimeType E.g. "image/png" + * @param string $name Name of file + * @return File + * @throws RuntimeException + */ + public static function createWithLocalFile($filepath, $mimeType=null, $name=null) { + $content = file_get_contents($filepath); + if ($content === false) { + throw new \RuntimeException("Read file error at $filepath"); + } + if (!$name) { + $name = basename($filepath); + } + return static::createWithData($name, $content, $mimeType); + } + + /** + * Get file attribute + * + * @param string $key + * @return mixed + */ + public function get($key) { + if (isset($this->_data[$key])) { + return $this->_data[$key]; + } + return null; + } + + /** + * Get name of file + * + * @return string + */ + public function getName() { + return $this->get("name"); + } + + /** + * Get key of file + * + * @return string + */ + public function getKey() { + return $this->get("key"); + } /** - * @return DateTime - */ - public function getCreatedAt() { - return $this->get("createdAt"); - } - - /** - * @return DateTime - */ - public function getUpdatedAt() { - return $this->get("updatedAt"); - } - - /** - * Get file MIME type - * - * @return string - */ - public function getMimeType() { - return $this->get("mime_type"); - } - - /** - * Get file url - * - * @return string - */ - public function getUrl() { - return $this->get("url"); - } - - /** - * Get thumbnail URL - * - * It returns a URL that could be used to display file thumbnail on - * client. The thumbnail will be generated on-the-fly when request - * arrives. - * - * @param float|int $width Image width - * @param float|int $height Image height - * @param float|int $quality Image quality factor between 0 ~ 100 - * @param bool $scaleToFit Scale to fit, or cut to fit - * @param string $format Image format: gif, png, webp etc. - * @return string - */ - public function getThumbUrl($width, $height, $quality=100, - $scaleToFit=true, $format="png") { - if (!$this->getUrl()) { - throw new \RuntimeException("File resource not available."); - } - if ($width < 0 || $height < 0) { - throw new \InvalidArgumentException("Width or height must". - " be positve."); - } - if ($quality > 100 || $quality < 0) { - throw new \InvalidArgumentException("Quality must be between". - " 0 and 100."); - } - $mode = $scaleToFit ? 2 : 1; - return $this->getUrl() . "?imageView/{$mode}/w/{$width}/h/{$height}". - "/q/{$quality}/format/{$format}"; - } - - /** - * Get file size - * - * @return int - */ - public function getSize() { - return $this->getMeta("size"); - } - - /** - * Get id of uploaded user - * - * @return string|null - */ - public function getOwnerId() { - return $this->getMeta("owner"); - } - - /** - * Set meta data - * - * @param string $key - * @param miexed $val - * @return self - */ - public function setMeta($key, $val) { - $this->_metaData[$key] = $val; - return $this; - } - - /** - * Get meta data - * - * It returns all metaData if key is null - * - * @param string $key - * @return mixed - */ - public function getMeta($key=null) { - if (!$key) { - return $this->_metaData; - } - - if (isset($this->_metaData[$key])) { - return $this->_metaData[$key]; - } - return null; + * Set key of file + * + * @return self + */ + public function setKey($val) { + $this->_data["key"] = $val; + return $this; + } + + /** + * Get objectId of file + * + * @return string + */ + public function getObjectId() { + return $this->get("objectId"); + } + + /** + * @return DateTime + */ + public function getCreatedAt() { + return $this->get("createdAt"); + } + + /** + * @return DateTime + */ + public function getUpdatedAt() { + return $this->get("updatedAt"); + } + + /** + * Get file MIME type + * + * @return string + */ + public function getMimeType() { + return $this->get("mime_type"); + } + + /** + * Get file url + * + * @return string + */ + public function getUrl() { + return $this->get("url"); + } + + /** + * Get thumbnail URL + * + * It returns a URL that could be used to display file thumbnail on + * client. The thumbnail will be generated on-the-fly when request + * arrives. + * + * @param float|int $width Image width + * @param float|int $height Image height + * @param float|int $quality Image quality factor between 0 ~ 100 + * @param bool $scaleToFit Scale to fit, or cut to fit + * @param string $format Image format: gif, png, webp etc. + * @return string + */ + public function getThumbUrl($width, $height, $quality=100, + $scaleToFit=true, $format="png") { + if (!$this->getUrl()) { + throw new \RuntimeException("File resource not available."); + } + if ($width < 0 || $height < 0) { + throw new \InvalidArgumentException("Width or height must". + " be positve."); + } + if ($quality > 100 || $quality < 0) { + throw new \InvalidArgumentException("Quality must be between". + " 0 and 100."); + } + $mode = $scaleToFit ? 2 : 1; + return $this->getUrl() . "?imageView/{$mode}/w/{$width}/h/{$height}". + "/q/{$quality}/format/{$format}"; + } + + /** + * Get file size + * + * @return int + */ + public function getSize() { + return $this->getMeta("size"); + } + + /** + * Get id of uploaded user + * + * @return string|null + */ + public function getOwnerId() { + return $this->getMeta("owner"); + } + + /** + * Set meta data + * + * @param string $key + * @param miexed $val + * @return self + */ + public function setMeta($key, $val) { + $this->_metaData[$key] = $val; + return $this; } /** - * Generate pseudo-uuid key for filename + * Get meta data * - * @return string - */ - private static function genFileKey() { - $octets = array_map(function() { - $num = floor((1 + Client::randomFloat()) * 0x10000); - return substr(dechex($num), 1); - }, range(0, 4)); - return implode("", $octets); - } + * It returns all metaData if key is null + * + * @param string $key + * @return mixed + */ + public function getMeta($key=null) { + if (!$key) { + return $this->_metaData; + } - /** - * Is the file exteranl - * - * @return bool - */ - private function isExternal() { - return $this->getMeta("__source") === "external"; - } - - /** - * Merge data and metaData from server response - * - * @param array $data - * @param array $meta Optional meta data - */ - private function _mergeData($data, $meta=array()) { - // manually convert createdAt and updatedAt fields so they'll - // be decoded as DateTime object. - forEach(array("createdAt", "updatedAt") as $key) { - if (isset($data[$key]) && is_string($data[$key])) { - $data[$key] = array("__type" => "Date", - "iso" => $data[$key]); - } - } - - forEach($data as $key => $val) { - $this->_data[$key] = Client::decode($val, $key); - } - - forEach($meta as $key => $val) { - $this->_metaData[$key] = Client::decode($val, $key); - } - } - - /** - * Merge server response after save - * - * @param array $data JSON decoded response - */ - public function mergeAfterSave($data) { - $meta = array(); - if (isset($data["metaData"])) { - $meta = $data["metaData"]; - unset($data["metaData"]); - } - if (isset($data["size"])) { - $meta["size"] = $data["size"]; - unset($data["size"]); - } - $this->_mergeData($data, $meta); - } - - /** - * Merge server response after fetch - * - * @param array $data JSON decoded response - */ - public function mergeAfterFetch($data) { - $meta = array(); - if (isset($data["metaData"])) { - $meta = $data["metaData"]; - unset($data["metaData"]); - } - $this->_mergeData($data, $meta); - } - - /** - * If there are unsaved changes. - * - * @return bool - */ - public function isDirty() { - $id = $this->getObjectId(); - return empty($id); - } - - /** - * Save file on the cloud - * - * @throws CloudException - */ - public function save() { - if (!$this->isDirty()) { - return; - } - - $data = array( - "name" => $this->getName(), - "ACL" => $this->get("ACL"), - "mime_type" => $this->getMimeType(), - "metaData" => $this->getMeta(), - ); - - if ($this->isExternal()) { - $data["url"] = $this->getUrl(); - $resp = Client::post("/files/{$this->getName()}", $data); - $this->mergeAfterSave($resp); - } else { - $key = static::genFileKey(); - $key = "{$key}." . pathinfo($this->getName(), PATHINFO_EXTENSION); - $data["key"] = $key; - $data["__type"] = "File"; - $resp = Client::post("/fileTokens", $data); - if (!isset($resp["token"])) { - // adapt for S3, when there is no token - $resp["token"] = null; - } - - $callbackParams = array("token" => $resp["token"]); - try { - $uploader = SimpleUploader::createUploader($resp["provider"]); - $uploader->initialize($resp["upload_url"], $resp["token"]); - $uploader->upload($this->_source, $this->getMimeType(), $key); - $callbackParams["result"] = true; - } catch (\Exception $ex) { - $callbackParams["result"] = false; - throw $ex; - } finally { - try { - Client::post("/fileCallback", $callbackParams); - } catch (\Exception $ex) { - error_log("Request /fileCallback failed."); - } - } - - forEach(array("upload_url", "token") as $k) { - if (isset($resp[$k])) { - unset($resp[$k]); - } - } - $this->mergeAfterSave($resp); - } - } - - /** - * Fetch file object by id - * - * Note it fetches descriptive data from LeanCloud, but not file content. - * The content should be fetched from file URL. - * - * @return File - */ - public static function fetch($objectId) { - $file = new File(""); - $resp = Client::get("/files/{$objectId}"); - $file->mergeAfterFetch($resp); - return $file; - } - - /** - * Delete file on cloud - * - * @throws CloudException - */ - public function destroy() { - if (!$this->getObjectId()) { - return false; - } - Client::delete("/files/{$this->getObjectId()}"); - } - - /** - * Encode to JSON representation - * - * @return array - */ - public function encode() { - if (!$this->getObjectId()) { - throw new \RuntimeException("Cannot serialize unsaved file."); - } - return array( - "__type" => "File", - "id" => $this->getObjectId(), - "name" => $this->getName(), - "url" => $this->getUrl() - ); - } -} -
+ if (isset($this->_metaData[$key])) { + return $this->_metaData[$key]; + } + return null; + } + + /** + * Is the file exteranl + * + * @return bool + */ + private function isExternal() { + return $this->getMeta("__source") === "external"; + } + + /** + * Merge data and metaData from server response + * + * @param array $data + * @param array $meta Optional meta data + */ + private function _mergeData($data, $meta=array()) { + // manually convert createdAt and updatedAt fields so they'll + // be decoded as DateTime object. + forEach(array("createdAt", "updatedAt") as $key) { + if (isset($data[$key]) && is_string($data[$key])) { + $data[$key] = array("__type" => "Date", + "iso" => $data[$key]); + } + } + + forEach($data as $key => $val) { + $this->_data[$key] = Client::decode($val, $key); + } + + forEach($meta as $key => $val) { + $this->_metaData[$key] = Client::decode($val, $key); + } + } + + /** + * Merge server response after save + * + * @param array $data JSON decoded response + */ + public function mergeAfterSave($data) { + $meta = array(); + if (isset($data["metaData"])) { + $meta = $data["metaData"]; + unset($data["metaData"]); + } + if (isset($data["size"])) { + $meta["size"] = $data["size"]; + unset($data["size"]); + } + $this->_mergeData($data, $meta); + } + + /** + * Merge server response after fetch + * + * @param array $data JSON decoded response + */ + public function mergeAfterFetch($data) { + $meta = array(); + if (isset($data["metaData"])) { + $meta = $data["metaData"]; + unset($data["metaData"]); + } + $this->_mergeData($data, $meta); + } + + /** + * If there are unsaved changes. + * + * @return bool + */ + public function isDirty() { + $id = $this->getObjectId(); + return empty($id); + } + + /** + * Save file on the cloud + * + * @throws CloudException + */ + public function save() { + if (!$this->isDirty()) { + return; + } + + $data = array( + "name" => $this->getName(), + "ACL" => $this->get("ACL"), + "mime_type" => $this->getMimeType(), + "metaData" => $this->getMeta(), + ); + + if ($this->isExternal()) { + $data["url"] = $this->getUrl(); + $resp = Client::post("/files", $data); + $this->mergeAfterSave($resp); + } else { + $key = $this->getKey(); + if (isset($key)) { + $data["key"] = $key; + } + $data["__type"] = "File"; + $resp = Client::post("/fileTokens", $data); + if (!isset($resp["token"])) { + // adapt for S3, when there is no token + $resp["token"] = null; + } + + $callbackParams = array("token" => $resp["token"]); + try { + $uploader = SimpleUploader::createUploader($resp["provider"]); + $uploader->initialize($resp["upload_url"], $resp["token"]); + $uploader->upload($this->_source, $this->getMimeType(), $key); + $callbackParams["result"] = true; + } catch (\Exception $ex) { + $callbackParams["result"] = false; + throw $ex; + } finally { + try { + Client::post("/fileCallback", $callbackParams); + } catch (\Exception $ex) { + error_log("Request /fileCallback failed."); + } + } + + forEach(array("upload_url", "token") as $k) { + if (isset($resp[$k])) { + unset($resp[$k]); + } + } + + $this->mergeAfterSave($resp); + } + } + + /** + * Fetch file object by id + * + * Note it fetches descriptive data from LeanCloud, but not file content. + * The content should be fetched from file URL. + * + * @return File + */ + public static function fetch($objectId) { + $file = new File(""); + $resp = Client::get("/files/{$objectId}"); + $file->mergeAfterFetch($resp); + return $file; + } + + /** + * Delete file on cloud + * + * @throws CloudException + */ + public function destroy() { + if (!$this->getObjectId()) { + return false; + } + Client::delete("/files/{$this->getObjectId()}"); + } + + /** + * Encode to JSON representation + * + * @return array + */ + public function encode() { + if (!$this->getObjectId()) { + throw new \RuntimeException("Cannot serialize unsaved file."); + } + return array( + "__type" => "File", + "id" => $this->getObjectId(), + "name" => $this->getName(), + "url" => $this->getUrl() + ); + } +} +