VCardImport   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 151
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 59
c 1
b 0
f 1
dl 0
loc 151
rs 10
wmc 21

8 Methods

Rating   Name   Duplication   Size   Complexity  
A setImportGroup() 0 3 1
A getImportCount() 0 3 1
A loadContactGroups() 0 10 2
A getImportGroup() 0 3 1
B importVCard() 0 44 10
A getGroupResourcename() 0 14 3
A __construct() 0 7 2
A getLastPersonResource() 0 3 1
1
<?php
2
declare(strict_types=1);
3
4
namespace SKien\Google;
5
6
use SKien\VCard\VCard;
0 ignored issues
show
Bug introduced by
The type SKien\VCard\VCard was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
7
8
/**
9
 * Import of a VCard file.
10
 *
11
 * Categories from the VCard are converted into contact groups for the Google
12
 * contacts. Since the `resourceName` of the group(s) is required when creating
13
 * a contact, an internal list (`groupName` => `resourceName`) of the available
14
 * groups is loaded before the VCard is read. <br/>
15
 * Categories (-> groups) that do not exist will be created and added to the
16
 * internal list.
17
 *
18
 * For a better overview of all imported contacts, the class offers the possibility
19
 * to create a new group to which all imported contacts are assigned (default name
20
 * is "VCard Import <<timestamp>>" - this can be changed with the setImportGroup()
21
 * method).
22
 *
23
 * > Since a VCard file can contain multiple contacts, the initial idea was to
24
 * > use the 'batchCreateContacts()' API function for creation. However, it is
25
 * > unfortunately not possible to transfer a photo/portrait directly when
26
 * > creating contacts, all the photos contained in the VCard file would have
27
 * > to be saved temporarily and subsequently assigned to the newly created
28
 * > contacts.  And doing so, the assignment of the images to the newly created
29
 * > 'personResourceName' will be a another hurdle. <br/>
30
 * > For my purposes the focus does not lie on importing multiple contacts from
31
 * > VCard data, so I've decided not to use 'batchCreateContacts()'. When
32
 * > creating the contacts sequentialy each by using a 'createContacts()' - API
33
 * > call, a photo can be assigned directly after the creation using the returned
34
 * > 'personResourceName'
35
 *
36
 * @author Stefanius <[email protected]>
37
 * @copyright MIT License - see the LICENSE file for details
38
 */
