diff --git entity_example/entity_cleanup_example/entity_cleanup_example.info entity_example/entity_cleanup_example/entity_cleanup_example.info new file mode 100644 index 0000000..1861ddd --- /dev/null +++ entity_example/entity_cleanup_example/entity_cleanup_example.info @@ -0,0 +1,5 @@ +name = entity cleanup example +description = cleans up instances bug 943772 +core = 7.x +package = Example modules +dependencies[] = entity_example diff --git entity_example/entity_cleanup_example/entity_cleanup_example.module entity_example/entity_cleanup_example/entity_cleanup_example.module new file mode 100644 index 0000000..bd63c98 --- /dev/null +++ entity_example/entity_cleanup_example/entity_cleanup_example.module @@ -0,0 +1,15 @@ + array( + 'person_id' => array( + 'type' => 'serial', + 'unsigned' => TRUE, + 'not null' => TRUE + ), + 'personality' => array( + 'description' => 'the bundle property', + 'type' => 'text', + 'size' => 'medium', + 'not null' => TRUE + ), + 'name' => array( + 'type' => 'text', + 'size' => 'medium' + ) + ), + 'primary key' => array('person_id') + ); + return $schema; +} +/* + * there is a bug in drupal 943772, where field_info_field doesn't function properly during module uninstall + * so the below hook_uninstall is futile + */ +/* +function entity_example_uninstall(){ + field_attach_delete_bundle( 'person' , 'teacher' ); + field_attach_delete_bundle( 'person' , 'student' ); +} +*/ diff --git entity_example/entity_example.module entity_example/entity_example.module new file mode 100644 index 0000000..95274bc --- /dev/null +++ entity_example/entity_example.module @@ -0,0 +1,167 @@ + t('person'), + 'base table' => 'person', // defined in entity_example.install + 'uri callback' => 'entity_example_personuri', + 'fieldable' => TRUE, + 'entity keys' => array( + 'id' => 'person_id' , // used by entity_load to query the base table + 'bundle' => 'personality' // used by field_attach api to load the fields + ), + 'bundle keys' => array( 'bundle' => 'personality' ), + 'bundles' => array() + ); + // teacher bundle + $person['bundles']['teacher'] = array( + 'label' => t('Teacher'), + 'admin' => array( + // path defined in entity_example_menu + // field attach uses this to add MENU_LOCAL_TASK items + // to manage and display fields + 'path' => 'admin/person/%personality', + // real path after the wildcard is loaded + 'real path' => 'admin/person/teacher', + // %personality is arg(2) + 'bundle argument' => 2, + 'access arguments' => array('administer people') + ) + ); + // student bundle + $person['bundles']['student'] = array( + 'label' => t('Student'), + 'admin' => array( + 'path' => 'admin/person/%personality', + 'real path' => 'admin/person/student', + 'bundle argument' => 2, + 'access arguments' => array('administer people') + ) + ); + // the hook may define several entities + $entities = array( + 'person' => $person + ); + return $entities; +} + +function entity_example_menu() { + $items = array(); + // pages to view and edit person + $items += entity_example_menu_person(); + // pages to admin person entity and create persons + $items += entity_example_menu_admin_person(); + return $items; +} + +function entity_example_menu_person() { + // lists all persons + // appears under site navigation menu + $items['examples/person'] = array( + 'title' => 'person list', + 'access arguments' => array('access content'), + 'page callback' => 'entity_example_person_list', + 'file' => 'entity_example.pages.inc', + 'type' => MENU_NORMAL_ITEM + ); + // single person page + // see person_load to see how %person is loaded + $items['examples/person/%person'] = array( + 'title callback' => 'entity_example_person_title', + 'title arguments' => array(2), + 'page callback' => 'entity_example_person', + 'page arguments' => array(2), + 'access arguments' => array('access content'), + 'file' => 'entity_example.pages.inc', + 'type' => MENU_CALLBACK + ); + // view person tab + $items['examples/person/%person/view'] = array( + 'title' => 'view', + 'access arguments' => array('access content'), + 'weight' => -3, + 'type' => MENU_DEFAULT_LOCAL_TASK + ); + // edit person tab + $items['examples/person/%person/edit'] = array( + 'title' => 'edit', + 'page callback' => 'drupal_get_form', + 'page arguments' => array( 'entity_example_person_edit' , 2 ), + 'access arguments' => array('access content'), + 'file' => 'entity_example.pages.inc', + 'type' => MENU_LOCAL_TASK + ); + return $items; +} + +function entity_example_menu_admin_person() { +// list personalities +// appears under administration toolbar + $items['admin/person'] = array( + 'title' => 'admin person', + 'access arguments' => array('access content'), + 'page callback' => 'entity_example_person_admin', + 'file' => 'entity_example.pages.inc', + 'type' => MENU_NORMAL_ITEM + ); + // personality admin page , used by field attach api + // see personality_load to see how %personality is loaded + $items['admin/person/%personality'] = array( + 'title callback' => 'entity_example_personality_title', + 'title arguments' => array(2), + 'access arguments' => array('access content'), + 'page arguments' => array(2), + ); + // personality default tab : create a person + $items['admin/person/%personality/add'] = array( + 'title' => 'add', + 'access arguments' => array('access content'), + 'type' => MENU_DEFAULT_LOCAL_TASK + ); + return $items; +} +/* + * argument loader for %person + */ +function person_load($id) { + // entity load queries the base table and + // takes care of loading attached fields as well + $persons = entity_load( 'person' , array($id) ); + return $persons[$id]; +} +/* + * argument loader for %personality + * makes sure no xss is used thourgh the personality property + */ +function personality_load($personality) { + switch ($personality) { + case 'teacher': + case 'student': + return $personality; + default: + return FALSE; + } +} +function entity_example_personality_title( $personality ) { + return $personality; +} +function entity_example_person_title( $person ) { + return $person->name; +} +function entity_example_personuri($person) { + return array( 'path' => 'person/' . $person->person_id ); +} + + + +/** + * Implements hook_help(). + */ +function entity_example_help($path, $arg) { + switch ($path) { + case 'admin/help#entity_example': + return "

