Пример #1
0
 /**
  * @inheritDoc
  */
 public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null)
 {
     if ($this->scheduler !== null) {
         $scheduler = $this->scheduler;
     }
     if ($scheduler === null) {
         throw new \Exception("You must use a scheduler that support non-zero delay.");
     }
     $lastScheduledTime = 0;
     $disposable = new CompositeDisposable();
     $sourceDisposable = new EmptyDisposable();
     $sourceDisposable = $observable->subscribe(new CallbackObserver(function ($x) use($scheduler, $observer, &$lastScheduledTime, $disposable) {
         $schedDisp = $scheduler->schedule(function () use($x, $observer, &$schedDisp, $disposable) {
             $observer->onNext($x);
             $disposable->remove($schedDisp);
         }, $this->delay);
         $disposable->add($schedDisp);
     }, function ($err) use($scheduler, $observer, &$lastScheduledTime, $disposable, &$sourceDisposable) {
         $disposable->remove($sourceDisposable);
         $sourceDisposable->dispose();
         $observer->onError($err);
     }, function () use($scheduler, $observer, $disposable, &$sourceDisposable) {
         $disposable->remove($sourceDisposable);
         $sourceDisposable->dispose();
         $schedDisp = $scheduler->schedule(function () use($observer, &$schedDisp, $disposable) {
             $observer->onCompleted();
             $disposable->remove($schedDisp);
         }, $this->delay);
         $disposable->add($schedDisp);
     }), $scheduler);
     $disposable->add($sourceDisposable);
     return $disposable;
 }
Пример #2
0
 public function scheduleRecursive($action)
 {
     if (!is_callable($action)) {
         throw new InvalidArgumentException("Action should be a callable.");
     }
     $group = new CompositeDisposable();
     $scheduler = $this;
     $recursiveAction = null;
     $recursiveAction = function () use($action, &$scheduler, &$group, &$recursiveAction) {
         $action(function () use(&$scheduler, &$group, &$recursiveAction) {
             $isAdded = false;
             $isDone = true;
             $d = $scheduler->schedule(function () use(&$isAdded, &$isDone, &$group, &$recursiveAction, &$d) {
                 if (is_callable($recursiveAction)) {
                     $recursiveAction();
                 } else {
                     throw new \Exception("recursiveAction is not callable");
                 }
                 if ($isAdded) {
                     $group->remove($d);
                 } else {
                     $isDone = true;
                 }
             });
             if (!$isDone) {
                 $group->add($d);
                 $isAdded = true;
             }
         });
     };
     $group->add($this->schedule($recursiveAction));
     return $group;
 }
Пример #3
0
 public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null)
 {
     $singleDisposable = new SingleAssignmentDisposable();
     $disposable = new CompositeDisposable();
     $disposable->add($singleDisposable);
     $callbackObserver = new CallbackObserver(function (Observable $x) use($disposable, $scheduler, $observer) {
         if ($this->hasCurrent) {
             return;
         }
         $this->hasCurrent = true;
         $inner = new SingleAssignmentDisposable();
         $disposable->add($inner);
         $innerSub = $x->subscribe(new CallbackObserver([$observer, "onNext"], [$observer, "onError"], function () use($disposable, $inner, $observer) {
             $disposable->remove($inner);
             $this->hasCurrent = false;
             if ($this->isStopped && $disposable->count() === 1) {
                 $observer->onCompleted();
             }
         }), $scheduler);
         $inner->setDisposable($innerSub);
     }, [$observer, 'onError'], function () use($disposable, $observer) {
         $this->isStopped = true;
         if (!$this->hasCurrent && $disposable->count() === 1) {
             $observer->onCompleted();
         }
     });
     $singleDisposable->setDisposable($observable->subscribe($callbackObserver, $scheduler));
     return $disposable;
 }
Пример #4
0
 private function subscribeToResult(ObservableInterface $observable, SchedulerInterface $scheduler, ObserverInterface $observer, $outerIndex)
 {
     return $observable->subscribe(new CallbackObserver(function ($value) use($observer, $outerIndex) {
         if (!$this->hasFirst) {
             $this->hasFirst = true;
             foreach ($this->subscriptions as $i => $subscription) {
                 if ($i !== $outerIndex) {
                     $subscription->dispose();
                     unset($this->subscriptions[$i]);
                     $this->innerSubscription->remove($subscription);
                 }
             }
         }
         $observer->onNext($value);
     }, [$observer, 'onError'], [$observer, 'onCompleted']), $scheduler);
 }
