--- /dev/null
+<?php
+
+/**
+ * Gaslight Media Members Database
+ * Admin Data Import
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPlugin
+ * @package glmMembersDatabase
+ * @author Chuck Scott <cscott@gaslightmedia.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version 0.1
+ */
+require_once GLM_MEMBERS_FIELDS_PLUGIN_CLASS_PATH.'/data/dataCustomFieldsData.php';
+require_once GLM_MEMBERS_PLUGIN_CLASS_PATH.'/data/dataMemberInfo.php';
+/*
+ * This class performs the work for the default action of the "Import" menu
+ * option.
+ *
+ */
+class GlmMembersAdmin_import_fields extends GlmDataFieldsCustomFieldsData
+{
+
+ const CSV_CHARS_PER_LINE = 6000;
+ /**
+ * WordPress Database Object
+ *
+ * @var $wpdb
+ * @access public
+ */
+ public $wpdb;
+ /**
+ * Plugin Configuration Data
+ *
+ * @var $config
+ * @access public
+ */
+ public $config;
+
+ /**
+ * errors
+ *
+ * @var $errors
+ * @access public
+ */
+ public $errors = array();
+
+ /**
+ * numberProcessed
+ *
+ * @var float
+ * @access public
+ */
+ public $numberProcessed = 0;
+
+ /**
+ * totalFields
+ *
+ * @var float
+ * @access public
+ */
+ public $totalFields = 0;
+
+ /**
+ * processingComplete
+ *
+ * @var bool
+ * @access public
+ */
+ public $processingComplete = false;
+
+ /**
+ * Constructor
+ *
+ * This contractor sets up this model. At this time that only includes
+ * storing away the WordPress data object.
+ *
+ * @return object Class object
+ *
+ */
+ public function __construct ($wpdb, $config)
+ {
+
+ // Save WordPress Database object
+ $this->wpdb = $wpdb;
+
+ // Save plugin configuration object
+ $this->config = $config;
+
+ // Run constructor for members data class
+ parent::__construct(false, false);
+
+ }
+
+ /**
+ * Perform Model Action
+ *
+ * This method does the work for this model and returns any resulting data
+ *
+ * @return array Status and data array
+ *
+ * 'status'
+ *
+ * True if successful and false if there was a fatal failure.
+ *
+ * 'menuItemRedirect'
+ *
+ * If not false, provides a menu item the controller should
+ * execute after this one. Normally if this is used, there would also be a
+ * modelRedirect value supplied as well.
+ *
+ * 'modelRedirect'
+ *
+ * If not false, provides an action the controller should execute after
+ * this one.
+ *
+ * 'view'
+ *
+ * A suggested view name that the controller should use instead of the
+ * default view for this model or false to indicate that the default view
+ * should be used.
+ *
+ * 'data'
+ *
+ * Data that the model is returning for use in merging with the view to
+ * produce output.
+ *
+ */
+ public function modelAction ($actionData = false)
+ {
+ // Set the view file
+ $view = 'fields.html';
+ $failure = false;
+ $option = 'fields';
+ $clearData = false;
+ $importRet = false;
+ $haveMembers = false;
+ $fileExists = false;
+ $isValid = false;
+ // Check to see if they have members
+ $haveMembers = $this->wpdb->get_var(
+ "SELECT count(id)
+ FROM " . GLM_MEMBERS_PLUGIN_DB_PREFIX . "members"
+ );
+ // $fileData - The main files needed for the member import
+ // - field: input field name
+ // - name: file name
+ // - exists: Does file exists. Set to false at first.
+ // - validate: Validation array. Header line must match this.
+ // - type: Type of file. Used in the processing function.
+ $fileData = array(
+ 'Fields' => array(
+ 'field' => 'fields_file',
+ 'name' => 'fieldsData.csv',
+ 'exists' => false,
+ 'validate' => array( 'member_id', 'field_name', 'field_value' ),
+ 'type' => 'fields',
+ ),
+ );
+ // Setting readyToProcess to false (initialize)
+ $readyToProcess = false;
+
+ // Set the $option if found in $_REQUEST array
+ if (isset($_REQUEST['option']) && $_REQUEST['option'] != '') {
+ $option = $_REQUEST['option'];
+ }
+
+ // Set the $option2 if found in $_REQUEST array
+ if (isset($_REQUEST['option2']) && $_REQUEST['option2'] != '') {
+ $option2 = $_REQUEST['option2'];
+ }
+
+ // Set variable for the upload directory
+ $wpUploadDir = wp_get_upload_dir();
+
+ // Set the $uploadPath for import files
+ $uploadPath = $wpUploadDir['basedir'] . '/' . 'glm-member-import';
+
+ // If the folder for the upload import files doesn't exists create one.
+ if ( !is_dir( $uploadPath ) ) {
+ // Get old umask
+ $oldMask = umask(0);
+ // Set folder permission
+ mkdir( $uploadPath, 0770 );
+ // reset old umask
+ umask( $oldMask );
+ }
+
+ switch( $option ) {
+
+ case 'fieldsValidate';
+ $validFiles = 0;
+ // Set the view file
+ $view = 'fieldsValidate.html';
+ $fileCount = count( $fileData );
+ // Move any files uploaded
+ if ( isset( $_FILES ) ) {
+ foreach ( $fileData as $fileHeader => $file ) {
+ if ( !$_FILES[$file['field']]['error'] ) {
+ move_uploaded_file( $_FILES[$file['field']]['tmp_name'], $uploadPath . '/'. $file['name'] );
+ }
+ }
+ }
+ // Check that each file exists
+ foreach ( $fileData as $fileHeader => $file ) {
+ if ( is_file( $uploadPath . '/' . $file['name'] ) ) {
+ $fileData[$fileHeader]['exists'] = true;
+ $fData = $this->readCSVFileHeaders( $uploadPath . '/' . $file['name'] );
+ $isValid = ( $file['validate'] == $fData );
+ if ( $isValid ) {
+ $validFiles++;
+ }
+ $fileData[$fileHeader]['data'] = $fData;
+ $fileData[$fileHeader]['isValid'] = $isValid;
+ }
+ }
+ $readyToProcess = ( $validFiles == $fileCount );
+ break;
+
+ case 'fieldsProcess':
+ $memberInfoData = new GlmDataMemberInfo( $this->wpdb, $this->config );
+ foreach ( $fileData as $fileHeader => $file ) {
+ if ( is_file( $uploadPath . '/' . $file['name'] ) ) {
+ $fields = $this->readCSVFields( $uploadPath . '/'. $file['name'] );
+ //echo '<pre>$fields: ' . print_r( $fields, true ) . '</pre>';
+ $this->totalFields = count( $fields );
+ // Clear the custom field data table
+ $this->wpdb->query( "DELETE FROM " . GLM_MEMBERS_FIELDS_PLUGIN_DB_PREFIX . "custom_field_data" );
+ foreach ( $fields as $customRow ) {
+ // Need to first get the member id from the database
+ // It will match from the old_member_id field
+ $memberId = $this->wpdb->get_var(
+ $this->wpdb->prepare(
+ "SELECT id
+ FROM " . GLM_MEMBERS_PLUGIN_DB_PREFIX . "members
+ WHERE old_member_id = %d",
+ $customRow[0]
+ )
+ );
+ // get the active member info id
+ $memberInfoId =
+ $memberInfoData->getActiveInfoIdForMember( $memberId );
+ $customFieldId = $this->wpdb->get_var(
+ $this->wpdb->prepare(
+ "SELECT id
+ FROM " . GLM_MEMBERS_FIELDS_PLUGIN_DB_PREFIX . "custom_fields
+ WHERE field_name = %s",
+ $customRow[1]
+ )
+ );
+ if ( $customFieldId ) {
+ $newId = $this->wpdb->insert(
+ GLM_MEMBERS_FIELDS_PLUGIN_DB_PREFIX . 'custom_field_data',
+ array(
+ 'ref_dest' => $memberInfoId,
+ 'field_id' => $customFieldId,
+ 'field_data' => $customRow[2],
+ ),
+ array(
+ '%d',
+ '%d',
+ '%s'
+ )
+ );
+ $this->numberProcessed++;
+ }
+ }
+ $importRet = array();
+ }
+ }
+ if ( count( $this->errors ) == 0 ) {
+ $readyToProcess = true;
+ }
+ // Here we need to check to see if we processed all members.
+ // Also the counter has to increment the total processed so far.
+ if ( $this->numberProcessed == $this->totalFields ) {
+ $this->processingComplete = true;
+ }
+ // Set the view file:<
+ $view = 'fieldsProcess.html';
+ break;
+
+ case 'fields':
+ default:
+ // Set the view file
+ $view = 'fields.html';
+ // check upload dir to see if they have any files in yet
+ foreach ( $fileData as $fileHeader => $file ) {
+ if ( is_file( $uploadPath . '/' . $file['name'] ) ) {
+ $fileData[$fileHeader]['exists'] = true;
+ $fileData[$fileHeader]['mtime'] = filemtime( $uploadPath . '/' . $file['name'] );
+ }
+ }
+
+ break;
+
+ }
+
+ // Setup the template data array
+ $templateData = array(
+ 'fileExists' => $fileExists,
+ 'option' => $option,
+ 'errors' => $this->errors,
+ 'numberProcessed' => $this->numberProcessed,
+ 'totalFields' => $this->totalFields,
+ 'completed' => $this->processingComplete,
+ 'data' => false,
+ 'fileData' => $fileData,
+ 'clearData' => $clearData,
+ 'importRet' => $importRet,
+ 'csvData' => '<pre>$fileData: ' . print_r( $fileData, true ) . '</pre>',
+ 'readyToProcess' => $readyToProcess,
+ 'haveMembers' => $haveMembers,
+ 'isValid' => $isValid,
+ 'sampleFileUrl' => GLM_MEMBERS_PLUGIN_BASE_URL . '/sample-files/',
+ );
+
+ // Return status, suggested view, and data to controller
+ return array(
+ 'status' => true,
+ 'menuItemRedirect' => false,
+ 'modelRedirect' => false,
+ 'view' => 'admin/import/' . $view,
+ 'data' => $templateData,
+ );
+
+ }
+
+ /**
+ * Read in fields from a csv file
+ *
+ * Header line as follows. Data follows immediately below this line. this
+ * line and all above it are ignored.
+ *
+ * 'member_id','member_name','member_login','member_passwd','contact_email'
+ *
+ * @param string $csv Temporary file name of csv file upload
+ *
+ * @return array Array of data from CSV file or an error message
+ *
+ */
+ public function readCSVFields($csv)
+ {
+
+ $fields = array();
+ $startImport = false;
+
+ // Try to open file
+ if (($handle = fopen($csv, "r")) !== false) {
+
+ // For each line in the file
+ while (($c = fgetcsv($handle, 1000, ",")) !== false) {
+
+ // If we're past the header, the first item is numeric, and we have at least 5 fields
+ if($startImport && ($c[0]-0) > 0 && count($c) >= 3) {
+
+ // Add this line of data to Contacts
+ $fields[] = $c;
+
+ }
+
+ // If we find the header, assume all data is below that
+ if ($c[0] == 'member_id') {
+ $startImport = true;
+ }
+
+ }
+
+ fclose($handle);
+
+ } else {
+ return "No file submitted.";
+ }
+
+ // If we never found the header
+ if (!$startImport) {
+ return "Required header not found in file.";
+ }
+
+ // If we found no data below the header
+ if (count($fields) == 0) {
+ return "Header found but no data followed";
+ }
+
+ return $fields;
+
+ }
+
+ /**
+ * readCSVFileHeaders
+ *
+ * Read the cvs file. Just the first line is read.
+ *
+ * @param mixed $fileName Name of the file (path)
+
+ * @access public
+ * @return void
+ */
+ public function readCSVFileHeaders( $fileName )
+ {
+ $fileHeaders = array();
+ if ( ( $fp = fopen( $fileName, 'r' ) ) !== false ) {
+ // get first line to use as headers
+ $fileHeaders = fgetcsv( $fp, SELF::CSV_CHARS_PER_LINE, ',' );
+ fclose( $fp );
+ }
+
+ return $fileHeaders;
+ }
+}