Example #1
0
 /**
  * Virtual properties like "length".
  *
  * @param string $property
  *
  * @return mixed
  */
 public function __get($property)
 {
     if ($property == 'length') {
         return mb_strlen($this->text, 'UTF-8');
     }
     $properties = \Sledgehammer\reflect_properties($this);
     $properties['public']['length'] = -1;
     \Sledgehammer\warning('Property: "' . $property . '" doesn\'t exist in a "' . get_class($this) . '" object.', \Sledgehammer\build_properties_hint($properties));
 }
Example #2
0
 /**
  * Return credentials or false and send login headers.
  *
  * @return array|false
  */
 public function authenticate()
 {
     if (isset($_SERVER['PHP_AUTH_USER'])) {
         // Is er een gebruikersnaam bekend?
         if (call_user_func($this->validation, $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])) {
             return array('username' => $_SERVER['PHP_AUTH_USER'], 'password' => $_SERVER['PHP_AUTH_PW']);
         }
     }
     if (headers_sent()) {
         \Sledgehammer\warning('Unable show login dialog, HTTP headers already sent');
         return false;
     }
     $this->logout();
     return false;
 }
Example #3
0
 /**
  * @param string $template
  * @param array  $variables
  * @param array  $headers
  */
 public function __construct($template, $variables = array(), $headers = array())
 {
     $this->variables = $variables;
     $this->headers = $headers;
     if (file_exists($template)) {
         // file found?
         $this->template = $template;
     } elseif (substr($template, 0, 1) !== '/') {
         // A relative path?
         foreach (static::$includePaths as $folder) {
             if (file_exists($folder . $template)) {
                 // file found?
                 $this->template = $folder . $template;
                 break;
             }
         }
     }
     if ($this->template === null) {
         \Sledgehammer\warning('Template: "' . $template . '" not found', ['includePaths' => static::$includePaths]);
         $this->template = $template;
     }
 }
Example #4
0
 /**
  * CDATA & Inline DTD tags.
  *
  * @link http://nl.wikipedia.org/wiki/Document_Type_Definition#Voorbeeld_2
  */
 public function parseDTDTag()
 {
     if ($this->substr(0, 2) !== '<!') {
         throw new \Exception('parseDTDTag() saninty check failed');
     }
     // @link http://en.wikipedia.org/wiki/CDATA#CDATA_sections_in_XML
     if ($this->substr(0, 9) == '<![CDATA[') {
         $this->buildToken($this->position + 8);
         $pos = $this->strpos(']]>');
         if ($pos === false) {
             $this->warning('CDATA not terminated');
             $this->buildLastToken('T_CDATA');
             return;
         }
         if ($this->position == $pos) {
             \Sledgehammer\warning('Empty CDATA');
             // Required?
         } else {
             $this->buildToken($pos - 1, 'T_CDATA');
         }
         $this->buildToken($this->position + 2);
         $this->state = 'CONTENT';
         return;
     }
     $this->buildToken($this->position + 1);
     $pos = $this->firstOccurrance(array_merge(array('[', '>'), $this->wsArray));
     if ($pos === false) {
         $this->warning('Inline DTD tag not terminated');
         $this->buildLastToken('T_DTD_ENTITY');
         return;
     }
     if ($pos == $this->position) {
         $this->warning(' No DTD Entity defined');
     } else {
         $this->buildToken($pos - 1, 'T_DTD_ENTITY');
     }
     $this->parseDTDAttributes('OPEN');
 }