Пример #5
0
 /**
  * @param \Rx\ObservableInterface $observable
  * @param \Rx\ObserverInterface $observer
  * @param \Rx\SchedulerInterface $scheduler
  * @return \Rx\DisposableInterface
  */
 public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null)
 {
     $group = new CompositeDisposable();
     $isStopped = false;
     $sourceSubscription = new SingleAssignmentDisposable();
     $group->add($sourceSubscription);
     $callbackObserver = new CallbackObserver(function (ObservableInterface $innerSource) use(&$group, &$isStopped, $observer, &$scheduler) {
         $innerSubscription = new SingleAssignmentDisposable();
         $group->add($innerSubscription);
         $innerSubscription->setDisposable($innerSource->subscribe(new CallbackObserver(function ($nextValue) use($observer) {
             $observer->onNext($nextValue);
         }, function ($error) use($observer) {
             $observer->onError($error);
         }, function () use(&$group, &$innerSubscription, &$isStopped, $observer) {
             $group->remove($innerSubscription);
             if ($isStopped && $group->count() === 1) {
                 $observer->onCompleted();
             }
         }), $scheduler));
     }, [$observer, 'onError'], function () use(&$group, &$isStopped, $observer) {
         $isStopped = true;
         if ($group->count() === 1) {
             $observer->onCompleted();
         }
     });
     $subscription = $this->sources->subscribe($callbackObserver, $scheduler);
     $sourceSubscription->setDisposable($subscription);
     return $group;
 }
Пример #6
0
 /**
  * @param ObservableInterface $observable
  * @param ObserverInterface $observer
  * @param SchedulerInterface|null $scheduler
  * @return CompositeDisposable
  */
 public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null)
 {
     $subscription = $observable->subscribe(new CallbackObserver(function (ObservableInterface $innerObservable) use($observable, $observer, $scheduler) {
         try {
             if ($this->startBuffering === true) {
                 $this->buffer[] = $innerObservable;
                 return;
             }
             $onCompleted = function () use(&$subscribeToInner, $observer) {
                 $this->disposable->remove($this->innerDisposable);
                 $this->innerDisposable->dispose();
                 $this->innerCompleted = true;
                 $obs = array_shift($this->buffer);
                 if (empty($this->buffer)) {
                     $this->startBuffering = false;
                 }
                 if ($obs) {
                     $subscribeToInner($obs);
                 } elseif ($this->sourceCompleted === true) {
                     $observer->onCompleted();
                 }
             };
             $subscribeToInner = function ($observable) use($observer, $scheduler, &$onCompleted) {
                 $callbackObserver = new CallbackObserver([$observer, 'onNext'], [$observer, 'onError'], $onCompleted);
                 $this->innerCompleted = false;
                 $this->startBuffering = true;
                 $this->innerDisposable = $observable->subscribe($callbackObserver, $scheduler);
                 $this->disposable->add($this->innerDisposable);
             };
             $subscribeToInner($innerObservable);
         } catch (\Exception $e) {
             $observer->onError($e);
         }
     }, [$observer, 'onError'], function () use($observer) {
         $this->sourceCompleted = true;
         if ($this->innerCompleted === true) {
             $observer->onCompleted();
         }
     }), $scheduler);
     $this->disposable->add($subscription);
     return $this->disposable;
 }
Пример #7
0
 /**
  * @inheritDoc
  */
 public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null)
 {
     $errors = new Subject();
     $disposable = new CompositeDisposable();
     $sourceDisposable = new EmptyDisposable();
     $innerCompleted = false;
     $sourceError = false;
     try {
         $when = call_user_func($this->notificationHandler, $errors->asObservable());
     } catch (\Exception $e) {
         $observer->onError($e);
         return;
     }
     $subscribeToSource = function () use($observer, $disposable, $observable, &$sourceError, $errors, &$sourceDisposable, $scheduler, &$innerCompleted) {
         $sourceError = false;
         $sourceDisposable = $observable->subscribe(new CallbackObserver([$observer, 'onNext'], function ($err) use(&$sourceError, $errors, $disposable, &$sourceDisposable, &$innerCompleted, $observer) {
             $sourceError = true;
             $disposable->remove($sourceDisposable);
             $sourceDisposable->dispose();
             if ($innerCompleted) {
                 $observer->onCompleted();
                 return;
             }
             $errors->onNext($err);
         }, [$observer, 'onCompleted']), $scheduler);
         $disposable->add($sourceDisposable);
     };
     $whenDisposable = $when->subscribe(new CallbackObserver(function ($x) use($subscribeToSource, &$sourceError) {
         if ($sourceError) {
             $sourceError = false;
             $subscribeToSource();
         }
     }, [$observer, 'onError'], function () use(&$innerCompleted, &$sourceError, $observer) {
         $innerCompleted = true;
         if ($sourceError) {
             $observer->onCompleted();
         }
     }), $scheduler);
     $disposable->add($whenDisposable);
     $subscribeToSource();
     return $disposable;
 }
