/**
  * Create a mock object of the given class.
  *
  * Return null if users decide not to mock this object.
  *
  * @param       $className
  * @param array $arguments
  *
  * @return null|object
  */
 public function createMockInstance($className, array $arguments)
 {
     // Make sure to update the index if the caller hierarchy changes.
     // #1  Box\TestScribe\Mock\InjectedMockMgr->createMockInstance()
     // #2  Box\TestScribe\App::createMockedInstance()
     // #3  Box\TestScribe\_fixture\ServiceLocator::resolve_internal()
     // #4  Box\TestScribe\_fixture\ServiceLocator::resolve()
     // #5  Box\TestScribe\_fixture\_input\CalculatorViaLocator->calculateWithACalculator()
     $isTheCallFromTheClassBeingTested = $this->callOriginatorChecker->isCallFromTheClassBeingTested(5);
     if (!$isTheCallFromTheClassBeingTested) {
         return null;
     }
     if (array_key_exists($className, $this->injectedMockedObjects)) {
         // @TODO (ryang 1/27/15) : in Box webapp the diesel system will return
         // the same mock object if Diesel::Foo is called multiple times in
         // the same test and a mock for Foo is registered.
         // research if this behavior should be assumed for all
         // service locator systems.
         $msg = "Instantiating class ( {$className} ) which was mocked." . " Return the same mock object.";
         $this->output->writeln($msg);
         /**
          * @var MockClass $mockClass
          */
         $mockClass = $this->injectedMockedObjects[$className];
         return $mockClass->getMockedDynamicClassObj();
     }
     $mockClass = $this->fullMockObjectFactory->createMockObject($className);
     $this->injectedMockedObjects[$className] = $mockClass;
     $mockedDynamicClassObj = $mockClass->getMockedDynamicClassObj();
     return $mockedDynamicClassObj;
 }
 /**
  * @param string $str a PHP variable definition string with PHP syntax.
  *
  * @return \Box\TestScribe\Input\ExpressionWithMocks
  */
 public function process($str)
 {
     // Make sure to reset this member variable
     // because this class is a singleton.
     // @TODO (ryang 12/31/14) : investigate why using a local variable
     // and closure doesn't work.
     $this->mocks = [];
     $callback = function ($matches) {
         $className = $matches[0];
         $mockClass = $this->fullMockObjectFactory->createMockObject($className);
         $replacementStr = "\$" . $mockClass->getMockObjectName();
         $this->mocks[] = $mockClass;
         return $replacementStr;
     };
     // Need to escape '\' multiple times to make regex work.
     // The first \ is to escape PHP string '\' to allow it to be passed to regex engine.
     // preg_quote doesn't work since it escapes ^ incorrectly.
     // Test if the input is a string by testing if it starts with
     // a ' or " character.
     $isString = preg_match('#^\\s*[\'"]#', $str);
     if ($isString === 1) {
         $rc = new ExpressionWithMocks($str, []);
         return $rc;
     }
     // Match an identifier that starts with a '\' character
     // followed by letters or digits or '\'
     // and check if it is not part of a string
     // by looking ahead to see if it sees a ' or " character
     // or encounters a ',' character first.
     // e.g. [\Foo, "a"] should detect \Foo
     // e.g. ["\Foo"] should not detect \Foo
     // e.g. ["a\"b"] should not detect \"
     $regExpressionPattern = '#\\\\[a-zA-Z0-9_\\\\]+(?![^,]*[\'"])#';
     $replacedStr = preg_replace_callback($regExpressionPattern, $callback, $str);
     if ($replacedStr === null) {
         throw new \RuntimeException("Failed to replace class name references in the input string.");
     }
     $rc = new ExpressionWithMocks($replacedStr, $this->mocks);
     return $rc;
 }