public function testMassUpdateNameId() { $contact = $this->contact('testAnyone'); // First, need to break all the nameIds... Contacts::model()->updateAll(array('nameId' => null)); // Try with the mass update method, one ID: X2Model::massUpdateNameId('Contacts', array($contact->id)); $contact->refresh(); $this->assertEquals(Fields::nameId($contact->name, $contact->id), $contact->nameId); // Again, but with the "ids" parameter an int instead of an array X2Model::massUpdateNameId('Contacts', $contact->id); $contact->refresh(); $this->assertEquals(Fields::nameId($contact->name, $contact->id), $contact->nameId); // Try again, multiple records: $contact2 = $this->contact('testUser'); Contacts::model()->updateAll(array('nameId' => null)); X2Model::massUpdateNameId('Contacts', array($contact->id, $contact2->id)); $contact->refresh(); $contact2->refresh(); $this->assertEquals(Fields::nameId($contact->name, $contact->id), $contact->nameId); $this->assertEquals(Fields::nameId($contact2->name, $contact2->id), $contact2->nameId); // Try one last time, all records: Contacts::model()->updateAll(array('nameId' => null)); X2Model::massUpdateNameId('Contacts'); $contact->refresh(); $contact2->refresh(); $this->assertEquals(Fields::nameId($contact->name, $contact->id), $contact->nameId); $this->assertEquals(Fields::nameId($contact2->name, $contact2->id), $contact2->nameId); }
/** * Sets the nameId field appropriately. * * The model must be inserted already, so that its primary key can * be used. * @param bool $save If true, update the model when done. */ public function updateNameId($save = false) { if (!$this->hasAttribute('nameId')) { return; } $this->_oldAttributes['nameId'] = $this->nameId; $this->nameId = Fields::nameId($this->name, $this->id); if ($save) { $that = $this; $this->runWithoutBehavior('X2FlowTriggerBehavior', function () use($that) { $that->updateByPk($that->id, array('nameId' => $that->nameId)); }); } }
public function testAfterSave() { $contact = $this->contact('testAnyone'); $account = $this->account('account1'); $account2 = $this->account('account2'); $this->assertFalse($contact->relationships->hasRelationship($account)); $contact->company = Fields::nameId($account->name, $account->id); $this->assertSaves($contact); $this->assertTrue($contact->relationships->hasRelationship($account)); //Contact needs to be reloaded to refresh oldAttributes for afterSave $contact = Contacts::model()->findByPk($contact->id); $contact->company = Fields::nameId($account2->name, $account2->id); $this->assertSaves($contact); $this->assertFalse($contact->relationships->hasRelationship($account)); $this->assertTrue($contact->relationships->hasRelationship($account2)); $contact = Contacts::model()->findByPk($contact->id); $contact->company = NULL; $this->assertSaves($contact); $this->assertFalse($contact->relationships->hasRelationship($account)); $this->assertFalse($contact->relationships->hasRelationship($account2)); }
/** * Assert that an Action's association* fields are properly set * @param Actions $action * @param X2Model $association */ protected function assertActionAssociation(Actions $action, X2Model $association) { $associationNameId = Fields::nameId($association->name, $association->id); $this->assertEquals(lcfirst(get_class($association)), $action->associationType); $this->assertEquals($association->id, $action->associationId); $this->assertEquals($associationNameId, $action->associationName); }
public function actionCreateRecords() { $contact = new Contacts(); $account = new Accounts(); $opportunity = new Opportunity(); $users = User::getNames(); if (isset($_POST['Contacts']) && isset($_POST['Accounts']) && isset($_POST['Opportunity'])) { $contact->setX2Fields($_POST['Contacts']); $account->setX2Fields($_POST['Accounts']); $opportunity->setX2Fields($_POST['Opportunity']); $validAccount = true; if ($account->validate() == false) { $validAccount = false; // validate other models so that the user gets feedback $contact->validate(); $opportunity->validate(); } if ($validAccount) { $allValid = true; $a = $this->createAccount($account, $account->attributes, '1'); // Contact and Opportunity require Account id for lookup field $contact->company = Fields::nameId($account->name, $account->id); if ($contact->validate() == false) { $allValid = false; } $c = $this->createContact($contact, $contact->attributes, '1'); $opportunity->accountName = Fields::nameId($account->name, $account->id); $opportunity->contactName = Fields::nameId($contact->name, $contact->id); if ($opportunity->validate() == false) { $allValid = false; } $o = $this->createOpportunity($opportunity, $opportunity->attributes, '1'); if ($allValid && $c && $a && $o) { // all records created? Relationships::create('Contacts', $contact->id, 'Accounts', $account->id); Relationships::create('Opportunity', $opportunity->id, 'Contacts', $contact->id); Relationships::create('Opportunity', $opportunity->id, 'Accounts', $account->id); if (isset($_GET['ret'])) { if ($_GET['ret'] == 'contacts') { $this->redirect(array("/contacts/contacts/view", 'id' => $contact->id)); } else { if ($_GET['ret'] == 'accounts') { $this->redirect(array("/accounts/accounts/view", 'id' => $account->id)); } else { if ($_GET['ret'] == 'opportunities') { $this->redirect(array("/opportunities/opportunities/view", 'id' => $opportunity->id)); } } } } else { $this->redirect(array("/contacts/contacts/view", $contact->id)); } } else { // otherwise clean up $types = array('account' => 'Accounts', 'contact' => 'Contacts', 'opportunity' => 'Opportunity'); foreach ($types as $model => $type) { if (${$model} && isset(${$model}->id)) { $modelId = ${$model}->id; ${$model}->delete(); // delete all new actions and events from creating/deleting records foreach (array('Actions', 'Events') as $meta) { X2Model::model($meta)->deleteAllByAttributes(array('associationId' => $modelId, 'associationType' => $type)); } } } } } } $this->render('createRecords', array('contact' => $contact, 'account' => $account, 'opportunity' => $opportunity, 'users' => $users)); }
public function testNameId() { $d = Fields::NAMEID_DELIM; $this->assertEquals('My Name' . $d . '12345', Fields::nameId('My Name', 12345)); }
/** * Test the creation, reading, updating and deletion of records through the * API, and validation errors. */ public function assertCRUD() { $urlParam = $this->urlParam; $urlParam['{action}'] = 'create'; $param = $this->param; $modelAttrs = array('Accounts' => array('name' => 'ApiAccount', 'type' => 'business', 'assignedTo' => 'testuser'), 'Actions' => array('assignedTo' => 'testuser', 'dueDate' => time() + 86400), 'Contacts' => array('firstName' => 'ApiContactFirstName', 'lastName' => 'ApiContactLastName', 'email' => '*****@*****.**', 'visibility' => 1, 'assignedTo' => 'admin'), 'Docs' => array('name' => 'Excellent birds', 'subject' => 'Test subject', 'text' => 'Vel lorem risus, massa, sociis sagittis! Turpis magna sed, tristique? Pid massa integer facilisis...'), 'Opportunity' => array('name' => 'Falling snow', 'description' => 'Urna dolor? Sed tortor arcu mid porttitor egestas pulvinar etiam, diam? Aliquam, cras ultricies elementum?...', 'assignedTo' => 'testuser'), 'Product' => array('name' => 'Excellent snow', 'description' => "Enim amet! Porttitor, amet pulvinar augue sed auctor, phasellus pellentesque nunc nunc amet proin...", 'type' => 'watch it fall'), 'Services' => array('contactId' => $this->contacts('testUser')->id, 'description' => 'This is the picture! (of the error). Fix it.', 'impact' => '1 - Severe', 'status' => 'new')); $classModulesMap = array_combine(array_keys($modelAttrs), array_keys($modelAttrs)); $classModulesMap['Product'] = 'Products'; $classModulesMap['Opportunity'] = 'Opportunities'; // Stash models in here: $models = array(); // Users to try the actions for: $n_users = count($this->users); $i = 0; foreach ($this->users as $userParam) { $param = array('user' => $userParam['username'], 'userKey' => $userParam['userKey']); $apiModel = $this->newModel($userParam['username'], $userParam['userKey']); $i++; foreach ($modelAttrs as $class => $attrs) { // echo "Testing creation of $class record through API\n"; $urlParam['{model}'] = $class; $ch = $this->getCurlHandle($urlParam, array_merge($param, $attrs)); $cr = curl_exec($ch); file_put_contents('api_response.html', $cr); $authAction = $classModulesMap[$class] . 'Create'; $this->assertResponseCodeIs(200, $ch, 'Failed create operation. Response = ' . $cr); $access = $this->assertAuthControlCorrectness($authAction, $ch, $apiModel); if ($access) { $userAttrs = array(); foreach (array('createdBy', 'updatedBy') as $name) { if (X2Model::model($class)->hasAttribute($name)) { $userAttrs[$name] = $param['user']; } } if ($class == 'Services') { // Test setting a linktype field and having it turn into a nameId reference: $attrs['contactId'] = Fields::nameId($this->contacts('testUser')->name, $this->contacts('testUser')->id); } $models[$class] = X2Model::model($class)->findByAttributes(array_merge($attrs, $userAttrs)); $this->assertTrue((bool) $models[$class], "Model of class {$class} not created properly when user = {$param['user']}. The response was: {$cr}."); foreach ($attrs as $attr => $value) { $this->assertEquals($value, $models[$class]->{$attr}); } // Test that createDate was set properly: if ($models[$class]->hasAttribute('createDate')) { $this->assertNotNull($models[$class]->createDate); } } } } // We've got our models. Now let's test finding by attributes ("lookup"): $urlParam['{action}'] = 'view'; // We're going to need primary keys for the direct "view" read action: $pkValues = array(); foreach ($this->users as $userParam) { $param = array('user' => $userParam['username'], 'userKey' => $userParam['userKey']); $apiModel = $this->newModel($userParam['username'], $userParam['userKey']); foreach ($modelAttrs as $class => $attrs) { $urlParam['{model}'] = $class; $ch = $this->getCurlHandle($urlParam, array_merge($param, array('id' => $models[$class]->id))); $cr = curl_exec($ch); file_put_contents('api_response.html', $cr); $authAction = $classModulesMap[$class] . 'View'; $access = $this->assertAuthControlCorrectness($authAction, $ch, $apiModel); if ($access) { $this->assertResponseCodeIs(200, $ch); $queriedModel = CJSON::decode($cr); // Response must be valid JSON: $this->assertEquals('array', gettype($queriedModel)); $models[$class]->refresh(); // Test that the attributes are all equal. This is pretty much overkill. foreach ($queriedModel as $attr => $value) { $this->assertEquals($models[$class]->{$attr}, $value, "Failed asserting attribute equality for {$class}.{$attr}"); } // This will be useful for the next tests (lookup by pk, update & delete): $pkValues[$class] = $models[$class]->primaryKey; } } } // Test "view": lookup by ID. We already know that access control for the // "view" action is already correct; it was tested just previously. So // this test shall use the admin user: $urlParam['{action}'] = 'view'; $param = array('user' => $userParam['username'], 'userKey' => $userParam['userKey']); foreach ($pkValues as $class => $pk) { $urlParam['{model}'] = $class; $get = array(); if (is_array($pk)) { // Composite primary key $get = array_merge($get, $pk); } else { // Single-column primary key $get[$models[$class]->tableSchema->primaryKey] = $pk; } $urlParam['{params}'] = '?' . http_build_query($get, '', '&'); $ch = $this->getCurlHandle($urlParam, $param); $cr = curl_exec($ch); file_put_contents('api_response.html', $cr); $this->assertResponseCodeIs(200, $ch); $queriedModel = CJSON::decode($cr); $this->assertEquals('array', gettype($queriedModel), 'Failed asserting that the response from the server was valid JSON.'); } // Test "update": modify record by ID: $urlParam['{action}'] = 'update'; $urlParam['{params}'] = ''; $modelAttrs = array('Accounts' => array('description' => 'I have now added a description to this account.'), 'Actions' => array('assignedTo' => 'testuser', 'dueDate' => time() + 86400), 'Contacts' => array('firstName' => 'ApiContactFirstNameEdited', 'lastName' => 'ApiContactLastNameEdited', 'email' => '*****@*****.**'), 'Docs' => array('name' => 'Excellent.', 'subject' => 'Test subject 2', 'text' => 'Edited...'), 'Opportunity' => array('name' => 'Falling snow', 'description' => 'Urna dolor? Aliquam, cras ultricies elementum?...Edited'), 'Product' => array('name' => 'Esnow', 'description' => "Enim amet! Edited", 'type' => 'watchfall'), 'Services' => array('description' => 'This is edited.')); foreach ($this->users as $userParam) { $param = array('user' => $userParam['username'], 'userKey' => $userParam['userKey']); $apiModel = $this->newModel($userParam['username'], $userParam['userKey']); foreach ($pkValues as $class => $pk) { $urlParam['{model}'] = $class; $post = array_merge($param, $modelAttrs[$class]); $get = array(); if (is_array($pk)) { // Composite primary key $get = array_merge($get, $pk); } else { // Single-column primary key $get[$models[$class]->tableSchema->primaryKey] = $pk; } $urlParam['{params}'] = '?' . http_build_query($get, '', '&'); $ch = $this->getCurlHandle($urlParam, $post); $cr = curl_exec($ch); file_put_contents('api_response.html', $cr); // Choose the expected response code based on the permissions: $authAction = $classModulesMap[$class] . 'Update'; $access = $this->assertAuthControlCorrectness($authAction, $ch, $apiModel); // Refresh the stowed model and verify that it was updated properly: $models[$class]->refresh(); if ($access) { foreach ($modelAttrs[$class] as $attr => $value) { $this->assertEquals($value, $models[$class]->{$attr}, "Failed asserting that attribute {$attr} was updated in model {$class}."); } } } } // Test errors. // We'll need use the admin user to avoid unnecessary 403's. // Test validation errors. $class = 'Docs'; $oldModelAttrs = $modelAttrs[$class]['subject']; $modelAttrs[$class]['subject'] = implode(',', range(1, 10000)); $urlParam['{model}'] = $class; $param = array('user' => $this->users('admin')->username, 'userKey' => $this->users('admin')->userKey); $post = array_merge($param, $modelAttrs[$class]); $get = array(); $pk = $pkValues[$class]; if (is_array($pk)) { // Composite primary key $get = array_merge($get, $pk); } else { // Single-column primary key $get[$models[$class]->tableSchema->primaryKey] = $pk; } $urlParam['{params}'] = '?' . http_build_query($get, '', '&'); $ch = $this->getCurlHandle($urlParam, $post); $cr = curl_exec($ch); file_put_contents('api_response.html', $cr); $this->assertResponseCodeIs(500, $ch, 'Failed asserting that a validation error could be triggered in the API'); // Test incorrect primary key errors: $class = 'Docs'; $modelAttrs[$class]['subject'] = $oldModelAttrs; $pk = 38923; $urlParam['{model}'] = $class; $get = array(); $get['id'] = $pk; $urlParam['{params}'] = '?' . http_build_query($get, '', '&'); $ch = $this->getCurlHandle($urlParam, $post); $cr = curl_exec($ch); file_put_contents('api_response.html', $cr); $this->assertResponseCodeIs(404, $ch, 'Failed asserting proper error code in an update operation with incorrect primary key.'); $urlParam['{action}'] = 'delete'; $ch = $this->getCurlHandle($urlParam, $post); $cr = curl_exec($ch); file_put_contents('api_response.html', $cr); $this->assertResponseCodeIs(404, $ch, 'Failed asserting proper error code in a delete operation with incorrect primary key.'); $urlParam['{action}'] = 'view'; $ch = $this->getCurlHandle($urlParam, $post); $cr = curl_exec($ch); file_put_contents('api_response.html', $cr); $this->assertResponseCodeIs(404, $ch, 'Failed asserting proper error code in a view operation with incorrect primary key.'); // Test missing primary key errors: $get = array(); $urlParam['{params}'] = '?' . http_build_query($get, '', '&'); $ch = $this->getCurlHandle($urlParam, $post); $cr = curl_exec($ch); file_put_contents('api_response.html', $cr); $this->assertResponseCodeIs(400, $ch, 'Failed asserting proper error code in an update operation missing primary key.'); $urlParam['{action}'] = 'delete'; $ch = $this->getCurlHandle($urlParam, $post); $cr = curl_exec($ch); file_put_contents('api_response.html', $cr); $this->assertResponseCodeIs(400, $ch, 'Failed asserting proper error code in a delete operation missing primary key.'); $urlParam['{action}'] = 'view'; $ch = $this->getCurlHandle($urlParam, $post); $cr = curl_exec($ch); file_put_contents('api_response.html', $cr); $this->assertResponseCodeIs(400, $ch, 'Failed asserting proper error code in a view operation missing primary key.'); // Test deletion. $urlParam['{action}'] = 'delete'; $urlParam['{params}'] = ''; foreach ($pkValues as $class => $pk) { $urlParam['{model}'] = $class; $post = $param; if (is_array($pk)) { // Composite primary key $post = array_merge($post, $pk); } else { // Single-column primary key $post[$models[$class]->tableSchema->primaryKey] = $pk; } $ch = $this->getCurlHandle($urlParam, $post); $cr = curl_exec($ch); file_put_contents('api_response.html', $cr); $this->assertResponseCodeIs(200, $ch, 'Failed asserting that deletion request succeeded.'); $model = X2Model::model($class)->findByPk($pk); // No more model matching PK? $this->assertFalse((bool) $model, 'Failed asserting that the deletion target exists.'); } }