Example #5
0
 /**
  * Fetch a single row.
  *
  * @param string $statement           The SQL query
  * @param bool   $allow_empty_results true: Suppress the notice when no record is found.
  *
  * @return array|false
  */
 public function fetchRow($statement, $allow_empty_results = false)
 {
     $result = $this->query($statement);
     if ($result == false) {
         // Foutieve query
         return false;
     } elseif ($result->columnCount() == 0) {
         // UPDATE, INSERT query
         \Sledgehammer\warning('Resultset has no columns, expecting 1 or more columns');
         return false;
     }
     $results = $result->fetchAll();
     $count = count($results);
     if ($count == 1) {
         return $results[0];
     }
     if (count($results) > 1) {
         \Sledgehammer\notice('Unexpected ' . count($results) . ' rows, expecting 1 row');
     } elseif (!$allow_empty_results) {
         \Sledgehammer\notice('Row not found');
     }
     return false;
 }
Example #6
0
 /**
  * Reports the error/exception to the ErrorHandler and returns the error as Json object.
  * The javascript client should detect and report the error to the user:
  *   if (result.success !== true) { alert(result.error); }.
  *
  * @param string|Exception $error The error message or Exception
  * @param int              $http  The HTTP status code (defaults to 400 Bad Request)
  *
  * @return Json
  */
 public static function error($error, $http = 400)
 {
     if (headers_sent() === false && DebugR::isEnabled()) {
         ErrorHandler::instance()->html = false;
     }
     if ($error instanceof Exception) {
         \Sledgehammer\report_exception($error);
         $error = $error->getMessage();
     } else {
         \Sledgehammer\warning($error);
     }
     return new self(array('success' => false, 'error' => $error), array('http' => array('Status' => $http . ' ' . Framework::$statusCodes[$http], 'Content-Type' => ErrorHandler::instance()->html ? 'text/html;  charset=utf-8' : 'application/json')));
 }
Example #7
0
 /**
  * Report that $property doesn't exist and set the property to the given $value.
  *
  * @param string $property
  * @param mixed  $value
  */
 public function __set($property, $value)
 {
     \Sledgehammer\warning('Property "' . $property . '" doesn\'t exist in a ' . get_class($this) . ' object', \Sledgehammer\build_properties_hint(\Sledgehammer\reflect_properties($this)));
     $this->{$property} = $value;
     // Add the property to the object. (PHP's default behavior)
 }
Example #8
0
 /**
  * Access CURLINFO_* info as properties.
  *
  * @param string $property
  *
  * @return mixed
  */
 public function __get($property)
 {
     $const = 'CURLINFO_' . strtoupper($property);
     if (defined($const)) {
         $option = eval('return ' . $const . ';');
         $this->waitForCompletion();
         return curl_getinfo($this->handle, $option);
     }
     $properties = \Sledgehammer\reflect_properties($this);
     $properties['public'] = array_merge($properties['public'], curl_getinfo($this->handle));
     \Sledgehammer\warning('Property "' . $property . '" doesn\'t exist in a ' . get_class($this) . ' object', \Sledgehammer\build_properties_hint($properties));
 }