Пример #8
0
 /**
  * @param \Rx\ObservableInterface $observable
  * @param \Rx\ObserverInterface $observer
  * @param \Rx\SchedulerInterface $scheduler
  * @return \Rx\DisposableInterface
  */
 public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null)
 {
     $map = [];
     $groupDisposable = new CompositeDisposable();
     $refCountDisposable = new RefCountDisposable($groupDisposable);
     $keySelector = $this->keySelector;
     $elementSelector = $this->elementSelector;
     $durationSelector = $this->durationSelector;
     $keySerializer = $this->keySerializer;
     $sourceEmits = true;
     $callbackObserver = new CallbackObserver(function ($value) use(&$map, $keySelector, $elementSelector, $durationSelector, $observer, $keySerializer, $groupDisposable, $refCountDisposable, $scheduler, &$sourceEmits) {
         try {
             $key = $keySelector($value);
             $serializedKey = $keySerializer($key);
         } catch (Exception $e) {
             foreach ($map as $groupObserver) {
                 $groupObserver->onError($e);
             }
             $observer->onError($e);
             return;
         }
         $fireNewMapEntry = false;
         try {
             if (!isset($map[$serializedKey])) {
                 $map[$serializedKey] = new Subject();
                 $fireNewMapEntry = true;
             }
             $writer = $map[$serializedKey];
         } catch (Exception $e) {
             foreach ($map as $groupObserver) {
                 $groupObserver->onError($e);
             }
             $observer->onError($e);
             return;
         }
         if ($fireNewMapEntry) {
             $group = new GroupedObservable($key, $writer, $refCountDisposable);
             $durationGroup = new GroupedObservable($key, $writer);
             try {
                 $duration = $durationSelector($durationGroup);
             } catch (\Exception $e) {
                 foreach ($map as $groupObserver) {
                     $groupObserver->onError($e);
                 }
                 $observer->onError($e);
                 return;
             }
             if ($sourceEmits) {
                 $observer->onNext($group);
             }
             $md = new SingleAssignmentDisposable();
             $groupDisposable->add($md);
             $expire = function () use(&$map, &$md, $serializedKey, &$writer, &$groupDisposable) {
                 if (isset($map[$serializedKey])) {
                     unset($map[$serializedKey]);
                     $writer->onCompleted();
                 }
                 $groupDisposable->remove($md);
             };
             $callbackObserver = new CallbackObserver(function () {
             }, function (Exception $exception) use($map, $observer) {
                 foreach ($map as $writer) {
                     $writer->onError($exception);
                 }
                 $observer->onError($exception);
             }, function () use($expire) {
                 $expire();
             });
             $subscription = $duration->take(1)->subscribe($callbackObserver, $scheduler);
             $md->setDisposable($subscription);
         }
         try {
             $element = $elementSelector($value);
         } catch (Exception $exception) {
             foreach ($map as $writer) {
                 $writer->onError($exception);
             }
             $observer->onError($exception);
             return;
         }
         $writer->onNext($element);
     }, function (Exception $error) use(&$map, $observer) {
         foreach ($map as $writer) {
             $writer->onError($error);
         }
         $observer->onError($error);
     }, function () use(&$map, $observer) {
         foreach ($map as $writer) {
             $writer->onCompleted();
         }
         $observer->onCompleted();
     });
     $subscription = $observable->subscribe($callbackObserver, $scheduler);
     $groupDisposable->add($subscription);
     $sourceDisposable = new CallbackDisposable(function () use($refCountDisposable, &$sourceEmits) {
         $sourceEmits = false;
         $refCountDisposable->dispose();
     });
     return $sourceDisposable;
 }
