├── .gitignore ├── CodeGenUtils.js ├── PHPCodeGenerator.js ├── PHPPreferences.js ├── README.md ├── main.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## PHPStorm 3 | ################# 4 | 5 | .idea 6 | 7 | -------------------------------------------------------------------------------- /CodeGenUtils.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 MKLab. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | /*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, regexp: true */ 25 | /*global define, _ */ 26 | 27 | define(function (require, exports, module) { 28 | "use strict"; 29 | 30 | /** 31 | * CodeWriter 32 | * @constructor 33 | */ 34 | function CodeWriter(indentString) { 35 | 36 | /** @member {Array.} lines */ 37 | this.lines = []; 38 | 39 | /** @member {string} indentString */ 40 | this.indentString = indentString || " "; // default 4 spaces 41 | 42 | /** @member {Array.} indentations */ 43 | this.indentations = []; 44 | 45 | /** @member {Array} section */ 46 | this.sections = []; 47 | } 48 | 49 | /** 50 | * Indent 51 | */ 52 | CodeWriter.prototype.indent = function () { 53 | this.indentations.push(this.indentString); 54 | }; 55 | 56 | /** 57 | * Outdent 58 | */ 59 | CodeWriter.prototype.outdent = function () { 60 | this.indentations.splice(this.indentations.length - 1, 1); 61 | }; 62 | 63 | /** 64 | * Add named section to ba able to write lines in it 65 | * @param {string} line 66 | * @param {boolean} uniqueItems 67 | */ 68 | CodeWriter.prototype.addSection = function (name, uniqueItems) { 69 | uniqueItems = uniqueItems || false; 70 | 71 | if (!_.contains(this.sections, {name: name})) { 72 | this.sections.push({ 73 | name: name, 74 | line: this.lines.length, 75 | indentations: _.clone(this.indentations), 76 | insertEmptyLine: true, 77 | uniqueItems: uniqueItems, 78 | items: [] 79 | }); 80 | } 81 | }; 82 | 83 | /** 84 | * Write a line in section 85 | * @param {string} line 86 | * @param {string} name 87 | */ 88 | CodeWriter.prototype.writeLineInSection = function (line, name) { 89 | var section = _.findWhere(this.sections, {name: name}); 90 | if (section) { 91 | if (line && (!section.uniqueItems || !_.contains(section.items, line))) { 92 | this.lines.splice(section.line, 0, section.indentations.join("") + line); 93 | section.items.push(line); 94 | } else { 95 | this.lines.splice(section.line, 0, ""); 96 | } 97 | section.line++; 98 | if (section.insertEmptyLine) { 99 | this.lines.splice(section.line, 0, ""); 100 | section.insertEmptyLine = false; 101 | } 102 | } 103 | }; 104 | 105 | /** 106 | * Write a line 107 | * @param {string} line 108 | */ 109 | CodeWriter.prototype.writeLine = function (line) { 110 | if (line) { 111 | this.lines.push(this.indentations.join("") + line); 112 | } else { 113 | this.lines.push(""); 114 | } 115 | }; 116 | 117 | /** 118 | * Return as all string data 119 | * @return {string} 120 | */ 121 | CodeWriter.prototype.getData = function () { 122 | return this.lines.join("\n"); 123 | }; 124 | 125 | exports.CodeWriter = CodeWriter; 126 | 127 | }); -------------------------------------------------------------------------------- /PHPCodeGenerator.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 MKLab. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, regexp: true */ 24 | /*global define, $, _, window, staruml, type, document, php7, app */ 25 | 26 | define ( function ( require , exports , module ) { 27 | "use strict"; 28 | 29 | var Repository = app.getModule ( "core/Repository" ) , 30 | ProjectManager = app.getModule ( "engine/ProjectManager" ) , 31 | Engine = app.getModule ( "engine/Engine" ) , 32 | FileSystem = app.getModule ( "filesystem/FileSystem" ) , 33 | FileUtils = app.getModule ( "file/FileUtils" ) , 34 | Async = app.getModule ( "utils/Async" ) , 35 | UML = app.getModule ( "uml/UML" ); 36 | 37 | var CodeGenUtils = require ( "CodeGenUtils" ); 38 | 39 | //constant for separate namespace on code 40 | var SEPARATE_NAMESPACE = '\\'; 41 | 42 | /** 43 | * PHP Code Generator 44 | * @constructor 45 | * 46 | * @param {type.UMLPackage} baseModel 47 | * @param {string} basePath generated files and directories to be placed 48 | */ 49 | function PHPCodeGenerator ( baseModel , basePath ) { 50 | 51 | /** @member {type.Model} */ 52 | this.baseModel = baseModel; 53 | 54 | /** @member {string} */ 55 | this.basePath = basePath; 56 | 57 | } 58 | 59 | /** 60 | * Return Indent String based on options 61 | * @param {Object} options 62 | * @return {string} 63 | */ 64 | PHPCodeGenerator.prototype.getIndentString = function ( options ) { 65 | if ( options.useTab ) { 66 | return "\t"; 67 | } else { 68 | var i , len , indent = []; 69 | for ( i = 0, len = options.indentSpaces; i < len; i++ ) { 70 | indent.push ( " " ); 71 | } 72 | return indent.join ( "" ); 73 | } 74 | }; 75 | 76 | /** 77 | * Generate codes from a given element 78 | * @param {type.Model} elem 79 | * @param {string} path 80 | * @param {Object} options 81 | * @return {$.Promise} 82 | */ 83 | PHPCodeGenerator.prototype.generate = function ( elem , path , options ) { 84 | var result = new $.Deferred () , 85 | self = this , 86 | fullPath = path + "/" + elem.name , 87 | directory; 88 | 89 | // Package 90 | if ( elem instanceof type.UMLPackage ) { 91 | directory = FileSystem.getDirectoryForPath ( fullPath ); 92 | directory.create ( function ( err , stat ) { 93 | if ( !err ) { 94 | Async.doSequentially ( 95 | elem.ownedElements , 96 | function ( child ) { 97 | return self.generate ( child , fullPath , options ); 98 | } , 99 | false 100 | ).then ( result.resolve , result.reject ); 101 | } else { 102 | result.reject ( err ); 103 | } 104 | } ); 105 | } else if ( this.isClass ( elem , type ) ) { 106 | this.generateClass ( elem , path , options , result ); 107 | } else { 108 | result.resolve (); 109 | } 110 | return result.promise (); 111 | }; 112 | 113 | /** 114 | * verify type class 115 | * @param elem 116 | * @param type 117 | * @returns {boolean} 118 | */ 119 | PHPCodeGenerator.prototype.isClass = function ( elem , type ) { 120 | return elem instanceof type.UMLClass 121 | || elem instanceof type.UMLInterface 122 | || elem instanceof type.UMLEnumeration; 123 | }; 124 | 125 | /** 126 | * generate file class 127 | * @param elem 128 | * @param path 129 | * @param options 130 | * @param result 131 | */ 132 | PHPCodeGenerator.prototype.generateClass = function ( elem , path , options , result ) { 133 | var codeWriter , 134 | file , 135 | classExtension = ""; 136 | 137 | codeWriter = new CodeGenUtils.CodeWriter ( this.getIndentString ( options ) ); 138 | codeWriter.writeLine ( "} 201 | */ 202 | PHPCodeGenerator.prototype.getModifiersClass = function ( elem ) { 203 | var modifiers = []; 204 | 205 | if ( elem.isStatic === true ) { 206 | modifiers.push ( "static" ); 207 | } 208 | if ( elem.isAbstract === true ) { 209 | modifiers.push ( "abstract" ); 210 | } 211 | if ( elem.isFinalSpecification === true || elem.isLeaf === true ) { 212 | modifiers.push ( "final" ); 213 | } 214 | // transient 215 | // volatile 216 | // strictfp 217 | // const 218 | // native 219 | return modifiers; 220 | }; 221 | /** 222 | * Collect modifiers of a given element. 223 | * @param {type.Model} elem 224 | * @return {Array.} 225 | */ 226 | PHPCodeGenerator.prototype.getModifiers = function ( elem ) { 227 | var modifiers = []; 228 | var visibility = this.getVisibility ( elem ); 229 | if ( visibility ) { 230 | modifiers.push ( visibility ); 231 | } 232 | var status = this.getModifiersClass ( elem ); 233 | return _.union ( modifiers , status ); 234 | }; 235 | 236 | /** 237 | * Collect super classes of a given element 238 | * @param {type.Model} elem 239 | * @return {Array.} 240 | */ 241 | PHPCodeGenerator.prototype.getSuperClasses = function ( elem ) { 242 | var generalizations = Repository.getRelationshipsOf ( elem , function ( rel ) { 243 | return (rel instanceof type.UMLGeneralization && rel.source === elem); 244 | } ); 245 | return _.map ( generalizations , function ( gen ) { 246 | return gen.target; 247 | } ); 248 | }; 249 | 250 | /** 251 | * Collect super interfaces of a given element 252 | * @param {type.Model} elem 253 | * @return {Array.} 254 | */ 255 | PHPCodeGenerator.prototype.getSuperInterfaces = function ( elem ) { 256 | var realizations = Repository.getRelationshipsOf ( elem , function ( rel ) { 257 | return (rel instanceof type.UMLInterfaceRealization && rel.source === elem); 258 | } ); 259 | return _.map ( realizations , function ( gen ) { 260 | return gen.target; 261 | } ); 262 | }; 263 | 264 | /** 265 | * 266 | * @param {type.Model} elem 267 | * @return {Array} 268 | */ 269 | PHPCodeGenerator.prototype.getNamespaces = function ( elem ) { 270 | var _namespace = []; 271 | var _parent = []; 272 | if ( elem._parent instanceof type.UMLPackage && !(elem._parent instanceof type.UMLModel) ) { 273 | _namespace.push ( elem._parent.name ); 274 | _parent = this.getNamespaces ( elem._parent ); 275 | } 276 | 277 | return _.union ( _parent , _namespace ); 278 | }; 279 | 280 | /** 281 | * Return type expression 282 | * @param {type.Model} elem 283 | * @return {string} 284 | */ 285 | PHPCodeGenerator.prototype.getDocumentType = function ( elem ) { 286 | var _type = "void"; 287 | var _namespace = ""; 288 | 289 | if ( elem === null ) { 290 | return _type; 291 | } 292 | 293 | // type name 294 | if ( elem instanceof type.UMLAssociationEnd ) { 295 | if ( elem.reference instanceof type.UMLModelElement && elem.reference.name.length > 0 ) { 296 | _type = elem.reference.name; 297 | _namespace = _.map ( this.getNamespaces ( elem.reference ) , function ( e ) { return e; } ).join ( SEPARATE_NAMESPACE ); 298 | 299 | if ( _namespace !== "" ) { 300 | _namespace = SEPARATE_NAMESPACE + _namespace; 301 | } 302 | _type = _namespace + SEPARATE_NAMESPACE + _type; 303 | } 304 | } else { 305 | if ( elem.type instanceof type.UMLModelElement && elem.type.name.length > 0 ) { 306 | _type = elem.type.name; 307 | _namespace = _.map ( this.getNamespaces ( elem.type ) , function ( e ) { return e; } ).join ( SEPARATE_NAMESPACE ); 308 | 309 | if ( _namespace !== "" ) { 310 | _namespace = SEPARATE_NAMESPACE + _namespace; 311 | } 312 | _type = _namespace + SEPARATE_NAMESPACE + _type; 313 | } else if ( _.isString ( elem.type ) && elem.type.length > 0 ) { 314 | _type = elem.type; 315 | } 316 | } 317 | // multiplicity 318 | if ( elem.multiplicity && this.isAllowedTypeHint ( _type ) ) { 319 | if ( _.contains ( [ "0..*" , "1..*" , "*" ] , elem.multiplicity.trim () ) ) { 320 | _type += "[]"; 321 | } 322 | } 323 | return _type; 324 | }; 325 | 326 | /** 327 | * 328 | * @param elem 329 | * @returns {string} 330 | */ 331 | PHPCodeGenerator.prototype.getType = function ( elem ) { 332 | if ( elem === null ) { 333 | return "void"; 334 | } 335 | var _type = this.getDocumentType ( elem ); 336 | if ( elem.multiplicity && this.isAllowedTypeHint ( _type ) ) { 337 | if ( _type.indexOf ( "[]" ) !== -1 ) { 338 | _type = "array"; 339 | } 340 | } 341 | return _type; 342 | }; 343 | 344 | PHPCodeGenerator.prototype.getTypeHint = function ( elem ) { 345 | var _type = "void" , 346 | _namespacePath = [] , 347 | _globalNamespace = this.namespacePath , 348 | _namespace = "" , 349 | _isObject = false; 350 | 351 | if ( elem === null ) { 352 | return _type; 353 | } 354 | 355 | // type name 356 | if ( elem instanceof type.UMLAssociationEnd ) { 357 | if ( elem.reference instanceof type.UMLModelElement && elem.reference.name.length > 0 ) { 358 | _isObject = true; 359 | _type = elem.reference.name; 360 | _namespacePath = this.getNamespaces ( elem.reference ); 361 | } 362 | } else { 363 | if ( elem.type instanceof type.UMLModelElement && elem.type.name.length > 0 ) { 364 | _isObject = true; 365 | _type = elem.type.name; 366 | _namespacePath = this.getNamespaces ( elem.type ); 367 | } else if ( _.isString ( elem.type ) && elem.type.length > 0 ) { 368 | _type = elem.type; 369 | } 370 | } 371 | 372 | if ( _isObject ) { 373 | if ( _globalNamespace.isEqual ( _globalNamespace.intersect ( _namespacePath ) ) ) { 374 | _namespace = _.map ( _namespacePath.diff ( _globalNamespace ) , function ( e ) { return e; } ).join ( SEPARATE_NAMESPACE ); 375 | } else { 376 | _namespace = _.map ( _namespacePath , function ( e ) { return e; } ).join ( SEPARATE_NAMESPACE ); 377 | _namespace = SEPARATE_NAMESPACE + _namespace; 378 | } 379 | 380 | if ( _namespace.length > 0 ) { 381 | _type = _namespace + SEPARATE_NAMESPACE + _type; 382 | } 383 | } 384 | 385 | return _type; 386 | }; 387 | 388 | Array.prototype.intersect = function ( array ) { 389 | var result = []; 390 | for ( var i = 0 , len = this.length; i < len; i++ ) { 391 | if ( this[ i ] == array[ i ] ) { 392 | result.push ( array[ i ] ); 393 | } 394 | } 395 | return result; 396 | }; 397 | 398 | Array.prototype.isEqual = function ( array ) { 399 | if ( this.length != array.length ) { 400 | return false; 401 | } 402 | for ( var i = 0 , len = this.length; i < len; i++ ) { 403 | if ( this[ i ] != array[ i ] ) { 404 | return false; 405 | } 406 | } 407 | return true; 408 | }; 409 | 410 | Array.prototype.diff = function ( array ) { 411 | var result = []; 412 | for ( var i = 0 , len = this.length; i < len; i++ ) { 413 | if ( this[ i ] != array[ i ] ) { 414 | result.push ( this[ i ] ); 415 | } 416 | } 417 | return result; 418 | }; 419 | 420 | /** 421 | * Write Doc 422 | * @param {StringWriter} codeWriter 423 | * @param {string} text 424 | * @param {Object} options 425 | */ 426 | PHPCodeGenerator.prototype.writeDoc = function ( codeWriter , text , options ) { 427 | var i , len , lines , terms; 428 | if ( options.phpDoc && _.isString ( text ) ) { 429 | lines = text.trim ().split ( "\n" ); 430 | codeWriter.writeLine ( "/**" ); 431 | for ( i = 0, len = lines.length; i < len; i++ ) { 432 | terms = [ " *" ]; 433 | if ( lines[ i ] !== "" ) { 434 | terms.push ( lines[ i ].trim () ); 435 | } 436 | codeWriter.writeLine ( terms.join ( " " ) ); 437 | } 438 | codeWriter.writeLine ( " */" ); 439 | } 440 | }; 441 | 442 | /** 443 | * Write Specification 444 | * @param {StringWriter} codeWriter 445 | * @param {string} text 446 | */ 447 | PHPCodeGenerator.prototype.writeSpec = function ( codeWriter , text ) { 448 | var i , len , lines; 449 | if ( _.isString ( text ) ) { 450 | lines = text.trim ().split ( "\n" ); 451 | for ( i = 0, len = lines.length; i < len; i++ ) { 452 | codeWriter.writeLine ( lines[ i ] ); 453 | } 454 | } 455 | }; 456 | 457 | var namespacePath = null; 458 | 459 | /** 460 | * Write Package Declaration 461 | * @param {StringWriter} codeWriter 462 | * @param {type.Model} elem 463 | */ 464 | PHPCodeGenerator.prototype.writePackageDeclaration = function ( codeWriter , elem ) { 465 | var namespace = null; 466 | this.namespacePath = this.getNamespaces ( elem ); 467 | if ( this.namespacePath.length > 0 ) { 468 | namespace = this.namespacePath.join ( SEPARATE_NAMESPACE ); 469 | } 470 | if ( namespace ) { 471 | codeWriter.writeLine ( "namespace " + namespace + ";" ); 472 | } 473 | }; 474 | 475 | /** 476 | * Write Constructor 477 | * @param {StringWriter} codeWriter 478 | * @param {type.Model} elem 479 | * @param {Object} options 480 | */ 481 | PHPCodeGenerator.prototype.writeConstructor = function ( codeWriter , elem , options ) { 482 | var haveConstruct = false; 483 | for ( var i = 0 , len = elem.operations.length; i < len; i++ ) { 484 | if ( elem.operations[ i ].name.indexOf ( "__construct" ) !== -1 ) { 485 | haveConstruct = true; 486 | } 487 | } 488 | var _extends = this.getSuperClasses ( elem ); 489 | 490 | if ( elem.name.length > 0 && _extends.length <= 0 ) { 491 | if ( !haveConstruct ) { 492 | var terms = []; 493 | // Doc 494 | this.writeDoc ( codeWriter , elem.documentation , options ); 495 | var visibility = this.getVisibility ( elem ); 496 | if ( visibility ) { 497 | terms.push ( visibility ); 498 | } 499 | terms.push ( "function __construct()" ); 500 | codeWriter.writeLine ( terms.join ( " " ) ); 501 | codeWriter.writeLine ( "{" ); 502 | codeWriter.writeLine ( "}" ); 503 | } 504 | } 505 | }; 506 | 507 | /** 508 | * Write Member Variable 509 | * @param {StringWriter} codeWriter 510 | * @param {type.Model} elem 511 | * @param {Object} options 512 | */ 513 | PHPCodeGenerator.prototype.writeMemberVariable = function ( codeWriter , elem , options ) { 514 | if ( elem.name.length > 0 ) { 515 | var terms = []; 516 | // doc 517 | var doc = "@var " + this.getDocumentType ( elem ) + " " + elem.documentation.trim (); 518 | this.writeDoc ( codeWriter , doc , options ); 519 | 520 | // modifiers const 521 | if ( elem.isFinalSpecification === true || elem.isLeaf === true ) { 522 | terms.push ( "const " + elem.name.toUpperCase () ); 523 | } 524 | else { 525 | // modifiers 526 | var _modifiers = this.getModifiers ( elem ); 527 | if ( _modifiers.length > 0 ) { 528 | terms.push ( _modifiers.join ( " " ) ); 529 | } 530 | // name 531 | terms.push ( "$" + elem.name ); 532 | } 533 | // initial value 534 | if ( elem.defaultValue && elem.defaultValue.length > 0 ) { 535 | terms.push ( "= " + elem.defaultValue ); 536 | } 537 | codeWriter.writeLine ( terms.join ( " " ) + ";" ); 538 | } 539 | }; 540 | 541 | /** 542 | * Write Methods for Abstract parent and Interfaces 543 | * @param {StringWriter} codeWriter 544 | * @param {type.Model} elem 545 | * @param {Object} options 546 | * @param {boolean} onlyAbstract 547 | */ 548 | PHPCodeGenerator.prototype.writeSuperMethods = function ( codeWriter , elem , options , methods , onlyAbstract ) { 549 | onlyAbstract = onlyAbstract || false; 550 | for ( var i = 0 , len = elem.operations.length; i < len; i++ ) { 551 | var method = elem.operations[ i ]; 552 | if ( method !== undefined && !_.contains ( methods , method.name ) && !onlyAbstract || method.isAbstract === true ) { 553 | var clone = _.clone ( method ); 554 | if ( onlyAbstract ) { 555 | clone.isAbstract = false; 556 | } 557 | clone.documentation = "@inheritDoc"; 558 | var implemented = this.writeMethod ( codeWriter , clone , options , false , false ); 559 | if ( implemented ) { 560 | codeWriter.writeLine (); 561 | methods.push ( method.name ); 562 | } 563 | } 564 | } 565 | }; 566 | 567 | /** 568 | * Write Method 569 | * @param {StringWriter} codeWriter 570 | * @param {type.Model} elem 571 | * @param {Object} options 572 | * @param {boolean} skipBody 573 | * @param {boolean} skipParams 574 | * @return {boolean} 575 | */ 576 | PHPCodeGenerator.prototype.writeMethod = function ( codeWriter , elem , options , skipBody , skipParams ) { 577 | if ( elem.name.length > 0 ) { 578 | var terms = []; 579 | var params = elem.getNonReturnParameters (); 580 | var returnParam = elem.getReturnParameter (); 581 | var _that = this; 582 | // doc 583 | var doc = elem.documentation.trim (); 584 | _.each ( params , function ( param ) { 585 | doc += "\n@param " + _that.getDocumentType ( param ) + " $" + param.name + " " + param.documentation; 586 | } ); 587 | if ( returnParam ) { 588 | doc += "\n@return " + this.getDocumentType ( returnParam ) + " " + returnParam.documentation; 589 | } 590 | this.writeDoc ( codeWriter , doc , options ); 591 | 592 | // modifiers 593 | var _modifiers = this.getModifiers ( elem ); 594 | if ( _modifiers.length > 0 ) { 595 | terms.push ( _modifiers.join ( " " ) ); 596 | } 597 | 598 | terms.push ( "function" ); 599 | 600 | // name + parameters 601 | var paramTerms = []; 602 | if ( !skipParams ) { 603 | var i , len; 604 | for ( i = 0, len = params.length; i < len; i++ ) { 605 | var p = params[ i ]; 606 | var s = "$" + p.name; 607 | var defaultValue = p.defaultValue; 608 | var type = this.getType ( p ); 609 | if ( options.phpStrictMode && this.isAllowedTypeHint ( type ) ) { 610 | s = this.getTypeHint ( p ) + " " + s; 611 | } 612 | 613 | if ( defaultValue.length > 0 ) { 614 | s += " = " + defaultValue; 615 | } 616 | paramTerms.push ( s ); 617 | } 618 | } 619 | 620 | var functionName = elem.name + "(" + paramTerms.join ( ", " ) + ")"; 621 | if ( options.phpReturnType ) { 622 | functionName = functionName + ':' + this.getTypeHint ( returnParam ); 623 | } 624 | terms.push ( functionName ); 625 | 626 | // body 627 | if ( skipBody === true || _.contains ( _modifiers , "abstract" ) ) { 628 | codeWriter.writeLine ( terms.join ( " " ) + ";" ); 629 | } else { 630 | codeWriter.writeLine ( terms.join ( " " ) ); 631 | codeWriter.writeLine ( "{" ); 632 | codeWriter.indent (); 633 | 634 | //specification 635 | if ( elem.specification.length > 0 ) { 636 | this.writeSpec ( codeWriter , elem.specification ); 637 | } else { 638 | codeWriter.writeLine ( "// TODO: implement here" ); 639 | 640 | // return statement 641 | if ( returnParam ) { 642 | var returnType = this.getType ( returnParam ); 643 | if ( returnType === "boolean" || returnType === "bool" ) { 644 | codeWriter.writeLine ( "return false;" ); 645 | } else if ( returnType === "int" || returnType === "long" || returnType === "short" || returnType === "byte" ) { 646 | codeWriter.writeLine ( "return 0;" ); 647 | } else if ( returnType === "float" || returnType === "double" ) { 648 | codeWriter.writeLine ( "return 0.0;" ); 649 | } else if ( returnType === "char" ) { 650 | codeWriter.writeLine ( "return '0';" ); 651 | } else if ( returnType === "string" ) { 652 | codeWriter.writeLine ( 'return "";' ); 653 | } else if ( returnType === "array" ) { 654 | codeWriter.writeLine ( "return array();" ); 655 | } else { 656 | codeWriter.writeLine ( "return null;" ); 657 | } 658 | } 659 | } 660 | 661 | codeWriter.outdent (); 662 | codeWriter.writeLine ( "}" ); 663 | } 664 | return true; 665 | } 666 | 667 | return false; 668 | }; 669 | 670 | /** 671 | * Write Class 672 | * @param {StringWriter} codeWriter 673 | * @param {type.Model} elem 674 | * @param {Object} options 675 | */ 676 | PHPCodeGenerator.prototype.writeClass = function ( codeWriter , elem , options ) { 677 | var i , len , terms = []; 678 | 679 | // Doc 680 | var doc = elem.documentation.trim (); 681 | if ( ProjectManager.getProject ().author && ProjectManager.getProject ().author.length > 0 ) { 682 | doc += "\n@author " + ProjectManager.getProject ().author; 683 | } 684 | this.writeDoc ( codeWriter , doc , options ); 685 | 686 | // Modifiers 687 | var _modifiers = this.getModifiersClass ( elem ); 688 | if ( _modifiers.length > 0 ) { 689 | terms.push ( _modifiers.join ( " " ) ); 690 | } 691 | 692 | // Class 693 | terms.push ( "class" ); 694 | terms.push ( elem.name ); 695 | 696 | // Extends 697 | var _extends = this.getSuperClasses ( elem ); 698 | var _superClass; 699 | if ( _extends.length > 0 ) { 700 | _superClass = _extends[ 0 ]; 701 | terms.push ( "extends " + _superClass.name ); 702 | } 703 | 704 | // Implements 705 | var _implements = this.getSuperInterfaces ( elem ); 706 | if ( _implements.length > 0 ) { 707 | terms.push ( "implements " + _.map ( _implements , function ( e ) { 708 | return e.name; 709 | } ).join ( ", " ) ); 710 | } 711 | 712 | codeWriter.writeLine ( terms.join ( " " ) ); 713 | codeWriter.writeLine ( "{" ); 714 | codeWriter.indent (); 715 | 716 | // Constructor 717 | this.writeConstructor ( codeWriter , elem , options ); 718 | codeWriter.writeLine (); 719 | 720 | // Member Variables 721 | // (from attributes) 722 | for ( i = 0, len = elem.attributes.length; i < len; i++ ) { 723 | this.writeMemberVariable ( codeWriter , elem.attributes[ i ] , options ); 724 | codeWriter.writeLine (); 725 | } 726 | // (from associations) 727 | var associations = Repository.getRelationshipsOf ( elem , function ( rel ) { 728 | return (rel instanceof type.UMLAssociation); 729 | } ); 730 | for ( i = 0, len = associations.length; i < len; i++ ) { 731 | var asso = associations[ i ]; 732 | if ( asso.end1.reference === elem && asso.end2.navigable === true ) { 733 | this.writeMemberVariable ( codeWriter , asso.end2 , options ); 734 | codeWriter.writeLine (); 735 | } else if ( asso.end2.reference === elem && asso.end1.navigable === true ) { 736 | this.writeMemberVariable ( codeWriter , asso.end1 , options ); 737 | codeWriter.writeLine (); 738 | } 739 | } 740 | 741 | // Methods 742 | var methods = []; 743 | for ( i = 0, len = elem.operations.length; i < len; i++ ) { 744 | var implemented = this.writeMethod ( codeWriter , elem.operations[ i ] , options , false , false ); 745 | if ( implemented ) { 746 | codeWriter.writeLine (); 747 | methods.push ( elem.operations[ i ].name ); 748 | } 749 | } 750 | 751 | if ( _superClass !== undefined ) { 752 | this.writeSuperMethods ( codeWriter , _superClass , options , methods , true ); 753 | } 754 | 755 | if ( _implements.length > 0 ) { 756 | for ( i = 0, len = _implements.length; i < len; i++ ) { 757 | this.writeSuperMethods ( codeWriter , _implements[ i ] , options , methods ); 758 | } 759 | } 760 | 761 | // Inner Definitions 762 | for ( i = 0, len = elem.ownedElements.length; i < len; i++ ) { 763 | var def = elem.ownedElements[ i ]; 764 | if ( this.isClass ( def , type ) ) { 765 | this.writeClasses ( codeWriter , def , options ); 766 | } 767 | codeWriter.writeLine (); 768 | } 769 | 770 | codeWriter.outdent (); 771 | codeWriter.lines.pop (); 772 | codeWriter.writeLine ( "}\n" ); 773 | }; 774 | 775 | /** 776 | * Write Interface 777 | * @param {StringWriter} codeWriter 778 | * @param {type.Model} elem 779 | * @param {Object} options 780 | */ 781 | PHPCodeGenerator.prototype.writeInterface = function ( codeWriter , elem , options ) { 782 | var i , len , terms = []; 783 | 784 | // Doc 785 | this.writeDoc ( codeWriter , elem.documentation , options ); 786 | 787 | // Interface 788 | terms.push ( "interface" ); 789 | terms.push ( elem.name ); 790 | 791 | // Extends 792 | var _extends = this.getSuperClasses ( elem ); 793 | if ( _extends.length > 0 ) { 794 | terms.push ( "extends " + _.map ( _extends , function ( e ) { 795 | return e.name; 796 | } ).join ( ", " ) ); 797 | } 798 | codeWriter.writeLine ( terms.join ( " " ) ); 799 | codeWriter.writeLine ( "{" ); 800 | codeWriter.indent (); 801 | 802 | // Member Variables 803 | // (from attributes) 804 | for ( i = 0, len = elem.attributes.length; i < len; i++ ) { 805 | this.writeMemberVariable ( codeWriter , elem.attributes[ i ] , options ); 806 | codeWriter.writeLine (); 807 | } 808 | // (from associations) 809 | var associations = Repository.getRelationshipsOf ( elem , function ( rel ) { 810 | return (rel instanceof type.UMLAssociation); 811 | } ); 812 | for ( i = 0, len = associations.length; i < len; i++ ) { 813 | var asso = associations[ i ]; 814 | if ( asso.end1.reference === elem && asso.end2.navigable === true ) { 815 | this.writeMemberVariable ( codeWriter , asso.end2 , options ); 816 | codeWriter.writeLine (); 817 | } else if ( asso.end2.reference === elem && asso.end1.navigable === true ) { 818 | this.writeMemberVariable ( codeWriter , asso.end1 , options ); 819 | codeWriter.writeLine (); 820 | } 821 | } 822 | 823 | // Methods 824 | for ( i = 0, len = elem.operations.length; i < len; i++ ) { 825 | this.writeMethod ( codeWriter , elem.operations[ i ] , options , true , false ); 826 | codeWriter.writeLine (); 827 | } 828 | 829 | // Inner Definitions 830 | for ( i = 0, len = elem.ownedElements.length; i < len; i++ ) { 831 | var def = elem.ownedElements[ i ]; 832 | this.writeClasses ( codeWriter , def , options ); 833 | codeWriter.writeLine (); 834 | } 835 | 836 | codeWriter.outdent (); 837 | codeWriter.lines.pop (); 838 | codeWriter.writeLine ( "}\n" ); 839 | }; 840 | 841 | /** 842 | * Write Enum 843 | * @param {StringWriter} codeWriter 844 | * @param {type.Model} elem 845 | * @param {Object} options 846 | */ 847 | PHPCodeGenerator.prototype.writeEnum = function ( codeWriter , elem , options ) { 848 | var i , len , terms = [] , 849 | literals = []; 850 | // Doc 851 | this.writeDoc ( codeWriter , elem.documentation , options ); 852 | 853 | // Enum 854 | terms.push ( "class" ); 855 | terms.push ( elem.name ); 856 | terms.push ( "extends" ); 857 | terms.push ( SEPARATE_NAMESPACE + "SplEnum" ); 858 | 859 | codeWriter.writeLine ( terms.join ( " " ) + "\n{" ); 860 | codeWriter.indent (); 861 | 862 | // Literals 863 | for ( i = 0, len = elem.literals.length; i < len; i++ ) { 864 | literals.push ( "const" ); 865 | literals.push ( elem.literals[ i ].name ); 866 | literals.push ( "=" ); 867 | literals.push ( i ); 868 | literals.push ( ";" ); 869 | } 870 | 871 | codeWriter.writeLine ( literals.join ( " " ) + "\n" ); 872 | 873 | codeWriter.outdent (); 874 | codeWriter.lines.pop (); 875 | codeWriter.writeLine ( "}\n" ); 876 | }; 877 | 878 | /** 879 | * Write AnnotationType 880 | * @param {StringWriter} codeWriter 881 | * @param {type.Model} elem 882 | * @param {Object} options 883 | */ 884 | PHPCodeGenerator.prototype.writeAnnotationType = function ( codeWriter , elem , options ) { 885 | var i , len , terms = []; 886 | 887 | // Doc 888 | var doc = elem.documentation.trim (); 889 | if ( Repository.getProject ().author && Repository.getProject ().author.length > 0 ) { 890 | doc += "\n@author " + Repository.getProject ().author; 891 | } 892 | this.writeDoc ( codeWriter , doc , options ); 893 | 894 | // Modifiers 895 | var _modifiers = this.getModifiersClass ( elem ); 896 | 897 | if ( _modifiers.length > 0 ) { 898 | terms.push ( _modifiers.join ( " " ) ); 899 | } 900 | 901 | // AnnotationType 902 | terms.push ( "@interface" ); 903 | terms.push ( elem.name ); 904 | 905 | codeWriter.writeLine ( terms.join ( " " ) + "\n{" ); 906 | codeWriter.writeLine (); 907 | codeWriter.indent (); 908 | 909 | // Member Variables 910 | for ( i = 0, len = elem.attributes.length; i < len; i++ ) { 911 | this.writeMemberVariable ( codeWriter , elem.attributes[ i ] , options ); 912 | codeWriter.writeLine (); 913 | } 914 | 915 | // Methods 916 | for ( i = 0, len = elem.operations.length; i < len; i++ ) { 917 | this.writeMethod ( codeWriter , elem.operations[ i ] , options , true , true ); 918 | codeWriter.writeLine (); 919 | } 920 | 921 | // Inner Definitions 922 | for ( i = 0, len = elem.ownedElements.length; i < len; i++ ) { 923 | var def = elem.ownedElements[ i ]; 924 | this.writeClasses ( codeWriter , def , options ); 925 | codeWriter.writeLine (); 926 | } 927 | 928 | codeWriter.outdent (); 929 | codeWriter.writeLine ( "}" ); 930 | }; 931 | 932 | /** 933 | * Is PHP allowed type hint ? 934 | * @param {string} type 935 | * @return {boolean} 936 | */ 937 | PHPCodeGenerator.prototype.isAllowedTypeHint = function ( type ) { 938 | switch ( type ) { 939 | case "void": 940 | return false; 941 | default: 942 | return true; 943 | } 944 | }; 945 | 946 | /** 947 | * Generate 948 | * @param {type.Model} baseModel 949 | * @param {string} basePath 950 | * @param {Object} options 951 | */ 952 | function generate ( baseModel , basePath , options ) { 953 | var phpCodeGenerator = new PHPCodeGenerator ( baseModel , basePath ); 954 | return phpCodeGenerator.generate ( baseModel , basePath , options ); 955 | } 956 | 957 | exports.generate = generate; 958 | 959 | } ); 960 | -------------------------------------------------------------------------------- /PHPPreferences.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2014 Minkyu Lee. All rights reserved. 3 | * 4 | * NOTICE: All information contained herein is, and remains the 5 | * property of Minkyu Lee. The intellectual and technical concepts 6 | * contained herein are proprietary to Minkyu Lee and may be covered 7 | * by Republic of Korea and Foreign Patents, patents in process, 8 | * and are protected by trade secret or copyright law. 9 | * Dissemination of this information or reproduction of this material 10 | * is strictly forbidden unless prior written permission is obtained 11 | * from Minkyu Lee (niklaus.lee@gmail.com). 12 | * 13 | */ 14 | 15 | /*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, regexp: true */ 16 | /*global define, $, _, window, appshell, staruml, app */ 17 | 18 | define(function (require, exports, module) { 19 | "use strict"; 20 | 21 | var AppInit = app.getModule("utils/AppInit"), 22 | Core = app.getModule("core/Core"), 23 | PreferenceManager = app.getModule("core/PreferenceManager"); 24 | 25 | var preferenceId = "php"; 26 | 27 | var phpPreferences = { 28 | "php.gen": { 29 | text: "PHP Code Generation", 30 | type: "Section" 31 | }, 32 | "php.gen.phpDoc": { 33 | text: "PHPDoc", 34 | description: "Generate PHPDoc comments.", 35 | type: "Check", 36 | default: true 37 | }, 38 | "php.gen.phpStrictMode": { 39 | text: "Strict Mode", 40 | description: "Generate PHP Strict Mode.", 41 | type: "Check", 42 | default: true 43 | }, 44 | "php.gen.phpReturnType": { 45 | text: "Return Type", 46 | description: "Generate PHP Return Type (e.q. PHP7).", 47 | type: "Check", 48 | default: true 49 | }, 50 | "php.gen.useTab": { 51 | text: "Use Tab", 52 | description: "Use Tab for indentation instead of spaces.", 53 | type: "Check", 54 | default: false 55 | }, 56 | "php.gen.indentSpaces": { 57 | text: "Indent Spaces", 58 | description: "Number of spaces for indentation.", 59 | type: "Number", 60 | default: 4 61 | }, 62 | "php.gen.classExtension": { 63 | text: "Append to class filename", 64 | description: "Insert value into class filename extensions (e.g. MyClass.class.php)", 65 | type: "String", 66 | default: "" 67 | }, 68 | "php.gen.interfaceExtension": { 69 | text: "Append to interface filename", 70 | description: "Insert value into interface filename extensions (e.g. MyInterface.interface.php)", 71 | type: "String", 72 | default: "" 73 | } 74 | }; 75 | 76 | function getId() { 77 | return preferenceId; 78 | } 79 | 80 | function getGenOptions() { 81 | return { 82 | phpDoc : PreferenceManager.get("php.gen.phpDoc"), 83 | useTab : PreferenceManager.get("php.gen.useTab"), 84 | indentSpaces : PreferenceManager.get("php.gen.indentSpaces"), 85 | classExtension : PreferenceManager.get("php.gen.classExtension"), 86 | interfaceExtension : PreferenceManager.get("php.gen.interfaceExtension"), 87 | phpStrictMode : PreferenceManager.get("php.gen.phpStrictMode"), 88 | phpReturnType : PreferenceManager.get("php.gen.phpReturnType") 89 | }; 90 | } 91 | 92 | AppInit.htmlReady(function () { 93 | PreferenceManager.register(preferenceId, "PHP", phpPreferences); 94 | }); 95 | 96 | exports.getId = getId; 97 | exports.getGenOptions = getGenOptions; 98 | 99 | }); 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PHP Extension for StarUML 2 2 | ============================ 3 | 4 | This extension for StarUML(http://staruml.io) support to generate PHP code from UML model. Install this extension from Extension Manager of StarUML. 5 | 6 | PHP Code Generation 7 | -------------------- 8 | 9 | 1. Click the menu (`Tools > PHP > Generate Code...`) 10 | 2. Select a base model (or package) that will be generated to PHP. 11 | 3. Select a folder where generated PHP source files will be placed. 12 | 13 | Configurations optionals 14 | ------------------------ 15 | * Strict Mode (Type Hinting) 16 | * Return Type (PHP7) 17 | * PHPDoc 18 | * Append to file extension 19 | 20 | Features 21 | -------- 22 | 23 | Belows are the rules to convert from UML model elements to PHP source codes. 24 | 25 | ### UMLPackage 26 | 27 | * converted to _PHP Package_ (as a folder). 28 | * create namespaces 29 | 30 | ### UMLClass 31 | 32 | * converted to _PHP Class_. (as a optional separate `.class.php` file) 33 | * `isAbstract` property to `abstract` modifier. 34 | * `isFinalSpecification` and `isLeaf` property to `final` modifier. 35 | * Default constructor is generated. 36 | * All contained types (_UMLClass_, _UMLInterface_) are generated as inner type definition. 37 | * Documentation property to PHPDoc comment. 38 | 39 | ### UMLAttribute 40 | 41 | * converted to _PHP Field_. 42 | * `visibility` property to one of modifiers `public`, `protected`, `private` and none. 43 | * `name` property to field identifier. 44 | * `type` property to field type. 45 | * `multiplicity` property to array type. 46 | * `isStatic` property to `static` modifier. 47 | * `isLeaf` property to `final` modifier. 48 | * `defaultValue` property to initial value. 49 | * Documentation property to PHPDoc comment. 50 | 51 | ### UMLOperation 52 | 53 | * converted to _PHP Methods_. 54 | * `visibility` property to one of modifiers `public`, `protected`, `private` and none. 55 | * `name` property to method identifier. 56 | * `isAbstract` property to `abstract` modifier. 57 | * `isStatic` property to `static` modifier. 58 | * _UMLParameter_ to _PHP Method Parameters_. 59 | * _UMLParameter_'s name property to parameter identifier. 60 | * _UMLParameter_'s type property to type of parameter. 61 | * _UMLParameter_ with `direction` = `return` to return type of method. When no return parameter, `void` is used. 62 | * _UMLParameter_ with `isReadOnly` = `true` to `final` modifier of parameter. 63 | * Documentation property to PHPDoc comment. 64 | 65 | ### UMLInterface 66 | 67 | * converted to _PHP Interface_. (as a separate `.interface.php` file) 68 | * `visibility` property to one of modifiers `public`, `protected`, `private` and none. 69 | * Documentation property to PHPDoc comment. 70 | 71 | ### UMLAssociationEnd 72 | 73 | * converted to _PHP Field_. 74 | * `visibility` property to one of modifiers `public`, `protected`, `private` and none. 75 | * `name` property to field identifier. 76 | * `type` property to field type. 77 | * If `multiplicity` is one of `0..*`, `1..*`, `*`, then collection type (`Array`) is used. 78 | * `defaultValue` property to initial value. 79 | * Documentation property to PHPDoc comment. 80 | 81 | ### UMLGeneralization 82 | 83 | * converted to _PHP Extends_ (`extends`). 84 | * Allowed only for _UMLClass_ to _UMLClass_, and _UMLInterface_ to _UMLInterface_. 85 | 86 | ### UMLInterfaceRealization 87 | 88 | * converted to _PHP Implements_ (`implements`). 89 | * Allowed only for _UMLClass_ to _UMLInterface_. 90 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 MKLab. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | /*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, regexp: true */ 25 | /*global define, $, _, window, app, type, appshell, document, PHPReverseEngineer */ 26 | 27 | define(function (require, exports, module) { 28 | "use strict"; 29 | 30 | var AppInit = app.getModule("utils/AppInit"), 31 | Repository = app.getModule("core/Repository"), 32 | Engine = app.getModule("engine/Engine"), 33 | Commands = app.getModule("command/Commands"), 34 | CommandManager = app.getModule("command/CommandManager"), 35 | MenuManager = app.getModule("menu/MenuManager"), 36 | Dialogs = app.getModule("dialogs/Dialogs"), 37 | ElementPickerDialog = app.getModule("dialogs/ElementPickerDialog"), 38 | FileSystem = app.getModule("filesystem/FileSystem"), 39 | FileSystemError = app.getModule("filesystem/FileSystemError"), 40 | ExtensionUtils = app.getModule("utils/ExtensionUtils"), 41 | UML = app.getModule("uml/UML"); 42 | 43 | var CodeGenUtils = require("CodeGenUtils"), 44 | PHPPreferences = require("PHPPreferences"), 45 | PHPCodeGenerator = require("PHPCodeGenerator"); 46 | 47 | /** 48 | * Commands IDs 49 | */ 50 | var CMD_PHP = 'php', 51 | CMD_PHP_GENERATE = 'php.generate', 52 | CMD_PHP_CONFIGURE = 'php.configure'; 53 | 54 | /** 55 | * Command Handler for PHP Generate 56 | * 57 | * @param {Element} base 58 | * @param {string} path 59 | * @param {Object} options 60 | * @return {$.Promise} 61 | */ 62 | function _handleGenerate(base, path, options) { 63 | var result = new $.Deferred(); 64 | 65 | // If options is not passed, get from preference 66 | options = options || PHPPreferences.getGenOptions(); 67 | 68 | // If base is not assigned, popup ElementPicker 69 | if (!base) { 70 | ElementPickerDialog.showDialog("Select a base model to generate codes", null, type.UMLPackage) 71 | .done(function (buttonId, selected) { 72 | if (buttonId === Dialogs.DIALOG_BTN_OK && selected) { 73 | base = selected; 74 | 75 | // If path is not assigned, popup Open Dialog to select a folder 76 | if (!path) { 77 | FileSystem.showOpenDialog(false, true, "Select a folder where generated codes to be located", null, null, function (err, files) { 78 | if (!err) { 79 | if (files.length > 0) { 80 | path = files[0]; 81 | PHPCodeGenerator.generate(base, path, options).then(result.resolve, result.reject); 82 | } else { 83 | result.reject(FileSystem.USER_CANCELED); 84 | } 85 | } else { 86 | result.reject(err); 87 | } 88 | }); 89 | } else { 90 | PHPCodeGenerator.generate(base, path, options).then(result.resolve, result.reject); 91 | } 92 | } else { 93 | result.reject(); 94 | } 95 | }); 96 | } else { 97 | // If path is not assigned, popup Open Dialog to select a folder 98 | if (!path) { 99 | FileSystem.showOpenDialog(false, true, "Select a folder where generated codes to be located", null, null, function (err, files) { 100 | if (!err) { 101 | if (files.length > 0) { 102 | path = files[0]; 103 | PHPCodeGenerator.generate(base, path, options).then(result.resolve, result.reject); 104 | } else { 105 | result.reject(FileSystem.USER_CANCELED); 106 | } 107 | } else { 108 | result.reject(err); 109 | } 110 | }); 111 | } else { 112 | PHPCodeGenerator.generate(base, path, options).then(result.resolve, result.reject); 113 | } 114 | } 115 | return result.promise(); 116 | } 117 | 118 | /** 119 | * Command Handler for PHP Reverse 120 | * 121 | * @param {string} basePath 122 | * @param {Object} options 123 | * @return {$.Promise} 124 | */ 125 | function _handleReverse(basePath, options) { 126 | var result = new $.Deferred(); 127 | 128 | // If options is not passed, get from preference 129 | options = PHPPreferences.getRevOptions(); 130 | 131 | // If basePath is not assigned, popup Open Dialog to select a folder 132 | if (!basePath) { 133 | FileSystem.showOpenDialog(false, true, "Select Folder", null, null, function (err, files) { 134 | if (!err) { 135 | if (files.length > 0) { 136 | basePath = files[0]; 137 | PHPReverseEngineer.analyze(basePath, options).then(result.resolve, result.reject); 138 | } else { 139 | result.reject(FileSystem.USER_CANCELED); 140 | } 141 | } else { 142 | result.reject(err); 143 | } 144 | }); 145 | } 146 | return result.promise(); 147 | } 148 | 149 | 150 | /** 151 | * Popup PreferenceDialog with PHP Preference Schema 152 | */ 153 | function _handleConfigure() { 154 | CommandManager.execute(Commands.FILE_PREFERENCES, PHPPreferences.getId()); 155 | } 156 | 157 | // Register Commands 158 | CommandManager.register("PHP", CMD_PHP, CommandManager.doNothing); 159 | CommandManager.register("Generate Code...", CMD_PHP_GENERATE, _handleGenerate); 160 | CommandManager.register("Configure...", CMD_PHP_CONFIGURE, _handleConfigure); 161 | 162 | var menu, menuItem; 163 | menu = MenuManager.getMenu(Commands.TOOLS); 164 | menuItem = menu.addMenuItem(CMD_PHP); 165 | menuItem.addMenuItem(CMD_PHP_GENERATE); 166 | menuItem.addMenuDivider(); 167 | menuItem.addMenuItem(CMD_PHP_CONFIGURE); 168 | 169 | }); 170 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "staruml.php", 3 | "title": "PHP", 4 | "description": "PHP code generation.", 5 | "homepage": "https://github.com/pedro151/starumlPHP", 6 | "keywords": ["php"], 7 | "version": "1.0.0", 8 | "author": { 9 | "name": "Pedro Alarcão", 10 | "url": "https://github.com/pedro151" 11 | }, 12 | "license": "MIT", 13 | "engines": { 14 | "staruml": ">=2.0.0" 15 | } 16 | } 17 | --------------------------------------------------------------------------------