Example #9
0
 /**
  * Return a subsection of the collection based on the conditions.
  *
  * Convert the $conditions to SQL object when appropriate.
  *
  * auto converts
  *   ['x_id' => null]  to "x_id IS NULL"
  * 	 ['x_id !=' => null]  to "x_id IS NOT NULL"
  *  'hits' => 0]  to "hits = '0'"  (Because in mysql '' = 0 evaluates to true, '' = '0' to false)
  *
  * @param array $conditions
  *
  * @return Collection
  */
 public function where($conditions)
 {
     if ($this->data !== null || is_string($this->sql) || is_object($conditions) && is_callable($conditions) || $this->sql->limit !== false || $this->sql->offset != 0) {
         return parent::where($conditions);
     }
     $db = Connection::instance($this->dbLink);
     $sql = $this->sql;
     $logicalOperator = \Sledgehammer\extract_logical_operator($conditions);
     if ($logicalOperator === false) {
         if (count($conditions) > 1) {
             \Sledgehammer\notice('Conditions with multiple conditions require a logical operator.', "Example: array('AND', 'x' => 1, 'y' => 5)");
         }
         $logicalOperator = 'AND';
     } else {
         unset($conditions[0]);
     }
     if ($logicalOperator === 'AND') {
         $method = 'andWhere';
     } elseif ($logicalOperator === 'OR') {
         $method = 'orWhere';
     } else {
         throw new Exception('Unsupported logical operator "' . $logicalOperator . '", expecting "AND" or "OR"');
     }
     // The result are rows(fetch_assoc arrays), all conditions must be columnnames (or invalid)
     foreach ($conditions as $path => $value) {
         if (preg_match('/^(.*) (' . \Sledgehammer\COMPARE_OPERATORS . ')$/', $path, $matches)) {
             $column = $this->convertPathToColumn($matches[1]);
             $operator = $matches[2];
         } else {
             $column = $this->convertPathToColumn($path);
             $operator = '==';
         }
         if ($column === false) {
             // Converting to path failed?
             \Sledgehammer\array_key_unshift($conditions, 0, $logicalOperator);
             return parent::where($conditions);
         }
         if ($value === null) {
             switch ($operator) {
                 case '==':
                     $operator = 'IS';
                     $expectation = 'NULL';
                     break;
                 case '!=':
                     $operator = 'IS NOT ';
                     $expectation = 'NULL';
                     break;
                 case '>':
                 case '<':
                 case '>=':
                 case '<=':
                     $expectation = "''";
                     break;
                 default:
                     \Sledgehammer\warning('Unknown behavior for NULL values with operator "' . $operator . '"');
                     $expectation = $db->quote($expectation);
                     break;
             }
             $sql = $sql->{$method}($column . ' ' . $operator . ' ' . $expectation);
         } else {
             if ($operator === '!=') {
                 $sql = $sql->{$method}('(' . $column . ' != ' . $db->quote($value, PDO::PARAM_STR) . ' OR ' . $column . ' IS NULL)');
             } elseif ($operator === 'IN') {
                 if ((is_array($value) || $value instanceof Traversable) === false) {
                     \Sledgehammer\notice('Operator IN expects an array or Traversable', $value);
                     $value = explode(',', $value);
                 }
                 $quoted = [];
                 foreach ($value as $val) {
                     $quoted[] = $this->quote($db, $column, $val);
                 }
                 $sql = $sql->{$method}($column . ' ' . $operator . ' (' . implode(', ', $quoted) . ')');
             } else {
                 if ($operator === '==') {
                     $operator = '=';
                 }
                 $sql = $sql->{$method}($column . ' ' . $operator . ' ' . $this->quote($db, $column, $value));
             }
         }
     }
     return new self($sql, $this->dbLink);
 }
Example #10
0
 /**
  * Release the lock for this cached entry.
  */
 private function apc_release()
 {
     if (apc_delete($this->_guid . '.lock') == false) {
         \Sledgehammer\warning('apc_delete() failed, was already released?');
     }
 }
Example #11
0
 /**
  * Remove a callback from an event.
  *
  * @param string $event
  * @param string $identifier
  */
 public function off($event, $identifier)
 {
     if ($this->hasEvent($event) === false) {
         \Sledgehammer\warning('Event: "' . $event . '" not registered', 'Available events: ' . \Sledgehammer\quoted_human_implode(', ', array_keys($this->events)));
         return false;
     }
     if (empty($this->events[$event][$identifier])) {
         \Sledgehammer\warning('Identifier: "' . $identifier . '" not found in listeners for event: "' . $event . '"', 'Available identifiers: ' . \Sledgehammer\quoted_human_implode(', ', array_keys($this->events[$event])));
         return false;
     }
     unset($this->events[$event][$identifier]);
     return true;
 }