" . t('entity example implements person entity that has teacher,student bundles , and it adds administration page under "person admin"') . "

"; + } +} diff --git entity_example/entity_example.pages.inc entity_example/entity_example.pages.inc new file mode 100644 index 0000000..00e2a90 --- /dev/null +++ entity_example/entity_example.pages.inc @@ -0,0 +1,180 @@ +fields('p')->execute(); + $persons = array(); + foreach ( $results as $record ) { + $persons[ $record->person_id ] = $record; + } + // load attached fields into the entity + // calling attach_load on array is more effiecient than inside the above loop + field_attach_load( 'person' , $persons ); + $content = array(); + foreach ( $persons as $person ) { + $content[] = array( + '#markup' => l( "$person->personality: $person->name" , 'examples/person/' . $person->person_id ) + ); + // render attached fields for this entity + $content[] = field_attach_view( 'person' , $person , 'full' ); + } + return $content; +} +/* + * view a person + */ +function entity_example_person( $person ) { + // person object is already loaded using entity_load + $content[] = array( + '#markup' => l( $person->name , 'examples/person/' . $person->person_id ) + ); + $content[] = field_attach_view( 'person' , $person , 'full' ); + return $content; +} +/* + * person administration + * the default will list the bundles ( personalities ) + * when clicking a link , the personality specific administration + * is reached , the page has tabs where default tab is handled + * by this function and [ manage/display fields ] is hanlded by field attach + * the default tab will you add personality form + */ +function entity_example_person_admin($personality = NULL) { + if ($personality) { + return drupal_get_form( 'entity_example_addperson' , $personality ); + } + else{ + $rows = array(); + $rows[] = array( l( t('teacher') , 'admin/person/teacher' ) ); + $rows[] = array( l( t('student') , 'admin/person/student' ) ); + $header = array( 'personalities' ); + $content = array( + '#theme' => 'table', + '#header' => $header, + '#rows' => $rows + ); + return $content; + } +} + +/* + * create a new person + */ +function entity_example_addperson($form , &$form_state , $personality) { + $form['name'] = array( + '#type' => 'textfield', + '#title' => 'name' + ); + + $person = new stdClass(); + $person->personality = $personality; + $person->id = 0; + + $form['person'] = array( + '#type' => 'value', + '#value' => $person + ); + // validations requires is element + $form['personality'] = array( + '#type' => 'value', + '#value' => $personality + ); + // attach form elements for attached fields + field_attach_form( 'person' , $person , $form , $form_state ); + + $form['actions'] = array('#type' => 'actions'); + $form['actions']['add'] = array( + '#type' => 'submit', + '#value' => 'add' + ); + return $form; +} +function entity_example_addperson_validate( $form , &$form_state ) { + entity_form_field_validate( 'person' , $form , $form_state ); +} +function entity_example_addperson_submit( $form , &$form_state ) { + $person = $form_state['values']['person']; + $person->name = $form_state['values']['name']; + // first the person gets a person_id + drupal_write_record( 'person' , $person ); + // person object gets properties filled from form_state submitted data + entity_form_submit_build_entity( 'person' , $person , $form , $form_state ); + // form life cycle handling ? + field_attach_submit( 'person' , $person , $form , $form_state ); + // insert fields + field_attach_insert( 'person' , $person ); + + drupal_set_message( + t( 'new @personality got added' , + array('@personality' => $person->personality) ) + ); +} + +/* + * edit an existing person + */ +function entity_example_person_edit($form , &$form_state , $person) { + $form['name'] = array( + '#type' => 'textfield', + '#title' => 'name', + '#default_value' => $person->name + ); + + $form['person'] = array( + '#type' => 'value', + '#value' => $person + ); + $form['personality'] = array( + '#type' => 'value', + '#value' => $person->personality + ); + field_attach_form( 'person' , $person , $form , $form_state ); + + $form['actions'] = array('#type' => 'actions'); + $form['actions']['save'] = array( + '#type' => 'submit', + '#value' => 'save' + ); + $form['actions']['delete'] = array( + '#type' => 'submit', + '#value' => 'delete', + '#submit' => array('entity_example_person_edit_delete') + ); + return $form; +} +function entity_example_person_edit_validate( $form , &$form_state ) { + entity_form_field_validate( 'person' , $form , $form_state ); +} +function entity_example_person_edit_submit( $form , &$form_state ) { + $person = $form_state['values']['person']; + $person->name = check_plain( $form_state['values']['name'] ); + drupal_write_record( 'person' , $person , array('person_id') ); + entity_form_submit_build_entity( 'person' , $person , $form , $form_state ); + field_attach_submit( 'person' , $person , $form , $form_state ); + // update fields + field_attach_update( 'person' , $person ); + + drupal_set_message( + t( 'the @personality got saved' , + array('@personality' => $person->personality) ) + ); + $form_state['redirect'] = 'examples/person/' . $person->person_id; +} +function entity_example_person_edit_delete( $form , &$form_state ) { + $person = $form_state['values']['person']; + field_attach_delete( 'person' , $person ); + db_delete('person') + ->condition( 'person_id' , $person->person_id , '=' ) + ->execute(); + $form_state['redirect'] = 'examples/person'; +} diff --git entity_example/entity_example.test entity_example/entity_example.test new file mode 100644 index 0000000..34d3115 --- /dev/null +++ entity_example/entity_example.test @@ -0,0 +1,134 @@ + 'Entity example', + 'description' => 'test attaching field', + 'group' => 'Examples', + ); + } + + function setUp() { + // Enable the module. + parent::setUp('entity_example'); + + // Create and login user. + $account = $this->drupalCreateUser(array('access content')); + $this->drupalLogin($account); + + $field = array( + 'field_name' => 'test_text' , + 'type' => 'text' + ); + field_create_field($field); + $instance = array( + 'label' => 'Subject', + 'field_name' => 'test_text', + 'entity_type' => 'person', + 'bundle' => 'teacher' + ); + field_create_instance($instance); + + $instance = array( + 'label' => 'Hobby', + 'field_name' => 'test_text', + 'entity_type' => 'person', + 'bundle' => 'student' + ); + field_create_instance($instance); + } + + /** + * test person field attach + */ + function testFieldAttach() { + + // Create first teacher + $edit = array( + 'name' => 'first teacher', + 'test_text[und][0][value]' => 'Music', + ); + $this->drupalPost('admin/person/teacher' , $edit, 'add'); + $this->assertText('new teacher got added' , 'teacher addition message is shown'); + + // View first teacher page + $this->drupalGet('examples/person/1'); + $this->assertText('Music' , 'subject got saved'); + + // Create second teacher + $edit = array( + 'name' => 'second teacher', + 'test_text[und][0][value]' => 'Phisics', + ); + $this->drupalPost('admin/person/teacher' , $edit, 'add'); + $this->assertText('new teacher got added' , 'teacher addition message is shown'); + + // Update second teacher + $edit = array( + 'name' => 'teacher second', + 'test_text[und][0][value]' => 'History', + ); + $this->drupalPost('examples/person/2/edit' , $edit, 'save'); + $this->assertText('the teacher got saved' , 'teacher update message is shown'); + $this->assertText('History' , 'Subject updated'); + $this->assertText('teacher second' , 'name updated'); + + // View second teacher page + $this->drupalGet('examples/person/2'); + $this->assertText('History' , 'subject got updated'); + + // View persons list page + $this->drupalGet('examples/person'); + $this->assertText('teacher: first teacher' , 'first teacher is shown'); + $this->assertText('Music' , 'Music subject is shown'); + $this->assertText('teacher: teacher second' , 'second teacher is shown'); + $this->assertText('History' , 'History subject is shown'); + + // delete second teacher + $this->drupalPost('examples/person/2/edit' , $edit, 'delete'); + $this->assertNoText('teacher: second teacher' , 'second teacher got deleted'); + + // Create first student + $edit = array( + 'name' => 'first student', + 'test_text[und][0][value]' => 'Painting', + ); + $this->drupalPost('admin/person/student' , $edit, 'add'); + $this->assertText('new student got added' , 'student addition message is shown'); + + // View first student page + $this->drupalGet('examples/person/3'); + $this->assertText('Painting' , 'Hobby got saved'); + + // Update firstn student + $edit = array( + 'name' => 'first student ', + 'test_text[und][0][value]' => 'Swimming', + ); + $this->drupalPost('examples/person/3/edit' , $edit, 'save'); + $this->assertText('the student got saved' , 'student update message is shown'); + $this->assertText('Swimming' , 'Hobby got updated'); + + // View persons list page + $this->drupalGet('examples/person'); + $this->assertText('teacher: first teacher' , 'first teacher is shown'); + $this->assertText('Music' , 'Music subject is shown'); + $this->assertText('student: first student' , 'first student is shown'); + $this->assertText('Swimming' , 'Swimming hobby is shown'); + + } +} +