Пример #9
0
 public function groupByUntil($keySelector, $elementSelector = null, $durationSelector = null, $keySerializer = null)
 {
     $currentObservable = $this;
     if (!is_callable($keySelector)) {
         throw new InvalidArgumentException('Key selector should be a callable.');
     }
     if (null === $elementSelector) {
         $elementSelector = function ($elem) {
             return $elem;
         };
     } else {
         if (!is_callable($elementSelector)) {
             throw new InvalidArgumentException('Element selector should be a callable.');
         }
     }
     if (null === $durationSelector) {
         $durationSelector = function ($x) {
             return $x;
         };
     } else {
         if (!is_callable($durationSelector)) {
             throw new InvalidArgumentException('Duration selector should be a callable.');
         }
     }
     if (null === $keySerializer) {
         $keySerializer = function ($x) {
             return $x;
         };
     } else {
         if (!is_callable($keySerializer)) {
             throw new InvalidArgumentException('Key serializer should be a callable.');
         }
     }
     return new AnonymousObservable(function ($observer, $scheduler) use($currentObservable, $keySelector, $elementSelector, $durationSelector, $keySerializer) {
         $map = array();
         $groupDisposable = new CompositeDisposable();
         $refCountDisposable = new RefCountDisposable($groupDisposable);
         $groupDisposable->add($currentObservable->subscribeCallback(function ($value) use(&$map, $keySelector, $elementSelector, $durationSelector, $observer, $keySerializer, $groupDisposable, $refCountDisposable) {
             try {
                 $key = $keySelector($value);
                 $serializedKey = $keySerializer($key);
             } catch (Exception $e) {
                 foreach ($map as $groupObserver) {
                     $groupObserver->onError($e);
                 }
                 $observer->onError($e);
                 return;
             }
             $fireNewMapEntry = false;
             try {
                 if (!isset($map[$serializedKey])) {
                     $map[$serializedKey] = new Subject();
                     $fireNewMapEntry = true;
                 }
                 $writer = $map[$serializedKey];
             } catch (Exception $e) {
                 foreach ($map as $groupObserver) {
                     $groupObserver->onError($e);
                 }
                 $observer->onError($e);
                 return;
             }
             if ($fireNewMapEntry) {
                 $group = new GroupedObservable($key, $writer, $refCountDisposable);
                 $durationGroup = new GroupedObservable($key, $writer);
                 try {
                     $duration = $durationSelector($durationGroup);
                 } catch (Exception $e) {
                     foreach ($map as $groupObserver) {
                         $groupObserver->onError($e);
                     }
                     $observer->onError($e);
                     return;
                 }
                 $observer->onNext($group);
                 $md = new SingleAssignmentDisposable();
                 $groupDisposable->add($md);
                 $expire = function () use(&$map, &$md, $serializedKey, &$writer, &$groupDisposable) {
                     if (isset($map[$serializedKey])) {
                         unset($map[$serializedKey]);
                         $writer->onCompleted();
                     }
                     $groupDisposable->remove($md);
                 };
                 $md->setDisposable($duration->take(1)->subscribeCallback(function () {
                 }, function (Exception $exception) use($map, $observer) {
                     foreach ($map as $writer) {
                         $writer->onError($exception);
                     }
                     $observer->onError($exception);
                 }, function () use($expire) {
                     $expire();
                 }));
             }
             try {
                 $element = $elementSelector($value);
             } catch (Exception $exception) {
                 foreach ($map as $writer) {
                     $writer->onError($exception);
                 }
                 $observer->onError($exception);
                 return;
             }
             $writer->onNext($element);
         }, function (Exception $error) use(&$map, $observer) {
             foreach ($map as $writer) {
                 $writer->onError($error);
             }
             $observer->onError($error);
         }, function () use(&$map, $observer) {
             foreach ($map as $writer) {
                 $writer->onCompleted();
             }
             $observer->onCompleted();
         }, $scheduler));
         return $refCountDisposable;
     });
 }
Пример #10
0
 /**
  * @test
  */
 public function removing_a_disposable_that_is_not_contained_has_no_effect()
 {
     $disposable = new CompositeDisposable(array());
     $disposed1 = false;
     $d1 = new CallbackDisposable(function () use(&$disposed1) {
         $disposed1 = true;
     });
     $disposable->remove($d1);
     $this->assertFalse($disposed1);
 }