Example #12
0
 /**
  * Build a path string from a (mutated) parsed path.
  *
  * @param array $parsedPath Output from PropertyPath::parse($path)
  *
  * @return string path
  */
 public static function assemble($parsedPath)
 {
     $path = '';
     // @todo Excape values
     $tokens = array_values($parsedPath);
     // Force to first $index to 0
     foreach ($tokens as $index => $token) {
         $value = self::escape($token[1]);
         switch ($token[0]) {
             case self::TYPE_ANY:
                 if ($index != 0) {
                     $path .= '.';
                 }
                 $path .= $value;
                 break;
             case self::TYPE_PROPERTY:
                 $path .= '->' . $value;
                 break;
             case self::TYPE_ELEMENT:
                 $path .= '[' . $value . ']';
                 break;
             case self::TYPE_METHOD:
                 $path .= $value . '()';
                 break;
             case self::TYPE_OPTIONAL:
                 if ($index != 0) {
                     $path .= '.';
                 }
                 $path .= $value . '?';
                 break;
             case self::TYPE_OPTIONAL_PROPERTY:
                 $path .= '->' . $value . '?';
                 break;
             case self::TYPE_OPTIONAL_ELEMENT:
                 $path .= '[' . $value . '?]';
                 break;
             default:
                 \Sledgehammer\warning('Unsupported token', $token);
         }
     }
     return $path;
 }
Example #13
0
 /**
  * Import a class into the required namespace.
  *
  * @param string $definition Fully qualified class/interface name
  *
  * @return bool
  */
 private function resolveNamespace($definition)
 {
     if (strpos($definition, '\\') === false) {
         // Definition in the global namespace?
         if ($this->isLast() === false) {
             return false;
             // Allow the other autoloaders to define the definition.
         }
         $extends = false;
         $class = $definition;
         foreach (array_keys($this->definitions) as $definition) {
             $pos = strrpos($definition, '\\');
             if ($pos !== false && substr($definition, $pos + 1) === $class) {
                 $extends = $definition;
                 $targetNamespace = '';
                 $this->define($definition);
                 break;
             }
         }
         if ($extends === false) {
             // No matching classname found?
             return false;
         }
     } else {
         $namespaces = explode('\\', $definition);
         $class = array_pop($namespaces);
         $targetNamespace = implode('\\', $namespaces);
         if (count($namespaces) === 1 && $namespaces[0] == 'Sledgehammer') {
             // Pre 2016 notation?
             $extends = 'Sledgehammer\\Core\\' . $class;
         } else {
             // Try stripping 1 namespace (todo multiple)
             array_pop($namespaces);
             // een namespace laag hoger
             $extends = implode('\\', $namespaces);
             if ($extends == '') {
                 $extends = $class;
             } else {
                 $extends .= '\\' . $class;
             }
         }
         if (isset($this->definitions[$extends])) {
             $this->define($extends);
         }
     }
     $php = 'namespace ' . $targetNamespace . " {\n\t";
     if (class_exists($extends, false)) {
         $php .= 'class ' . $class;
         $reflection = new ReflectionClass($extends);
         if (count($reflection->getMethods(ReflectionMethod::IS_ABSTRACT)) !== 0) {
             \Sledgehammer\notice('Cant\' import "' . $class . '" into namespace "' . $targetNamespace . '" ("' . $extends . '" contains abstract methods)');
             return false;
         }
     } elseif (interface_exists($class, false)) {
         $php .= 'interface ' . $class;
     } else {
         return false;
     }
     if ($targetNamespace === '') {
         $namespaces = explode('\\', $definition);
         array_pop($namespaces);
         \Sledgehammer\warning('Definition "' . $class . '" not found, importing "' . $definition . '" into the the global namespace', 'Change the classname or add "namespace ' . implode('\\', $namespaces) . ';" or "use \\' . $definition . ';" to the beginning of the php file"');
     } elseif (error_reporting() == (error_reporting() | E_STRICT)) {
         // Strict mode
         \Sledgehammer\notice('Importing "' . $extends . '" into namespace "' . $targetNamespace . '"', 'use ' . $extends . ';');
     }
     $php .= ' extends \\' . $extends . " {}\n}";
     eval($php);
     return true;
 }