39
class VCardImport
40
{
41
    /** create a new contact group where all imported contacts are assigned to     */
42
    public const OPT_CREATE_IMPORT_GROUP = 0x0001;
43
44
    /** @var GClient the client we need for the import     */
45
    protected GClient $oClient;
46
    /** @var array<string,string>  array of available google contact groups groupName -> groupResourcename   */
47
    protected array $aGroupResourcenames = [];
48
    /** @var int options for the import     */
49
    protected int $iOptions = 0;
50
    /** @var string name of the importgroup to create and assign the new contacts     */
51
    protected string $strImportGroup = '';
52
    /** @var string resourceName of the last imported contact     */
53
    protected string $strLastPersonResource = '';
54
    /** @var int count of contacts beeing imported     */
55
    protected int $iImportCount = 0;
56
57
    /**
58
     * Create an instance of the class.
59
     */
60
    public function __construct(GClient &$oClient, int $iOptions = 0)
61
    {
62
        $this->oClient = $oClient;
63
        $this->iOptions = $iOptions;
64
65
        if (($iOptions & self::OPT_CREATE_IMPORT_GROUP) !== 0) {
66
            $this->strImportGroup = 'VCard Import ' . date('d.m.Y H:i');
67
        }
68
    }
69
70
    /**
71
     * Read the given VCard file and import the contact(s).
72
     * @param string $strFilename
73
     * @return bool
74
     */
75
    public function importVCard(string $strFilename) : bool
76
    {
77
        $result = false;
78
        $oVCard = new VCard();
79
80
        // since the API requests are JSON encoded, UTF-8 is the only choice...
81
        VCard::setEncoding('UTF-8');
82
        $iContacts = $oVCard->read($strFilename);
83
        if ($iContacts > 0 && $this->loadContactGroups()) {
84
            $oContacts = new GContacts($this->oClient);
85
            $oContacts->addPersonFields(GContact::PF_NAMES);
86
            $result = true;
87
            for ($i = 0; $i < $iContacts; $i++) {
88
                // create google contact from VCard, add groupmembership
89
                $oVCContact = $oVCard->getContact($i);
90
                $oContact = GContactFromVCard::fromVCardContact($oVCContact);
91
                if (!empty($this->strImportGroup)) {
92
                    $oContact->addGroupMembership($this->getGroupResourcename($this->strImportGroup));
93
                }
94
                $iCatCount = $oVCContact->getCategoriesCount();
95
                for ($iCat = 0; $iCat < $iCatCount; $iCat++) {
96
                    $oContact->addGroupMembership($this->getGroupResourcename($oVCContact->getCategory($iCat)));
97
                }
98
                // save the contact
99
                $oContact = $oContacts->createContact($oContact);
100
                if ($oContact === false) {
101
                    $result = false;
102
                    break;
103
                }
104
                // and set in the VCard contact contained portrait
105
                if (($blobPortrait = $oVCContact->getPortraitBlob()) !== '') {
106
                    if (($iPos = strpos($blobPortrait, 'base64,')) !== false) {
107
                        $blobPortrait = substr($blobPortrait, $iPos + 7);
108
                    }
109
                    if ($oContacts->setContactPhoto($oContact->getResourceName(), $blobPortrait) === false) {
110
                        $result = false;
111
                        break;
112
                    }
113
                }
114
                $this->iImportCount++;
115
                $this->strLastPersonResource = $oContact->getResourceName();
116
            }
117
        }
118
        return $result;
119
    }
120
121
    /**
122
     * @return string
123
     */
124
    public function getLastPersonResource() : string
125
    {
126
        return $this->strLastPersonResource;
127
    }
128
129
    /**
130
     * @return int
131
     */
132
    public function getImportCount() : int
133
    {
134
        return $this->iImportCount;
135
    }
136
137
    /**
138
     * @return string
139
     */
140
    public function getImportGroup() : string
141
    {
142
        return $this->strImportGroup;
143
    }
144
145
    /**
146
     * @param string $strImportGroup
147
     */
148
    public function setImportGroup(string $strImportGroup) : void
149
    {
150
        $this->strImportGroup = $strImportGroup;
151
    }
152
153
    /**
154
     * Load available contact groups.
155
     * @return bool
156
     */
157
    private function loadContactGroups() : bool
158
    {
159
        $oGroups = new GContactGroups($this->oClient);
160
        $aGroups = $oGroups->list(GContactGroups::GT_ALL_CONTACT_GROUPS, GContactGroups::RES_LIST);
161
        if ($aGroups !== false) {
0 ignored issues
show
introduced by
The condition $aGroups !== false is always false.
Loading history...
162
            // result of GContactGroups::list() contains pairs `resourceName` => `groupName`
163
            // for our assignment, we need it vice versa
164
            $this->aGroupResourcenames = array_flip($aGroups);
165
        }
166
        return ($aGroups !== false);
167
    }
168
169
    /**
170
     * Get the resourcename of a given contact group.
171
     * If the requested group doesn't exist so far, it will be created and added
172
     * to the internal group list for later use.
173
     * @param string $strGroupName
174
     * @return string
175
     */
176
    private function getGroupResourcename(string $strGroupName) : string
177
    {
178
        if (isset($this->aGroupResourcenames[$strGroupName])) {
179
            return $this->aGroupResourcenames[$strGroupName];
180
        }
181
        // doesn't exist so far - just create the group and add  it to the list
182
        $oGroups = new GContactGroups($this->oClient);
183
        $strGroupResourcename = '';
184
        $aGroup = $oGroups->createGroup($strGroupName);
185
        if ($aGroup !== false) {
186
            $strGroupResourcename = $aGroup['resourceName'];
187
            $this->aGroupResourcenames[$strGroupName] = $strGroupResourcename;
188
        }
189
        return $strGroupResourcename;
190
    }
191
}