Overview

Namespaces

  • LeanCloud
    • Engine
    • Operation
    • Storage
    • Uploader

Classes

  • LeanCloud\ACL
  • LeanCloud\AppRouter
  • LeanCloud\Bytes
  • LeanCloud\Client
  • LeanCloud\Engine\Cloud
  • LeanCloud\Engine\LaravelEngine
  • LeanCloud\Engine\LeanEngine
  • LeanCloud\Engine\SlimEngine
  • LeanCloud\File
  • LeanCloud\GeoPoint
  • LeanCloud\LeanObject
  • LeanCloud\MIMEType
  • LeanCloud\Operation\ArrayOperation
  • LeanCloud\Operation\DeleteOperation
  • LeanCloud\Operation\IncrementOperation
  • LeanCloud\Operation\RelationOperation
  • LeanCloud\Operation\SetOperation
  • LeanCloud\Push
  • LeanCloud\Query
  • LeanCloud\Region
  • LeanCloud\Relation
  • LeanCloud\Role
  • LeanCloud\RouteCache
  • LeanCloud\SaveOption
  • LeanCloud\SMS
  • LeanCloud\Storage\CookieStorage
  • LeanCloud\Storage\SessionStorage
  • LeanCloud\Uploader\QCloudUploader
  • LeanCloud\Uploader\QiniuUploader
  • LeanCloud\Uploader\S3Uploader
  • LeanCloud\Uploader\SimpleUploader
  • LeanCloud\User

Interfaces

  • LeanCloud\Operation\IOperation
  • LeanCloud\Storage\IStorage

Exceptions

  • LeanCloud\BatchRequestError
  • LeanCloud\CloudException
  • LeanCloud\Engine\FunctionError
  • Overview
  • Namespace
  • Class
  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: 
<?php
namespace LeanCloud\Operation;

use LeanCloud\Relation;

/**
 * Relation operation
 *
 * Operation that supports adding and removing objects from `Relation`.
 */
class RelationOperation implements IOperation {
    /**
     * The key of field the operation is about to apply
     *
     * @var string
     */
    private $key;

    /**
     * The target className of relation operation
     *
     * @var string
     */
    private $targetClassName;

    /**
     * The objects to add
     *
     * @var array
     */
    private $objects_to_add = array();

    /**
     * The objects to remove
     *
     * @var array
     */
    private $objects_to_remove = array();

    /**
     * Initialize relation operation
     *
     * @param string $key     Field key
     * @param array  $adds    The objects to add
     * @param array  $removes The objects to remove
     * @throws RuntimeException
     */
    public function __construct($key, $adds, $removes) {
        if (empty($adds) && empty($removes)) {
            throw new \InvalidArgumentException("Operands are empty.");
        }
        $this->key   = $key;
        // The op order here ensures add wins over remove
        $this->remove($removes);
        $this->add($adds);
    }

    /**
     * Get key of field the operation applies to.
     *
     * @return string
     */
    public function getKey() {
        return $this->key;
    }

    /**
     * Get target className of relation
     *
     * @return string
     */
    public function getTargetClassName() {
        return $this->targetClassName;
    }

    /**
     * Encode to JSON represented operation
     *
     * @return array
     */
    public function encode() {
        $adds    = array("__op" => "AddRelation",
                         "objects" => array());
        $removes = array("__op" => "RemoveRelation",
                         "objects" => array());
        forEach($this->objects_to_add as $obj) {
            $adds["objects"][] = $obj->getPointer();
        }
        forEach($this->objects_to_remove as $obj) {
            $removes["objects"][] = $obj->getPointer();
        }

        if (empty($this->objects_to_remove)) {
            return $adds;
        }
        if (empty($this->objects_to_add)) {
            return $removes;
        }
        return array("__op" => "Batch",
                     "ops"  => array($adds, $removes));
    }

    /**
     * Add object(s) to relation
     *
     * @param array $objects LeanObject(s) to add
     */
    private function add($objects) {
        if (empty($objects)) { return; }
        if (!$this->targetClassName) {
            $this->targetClassName = current($objects)->getClassName();
        }
        forEach($objects as $obj) {
            if (!$obj->getObjectId()) {
                throw new \RuntimeException("Cannot add unsaved object" .
                                            " to relation.");
            }
            if ($obj->getClassName() !== $this->targetClassName) {
                throw new \RuntimeException("LeanObject type incompatible" .
                                            " with relation.");
            }
            if (isset($this->objects_to_remove[$obj->getObjectID()])) {
                unset($this->objects_to_remove[$obj->getObjectID()]);
            }
            $this->objects_to_add[$obj->getObjectId()] = $obj;
        }
    }

    /**
     * Remove object(s) from relation
     *
     * @param array $objects LeanObject(s) to remove
     */
    private function remove($objects) {
        if (empty($objects)) { return; }
        if (!$this->targetClassName) {
            $this->targetClassName = current($objects)->getClassName();
        }
        forEach($objects as $obj) {
            if (!$obj->getObjectId()) {
                throw new \RuntimeException("Cannot remove unsaved object" .
                                            " from relation.");
            }
            if ($obj->getClassName() !== $this->targetClassName) {
                throw new \RuntimeException("LeanObject type incompatible" .
                                            " with relation.");
            }
            if (isset($this->objects_to_add[$obj->getObjectID()])) {
                unset($this->objects_to_add[$obj->getObjectID()]);
            }
            $this->objects_to_remove[$obj->getObjectId()] = $obj;
        }
    }

    /**
     * Apply the operation on previous relation
     *
     * @param Relation $relation Previous relation
     * @param LeanObject   $object   Parent of relation
     * @return Relation
     * @throws RuntimeException
     */
    public function applyOn($relation, $object=null) {
        if (!$relation) {
            return new Relation($object, $this->getKey(),
                                    $this->getTargetClassName());
        }
        if (!($relation instanceof Relation)) {
            throw new \RuntimeException("Operation incompatible with " .
                                        "previous value.");
        }
        // TODO: check target class
        return $relation;
    }

    /**
     * Merge with (previous) operation
     *
     * @param  IOperation $prevOp Previous operation
     * @return IOperation
     */
    public function mergeWith($prevOp) {
        if (!$prevOp) {
            return $this;
        }
        if ($prevOp instanceof RelationOperation) {
            $adds    = array_merge($this->objects_to_add,
                                   $prevOp->objects_to_add);
            $removes = array_merge($this->objects_to_remove,
                                   $prevOp->objects_to_remove);
            return new RelationOperation($this->getKey(), $adds, $removes);
        } else {
            throw new \RuntimeException("Operation incompatible with " .
                                        "previous one.");
        }
    }
}

API documentation generated by ApiGen