diff --git a/README.md b/README.md index aa120964..bc931d14 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,8 @@ from your PHP app or script. Designed to work with the self-hosted Parse Server - [Server Info](#server-info) - [Version](#version) - [Features](#features) + - [Schema](#schema) + - [Purge](#purge) - [Contributing / Testing](#contributing--testing) ## Installation @@ -477,6 +479,61 @@ $globalConfigFeatures = ParseServerInfo::getGlobalConfigFeatures(); ``` +### Schema +Direct manipulation of the classes that are on your server is possible through `ParseSchema`. +Although fields and classes can be automatically generated (the latter assuming client class creation is enabled) `ParseSchema` gives you explicit control over these classes and their fields. +```php +// create an instance to manage your class +$mySchema = new ParseSchema("MyClass"); + +// gets the current schema data as an associative array, for inspection +$data = $mySchema->get(); + +// add any # of fields, without having to create any objects +$mySchema->addString('string_field'); +$mySchema->addNumber('num_field'); +$mySchema->addBoolean('bool_field'); +$mySchema->addDate('date_field'); +$mySchema->addFile('file_field'); +$mySchema->addGeoPoint('geopoint_field'); +$mySchema->addPolygon('polygon_field'); +$mySchema->addArray('array_field'); +$mySchema->addObject('obj_field'); +$mySchema->addPointer('pointer_field'); + +// you can even setup pointer/relation fields this way +$mySchema->addPointer('pointer_field', 'TargetClass'); +$mySchema->addRelation('relation_field', 'TargetClass'); + +// new types can be added as they are available +$mySchema->addField('new_field', 'ANewDataType'); + +// save/update this schema to persist your field changes +$mySchema->save(); +// or +$mySchema->update(); + +``` +Assuming you want to remove a field you can simply call `deleteField` and `save/update` to clear it out. +```php +$mySchema->deleteField('string_field'); +$mySchema->save(): +// or for an existing schema... +$mySchema->update(): +``` +A schema can be removed via `delete`, but it must be empty first. +```php +$mySchema->delete(); +``` + +#### Purge +All objects can be purged from a schema (class) via `purge`. But be careful! This can be considered an irreversible action. +Only do this if you _really_ need to delete all objects from a class, such as when you need to delete the class (as in the code example above). +```php +// delete all objects in the schema +$mySchema->purge(); +``` + ## Contributing / Testing See [CONTRIBUTING](CONTRIBUTING.md) for information on testing and contributing to diff --git a/src/Parse/ParseSchema.php b/src/Parse/ParseSchema.php index cfc1e549..2d22d259 100644 --- a/src/Parse/ParseSchema.php +++ b/src/Parse/ParseSchema.php @@ -61,6 +61,13 @@ class ParseSchema */ public static $GEO_POINT = 'GeoPoint'; + /** + * Polygon data type + * + * @var string + */ + public static $POLYGON = 'Polygon'; + /** * Array data type * @@ -258,6 +265,29 @@ public function update() return $result; } + /** + * Removes all objects from a Schema (class) in Parse. + * EXERCISE CAUTION, running this will delete all objects for this schema and cannot be reversed + * + * @throws Exception + */ + public function purge() + { + self::assertClassName(); + + $result = ParseClient::_request( + 'DELETE', + 'purge/'.$this->className, + null, + null, + $this->useMasterKey + ); + + if (!empty($result)) { + throw new Exception('Error on purging all objects from schema "'.$this->className.'"'); + } + } + /** * Removing a Schema from Parse. * You can only remove a schema from your app if it is empty (has 0 objects). @@ -450,6 +480,28 @@ public function addGeoPoint($fieldName = null) return $this; } + /** + * Adding Polygon Field. + * + * @param string $fieldName Name of the field will created on Parse + * + * @throws \Exception + * + * @return ParseSchema fields return self to create field on Parse + */ + public function addPolygon($fieldName = null) + { + if (!$fieldName) { + throw new Exception('field name may not be null.', 105); + } + + $this->fields[$fieldName] = [ + 'type' => self::$POLYGON, + ]; + + return $this; + } + /** * Adding Array Field. * @@ -589,6 +641,7 @@ public function assertTypes($type = null) $type !== self::$DATE && $type !== self::$FILE && $type !== self::$GEO_POINT && + $type !== self::$POLYGON && $type !== self::$ARRAY && $type !== self::$OBJECT && $type !== self::$POINTER && diff --git a/tests/Parse/ParseSchemaTest.php b/tests/Parse/ParseSchemaTest.php index 960915cf..c953508a 100644 --- a/tests/Parse/ParseSchemaTest.php +++ b/tests/Parse/ParseSchemaTest.php @@ -13,6 +13,9 @@ use Parse\HttpClients\ParseCurlHttpClient; use Parse\HttpClients\ParseStreamHttpClient; use Parse\ParseClient; +use Parse\ParseException; +use Parse\ParseObject; +use Parse\ParseQuery; use Parse\ParseSchema; use Parse\ParseUser; @@ -72,6 +75,7 @@ public function testGetFieldsSchema() $this->assertEquals(ParseSchema::$DATE, $result['fields']['dateField']['type']); $this->assertEquals(ParseSchema::$FILE, $result['fields']['fileField']['type']); $this->assertEquals(ParseSchema::$GEO_POINT, $result['fields']['geoPointField']['type']); + $this->assertEquals(ParseSchema::$POLYGON, $result['fields']['polygonField']['type']); $this->assertEquals(ParseSchema::$ARRAY, $result['fields']['arrayField']['type']); $this->assertEquals(ParseSchema::$OBJECT, $result['fields']['objectField']['type']); $this->assertEquals(ParseSchema::$POINTER, $result['fields']['pointerField']['type']); @@ -90,6 +94,7 @@ private static function createFieldsOfSchema() ->addDate('dateField') ->addFile('fileField') ->addGeoPoint('geoPointField') + ->addPolygon('polygonField') ->addArray('arrayField') ->addObject('objectField') ->addPointer('pointerField', '_User') @@ -194,6 +199,54 @@ public function testUpdateWrongFieldType() $schema->update(); } + /** + * @group schema-purge + */ + public function testPurgeSchema() + { + // get a handle to this schema + $schema = new ParseSchema('SchemaTest'); + + // create an object in this schema + $obj = new ParseObject('SchemaTest'); + $obj->set('field', 'the_one_and_only'); + $obj->save(); + + // attempt to delete this schema (expecting to fail) + try { + $schema->delete(); + $this->assertTrue(false, 'Did not fail on delete as expected'); + } catch (ParseException $pe) { + $this->assertEquals( + 'Class SchemaTest is not empty, contains 1 objects, cannot drop schema.', + $pe->getMessage() + ); + } + + // purge this schema + $schema->purge(); + + // verify no more objects are present + $query = new ParseQuery('SchemaTest'); + $this->assertEquals(0, $query->count()); + + // delete again + $schema->delete(); + } + + /** + * @group schema-purge + */ + public function testPurgingNonexistentSchema() + { + $this->setExpectedException( + 'Parse\ParseException', + 'Bad Request' + ); + $schema = new ParseSchema('NotARealSchema'); + $schema->purge(); + } + public function testDeleteSchema() { $createSchema = new ParseSchema('SchemaDeleteTest'); @@ -267,6 +320,13 @@ public function testGeoPointFieldNameException() $schema->addGeoPoint(); } + public function testPolygonFieldNameException() + { + $schema = self::$schema; + $this->setExpectedException('\Exception', 'field name may not be null.'); + $schema->addPolygon(); + } + public function testArrayFieldNameException() { $schema = self::$schema;